blob: 0a310171ef0b4437f529bc0fc73e1ffd3afd1e7c [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.EDIFName;
import com.xilinx.rapidwright.edif.EDIFPort;
import com.xilinx.rapidwright.edif.EDIFPortInst;
import org.python.bouncycastle.crypto.tls.DefaultTlsCipherFactory;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
public class dump_clocking {
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;
}
static boolean is_node_inverted(Net n, Node cursor) {
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;
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;
}
static int get_clock_depth(Net n, Node cursor) {
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);
}
}
int distr_count = 0;
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();
// System.out.println(" " + name);
if (p.isBidirectional() && p.getStartNode().equals(cursor))
cursor = p.getEndNode();
else
cursor = p.getStartNode();
if (cursor.getWireName().contains("DISTR"))
distr_count++;
//System.out.println(" <---" + cursor.getTile().getName() + "/" + cursor.getWireName());
}
//System.out.println("distr count: " + distr_count);
return distr_count;
}
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_clk");
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);
int max_distr_depth = 0;
for (PIP p : n.getPIPs()) {
if (!p.isBidirectional()) {
uphill.put(p.getEndNode(), p);
}
allnodes.add(p.getStartNode());
allnodes.add(p.getEndNode());
TileTypeEnum ptt = p.getTile().getTileTypeEnum();
if (ptt == TileTypeEnum.RCLK_INT_L || ptt == TileTypeEnum.RCLK_INT_R) {
if (p.getEndWireName().startsWith("CLK_LEAF_SITES_") && p.getEndWireName().endsWith("_CLK_LEAF")) {
String tile = p.getTile().getName() + ":" + p.getTile().getTileTypeEnum().toString();
if (!pips_by_tile.containsKey(tile))
pips_by_tile.put(tile, new ArrayList<>());
pips_by_tile.get(tile).add("WIRE." + p.getEndWireName() + ".DRIVEN");
if (p.getStartWireName().endsWith("_CLK_IN") && p.isRouteThru()) {
String site = site_index_in_tile(p.getTile(), p.getStartNode().getSitePin().getSite());
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.IN_USE");
if (n.getName().startsWith("leaf_delay_")) {
int count = 0;
for (PIP p2 : n.getPIPs()) {
if (p2.getEndWireName().startsWith("CLK_LEAF_SITES_") && p2.getEndWireName().endsWith("_CLK_LEAF") && p2.getStartWireName().endsWith("_CLK_IN"))
++count;
}
if (count == 1) {
int value = Integer.parseInt(n.getName().split("_")[2]);
sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.DELAY_TAP_" + value);
}
if (is_node_inverted(n, p.getStartNode())) {
sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.IINV.1");
}
}
}
}
}
if (p.getStartWire().getWireName().contains("BUFCE_ROW_FSR") && p.getStartWire().getWireName().endsWith("CLK_IN")) {
max_distr_depth = Math.max(max_distr_depth, get_clock_depth(n, p.getStartNode()));
}
}
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 ||
wtt == TileTypeEnum.RCLK_DSP_INTF_R || wtt == TileTypeEnum.RCLK_RCLK_URAM_INTF_L_FT ||
wtt == TileTypeEnum.RCLK_CLEM_R || wtt == TileTypeEnum.RCLK_CLEL_R || wtt == TileTypeEnum.GTH_QUAD_RIGHT) {
if (w.getWireName().startsWith("CLK_TEST_BUF_SITE_") || w.getWireName().startsWith("CLK_HROUTE_CORE_OPT") ||
w.getWireName().startsWith("CLK_VDISTR_BOT") || w.getWireName().startsWith("CLK_VDISTR_TOP") ||
w.getWireName().startsWith("CLK_VROUTE_BOT") || w.getWireName().startsWith("CLK_VROUTE_TOP")) {
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 ||
wtt == TileTypeEnum.RCLK_RCLK_XIPHY_INNER_FT || wtt == TileTypeEnum.RCLK_HDIO || wtt == TileTypeEnum.GTH_QUAD_RIGHT) {
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");
}
}
if (wtt == TileTypeEnum.CMT_L) {
//CLK_HROUTE_
if (w.getWireName().startsWith("CLK_HROUTE_") || w.getWireName().startsWith("CLK_HDISTR_") || w.getWireName().startsWith("CLK_VDISTR_") ||
w.getWireName().startsWith("CLK_TEST_BUF_SITE_")) {
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();
if (p.getTile().getTileTypeEnum() == TileTypeEnum.BRAM || p.getTile().getTileTypeEnum() == TileTypeEnum.INT)
continue;
if (!pips_by_tile.containsKey(tile))
pips_by_tile.put(tile, new ArrayList<>());
if (p.isBidirectional()) {
Node cursor = p.getStartNode();
boolean is_fwd = false;
if (uphill.containsKey(p.getStartNode())) {
is_fwd = true;
uphill.put(p.getEndNode(), p);
} else if (uphill.containsKey(p.getEndNode())) {
is_fwd = false;
uphill.put(p.getStartNode(), p);
} else {
continue;
}
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());
}
if (n.getName().contains("clk_dly_fuzz") && p.getStartWire().getWireName().contains("BUFCE_ROW_FSR") && p.getStartWire().getWireName().endsWith("CLK_IN")) {
int depth = get_clock_depth(n, p.getStartNode());
int tap = max_distr_depth - depth;
String bufce_name = site_index_in_tile(p.getTile(), p.getStartNode().getSitePin().getSite());
for (int i = 0; i < 3; i++) {
if (((tap >> i) & 0x1) == 1) {
pips_by_tile.get(tile).add(bufce_name + ".COMP_DELAY_TAP[" + i + "]");
}
}
}
}
}
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.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);
}
}
}
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFCE_ROW_FSR) {
for (Cell c : si.getCells()) {
if (c.getType().equals("<LOCKED>"))
System.out.println(c.getBELName());
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE || si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE_DIV) {
String name = site_index_in_tile(si.getTile(), si.getSite());
for (Cell c : si.getCells()) {
if (c.getType() != null && c.getType().startsWith("BUFGCE")) {
tfeat.add(name + "." + c.getType() + ".IN_USE");
var all_props = c.getProperties();
for (var e : all_props.entrySet()) {
String propname = e.getKey().getName();
String v = e.getValue().getValue();
int base_pos = v.indexOf("'b");
if (base_pos != -1)
v = v.substring(base_pos + 2);
if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
String pinname = propname.substring(3, propname.length() - 9);
if (pinname.equals("I")) {
if (is_sink_inverted(si.getSitePinInst("CLK_IN")))
v = (v.equals("1") ? "0" : "1");
String sw = c.getSiteWireNameFromLogicalPin(pinname);
if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
continue;
}
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
} else if ((si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE && propname.equals("CE_TYPE")) || propname.equals("BUFGCE_DIVIDE")) {
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
}
}
}
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFGCTRL) {
String name = site_index_in_tile(si.getTile(), si.getSite());
for (Cell c : si.getCells()) {
if (c.getType() != null && c.getType().startsWith("BUFGCTRL")) {
tfeat.add(name + "." + c.getType() + ".IN_USE");
var all_props = c.getProperties();
for (var e : all_props.entrySet()) {
String propname = e.getKey().getName();
String v = e.getValue().getValue();
int base_pos = v.indexOf("'b");
if (base_pos != -1)
v = v.substring(base_pos + 2);
if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
String pinname = propname.substring(3, propname.length() - 9);
if (pinname.equals("I0") || pinname.equals("I1")) {
String sw = c.getSiteWireNameFromLogicalPin(pinname);
if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
continue;
if (is_sink_inverted(si.getSitePinInst("CLK_" + pinname)))
v = (v.equals("1") ? "0" : "1");
}
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
} else if (propname.equals("INIT_OUT") || propname.startsWith("PRESELECT_")) {
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
}
}
}
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.MMCM) {
String name = site_index_in_tile(si.getTile(), si.getSite());
Cell c = si.getCell("MMCM");
if (c == null || c.getType() == null)
continue;
tfeat.add(name + ".IN_USE");
var all_props = c.getProperties();
for (var e : all_props.entrySet()) {
String propname = e.getKey().getName();
String v = e.getValue().getValue();
int base_pos = v.indexOf("'b");
if (base_pos != -1)
v = v.substring(base_pos + 2);
if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
String pinname = propname.substring(3, propname.length() - 9);
if (pinname.equals("CLKIN1") || pinname.equals("CLKIN2") || pinname.equals("CLKFBIN"))
continue;
String sw = c.getSiteWireNameFromLogicalPin(pinname);
if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
continue;
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
} else if (propname.equals("COMPENSATION")) {
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
}
}
} else if (si.getSiteTypeEnum() == SiteTypeEnum.PLL) {
String name = site_index_in_tile(si.getTile(), si.getSite());
Cell c = si.getCell("PLL");
if (c == null || c.getType() == null)
continue;
tfeat.add(name + ".IN_USE");
var all_props = c.getProperties();
for (var e : all_props.entrySet()) {
String propname = e.getKey().getName();
String v = e.getValue().getValue();
int base_pos = v.indexOf("'b");
if (base_pos != -1)
v = v.substring(base_pos + 2);
if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
String pinname = propname.substring(3, propname.length() - 9);
if (pinname.equals("CLKIN") || pinname.equals("CLKFBIN"))
continue;
String sw = c.getSiteWireNameFromLogicalPin(pinname);
if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
continue;
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
} else if (propname.equals("COMPENSATION")) {
tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
}
}
}
}
for (Tile t : des.getDevice().getAllTiles()) {
if (t.getTileTypeEnum() != TileTypeEnum.RCLK_HPIO_L)
continue;
boolean dci_used = false;
Tile[] io_tiles = {des.getDevice().getTile(t.getRow()+30, t.getColumn()), des.getDevice().getTile(t.getRow()-1, t.getColumn())};
for (Tile iot : io_tiles) {
for (Site s : iot.getSites()) {
SiteInst si = des.getSiteInstFromSite(s);
if (si == null)
continue;
Cell pad = si.getCell(si.getBEL("PAD"));
if (pad == null)
continue;
EDIFPort p = des.getTopEDIFCell().getPort(pad.getName());
if (des.getTopEDIFCell().getNet(pad.getName()) == null)
continue;
var prop = des.getTopEDIFCell().getNet(pad.getName()).getProperties();
if (prop == null || !prop.containsKey(new EDIFName("IOSTANDARD")))
continue;
String iostd = prop.get(new EDIFName("IOSTANDARD")).getValue();
if (iostd.contains("POD12_DCI") && !f.getName().contains("ipi")) // FIXME: find out why this loses bits
dci_used = true;
}
}
if (dci_used) {
String tile = t.getName() + ":" + t.getTileTypeEnum().toString();
if (!sitefeatures_by_tile.containsKey(tile))
sitefeatures_by_tile.put(tile, new ArrayList<>());
ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
tfeat.add("POD12_DCI_USED");
}
}
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.RCLK_INT_L|| tt == TileTypeEnum.RCLK_CLEM_L || tt == TileTypeEnum.RCLK_INT_R || tt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || tt == TileTypeEnum.RCLK_CLEM_R ||
tt == TileTypeEnum.RCLK_DSP_INTF_L || tt == TileTypeEnum.RCLK_BRAM_L || tt == TileTypeEnum.RCLK_BRAM_R || tt == TileTypeEnum.RCLK_BRAM_INTF_L ||
tt == TileTypeEnum.RCLK_DSP_INTF_R || tt == TileTypeEnum.RCLK_DSP_CLKBUF_L || tt == TileTypeEnum.RCLK_RCLK_XIPHY_INNER_FT || tt == TileTypeEnum.RCLK_RCLK_INTF_XIPHY_LEFT_L_FT ||
tt == TileTypeEnum.RCLK_HDIO || tt == TileTypeEnum.RCLK_HPIO_L || tt == TileTypeEnum.RCLK_HPIO_R ||
tt == TileTypeEnum.RCLK_CLEL_L || tt == TileTypeEnum.RCLK_CLEL_R || tt == TileTypeEnum.RCLK_CLEL_L_L || tt == TileTypeEnum.RCLK_CLEL_L_R ||
tt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_R || tt == TileTypeEnum.CMT_L || tt == TileTypeEnum.CMT_RIGHT ||
tt == TileTypeEnum.RCLK_RCLK_URAM_INTF_L_FT || tt == TileTypeEnum.GTH_QUAD_RIGHT) {
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();
}
}
}
}