blob: 56cfc11f33f9cc35e726a5340c427a883b6f3b60 [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.EDIFPortInst;
import com.xilinx.rapidwright.edif.EDIFPropertyValue;
import com.xilinx.rapidwright.edif.EDIFValueType;
import jnr.ffi.annotations.In;
import org.json.Property;
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_features {
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()) {
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);
}
static HashSet<String> inverted_pips = new HashSet<>();
static boolean is_sink_inverted(SitePinInst spi) {
if (spi == null || spi.getNet() == null)
return false;
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 void main(String[] args) throws IOException {
Scanner scanner = new Scanner(new File("/invpips.txt"));
while (scanner.hasNextLine()) {
String nl = scanner.nextLine().trim();
inverted_pips.add(nl);
}
File folder = new File("/specimen");
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<>();
HashMap<String, ArrayList<String>> sitefeatures_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 (Node node : allnodes) {
for (Wire w : node.getAllWiresInNode()) {
TileTypeEnum wtt = w.getTile().getTileTypeEnum();
if (wtt == TileTypeEnum.RCLK_BRAM_INTF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_TD_R ||
wtt == TileTypeEnum.RCLK_CLEL_L_L || wtt == TileTypeEnum.RCLK_CLEL_L || wtt == TileTypeEnum.RCLK_CLEL_L_R ||
wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_L || wtt == TileTypeEnum.RCLK_DSP_INTF_L) {
if (w.getWireName().startsWith("CLK_TEST_BUF_SITE_") || w.getWireName().startsWith("CLK_HROUTE_CORE_OPT")) {
String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
if (!pips_by_tile.containsKey(tile))
pips_by_tile.put(tile, new ArrayList<>());
pips_by_tile.get(tile).add("WIRE." + w.getWireName() + ".USED");
}
}
if (wtt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_L) {
if (w.getWireName().startsWith("CLK_HROUTE") || w.getWireName().startsWith("CLK_HDISTR") ) {
String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
if (!pips_by_tile.containsKey(tile))
pips_by_tile.put(tile, new ArrayList<>());
pips_by_tile.get(tile).add("WIRE." + w.getWireName() + ".USED");
}
}
}
}
for (PIP p : n.getPIPs()) {
String tile = p.getTile().getName() + ":" + p.getTile().getTileTypeEnum().toString();
TileTypeEnum ptt = p.getTile().getTileTypeEnum();
if (ptt == TileTypeEnum.BRAM)
continue;
if (!pips_by_tile.containsKey(tile))
pips_by_tile.put(tile, new ArrayList<>());
if (ptt == TileTypeEnum.INT_INTF_L_IO) {
if (p.getEndWireName().contains("LOGIC_OUTS"))
pips_by_tile.get(tile).add("WIRE.LOGIC_OUTS_R.DRIVEN");
continue;
}
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());
}
}
}
for (SiteInst si : des.getSiteInsts()) {
String tile = si.getTile().getName() + ":" + si.getTile().getTileTypeEnum().toString();
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
if (si.getSiteTypeEnum() == SiteTypeEnum.SLICEL || si.getSiteTypeEnum() == SiteTypeEnum.SLICEM) {
boolean[] clkinv = {false, false}, srinv = {false, false}, ffsync = {false, false}, latch = {false, false};
boolean[] haveff = {false, false};
boolean[] srused = {false, false, false, false};
boolean[] ceused = {false, false, false, false};
for (BEL b : si.getBELs()) {
String belName = b.getName();
Cell c = si.getCell(b);
if (c == null)
continue;
if (belName.contains("LUT")) {
if (c.getType().startsWith("RAM")) {
tfeat.add(belName.replaceAll("[56]", "") + ".RAM");
if (c.getType().contains("32"))
tfeat.add(belName.replaceAll("[56]", "") + ".RAM.SMALL");
else
tfeat.add(belName.replaceAll("[56]", "") + ".RAM.LARGE");
}
if (c.getType().contains("SRL"))
tfeat.add(belName.replaceAll("[56]", "") + ".SRL");
if (c.getType().contains("SRL16"))
tfeat.add(belName.replaceAll("[56]", "") + ".SRL.SMALL");
if (c.getType().contains("SRLC32"))
tfeat.add(belName.replaceAll("[56]", "") + ".SRL.LARGE");
for (int i = 6; i <= 8; i++) {
if (c.getPhysicalPinMapping("WADR" + i) != null)
tfeat.add("WA" + (i+1) + "USED");
}
if (c.getType().contains("SRLC32") && c.getEDIFCellInst() != null) {
EDIFPortInst epi = c.getEDIFCellInst().getPortInst("D");
if (epi != null && c.getPhysicalPinMapping("D") != null)
tfeat.add(belName.replaceAll("[56]", "") + ".DI1." + c.getPhysicalPinMapping("D"));
} else if (c.getLogicalPinMapping("DI1") != null) {
tfeat.add(belName.replaceAll("[56]", "") + ".DI1.DI1");
}
if ((c.getType().contains("RAM") || c.getType().contains("SRL")) && c.getEDIFCellInst() != null && c.getProperty("IS_CLK_INVERTED") != null) {
String lclkinv = c.getProperty("IS_CLK_INVERTED").getValue();
tfeat.add("LCLKINV." + lclkinv.substring(lclkinv.length() - 1));
}
}
var p2l = c.getPinMappingsP2L();
if (belName.contains("LUT") && c.getEDIFCellInst() != null && c.getProperty("INIT") != null) {
boolean has_56lut = false;
if (belName.contains("6LUT") && si.getCell(si.getBEL(belName.replace('6', '5'))) != null)
has_56lut = true;
if (!has_56lut && (c.getType().startsWith("LUT"))) {
// LUT init bits
long long_init = LUTTools.getInitValue(c.getProperty("INIT").getValue());
for (int i = 0; i < 64; i++) {
if (belName.contains("5LUT") && (i >= 32))
continue;
String sw = belName.substring(0, 1) + "6";
Net sn = si.getNetFromSiteWire(sw);
if (belName.contains("6LUT") && sn != null && sn.getName().equals(Net.VCC_NET))
continue;
int init_index = 0;
boolean valid_index = true;
for (int j = 0; j < 6; j++) {
if ((i & (1 << j)) == 0)
continue;
String log = p2l.getOrDefault("A" + Integer.toString(j + 1), "");
if (log.isEmpty())
continue;
if (log.startsWith("RADR")) {
init_index |= (1 << (Integer.parseInt(log.substring(4))));
} else if (log.startsWith("A[")) {
init_index |= (1 << (Integer.parseInt(log.substring(2, 3))));
} else if (!log.startsWith("I") && !log.startsWith("A")) {
valid_index = false;
break;
} else {
init_index |= (1 << (Integer.parseInt(log.substring(1))));
}
}
if (!valid_index)
continue;
if ((long_init & (1L << init_index)) == 0)
continue;
tfeat.add(belName.replaceAll("[56]", "") + ".INIT[" + i + "]");
}
}
} else if (belName.contains("FF")) {
boolean is_latch = false, is_sync = false, srval = false;
String clkpin, srpin, cepin;
if (c.getType().equals("FDPE")) {
is_latch = false;
is_sync = false;
srval = true;
clkpin = "C";
cepin = "CE";
srpin = "PRE";
} else if (c.getType().equals("FDCE")) {
is_latch = false;
is_sync = false;
srval = false;
clkpin = "C";
cepin = "CE";
srpin = "CLR";
} else if (c.getType().equals("FDSE")) {
is_latch = false;
is_sync = true;
srval = true;
clkpin = "C";
cepin = "CE";
srpin = "S";
} else if (c.getType().equals("FDRE")) {
is_latch = false;
is_sync = true;
srval = false;
clkpin = "C";
cepin = "CE";
srpin = "R";
} else if (c.getType().equals("LDPE")) {
is_latch = true;
is_sync = false;
srval = true;
clkpin = "G";
cepin = "GE";
srpin = "PRE";
} else if (c.getType().equals("LDCE")) {
is_latch = true;
is_sync = false;
srval = false;
clkpin = "G";
cepin = "GE";
srpin = "CLR";
} else {
continue;
}
String primtype = is_latch ? "LATCH" : "FF";
if (c.getProperty("INIT") != null) {
String init = c.getProperty("INIT").getValue();
tfeat.add(belName + "." + primtype + ".INIT." + init.substring(init.length() - 1));
}
tfeat.add(belName + "." + primtype + ".SRVAL." + (srval ? "1" : "0"));
int half = ("EFGH".contains(belName.substring(0, 1))) ? 1 : 0;
latch[half] = is_latch;
ffsync[half] = is_sync;
clkinv[half] = (c.getProperty("IS_" + clkpin + "_INVERTED") != null && c.getProperty("IS_" + clkpin + "_INVERTED").getValue().equals("1'b1"));
srinv[half] = (c.getProperty("IS_" + srpin + "_INVERTED") != null && c.getProperty("IS_" + srpin + "_INVERTED").getValue().equals("1'b1"));
haveff[half] = true;
int two = belName.endsWith("2") ? 1 : 0;
srused[half * 2 + two] = (c.getPhysicalPinMapping(srpin) != null);
ceused[half * 2 + two] = (c.getPhysicalPinMapping(cepin) != null);
} else if (belName.contains("CARRY8")) {
if (!c.getType().equals("CARRY8"))
continue;
if (c.getProperty("CARRY_TYPE") != null)
tfeat.add("CARRY8.CARRY_TYPE." + c.getProperty("CARRY_TYPE").getValue());
String[] pins = {"CI", "DI[0]", "DI[1]", "DI[2]", "DI[3]", "DI[4]", "DI[5]", "DI[6]", "DI[7]", "CI_TOP"};
for (String p : pins) {
String phys = c.getPhysicalPinMapping(p);
if (phys != null && (!p.equals("CI") || !phys.equals("CIN"))) {
EDIFPortInst epi = c.getEDIFCellInst().getPortInst(p);
if (epi != null && epi.getNet() != null) {
String pn = p.replace("[", "").replace("]", "");
tfeat.add("CARRY8." + pn + "." + phys);
}
} else if (p.equals("CI") || p.equals("CI_TOP")) {
EDIFPortInst epi = c.getEDIFCellInst().getPortInst(p);
if (epi != null && epi.getNet() != null) {
String netname = epi.getNet().getName();
if (netname.equals("<const0>"))
tfeat.add("CARRY8." + p + ".0");
else if (netname.equals("<const1>"))
tfeat.add("CARRY8." + p + ".1");
}
}
}
}
}
for (int i = 0; i < 2; i++) {
String half = "ABCDEFGH".substring(4 * i, 4 * (i + 1));
if (!haveff[i])
continue;
String primtype = latch[i] ? "LATCH" : "FF";
tfeat.add(half + "FF." + primtype);
tfeat.add(half + "FF." + primtype + ".CLKINV." + (clkinv[i] ? "1" : "0"));
tfeat.add(half + "FF." + primtype + ".SRINV." + (srinv[i] ? "1" : "0"));
if (ffsync[i])
tfeat.add(half + "FF." + primtype + ".SYNC");
for (int j = 0; j < 2; j++) {
if (srused[i * 2 + j])
tfeat.add(half + "FF" + (j == 1 ? "2" : "") + ".SRUSED");
if (ceused[i * 2 + j])
tfeat.add(half + "FF" + (j == 1 ? "2" : "") + ".CEUSED");
}
}
for (SitePIP sp : si.getUsedSitePIPs()) {
if (sp.getBELName().contains("INV"))
continue;
if (sp.getBELName().startsWith("OUTMUX") && sp.getInputPinName().equals("D6")) {
if (si.getSitePinInst(sp.getOutputPin().getConnectedSitePinName()) == null)
continue;
}
tfeat.add(sp.getBELName() + "." + sp.getInputPinName());
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFCE_LEAF) {
String name = site_index_in_tile(si.getTile(), si.getSite());
for (Cell c : si.getCells()) {
if (c.getType() != null && c.getType().equals("BUFCE_LEAF")) {
tfeat.add(name + ".BUFCE_LEAF.IN_USE");
if (c.getProperty("CE_TYPE") != null)
tfeat.add(name + ".BUFCE_LEAF.CE_TYPE." + c.getProperty("CE_TYPE").getValue());
var all_props = c.getProperties();
for (var e : all_props.entrySet()) {
String propname = e.getKey().getName();
if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
String pinname = propname.substring(3, propname.length() - 9);
String v = e.getValue().getValue();
int base_pos = v.indexOf("'b");
if (base_pos != -1)
v = v.substring(base_pos + 2);
if (pinname.equals("I"))
if (is_sink_inverted(si.getSitePinInst("CLK_IN")))
v = (v.equals("1") ? "0" : "1");
tfeat.add(name + ".BUFCE_LEAF." + pinname + "INV." + v);
}
}
}
}
}
}
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.CLEL_L || tt == TileTypeEnum.CLEL_R || tt == TileTypeEnum.CLEM_R || tt == TileTypeEnum.CLEM
|| tt == TileTypeEnum.INT || tt == TileTypeEnum.INT_INTF_L_IO) {
String tname = t.getName() + ":" + tt.toString();
if (!pips_by_tile.containsKey(tname) && !sitefeatures_by_tile.containsKey(tname))
continue;
v.println(".tile " + tname);
if (pips_by_tile.containsKey(tname))
for (String p : pips_by_tile.get(tname))
v.println(p);
if (sitefeatures_by_tile.containsKey(tname))
for (String sf : sitefeatures_by_tile.get(tname))
v.println(sf);
}
}
vf.close();
}
}
}
}