| // 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(); |
| } |
| } |
| } |
| } |