Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various preprocessing fixes for Versal routing #1115

Merged
merged 16 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 90 additions & 47 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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI - In 2024.2 there will be a convenient API to replace this.

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());
assert(cell.isRoutethru());
eddieh-xlnx marked this conversation as resolved.
Show resolved Hide resolved
eddieh-xlnx marked this conversation as resolved.
Show resolved Hide resolved
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
28 changes: 27 additions & 1 deletion src/com/xilinx/rapidwright/rwroute/CUFR.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,28 @@ protected void routeIndirectConnections(Collection<Connection> connections) {
}

/**
* Routes a {@link Design} instance.
* Routes a design in the full timing-driven routing mode using CUFR.
* @param design The {@link Design} instance to be routed.
*/
public static Design routeDesignFullTimingDriven(Design design) {
return routeDesignWithUserDefinedArguments(design, new String[] {
"--hus"
});
}

/**
* Routes a design in the full non-timing-driven routing mode using CUFR.
* @param design The {@link Design} instance to be routed.
*/
public static Design routeDesignFullNonTimingDriven(Design design) {
return routeDesignWithUserDefinedArguments(design, new String[] {
"--hus",
"--nonTimingDriven"
});
}

/**
* Routes a {@link Design} instance using CUFR.
* @param design The {@link Design} instance to be routed.
* @param args An array of string arguments, can be null.
* If null, the design will be routed in the full timing-driven routing mode with default a {@link RWRouteConfig} instance.
Expand All @@ -174,6 +195,11 @@ public static Design routeDesignWithUserDefinedArguments(Design design, String[]
// Instantiates a RWRouteConfig Object and parses the arguments.
// Uses the default configuration if basic usage only.
RWRouteConfig config = new RWRouteConfig(args);

if (!config.isHus()) {
System.err.println("WARNING: Hybrid Updating Strategy (HUS) is not enabled.");
}

return routeDesign(design, new CUFR(design, config));
}

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
51 changes: 51 additions & 0 deletions src/com/xilinx/rapidwright/rwroute/PartialCUFR.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,53 @@ protected void printRoutingStatistics() {
super.printRoutingStatistics();
}

/**
* Routes a design in the partial non-timing-driven routing mode.
* @param design The {@link Design} instance to be routed.
* @param pinsToRoute Collection of {@link SitePinInst}-s to be routed. If null, route all unrouted pins in the design.
*/
public static Design routeDesignPartialNonTimingDriven(Design design, Collection<SitePinInst> pinsToRoute) {
boolean softPreserve = false;
return routeDesignPartialNonTimingDriven(design, pinsToRoute, softPreserve);
}

/**
* Routes a design in the partial non-timing-driven routing mode using CUFR.
* @param design The {@link Design} instance to be routed.
* @param pinsToRoute Collection of {@link SitePinInst}-s to be routed. If null, route all unrouted pins in the design.
* @param softPreserve Allow routed nets to be unrouted and subsequently rerouted in order to improve routability.
*/
public static Design routeDesignPartialNonTimingDriven(Design design, Collection<SitePinInst> pinsToRoute, boolean softPreserve) {
return routeDesignWithUserDefinedArguments(design, new String[] {
"--hus",
"--fixBoundingBox",
// use U-turn nodes and no masking of nodes cross RCLK
// Pros: maximum routability
// Con: might result in delay optimism and a slight increase in runtime
"--useUTurnNodes",
"--nonTimingDriven",
"--verbose"},
pinsToRoute, softPreserve);
}

/**
* Routes a design in the partial timing-driven routing mode using CUFR.
* @param design The {@link Design} instance to be routed.
* @param pinsToRoute Collection of {@link SitePinInst}-s to be routed. If null, route all unrouted pins in the design.
* @param softPreserve Allow routed nets to be unrouted and subsequently rerouted in order to improve routability.
*/
public static Design routeDesignPartialTimingDriven(Design design, Collection<SitePinInst> pinsToRoute, boolean softPreserve) {
return routeDesignWithUserDefinedArguments(design, new String[] {
"--hus",
"--fixBoundingBox",
// use U-turn nodes and no masking of nodes cross RCLK
// Pros: maximum routability
// Con: might result in delay optimism and a slight increase in runtime
"--useUTurnNodes",
"--verbose"},
pinsToRoute, softPreserve);
}

/**
* Partially routes a {@link Design} instance; specifically, all nets with no routing PIPs already present.
* @param design The {@link Design} instance to be routed.
Expand Down Expand Up @@ -194,6 +241,10 @@ public static Design routeDesignWithUserDefinedArguments(Design design,
System.out.println("WARNING: Masking nodes across RCLK for partial routing could result in routability problems.");
}

if (!config.isHus()) {
System.err.println("WARNING: Hybrid Updating Strategy (HUS) is not enabled.");
}

return routeDesign(design, new PartialCUFR(design, config, pinsToRoute, softPreserve));
}

Expand Down
Loading
Loading