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

[PartialRouter] Disable ripup in global/static routing #1067

Merged
merged 3 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading