Skip to content

Commit

Permalink
Various preprocessing fixes for Versal routing (#1115)
Browse files Browse the repository at this point in the history
* [IntentCode] Add isVersalCnode() helper method

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

Conflicts:
	src/com/xilinx/rapidwright/device/IntentCode.java

* [GlobalSignalRouting] Allow INTF CNODEs, all CNODEs even if reserved

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* Revert "[IntentCode] Add isVersalCnode() helper method"

This reverts commit 435152a.

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* Move Versal {B,C}NODE heuristic from determineRoutingTargets() to

initializeRouting(), which is after route{GlobalClock,Static}Nets()

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [RouterHelper] invertPossibleGndPinsToVccPins() exception for DSP58

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [DesignTools] getAllRoutedSitePinsFromPhysicalPin() handle SLICE_FF_CLK_MOD

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [DesignTools] getAllRoutedSitePinsFromPhysicalPin() to handle DSP_CAS_DELAY

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [CUFR] CUFR and PartialCUFR to default to --hus

Emit warning if not enabled

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [RouterHelper] invertPossibleGndPinsToVccPins() to invert Versal BRAM.CLK

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [RouterHelper] invertPossibleGndPinsToVccPins() to use correct sitewire

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [DesignTools] createA1A6ToStaticNets() to handle SRL16s on LUT5+6

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* Fix DesignTools.createA1A6ToStaticNets()

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [RouteNode] Correct assertions in setBaseCost() for Versal

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* [TestNode] Extend testNodeReachabilityVersal

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* Update comment

Signed-off-by: Eddie Hung <eddie.hung@amd.com>

* Update src/com/xilinx/rapidwright/design/DesignTools.java

Signed-off-by: eddieh-xlnx <eddie.hung@amd.com>

---------

Signed-off-by: Eddie Hung <eddie.hung@amd.com>
Signed-off-by: eddieh-xlnx <eddie.hung@amd.com>
  • Loading branch information
eddieh-xlnx authored Nov 23, 2024
1 parent 7bd8e7d commit d75c404
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 90 deletions.
135 changes: 89 additions & 46 deletions src/com/xilinx/rapidwright/design/DesignTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -2296,11 +2296,19 @@ public static List<String> getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne
} else if (bel.isLUT() ||
bel.getBELType().endsWith("MUX") || // F[789]MUX
// Versal
bel.isSliceFFClkMod() ||
bel.getName().endsWith("_IMR")) {
Cell possibleRouteThru = inst.getCell(bel);
if (possibleRouteThru != null && possibleRouteThru.isRoutethru()) {
String routeThru = possibleRouteThru.getPinMappingsP2L().keySet().iterator().next();
queue.add(bel.getPin(routeThru));
if (possibleRouteThru == null) {
BELPin clkBelPin = bel.isSliceFFClkMod() ? bel.getPin("CLK") : null;
if (clkBelPin != null && inst.getNetFromSiteWire(clkBelPin.getSiteWireName()) == net) {
queue.add(clkBelPin);
}
} else {
if (possibleRouteThru.isRoutethru()) {
String routeThru = possibleRouteThru.getPinMappingsP2L().keySet().iterator().next();
queue.add(bel.getPin(routeThru));
}
}
}
}
Expand All @@ -2309,20 +2317,40 @@ public static List<String> getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne
if (!siteWires.contains(sink.getSiteWireName())) continue;
if (sink.isSitePort()) {
sitePins.add(sink.getName());
} else if (sink.getBEL().getBELClass() == BELClass.RBEL) {
continue;
}
BEL bel = sink.getBEL();
if (bel.getBELClass() == BELClass.RBEL) {
// Check if the SitePIP is being used
SitePIP sitePIP = inst.getUsedSitePIP(sink.getBELName());
if (sitePIP == null) continue;
// Don't proceed if it's configured for a different pin
if (!sitePIP.getInputPinName().equals(sink.getName())) continue;
SitePIP sitePIP = inst.getUsedSitePIP(sink);
if (sitePIP == null) {
continue;
}
assert(sitePIP.getInputPinName().equals(sink.getName()));
// Make this the new source to search from and keep looking...
queue.add(sitePIP.getOutputPin());
} else if (sink.getBEL().isFF()) {
} else if (bel.isFF()) {
// FF pass thru option (not a site PIP)
siteWireName = sink.getBEL().getPin("Q").getSiteWireName();
siteWireName = bel.getPin("Q").getSiteWireName();
if (siteWires.contains(siteWireName)) {
sitePins.add(siteWireName);
}
} else if (bel.getBELType().equals("DSP_CAS_DELAY")) {
// Versal only
SitePIP sitePIP = inst.getUsedSitePIP(sink);
if (sitePIP == null) {
continue;
}
assert(sitePIP.getInputPinName().equals(sink.getName()));
// For an unknown reason, it appears that the sitewire is not painted correctly ...
// Make this the new source to search from and keep looking...
// queue.add(sitePIP.getOutputPin());
// ... so assume it is and workaround
BELPin source = sitePIP.getOutputPin();
assert(source.getSiteConns().size() == 1);
BELPin port = source.getSiteConns().get(0);
assert(port.isSitePort());
sitePins.add(port.getName());
}
}
}
Expand Down Expand Up @@ -3244,61 +3272,74 @@ public static void createA1A6ToStaticNets(Design design) {
}

String belName = bel.getName();
if ("SRL16E".equals(cell.getType()) || "SRLC32E".equals(cell.getType())) {
String pinName = belName.charAt(0) + "1";
SitePinInst spi = si.getSitePinInst(pinName);
if (spi != null) {
assert(spi.getNet().isVCCNet());
char fiveOrSix = belName.charAt(1);
if (fiveOrSix == '5') {
// Assume that only 5LUT can use O5
assert(cell.getLogicalPinMapping("O5") != null || cell.isRoutethru());
if (LUTTools.getCompanionLUTCell(cell) != null) {
// 5LUT is used, but 6LUT also exists; let the 6LUT deal with things
continue;
}
vccNet.createPin(pinName, si);
}
} else {
assert(fiveOrSix == '6');

if (cell.getLogicalPinMapping("A6") != null) {
// A6 pin is being used by LUT
continue;
if ("SRLC32E".equals(cell.getType())) {
// For SRLC32Es, only the A1 needs to be tied to VCC
String pinName = belName.charAt(0) + "1";
SitePinInst spi = si.getSitePinInst(pinName);
if (spi == null) {
vccNet.createPin(pinName, si);
} else {
assert(spi.getNet().isVCCNet());
}
// A6 is needed as a logical pin
assert(cell.getLogicalPinMapping("A6") != null);
}

if (cell.getLogicalPinMapping("A6") != null) {
// A6 pin is being used by LUT/SRL; no need to tie it to VCC
continue;
}
}

char fiveOrSix = belName.charAt(1);
assert(fiveOrSix == '5' || fiveOrSix == '6');
Net staticNet = vccNet;

BEL lut6Bel = (fiveOrSix == '5') ? si.getBEL(belName.charAt(0) + "6LUT") : bel;
Net a6Net = si.getNetFromSiteWire(lut6Bel.getPin("A6").getSiteWireName());

// SRL16Es that have been transformed from SRLC32E require GND on their A6 pin
if (cell.getType().equals("SRL16E") && "SRLC32E".equals(cell.getPropertyValueString("XILINX_LEGACY_PRIM"))) {
staticNet = gndNet;
// Expect sitewire to be VCC and GND
if (!a6Net.isStaticNet()) {
throw new RuntimeException("ERROR: Site pin " + si.getSiteName() + "/" + belName.charAt(0) + "6 is not a static net");
boolean expectGndNet = false;
if ("SRL16E".equals(cell.getType())) {
String pinName = belName.charAt(0) + "1";
SitePinInst spi = si.getSitePinInst(pinName);
if (spi == null) {
vccNet.createPin(pinName, si);
}
} else {
// Tie A6 to staticNet only if sitewire says so
if (a6Net != staticNet) {
continue;

// SRL16Es that have been transformed from SRLC32E require GND on their A6 pin
if ("SRLC32E".equals(cell.getPropertyValueString("XILINX_LEGACY_PRIM"))) {
expectGndNet = true;
staticNet = gndNet;
// Expect sitewire to be VCC or GND
if (!a6Net.isStaticNet()) {
throw new RuntimeException("ERROR: Site pin " + si.getSiteName() + "/" + belName.charAt(0) + "6 is not a static net");
}
}
}

// Tie A6 to staticNet only if sitewire says so
if (a6Net != staticNet && !expectGndNet) {
continue;
}

if (cell.getLogicalPinMapping("O5") != null) {
// LUT output comes out on O5
if (fiveOrSix == '5') {
// It's a 5LUT
if (si.getCell(belName.charAt(0) + "6LUT") != null) {
// But 6LUT exists; let the 6LUT deal with it
continue;
}
} else {
throw new RuntimeException("Assumption that only 5LUTs can use O5 failed here.");
}
assert(fiveOrSix == '5');
} else {
if (fiveOrSix != '6') {
// Assume that O6 is only driven by 6LUT, even though possible for 5LUT, unless
// it's a routethru
assert (cell.isRoutethru());
continue;
}

assert(fiveOrSix == '6');
}

Expand Down Expand Up @@ -3370,14 +3411,16 @@ public static void createCeSrRstPinsToVCC(Design design) {
Net net = si.getNetFromSiteWire(sitePinName);
if (net != null) {
if (belPinName == CE) {
if (!net.isVCCNet()) {
continue;
}
// CE: it is possible for sitewire to be assigned to a non VCC net, but a SitePinInst to not yet exist
assert(!net.isVCCNet());
continue;
} else {
// SR: it is possible for sitewire to be assigned the GND net, yet still be routed to VCC
assert(belPinName == SR);
if (!net.isStaticNet()) {
continue;
}
// SR: it is possible for sitewire to be assigned the GND net, yet still be routed to VCC
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/com/xilinx/rapidwright/device/IntentCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ public boolean isUltraScaleClockDistribution() {
return NODE_GLOBAL_HDISTR == this || NODE_GLOBAL_VDISTR == this;
}

public boolean isVersalClocking() {
return NODE_GLOBAL_HDISTR == this || NODE_GLOBAL_HDISTR_LOCAL == this || NODE_GLOBAL_HROUTE_HSR == this ||
NODE_GLOBAL_VDISTR == this || NODE_GLOBAL_VDISTR_LVL2 == this || NODE_GLOBAL_VROUTE == this ||
NODE_GLOBAL_GCLK == this || NODE_GLOBAL_LEAF == this || NODE_GLOBAL_BUFG == this;
}

private static final int SERIES7_START_IDX = 23;
private static final int SERIES7_END_IDX = SERIES7_START_IDX + 33 - 1;

Expand Down
23 changes: 14 additions & 9 deletions src/com/xilinx/rapidwright/rwroute/GlobalSignalRouting.java
Original file line number Diff line number Diff line change
Expand Up @@ -444,15 +444,6 @@ public static void routeStaticNet(List<SitePinInst> pins,
}

IntentCode uphillIntentCode = uphillNode.getIntentCode();
if (uphillIntentCode == IntentCode.NODE_CLE_CNODE && intentCode != IntentCode.NODE_CLE_CTRL) {
assert(isVersal);
// Only allow PIPs from NODE_CLE_CNODE to NODE_CLE_CTRL intent codes
// (NODE_CLE_NODEs can also be used to re-enter the INT tile --- do not allow this
// so that these precious resources are not consumed by the static router thereby
// blocking the signal router from using them)
continue;
}

switch(uphillIntentCode) {
case NODE_GLOBAL_VDISTR:
case NODE_GLOBAL_HROUTE:
Expand All @@ -469,6 +460,20 @@ public static void routeStaticNet(List<SitePinInst> pins,
case NODE_VLONG7:
case NODE_VLONG12:
continue;
case NODE_CLE_CNODE:
// Only allow PIPs from NODE_{CLE,INTF}_CNODE to NODE_{CLE,INTF}_CTRL intent codes
// (NODE_CLE_NODEs can also be used to re-enter the INT tile --- do not allow this
// so that these precious resources are not consumed by the static router thereby
// blocking the signal router from using them)
if (intentCode != IntentCode.NODE_CLE_CTRL) {
continue;
}
break;
case NODE_INTF_CNODE:
if (intentCode != IntentCode.NODE_INTF_CTRL) {
continue;
}
break;

// VCC net should never need to use S/D/Q nodes ...
case NODE_SINGLE:
Expand Down
52 changes: 26 additions & 26 deletions src/com/xilinx/rapidwright/rwroute/RWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -326,32 +326,6 @@ protected void determineRoutingTargets() {

// Wait for all outstanding RouteNodeGraph.preserveAsync() calls to complete
routingGraph.awaitPreserve();

// On Versal only, reserve all uphills of NODE_(CLE|INTF)_CTRL sinks since
// their [BC]NODEs can also be used to reach NODE_INODEs --- not applying this
// heuristic can lead to avoidable congestion
if (routingGraph.isVersal) {
for (Connection connection : indirectConnections) {
RouteNode sinkRnode = connection.getSinkRnode();
if (sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK_BOTH) {
for (Node uphill : sinkRnode.getAllUphillNodes()) {
if (uphill.isTiedToVcc()) {
continue;
}
Net preservedNet = routingGraph.getPreservedNet(uphill);
if (preservedNet != null && preservedNet != connection.getNet()) {
continue;
}
assert((sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL &&
(uphill.getIntentCode() == IntentCode.NODE_CLE_CNODE || uphill.getIntentCode() == IntentCode.NODE_CLE_BNODE)) ||
(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL &&
(uphill.getIntentCode() == IntentCode.NODE_INTF_CNODE || uphill.getIntentCode() == IntentCode.NODE_INTF_BNODE)));
RouteNode rnode = routingGraph.getOrCreate(uphill, RouteNodeType.LOCAL_RESERVED);
rnode.setType(RouteNodeType.LOCAL_RESERVED);
}
}
}
}
}

private void categorizeNets() {
Expand Down Expand Up @@ -804,6 +778,32 @@ private void initializeRouting() {
oneMinusTimingWeight = 1 - timingWeight;
oneMinusWlWeight = 1 - wlWeight;
printIterationHeader(config.isTimingDriven());

// On Versal only, reserve all uphills of NODE_(CLE|INTF)_CTRL sinks since
// their [BC]NODEs can also be used to reach NODE_INODEs --- not applying this
// heuristic can lead to avoidable congestion
if (routingGraph.isVersal) {
for (Connection connection : indirectConnections) {
RouteNode sinkRnode = connection.getSinkRnode();
if (sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK_BOTH) {
for (Node uphill : sinkRnode.getAllUphillNodes()) {
if (uphill.isTiedToVcc()) {
continue;
}
Net preservedNet = routingGraph.getPreservedNet(uphill);
if (preservedNet != null && preservedNet != connection.getNet()) {
continue;
}
assert((sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL &&
(uphill.getIntentCode() == IntentCode.NODE_CLE_CNODE || uphill.getIntentCode() == IntentCode.NODE_CLE_BNODE)) ||
(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL &&
(uphill.getIntentCode() == IntentCode.NODE_INTF_CNODE || uphill.getIntentCode() == IntentCode.NODE_INTF_BNODE)));
RouteNode rnode = routingGraph.getOrCreate(uphill, RouteNodeType.LOCAL_RESERVED);
rnode.setType(RouteNodeType.LOCAL_RESERVED);
}
}
}
}
}

/**
Expand Down
Loading

0 comments on commit d75c404

Please sign in to comment.