blob: 6bfa1435316b3b09530f5e838097d93ea0f524c0 [file] [log] [blame]
// Copyright 2020 Project U-Ray Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dev.fpga.rapidwright;
import com.xilinx.rapidwright.design.*;
import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.device.*;
import com.xilinx.rapidwright.edif.*;
import org.json.Property;
import org.python.antlr.ast.Str;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;
public class dump_io {
static boolean is_hpio(SiteTypeEnum ste) {
return ste == SiteTypeEnum.HPIOB || ste == SiteTypeEnum.HPIOB_S || ste == SiteTypeEnum.HPIOB_SNGL || ste ==
SiteTypeEnum.HPIOB_M;
}
static boolean is_hdio(SiteTypeEnum ste) {
return ste == SiteTypeEnum.HDIOB_M || ste == SiteTypeEnum.HDIOB_S;
}
static boolean is_hdiol(SiteTypeEnum ste) {
return ste == SiteTypeEnum.HDIOLOGIC_M || ste == SiteTypeEnum.HDIOLOGIC_S;
}
static String site_index_in_tile(Tile t, Site s) {
int min_x = s.getInstanceX(), min_y = s.getInstanceY();
for (Site s2 : t.getSites()) {
if (s2.getSiteTypeEnum() == s.getSiteTypeEnum() ||
(is_hpio(s2.getSiteTypeEnum()) && is_hpio(s.getSiteTypeEnum())) ||
(is_hdio(s2.getSiteTypeEnum()) && is_hdio(s.getSiteTypeEnum())) ||
(is_hdiol(s2.getSiteTypeEnum()) && is_hdiol(s.getSiteTypeEnum())))
{
min_x = Math.min(min_x, s2.getInstanceX());
min_y = Math.min(min_y, s2.getInstanceY());
}
}
return s.getSiteTypeEnum().toString() + "_X" + (s.getInstanceX() - min_x) + "Y" + (s.getInstanceY() - min_y);
}
public static String clean_value(String orig) {
if (orig.startsWith("1'b"))
return orig.substring(3);
else
return orig;
}
static HashSet<String> inverted_pips = new HashSet<>();
static boolean is_sink_inverted(SitePinInst spi) {
Net n = spi.getNet();
HashMap<Node, PIP> pip_uphill = new HashMap<>();
for (PIP p : n.getPIPs()) {
pip_uphill.putIfAbsent(p.getEndNode(), p);
if (p.isBidirectional()) {
pip_uphill.putIfAbsent(p.getStartNode(), p);
}
}
boolean inv = false;
Node cursor = spi.getConnectedNode();
while (pip_uphill.containsKey(cursor)) {
PIP p = pip_uphill.get(cursor);
String name = p.getTile().getName() + "/" + p.getTile().getTileTypeEnum().toString() + "." + p.getStartWireName() + (p.isBidirectional() ? "<<->>" : "->>") + p.getEndWireName();
if (inverted_pips.contains(name))
inv = !inv;
//System.out.println(name + " " + inv);
if (p.isBidirectional() && p.getStartNode().equals(cursor))
cursor = p.getEndNode();
else
cursor = p.getStartNode();
}
return inv;
}
public static boolean process_inv(ArrayList<String> features, String prefix, String feature, Cell c, String value) {
if (!feature.endsWith("INVERTED"))
return false;
int p0 = feature.indexOf('_'), p1 = feature.lastIndexOf('_');
String port = feature.substring(p0 + 1, p1);
String phys = c.getPhysicalPinMapping(port);
if (phys == null)
return true;
String site_wire = c.getSiteWireNameFromPhysicalPin(phys);
if (site_wire == null)
return true;
Net n = c.getSiteInst().getNetFromSiteWire(site_wire);
if (n == null)
return true;
if (n.isStaticNet() || n.getLogicalNet() == null)
return true;
int prop_value = Integer.parseInt(clean_value(value));
ArrayList<String> sw = new ArrayList<>();
if (is_sink_inverted((c.getSitePinFromLogicalPin(port, sw))))
prop_value ^= 1;
features.add(prefix + "." + feature + "." + prop_value);
return true;
}
public static void add_oserdes(ArrayList<String> features, String prefix, Cell c) {
if (c.getType().equals("<LOCKED>"))
return;
features.add(prefix + ".USED");
String cprefix = prefix + "." + c.getType();
features.add(cprefix + ".USED");
String[] basic_props = {"ODDR_MODE", "OSERDES_D_BYPASS", "OSERDES_T_BYPASS", "INIT",
"IS_CLKDIV_INVERTED", "IS_CLK_INVERTED", "IS_RST_INVERTED", "DATA_WIDTH"};
for (var prop : basic_props) {
var value = c.getProperty(prop);
if (value == null)
continue;
if (process_inv(features, cprefix, prop, c, value.getValue()))
continue;
features.add(cprefix + "." + prop + "." + clean_value(value.getValue()));
}
}
public static void add_iserdes(ArrayList<String> features, String prefix, Cell c) {
if (c.getType().equals("<LOCKED>"))
return;
features.add(prefix + ".USED");
String cprefix = prefix + "." + c.getType();
features.add(cprefix + ".USED");
String[] basic_props = {"IDDR_MODE", "DDR_CLK_EDGE",
"IS_CLK_B_INVERTED", "IS_CLK_INVERTED",
"IS_RST_INVERTED", "DATA_WIDTH"};
for (var prop : basic_props) {
var value = c.getProperty(prop);
if (value == null)
continue;
if (process_inv(features, cprefix, prop, c, value.getValue()))
continue;
features.add(cprefix + "." + prop + "." + clean_value(value.getValue()));
}
process_inv(features, cprefix, "IS_CLKDIV_INVERTED", c, "1'b0");
}
public static void add_iddr(ArrayList<String> features, String prefix, Cell c) {
if (c.getType().equals("<LOCKED>"))
return;
features.add(prefix + ".USED");
String cprefix = prefix + "." + c.getType();
features.add(cprefix + ".USED");
String[] basic_props = {"DDR_CLK_EDGE",
"IS_C_INVERTED", "IS_CB_INVERTED", "IS_RST_INVERTED"};
for (var prop : basic_props) {
var value = c.getProperty(prop);
if (value == null)
continue;
if (process_inv(features, cprefix, prop, c, value.getValue()))
continue;
features.add(cprefix + "." + prop + "." + clean_value(value.getValue()));
}
}
public static void add_delay(ArrayList<String> features, String prefix, Cell c) {
if (c.getType().equals("<LOCKED>"))
return;
features.add(prefix + ".USED");
String[] basic_props = {"DELAY_FORMAT", "DELAY_SRC",
"DELAY_TYPE", "IS_CLK_INVERTED", "IS_RST_INVERTED", "LOOPBACK",
"UPDATE_MODE"};
for (var prop : basic_props) {
var value = c.getProperty(prop);
if (value == null)
continue;
if (process_inv(features, prefix, prop, c, value.getValue()))
continue;
features.add(prefix + "." + prop + "." + clean_value(value.getValue()));
}
if (c.getProperty("DELAY_FORMAT") != null && c.getProperty("DELAY_FORMAT").getValue().equals("COUNT")) {
var counts = c.getProperty("DELAY_VALUE");
if (counts != null) {
int x = Integer.parseInt(counts.getValue());
for (int i = 0; i < 9; i++) {
if (((x >> i) & 0x1) == 0x1)
features.add(prefix + ".DELAY_VALUE[" + i + "]");
}
}
} else if (c.getProperty("DELAY_FORMAT") != null && c.getProperty("DELAY_FORMAT").getValue().equals("TIME")) {
var del = c.getProperty("DELAY_VALUE");
if (del != null) {
int ps = Integer.parseInt(del.getValue());
if (ps >= 8) {
int refdiv = Math.min(511, (int)Math.floor((2000000.0/300.0) / ((double)ps)));
for (int i = 0; i < 9; i++) {
if (((refdiv >> i) & 0x1) == 0x1)
features.add(prefix + ".REFCLK_MULT[" + i + "]");
}
}
}
}
}
public static void add_ff(ArrayList<String> features, String prefix, Cell c) {
String ct = c.getType();
if (!ct.equals("FDRE") && !ct.equals("FDPE") && !ct.equals("FDCE") && !ct.equals("FDSE"))
return;
features.add(prefix + ".USED");
features.add(prefix + "." + c.getType());
var init = c.getProperty("INIT");
if (init != null)
features.add(prefix + ".INIT." + init.getIntValue().toString());
}
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(new File("mig/invpips.txt"));
while (scanner.hasNextLine()) {
String nl = scanner.nextLine().trim();
inverted_pips.add(nl);
}
File folder = new File("mig/specimen_io");
File[] listOfFiles = folder.listFiles();
for (File f : listOfFiles) {
if (f.getName().endsWith(".dcp")) {
Design des = Design.readCheckpoint(f.getAbsolutePath());
HashMap<String, ArrayList<String>> pips_by_tile = new HashMap<>();
for (Net n : des.getNets()) {
HashMap<Node, PIP> uphill = new HashMap<>();
HashSet<Node> allnodes = new HashSet<>();
if (n.getSource() != null)
uphill.put(n.getSource().getConnectedNode(), null);
for (PIP p : n.getPIPs()) {
uphill.put(p.getEndNode(), p);
allnodes.add(p.getStartNode());
allnodes.add(p.getEndNode());
}
for (PIP p : n.getPIPs()) {
String tile = p.getTile().getName() + ":" + p.getTile().getTileTypeEnum().toString();
TileTypeEnum ptt = p.getTile().getTileTypeEnum();
if (!pips_by_tile.containsKey(tile))
pips_by_tile.put(tile, new ArrayList<>());
String startName = p.getStartWireName(), endName = p.getEndWireName();
if (ptt == TileTypeEnum.XIPHY_BYTE_L) {
if (!endName.contains("ODT") && (startName.contains("CLB2PHY") || endName.contains("CLB2PHY")))
continue;
if (endName.contains("CLK_PIN") || endName.contains("CLKDIV_PIN") || endName.contains("D_PIN"))
continue;
SitePin sp = p.getEndNode().getSitePin();
if (sp != null) {
Site s = sp.getSite();
if (s.getSiteTypeEnum() == SiteTypeEnum.BITSLICE_RX_TX && endName.contains("Q5")) {
SiteInst si = des.getSiteInstFromSite(s);
boolean bypass = true;
if (si != null) {
for (Cell c : si.getCells()) {
if (!c.getType().equals("<LOCKED>")) {
bypass = false;
break;
}
}
}
if (bypass) {
String sn = site_index_in_tile(s.getTile(), s);
pips_by_tile.get(tile).add(sn + ".BYPASS." + sp.getPinName());
}
}
}
}
if (p.isBidirectional()) {
boolean is_fwd = uphill.containsKey(p.getStartNode());
pips_by_tile.get(tile).add("PIP." + p.getEndWireName() + "." + p.getStartWireName() + (is_fwd ? ".FWD" : ".REV"));
} else {
pips_by_tile.get(tile).add("PIP." + p.getEndWireName() + "." + p.getStartWireName());
}
}
}
HashMap<String, ArrayList<String>> sitefeatures_by_tile = new HashMap<>();
for (SiteInst si : des.getSiteInsts()) {
SiteTypeEnum ste = si.getSiteTypeEnum();
if (ste != SiteTypeEnum.HPIOB &&
ste != SiteTypeEnum.HPIOB_M &&
ste != SiteTypeEnum.HPIOB_S &&
ste != SiteTypeEnum.HPIOB_SNGL &&
ste != SiteTypeEnum.HDIOB_M && ste != SiteTypeEnum.HDIOB_S)
continue;
String tile = si.getTile().getName() + ":" + si.getTile().getTileTypeEnum().toString();
String sn = site_index_in_tile(si.getTile(), si.getSite());
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
Net ionet = si.getNetFromSiteWire("OUTBUF_O");
if (ionet == null)
continue;
Cell pad = si.getCell(si.getBEL("PAD"));
if (pad == null)
continue;
EDIFPort p = des.getTopEDIFCell().getPort(pad.getName());
var prop = des.getTopEDIFCell().getNet(pad.getName()).getProperties();
var pprop = p.getProperties();
String iostd = prop.get(new EDIFName("IOSTANDARD")).getValue();
String prefix = sn + "." + iostd;
tfeat.add(sn + ".USED");
tfeat.add(prefix + ".USED");
Cell inbuf = si.getCell(si.getBEL("INBUF"));
Cell outbuf = si.getCell(si.getBEL("OUTBUF"));
Cell pull = si.getCell(si.getBEL("PULL"));
if (pull != null)
System.out.println(pull.getType());
if (inbuf != null) {
tfeat.add(sn + ".IN");
tfeat.add(prefix + ".IN");
if (outbuf == null) {
tfeat.add(sn + ".IN_ONLY");
tfeat.add(prefix + ".IN_ONLY");
}
if (iostd.startsWith("SSTL") || iostd.startsWith("POD") || iostd.startsWith("HSUL") || iostd.startsWith("HSTL"))
{
if (pprop.containsKey(new EDIFName("X_internal_vref"))) {
double vref = Double.parseDouble(pprop.get(new EDIFName("X_internal_vref")).getValue());
tfeat.add("VREF.INTERNAL." + (int)(1000 * vref) + "_MV");
} else if (!pprop.containsKey(new EDIFName("X_internal_vref")) && !pprop.containsKey(new EDIFName("X_int_vref"))) {
tfeat.add("VREF.EXTERNAL");
}
}
if (iostd.endsWith("DCI") && (si.getTile().getTileYCoordinate() % 60) == 0) {
tfeat.add("VRP_USED");
}
Cell ibufctrl = si.getCell(si.getBEL("IBUFCTRL"));
if (ibufctrl != null && ibufctrl.getLogicalPinMapping("IBUFDISABLE") != null)
tfeat.add(sn + ".IBUFDISABLE_USED");
}
if (outbuf != null) {
tfeat.add(sn + ".OUT");
tfeat.add(prefix + ".OUT");
if (inbuf != null) {
tfeat.add(sn + ".IN_OUT");
tfeat.add(prefix + ".IN_OUT");
}
if (iostd.endsWith("DCI") && (si.getTile().getTileYCoordinate() % 60) == 0) {
tfeat.add("VRP_USED");
}
if (outbuf.getLogicalPinMapping("DCITERMDISABLE") != null) {
tfeat.add(sn + ".DCITERMDISABLE_USED");
}
}
if (pprop.containsKey(new EDIFName("X_PULLTYPE")))
tfeat.add(sn + ".PULLTYPE." + pprop.get(new EDIFName("X_PULLTYPE")).getValue());
if (pprop.containsKey(new EDIFName("X_DRIVE")))
tfeat.add(prefix + ".DRIVE." + pprop.get(new EDIFName("X_DRIVE")).getValue());
if (pprop.containsKey(new EDIFName("X_SLEW")) && outbuf != null) {
if (pprop.containsKey(new EDIFName("X_DRIVE"))) {
tfeat.add(prefix + ".DRIVE." + pprop.get(new EDIFName("X_DRIVE")).getValue() + ".SLEW." + pprop.get(new EDIFName("X_SLEW")).getValue());
}else {
tfeat.add(prefix + ".SLEW." + pprop.get(new EDIFName("X_SLEW")).getValue());
}
}
if (pprop.containsKey(new EDIFName("X_OUTPUT_IMPEDANCE")) && outbuf != null)
tfeat.add(prefix + ".OUTPUT_IMPEDANCE." + pprop.get(new EDIFName("X_OUTPUT_IMPEDANCE")).getValue());
if (pprop.containsKey(new EDIFName("X_EQUALIZATION")))
tfeat.add(prefix + ".EQUALIZATION." + pprop.get(new EDIFName("X_EQUALIZATION")).getValue());
if (pprop.containsKey(new EDIFName("X_ODT")))
tfeat.add(prefix + ".ODT." + pprop.get(new EDIFName("X_ODT")).getValue());
for (SitePIP pip : si.getUsedSitePIPs()) {
if (pip.getBEL().getBELType().contains("INV"))
continue;
tfeat.add(sn + "." + pip.getBEL().getName() + "." + pip.getInputPinName());
}
}
for (SiteInst si : des.getSiteInsts()) {
SiteTypeEnum ste = si.getSiteTypeEnum();
if (ste != SiteTypeEnum.HPIOBDIFFINBUF && ste != SiteTypeEnum.HPIOBDIFFOUTBUF)
continue;
String tile = si.getTile().getName() + ":" + si.getTile().getTileTypeEnum().toString();
String sn = site_index_in_tile(si.getTile(), si.getSite());
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
boolean used = false;
for (Cell c : si.getCells())
if (!c.getType().equals("<LOCKED>"))
used = true;
if (!used)
continue;;
if (ste == SiteTypeEnum.HPIOBDIFFINBUF) {
Node cursor = si.getSite().getConnectedNode("PAD_RES_0");
while (cursor.getSitePin() == null || cursor.getSitePin().getSite().getSiteTypeEnum() != SiteTypeEnum.HPIOB_M) {
for (Wire w : cursor.getAllWiresInNode()) {
if (w.getBackwardPIPs().isEmpty())
continue;
cursor = w.getBackwardPIPs().get(0).getStartNode();
break;
}
}
Site m = cursor.getSitePin().getSite();
SiteInst m_si = des.getSiteInstFromSite(m);
Cell pad = m_si.getCell(m_si.getBEL("PAD"));
EDIFPort p = des.getTopEDIFCell().getPort(pad.getName());
var prop = des.getTopEDIFCell().getNet(pad.getName()).getProperties();
var pprop = p.getProperties();
String iostd = prop.get(new EDIFName("IOSTANDARD")).getValue();
tfeat.add(sn + "." + iostd + ".DIFF_IN");
if (pprop.containsKey(new EDIFName("X_DIFF_TERM_ADV")))
tfeat.add(sn + "." + iostd + ".DIFF_TERM_ADV." + pprop.get(new EDIFName("X_DIFF_TERM_ADV")).getValue());
} else if (ste == SiteTypeEnum.HPIOBDIFFOUTBUF) {
Node cursor = si.getSite().getConnectedNode("AOUT");
while (cursor.getSitePin() == null || cursor.getSitePin().getSite().getSiteTypeEnum() != SiteTypeEnum.HPIOB_M) {
for (Wire w : cursor.getAllWiresInNode()) {
if (w.getForwardPIPs().isEmpty())
continue;
cursor = w.getForwardPIPs().get(0).getEndNode();
break;
}
}
Site m = cursor.getSitePin().getSite();
SiteInst m_si = des.getSiteInstFromSite(m);
Cell pad = m_si.getCell(m_si.getBEL("PAD"));
EDIFPort p = des.getTopEDIFCell().getPort(pad.getName());
var prop = des.getTopEDIFCell().getNet(pad.getName()).getProperties();
var pprop = p.getProperties();
String iostd = prop.get(new EDIFName("IOSTANDARD")).getValue();
tfeat.add(sn + "." + iostd + ".DIFF_OUT");
}
}
for (SiteInst si : des.getSiteInsts()) {
String tile = si.getTile().getName() + ":" + si.getTile().getTileTypeEnum().toString();
if (si.getSiteTypeEnum() == SiteTypeEnum.BITSLICE_COMPONENT_RX_TX) {
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
String sp = site_index_in_tile(si.getTile(), si.getSite()) + ".";
boolean only_locked = true;
for (Cell c : si.getCells())
if (!c.getType().equals("<LOCKED>"))
only_locked = false;
if (!only_locked)
tfeat.add(sp + "COMPONENT_MODE");
else
continue;
Cell idelay = si.getCell("IDELAY");
if (idelay != null)
add_delay(tfeat, sp + "IDELAY", idelay);
Cell odelay = si.getCell("ODELAY");
if (odelay != null)
add_delay(tfeat, sp + "ODELAY", odelay);
Cell iserdes = si.getCell("ISERDES");
if (iserdes != null)
add_iserdes(tfeat, sp + "ISERDES", iserdes);
Cell oserdes = si.getCell("OSERDES");
if (oserdes != null)
add_oserdes(tfeat, sp + "OSERDES", oserdes);
Cell iff = si.getCell("IN_FF");
if (iff != null)
add_ff(tfeat, sp + "IN_FF", iff);
Cell off = si.getCell("OUT_FF");
if (off != null)
add_ff(tfeat, sp + "OUT_FF", off);
for (SitePIP pip : si.getUsedSitePIPs()) {
if (pip.getBEL().getBELType().contains("INV"))
continue;
tfeat.add(sp + pip.getBEL().getName() + "." + pip.getInputPinName());
}
if (odelay != null && oserdes == null && off == null && si.getNetFromSiteWire("OSERDES_OQ") != null)
tfeat.add(sp + "OSERDES.BYPASSED");
if (idelay == null && si.getNetFromSiteWire("IDELAY_DATAOUT") != null)
tfeat.add(sp + "IDELAY.BYPASSED");
String[] used_sitewires = {"OSERDES_OQ", "TX_Q", "RX_D"};
for (String sw : used_sitewires) {
boolean active = false;
if (si.getNetFromSiteWire(sw) != null)
active = true;
for (SitePIP p : si.getUsedSitePIPs())
if (p.getInputPin().getSiteWireName().equals(sw))
active = true;
if (active)
tfeat.add(sp + sw + ".USED");
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.BITSLICE_CONTROL) {
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
String sp = site_index_in_tile(si.getTile(), si.getSite()) + ".";
for (Cell c : si.getCells()) {
if (c.getType().equals("IDELAYCTRL")) {
tfeat.add(sp + "IDELAYCTRL.USED");
}
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.HDIOLOGIC_M || si.getSiteTypeEnum() == SiteTypeEnum.HDIOLOGIC_S) {
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
String sp = site_index_in_tile(si.getTile(), si.getSite()) + ".";
boolean only_locked = true;
for (Cell c : si.getCells())
if (!c.getType().equals("<LOCKED>"))
only_locked = false;
if (!only_locked)
tfeat.add(sp + "USED");
else
continue;
Cell iff = si.getCell("IFF");
if (iff != null)
add_ff(tfeat, sp + "IFF", iff);
Cell off = si.getCell("OPFF");
if (off != null)
add_ff(tfeat, sp + "OPFF", off);
Cell tff = si.getCell("TFF");
if (tff != null)
add_ff(tfeat, sp + "TFF", tff);
Cell iddr = si.getCell("IDDR");
if (iddr != null)
add_iddr(tfeat, sp + "IDDR", iddr);
Cell optff = si.getCell("OPTFF");
if (optff != null)
add_oserdes(tfeat, sp + "OPTFF", optff);
}
}
FileWriter vf = new FileWriter(f.getAbsolutePath().replace(".dcp", ".features"), false);
PrintWriter v = new PrintWriter(vf);
for (Tile t : des.getDevice().getAllTiles()) {
TileTypeEnum tt = t.getTileTypeEnum();
if (tt == TileTypeEnum.HPIO_L || tt == TileTypeEnum.HPIO_RIGHT || tt == TileTypeEnum.HDIO_TOP_RIGHT
|| tt == TileTypeEnum.HDIO_BOT_RIGHT || tt == TileTypeEnum.XIPHY_BYTE_L) {
String tname = t.getName() + ":" + tt.toString();
if (sitefeatures_by_tile.containsKey(tname) || pips_by_tile.containsKey(tname)) {
v.println(".tile " + tname);
if (sitefeatures_by_tile.containsKey(tname))
for (String sf : sitefeatures_by_tile.get(tname))
v.println(sf);
if (pips_by_tile.containsKey(tname))
for (String pip : pips_by_tile.get(tname))
v.println(pip);
}
}
}
v.close();
vf.close();
}
}
}
}