Skip to content

Commit

Permalink
Introduce LOCAL_RESERVED
Browse files Browse the repository at this point in the history
Signed-off-by: Eddie Hung <eddie.hung@amd.com>
  • Loading branch information
eddieh-xlnx committed Nov 13, 2024
1 parent e877503 commit ce90eb7
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 19 deletions.
36 changes: 33 additions & 3 deletions src/com/xilinx/rapidwright/rwroute/RWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,32 @@ 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) {
for (Node uphill : sinkRnode.getAllUphillNodes()) {
if (uphill.isTiedToVcc()) {
continue;
}
Net preservedNet = routingGraph.getPreservedNet(uphill);
if (preservedNet != null && preservedNet != connection.getNetWrapper().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 @@ -1811,15 +1837,19 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) {
continue;
}
switch (childRNode.getType()) {
case LOCAL_RESERVED:
case LOCAL:
case LOCAL_EAST:
case LOCAL_WEST:
if (!routingGraph.isAccessible(childRNode, connection)) {
continue;
}
// Verify invariant that east/west wires stay east/west
assert(rnode.getType() != RouteNodeType.LOCAL_EAST || childRNode.getType() == RouteNodeType.LOCAL_EAST);
assert(rnode.getType() != RouteNodeType.LOCAL_WEST || childRNode.getType() == RouteNodeType.LOCAL_WEST);
// Verify invariant that east/west wires stay east/west ...
assert(rnode.getType() != RouteNodeType.LOCAL_EAST || childRNode.getType() == RouteNodeType.LOCAL_EAST ||
// ... unless it's an exclusive sink using a LOCAL_RESERVED node
(childRNode.getType() == RouteNodeType.LOCAL_RESERVED && connection.getSinkRnode().getType() == RouteNodeType.EXCLUSIVE_SINK));
assert(rnode.getType() != RouteNodeType.LOCAL_WEST || childRNode.getType() == RouteNodeType.LOCAL_WEST ||
(childRNode.getType() == RouteNodeType.LOCAL_RESERVED && connection.getSinkRnode().getType() == RouteNodeType.EXCLUSIVE_SINK));
break;
case NON_LOCAL:
// LOCALs cannot connect to NON_LOCALs except via a LUT routethru
Expand Down
1 change: 1 addition & 0 deletions src/com/xilinx/rapidwright/rwroute/RouteNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ private void setBaseCost(Series series) {
break;
case LOCAL_EAST:
case LOCAL_WEST:
case LOCAL_RESERVED:
assert(length == 0 ||
(length == 1 && (
((series == Series.UltraScalePlus || series == Series.UltraScale) && getIntentCode() == IntentCode.NODE_PINBOUNCE) ||
Expand Down
30 changes: 16 additions & 14 deletions src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,8 @@ public int averageChildren() {
public boolean isAccessible(RouteNode childRnode, Connection connection) {
// Only consider LOCAL nodes when:
// (a) considering LUT routethrus
if (!childRnode.getType().isLocal() || lutRoutethru) {
RouteNodeType type = childRnode.getType();
if (!type.isLocal() || lutRoutethru) {
return true;
}

Expand All @@ -694,17 +695,16 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) {
}

// (c) on the same side as the sink
RouteNodeType type = childRnode.getType();
Tile sinkTile = sinkRnode.getTile();
switch (sinkRnode.getType()) {
case EXCLUSIVE_SINK_EAST:
if (type == RouteNodeType.LOCAL_WEST) {
if (type == RouteNodeType.LOCAL_WEST || type == RouteNodeType.LOCAL_RESERVED) {
// West wires can never reach an east sink
return false;
}
break;
case EXCLUSIVE_SINK_WEST:
if (type == RouteNodeType.LOCAL_EAST) {
if (type == RouteNodeType.LOCAL_EAST || type == RouteNodeType.LOCAL_RESERVED) {
// East wires can never reach a west sink
return false;
}
Expand All @@ -715,9 +715,12 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) {
return false;
}
if (isVersal) {
// NODE_(CLE|INTF)_CTRL can be reached by NODE_(CLE|INTF)_[BC]NODE which have type LOCAL_(EAST|WEST)
assert((sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL && type != RouteNodeType.LOCAL) ||
(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL && type != RouteNodeType.LOCAL));
assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL || sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL);

// NODE_(CLE|INTF)_CTRL can only be reached by LOCAL_RESERVED nodes
if (type != RouteNodeType.LOCAL_RESERVED) {
return false;
}
} else {
assert(design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus);
assert(sinkRnode.getWireName().startsWith("CTRL_"));
Expand Down Expand Up @@ -749,14 +752,13 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) {
IntentCode sinkIntentCode = sinkRnode.getIntentCode();
assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE);

// Experimentally found that considering the following led to runtime increases
// // Only allow CNODEs that reach into the sink tile
// return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() &&
// childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate();
// Only allow CNODEs that reach into the sink tile
return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() &&
childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate();

// Do not allow CNODEs when not targeting a CTRL sink
// Note: NODE_{CLE,INTF}_CNODE (x24) -> NODE_INODE arcs (128/328 PIPs, 128/154 nodes) will be ignored
return false;
// // Do not allow CNODEs when not targeting a CTRL sink
// // Note: NODE_{CLE,INTF}_CNODE (x24) -> NODE_INODE arcs (128/328 PIPs, 128/154 nodes) will be ignored
// return false;
}
case NODE_CLE_BNODE:
case NODE_INTF_BNODE: {
Expand Down
6 changes: 4 additions & 2 deletions src/com/xilinx/rapidwright/rwroute/RouteNodeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ public enum RouteNodeType {

LOCAL,
LOCAL_EAST,
LOCAL_WEST;
LOCAL_WEST,

LOCAL_RESERVED;

public boolean isExclusiveSink() {
return this == EXCLUSIVE_SINK || this == EXCLUSIVE_SINK_EAST || this == EXCLUSIVE_SINK_WEST;
}

public boolean isLocal() {
return this == LOCAL || this == LOCAL_EAST || this == LOCAL_WEST;
return this == LOCAL || this == LOCAL_EAST || this == LOCAL_WEST || this == LOCAL_RESERVED;
}
}

0 comments on commit ce90eb7

Please sign in to comment.