Skip to content

Commit

Permalink
[PartialRouter] Disable ripup in global/static routing (#1067)
Browse files Browse the repository at this point in the history
* [PartialRouter] Disable ripup in global/static routing

Signed-off-by: Eddie Hung <[email protected]>

* Move static net preserving into RouteNodeGraph

Signed-off-by: Eddie Hung <[email protected]>

* Update src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java

Signed-off-by: eddieh-xlnx <[email protected]>

---------

Signed-off-by: Eddie Hung <[email protected]>
Signed-off-by: eddieh-xlnx <[email protected]>
  • Loading branch information
eddieh-xlnx authored Sep 20, 2024
1 parent ef2a82d commit 04e7c3c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 162 deletions.
141 changes: 1 addition & 140 deletions src/com/xilinx/rapidwright/rwroute/PartialRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,9 @@
import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.DesignTools;
import com.xilinx.rapidwright.design.Net;
import com.xilinx.rapidwright.design.SiteInst;
import com.xilinx.rapidwright.design.SitePinInst;
import com.xilinx.rapidwright.device.IntentCode;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.PIP;
import com.xilinx.rapidwright.device.SitePin;
import com.xilinx.rapidwright.device.Tile;
import com.xilinx.rapidwright.router.UltraScaleClockRouting;
import com.xilinx.rapidwright.tests.CodePerfTracker;
Expand Down Expand Up @@ -217,51 +214,6 @@ protected int getNumConnectionsCrossingSLRs() {
return numCrossingSLRs;
}

@Override
protected NodeStatus getGlobalRoutingNodeStatus(Net net, Node node) {
Net preservedNet = routingGraph.getPreservedNet(node);
if (preservedNet == net) {
return NodeStatus.INUSE;
}
if (preservedNet != null) {
if (!softPreserve) {
return NodeStatus.UNAVAILABLE;
}

// Do not steal from other global nets, since we can't tell if they
// can be re-routed
if (preservedNet.isClockNet() || preservedNet.isStaticNet()) {
return NodeStatus.UNAVAILABLE;
}

// Do not steal PINBOUNCEs from preserved nets that serve as
// a used site pin
if (node.getIntentCode() == IntentCode.NODE_PINBOUNCE) {
SitePin sitePin = node.getSitePin();
SiteInst si = (sitePin != null) ? design.getSiteInstFromSite(sitePin.getSite()) : null;
Net netOnSiteWire = (si != null) ? si.getNetFromSiteWire(sitePin.getPinName()) : null;
if (netOnSiteWire != null) {
assert(netOnSiteWire == preservedNet);
return NodeStatus.UNAVAILABLE;
}
}
}

RouteNode rnode = routingGraph.getNode(node);
if (rnode != null) {
if (!softPreserve) {
return NodeStatus.UNAVAILABLE;
}

if (rnode.getType() == RouteNodeType.PINFEED_I) {
// Node must be a sink pin for a non-global net
return NodeStatus.UNAVAILABLE;
}
}

return NodeStatus.AVAILABLE;
}

@Override
protected void routeGlobalClkNets() {
if (clkNets.isEmpty())
Expand All @@ -277,102 +229,11 @@ protected void routeGlobalClkNets() {
super.routeGlobalClkNet(clk);
} else {
System.out.println("INFO: Routing " + clkPins.size() + " pins of clock " + clk + " (non timing-driven)");
Function<Node, NodeStatus> gns = (node) -> this.getGlobalRoutingNodeStatus(clk, node);
Function<Node, NodeStatus> gns = (node) -> getGlobalRoutingNodeStatus(clk, node);
UltraScaleClockRouting.incrementalClockRouter(clk, clkPins, gns);
preserveNet(clk, false);
}
}

List<Net> unpreserveNets = unpreserveCongestedNets(clkNets);
if (!unpreserveNets.isEmpty()) {
System.out.println("INFO: Unpreserving " + unpreserveNets.size() + " nets due to clock congestion");
for (Net net : unpreserveNets) {
System.out.println("\t" + net);
}
}
}

@Override
protected void routeStaticNets() {
if (staticNetAndRoutingTargets.isEmpty())
return;

super.routeStaticNets();

List<Net> unpreserveNets = unpreserveCongestedNets(staticNetAndRoutingTargets.keySet());
if (!unpreserveNets.isEmpty()) {
System.out.println("INFO: Unpreserving " + unpreserveNets.size() + " nets due to static net congestion");
for (Net net : unpreserveNets) {
System.out.println("\t" + net);
}
}
}

private List<Net> unpreserveCongestedNets(Collection<Net> globalNets) {
if (!softPreserve) {
return Collections.emptyList();
}

// Even though route{GlobalClk,Static}Nets() has called preserveNet() for all its nets,
// it will not overwrite those nodes which have already been preserved by other nets.
// Discover such occurrences so that the entire 'victim' net can be correctly
// unpreserved (thus re-routed) and re-preserve the global.
List<Net> unpreserveNets = new ArrayList<>();
for (Net net : globalNets) {
for (PIP pip : net.getPIPs()) {
for (Node node : Arrays.asList(pip.getStartNode(), pip.getEndNode())) {
RouteNode rnode;
Net preservedNet = routingGraph.getPreservedNet(node);
if (preservedNet == net) {
rnode = routingGraph.getNode(node);
if (rnode == null) {
continue;
}

// This could be a leftover node from a previously unpreserved net
// (with its prev pointer set to allow its routing to be recovered)
// Fall through so that this can be cleared and blocked
} else {
if (preservedNet == null) {
// Assume this node has already been unpreserved
} else if (RouterHelper.isRoutableNetWithSourceSinks(preservedNet)) {
unpreserveNet(preservedNet);
unpreserveNets.add(preservedNet);
}

// Preserve node for global net
Net oldNet = routingGraph.preserve(node, net);
if (oldNet != null) {
// oldNet/preservedNet is not a routable net (e.g. driven by hier port)
assert(oldNet == preservedNet);
assert(!RouterHelper.isRoutableNetWithSourceSinks(preservedNet));
}

rnode = routingGraph.getNode(node);
if (rnode == null) {
assert(oldNet != null);
continue;
}

assert(rnode.getPrev() != null);
}

// RouteNode must only exist if its net has been unpreserved
// Clear its prev pointer so that it doesn't get misinterpreted
// by RouteNodeGraphPartial.isPartOfExistingRoute as being part of an existing route
rnode.clearPrev();

// Ideally, we would want to blow this RouteNode from existence as if it was preserved
// from the beginning. However, since other objects (e.g. Connection-s) may hold a reference
// to this, that would not be wise.
// Instead, increment the use of this RouteNode with a null net (since global nets have
// no corresponding NetWrapper) in order to indicate to Connection.isCongested() that it needs
// to be rerouted.
rnode.incrementUser(null);
}
}
}
return unpreserveNets;
}

@Override
Expand Down
22 changes: 0 additions & 22 deletions src/com/xilinx/rapidwright/rwroute/RWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -516,28 +516,6 @@ protected void routeStaticNets() {
GlobalSignalRouting.routeStaticNet(staticNet, gns, design, routethruHelper);

preserveNet(staticNet, false);

// When a [A-H]MUX pin is used as a static source, also preserve the [A-H]_O pin
// so that it can't be used by other static nets, nor as a LUT routethru
for (SitePinInst spi : staticNet.getPins()) {
if (!spi.isOutPin()) {
continue;
}

SiteInst si = spi.getSiteInst();
if (!Utils.isSLICE(si)) {
continue;
}

String pinName = spi.getName();
if (pinName.endsWith("MUX")) {
char lutLetter = pinName.charAt(0);
Node oNode = si.getSite().getConnectedNode(lutLetter + "_O");
routingGraph.preserve(oNode, staticNet);
} else {
assert(pinName.endsWith("_O"));
}
}
}
}

Expand Down
25 changes: 25 additions & 0 deletions src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.Net;
import com.xilinx.rapidwright.design.SiteInst;
import com.xilinx.rapidwright.design.SitePinInst;
import com.xilinx.rapidwright.device.Device;
import com.xilinx.rapidwright.device.IntentCode;
Expand Down Expand Up @@ -308,8 +309,32 @@ private Net preserve(Tile tile, int wireIndex, Net net) {
}

public void preserve(Net net, List<SitePinInst> pins) {
boolean isStaticNet = net.isStaticNet();
for (SitePinInst pin : pins) {
preserve(pin.getConnectedNode(), net);

if (isStaticNet && pin.isOutPin()) {
// When a LUT output is used as a static source, also preserve the other pin
// ([A-H]_O <-> [A-H]MUX) so that it can't be used by any other nets
SiteInst si = pin.getSiteInst();
if (!Utils.isSLICE(si)) {
continue;
}

String pinName = pin.getName();
char lutLetter = pinName.charAt(0);
String otherPinName;
if (pinName.endsWith("MUX")) {
otherPinName = lutLetter + "_O";
} else if (pinName.endsWith("_O")) {
otherPinName = lutLetter + "MUX";
} else {
throw new RuntimeException("ERROR: Unsupported site pin " + pin);
}

Node otherNode = si.getSite().getConnectedNode(otherPinName);
preserve(otherNode, net);
}
}

for (PIP pip : net.getPIPs()) {
Expand Down

0 comments on commit 04e7c3c

Please sign in to comment.