From f89c96e2f89d73acd62aea43ddd57ca626e3dab7 Mon Sep 17 00:00:00 2001 From: Wenhao Lin Date: Sun, 3 Nov 2024 23:30:42 -0700 Subject: [PATCH 01/64] Add optimization of signal routing Signed-off-by: Wenhao Lin --- .../xilinx/rapidwright/rwroute/RWRoute.java | 3 ++ .../rapidwright/rwroute/RouteNodeGraph.java | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index d44b7edd4..2f2a72b89 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1802,6 +1802,9 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { if (!routingGraph.isAccessible(childRNode, connection)) { continue; } + if (!routingGraph.isAccessibleINODEAndCNODEOnVersal(rnode, childRNode, connection)) { + continue; + } if (!config.isUseUTurnNodes() && childRNode.getDelay() > 10000) { // To filter out those nodes that are considered to be excluded with the masking resource approach, // such as U-turn shape nodes near the boundary diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index e68ad6d8c..f5630a662 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -594,6 +594,59 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; } + public boolean isAccessibleINODEAndCNODEOnVersal(RouteNode rnode, RouteNode childRnode, Connection connection){ + // Below situations should not be skipped + if (design.getSeries() != Series.Versal) { + return true; + } + + RouteNode sinkRnode = connection.getSinkRnode(); + Tile sinkTile = sinkRnode.getTile(); + IntentCode childIntentCode = childRnode.getIntentCode(); + switch (childIntentCode) { + case NODE_INODE: + // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); + break; + case NODE_CLE_CNODE: + // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL); + break; + case NODE_INTF_CNODE: + // Block access to all CNODEs outside the sink tile, since NODE_INTF_CNODE -> NODE_INTF_CTRL + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); + break; + default: + break; + } + + // TODO: Do we want to block NODE_PINBOUNCE if not in the sink INT tile? + // We have already blocked them in RWRoute.isAccessiblePinbounce. + + // TODO: Do we want to block all exploration of TileTypeEnum.CLE_BC_CORE and TileTypeEnum.INTF_[LR]OCF_[TB][LR]_TILE + // unless our sink is in that tile? (or is this already done by NODE_{CLE,INTF}_CNODE blocking above) + // No, we also need to take those neighbor CLE_BC_CORE tiles of the source tile. + // Furthermore, even if we don't take them into consideration, this is done by blocking CNODEs and BNODEs. + + // TODO: Is there any value in blocking NODE_{CLE,INTF}_BNODEs? + // We have already done this. Here is an invariant that NODE_{CLE, INTF}_BNODE -> {NODE_INODE, NODE_CLE_CTRL}, + // where NODE_CLE_CTRL must be a node that connects to the sink control pin. + // Since the sink rnode must not be the target, we only have INODEs here. However, those INODEs not located in the sink tile have been blocked. + + // TODO: What's special about nodes with wirename INT/OUT_[NESW]NODE_[EW]_*? + // Nothing special is found yet. + return true; + } + protected boolean allowRoutethru(Node head, Node tail) { if (!Utils.isCLB(tail.getTile().getTileTypeEnum())) { return false; From 57f39dfedf45744126eee4012f31161f287d5556 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 09:49:10 -0800 Subject: [PATCH 02/64] Merge new method into RoutingGraph.isAccessible() Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 3 - .../rapidwright/rwroute/RouteNodeGraph.java | 114 +++++++++--------- 2 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 2f2a72b89..d44b7edd4 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1802,9 +1802,6 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { if (!routingGraph.isAccessible(childRNode, connection)) { continue; } - if (!routingGraph.isAccessibleINODEAndCNODEOnVersal(rnode, childRNode, connection)) { - continue; - } if (!config.isUseUTurnNodes() && childRNode.getDelay() > 10000) { // To filter out those nodes that are considered to be excluded with the masking resource approach, // such as U-turn shape nodes near the boundary diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index f5630a662..66deec30b 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -37,7 +37,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.design.Net; @@ -109,10 +108,12 @@ public class RouteNodeGraph { /** Map indicating the wire indices corresponding to the [A-H]MUX output */ protected final Map muxWires; - /** Flag for whether LUT routethrus are to be considered - */ + /** Flag for whether LUT routethrus are to be considered */ protected final boolean lutRoutethru; + /** Flag for whether design targets the Versal series */ + protected final boolean isVersal; + public RouteNodeGraph(Design design, RWRouteConfig config) { this(design, config, new HashMap<>()); } @@ -286,6 +287,8 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map pins) { String pinName = pin.getName(); char lutLetter = pinName.charAt(0); String otherPinName = null; - String otherPinNameSuffix = design.getSeries() == Series.Versal ? "Q" : "MUX"; + String otherPinNameSuffix = isVersal ? "Q" : "MUX"; if (pinName.endsWith(otherPinNameSuffix)) { otherPinName = lutLetter + "_O"; } else if (pinName.endsWith("_O")) { @@ -573,6 +576,56 @@ public int averageChildren() { } public boolean isAccessible(RouteNode childRnode, Connection connection) { + if (isVersal) { + RouteNode sinkRnode = connection.getSinkRnode(); + Tile sinkTile = sinkRnode.getTile(); + IntentCode childIntentCode = childRnode.getIntentCode(); + switch (childIntentCode) { + case NODE_INODE: + // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); + break; + case NODE_CLE_CNODE: + // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL); + break; + case NODE_INTF_CNODE: + // Block access to all CNODEs outside the sink tile, since NODE_INTF_CNODE -> NODE_INTF_CTRL + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); + break; + default: + break; + } + + // TODO: Do we want to block NODE_PINBOUNCE if not in the sink INT tile? + // We have already blocked them in RWRoute.isAccessiblePinbounce. + + // TODO: Do we want to block all exploration of TileTypeEnum.CLE_BC_CORE and TileTypeEnum.INTF_[LR]OCF_[TB][LR]_TILE + // unless our sink is in that tile? (or is this already done by NODE_{CLE,INTF}_CNODE blocking above) + // No, we also need to take those neighbor CLE_BC_CORE tiles of the source tile. + // Furthermore, even if we don't take them into consideration, this is done by blocking CNODEs and BNODEs. + + // TODO: Is there any value in blocking NODE_{CLE,INTF}_BNODEs? + // We have already done this. Here is an invariant that NODE_{CLE, INTF}_BNODE -> {NODE_INODE, NODE_CLE_CTRL}, + // where NODE_CLE_CTRL must be a node that connects to the sink control pin. + // Since the sink rnode must not be the target, we only have INODEs here. However, those INODEs not located in the sink tile have been blocked. + + // TODO: What's special about nodes with wirename INT/OUT_[NESW]NODE_[EW]_*? + // Nothing special is found yet. + return true; + } + + assert(design.getDevice().getSeries() == Series.UltraScale || design.getDevice().getSeries() == Series.UltraScalePlus); + Tile childTile = childRnode.getTile(); TileTypeEnum childTileType = childTile.getTileTypeEnum(); BitSet bs = accessibleWireOnlyIfAboveBelowTarget.get(childTileType); @@ -594,59 +647,6 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; } - public boolean isAccessibleINODEAndCNODEOnVersal(RouteNode rnode, RouteNode childRnode, Connection connection){ - // Below situations should not be skipped - if (design.getSeries() != Series.Versal) { - return true; - } - - RouteNode sinkRnode = connection.getSinkRnode(); - Tile sinkTile = sinkRnode.getTile(); - IntentCode childIntentCode = childRnode.getIntentCode(); - switch (childIntentCode) { - case NODE_INODE: - // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) - if (childRnode.getTile() != sinkTile) { - return false; - } - assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); - break; - case NODE_CLE_CNODE: - // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL - if (childRnode.getTile() != sinkTile) { - return false; - } - assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL); - break; - case NODE_INTF_CNODE: - // Block access to all CNODEs outside the sink tile, since NODE_INTF_CNODE -> NODE_INTF_CTRL - if (childRnode.getTile() != sinkTile) { - return false; - } - assert(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); - break; - default: - break; - } - - // TODO: Do we want to block NODE_PINBOUNCE if not in the sink INT tile? - // We have already blocked them in RWRoute.isAccessiblePinbounce. - - // TODO: Do we want to block all exploration of TileTypeEnum.CLE_BC_CORE and TileTypeEnum.INTF_[LR]OCF_[TB][LR]_TILE - // unless our sink is in that tile? (or is this already done by NODE_{CLE,INTF}_CNODE blocking above) - // No, we also need to take those neighbor CLE_BC_CORE tiles of the source tile. - // Furthermore, even if we don't take them into consideration, this is done by blocking CNODEs and BNODEs. - - // TODO: Is there any value in blocking NODE_{CLE,INTF}_BNODEs? - // We have already done this. Here is an invariant that NODE_{CLE, INTF}_BNODE -> {NODE_INODE, NODE_CLE_CTRL}, - // where NODE_CLE_CTRL must be a node that connects to the sink control pin. - // Since the sink rnode must not be the target, we only have INODEs here. However, those INODEs not located in the sink tile have been blocked. - - // TODO: What's special about nodes with wirename INT/OUT_[NESW]NODE_[EW]_*? - // Nothing special is found yet. - return true; - } - protected boolean allowRoutethru(Node head, Node tail) { if (!Utils.isCLB(tail.getTile().getTileTypeEnum())) { return false; From 74df32407f4711fca20b742abaaf3d7352cb4f6d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 10:22:51 -0800 Subject: [PATCH 03/64] Fix typo Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 66deec30b..056eedaa4 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -582,7 +582,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { IntentCode childIntentCode = childRnode.getIntentCode(); switch (childIntentCode) { case NODE_INODE: - // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) + // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE -> NODE_PINBOUNCE) if (childRnode.getTile() != sinkTile) { return false; } From 3bf9cb9cd58cd8b9ad63c2f17d8eb48806c57629 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 10:23:02 -0800 Subject: [PATCH 04/64] Add TestNode.testNodeReachabilityVersal() to check assumptions Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 2b24b6544..bcfb0ba22 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -145,6 +145,7 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str if (!Utils.isInterConnect(downhill.getTile().getTileTypeEnum())) { continue; } + // Check that they are all in the same column Assertions.assertEquals(baseTile.getTileXCoordinate(), downhill.getTile().getTileXCoordinate()); queue.add(downhill); @@ -153,6 +154,68 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str System.out.println("visited.size() = " + visited.size()); } + @ParameterizedTest + @CsvSource({ + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE", + "xcvp1002,INT_X38Y220,NODE_INODE", + "xcvp1002,INT_X38Y220,NODE_IMUX", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_BNODE", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CNODE", + }) + public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName) { + Device device = Device.getDevice(partName); + Tile baseTile = device.getTile(tileName); + Queue queue = new ArrayDeque<>(); + IntentCode ic = IntentCode.valueOf(intentCodeName); + for (int wireIdx = 0; wireIdx < baseTile.getWireCount(); wireIdx++) { + if (baseTile.getWireIntentCode(wireIdx) != ic) { + continue; + } + queue.add(Node.getNode(baseTile, wireIdx)); + } + System.out.println("Initial queue.size() = " + queue.size()); + System.out.println("Initial queue = " + queue); + + // Print out the intent code of nodes that are immediately uphill of this intent code + System.out.println("Immediately uphill:"); + queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream).map(Node::getIntentCode) + .distinct() + .sorted() + .forEachOrdered(s -> System.out.println("\t" + s)); + + // Print out the intent code of nodes that are immediately downhill of this intent code + System.out.println("Immediately downhill:"); + queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream).map(Node::getIntentCode) + .distinct() + .sorted() + .forEachOrdered(s -> System.out.println("\t" + s)); + + Set visited = new HashSet<>(); + while (!queue.isEmpty()) { + Node node = queue.poll(); + for (Node downhill : node.getAllDownhillNodes()) { + if (!visited.add(downhill)) { + continue; + } + if (!Utils.isInterConnect(downhill.getTile().getTileTypeEnum())) { + continue; + } + // All INT-to-INT connections should be to the same tile + if (baseTile.getTileTypeEnum() == TileTypeEnum.CLE_BC_CORE) { + // Except CLE_BC_CORE tiles which spans two adjacent INT tiles + if (baseTile != downhill.getTile()) { + Assertions.assertTrue(1 >= Math.abs(baseTile.getTileXCoordinate() - downhill.getTile().getTileXCoordinate())); + Assertions.assertEquals(TileTypeEnum.INT, downhill.getTile().getTileTypeEnum()); + } + } else { + Assertions.assertEquals(baseTile, downhill.getTile()); + } + queue.add(downhill); + } + } + System.out.println("visited.size() = " + visited.size()); + } + @ParameterizedTest @CsvSource({ // https://github.com/Xilinx/RapidWright/issues/983 From bf4d0763f45cfdeb0200db607b312a1fa8d96674 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 10:47:05 -0800 Subject: [PATCH 05/64] Add NODE_CLE_OUTPUT too Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index bcfb0ba22..952b83c35 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -24,6 +24,7 @@ import java.util.ArrayDeque; import java.util.Collection; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Queue; @@ -161,6 +162,8 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str "xcvp1002,INT_X38Y220,NODE_IMUX", "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_BNODE", "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CNODE", + "xcvp1002,CLE_E_CORE_X38Y220,NODE_CLE_OUTPUT", + "xcvp1002,CLE_W_CORE_X38Y220,NODE_CLE_OUTPUT", }) public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName) { Device device = Device.getDevice(partName); @@ -190,6 +193,7 @@ public void testNodeReachabilityVersal(String partName, String tileName, String .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); + TileTypeEnum baseTileTypeEnum = baseTile.getTileTypeEnum(); Set visited = new HashSet<>(); while (!queue.isEmpty()) { Node node = queue.poll(); @@ -200,8 +204,24 @@ public void testNodeReachabilityVersal(String partName, String tileName, String if (!Utils.isInterConnect(downhill.getTile().getTileTypeEnum())) { continue; } + if (Utils.isCLB(baseTileTypeEnum)) { + if (EnumSet.of(IntentCode.NODE_VLONG7, IntentCode.NODE_VLONG12, IntentCode.NODE_HLONG10, IntentCode.NODE_HLONG6).contains(downhill.getIntentCode())) { + // Ignore long wires that obviously leave the tile + } else { + // All other wires should have the same X coordinate, if not the same Y + Assertions.assertEquals(baseTile.getTileXCoordinate(), downhill.getTile().getTileXCoordinate()); + if (baseTile.getTileYCoordinate() != downhill.getTile().getTileYCoordinate()) { + // Only exception for Y are specific NODE_SDQNODEs with the following wire name + Assertions.assertTrue(downhill.getWireName().matches("OUT_[NEWS]NODE_[EW]_\\d+")); + Assertions.assertEquals(IntentCode.NODE_SDQNODE, downhill.getIntentCode()); + Assertions.assertTrue(1 >= Math.abs(baseTile.getTileYCoordinate() - downhill.getTile().getTileYCoordinate())); + } + } + // Do not descend further + continue; + } // All INT-to-INT connections should be to the same tile - if (baseTile.getTileTypeEnum() == TileTypeEnum.CLE_BC_CORE) { + if (baseTileTypeEnum == TileTypeEnum.CLE_BC_CORE) { // Except CLE_BC_CORE tiles which spans two adjacent INT tiles if (baseTile != downhill.getTile()) { Assertions.assertTrue(1 >= Math.abs(baseTile.getTileXCoordinate() - downhill.getTile().getTileXCoordinate())); From 1f8a9d3105846529bb70f01c163e28298981d9fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 15:06:49 -0800 Subject: [PATCH 06/64] Expand TestNode.testNodeReachabilityUltraScale() Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 2b24b6544..301e39e90 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -24,6 +24,7 @@ import java.util.ArrayDeque; import java.util.Collection; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Queue; @@ -83,45 +84,61 @@ public void testUphillNodeIsInvalid() { @ParameterizedTest @CsvSource({ // UltraScale+ part - "xcvu3p,INT_X37Y220,BOUNCE_", - "xcvu3p,INT_X37Y220,BYPASS_", - "xcvu3p,INT_X37Y220,INT_NODE_GLOBAL_", - "xcvu3p,INT_X37Y220,INT_NODE_IMUX_", - "xcvu3p,INT_X37Y220,INODE_", - // These nodes fanout to NESW nodes in the tile above or below - // "xcvu3p,INT_X37Y220,SDQNODE_", + "xcvu3p,INT_X37Y220,BOUNCE_.*", + "xcvu3p,INT_X37Y220,BYPASS_.*", + "xcvu3p,INT_X37Y220,INT_NODE_GLOBAL_.*", + "xcvu3p,INT_X37Y220,INT_NODE_IMUX_.*", + "xcvu3p,INT_X37Y220,INODE_.*", + "xcvu3p,INT_X37Y220,INT_INT_SDQ_.*", // IntentCode.NODE_SINGLE + "xcvu3p,INT_X37Y220,INT_NODE_SDQ_.*", + "xcvu3p,INT_X37Y220,SDQNODE_.*", + "xcvu3p,INT_X37Y220,IMUX_.*", + "xcvu3p,INT_X37Y220,CTRL_.*", + "xcvu3p,CLEM_X37Y220,CLE_CLE_M_SITE_0_[A-H](_O|Q|Q2|MUX)", // UltraScale part - "xcvu065,INT_X38Y220,BOUNCE_", - "xcvu065,INT_X38Y220,BYPASS_", - "xcvu065,INT_X38Y220,INT_NODE_GLOBAL_", - "xcvu065,INT_X38Y220,INT_NODE_IMUX_", - "xcvu065,INT_X38Y220,INODE_", - // "xcvu065,INT_X38Y220,QLND", - // "xcvu065,INT_X38Y220,SDND", + "xcvu065,INT_X38Y220,BOUNCE_.*", + "xcvu065,INT_X38Y220,BYPASS_.*", + "xcvu065,INT_X38Y220,INT_NODE_GLOBAL_.*", + "xcvu065,INT_X38Y220,INT_NODE_IMUX_.*", + "xcvu065,INT_X38Y220,INODE_.*", + "xcvu065,INT_X38Y220,INT_INT_SINGLE_.*", // IntentCode.NODE_SINGLE + "xcvu065,INT_X38Y220,INT_NODE_SINGLE_DOUBLE_.*", + "xcvu065,INT_X38Y220,INT_NODE_QUAD_LONG_.*", + "xcvu065,INT_X38Y220,IMUX_.*", + "xcvu065,INT_X38Y220,CTRL_.*", + "xcvu065,INT_X38Y220,QLND.*", + "xcvu065,INT_X38Y220,SDND.*", + "xcvu065,CLE_M_X38Y220,CLE_CLE_M_SITE_0_[A-H](_O|Q|Q2|MUX)", }) - public void testNodeReachabilityUltraScale(String partName, String tileName, String wirePrefix) { + public void testNodeReachabilityUltraScale(String partName, String tileName, String wireRegex) { Device device = Device.getDevice(partName); Tile baseTile = device.getTile(tileName); Queue queue = new ArrayDeque<>(); + Set intentCodes = EnumSet.noneOf(IntentCode.class); for (String wireName : baseTile.getWireNames()) { - if (!wireName.startsWith(wirePrefix)) { + if (!wireName.matches(wireRegex)) { continue; } - queue.add(Node.getNode(baseTile, wireName)); + Node node = Node.getNode(baseTile, wireName); + queue.add(node); + intentCodes.add(node.getIntentCode()); } System.out.println("Initial queue.size() = " + queue.size()); + System.out.println("Intent codes = " + intentCodes); // Print out the prefixes of nodes that are immediately uphill of these wire prefixes // (i.e. "BOUNCE_E_0_FT1" -> "BOUNCE_") System.out.println("Immediately uphill:"); - queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream).map(Node::getWireName) - .map(s -> s.replaceFirst("((BOUNCE|BYPASS|CTRL|INT_NODE_[^_]+|INODE)_).*", "$1")) + boolean ultraScalePlus = partName.endsWith("p"); + queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream) + .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") + .map(s -> s.replaceFirst("((BOUNCE|BYPASS|CTRL|INT_NODE_[^_]+|INODE|IMUX|SDQNODE)_)[^\\(]+", "$1")) .map(s -> s.replaceFirst( - // UltraScale+ - (partName.endsWith("p")) ? "((CLE_CLE_[LM]_SITE_0|CLK_LEAF_SITES|EE[124]|INT_INT_SDQ|NN[12]|SS[12]|WW[124])_).*" - // UltraScale - : "((CLE_CLE_[LM]_SITE_0|CLK_BUFCE_LEAF_X16_1_CLK|EE[124]|INT_INT_SINGLE|NN[12]|SS[12]|WW[124])_).*", + // UltraScale+ + ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|CLK_LEAF_SITES|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12))_)[^\\(]+" + // UltraScale + : "((CLE_CLE_[LM]_SITE_0|CLK_BUFCE_LEAF_X16_1_CLK|EE[124]|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|SDND[NS]W)_)[^\\(]+", "$1")) .distinct() .sorted() @@ -129,8 +146,15 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str // Print out the prefixes of nodes that are immediately downhill of these wire prefixes System.out.println("Immediately downhill:"); - queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream).map(Node::getWireName) - .map(s -> s.replaceFirst("((BOUNCE|BYPASS|CTRL|IMUX|INT_NODE_[^_]+|INODE)_).*", "$1")) + queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream) + .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") + .map(s -> s.replaceFirst("((BOUNCE|BYPASS|CTRL|IMUX|INT_NODE_[^_]+|INODE|SDQNODE)_)[^\\(]+", "$1")) + .map(s -> s.replaceFirst( + // UltraScale+ + ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12))_)[^\\(]+" + // UltraScale + : "((INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|QLND(NW|SE)|SDND[NS]W)_)[^\\(]+", + "$1")) .distinct() .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); @@ -138,6 +162,13 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str Set visited = new HashSet<>(); while (!queue.isEmpty()) { Node node = queue.poll(); + String wireName = node.getWireName(); + if ((ultraScalePlus && wireName.matches("(INT_NODE_SDQ|SDQNODE)_.*")) || // UltraScale+ + (!ultraScalePlus && wireName.matches("(INT_NODE_(SINGLE_DOUBLE|QUAD_LONG)|QLND(NW|SE|SW)|SDND[NS]W)_.*")) // UltraScale + ) { + // Do not desccend into SDQNODEs + continue; + } for (Node downhill : node.getAllDownhillNodes()) { if (!visited.add(downhill)) { continue; From bba91e13ccdddc589d613146850392193ce9cc9c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 16:00:02 -0800 Subject: [PATCH 07/64] More Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 301e39e90..3bdb07caf 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -94,6 +94,10 @@ public void testUphillNodeIsInvalid() { "xcvu3p,INT_X37Y220,SDQNODE_.*", "xcvu3p,INT_X37Y220,IMUX_.*", "xcvu3p,INT_X37Y220,CTRL_.*", + "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)1_.*", + "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)2_.*", + "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)4_.*", + "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)12_.*", "xcvu3p,CLEM_X37Y220,CLE_CLE_M_SITE_0_[A-H](_O|Q|Q2|MUX)", // UltraScale part @@ -107,6 +111,12 @@ public void testUphillNodeIsInvalid() { "xcvu065,INT_X38Y220,INT_NODE_QUAD_LONG_.*", "xcvu065,INT_X38Y220,IMUX_.*", "xcvu065,INT_X38Y220,CTRL_.*", + "xcvu065,INT_X37Y220,(NN|EE|SS|WW)1_.*", + "xcvu065,INT_X37Y220,(NN|EE|SS|WW)2_.*", + "xcvu065,INT_X37Y220,(NN|EE|SS|WW)4_.*", + "xcvu065,INT_X37Y220,(NN|EE|SS|WW)5_.*", + "xcvu065,INT_X37Y220,(NN|EE|SS|WW)12_.*", + "xcvu065,INT_X37Y220,(NN|EE|SS|WW)16_.*", "xcvu065,INT_X38Y220,QLND.*", "xcvu065,INT_X38Y220,SDND.*", "xcvu065,CLE_M_X38Y220,CLE_CLE_M_SITE_0_[A-H](_O|Q|Q2|MUX)", @@ -138,7 +148,7 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str // UltraScale+ ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|CLK_LEAF_SITES|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12))_)[^\\(]+" // UltraScale - : "((CLE_CLE_[LM]_SITE_0|CLK_BUFCE_LEAF_X16_1_CLK|EE[124]|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|SDND[NS]W)_)[^\\(]+", + : "((CLE_CLE_[LM]_SITE_0|CLK_BUFCE_LEAF_X16_1_CLK|EE[124]|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|QLND(NW|SE|SW)|SDND[NS]W)_)[^\\(]+", "$1")) .distinct() .sorted() @@ -153,7 +163,7 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str // UltraScale+ ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12))_)[^\\(]+" // UltraScale - : "((INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|QLND(NW|SE)|SDND[NS]W)_)[^\\(]+", + : "((CLE_CLE_[LM]_SITE_0|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|QLND(NW|S[EW])|SDND[NS]W)_)[^\\(]+", "$1")) .distinct() .sorted() @@ -163,10 +173,11 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str while (!queue.isEmpty()) { Node node = queue.poll(); String wireName = node.getWireName(); - if ((ultraScalePlus && wireName.matches("(INT_NODE_SDQ|SDQNODE)_.*")) || // UltraScale+ - (!ultraScalePlus && wireName.matches("(INT_NODE_(SINGLE_DOUBLE|QUAD_LONG)|QLND(NW|SE|SW)|SDND[NS]W)_.*")) // UltraScale + if ((ultraScalePlus && wireName.matches("(INT_NODE_SDQ|SDQNODE)_.*")) || // UltraScale+ + (!ultraScalePlus && wireName.matches("(INT_NODE_(SINGLE_DOUBLE|QUAD_LONG)|QLND(NW|SE|SW)|SDND[NS]W)_.*") || // UltraScale + wireName.matches("(NN|EE|SS|WW)\\d+(_[EW])?_BEG\\d+")) ) { - // Do not desccend into SDQNODEs + // Do not desccend into SDQNODEs or SDQLs continue; } for (Node downhill : node.getAllDownhillNodes()) { From 4356b036e1993e05c092644ffb7c3763e2c7ee5d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 17:16:34 -0800 Subject: [PATCH 08/64] Add and use RouteNodeType.LOCAL Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 6 +- .../xilinx/rapidwright/rwroute/RouteNode.java | 9 +- .../rapidwright/rwroute/RouteNodeGraph.java | 103 ++++++++---------- .../rapidwright/rwroute/RouteNodeInfo.java | 29 +++-- .../rapidwright/rwroute/RouteNodeType.java | 3 +- 5 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index d44b7edd4..81098d23c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -56,7 +56,6 @@ import com.xilinx.rapidwright.util.Pair; import com.xilinx.rapidwright.util.RuntimeTracker; import com.xilinx.rapidwright.util.RuntimeTrackerTree; -import com.xilinx.rapidwright.util.Utils; import java.util.ArrayList; import java.util.Arrays; @@ -1798,6 +1797,11 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } switch (childRNode.getType()) { + case LOCAL: + if (!routingGraph.isAccessible(childRNode, connection)) { + continue; + } + break; case WIRE: if (!routingGraph.isAccessible(childRNode, connection)) { continue; diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 1dbc5f4c6..30dcc32d7 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -92,7 +92,7 @@ public class RouteNode extends Node implements Comparable { protected RouteNode(RouteNodeGraph routingGraph, Node node, RouteNodeType type) { super(node); - RouteNodeInfo nodeInfo = RouteNodeInfo.get(this, routingGraph.lagunaI); + RouteNodeInfo nodeInfo = RouteNodeInfo.get(this, routingGraph); this.type = (type == null) ? nodeInfo.type : type; endTileXCoordinate = nodeInfo.endTileXCoordinate; endTileYCoordinate = nodeInfo.endTileYCoordinate; @@ -118,6 +118,9 @@ public int compareTo(RouteNode that) { private void setBaseCost() { baseCost = 0.4f; switch (type) { + case LOCAL: + assert(length <= 1); + break; case LAGUNA_I: // Make all approaches to SLLs zero-cost to encourage exploration // Assigning a base cost of zero would normally break congestion resolution @@ -139,10 +142,10 @@ private void setBaseCost() { case NODE_LAGUNA_OUTPUT: // LAG_LAG.{LAG_MUX_ATOM_*_TXOUT,RXD*} (US+) case NODE_LAGUNA_DATA: // LAG_LAG.UBUMP* super long lines for u-turns at the boundary of the device (US+) case NODE_PINFEED: + case INTENT_DEFAULT: // INT.VCC_WIRE assert(length == 0); break; - case NODE_LOCAL: // US and US+ - case INTENT_DEFAULT: + case NODE_LOCAL: // US and US+ assert(length <= 1); break; case NODE_VSINGLE: // Versal-only diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index e68ad6d8c..a934df8f3 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -37,7 +37,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.design.Net; @@ -100,19 +99,15 @@ public class RouteNodeGraph { */ protected final Map lagunaI; - /** Map indicating which wire indices within an INT tile should be considered - * accessible only if it is within the same column (same X tile coordinate) as - * the target tile. - */ - protected final Map accessibleWireOnlyIfAboveBelowTarget; - /** Map indicating the wire indices corresponding to the [A-H]MUX output */ protected final Map muxWires; - /** Flag for whether LUT routethrus are to be considered - */ + /** Flag for whether LUT routethrus are to be considered */ protected final boolean lutRoutethru; + /** Map indicating the wire indices that have a local intent code, but is what RWRoute considers to be non-local */ + protected final Map nonLocalWires; + public RouteNodeGraph(Design design, RWRouteConfig config) { this(design, config, new HashMap<>()); } @@ -142,55 +137,39 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); + nonLocalWires = new EnumMap<>(TileTypeEnum.class); BitSet wires = new BitSet(); Tile intTile = device.getArbitraryTileOfType(TileTypeEnum.INT); // Device.getArbitraryTileOfType() typically gives you the North-Western-most // tile (with minimum X, maximum Y). Analyze the tile just below that. intTile = intTile.getTileXYNeighbor(0, -1); + nonLocalWires.put(intTile.getTileTypeEnum(), wires); Series series = device.getSeries(); - for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { - Node baseNode = Node.getNode(intTile, wireIndex); - if (baseNode == null) { - continue; - } - Tile baseTile = baseNode.getTile(); - String wireName = baseNode.getWireName(); - if (wireName.startsWith("BOUNCE_")) { - assert(baseNode.getIntentCode() == IntentCode.NODE_PINBOUNCE); - assert(baseTile.getTileXCoordinate() == intTile.getTileXCoordinate()); - // Uphill from INT_NODE_IMUX_* in tile above/below and INODE_* in above/target or below/target tiles - // Downhill to INT_NODE_IMUX_* and INODE_* to above/below tile - } else if (wireName.startsWith("BYPASS_")) { - assert(baseNode.getIntentCode() == IntentCode.NODE_PINBOUNCE); - assert(baseTile == intTile); - assert(wireIndex == baseNode.getWireIndex()); - // Uphill and downhill are INT_NODE_IMUX_* in the target tile and INODE_* to above/below tiles - } else if (wireName.startsWith("INT_NODE_GLOBAL_")) { - assert(baseNode.getIntentCode() == IntentCode.NODE_LOCAL); - assert(baseTile == intTile); - assert(wireIndex == baseNode.getWireIndex()); - // Downhill to CTRL_* in the target tile, INODE_* to above/below tile, INT_NODE_IMUX_* in target tile - } else if (wireName.startsWith("INT_NODE_IMUX_") && - // Do not block INT_NODE_IMUX node accessibility when LUT routethrus are considered - !lutRoutethru) { - assert(((series == Series.UltraScale || series == Series.UltraScalePlus) && baseNode.getIntentCode() == IntentCode.NODE_LOCAL) || - (series == Series.Versal && baseNode.getIntentCode() == IntentCode.NODE_INODE)); - assert(baseTile == intTile); - assert(wireIndex == baseNode.getWireIndex()); - // Downhill to BOUNCE_* in the above/below/target tile, BYPASS_* in the base tile, IMUX_* in target tile - } else if (wireName.startsWith("INODE_")) { - assert(baseNode.getIntentCode() == IntentCode.NODE_LOCAL); - assert(baseTile.getTileXCoordinate() == intTile.getTileXCoordinate()); - // Uphill from nodes in above/target or below/target tiles - // Downhill to BOUNCE_*/BYPASS_*/IMUX_* in above/target or below/target tiles - } else { - continue; + if (series == Series.UltraScale || series == Series.UltraScalePlus) { + for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { + Node baseNode = Node.getNode(intTile, wireIndex); + if (baseNode == null) { + continue; + } + if (baseNode.getIntentCode() != IntentCode.NODE_LOCAL) { + continue; + } + String wireName = baseNode.getWireName(); + if (!wireName.startsWith("INT_NODE_SDQ_") && !wireName.startsWith("SDQNODE_")) { + continue; + } + Tile baseTile = baseNode.getTile(); + if (baseTile != intTile) { + if (wireName.endsWith("_FT0")) { + assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else { + assert(wireName.endsWith("_FT1")); + assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); + } + } + wires.set(baseNode.getWireIndex()); } - - wires.set(baseNode.getWireIndex()); } - accessibleWireOnlyIfAboveBelowTarget.put(intTile.getTileTypeEnum(), wires); if (lutRoutethru) { assert(design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus); @@ -573,25 +552,29 @@ public int averageChildren() { } public boolean isAccessible(RouteNode childRnode, Connection connection) { + // Only consider LOCAL nodes when: + // (a) considering LUT routethrus + if (childRnode.getType() != RouteNodeType.LOCAL || lutRoutethru) { + return true; + } + + // (b) in the sink tile Tile childTile = childRnode.getTile(); - TileTypeEnum childTileType = childTile.getTileTypeEnum(); - BitSet bs = accessibleWireOnlyIfAboveBelowTarget.get(childTileType); - if (bs == null || !bs.get(childRnode.getWireIndex())) { + Tile sinkTile = connection.getSinkRnode().getTile(); + if (childTile == sinkTile) { return true; } + // (c) connection crosses SLR and this is a Laguna column int childX = childTile.getTileXCoordinate(); if (connection.isCrossSLR() && nextLagunaColumn[childX] == childX) { - // Connection crosses SLR and this is a Laguna column - return true; - } - Tile sinkTile = connection.getSinkRnode().getTile(); - if (childX != sinkTile.getTileXCoordinate()) { - return false; + return true; } - return Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; + // (d) when in row above/below the sink tile + return childX == sinkTile.getTileXCoordinate() && + Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; } protected boolean allowRoutethru(Node head, Node tail) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 264c5726f..d994de8ea 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -29,7 +29,6 @@ import com.xilinx.rapidwright.device.Wire; import java.util.BitSet; -import java.util.Map; public class RouteNodeInfo { public final RouteNodeType type; @@ -47,7 +46,7 @@ private RouteNodeInfo(RouteNodeType type, this.length = length; } - public static RouteNodeInfo get(Node node, Map lagunaI) { + public static RouteNodeInfo get(Node node, RouteNodeGraph routingGraph) { Wire[] wires = node.getAllWiresInNode(); Tile baseTile = node.getTile(); TileTypeEnum baseTileType = baseTile.getTileTypeEnum(); @@ -66,7 +65,7 @@ public static RouteNodeInfo get(Node node, Map lagunaI) { endTile = node.getTile(); } - RouteNodeType type = getType(node, endTile, lagunaI); + RouteNodeType type = getType(node, endTile, routingGraph); short endTileXCoordinate = getEndTileXCoordinate(node, type, (short) endTile.getTileXCoordinate()); short endTileYCoordinate = (short) endTile.getTileYCoordinate(); short length = getLength(baseTile, type, endTileXCoordinate, endTileYCoordinate); @@ -126,19 +125,33 @@ private static short getEndTileXCoordinate(Node node, RouteNodeType type, short return endTileXCoordinate; } - private static RouteNodeType getType(Node node, Tile endTile, Map lagunaI) { + private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph routingGraph) { // NOTE: IntentCode is device-dependent IntentCode ic = node.getIntentCode(); switch (ic) { case NODE_PINBOUNCE: return RouteNodeType.PINBOUNCE; - case NODE_PINFEED: - BitSet bs = (lagunaI != null) ? lagunaI.get(node.getTile()) : null; - if (bs != null && bs.get(node.getWireIndex())) { - return RouteNodeType.LAGUNA_I; + case NODE_LOCAL: { + assert(node.getTile().getTileTypeEnum() == TileTypeEnum.INT); + if (routingGraph != null) { + BitSet bs = routingGraph.nonLocalWires.get(node.getTile().getTileTypeEnum()); + if (!bs.get(node.getWireIndex())) { + return RouteNodeType.LOCAL; + } + break; + } + } + + case NODE_PINFEED: { + if (routingGraph != null && routingGraph.lagunaI != null) { + BitSet bs = routingGraph.lagunaI.get(node.getTile()); + if (bs != null && bs.get(node.getWireIndex())) { + return RouteNodeType.LAGUNA_I; + } } break; + } case NODE_LAGUNA_OUTPUT: // UltraScale+ only assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index d81176409..edf61b2fe 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -61,6 +61,7 @@ public enum RouteNodeType { * Denotes other wiring {@link RouteNode} Objects * that are created for routing {@link Connection} Objects. */ - WIRE + WIRE, + LOCAL } From 7e7015a3fb38f1eb5d85b0a6be0035c92f667e29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 17:29:26 -0800 Subject: [PATCH 09/64] Merge RouteNodeType.PINBOUNCE into LOCAL; rename WIRE, PINFEED_{I,O} Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/Connection.java | 6 ++-- .../rapidwright/rwroute/NetWrapper.java | 2 +- .../rapidwright/rwroute/PartialRouter.java | 6 ++-- .../xilinx/rapidwright/rwroute/RWRoute.java | 35 +++++-------------- .../xilinx/rapidwright/rwroute/RouteNode.java | 29 +++++++-------- .../rapidwright/rwroute/RouteNodeGraph.java | 16 ++------- .../rapidwright/rwroute/RouteNodeInfo.java | 8 ++--- .../rapidwright/rwroute/RouteNodeType.java | 23 ++---------- .../rwroute/TimingAndWirelengthReport.java | 6 ++-- 9 files changed, 42 insertions(+), 89 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/Connection.java b/src/com/xilinx/rapidwright/rwroute/Connection.java index 69aef1b90..aad68f0ed 100644 --- a/src/com/xilinx/rapidwright/rwroute/Connection.java +++ b/src/com/xilinx/rapidwright/rwroute/Connection.java @@ -305,9 +305,9 @@ public void addAltSinkRnode(RouteNode sinkRnode) { } else { assert(!altSinkRnodes.contains(sinkRnode)); } - assert(sinkRnode.getType() == RouteNodeType.PINFEED_I || + assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK || // Can be a WIRE if node is not exclusive a sink - sinkRnode.getType() == RouteNodeType.WIRE); + sinkRnode.getType() == RouteNodeType.NON_LOCAL); altSinkRnodes.add(sinkRnode); } @@ -487,7 +487,7 @@ public void setAllTargets(RWRoute.ConnectionState state) { // where the same physical pin services more than one logical pin if (rnode.countConnectionsOfUser(netWrapper) == 0 || // Except if it is not a PINFEED_I - rnode.getType() != RouteNodeType.PINFEED_I) { + rnode.getType() != RouteNodeType.EXCLUSIVE_SINK) { assert(rnode.getIntentCode() != IntentCode.NODE_PINBOUNCE); rnode.markTarget(state); } diff --git a/src/com/xilinx/rapidwright/rwroute/NetWrapper.java b/src/com/xilinx/rapidwright/rwroute/NetWrapper.java index 200bbf7c6..05dc3eff8 100644 --- a/src/com/xilinx/rapidwright/rwroute/NetWrapper.java +++ b/src/com/xilinx/rapidwright/rwroute/NetWrapper.java @@ -171,7 +171,7 @@ public SitePinInst getOrCreateAlternateSource(RouteNodeGraph routingGraph) { return null; } - altSourceRnode = routingGraph.getOrCreate(altSourceNode, RouteNodeType.PINFEED_O); + altSourceRnode = routingGraph.getOrCreate(altSourceNode, RouteNodeType.EXCLUSIVE_SOURCE); } assert(altSourceRnode != null); return altSource; diff --git a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java index 1ad73e55d..871637153 100644 --- a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java +++ b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java @@ -256,7 +256,7 @@ protected void determineRoutingTargets() { preservedNet = routingGraph.getPreservedNet(sinkRnode); if (preservedNet != null && preservedNet != net) { unpreserveNets.add(preservedNet); - assert(sinkRnode.getType() == RouteNodeType.PINFEED_I); + assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK); } } @@ -598,8 +598,8 @@ protected void unpreserveNet(Net net) { assert(!connection.isDirect()); RouteNode sourceRnode = connection.getSourceRnode(); RouteNode sinkRnode = connection.getSinkRnode(); - assert(sourceRnode.getType() == RouteNodeType.PINFEED_O); - assert(sinkRnode.getType() == RouteNodeType.PINFEED_I); + assert(sourceRnode.getType() == RouteNodeType.EXCLUSIVE_SOURCE); + assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK); // Even though this connection is not expected to have any routing yet, // perform a rip up anyway in order to release any exclusive sinks diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 81098d23c..05348b723 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -588,7 +588,7 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { if (connection.getSourceRnode() == null) { assert(sourceINTNode != null); if (sourceINTRnode == null) { - sourceINTRnode = routingGraph.getOrCreate(sourceINTNode, RouteNodeType.PINFEED_O); + sourceINTRnode = routingGraph.getOrCreate(sourceINTNode, RouteNodeType.EXCLUSIVE_SOURCE); // Where only a single primary source exists, always preserve // its projected-to-INT source node, since it could // be a projection from LAGUNA/RXQ* -> RXD* (node for INT/LOGIC_OUTS_*) @@ -600,8 +600,8 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { } indirectConnections.add(connection); - RouteNode sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.PINFEED_I); - sinkRnode.setType(RouteNodeType.PINFEED_I); + RouteNode sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK); connection.setSinkRnode(sinkRnode); // Where appropriate, allow all 6 LUT pins to be swapped to begin with @@ -650,8 +650,8 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { if (routingGraph.isPreserved(node)) { continue; } - RouteNode altSinkRnode = routingGraph.getOrCreate(node, RouteNodeType.PINFEED_I); - assert(altSinkRnode.getType() == RouteNodeType.PINFEED_I); + RouteNode altSinkRnode = routingGraph.getOrCreate(node, RouteNodeType.EXCLUSIVE_SINK); + assert(altSinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK); connection.addAltSinkRnode(altSinkRnode); } @@ -1802,7 +1802,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } break; - case WIRE: + case NON_LOCAL: if (!routingGraph.isAccessible(childRNode, connection)) { continue; } @@ -1812,14 +1812,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } break; - case PINBOUNCE: - // A PINBOUNCE can only be a target if this connection has an alternate sink - assert(!childRNode.isTarget() || connection.getAltSinkRnodes().isEmpty()); - if (!isAccessiblePinbounce(childRNode, connection)) { - continue; - } - break; - case PINFEED_I: + case EXCLUSIVE_SINK: if (!isAccessiblePinfeedI(childRNode, connection)) { continue; } @@ -1858,25 +1851,13 @@ protected boolean isAccessible(RouteNode child, Connection connection) { return !config.isUseBoundingBox() || child.isInConnectionBoundingBox(connection); } - /** - * Checks if a NODE_PINBOUNCE is suitable to be used for routing to a target. - * @param child The PINBOUNCE rnode in question. - * @param connection The connection to route. - * @return true, if the PINBOUNCE rnode is in the same column as the target and within one INT tile of the target. - */ - protected boolean isAccessiblePinbounce(RouteNode child, Connection connection) { - assert(child.getType() == RouteNodeType.PINBOUNCE); - - return routingGraph.isAccessible(child, connection); - } - protected boolean isAccessiblePinfeedI(RouteNode child, Connection connection) { // When LUT pin swapping is enabled, PINFEED_I are not exclusive anymore return isAccessiblePinfeedI(child, connection, !lutPinSwapping); } protected boolean isAccessiblePinfeedI(RouteNode child, Connection connection, boolean assertOnOveruse) { - assert(child.getType() == RouteNodeType.PINFEED_I); + assert(child.getType() == RouteNodeType.EXCLUSIVE_SINK); assert(!assertOnOveruse || !child.isOverUsed()); if (child.isTarget()) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 30dcc32d7..d0186fada 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -27,6 +27,7 @@ import com.xilinx.rapidwright.design.Net; import com.xilinx.rapidwright.device.IntentCode; import com.xilinx.rapidwright.device.Node; +import com.xilinx.rapidwright.device.Series; import com.xilinx.rapidwright.device.Tile; import com.xilinx.rapidwright.device.TileTypeEnum; import com.xilinx.rapidwright.util.RuntimeTracker; @@ -98,7 +99,7 @@ protected RouteNode(RouteNodeGraph routingGraph, Node node, RouteNodeType type) endTileYCoordinate = nodeInfo.endTileYCoordinate; length = nodeInfo.length; children = null; - setBaseCost(); + setBaseCost(routingGraph.design.getSeries()); presentCongestionCost = initialPresentCongestionCost; historicalCongestionCost = initialHistoricalCongestionCost; usersConnectionCounts = null; @@ -115,11 +116,17 @@ public int compareTo(RouteNode that) { return (int) Math.signum(this.lowerBoundTotalPathCost - that.lowerBoundTotalPathCost); } - private void setBaseCost() { + private void setBaseCost(Series series) { baseCost = 0.4f; switch (type) { + case EXCLUSIVE_SOURCE: + assert(length == 0); + break; + case EXCLUSIVE_SINK: case LOCAL: - assert(length <= 1); + assert(length == 0 || + length == 1 && (getIntentCode() == IntentCode.NODE_PINBOUNCE || (type == RouteNodeType.LOCAL && getWireName().matches("INODE_[EW]_\\d+_FT[01]"))) + && (series == Series.UltraScale || series == Series.UltraScalePlus)); break; case LAGUNA_I: // Make all approaches to SLLs zero-cost to encourage exploration @@ -132,7 +139,7 @@ private void setBaseCost() { assert(length == RouteNodeGraph.SUPER_LONG_LINE_LENGTH_IN_TILES); baseCost = 0.3f * length; break; - case WIRE: + case NON_LOCAL: // NOTE: IntentCode is device-dependent IntentCode ic = getIntentCode(); switch(ic) { @@ -218,12 +225,6 @@ private void setBaseCost() { throw new RuntimeException(ic.toString()); } break; - case PINFEED_I: - case PINBOUNCE: - break; - case PINFEED_O: - baseCost = 1f; - break; default: throw new RuntimeException(type.toString()); } @@ -351,11 +352,11 @@ public RouteNodeType getType() { */ public void setType(RouteNodeType type) { assert(this.type == type || - // Support demotion from PINFEED_I to PINBOUNCE since they have the same base cost - (this.type == RouteNodeType.PINFEED_I && type == RouteNodeType.PINBOUNCE) || - // Or promotion from PINBOUNCE to PINFEED_I (by PartialRouter when PINBOUNCE on + // Support demotion from EXCLUSIVE_SINK to LOCAL since they have the same base cost + (this.type == RouteNodeType.EXCLUSIVE_SINK && type == RouteNodeType.LOCAL) || + // Or promotion from LOCAL to EXCLUSIVE_SINK (by PartialRouter when NODE_PINBOUNCE on // preserved net needs to become a PINFEED_I) - (this.type == RouteNodeType.PINBOUNCE && type == RouteNodeType.PINFEED_I)); + (this.type == RouteNodeType.LOCAL && type == RouteNodeType.EXCLUSIVE_SINK)); this.type = type; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index a934df8f3..f21cc2fba 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -416,9 +416,9 @@ protected boolean isExcluded(RouteNode parent, Node child) { // PINFEEDs can lead to a site pin, or into a Laguna tile RouteNode childRnode = getNode(child); if (childRnode != null) { - assert(childRnode.getType() == RouteNodeType.PINFEED_I || + assert(childRnode.getType() == RouteNodeType.EXCLUSIVE_SINK || childRnode.getType() == RouteNodeType.LAGUNA_I || - (lutRoutethru && childRnode.getType() == RouteNodeType.WIRE)); + (lutRoutethru && childRnode.getType() == RouteNodeType.NON_LOCAL)); } else if (!lutRoutethru) { // child does not already exist in our routing graph, meaning it's not a used site pin // in our design, but it could be a LAGUNA_I @@ -513,17 +513,7 @@ public int numNodes() { } protected RouteNode create(Node node, RouteNodeType type) { - RouteNode rnode = new RouteNode(this, node, type); - // PINFEED_I should have zero length, except for on US/US+ where the PINFEED_I can be a PINBOUNCE node. - assert(rnode.getType() != RouteNodeType.PINFEED_I || - rnode.getLength() == 0 || - (rnode.getLength() == 1 && (design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus) && - rnode.getIntentCode() == IntentCode.NODE_PINBOUNCE)); - // PINBOUNCE should have zero length, except for on US/US+ - assert(rnode.getType() != RouteNodeType.PINBOUNCE || - rnode.getLength() == 0 || - (rnode.getLength() == 1 && design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus)); - return rnode; + return new RouteNode(this, node, type); } public RouteNode getOrCreate(Node node) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index d994de8ea..cc16ff2cc 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -129,9 +129,6 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou // NOTE: IntentCode is device-dependent IntentCode ic = node.getIntentCode(); switch (ic) { - case NODE_PINBOUNCE: - return RouteNodeType.PINBOUNCE; - case NODE_LOCAL: { assert(node.getTile().getTileTypeEnum() == TileTypeEnum.INT); if (routingGraph != null) { @@ -143,6 +140,9 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } } + case NODE_PINBOUNCE: + return RouteNodeType.LOCAL; + case NODE_PINFEED: { if (routingGraph != null && routingGraph.lagunaI != null) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); @@ -183,6 +183,6 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou break; } - return RouteNodeType.WIRE; + return RouteNodeType.NON_LOCAL; } } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index edf61b2fe..02b7f9fcf 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -29,21 +29,8 @@ import com.xilinx.rapidwright.device.Node; public enum RouteNodeType { - /** - * Denotes {@link RouteNode} objects that correspond to the output pins of {@link Net} Objects, - * typically the source {@link RouteNode} Objects of {@link Connection} Objects. - */ - PINFEED_O, - /** - * Denotes {@link RouteNode} objects that correspond to input pins of {@link Net} Objects, - * typically the sink {@link RouteNode} Objects of {@link Connection} Objects. - */ - PINFEED_I, - /** - * Denotes {@link RouteNode} objects that are created based on {@link Node} Objects - * that have an {@link IntentCode} of NODE_PINBOUNCE. - */ - PINBOUNCE, + EXCLUSIVE_SOURCE, + EXCLUSIVE_SINK, /** * Denotes {@link RouteNode} objects that correspond to a super long line {@link Node}, @@ -57,11 +44,7 @@ public enum RouteNodeType { */ LAGUNA_I, - /** - * Denotes other wiring {@link RouteNode} Objects - * that are created for routing {@link Connection} Objects. - */ - WIRE, + NON_LOCAL, LOCAL } diff --git a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java index 7da5a405f..c51cc6789 100644 --- a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java +++ b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java @@ -25,7 +25,6 @@ package com.xilinx.rapidwright.rwroute; import java.util.HashMap; -import java.util.List; import java.util.Map; import com.xilinx.rapidwright.design.Design; @@ -35,7 +34,6 @@ import com.xilinx.rapidwright.design.SitePinInst; import com.xilinx.rapidwright.device.IntentCode; import com.xilinx.rapidwright.device.Node; -import com.xilinx.rapidwright.device.TileTypeEnum; import com.xilinx.rapidwright.timing.TimingManager; import com.xilinx.rapidwright.timing.TimingVertex; import com.xilinx.rapidwright.timing.delayestimator.DelayEstimatorBase; @@ -130,11 +128,11 @@ private NetWrapper createNetWrapper(Net net) { if (sinkINTNode == null) { connection.setDirect(true); } else { - connection.setSinkRnode(routingGraph.getOrCreate(sinkINTNode, RouteNodeType.PINFEED_I)); + connection.setSinkRnode(routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK)); if (sourceINTNode == null) { sourceINTNode = RouterHelper.projectOutputPinToINTNode(source); } - connection.setSourceRnode(routingGraph.getOrCreate(sourceINTNode, RouteNodeType.PINFEED_O)); + connection.setSourceRnode(routingGraph.getOrCreate(sourceINTNode, RouteNodeType.EXCLUSIVE_SOURCE)); connection.setDirect(false); } } From b9ff45f71e2a7d39a26ca66f7eb4e2eeea1b6721 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Nov 2024 17:38:08 -0800 Subject: [PATCH 10/64] LUT routethru fixes Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 5 ++++- src/com/xilinx/rapidwright/rwroute/RouteNode.java | 2 +- .../xilinx/rapidwright/rwroute/RouteNodeGraph.java | 4 ++-- .../xilinx/rapidwright/rwroute/RouteNodeInfo.java | 12 ++++++------ .../xilinx/rapidwright/rwroute/RouteNodeType.java | 4 +--- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 05348b723..b17198c66 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1803,6 +1803,9 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { } break; case NON_LOCAL: + assert(rnode.getType() != RouteNodeType.LOCAL || + routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED); + if (!routingGraph.isAccessible(childRNode, connection)) { continue; } @@ -1817,7 +1820,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } break; - case LAGUNA_I: + case LAGUNA_PINFEED: if (!connection.isCrossSLR() || connection.getSinkRnode().getSLRIndex(routingGraph) == childRNode.getSLRIndex(routingGraph)) { // Do not consider approaching a SLL if not needing to cross diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index d0186fada..e66d95938 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -128,7 +128,7 @@ private void setBaseCost(Series series) { length == 1 && (getIntentCode() == IntentCode.NODE_PINBOUNCE || (type == RouteNodeType.LOCAL && getWireName().matches("INODE_[EW]_\\d+_FT[01]"))) && (series == Series.UltraScale || series == Series.UltraScalePlus)); break; - case LAGUNA_I: + case LAGUNA_PINFEED: // Make all approaches to SLLs zero-cost to encourage exploration // Assigning a base cost of zero would normally break congestion resolution // (since RWroute.getNodeCost() would return zero) but doing it here should be diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index f21cc2fba..224d4f913 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -417,8 +417,8 @@ protected boolean isExcluded(RouteNode parent, Node child) { RouteNode childRnode = getNode(child); if (childRnode != null) { assert(childRnode.getType() == RouteNodeType.EXCLUSIVE_SINK || - childRnode.getType() == RouteNodeType.LAGUNA_I || - (lutRoutethru && childRnode.getType() == RouteNodeType.NON_LOCAL)); + childRnode.getType() == RouteNodeType.LAGUNA_PINFEED || + (lutRoutethru && childRnode.getType() == RouteNodeType.LOCAL)); } else if (!lutRoutethru) { // child does not already exist in our routing graph, meaning it's not a used site pin // in our design, but it could be a LAGUNA_I diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index cc16ff2cc..0ee5c1625 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -92,7 +92,7 @@ private static short getLength(Tile baseTile, RouteNodeType type, short endTileX } break; case INT: - if (type == RouteNodeType.LAGUNA_I) { + if (type == RouteNodeType.LAGUNA_PINFEED) { assert(length == 0); } break; @@ -111,7 +111,7 @@ private static short getEndTileXCoordinate(Node node, RouteNodeType type, short // fanout nodes of the SLL are marked as) unless it is a fanin (LAGUNA_I) // (i.e. do not apply it to the fanout nodes). // Nor apply it to VCC_WIREs since their end tiles are INT tiles. - if ((node.getIntentCode() != IntentCode.NODE_LAGUNA_OUTPUT || type == RouteNodeType.LAGUNA_I) && + if ((node.getIntentCode() != IntentCode.NODE_LAGUNA_OUTPUT || type == RouteNodeType.LAGUNA_PINFEED) && !node.isTiedToVcc()) { assert(baseTile.getTileXCoordinate() == endTileXCoordinate); endTileXCoordinate++; @@ -147,16 +147,16 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou if (routingGraph != null && routingGraph.lagunaI != null) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); if (bs != null && bs.get(node.getWireIndex())) { - return RouteNodeType.LAGUNA_I; + return RouteNodeType.LAGUNA_PINFEED; } } - break; + return RouteNodeType.LOCAL; } case NODE_LAGUNA_OUTPUT: // UltraScale+ only assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG); if (node.getWireName().endsWith("_TXOUT")) { - return RouteNodeType.LAGUNA_I; + return RouteNodeType.LAGUNA_PINFEED; } break; @@ -177,7 +177,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou return RouteNodeType.SUPER_LONG_LINE; } else if (wireName.endsWith("_TXOUT")) { // This is the inner LAGUNA_I, mark it so it gets a base cost discount - return RouteNodeType.LAGUNA_I; + return RouteNodeType.LAGUNA_PINFEED; } } break; diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index 02b7f9fcf..2510b4701 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -24,8 +24,6 @@ package com.xilinx.rapidwright.rwroute; -import com.xilinx.rapidwright.design.Net; -import com.xilinx.rapidwright.device.IntentCode; import com.xilinx.rapidwright.device.Node; public enum RouteNodeType { @@ -42,7 +40,7 @@ public enum RouteNodeType { * Denotes {@link RouteNode} objects that correspond to {@link Node} objects that enter * a Laguna tile from an INT tile, or those Laguna tile nodes leading to a SUPER_LONG_LINE. */ - LAGUNA_I, + LAGUNA_PINFEED, NON_LOCAL, From aabab3c9ea31cb4ca5201bd75e10b6ec8c26646f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 5 Nov 2024 08:35:16 -0800 Subject: [PATCH 11/64] Add testNodeReachabilityVersal() Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 105 +++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 3bdb07caf..08617bba0 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -175,7 +175,8 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str String wireName = node.getWireName(); if ((ultraScalePlus && wireName.matches("(INT_NODE_SDQ|SDQNODE)_.*")) || // UltraScale+ (!ultraScalePlus && wireName.matches("(INT_NODE_(SINGLE_DOUBLE|QUAD_LONG)|QLND(NW|SE|SW)|SDND[NS]W)_.*") || // UltraScale - wireName.matches("(NN|EE|SS|WW)\\d+(_[EW])?_BEG\\d+")) + EnumSet.of(IntentCode.NODE_SINGLE, IntentCode.NODE_DOUBLE, IntentCode.NODE_HQUAD, IntentCode.VQUAD, IntentCode.HLONG, IntentCode. VLONG) + .contains(node.getIntentCode())) ) { // Do not desccend into SDQNODEs or SDQLs continue; @@ -195,6 +196,108 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str System.out.println("visited.size() = " + visited.size()); } + @ParameterizedTest + @CsvSource({ + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE", + "xcvp1002,INT_X38Y220,NODE_INODE", + "xcvp1002,INT_X38Y220,NODE_IMUX", + "xcvp1002,INT_X38Y220,NODE_SDQNODE", + "xcvp1002,INT_X38Y220,NODE_HSINGLE", + "xcvp1002,INT_X38Y220,NODE_VSINGLE", + "xcvp1002,INT_X38Y220,NODE_HDOUBLE", + "xcvp1002,INT_X38Y220,NODE_VDOUBLE", + "xcvp1002,INT_X38Y220,NODE_HQUAD", + "xcvp1002,INT_X38Y220,NODE_VQUAD", + "xcvp1002,INT_X38Y220,NODE_HLONG6", + "xcvp1002,INT_X38Y220,NODE_HLONG10", + "xcvp1002,INT_X38Y220,NODE_VLONG7", + "xcvp1002,INT_X38Y220,NODE_VLONG12", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_BNODE", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CNODE", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CTRL", + "xcvp1002,CLE_W_CORE_X38Y220,NODE_PINFEED", + "xcvp1002,CLE_E_CORE_X38Y220,NODE_CLE_OUTPUT", + "xcvp1002,CLE_W_CORE_X38Y220,NODE_CLE_OUTPUT", + }) + public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName) { + Device device = Device.getDevice(partName); + Tile baseTile = device.getTile(tileName); + Queue queue = new ArrayDeque<>(); + IntentCode ic = IntentCode.valueOf(intentCodeName); + for (int wireIdx = 0; wireIdx < baseTile.getWireCount(); wireIdx++) { + if (baseTile.getWireIntentCode(wireIdx) != ic) { + continue; + } + queue.add(Node.getNode(baseTile, wireIdx)); + } + System.out.println("Initial queue.size() = " + queue.size()); + System.out.println("Initial queue = " + queue); + + // Print out the intent code of nodes that are immediately uphill of this intent code + System.out.println("Immediately uphill:"); + queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream).map(Node::getIntentCode) + .distinct() + .sorted() + .forEachOrdered(s -> System.out.println("\t" + s)); + + // Print out the intent code of nodes that are immediately downhill of this intent code + System.out.println("Immediately downhill:"); + queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream).map(Node::getIntentCode) + .distinct() + .sorted() + .forEachOrdered(s -> System.out.println("\t" + s)); + + TileTypeEnum baseTileTypeEnum = baseTile.getTileTypeEnum(); + Set visited = new HashSet<>(); + while (!queue.isEmpty()) { + Node node = queue.poll(); + if (EnumSet.of(IntentCode.NODE_SDQNODE, IntentCode.NODE_HSINGLE, IntentCode.NODE_VSINGLE, + IntentCode.NODE_HDOUBLE, IntentCode.NODE_VDOUBLE, + IntentCode.NODE_HQUAD, IntentCode.NODE_VQUAD, + IntentCode.NODE_HLONG10, IntentCode.NODE_HLONG6, + IntentCode.NODE_VLONG12, IntentCode.NODE_VLONG7).contains(node.getIntentCode())) { + // Do not desccend into SDQNODEs or any SDQLs + continue; + } + for (Node downhill : node.getAllDownhillNodes()) { + if (!visited.add(downhill)) { + continue; + } + if (!Utils.isInterConnect(downhill.getTile().getTileTypeEnum())) { + continue; + } + if (Utils.isCLB(baseTileTypeEnum)) { + if (EnumSet.of(IntentCode.NODE_VLONG7, IntentCode.NODE_VLONG12, IntentCode.NODE_HLONG10, IntentCode.NODE_HLONG6).contains(downhill.getIntentCode())) { + // Ignore long wires that obviously leave the tile + } else { + // All other wires should have the same X coordinate, if not the same Y + Assertions.assertEquals(baseTile.getTileXCoordinate(), downhill.getTile().getTileXCoordinate()); + if (baseTile.getTileYCoordinate() != downhill.getTile().getTileYCoordinate()) { + // Only exception for Y are specific NODE_SDQNODEs with the following wire name + Assertions.assertTrue(downhill.getWireName().matches("OUT_[NEWS]NODE_[EW]_\\d+")); + Assertions.assertEquals(IntentCode.NODE_SDQNODE, downhill.getIntentCode()); + Assertions.assertTrue(1 >= Math.abs(baseTile.getTileYCoordinate() - downhill.getTile().getTileYCoordinate())); + } + } + // Do not descend further + continue; + } + // All INT-to-INT connections should be to the same tile + if (baseTileTypeEnum == TileTypeEnum.CLE_BC_CORE) { + // Except CLE_BC_CORE tiles which spans two adjacent INT tiles + if (baseTile != downhill.getTile()) { + Assertions.assertTrue(1 >= Math.abs(baseTile.getTileXCoordinate() - downhill.getTile().getTileXCoordinate())); + Assertions.assertEquals(TileTypeEnum.INT, downhill.getTile().getTileTypeEnum()); + } + } else { + Assertions.assertEquals(baseTile, downhill.getTile()); + } + queue.add(downhill); + } + } + System.out.println("visited.size() = " + visited.size()); + } + @ParameterizedTest @CsvSource({ // https://github.com/Xilinx/RapidWright/issues/983 From 9929603a3faa5057c7bf913065ad488fc8286eac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 5 Nov 2024 08:52:23 -0800 Subject: [PATCH 12/64] Support UltraScale Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 5 +- .../xilinx/rapidwright/rwroute/RouteNode.java | 11 +++-- .../rapidwright/rwroute/RouteNodeGraph.java | 49 +++++++++++++------ .../rapidwright/rwroute/RouteNodeInfo.java | 2 +- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index b17198c66..712d199f2 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1803,8 +1803,11 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { } break; case NON_LOCAL: + // LOCALs cannot connect to NON_LOCALs except via a LUT routethru assert(rnode.getType() != RouteNodeType.LOCAL || - routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED); + routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED || + // FIXME: + design.getSeries() == Series.Versal); if (!routingGraph.isAccessible(childRNode, connection)) { continue; diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index e66d95938..ed9eb82b1 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -120,13 +120,18 @@ private void setBaseCost(Series series) { baseCost = 0.4f; switch (type) { case EXCLUSIVE_SOURCE: - assert(length == 0); + assert(length == 0 || + (length <= 3 && series == Series.Versal)); break; case EXCLUSIVE_SINK: case LOCAL: assert(length == 0 || - length == 1 && (getIntentCode() == IntentCode.NODE_PINBOUNCE || (type == RouteNodeType.LOCAL && getWireName().matches("INODE_[EW]_\\d+_FT[01]"))) - && (series == Series.UltraScale || series == Series.UltraScalePlus)); + (length == 1 && (series == Series.UltraScalePlus || series == Series.UltraScale) && + (getIntentCode() == IntentCode.NODE_PINBOUNCE || + (series == Series.UltraScalePlus && type == RouteNodeType.LOCAL && getWireName().matches("INODE_[EW]_\\d+_FT[01]")) || + (series == Series.UltraScale && type == RouteNodeType.LOCAL && getWireName().matches("INODE_[12]_[EW]_\\d+_FT[NS]")) + )) + ); break; case LAGUNA_PINFEED: // Make all approaches to SLLs zero-cost to encourage exploration diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 224d4f913..cc17a4b3b 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -145,20 +145,23 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); for (TileTypeEnum tileTypeEnum : Utils.getCLBTileTypes()) { @@ -199,9 +218,9 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Tue, 5 Nov 2024 11:15:25 -0800 Subject: [PATCH 13/64] Extend RouteNodeType.LOCAL to Versal Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 14 +++---- .../xilinx/rapidwright/rwroute/RouteNode.java | 26 ++++-------- .../rapidwright/rwroute/RouteNodeGraph.java | 40 +++++++++++++++---- .../rapidwright/rwroute/RouteNodeInfo.java | 9 +++++ 4 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 712d199f2..289241c08 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1805,9 +1805,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { case NON_LOCAL: // LOCALs cannot connect to NON_LOCALs except via a LUT routethru assert(rnode.getType() != RouteNodeType.LOCAL || - routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED || - // FIXME: - design.getSeries() == Series.Versal); + routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED); if (!routingGraph.isAccessible(childRNode, connection)) { continue; @@ -1819,7 +1817,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { } break; case EXCLUSIVE_SINK: - if (!isAccessiblePinfeedI(childRNode, connection)) { + if (!isAccessibleSink(childRNode, connection)) { continue; } break; @@ -1857,12 +1855,12 @@ protected boolean isAccessible(RouteNode child, Connection connection) { return !config.isUseBoundingBox() || child.isInConnectionBoundingBox(connection); } - protected boolean isAccessiblePinfeedI(RouteNode child, Connection connection) { - // When LUT pin swapping is enabled, PINFEED_I are not exclusive anymore - return isAccessiblePinfeedI(child, connection, !lutPinSwapping); + protected boolean isAccessibleSink(RouteNode child, Connection connection) { + // When LUT pin swapping is enabled, EXCLUSIVE_SINK-s are not exclusive anymore + return isAccessibleSink(child, connection, !lutPinSwapping); } - protected boolean isAccessiblePinfeedI(RouteNode child, Connection connection, boolean assertOnOveruse) { + protected boolean isAccessibleSink(RouteNode child, Connection connection, boolean assertOnOveruse) { assert(child.getType() == RouteNodeType.EXCLUSIVE_SINK); assert(!assertOnOveruse || !child.isOverUsed()); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index ed9eb82b1..63e7cb0dd 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -33,6 +33,7 @@ import com.xilinx.rapidwright.util.RuntimeTracker; import java.util.ArrayList; +import java.util.EnumSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -124,12 +125,15 @@ private void setBaseCost(Series series) { (length <= 3 && series == Series.Versal)); break; case EXCLUSIVE_SINK: + assert(length == 0); + break; case LOCAL: assert(length == 0 || - (length == 1 && (series == Series.UltraScalePlus || series == Series.UltraScale) && - (getIntentCode() == IntentCode.NODE_PINBOUNCE || - (series == Series.UltraScalePlus && type == RouteNodeType.LOCAL && getWireName().matches("INODE_[EW]_\\d+_FT[01]")) || - (series == Series.UltraScale && type == RouteNodeType.LOCAL && getWireName().matches("INODE_[12]_[EW]_\\d+_FT[NS]")) + (length == 1 && ( + ((series == Series.UltraScalePlus || series == Series.UltraScale) && getIntentCode() == IntentCode.NODE_PINBOUNCE) || + (series == Series.UltraScalePlus && getWireName().matches("INODE_[EW]_\\d+_FT[01]")) || + (series == Series.UltraScale && getWireName().matches("INODE_[12]_[EW]_\\d+_FT[NS]")) || + (series == Series.Versal && EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE).contains(getIntentCode())) )) ); break; @@ -212,20 +216,6 @@ private void setBaseCost(Series series) { // Feedthrough nodes to reach tiles immediately above/below (length == 1 && getWireName().matches("OUT_[NESW]NODE_[EW]_\\d+"))); break; - case NODE_INODE: // INT.INT_NODE_IMUX_ATOM_*_INT_OUT[01] - case NODE_IMUX: // INT.IMUX_B_[EW]* - case NODE_CLE_CTRL: // CLE_BC_CORE*.CTRL_[LR]_B* - case NODE_INTF_CTRL: // INTF_[LR]OCF_[TB][LR]_TILE.INTF_IRI* - assert(length == 0); - break; - case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* - case NODE_CLE_CNODE: // CLE_BC_CORE*.CNODE_OUTS_[EW]* - case NODE_INTF_BNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_BNODE_OUTS* - case NODE_INTF_CNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_CNODE_OUTS* - // length == 1 because one side of BCNODE-s are shared between CLE_W_CORE_XaYb and CLE_E_CORE_X(a+1)Yb - // or CLE_W_CORE_X(a-1)Yb and CLE_E_CORE_XaYb - assert(length <= 1); - break; default: throw new RuntimeException(ic.toString()); } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 724326cf6..ef908c356 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -108,6 +108,9 @@ public class RouteNodeGraph { /** Map indicating the wire indices that have a local intent code, but is what RWRoute considers to be non-local */ protected final Map nonLocalWires; + /** Flag for whether design targets the Versal series */ + protected final boolean isVersal; + public RouteNodeGraph(Design design, RWRouteConfig config) { this(design, config, new HashMap<>()); } @@ -147,7 +150,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Tue, 5 Nov 2024 11:30:56 -0800 Subject: [PATCH 14/64] Exclude Versal's NODE_IMUX/NODE_{CLE,INTF}_CTRL if not in RRG Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index ef908c356..590a24cfe 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -23,10 +23,8 @@ package com.xilinx.rapidwright.rwroute; -import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; -import java.util.Collection; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; @@ -79,11 +77,6 @@ public class RouteNodeGraph { */ private final CountUpDownLatch asyncPreserveOutstanding; - /** - * Visited rnodes data during connection routing - */ - private final Collection targets; - private long createRnodeTime; public static final short SUPER_LONG_LINE_LENGTH_IN_TILES = 60; @@ -124,7 +117,6 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(); preservedMapSize = new AtomicInteger(); asyncPreserveOutstanding = new CountUpDownLatch(); - targets = new ArrayList<>(); createRnodeTime = 0; Device device = design.getDevice(); @@ -290,7 +282,6 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Wed, 6 Nov 2024 23:22:27 -0800 Subject: [PATCH 15/64] More explanatory approach; no difference Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index c1879a52c..0c665dfa3 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -588,19 +588,35 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { if (isVersal) { if (childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate()) { + // Same row as our sink tile + boolean childInInt = childTile.getTileTypeEnum() == TileTypeEnum.INT; boolean sinkInInt = sinkTile.getTileTypeEnum() == TileTypeEnum.INT; - if (!childInInt && sinkInInt) { - // Allow CLE CNODE/BNODEs that reach into the sink INT tile + + if (!sinkInInt) { + // Sink is a NODE_{CTRL,INTF}_CTRL + + if (!childInInt) { + // Same row, but not the same exact CLE_BC_CORE tile, as our sink + assert(childTile != sinkTile); + return false; + } + + // Allow use of LOCALs inside the two INT tiles that border this non-INT sink tile + assert(childInInt); + return Math.abs(childTile.getTileXCoordinate() - sinkTile.getTileXCoordinate()) <= 1; + } + + if (!childInInt) { + // Allow CNODE/BNODEs that reach into the sink INT tile assert(EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE, IntentCode.NODE_INTF_BNODE, IntentCode.NODE_INTF_CNODE) .contains(childRnode.getIntentCode())); return childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); } - if (childInInt && !sinkInInt) { - // Allow use of LOCALs inside the INT tile that (by way of being at most one X coordinate away) services the CLE_BC_CORE - return Math.abs(childRnode.getEndTileXCoordinate() - sinkTile.getTileXCoordinate()) <= 1; - } + // Do not use LOCALs in any other INT tile but our sink's + assert(sinkInInt && childInInt); + assert(childTile != sinkTile); } return false; From 14955fe703336f668fab15a6329d545edad82778 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 10:20:26 -0800 Subject: [PATCH 16/64] Improvement? Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 114 ++++++++++++------ 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 0c665dfa3..67edcdf48 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -578,50 +578,96 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return true; } - // (b) in the sink tile Tile childTile = childRnode.getTile(); RouteNode sinkRnode = connection.getSinkRnode(); Tile sinkTile = sinkRnode.getTile(); - if (childTile == sinkTile) { - return true; - } - if (isVersal) { - if (childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate()) { - // Same row as our sink tile - - boolean childInInt = childTile.getTileTypeEnum() == TileTypeEnum.INT; - boolean sinkInInt = sinkTile.getTileTypeEnum() == TileTypeEnum.INT; - - if (!sinkInInt) { - // Sink is a NODE_{CTRL,INTF}_CTRL - - if (!childInInt) { - // Same row, but not the same exact CLE_BC_CORE tile, as our sink - assert(childTile != sinkTile); + IntentCode childIntentCode = childRnode.getIntentCode(); + switch (childIntentCode) { + case NODE_INODE: + // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) + if (childRnode.getTile() != sinkTile) { return false; } - - // Allow use of LOCALs inside the two INT tiles that border this non-INT sink tile - assert(childInInt); - return Math.abs(childTile.getTileXCoordinate() - sinkTile.getTileXCoordinate()) <= 1; - } - - if (!childInInt) { - // Allow CNODE/BNODEs that reach into the sink INT tile - assert(EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE, IntentCode.NODE_INTF_BNODE, IntentCode.NODE_INTF_CNODE) - .contains(childRnode.getIntentCode())); - return childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); - } - - // Do not use LOCALs in any other INT tile but our sink's - assert(sinkInInt && childInInt); - assert(childTile != sinkTile); + assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); + break; + case NODE_CLE_CNODE: + // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL); + break; + case NODE_INTF_CNODE: + // Block access to all CNODEs outside the sink tile, since NODE_INTF_CNODE -> NODE_INTF_CTRL + if (childRnode.getTile() != sinkTile) { + return false; + } + assert(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); + break; + case NODE_PINBOUNCE: + // BOUNCEs are only accessible through INODEs, so transitively this node must be in the sink tile too + assert(childRnode.getTile() == sinkTile); + assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); + break; + case NODE_CLE_BNODE: + case NODE_INTF_BNODE: + IntentCode sinkIntentCode = sinkRnode.getIntentCode(); + // For CTRL sinks, only allow BNODEs in the sink tile + if (sinkIntentCode == IntentCode.NODE_CLE_CTRL || sinkIntentCode == IntentCode.NODE_INTF_CTRL) { + return childTile == sinkTile; + } + // For other sinks, only allow if BNODE reaches into the sink tile + assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); + return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && + childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); + default: + throw new RuntimeException("ERROR: Unhandled IntentCode: " + childIntentCode); } + return true; + } - return false; + // (b) in the sink tile + if (childTile == sinkTile) { + return true; } + // if (isVersal) { + // if (childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate()) { + // // Same row as our sink tile + // + // boolean childInInt = childTile.getTileTypeEnum() == TileTypeEnum.INT; + // boolean sinkInInt = sinkTile.getTileTypeEnum() == TileTypeEnum.INT; + // + // if (!sinkInInt) { + // // Sink is a NODE_{CTRL,INTF}_CTRL + // + // if (!childInInt) { + // // Same row, but not the same exact CLE_BC_CORE tile, as our sink + // assert(childTile != sinkTile); + // return false; + // } + // + // // Allow use of LOCALs inside the two INT tiles that border this non-INT sink tile + // assert(childInInt); + // return Math.abs(childTile.getTileXCoordinate() - sinkTile.getTileXCoordinate()) <= 1; + // } + // + // if (!childInInt) { + // // Allow CNODE/BNODEs that reach into the sink INT tile + // assert(EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE, IntentCode.NODE_INTF_BNODE, IntentCode.NODE_INTF_CNODE) + // .contains(childRnode.getIntentCode())); + // return childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); + // } + // + // // Do not use LOCALs in any other INT tile but our sink's + // assert(sinkInInt && childInInt); + // assert(childTile != sinkTile); + // } + // + // return false; + // } + // (c) connection crosses SLR and this is a Laguna column int childX = childTile.getTileXCoordinate(); if (connection.isCrossSLR() && nextLagunaColumn[childX] == childX) { From 56afd4b21958a3d129070f54d45a62f98999b6bb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 10:23:43 -0800 Subject: [PATCH 17/64] Cleanup Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 74 +++---------------- 1 file changed, 11 insertions(+), 63 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 67edcdf48..890ec4ef9 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -578,96 +578,44 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return true; } + // (b) in the sink tile Tile childTile = childRnode.getTile(); RouteNode sinkRnode = connection.getSinkRnode(); Tile sinkTile = sinkRnode.getTile(); + if (childTile == sinkTile) { + return true; + } + if (isVersal) { IntentCode childIntentCode = childRnode.getIntentCode(); switch (childIntentCode) { case NODE_INODE: // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) - if (childRnode.getTile() != sinkTile) { - return false; - } - assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); - break; + return false; case NODE_CLE_CNODE: // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL - if (childRnode.getTile() != sinkTile) { - return false; - } - assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL); - break; + return false; case NODE_INTF_CNODE: // Block access to all CNODEs outside the sink tile, since NODE_INTF_CNODE -> NODE_INTF_CTRL - if (childRnode.getTile() != sinkTile) { - return false; - } - assert(sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); - break; + return false; case NODE_PINBOUNCE: // BOUNCEs are only accessible through INODEs, so transitively this node must be in the sink tile too - assert(childRnode.getTile() == sinkTile); - assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); - break; + return false; case NODE_CLE_BNODE: case NODE_INTF_BNODE: IntentCode sinkIntentCode = sinkRnode.getIntentCode(); // For CTRL sinks, only allow BNODEs in the sink tile if (sinkIntentCode == IntentCode.NODE_CLE_CTRL || sinkIntentCode == IntentCode.NODE_INTF_CTRL) { - return childTile == sinkTile; + return false; } // For other sinks, only allow if BNODE reaches into the sink tile assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); - default: - throw new RuntimeException("ERROR: Unhandled IntentCode: " + childIntentCode); } - return true; + throw new RuntimeException("ERROR: Unhandled IntentCode: " + childIntentCode); } - // (b) in the sink tile - if (childTile == sinkTile) { - return true; - } - - // if (isVersal) { - // if (childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate()) { - // // Same row as our sink tile - // - // boolean childInInt = childTile.getTileTypeEnum() == TileTypeEnum.INT; - // boolean sinkInInt = sinkTile.getTileTypeEnum() == TileTypeEnum.INT; - // - // if (!sinkInInt) { - // // Sink is a NODE_{CTRL,INTF}_CTRL - // - // if (!childInInt) { - // // Same row, but not the same exact CLE_BC_CORE tile, as our sink - // assert(childTile != sinkTile); - // return false; - // } - // - // // Allow use of LOCALs inside the two INT tiles that border this non-INT sink tile - // assert(childInInt); - // return Math.abs(childTile.getTileXCoordinate() - sinkTile.getTileXCoordinate()) <= 1; - // } - // - // if (!childInInt) { - // // Allow CNODE/BNODEs that reach into the sink INT tile - // assert(EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE, IntentCode.NODE_INTF_BNODE, IntentCode.NODE_INTF_CNODE) - // .contains(childRnode.getIntentCode())); - // return childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); - // } - // - // // Do not use LOCALs in any other INT tile but our sink's - // assert(sinkInInt && childInInt); - // assert(childTile != sinkTile); - // } - // - // return false; - // } - // (c) connection crosses SLR and this is a Laguna column int childX = childTile.getTileXCoordinate(); if (connection.isCrossSLR() && nextLagunaColumn[childX] == childX) { From cac787ed3147f183b7cbfce2dab5691fcc339a5d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 11:58:42 -0800 Subject: [PATCH 18/64] Update comments Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 890ec4ef9..70f9bea65 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -590,7 +590,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { IntentCode childIntentCode = childRnode.getIntentCode(); switch (childIntentCode) { case NODE_INODE: - // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE _> NODE_PINBOUNCE) + // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE -> NODE_PINBOUNCE) return false; case NODE_CLE_CNODE: // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL @@ -604,7 +604,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { case NODE_CLE_BNODE: case NODE_INTF_BNODE: IntentCode sinkIntentCode = sinkRnode.getIntentCode(); - // For CTRL sinks, only allow BNODEs in the sink tile + // For CTRL sinks, block all BNODEs outside the sink tile if (sinkIntentCode == IntentCode.NODE_CLE_CTRL || sinkIntentCode == IntentCode.NODE_INTF_CTRL) { return false; } @@ -612,6 +612,17 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); + case NODE_IMUX: + // IMUXes that are not EXCLUSIVE_SINKs will have been isExcluded() from the graph unless LUT routethrus are enabled + assert(lutRoutethru); + return true; + case NODE_PINFEED: + // Expected to be projected away + break; + case NODE_CLE_CTRL: + case NODE_INTF_CTRL: + // CTRL pins that are not EXCLUSIVE_SINKs will have been isExcluded() from the graph + break; } throw new RuntimeException("ERROR: Unhandled IntentCode: " + childIntentCode); } From ef4227c5f85f9518c63a3f52fd33a8f250e1ca44 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 12:26:08 -0800 Subject: [PATCH 19/64] Add NODE_INTF_{CNODE,BNODE} Signed-off-by: Eddie Hung --- .../src/com/xilinx/rapidwright/device/TestNode.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index e72e0cd4a..22f99789b 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -224,6 +224,8 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str "xcvp1002,CLE_W_CORE_X38Y220,NODE_PINFEED,true", "xcvp1002,CLE_E_CORE_X38Y220,NODE_CLE_OUTPUT,false", "xcvp1002,CLE_W_CORE_X38Y220,NODE_CLE_OUTPUT,false", + "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_CNODE,true", + "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_BNODE,true", }) public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName, boolean local) { Device device = Device.getDevice(partName); @@ -289,7 +291,16 @@ public void testNodeReachabilityVersal(String partName, String tileName, String } } // All INT-to-INT connections should be to the same tile - else if (baseTileTypeEnum == TileTypeEnum.CLE_BC_CORE) { + else if (EnumSet.of(TileTypeEnum.CLE_BC_CORE, + TileTypeEnum.INTF_LOCF_TL_TILE, + TileTypeEnum.INTF_LOCF_TR_TILE, + TileTypeEnum.INTF_LOCF_BL_TILE, + TileTypeEnum.INTF_LOCF_BR_TILE, + TileTypeEnum.INTF_ROCF_TL_TILE, + TileTypeEnum.INTF_ROCF_TR_TILE, + TileTypeEnum.INTF_ROCF_BL_TILE, + TileTypeEnum.INTF_ROCF_BR_TILE) + .contains(baseTileTypeEnum)) { // Except CLE_BC_CORE tiles which spans two adjacent INT tiles if (baseTile != downhill.getTile()) { Assertions.assertTrue(1 >= Math.abs(baseTile.getTileXCoordinate() - downhill.getTile().getTileXCoordinate())); From cd631ac34bb9c58af446637d1cf606030d2b5c16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 15:15:16 -0800 Subject: [PATCH 20/64] [TestNode] Expand testNodeReachabilityUltraScale Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 65 +++++++++++++------ 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index e72e0cd4a..18cbb524f 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -84,16 +84,23 @@ public void testUphillNodeIsInvalid() { @ParameterizedTest @CsvSource({ // UltraScale+ part - "xcvu3p,INT_X37Y220,BOUNCE_.*,true", - "xcvu3p,INT_X37Y220,BYPASS_.*,true", + "xcvu3p,INT_X37Y220,BOUNCE_E_.*,true", + "xcvu3p,INT_X37Y220,BOUNCE_W_.*,true", + "xcvu3p,INT_X37Y220,BYPASS_E.*,true", + "xcvu3p,INT_X37Y220,BYPASS_W.*,true", "xcvu3p,INT_X37Y220,INT_NODE_GLOBAL_.*,true", - "xcvu3p,INT_X37Y220,INT_NODE_IMUX_.*,true", - "xcvu3p,INT_X37Y220,INODE_.*,true", + "xcvu3p,INT_X37Y220,INT_NODE_IMUX_([0-9]|1[0-9]|2[0-9]|3[01])_.*,true", + "xcvu3p,INT_X37Y220,INT_NODE_IMUX_(3[2-9]|4[0-9]|5[0-9]|6[0-3])_.*,true", + "xcvu3p,INT_X37Y220,INODE_E_.*,true", + "xcvu3p,INT_X37Y220,INODE_W_.*,true", "xcvu3p,INT_X37Y220,INT_INT_SDQ_.*,false", // IntentCode.NODE_SINGLE "xcvu3p,INT_X37Y220,INT_NODE_SDQ_.*,false", - "xcvu3p,INT_X37Y220,SDQNODE_.*,false", - "xcvu3p,INT_X37Y220,IMUX_.*,true", - "xcvu3p,INT_X37Y220,CTRL_.*,true", + "xcvu3p,INT_X37Y220,SDQNODE_E_.*,false", + "xcvu3p,INT_X37Y220,SDQNODE_W_.*,false", + "xcvu3p,INT_X37Y220,IMUX_E.*,true", + "xcvu3p,INT_X37Y220,IMUX_W.*,true", + "xcvu3p,INT_X37Y220,CTRL_E.*,true", + "xcvu3p,INT_X37Y220,CTRL_W.*,true", "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)1_.*,false", "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)2_.*,false", "xcvu3p,INT_X37Y220,(NN|EE|SS|WW)4_.*,false", @@ -101,16 +108,22 @@ public void testUphillNodeIsInvalid() { "xcvu3p,CLEM_X37Y220,CLE_CLE_M_SITE_0_[A-H](_O|Q|Q2|MUX),false", // UltraScale part - "xcvu065,INT_X38Y220,BOUNCE_.*,true", - "xcvu065,INT_X38Y220,BYPASS_.*,true", + "xcvu065,INT_X38Y220,BOUNCE_E_.*,true", + "xcvu065,INT_X38Y220,BOUNCE_W_.*,true", + "xcvu065,INT_X38Y220,BYPASS_E.*,true", + "xcvu065,INT_X38Y220,BYPASS_W.*,true", "xcvu065,INT_X38Y220,INT_NODE_GLOBAL_.*,true", - "xcvu065,INT_X38Y220,INT_NODE_IMUX_.*,true", - "xcvu065,INT_X38Y220,INODE_.*,true", + "xcvu065,INT_X38Y220,INT_NODE_IMUX_([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_.*,true", + "xcvu065,INT_X38Y220,INT_NODE_IMUX_(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_.*,true", + "xcvu065,INT_X38Y220,INODE_[12]_E_.*,true", + "xcvu065,INT_X38Y220,INODE_[12]_W_.*,true", "xcvu065,INT_X38Y220,INT_INT_SINGLE_.*,false", // IntentCode.NODE_SINGLE "xcvu065,INT_X38Y220,INT_NODE_SINGLE_DOUBLE_.*,false", "xcvu065,INT_X38Y220,INT_NODE_QUAD_LONG_.*,false", - "xcvu065,INT_X38Y220,IMUX_.*,true", - "xcvu065,INT_X38Y220,CTRL_.*,true", + "xcvu065,INT_X38Y220,IMUX_E.*,true", + "xcvu065,INT_X38Y220,IMUX_W.*,true", + "xcvu065,INT_X38Y220,CTRL_E.*,true", + "xcvu065,INT_X38Y220,CTRL_W.*,true", "xcvu065,INT_X37Y220,(NN|EE|SS|WW)1_.*,false", "xcvu065,INT_X37Y220,(NN|EE|SS|WW)2_.*,false", "xcvu065,INT_X37Y220,(NN|EE|SS|WW)4_.*,false", @@ -143,13 +156,18 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str boolean ultraScalePlus = partName.endsWith("p"); queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream) .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") - .map(s -> s.replaceFirst("((BOUNCE|BYPASS|CTRL|INT_NODE_[^_]+|INODE|IMUX|SDQNODE)_)[^\\(]+", "$1")) + .map(s -> s.replaceFirst("^((BOUNCE|BYPASS|CTRL|INODE(_[12])?|IMUX|SDQNODE)_([EW]_?)?)[^ ]+", "$1")) + .map(s -> s.replaceFirst("(INT_NODE_(GLOBAL|SDQ|SINGLE_DOUBLE|QUAD_LONG)_)[^ ]+", "$1")) + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01])_INT_OUT[01]?", "$1<0-31>") + : s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_INT_OUT", "$1<0-31,64-95>")) + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3])_INT_OUT[01]?", "$1<32-63>") + : s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_INT_OUT", "$1<32-63,96-127>")) .map(s -> s.replaceFirst( // UltraScale+ - ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|CLK_LEAF_SITES|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12))_)[^\\(]+" + ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|CLK_LEAF_SITES|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12)(_[EW])?)_)[^\\(]+" // UltraScale - : "((CLE_CLE_[LM]_SITE_0|CLK_BUFCE_LEAF_X16_1_CLK|EE[124]|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|QLND(NW|SE|SW)|SDND[NS]W)_)[^\\(]+", - "$1")) + : "((CLE_CLE_[LM]_SITE_0|CLK_BUFCE_LEAF_X16_1_CLK|EE[124]|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)(_[EW])?|(EE|WW)(1|2|4|12)|QLND(NW|SE|SW)|SDND[NS]W)_)[^\\(]+", + "$1 ")) .distinct() .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); @@ -158,13 +176,18 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str System.out.println("Immediately downhill:"); queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream) .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") - .map(s -> s.replaceFirst("((BOUNCE|BYPASS|CTRL|IMUX|INT_NODE_[^_]+|INODE|SDQNODE)_)[^\\(]+", "$1")) + .map(s -> s.replaceFirst("^((BOUNCE|BYPASS|CTRL|INODE(_[12])?|IMUX|SDQNODE)_([EW]_?)?)[^ ]+", "$1")) + .map(s -> s.replaceFirst("(INT_NODE_(GLOBAL|SDQ|SINGLE_DOUBLE|QUAD_LONG)_)[^ ]+", "$1")) + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01])_INT_OUT[01]?", "$1<0-31>") + : s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_INT_OUT", "$1<0-31,64-95>")) + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3])_INT_OUT[01]?", "$1<32-63>") + : s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_INT_OUT", "$1<32-63,96-127>")) .map(s -> s.replaceFirst( // UltraScale+ - ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12))_)[^\\(]+" + ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12)(_[EW])?)_)[^\\(]+" // UltraScale - : "((CLE_CLE_[LM]_SITE_0|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)|QLND(NW|S[EW])|SDND[NS]W)_)[^\\(]+", - "$1")) + : "((CLE_CLE_[LM]_SITE_0|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)(_[EW])?|QLND(NW|S[EW])|SDND[NS]W)_)[^\\(]+", + "$1 ")) .distinct() .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); From 038aa805ece27059f409efbe4cff8e2e2ac2321d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 15:15:39 -0800 Subject: [PATCH 21/64] Expand testNodeReachabilityVersal too Signed-off-by: Eddie Hung --- .../src/com/xilinx/rapidwright/device/TestNode.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 18cbb524f..2b0d6bef1 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -247,6 +247,8 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str "xcvp1002,CLE_W_CORE_X38Y220,NODE_PINFEED,true", "xcvp1002,CLE_E_CORE_X38Y220,NODE_CLE_OUTPUT,false", "xcvp1002,CLE_W_CORE_X38Y220,NODE_CLE_OUTPUT,false", + "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_CNODE,true", + "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_BNODE,true", }) public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName, boolean local) { Device device = Device.getDevice(partName); @@ -312,7 +314,16 @@ public void testNodeReachabilityVersal(String partName, String tileName, String } } // All INT-to-INT connections should be to the same tile - else if (baseTileTypeEnum == TileTypeEnum.CLE_BC_CORE) { + else if (EnumSet.of(TileTypeEnum.CLE_BC_CORE, + TileTypeEnum.INTF_LOCF_TL_TILE, + TileTypeEnum.INTF_LOCF_TR_TILE, + TileTypeEnum.INTF_LOCF_BL_TILE, + TileTypeEnum.INTF_LOCF_BR_TILE, + TileTypeEnum.INTF_ROCF_TL_TILE, + TileTypeEnum.INTF_ROCF_TR_TILE, + TileTypeEnum.INTF_ROCF_BL_TILE, + TileTypeEnum.INTF_ROCF_BR_TILE) + .contains(baseTileTypeEnum)) { // Except CLE_BC_CORE tiles which spans two adjacent INT tiles if (baseTile != downhill.getTile()) { Assertions.assertTrue(1 >= Math.abs(baseTile.getTileXCoordinate() - downhill.getTile().getTileXCoordinate())); From 77fa308ddcb35bdf77214bc3a6f63b6577ce3a89 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 16:15:35 -0800 Subject: [PATCH 22/64] UltraScale+: Sub-divide LOCALs into _EAST/_WEST and stick to sink's side Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/Connection.java | 4 +- .../rapidwright/rwroute/PartialRouter.java | 4 +- .../xilinx/rapidwright/rwroute/RWRoute.java | 30 ++++- .../xilinx/rapidwright/rwroute/RouteNode.java | 13 +- .../rapidwright/rwroute/RouteNodeGraph.java | 112 ++++++++++++------ .../rapidwright/rwroute/RouteNodeInfo.java | 33 ++++-- .../rapidwright/rwroute/RouteNodeType.java | 15 ++- .../rwroute/TimingAndWirelengthReport.java | 13 +- 8 files changed, 164 insertions(+), 60 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/Connection.java b/src/com/xilinx/rapidwright/rwroute/Connection.java index 6c08342dc..95a7f87e0 100644 --- a/src/com/xilinx/rapidwright/rwroute/Connection.java +++ b/src/com/xilinx/rapidwright/rwroute/Connection.java @@ -305,7 +305,7 @@ public void addAltSinkRnode(RouteNode sinkRnode) { } else { assert(!altSinkRnodes.contains(sinkRnode)); } - assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK || + assert(sinkRnode.getType().isExclusiveSink() || // Can be a WIRE if node is not exclusive a sink sinkRnode.getType() == RouteNodeType.NON_LOCAL); altSinkRnodes.add(sinkRnode); @@ -487,7 +487,7 @@ public void setAllTargets(RWRoute.ConnectionState state) { // where the same physical pin services more than one logical pin if (rnode.countConnectionsOfUser(netWrapper) == 0 || // Except if it is not an EXCLUSIVE_SINK - rnode.getType() != RouteNodeType.EXCLUSIVE_SINK) { + rnode.getType().isExclusiveSink()) { assert(rnode.getIntentCode() != IntentCode.NODE_PINBOUNCE); rnode.markTarget(state); } diff --git a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java index 871637153..90435b794 100644 --- a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java +++ b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java @@ -256,7 +256,7 @@ protected void determineRoutingTargets() { preservedNet = routingGraph.getPreservedNet(sinkRnode); if (preservedNet != null && preservedNet != net) { unpreserveNets.add(preservedNet); - assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK); + assert(sinkRnode.getType().isExclusiveSink()); } } @@ -599,7 +599,7 @@ protected void unpreserveNet(Net net) { RouteNode sourceRnode = connection.getSourceRnode(); RouteNode sinkRnode = connection.getSinkRnode(); assert(sourceRnode.getType() == RouteNodeType.EXCLUSIVE_SOURCE); - assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK); + assert(sinkRnode.getType().isExclusiveSink()); // Even though this connection is not expected to have any routing yet, // perform a rip up anyway in order to release any exclusive sinks diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 4d2f363d5..0a38dd27e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -59,6 +59,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; @@ -600,8 +601,16 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { } indirectConnections.add(connection); - RouteNode sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK); + BitSet[] eastWestWires = routingGraph.eastWestWires.get(sinkINTNode.getTile().getTileTypeEnum()); + RouteNode sinkRnode; + if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { + sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_EAST); + } else { + assert(eastWestWires[1].get(sinkINTNode.getWireIndex())); + sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); + } connection.setSinkRnode(sinkRnode); // Where appropriate, allow all 6 LUT pins to be swapped to begin with @@ -650,8 +659,14 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { if (routingGraph.isPreserved(node)) { continue; } - RouteNode altSinkRnode = routingGraph.getOrCreate(node, RouteNodeType.EXCLUSIVE_SINK); - assert(altSinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK); + RouteNode altSinkRnode; + if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { + altSinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); + } else { + assert(eastWestWires[1].get(sinkINTNode.getWireIndex())); + altSinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); + } + assert(altSinkRnode.getType().isExclusiveSink()); connection.addAltSinkRnode(altSinkRnode); } @@ -1798,6 +1813,8 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { } switch (childRNode.getType()) { case LOCAL: + case LOCAL_EAST: + case LOCAL_WEST: if (!routingGraph.isAccessible(childRNode, connection)) { continue; } @@ -1818,7 +1835,8 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } break; - case EXCLUSIVE_SINK: + case EXCLUSIVE_SINK_EAST: + case EXCLUSIVE_SINK_WEST: if (!isAccessibleSink(childRNode, connection)) { continue; } @@ -1863,7 +1881,7 @@ protected boolean isAccessibleSink(RouteNode child, Connection connection) { } protected boolean isAccessibleSink(RouteNode child, Connection connection, boolean assertOnOveruse) { - assert(child.getType() == RouteNodeType.EXCLUSIVE_SINK); + assert(child.getType().isExclusiveSink()); assert(!assertOnOveruse || !child.isOverUsed()); if (child.isTarget()) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index c70a18000..d993496aa 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -93,7 +93,7 @@ public class RouteNode extends Node implements Comparable { protected RouteNode(RouteNodeGraph routingGraph, Node node, RouteNodeType type) { super(node); - RouteNodeInfo nodeInfo = RouteNodeInfo.get(this, routingGraph); + RouteNodeInfo nodeInfo = RouteNodeInfo.get(node, routingGraph); this.type = (type == null) ? nodeInfo.type : type; endTileXCoordinate = nodeInfo.endTileXCoordinate; endTileYCoordinate = nodeInfo.endTileYCoordinate; @@ -123,11 +123,16 @@ private void setBaseCost(Series series) { assert(length == 0 || (length <= 3 && series == Series.Versal)); break; - case EXCLUSIVE_SINK: + case EXCLUSIVE_SINK_EAST: + case EXCLUSIVE_SINK_WEST: assert(length == 0 || (length == 1 && (series == Series.UltraScalePlus || series == Series.UltraScale) && getIntentCode() == IntentCode.NODE_PINBOUNCE)); break; case LOCAL: + assert(length == 0); + break; + case LOCAL_EAST: + case LOCAL_WEST: assert(length == 0 || (length == 1 && ( ((series == Series.UltraScalePlus || series == Series.UltraScale) && getIntentCode() == IntentCode.NODE_PINBOUNCE) || @@ -361,10 +366,10 @@ public RouteNodeType getType() { public void setType(RouteNodeType type) { assert(this.type == type || // Support demotion from EXCLUSIVE_SINK to LOCAL since they have the same base cost - (this.type == RouteNodeType.EXCLUSIVE_SINK && type == RouteNodeType.LOCAL) || + (this.type.isExclusiveSink() && type == RouteNodeType.LOCAL) || // Or promotion from LOCAL to EXCLUSIVE_SINK (by PartialRouter when NODE_PINBOUNCE on // a newly unpreserved net becomes a sink) - (this.type == RouteNodeType.LOCAL && type == RouteNodeType.EXCLUSIVE_SINK)); + (this.type == RouteNodeType.LOCAL && type.isExclusiveSink())); this.type = type; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 324be57e3..289c99f51 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -35,6 +35,8 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.design.Net; @@ -101,6 +103,8 @@ public class RouteNodeGraph { /** Map indicating the wire indices that have a local intent code, but is what RWRoute considers to be non-local */ protected final Map ultraScaleNonLocalWires; + protected final Map eastWestWires; + public RouteNodeGraph(Design design, RWRouteConfig config) { this(design, config, new HashMap<>()); } @@ -133,6 +137,8 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); BitSet wires = new BitSet(); Tile intTile = device.getArbitraryTileOfType(TileTypeEnum.INT); @@ -140,49 +146,80 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); + BitSet eastWires = new BitSet(); + BitSet westWires = new BitSet(); + eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); + for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { Node baseNode = Node.getNode(intTile, wireIndex); if (baseNode == null) { continue; } - if (baseNode.getIntentCode() != IntentCode.NODE_LOCAL) { - continue; - } - Tile baseTile = baseNode.getTile(); - String wireName = baseNode.getWireName(); - if (isUltraScalePlus) { - if (!wireName.startsWith("INT_NODE_SDQ_") && !wireName.startsWith("SDQNODE_")) { + String baseWireName = baseNode.getWireName(); + IntentCode baseIntentCode = baseNode.getIntentCode(); + if (baseIntentCode == IntentCode.NODE_LOCAL) { + Tile baseTile = baseNode.getTile(); + assert(baseTile.getTileTypeEnum() == intTile.getTileTypeEnum()); + if (isUltraScalePlus) { + if (baseWireName.startsWith("INT_NODE_SDQ_") || baseWireName.startsWith("SDQNODE_")) { + if (baseTile != intTile) { + if (baseWireName.endsWith("_FT0")) { + assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else { + assert(baseWireName.endsWith("_FT1")); + assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); + } + } + wires.set(baseNode.getWireIndex()); + continue; + } + } else { + assert(isUltraScale); + + if (baseWireName.startsWith("INT_NODE_SINGLE_DOUBLE_") || baseWireName.startsWith("SDND") || + baseWireName.startsWith("INT_NODE_QUAD_LONG") || baseWireName.startsWith("QLND")) { + if (baseTile != intTile) { + if (baseWireName.endsWith("_FTN")) { + assert (baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else { + assert (baseWireName.endsWith("_FTS")); + assert (baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); + } + } + } + wires.set(baseNode.getWireIndex()); continue; } - if (baseTile != intTile) { - if (wireName.endsWith("_FT0")) { - assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else if (baseIntentCode != IntentCode.NODE_PINFEED && baseIntentCode != IntentCode.NODE_PINBOUNCE) { + continue; + } + + Matcher m = eastWestPattern.matcher(baseWireName); + if (m.matches()) { + if (m.group(4) != null) { + if (m.group(4).equals("E")) { + eastWires.set(baseNode.getWireIndex()); } else { - assert(wireName.endsWith("_FT1")); - assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); + assert(m.group(4).equals("W")); + westWires.set(baseNode.getWireIndex()); } - } - } else { - assert(isUltraScale); - - if (!wireName.startsWith("INT_NODE_SINGLE_DOUBLE_") && !wireName.startsWith("SDND") && - !wireName.startsWith("INT_NODE_QUAD_LONG") && !wireName.startsWith("QLND")) { - continue; - } - if (baseTile != intTile) { - if (wireName.endsWith("_FTN")) { - assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else if (m.group(5) != null) { + int i = Integer.valueOf(m.group(5)); + if (i < 32) { + eastWires.set(baseNode.getWireIndex()); } else { - assert(wireName.endsWith("_FTS")); - assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); + assert(i < 64); + westWires.set(baseNode.getWireIndex()); } } } - wires.set(baseNode.getWireIndex()); } } else { ultraScaleNonLocalWires = null; + eastWestWires = null; } if (lutRoutethru) { @@ -429,7 +466,7 @@ protected boolean isExcluded(RouteNode parent, Node child) { // PINFEEDs can lead to a site pin, or into a Laguna tile RouteNode childRnode = getNode(child); if (childRnode != null) { - assert(childRnode.getType() == RouteNodeType.EXCLUSIVE_SINK || + assert(childRnode.getType().isExclusiveSink() || childRnode.getType() == RouteNodeType.LAGUNA_PINFEED || (lutRoutethru && childRnode.getType() == RouteNodeType.LOCAL)); } else if (!lutRoutethru) { @@ -557,25 +594,34 @@ public int averageChildren() { public boolean isAccessible(RouteNode childRnode, Connection connection) { // Only consider LOCAL nodes when: // (a) considering LUT routethrus - if (childRnode.getType() != RouteNodeType.LOCAL || lutRoutethru) { + if (!childRnode.getType().isLocal() || lutRoutethru) { return true; } - // (b) in the sink tile + // (b) on the same side as the sink + RouteNodeType type = childRnode.getType(); + RouteNode sinkRnode = connection.getSinkRnode(); + RouteNodeType sinkType = sinkRnode.getType(); + assert(sinkType.isExclusiveSink()); + if ((type == RouteNodeType.LOCAL_EAST && sinkType != RouteNodeType.EXCLUSIVE_SINK_EAST) || + (type == RouteNodeType.LOCAL_WEST && sinkType != RouteNodeType.EXCLUSIVE_SINK_WEST)) { + return false; + } + + // (c) in the sink tile Tile childTile = childRnode.getTile(); - Tile sinkTile = connection.getSinkRnode().getTile(); + Tile sinkTile = sinkRnode.getTile(); if (childTile == sinkTile) { return true; } - // (c) connection crosses SLR and this is a Laguna column + // (d) connection crosses SLR and this is a Laguna column int childX = childTile.getTileXCoordinate(); if (connection.isCrossSLR() && nextLagunaColumn[childX] == childX) { - return true; } - // (d) when in X as the sink tile, but Y +/- 1 + // (e) when in X as the sink tile, but Y +/- 1 return childX == sinkTile.getTileXCoordinate() && Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 8a64cbeab..2573f0493 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -128,40 +128,53 @@ private static short getEndTileXCoordinate(Node node, RouteNodeType type, short private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph routingGraph) { // NOTE: IntentCode is device-dependent IntentCode ic = node.getIntentCode(); + TileTypeEnum tileTypeEnum = node.getTile().getTileTypeEnum(); switch (ic) { case NODE_LOCAL: { // US/US+ - assert(node.getTile().getTileTypeEnum() == TileTypeEnum.INT); + assert(tileTypeEnum == TileTypeEnum.INT); if (routingGraph != null) { - BitSet bs = routingGraph.ultraScaleNonLocalWires.get(node.getTile().getTileTypeEnum()); + BitSet bs = routingGraph.ultraScaleNonLocalWires.get(tileTypeEnum); if (!bs.get(node.getWireIndex())) { + BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); + if (eastWestWires[0].get(node.getWireIndex())) { + return RouteNodeType.LOCAL_EAST; + } else if (eastWestWires[1].get(node.getWireIndex())) { + return RouteNodeType.LOCAL_WEST; + } return RouteNodeType.LOCAL; } break; } } - case NODE_PINBOUNCE: - return RouteNodeType.LOCAL; - - case NODE_PINFEED: { + case NODE_PINFEED: if (routingGraph != null && routingGraph.lagunaI != null) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); if (bs != null && bs.get(node.getWireIndex())) { return RouteNodeType.LAGUNA_PINFEED; } } + // Fall through + case NODE_PINBOUNCE: + if (routingGraph != null) { + BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); + if (eastWestWires[0].get(node.getWireIndex())) { + return RouteNodeType.LOCAL_EAST; + } + assert (eastWestWires[1].get(node.getWireIndex())); + return RouteNodeType.LOCAL_WEST; + } return RouteNodeType.LOCAL; - } case NODE_LAGUNA_OUTPUT: // UltraScale+ only - assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG); + assert(tileTypeEnum == TileTypeEnum.LAG_LAG); if (node.getWireName().endsWith("_TXOUT")) { return RouteNodeType.LAGUNA_PINFEED; } break; case NODE_LAGUNA_DATA: // UltraScale+ only - assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG); + assert(tileTypeEnum == TileTypeEnum.LAG_LAG); if (node.getTile() != endTile) { return RouteNodeType.SUPER_LONG_LINE; } @@ -170,7 +183,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou break; case INTENT_DEFAULT: - if (node.getTile().getTileTypeEnum() == TileTypeEnum.LAGUNA_TILE) { // UltraScale only + if (tileTypeEnum == TileTypeEnum.LAGUNA_TILE) { // UltraScale only String wireName = node.getWireName(); if (wireName.startsWith("UBUMP")) { assert(node.getTile() != endTile); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index 2510b4701..e974e281e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -28,7 +28,8 @@ public enum RouteNodeType { EXCLUSIVE_SOURCE, - EXCLUSIVE_SINK, + EXCLUSIVE_SINK_EAST, + EXCLUSIVE_SINK_WEST, /** * Denotes {@link RouteNode} objects that correspond to a super long line {@link Node}, @@ -44,5 +45,15 @@ public enum RouteNodeType { NON_LOCAL, - LOCAL + LOCAL, + LOCAL_EAST, + LOCAL_WEST; + + public boolean isExclusiveSink() { + return this == EXCLUSIVE_SINK_EAST || this == EXCLUSIVE_SINK_WEST; + } + + public boolean isLocal() { + return this == LOCAL || this == LOCAL_EAST || this == LOCAL_WEST; + } } diff --git a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java index c51cc6789..3b7b94361 100644 --- a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java +++ b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java @@ -24,6 +24,7 @@ package com.xilinx.rapidwright.rwroute; +import java.util.BitSet; import java.util.HashMap; import java.util.Map; @@ -128,7 +129,17 @@ private NetWrapper createNetWrapper(Net net) { if (sinkINTNode == null) { connection.setDirect(true); } else { - connection.setSinkRnode(routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK)); + BitSet[] eastWestWires = routingGraph.eastWestWires.get(sinkINTNode.getTile().getTileTypeEnum()); + RouteNode sinkRnode; + if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { + sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_EAST); + } else { + assert(eastWestWires[1].get(sinkINTNode.getWireIndex())); + sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); + } + connection.setSinkRnode(sinkRnode); if (sourceINTNode == null) { sourceINTNode = RouterHelper.projectOutputPinToINTNode(source); } From 6229dbe3e3d92f869bff17741d3ba5d050446af8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 16:30:53 -0800 Subject: [PATCH 23/64] Re-add EXCLUSIVE_SINK (non-sided) for CTRL sinks Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 7 +++++-- src/com/xilinx/rapidwright/rwroute/RouteNode.java | 3 +++ .../xilinx/rapidwright/rwroute/RouteNodeGraph.java | 6 ++++-- .../xilinx/rapidwright/rwroute/RouteNodeInfo.java | 5 +++-- .../xilinx/rapidwright/rwroute/RouteNodeType.java | 3 ++- .../rwroute/TimingAndWirelengthReport.java | 12 +----------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 0a38dd27e..ba112f090 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -606,10 +606,12 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_EAST); - } else { - assert(eastWestWires[1].get(sinkINTNode.getWireIndex())); + } else if (eastWestWires[1].get(sinkINTNode.getWireIndex())) { sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); + } else { + sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK); } connection.setSinkRnode(sinkRnode); @@ -1835,6 +1837,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } break; + case EXCLUSIVE_SINK: case EXCLUSIVE_SINK_EAST: case EXCLUSIVE_SINK_WEST: if (!isAccessibleSink(childRNode, connection)) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index d993496aa..56df8a046 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -123,6 +123,9 @@ private void setBaseCost(Series series) { assert(length == 0 || (length <= 3 && series == Series.Versal)); break; + case EXCLUSIVE_SINK: + assert(length == 0); + break; case EXCLUSIVE_SINK_EAST: case EXCLUSIVE_SINK_WEST: assert(length == 0 || diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 289c99f51..01b55831c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -137,7 +137,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); BitSet wires = new BitSet(); @@ -604,7 +604,9 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { RouteNodeType sinkType = sinkRnode.getType(); assert(sinkType.isExclusiveSink()); if ((type == RouteNodeType.LOCAL_EAST && sinkType != RouteNodeType.EXCLUSIVE_SINK_EAST) || - (type == RouteNodeType.LOCAL_WEST && sinkType != RouteNodeType.EXCLUSIVE_SINK_WEST)) { + (type == RouteNodeType.LOCAL_WEST && sinkType != RouteNodeType.EXCLUSIVE_SINK_WEST) || + // Sinks without a side (e.g. CTRL) can only be approached from LOCAL nodes also without a side + (sinkType == RouteNodeType.EXCLUSIVE_SINK && type != RouteNodeType.LOCAL)) { return false; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 2573f0493..ffd11765e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -160,9 +160,10 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); if (eastWestWires[0].get(node.getWireIndex())) { return RouteNodeType.LOCAL_EAST; + } else if (eastWestWires[1].get(node.getWireIndex())) { + return RouteNodeType.LOCAL_WEST; } - assert (eastWestWires[1].get(node.getWireIndex())); - return RouteNodeType.LOCAL_WEST; + assert(node.getWireName().startsWith("CTRL_")); } return RouteNodeType.LOCAL; diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index e974e281e..0c024bb0b 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -28,6 +28,7 @@ public enum RouteNodeType { EXCLUSIVE_SOURCE, + EXCLUSIVE_SINK, EXCLUSIVE_SINK_EAST, EXCLUSIVE_SINK_WEST, @@ -50,7 +51,7 @@ public enum RouteNodeType { LOCAL_WEST; public boolean isExclusiveSink() { - return this == EXCLUSIVE_SINK_EAST || this == EXCLUSIVE_SINK_WEST; + return this == EXCLUSIVE_SINK || this == EXCLUSIVE_SINK_EAST || this == EXCLUSIVE_SINK_WEST; } public boolean isLocal() { diff --git a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java index 3b7b94361..0ff666a2f 100644 --- a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java +++ b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java @@ -129,17 +129,7 @@ private NetWrapper createNetWrapper(Net net) { if (sinkINTNode == null) { connection.setDirect(true); } else { - BitSet[] eastWestWires = routingGraph.eastWestWires.get(sinkINTNode.getTile().getTileTypeEnum()); - RouteNode sinkRnode; - if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { - sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_EAST); - } else { - assert(eastWestWires[1].get(sinkINTNode.getWireIndex())); - sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); - } - connection.setSinkRnode(sinkRnode); + connection.setSinkRnode(routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK)); if (sourceINTNode == null) { sourceINTNode = RouterHelper.projectOutputPinToINTNode(source); } From 74fdf59e608fbffa91187ec3d841b332fb6456fe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 16:40:15 -0800 Subject: [PATCH 24/64] Support UltraScale Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 01b55831c..2275eb334 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -208,13 +208,15 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map= 64 && i < 96))) { eastWires.set(baseNode.getWireIndex()); } else { - assert(i < 64); + assert(i < 64 || (isUltraScale && (i >= 96 && i < 128))); westWires.set(baseNode.getWireIndex()); } } + } else { + assert(baseWireName.matches("CTRL_[EW](_B)?\\d+|INT_NODE_GLOBAL_\\d+_INT_OUT[01]?")); } } } else { From a1dca3737ac739bc44c62f656760d2f1679df48c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 16:40:27 -0800 Subject: [PATCH 25/64] Print Signed-off-by: Eddie Hung --- test/src/com/xilinx/rapidwright/device/TestNode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 2b0d6bef1..8075a6cf7 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -148,6 +148,7 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str intentCodes.add(node.getIntentCode()); } System.out.println("Initial queue.size() = " + queue.size()); + System.out.println("Initial queue = " + queue); System.out.println("Intent codes = " + intentCodes); // Print out the prefixes of nodes that are immediately uphill of these wire prefixes From 977b0689aa0a726c4add8ffaf9017f3ead3f598a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 17:16:08 -0800 Subject: [PATCH 26/64] Expand testNodeReachabilityVersal Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/device/TestNode.java | 101 ++++++++++++------ 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 8075a6cf7..175172258 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -159,9 +159,9 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") .map(s -> s.replaceFirst("^((BOUNCE|BYPASS|CTRL|INODE(_[12])?|IMUX|SDQNODE)_([EW]_?)?)[^ ]+", "$1")) .map(s -> s.replaceFirst("(INT_NODE_(GLOBAL|SDQ|SINGLE_DOUBLE|QUAD_LONG)_)[^ ]+", "$1")) - .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01])_INT_OUT[01]?", "$1<0-31>") + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01])_INT_OUT[01]", "$1<0-31>") : s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_INT_OUT", "$1<0-31,64-95>")) - .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3])_INT_OUT[01]?", "$1<32-63>") + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3])_INT_OUT[01]", "$1<32-63>") : s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_INT_OUT", "$1<32-63,96-127>")) .map(s -> s.replaceFirst( // UltraScale+ @@ -179,16 +179,16 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") .map(s -> s.replaceFirst("^((BOUNCE|BYPASS|CTRL|INODE(_[12])?|IMUX|SDQNODE)_([EW]_?)?)[^ ]+", "$1")) .map(s -> s.replaceFirst("(INT_NODE_(GLOBAL|SDQ|SINGLE_DOUBLE|QUAD_LONG)_)[^ ]+", "$1")) - .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01])_INT_OUT[01]?", "$1<0-31>") + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01])_INT_OUT[01]", "$1<0-31>") : s.replaceFirst("(INT_NODE_IMUX_)([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_INT_OUT", "$1<0-31,64-95>")) - .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3])_INT_OUT[01]?", "$1<32-63>") + .map(s -> ultraScalePlus ? s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3])_INT_OUT[01]", "$1<32-63>") : s.replaceFirst("(INT_NODE_IMUX_)(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_INT_OUT", "$1<32-63,96-127>")) .map(s -> s.replaceFirst( // UltraScale+ ultraScalePlus ? "((CLE_CLE_[LM]_SITE_0|INT_INT_SDQ|(NN|EE|SS|WW)(1|2|4|12)(_[EW])?)_)[^\\(]+" // UltraScale - : "((CLE_CLE_[LM]_SITE_0|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)(_[EW])?|QLND(NW|S[EW])|SDND[NS]W)_)[^\\(]+", - "$1 ")) + : "((CLE_CLE_[LM]_SITE_0|INT_INT_SINGLE|(NN|SS)(1|2|4|5|12|16)|(EE|WW)(1|2|4|12)(_[EW])?|QLND(NW|S[EW])|SDND[NS]W)_)[^ ]+", + "$1")) .distinct() .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); @@ -228,30 +228,36 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str @ParameterizedTest @CsvSource({ - "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,true", - "xcvp1002,INT_X38Y220,NODE_INODE,true", - "xcvp1002,INT_X38Y220,NODE_IMUX,true", - "xcvp1002,INT_X38Y220,NODE_SDQNODE,false", - "xcvp1002,INT_X38Y220,NODE_HSINGLE,false", - "xcvp1002,INT_X38Y220,NODE_VSINGLE,false", - "xcvp1002,INT_X38Y220,NODE_HDOUBLE,false", - "xcvp1002,INT_X38Y220,NODE_VDOUBLE,false", - "xcvp1002,INT_X38Y220,NODE_HQUAD,false", - "xcvp1002,INT_X38Y220,NODE_VQUAD,false", - "xcvp1002,INT_X38Y220,NODE_HLONG6,false", - "xcvp1002,INT_X38Y220,NODE_HLONG10,false", - "xcvp1002,INT_X38Y220,NODE_VLONG7,false", - "xcvp1002,INT_X38Y220,NODE_VLONG12,false", - "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_BNODE,true", - "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CNODE,true", - "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CTRL,true", - "xcvp1002,CLE_W_CORE_X38Y220,NODE_PINFEED,true", - "xcvp1002,CLE_E_CORE_X38Y220,NODE_CLE_OUTPUT,false", - "xcvp1002,CLE_W_CORE_X38Y220,NODE_CLE_OUTPUT,false", - "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_CNODE,true", - "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_BNODE,true", + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_E.*,true", + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_W.*,true", + "xcvp1002,INT_X38Y220,NODE_INODE,INT_NODE_IMUX_ATOM_([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_.*,true", + "xcvp1002,INT_X38Y220,NODE_INODE,INT_NODE_IMUX_ATOM_(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_.*,true", + "xcvp1002,INT_X38Y220,NODE_IMUX,IMUX_B_E.*,true", + "xcvp1002,INT_X38Y220,NODE_IMUX,IMUX_B_W.*,true", + "xcvp1002,INT_X38Y220,NODE_SDQNODE,,false", + "xcvp1002,INT_X38Y220,NODE_HSINGLE,,false", + "xcvp1002,INT_X38Y220,NODE_VSINGLE,,false", + "xcvp1002,INT_X38Y220,NODE_HDOUBLE,,false", + "xcvp1002,INT_X38Y220,NODE_VDOUBLE,,false", + "xcvp1002,INT_X38Y220,NODE_HQUAD,,false", + "xcvp1002,INT_X38Y220,NODE_VQUAD,,false", + "xcvp1002,INT_X38Y220,NODE_HLONG6,,false", + "xcvp1002,INT_X38Y220,NODE_HLONG10,,false", + "xcvp1002,INT_X38Y220,NODE_VLONG7,,false", + "xcvp1002,INT_X38Y220,NODE_VLONG12,,false", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_BNODE,BNODE_OUTS_E.*,true", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_BNODE,BNODE_OUTS_W.*,true", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CNODE,CNODE_OUTS_E.*,true", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CNODE,CNODE_OUTS_W.*,true", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CTRL,CTRL_L_B.*,true", + "xcvp1002,CLE_BC_CORE_X37Y220,NODE_CLE_CTRL,CTRL_R_B.*,true", + "xcvp1002,CLE_W_CORE_X38Y220,NODE_PINFEED,,true", + "xcvp1002,CLE_E_CORE_X38Y220,NODE_CLE_OUTPUT,,false", + "xcvp1002,CLE_W_CORE_X38Y220,NODE_CLE_OUTPUT,,false", + "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_CNODE,,true", + "xcvp1002,INTF_ROCF_TR_TILE_X39Y153,NODE_INTF_BNODE,,true", }) - public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName, boolean local) { + public void testNodeReachabilityVersal(String partName, String tileName, String intentCodeName, String wireNameRegex, boolean local) { Device device = Device.getDevice(partName); Tile baseTile = device.getTile(tileName); IntentCode baseIntentCode = IntentCode.valueOf(intentCodeName); @@ -260,21 +266,48 @@ public void testNodeReachabilityVersal(String partName, String tileName, String if (baseTile.getWireIntentCode(wireIdx) != baseIntentCode) { continue; } - queue.add(Node.getNode(baseTile, wireIdx)); + + Node node = Node.getNode(baseTile, wireIdx); + if (wireNameRegex != null && !node.getWireName().matches(wireNameRegex)) { + continue; + } + queue.add(node); } System.out.println("Initial queue.size() = " + queue.size()); System.out.println("Initial queue = " + queue); - // Print out the intent code of nodes that are immediately uphill of this intent code + // Print out the prefixes of nodes that are immediately uphill of these wire prefixes + // (i.e. "BOUNCE_E_0_FT1" -> "BOUNCE_") System.out.println("Immediately uphill:"); - queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream).map(Node::getIntentCode) + boolean ultraScalePlus = partName.endsWith("p"); + queue.stream().map(Node::getAllUphillNodes).flatMap(List::stream) + .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") + .map(s -> s.replaceFirst("^((BOUNCE|IMUX_B)_[EW])[^ ]+", "$1")) + .map(s -> s.replaceFirst("^(CTRL_[LR]_)B\\d+", "$1")) + .map(s -> s.replaceFirst("(INT_NODE_SDQ_|INT_SDQ_RED_ATOM_)[^ ]+", "$1")) + .map(s -> s.replaceFirst("(INT_NODE_IMUX_ATOM_)([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_INT_OUT[01]", "$1<0-31,64-95>")) + .map(s -> s.replaceFirst("(INT_NODE_IMUX_ATOM_)(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_INT_OUT[01]", "$1<32-63,96-127>")) + .map(s -> s.replaceFirst("([BC]NODE_OUTS_[EW])\\d+", "$1")) + .map(s -> s.replaceFirst("((CLE_SLICE[LM]_TOP_[01]|OUT_[NESW]NODE|(NN|EE|SS|WW)(1|2|4|6|7|10|12)(_[EW])?)_)[^ ]+", "$1")) + .map(s -> s.replaceFirst("(CLK_LEAF_SITES_)\\d+_O", "$1")) + .map(s -> s.replaceFirst("(VCC_WIRE)\\d+", "$1")) .distinct() .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); - // Print out the intent code of nodes that are immediately downhill of this intent code + // Print out the prefixes of nodes that are immediately downhill of these wire prefixes System.out.println("Immediately downhill:"); - queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream).map(Node::getIntentCode) + queue.stream().map(Node::getAllDownhillNodes).flatMap(List::stream) + .map(n -> n.getWireName() + " (" + n.getIntentCode() + ")") + .map(s -> s.replaceFirst("^((BOUNCE|IMUX_B)_[EW])[^ ]+", "$1")) + .map(s -> s.replaceFirst("^(CTRL_[LR]_)B\\d+", "$1")) + .map(s -> s.replaceFirst("(INT_NODE_SDQ_|INT_SDQ_RED_ATOM_)[^ ]+", "$1")) + .map(s -> s.replaceFirst("(INT_NODE_IMUX_ATOM_)([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_INT_OUT[01]", "$1<0-31,64-95>")) + .map(s -> s.replaceFirst("(INT_NODE_IMUX_ATOM_)(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_INT_OUT[01]", "$1<32-63,96-127>")) + .map(s -> s.replaceFirst("([BC]NODE_OUTS_[EW])\\d+", "$1")) + .map(s -> s.replaceFirst("((CLE_SLICE[LM]_TOP_[01]|OUT_[NESW]NODE|(NN|EE|SS|WW)(1|2|4|6|7|10|12)(_[EW])?)_)[^ ]+", "$1")) + .map(s -> s.replaceFirst("(IF_INT_BNODE_OUTS)\\d+", "$1")) + .map(s -> s.replaceFirst("(INTF_IRI_QUADRANT_(GREEN|RED))_\\d+_[^ ]+", "$1")) .distinct() .sorted() .forEachOrdered(s -> System.out.println("\t" + s)); From 967890dc25721678ef77559e5789dc7ab40b4a5e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 17:20:50 -0800 Subject: [PATCH 27/64] Do not error out for Versal Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 162 ++++++++++-------- .../rapidwright/rwroute/RouteNodeInfo.java | 7 +- 2 files changed, 92 insertions(+), 77 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 2275eb334..5adf3ad36 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -101,7 +101,7 @@ public class RouteNodeGraph { protected final boolean lutRoutethru; /** Map indicating the wire indices that have a local intent code, but is what RWRoute considers to be non-local */ - protected final Map ultraScaleNonLocalWires; + protected final Map ultraScalesNonLocalWires; protected final Map eastWestWires; @@ -136,92 +136,104 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); + BitSet eastWires = new BitSet(); + BitSet westWires = new BitSet(); + eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); + + BitSet wires = new BitSet(); if (isUltraScale || isUltraScalePlus) { - Pattern eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE)_([EW]))|INT_NODE_IMUX_(\\d+)_).*"); - - ultraScaleNonLocalWires = new EnumMap<>(TileTypeEnum.class); - BitSet wires = new BitSet(); - Tile intTile = device.getArbitraryTileOfType(TileTypeEnum.INT); - // Device.getArbitraryTileOfType() typically gives you the North-Western-most - // tile (with minimum X, maximum Y). Analyze the tile just below that. - intTile = intTile.getTileXYNeighbor(0, -1); - ultraScaleNonLocalWires.put(intTile.getTileTypeEnum(), wires); - - eastWestWires = new EnumMap<>(TileTypeEnum.class); - BitSet eastWires = new BitSet(); - BitSet westWires = new BitSet(); - eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); - - for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { - Node baseNode = Node.getNode(intTile, wireIndex); - if (baseNode == null) { - continue; - } + ultraScalesNonLocalWires = new EnumMap<>(TileTypeEnum.class); + ultraScalesNonLocalWires.put(intTile.getTileTypeEnum(), wires); + eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE)_([EW]))|INT_NODE_IMUX_(\\d+)_).*"); + } else { + assert(series == Series.Versal); + ultraScalesNonLocalWires = null; - String baseWireName = baseNode.getWireName(); - IntentCode baseIntentCode = baseNode.getIntentCode(); - if (baseIntentCode == IntentCode.NODE_LOCAL) { - Tile baseTile = baseNode.getTile(); - assert(baseTile.getTileTypeEnum() == intTile.getTileTypeEnum()); - if (isUltraScalePlus) { - if (baseWireName.startsWith("INT_NODE_SDQ_") || baseWireName.startsWith("SDQNODE_")) { - if (baseTile != intTile) { - if (baseWireName.endsWith("_FT0")) { - assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); - } else { - assert(baseWireName.endsWith("_FT1")); - assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); - } - } - wires.set(baseNode.getWireIndex()); - continue; - } - } else { - assert(isUltraScale); - - if (baseWireName.startsWith("INT_NODE_SINGLE_DOUBLE_") || baseWireName.startsWith("SDND") || - baseWireName.startsWith("INT_NODE_QUAD_LONG") || baseWireName.startsWith("QLND")) { - if (baseTile != intTile) { - if (baseWireName.endsWith("_FTN")) { - assert (baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); - } else { - assert (baseWireName.endsWith("_FTS")); - assert (baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); - } + // FIXME: + eastWestPattern = null; + eastWestWires.put(TileTypeEnum.CLE_BC_CORE, new BitSet[]{eastWires, westWires}); + } + + for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { + Node baseNode = Node.getNode(intTile, wireIndex); + if (baseNode == null) { + continue; + } + + String baseWireName = baseNode.getWireName(); + IntentCode baseIntentCode = baseNode.getIntentCode(); + if (baseIntentCode == IntentCode.NODE_LOCAL) { + Tile baseTile = baseNode.getTile(); + assert(baseTile.getTileTypeEnum() == intTile.getTileTypeEnum()); + if (isUltraScalePlus) { + if (baseWireName.startsWith("INT_NODE_SDQ_") || baseWireName.startsWith("SDQNODE_")) { + if (baseTile != intTile) { + if (baseWireName.endsWith("_FT0")) { + assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else { + assert(baseWireName.endsWith("_FT1")); + assert(baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); } } wires.set(baseNode.getWireIndex()); continue; } - } else if (baseIntentCode != IntentCode.NODE_PINFEED && baseIntentCode != IntentCode.NODE_PINBOUNCE) { + } else if (isUltraScale) { + if (baseWireName.startsWith("INT_NODE_SINGLE_DOUBLE_") || baseWireName.startsWith("SDND") || + baseWireName.startsWith("INT_NODE_QUAD_LONG") || baseWireName.startsWith("QLND")) { + if (baseTile != intTile) { + if (baseWireName.endsWith("_FTN")) { + assert (baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() - 1); + } else { + assert (baseWireName.endsWith("_FTS")); + assert (baseTile.getTileYCoordinate() == intTile.getTileYCoordinate() + 1); + } + } + } + wires.set(baseNode.getWireIndex()); continue; } + } else if (baseIntentCode != IntentCode.NODE_PINFEED && baseIntentCode != IntentCode.NODE_PINBOUNCE) { + continue; + } - Matcher m = eastWestPattern.matcher(baseWireName); - if (m.matches()) { - if (m.group(4) != null) { - if (m.group(4).equals("E")) { - eastWires.set(baseNode.getWireIndex()); - } else { - assert(m.group(4).equals("W")); - westWires.set(baseNode.getWireIndex()); - } - } else if (m.group(5) != null) { - int i = Integer.valueOf(m.group(5)); - if (i < 32 || (isUltraScale && (i >= 64 && i < 96))) { - eastWires.set(baseNode.getWireIndex()); - } else { - assert(i < 64 || (isUltraScale && (i >= 96 && i < 128))); - westWires.set(baseNode.getWireIndex()); - } + if (eastWestPattern == null) { + // FIXME: + assert(series == Series.Versal); + continue; + } + + Matcher m = eastWestPattern.matcher(baseWireName); + if (m.matches()) { + if (m.group(4) != null) { + if (m.group(4).equals("E")) { + eastWires.set(baseNode.getWireIndex()); + } else { + assert(m.group(4).equals("W")); + westWires.set(baseNode.getWireIndex()); + } + } else if (m.group(5) != null) { + int i = Integer.valueOf(m.group(5)); + if (i < 32 || (isUltraScale && (i >= 64 && i < 96))) { + eastWires.set(baseNode.getWireIndex()); + } else { + assert(i < 64 || (isUltraScale && (i >= 96 && i < 128))); + westWires.set(baseNode.getWireIndex()); } - } else { - assert(baseWireName.matches("CTRL_[EW](_B)?\\d+|INT_NODE_GLOBAL_\\d+_INT_OUT[01]?")); } + } else { + assert(baseWireName.matches("CTRL_[EW](_B)?\\d+|INT_NODE_GLOBAL_\\d+_INT_OUT[01]?") + // FIXME: + || series == Series.Versal); } - } else { - ultraScaleNonLocalWires = null; - eastWestWires = null; } if (lutRoutethru) { @@ -233,7 +245,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Thu, 7 Nov 2024 18:33:44 -0800 Subject: [PATCH 28/64] Fix failing assertions Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNode.java | 2 -- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 56df8a046..8f8f78d12 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -124,8 +124,6 @@ private void setBaseCost(Series series) { (length <= 3 && series == Series.Versal)); break; case EXCLUSIVE_SINK: - assert(length == 0); - break; case EXCLUSIVE_SINK_EAST: case EXCLUSIVE_SINK_WEST: assert(length == 0 || diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 5adf3ad36..2ba58dbe2 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -482,7 +482,7 @@ protected boolean isExcluded(RouteNode parent, Node child) { if (childRnode != null) { assert(childRnode.getType().isExclusiveSink() || childRnode.getType() == RouteNodeType.LAGUNA_PINFEED || - (lutRoutethru && childRnode.getType() == RouteNodeType.LOCAL)); + (lutRoutethru && childRnode.getType().isLocal())); } else if (!lutRoutethru) { // child does not already exist in our routing graph, meaning it's not a used site pin // in our design, but it could be a LAGUNA_I From 95bba953317fb90a8ddc29f4772605c6772b6ce7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 18:35:07 -0800 Subject: [PATCH 29/64] Remove unused import Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java index 0ff666a2f..c51cc6789 100644 --- a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java +++ b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java @@ -24,7 +24,6 @@ package com.xilinx.rapidwright.rwroute; -import java.util.BitSet; import java.util.HashMap; import java.util.Map; From 3a25ead24a7d733af9114d61e799cd40ba5242a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 19:28:17 -0800 Subject: [PATCH 30/64] Fix another typo Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index ba112f090..9fa089202 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -620,6 +620,8 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { int numberOfSwappablePins = (lutPinSwapping && sink.isLUTInputPin()) ? LUTTools.MAX_LUT_SIZE : 0; if (numberOfSwappablePins > 0) { + assert(sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK_EAST || sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK_WEST); + for (Cell cell : DesignTools.getConnectedCells(sink)) { BEL bel = cell.getBEL(); assert(bel.isLUT()); @@ -661,13 +663,7 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { if (routingGraph.isPreserved(node)) { continue; } - RouteNode altSinkRnode; - if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { - altSinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); - } else { - assert(eastWestWires[1].get(sinkINTNode.getWireIndex())); - altSinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); - } + RouteNode altSinkRnode = routingGraph.getOrCreate(node, sinkRnode.getType()); assert(altSinkRnode.getType().isExclusiveSink()); connection.addAltSinkRnode(altSinkRnode); } From 0d60f48d373746aaadfd4e354c27e28d28e2e9b5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 20:13:16 -0800 Subject: [PATCH 31/64] Fix SLR crossings Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 2ba58dbe2..312eb276f 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -612,9 +612,18 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return true; } - // (b) on the same side as the sink - RouteNodeType type = childRnode.getType(); + // (b) needs to cross an SLR and this is a Laguna column + Tile childTile = childRnode.getTile(); RouteNode sinkRnode = connection.getSinkRnode(); + int childX = childTile.getTileXCoordinate(); + if (connection.isCrossSLR() && + childRnode.getSLRIndex(this) != sinkRnode.getSLRIndex(this) && + nextLagunaColumn[childX] == childX) { + return true; + } + + // (c) on the same side as the sink + RouteNodeType type = childRnode.getType(); RouteNodeType sinkType = sinkRnode.getType(); assert(sinkType.isExclusiveSink()); if ((type == RouteNodeType.LOCAL_EAST && sinkType != RouteNodeType.EXCLUSIVE_SINK_EAST) || @@ -624,20 +633,13 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return false; } - // (c) in the sink tile - Tile childTile = childRnode.getTile(); + // (d) in the sink tile Tile sinkTile = sinkRnode.getTile(); if (childTile == sinkTile) { return true; } - // (d) connection crosses SLR and this is a Laguna column - int childX = childTile.getTileXCoordinate(); - if (connection.isCrossSLR() && nextLagunaColumn[childX] == childX) { - return true; - } - - // (e) when in X as the sink tile, but Y +/- 1 + // (e) when in same X as the sink tile, but Y +/- 1 return childX == sinkTile.getTileXCoordinate() && Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; } From d4e0ea573da63c5af2fb2c72174020afe92631a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 20:18:34 -0800 Subject: [PATCH 32/64] More Versal fixes Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 7 ++++--- .../xilinx/rapidwright/rwroute/RouteNodeGraph.java | 11 ++++++----- src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 9fa089202..ed4541deb 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -601,12 +601,13 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { } indirectConnections.add(connection); - BitSet[] eastWestWires = routingGraph.eastWestWires.get(sinkINTNode.getTile().getTileTypeEnum()); + BitSet[] eastWestWires = (routingGraph.eastWestWires == null) ? null : + routingGraph.eastWestWires.get(sinkINTNode.getTile().getTileTypeEnum()); RouteNode sinkRnode; - if (eastWestWires[0].get(sinkINTNode.getWireIndex())) { + if (eastWestWires != null && eastWestWires[0].get(sinkINTNode.getWireIndex())) { sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_EAST); - } else if (eastWestWires[1].get(sinkINTNode.getWireIndex())) { + } else if (eastWestWires != null && eastWestWires[1].get(sinkINTNode.getWireIndex())) { sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); } else { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 312eb276f..8b0ca7eab 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -104,6 +104,7 @@ public class RouteNodeGraph { protected final Map ultraScalesNonLocalWires; protected final Map eastWestWires; + protected static final BitSet EMPTY_BITSET = new BitSet(0); public RouteNodeGraph(Design design, RWRouteConfig config) { this(design, config, new HashMap<>()); @@ -143,23 +144,23 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); + BitSet wires = new BitSet(); BitSet eastWires = new BitSet(); BitSet westWires = new BitSet(); - eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); - - BitSet wires = new BitSet(); if (isUltraScale || isUltraScalePlus) { ultraScalesNonLocalWires = new EnumMap<>(TileTypeEnum.class); ultraScalesNonLocalWires.put(intTile.getTileTypeEnum(), wires); eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE)_([EW]))|INT_NODE_IMUX_(\\d+)_).*"); + + eastWestWires = new EnumMap<>(TileTypeEnum.class); + eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); } else { assert(series == Series.Versal); ultraScalesNonLocalWires = null; // FIXME: eastWestPattern = null; - eastWestWires.put(TileTypeEnum.CLE_BC_CORE, new BitSet[]{eastWires, westWires}); + eastWestWires = null; } for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 10d9335b1..2387dd745 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -157,7 +157,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } // Fall through case NODE_PINBOUNCE: - if (routingGraph != null) { + if (routingGraph != null && routingGraph.eastWestWires != null) { BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); if (eastWestWires[0].get(node.getWireIndex())) { return RouteNodeType.LOCAL_EAST; From 07935a45533e6aac93d867cd30467bc8c585eb9a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 20:43:22 -0800 Subject: [PATCH 33/64] Update testSLRCrossingNonTimingDriven golden values Signed-off-by: Eddie Hung --- test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java b/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java index 071468658..97bb28c56 100644 --- a/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java +++ b/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java @@ -401,7 +401,7 @@ void testSingleConnectionHelper(String partName, // One SLR crossing // (Too) Close "SLICE_X9Y299,SLICE_X9Y300,500", // On Laguna column - "SLICE_X9Y300,SLICE_X9Y299,400", + "SLICE_X9Y300,SLICE_X9Y299,500", "SLICE_X0Y299,SLICE_X0Y300,200", // Far from Laguna column "SLICE_X0Y300,SLICE_X0Y299,200", "SLICE_X53Y299,SLICE_X53Y300,200", // Equidistant from two Laguna columns @@ -422,7 +422,7 @@ void testSingleConnectionHelper(String partName, "SLICE_X0Y430,SLICE_X12Y240,200", // Two SLR crossings - "SLICE_X162Y299,SLICE_X162Y599,200", + "SLICE_X162Y299,SLICE_X162Y599,600", "SLICE_X162Y599,SLICE_X162Y299,100", // Three SLR crossings From bb9db76c150b1dfc832e69cfe6c193980eb39799 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 20:44:01 -0800 Subject: [PATCH 34/64] Tidy up and comments Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 8b0ca7eab..587ed6c3c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -94,17 +94,21 @@ public class RouteNodeGraph { */ protected final Map lagunaI; - /** Map indicating the wire indices corresponding to the [A-H]MUX output */ - protected final Map muxWires; + /** Map indicating (for UltraScale/UltraScale+ only) the wire indices corresponding to the [A-H]MUX output + * to be blocked during LUT routethrus + */ + protected final Map ultraScalesMuxWiresToBlockWhenLutRoutethru; /** Flag for whether LUT routethrus are to be considered */ protected final boolean lutRoutethru; - /** Map indicating the wire indices that have a local intent code, but is what RWRoute considers to be non-local */ + /** Map indicating (for UltraScale/UltraScale+ only) the wire indices that have a local intent code, + * but is what RWRoute will consider to be non-local, e.g. INT_NODE_SDQ_* + */ protected final Map ultraScalesNonLocalWires; + /** Map indicating the wire indices corresponding to the east/west side of interconnect tiles */ protected final Map eastWestWires; - protected static final BitSet EMPTY_BITSET = new BitSet(0); public RouteNodeGraph(Design design, RWRouteConfig config) { this(design, config, new HashMap<>()); @@ -240,7 +244,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); + ultraScalesMuxWiresToBlockWhenLutRoutethru = new EnumMap<>(TileTypeEnum.class); for (TileTypeEnum tileTypeEnum : Utils.getCLBTileTypes()) { Tile clbTile = device.getArbitraryTileOfType(tileTypeEnum); if (clbTile == null) { @@ -258,10 +262,10 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map [A-H]MUX routethrus since Vivado does not support the LUT // being fractured to support more than one routethru net From 9e7d383d0159606e6cb9cc2c13c1702d87956ef7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 7 Nov 2024 21:55:09 -0800 Subject: [PATCH 35/64] Add a few more testcases Signed-off-by: Eddie Hung --- test/src/com/xilinx/rapidwright/rwroute/TestRouterHelper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/src/com/xilinx/rapidwright/rwroute/TestRouterHelper.java b/test/src/com/xilinx/rapidwright/rwroute/TestRouterHelper.java index 41efaf567..9aa04840e 100644 --- a/test/src/com/xilinx/rapidwright/rwroute/TestRouterHelper.java +++ b/test/src/com/xilinx/rapidwright/rwroute/TestRouterHelper.java @@ -60,6 +60,9 @@ public class TestRouterHelper { "xcvu3p,GTYE4_CHANNEL_X0Y12,TXOUTCLK_INT,null", "xcvu3p,IOB_X1Y95,I,INT_INTF_L_IO_X72Y109/LOGIC_OUTS_R23", "xcvu3p,IOB_X1Y80,I,INT_INTF_L_IO_X72Y92/LOGIC_OUTS_R22", + "xcvu3p,IOB_X1Y179,I,INT_INTF_L_CMT_X72Y208/LOGIC_OUTS_R18", + "xcvu3p,IOB_X1Y75,I,INT_INTF_L_CMT_X72Y88/LOGIC_OUTS_R18", + "xcvu3p,IOB_X1Y184,I,INT_INTF_L_IO_X72Y212/LOGIC_OUTS_R22", "xcvu3p,MMCM_X0Y0,LOCKED,INT_INTF_L_IO_X36Y54/LOGIC_OUTS_R0", "xcvp1002,MMCM_X2Y0,LOCKED,BLI_CLE_BOT_CORE_X27Y0/LOGIC_OUTS_D23" }) From 4f43cf54c37f84833c0cd7945465cf4d02dca5e8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Nov 2024 10:06:28 -0800 Subject: [PATCH 36/64] [RWRoute] Non-verbose mode to print out nodes popped Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index ed4541deb..26a652024 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -2160,7 +2160,9 @@ protected void printRoutingStatistics() { printFormattedString("Num iterations:", routeIteration); printFormattedString("Connections routed:", connectionsRouted.get()); printFormattedString("Nodes pushed:", nodesPushed.get()); - printFormattedString("Nodes popped:", nodesPopped.get()); + } + printFormattedString("Nodes popped:", nodesPopped.get()); + if (config.isVerbose()) { System.out.printf("------------------------------------------------------------------------------\n"); } From 7890b5a38c4896bf746e4821967721618aedaad4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Nov 2024 11:06:28 -0800 Subject: [PATCH 37/64] Update comments/asserts Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 5 ++++- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 26a652024..56e7b8b48 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1820,7 +1820,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { break; case NON_LOCAL: // LOCALs cannot connect to NON_LOCALs except via a LUT routethru - assert(rnode.getType() != RouteNodeType.LOCAL || + assert(!rnode.getType().isLocal() || routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED || // FIXME: design.getSeries() == Series.Versal); @@ -1837,6 +1837,9 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { case EXCLUSIVE_SINK: case EXCLUSIVE_SINK_EAST: case EXCLUSIVE_SINK_WEST: + assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_EAST || rnode.getType() == RouteNodeType.LOCAL_EAST); + assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_WEST || rnode.getType() == RouteNodeType.LOCAL_WEST); + assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL); if (!isAccessibleSink(childRNode, connection)) { continue; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 587ed6c3c..646414cc1 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -633,7 +633,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { assert(sinkType.isExclusiveSink()); if ((type == RouteNodeType.LOCAL_EAST && sinkType != RouteNodeType.EXCLUSIVE_SINK_EAST) || (type == RouteNodeType.LOCAL_WEST && sinkType != RouteNodeType.EXCLUSIVE_SINK_WEST) || - // Sinks without a side (e.g. CTRL) can only be approached from LOCAL nodes also without a side + // Sinks without a side (e.g. CTRL) must only be approached from LOCAL nodes also without a side (sinkType == RouteNodeType.EXCLUSIVE_SINK && type != RouteNodeType.LOCAL)) { return false; } From 15b74531ea38367c9e8c3118609c1cdf4ad26f17 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Nov 2024 11:52:07 -0800 Subject: [PATCH 38/64] Clean up RouteNodeGraph.isAccessible() Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 646414cc1..9e2c0844f 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -629,17 +629,35 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { // (c) on the same side as the sink RouteNodeType type = childRnode.getType(); - RouteNodeType sinkType = sinkRnode.getType(); - assert(sinkType.isExclusiveSink()); - if ((type == RouteNodeType.LOCAL_EAST && sinkType != RouteNodeType.EXCLUSIVE_SINK_EAST) || - (type == RouteNodeType.LOCAL_WEST && sinkType != RouteNodeType.EXCLUSIVE_SINK_WEST) || - // Sinks without a side (e.g. CTRL) must only be approached from LOCAL nodes also without a side - (sinkType == RouteNodeType.EXCLUSIVE_SINK && type != RouteNodeType.LOCAL)) { - return false; + Tile sinkTile = sinkRnode.getTile(); + switch (sinkRnode.getType()) { + case EXCLUSIVE_SINK_EAST: + if (type == RouteNodeType.LOCAL_WEST) { + // West wires can never reach an east sink + return false; + } + break; + case EXCLUSIVE_SINK_WEST: + if (type == RouteNodeType.LOCAL_EAST) { + // East wires can never reach a west sink + return false; + } + break; + case EXCLUSIVE_SINK: + // Only both-sided wires (e.g. INT_NODE_GLOBAL_*) can reach a both-sided sink (CTRL_*) + if (type != RouteNodeType.LOCAL) { + return false; + } + if (design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus) { + // This must be a CTRL sink; these can only be accessed from the sink tile rather than Y +/- 1 below + return childTile == sinkTile; + } + break; + default: + throw new RuntimeException("ERROR: Unexpected sink type " + sinkRnode.getType()); } // (d) in the sink tile - Tile sinkTile = sinkRnode.getTile(); if (childTile == sinkTile) { return true; } From b61a199bbc5d899c8aac5a1a651e06e1c03a3d82 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Nov 2024 12:17:40 -0800 Subject: [PATCH 39/64] Fixes for UltraScale Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 9e2c0844f..ece65969e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -154,7 +154,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); ultraScalesNonLocalWires.put(intTile.getTileTypeEnum(), wires); - eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE)_([EW]))|INT_NODE_IMUX_(\\d+)_).*"); + eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE(_[12])?)_([EW]))|INT_NODE_IMUX_(\\d+)_).*"); eastWestWires = new EnumMap<>(TileTypeEnum.class); eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); @@ -202,9 +202,9 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map= 64 && i < 96))) { eastWires.set(baseNode.getWireIndex()); } else { @@ -235,7 +235,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Fri, 8 Nov 2024 12:22:26 -0800 Subject: [PATCH 40/64] Skip another assert for Versal Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 56e7b8b48..9c0b26ea8 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1839,7 +1839,9 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { case EXCLUSIVE_SINK_WEST: assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_EAST || rnode.getType() == RouteNodeType.LOCAL_EAST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_WEST || rnode.getType() == RouteNodeType.LOCAL_WEST); - assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL); + assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL || + // FIXME: + design.getSeries() == Series.Versal); if (!isAccessibleSink(childRNode, connection)) { continue; } From b07f2dbbdf72aab5c3c706bf903024e690ac951a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 08:53:05 -0800 Subject: [PATCH 41/64] Fix Versal assertion Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 42bd6e5b6..7261b2607 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -131,7 +131,8 @@ private void setBaseCost(Series series) { (length == 1 && (series == Series.UltraScalePlus || series == Series.UltraScale) && getIntentCode() == IntentCode.NODE_PINBOUNCE)); break; case LOCAL: - assert(length == 0); + assert(length == 0 || + (series == Series.Versal && EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE).contains(getIntentCode()))); break; case LOCAL_EAST: case LOCAL_WEST: From 90e8d802e26fb484cd529e51c7f3bcfb0b7a5b0a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 09:32:04 -0800 Subject: [PATCH 42/64] Fix assertion Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 21ee7fc54..e89d4472a 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1820,7 +1820,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { break; case NON_LOCAL: // LOCALs cannot connect to NON_LOCALs except via a LUT routethru - assert(rnode.getType() != RouteNodeType.LOCAL || + assert(!rnode.getType().isLocal() || routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED); if (!routingGraph.isAccessible(childRNode, connection)) { From bdf791f6e7d18616ef6d826131a24e438eaf0709 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 13:39:44 -0800 Subject: [PATCH 43/64] Expand test Signed-off-by: Eddie Hung --- test/src/com/xilinx/rapidwright/device/TestNode.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/device/TestNode.java b/test/src/com/xilinx/rapidwright/device/TestNode.java index 175172258..eacef5bd4 100644 --- a/test/src/com/xilinx/rapidwright/device/TestNode.java +++ b/test/src/com/xilinx/rapidwright/device/TestNode.java @@ -228,8 +228,10 @@ public void testNodeReachabilityUltraScale(String partName, String tileName, Str @ParameterizedTest @CsvSource({ - "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_E.*,true", - "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_W.*,true", + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_E([0-9]|1[0-5]),true", + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_E(1[6-9]|2[0-9]|3[01]),true", + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_W([0-9]|1[0-5]),true", + "xcvp1002,INT_X38Y220,NODE_PINBOUNCE,BOUNCE_W(1[6-9]|2[0-9]|3[01]),true", "xcvp1002,INT_X38Y220,NODE_INODE,INT_NODE_IMUX_ATOM_([0-9]|1[0-9]|2[0-9]|3[01]|6[4-9]|7[0-9]|8[0-9]|9[0-5])_.*,true", "xcvp1002,INT_X38Y220,NODE_INODE,INT_NODE_IMUX_ATOM_(3[2-9]|4[0-9]|5[0-9]|6[0-3]|9[6-9]|10[0-9]|11[0-9]|12[0-7])_.*,true", "xcvp1002,INT_X38Y220,NODE_IMUX,IMUX_B_E.*,true", From c1e82749681caa0e8844a6cc15f96c15d0296fd4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 13:41:36 -0800 Subject: [PATCH 44/64] Apply #1098 to Versal too Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 9 +- .../rapidwright/rwroute/RouteNodeGraph.java | 239 ++++++++++-------- .../rapidwright/rwroute/RouteNodeInfo.java | 9 +- 3 files changed, 140 insertions(+), 117 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index e89d4472a..044e2d70f 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1817,6 +1817,12 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { if (!routingGraph.isAccessible(childRNode, connection)) { continue; } + assert(rnode.getType() != RouteNodeType.LOCAL_EAST || childRNode.getType() == RouteNodeType.LOCAL_EAST + // FIXME: + || childRNode.getTile().getName().matches("INTF_[LR]OCF_[TB]R_TILE_.*")); + assert(rnode.getType() != RouteNodeType.LOCAL_WEST || childRNode.getType() == RouteNodeType.LOCAL_WEST + // FIXME: + || childRNode.getTile().getName().matches("INTF_[LR]OCF_[TB]L_TILE_.*")); break; case NON_LOCAL: // LOCALs cannot connect to NON_LOCALs except via a LUT routethru @@ -1838,8 +1844,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_EAST || rnode.getType() == RouteNodeType.LOCAL_EAST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_WEST || rnode.getType() == RouteNodeType.LOCAL_WEST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL || - // FIXME: - design.getSeries() == Series.Versal); + (routingGraph.isVersal && rnode.getIntentCode() == IntentCode.NODE_CLE_BNODE)); if (!isAccessibleSink(childRNode, connection)) { continue; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 8fbb0046b..9cc826d18 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -145,30 +145,33 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); BitSet wires = new BitSet(); - BitSet eastWires = new BitSet(); - BitSet westWires = new BitSet(); if (isUltraScale || isUltraScalePlus) { + intTile = device.getArbitraryTileOfType(TileTypeEnum.INT); + // Device.getArbitraryTileOfType() typically gives you the North-Western-most + // tile (with minimum X, maximum Y). Analyze the tile just below that. + intTile = intTile.getTileXYNeighbor(0, -1); + ultraScalesNonLocalWires = new EnumMap<>(TileTypeEnum.class); ultraScalesNonLocalWires.put(intTile.getTileTypeEnum(), wires); - eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE(_[12])?)_([EW]))|INT_NODE_IMUX_(\\d+)_).*"); - eastWestWires = new EnumMap<>(TileTypeEnum.class); - eastWestWires.put(intTile.getTileTypeEnum(), new BitSet[]{eastWires, westWires}); + eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE(_[12])?)_(?[EW]))|INT_NODE_IMUX_(?\\d+)_).*"); } else { - assert(series == Series.Versal); + assert(isVersal); + + // Find an INT tile adjacent to a CLE_BC_CORE tile since Versal devices may contain AIEs on their northern edge + Tile bcCoreTile = device.getArbitraryTileOfType(TileTypeEnum.CLE_BC_CORE); + // Device.getArbitraryTileOfType() typically gives you the North-Western-most + // tile (with minimum X, maximum Y). Analyze the tile just below that. + intTile = bcCoreTile.getTileNeighbor(2, 0); + assert(intTile.getTileTypeEnum() == TileTypeEnum.INT); + ultraScalesNonLocalWires = null; - // FIXME: - eastWestPattern = null; - eastWestWires = null; + eastWestPattern = Pattern.compile("(((BOUNCE|IMUX_B|BNODE_OUTS)_(?[EW])(?\\d+))|INT_NODE_IMUX_ATOM_(?\\d+)_).*"); } for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { @@ -179,69 +182,86 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map new BitSet[]{new BitSet(), new BitSet()}); + BitSet eastWires = eastWestWires[0]; + BitSet westWires = eastWestWires[1]; + String ew = m.group("eastwest"); + String inode; + if (ew != null) { + assert(ew.equals("E") || ew.equals("W")); + if (baseIntentCode == IntentCode.NODE_CLE_BNODE) { + ew = ew.equals("E") ? "W" : "E"; } - } else if (m.group(6) != null) { - int i = Integer.valueOf(m.group(6)); - if (i < 32 || (isUltraScale && (i >= 64 && i < 96))) { + // Integer bounce = isVersal && baseIntentCode == IntentCode.NODE_PINBOUNCE ? Integer.valueOf(m.group("bounce")) : null; + if (ew.equals("E") /*&& (bounce == null || bounce < 16)*/) { eastWires.set(baseNode.getWireIndex()); - } else { - assert(i < 64 || (isUltraScale && (i >= 96 && i < 128))); + } else if (ew.equals("W") /*&& (bounce == null || bounce < 16)*/) { westWires.set(baseNode.getWireIndex()); + } else { + // assert(!isVersal || baseIntentCode == IntentCode.NODE_IMUX || (bounce >= 16 && bounce < 32)); + } + } else { + if ((inode = m.group("inode")) != null) { + int i = Integer.valueOf(inode); + if (i < 32 || ((isUltraScale || isVersal) && i >= 64 && i < 96)) { + eastWires.set(baseNode.getWireIndex()); + } else { + assert(i < 64 || (isUltraScale || isVersal && i >= 96 && i < 128)); + westWires.set(baseNode.getWireIndex()); + } } } } else { - assert(baseWireName.matches("CTRL_[EW](_B)?\\d+|INT_NODE_GLOBAL_\\d+(_INT)?_OUT[01]?") - // FIXME: - || series == Series.Versal); + assert((isUltraScale || isUltraScalePlus) && baseWireName.matches("CTRL_[EW](_B)?\\d+|INT_NODE_GLOBAL_\\d+(_INT)?_OUT[01]?")); } } @@ -644,54 +664,9 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return true; } - Tile sinkTile = sinkRnode.getTile(); - if (isVersal) { - if (childTile == sinkTile) { - return true; - } - - IntentCode childIntentCode = childRnode.getIntentCode(); - switch (childIntentCode) { - case NODE_INODE: - // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE -> NODE_PINBOUNCE) - return false; - case NODE_CLE_CNODE: - // Block access to all CNODEs outside the sink tile, since NODE_CLE_CNODE -> NODE_CLE_CTRL - return false; - case NODE_INTF_CNODE: - // Block access to all CNODEs outside the sink tile, since NODE_INTF_CNODE -> NODE_INTF_CTRL - return false; - case NODE_PINBOUNCE: - // BOUNCEs are only accessible through INODEs, so transitively this node must be in the sink tile too - return false; - case NODE_CLE_BNODE: - case NODE_INTF_BNODE: - IntentCode sinkIntentCode = sinkRnode.getIntentCode(); - // For CTRL sinks, block all BNODEs outside the sink tile - if (sinkIntentCode == IntentCode.NODE_CLE_CTRL || sinkIntentCode == IntentCode.NODE_INTF_CTRL) { - return false; - } - // For other sinks, only allow if BNODE reaches into the sink tile - assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); - return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && - childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); - case NODE_IMUX: - // IMUXes that are not EXCLUSIVE_SINKs will have been isExcluded() from the graph unless LUT routethrus are enabled - assert(lutRoutethru); - return true; - case NODE_PINFEED: - // Expected to be projected away - break; - case NODE_CLE_CTRL: - case NODE_INTF_CTRL: - // CTRL pins that are not EXCLUSIVE_SINKs will have been isExcluded() from the graph - break; - } - throw new RuntimeException("ERROR: Unhandled IntentCode: " + childIntentCode); - } - // (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) { @@ -710,11 +685,15 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { if (type != RouteNodeType.LOCAL) { return false; } - if (design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus) { - // This must be a CTRL sink; these can only be accessed from the sink tile rather than Y +/- 1 below - return childTile == sinkTile; + // This must be a CTRL sink; these can only be accessed from the sink tile (rather than Y +/- 1 below) + if (isVersal) { + assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL || + sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); + } else { + assert(design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus); + assert(sinkRnode.getWireName().startsWith("CTRL_")); } - break; + return childTile == sinkTile; default: throw new RuntimeException("ERROR: Unexpected sink type " + sinkRnode.getType()); } @@ -724,6 +703,46 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return true; } + if (isVersal) { + IntentCode childIntentCode = childRnode.getIntentCode(); + switch (childIntentCode) { + case NODE_INODE: + // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE -> NODE_PINBOUNCE) + return false; + case NODE_CLE_CNODE: + case NODE_INTF_CNODE: { + // CNODEs must only be used for CTRL sinks; must not be the case if we've reached here + // FIXME + IntentCode sinkIntentCode = sinkRnode.getIntentCode(); + assert(sinkIntentCode != IntentCode.NODE_CLE_CTRL && sinkIntentCode != IntentCode.NODE_INTF_CTRL); + return false; + } + case NODE_CLE_BNODE: + case NODE_INTF_BNODE: { + // Sinks at this point must only, only allow if BNODE reaches into the sink tile + IntentCode sinkIntentCode = sinkRnode.getIntentCode(); + assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); + return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && + childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); + } + case NODE_PINBOUNCE: + // BOUNCEs are only accessible through INODEs, so transitively this intent code is unreachable + break; + case NODE_IMUX: + // IMUXes that are not our target EXCLUSIVE_SINK will have been isExcluded() from the graph unless LUT routethrus are enabled + assert(lutRoutethru); + break; + case NODE_PINFEED: + // Expected to be projected away + break; + case NODE_CLE_CTRL: + case NODE_INTF_CTRL: + // CTRL pins that are not our target EXCLUSIVE_SINK will have been isExcluded() from the graph + break; + } + throw new RuntimeException("ERROR: Unhandled IntentCode: " + childIntentCode); + } + // (e) when in same X as the sink tile, but Y +/- 1 return childX == sinkTile.getTileXCoordinate() && Math.abs(childTile.getTileYCoordinate() - sinkTile.getTileYCoordinate()) <= 1; diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 10bf8f874..571f7470c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -157,6 +157,9 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } // Fall through case NODE_PINBOUNCE: + case NODE_INODE: // INT.INT_NODE_IMUX_ATOM_*_INT_OUT[01] (Versal only) + case NODE_IMUX: // INT.IMUX_B_[EW]* (Versal only) + case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* (Versal only) if (routingGraph != null && routingGraph.eastWestWires != null) { BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); if (eastWestWires[0].get(node.getWireIndex())) { @@ -165,17 +168,13 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou return RouteNodeType.LOCAL_WEST; } assert(node.getWireName().startsWith("CTRL_") || - // FIXME: - routingGraph.design.getSeries() == Series.Versal); + (routingGraph.isVersal && ic == IntentCode.NODE_PINBOUNCE && node.getWireName().matches("BOUNCE_[EW](1[6-9]|2[0-9]|3[01])"))); } return RouteNodeType.LOCAL; // Versal only - case NODE_INODE: // INT.INT_NODE_IMUX_ATOM_*_INT_OUT[01] - case NODE_IMUX: // INT.IMUX_B_[EW]* case NODE_CLE_CTRL: // CLE_BC_CORE*.CTRL_[LR]_B* case NODE_INTF_CTRL: // INTF_[LR]OCF_[TB][LR]_TILE.INTF_IRI* - case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* case NODE_CLE_CNODE: // CLE_BC_CORE*.CNODE_OUTS_[EW]* case NODE_INTF_BNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_BNODE_OUTS* case NODE_INTF_CNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_CNODE_OUTS* From 50287fedd6e0d924d378b7498758b21ca52509dc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 16:24:08 -0800 Subject: [PATCH 45/64] Assign CNODEs to be LOCAL_{EAST,WEST} (opposite to name) Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 3 +- .../rapidwright/rwroute/RouteNodeGraph.java | 46 +++++++++++-------- .../rapidwright/rwroute/RouteNodeInfo.java | 6 +-- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 044e2d70f..11742bf4f 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1844,7 +1844,8 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_EAST || rnode.getType() == RouteNodeType.LOCAL_EAST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_WEST || rnode.getType() == RouteNodeType.LOCAL_WEST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL || - (routingGraph.isVersal && rnode.getIntentCode() == IntentCode.NODE_CLE_BNODE)); + // [BC]NODEs are LOCAL_{EAST,WEST} since they connect to INODEs, but also service CTRL sinks + (routingGraph.isVersal && (rnode.getIntentCode() == IntentCode.NODE_CLE_BNODE || rnode.getIntentCode() == IntentCode.NODE_CLE_CNODE))); if (!isAccessibleSink(childRNode, connection)) { continue; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 9cc826d18..1c00f2a5c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -171,7 +171,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map[EW])(?\\d+))|INT_NODE_IMUX_ATOM_(?\\d+)_).*"); + eastWestPattern = Pattern.compile("(((BOUNCE|IMUX_B|[BC]NODE_OUTS)_(?[EW]))|INT_NODE_IMUX_ATOM_(?\\d+)_).*"); } for (int wireIndex = 0; wireIndex < intTile.getWireCount(); wireIndex++) { @@ -223,7 +223,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map= 16 && bounce < 32)); + assert(ew.equals("W")); + westWires.set(baseNode.getWireIndex()); } } else { if ((inode = m.group("inode")) != null) { @@ -681,19 +679,24 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { } break; case EXCLUSIVE_SINK: - // Only both-sided wires (e.g. INT_NODE_GLOBAL_*) can reach a both-sided sink (CTRL_*) - if (type != RouteNodeType.LOCAL) { + // This must be a CTRL sink; these can only be accessed from LOCAL nodes in the sink tile (rather than Y +/- 1 below) + if (childTile != sinkTile) { return false; } - // This must be a CTRL sink; these can only be accessed from the sink tile (rather than Y +/- 1 below) if (isVersal) { - assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL || - sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); + assert((sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL && type != RouteNodeType.LOCAL) || + (sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL && type == RouteNodeType.LOCAL)); } else { assert(design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus); assert(sinkRnode.getWireName().startsWith("CTRL_")); + + // Only both-sided wires (e.g. INT_NODE_GLOBAL_*) can reach a both-sided sink (CTRL_*) + if (type != RouteNodeType.LOCAL) { + return false; + } } - return childTile == sinkTile; + assert(childTile == sinkTile); + break; default: throw new RuntimeException("ERROR: Unexpected sink type " + sinkRnode.getType()); } @@ -711,15 +714,20 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return false; case NODE_CLE_CNODE: case NODE_INTF_CNODE: { - // CNODEs must only be used for CTRL sinks; must not be the case if we've reached here - // FIXME IntentCode sinkIntentCode = sinkRnode.getIntentCode(); - assert(sinkIntentCode != IntentCode.NODE_CLE_CTRL && sinkIntentCode != IntentCode.NODE_INTF_CTRL); + assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); + + // Experimentally, found this to lead to runtime increases + // // 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 pin return false; } case NODE_CLE_BNODE: case NODE_INTF_BNODE: { - // Sinks at this point must only, only allow if BNODE reaches into the sink tile + // Only allow BNODEs that reach into the sink tile IntentCode sinkIntentCode = sinkRnode.getIntentCode(); assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 571f7470c..9f92d1d6e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -159,6 +159,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou case NODE_PINBOUNCE: case NODE_INODE: // INT.INT_NODE_IMUX_ATOM_*_INT_OUT[01] (Versal only) case NODE_IMUX: // INT.IMUX_B_[EW]* (Versal only) + case NODE_CLE_CNODE: // CLE_BC_CORE*.CNODE_OUTS_[EW]* (Versal only) case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* (Versal only) if (routingGraph != null && routingGraph.eastWestWires != null) { BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); @@ -167,15 +168,14 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } else if (eastWestWires[1].get(node.getWireIndex())) { return RouteNodeType.LOCAL_WEST; } - assert(node.getWireName().startsWith("CTRL_") || - (routingGraph.isVersal && ic == IntentCode.NODE_PINBOUNCE && node.getWireName().matches("BOUNCE_[EW](1[6-9]|2[0-9]|3[01])"))); + assert((!routingGraph.isVersal && node.getWireName().startsWith("CTRL_") || + routingGraph.isVersal && ic == IntentCode.NODE_CLE_CNODE)); } return RouteNodeType.LOCAL; // Versal only case NODE_CLE_CTRL: // CLE_BC_CORE*.CTRL_[LR]_B* case NODE_INTF_CTRL: // INTF_[LR]OCF_[TB][LR]_TILE.INTF_IRI* - case NODE_CLE_CNODE: // CLE_BC_CORE*.CNODE_OUTS_[EW]* case NODE_INTF_BNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_BNODE_OUTS* case NODE_INTF_CNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_CNODE_OUTS* return RouteNodeType.LOCAL; From f4df0525dbbc71f63414ab1e087ee82637bf474d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 16:51:45 -0800 Subject: [PATCH 46/64] Fix merge Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNode.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 9729b9e13..42bd6e5b6 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -134,11 +134,6 @@ private void setBaseCost(Series series) { assert(length == 0); break; case LOCAL_EAST: - case LOCAL_WEST: - assert(length == 0 || - (series == Series.Versal && EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE).contains(getIntentCode()))); - break; - case LOCAL_EAST: case LOCAL_WEST: assert(length == 0 || (length == 1 && ( From 003a051b284a169f13751b761362b642e15433a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 17:08:23 -0800 Subject: [PATCH 47/64] Resolve FIXMEs Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 8 +--- .../rapidwright/rwroute/RouteNodeGraph.java | 38 ++++++++++++++++++- .../rapidwright/rwroute/RouteNodeInfo.java | 14 +++---- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 11742bf4f..98967952d 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1817,12 +1817,8 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { if (!routingGraph.isAccessible(childRNode, connection)) { continue; } - assert(rnode.getType() != RouteNodeType.LOCAL_EAST || childRNode.getType() == RouteNodeType.LOCAL_EAST - // FIXME: - || childRNode.getTile().getName().matches("INTF_[LR]OCF_[TB]R_TILE_.*")); - assert(rnode.getType() != RouteNodeType.LOCAL_WEST || childRNode.getType() == RouteNodeType.LOCAL_WEST - // FIXME: - || childRNode.getTile().getName().matches("INTF_[LR]OCF_[TB]L_TILE_.*")); + assert(rnode.getType() != RouteNodeType.LOCAL_EAST || childRNode.getType() == RouteNodeType.LOCAL_EAST); + assert(rnode.getType() != RouteNodeType.LOCAL_WEST || childRNode.getType() == RouteNodeType.LOCAL_WEST); break; case NON_LOCAL: // LOCALs cannot connect to NON_LOCALs except via a LUT routethru diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 1c00f2a5c..9afeb80ae 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -263,6 +263,38 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map new BitSet[]{new BitSet(), new BitSet()}); + BitSet eastWires = eastWestWires[0]; + BitSet westWires = eastWestWires[1]; + for (int wireIndex = 0; wireIndex < intfTile.getWireCount(); wireIndex++) { + IntentCode baseIntentCode = intfTile.getWireIntentCode(wireIndex); + if (baseIntentCode != IntentCode.NODE_INTF_BNODE) { + continue; + } + + if (EnumSet.of(TileTypeEnum.INTF_LOCF_TR_TILE, + TileTypeEnum.INTF_LOCF_BR_TILE, + TileTypeEnum.INTF_ROCF_TR_TILE, + TileTypeEnum.INTF_ROCF_BR_TILE).contains(tte)) { + eastWires.set(wireIndex); + } else { + westWires.set(wireIndex); + } + } + } + } + if (lutRoutethru) { assert(isUltraScalePlus || isUltraScale); @@ -684,8 +716,12 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return false; } if (isVersal) { + // CLE_CTRL can be reached by NODE_CLE_[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)); + // INTF_CTRL can be reached by NODE_INTF_BNODE which have type LOCAL_{EAST,WEST}, + // but also NODE_INTF_CNODE which are currently LOCAL + (sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL && (type != RouteNodeType.LOCAL || + childRnode.getIntentCode() == IntentCode.NODE_INTF_CNODE))); } else { assert(design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus); assert(sinkRnode.getWireName().startsWith("CTRL_")); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 9f92d1d6e..7ef02b910 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -24,7 +24,6 @@ import com.xilinx.rapidwright.device.IntentCode; import com.xilinx.rapidwright.device.Node; -import com.xilinx.rapidwright.device.Series; import com.xilinx.rapidwright.device.Tile; import com.xilinx.rapidwright.device.TileTypeEnum; import com.xilinx.rapidwright.device.Wire; @@ -157,10 +156,11 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } // Fall through case NODE_PINBOUNCE: - case NODE_INODE: // INT.INT_NODE_IMUX_ATOM_*_INT_OUT[01] (Versal only) - case NODE_IMUX: // INT.IMUX_B_[EW]* (Versal only) - case NODE_CLE_CNODE: // CLE_BC_CORE*.CNODE_OUTS_[EW]* (Versal only) - case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* (Versal only) + case NODE_INODE: // INT.INT_NODE_IMUX_ATOM_*_INT_OUT[01] (Versal only) + case NODE_IMUX: // INT.IMUX_B_[EW]* (Versal only) + case NODE_CLE_CNODE: // CLE_BC_CORE*.CNODE_OUTS_[EW]* (Versal only) + case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* (Versal only) + case NODE_INTF_BNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_BNODE_OUTS* (Versal only) if (routingGraph != null && routingGraph.eastWestWires != null) { BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); if (eastWestWires[0].get(node.getWireIndex())) { @@ -168,15 +168,13 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } else if (eastWestWires[1].get(node.getWireIndex())) { return RouteNodeType.LOCAL_WEST; } - assert((!routingGraph.isVersal && node.getWireName().startsWith("CTRL_") || - routingGraph.isVersal && ic == IntentCode.NODE_CLE_CNODE)); + assert(!routingGraph.isVersal && node.getWireName().startsWith("CTRL_")); } return RouteNodeType.LOCAL; // Versal only case NODE_CLE_CTRL: // CLE_BC_CORE*.CTRL_[LR]_B* case NODE_INTF_CTRL: // INTF_[LR]OCF_[TB][LR]_TILE.INTF_IRI* - case NODE_INTF_BNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_BNODE_OUTS* case NODE_INTF_CNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_CNODE_OUTS* return RouteNodeType.LOCAL; From c057226b9cf6a85d12269f1a726454a6fa5f3f1f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 19:05:43 -0800 Subject: [PATCH 48/64] Restore comment Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 98967952d..2b1a89158 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1817,6 +1817,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { 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); break; From 353775cd3c769c736c125d4652f67ed46705b625 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 19:07:46 -0800 Subject: [PATCH 49/64] Fix continue Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 9afeb80ae..9222dbfac 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -215,9 +215,8 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Tue, 12 Nov 2024 20:28:19 -0800 Subject: [PATCH 50/64] On Versal, make all NODE_PINFEEDs RouteNodeType.LOCAL Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 7ef02b910..2b799e975 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -148,7 +148,10 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } case NODE_PINFEED: - if (routingGraph != null && routingGraph.lagunaI != null) { + if (routingGraph == null || routingGraph.isVersal) { + return RouteNodeType.LOCAL; + } + if (routingGraph.lagunaI != null) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); if (bs != null && bs.get(node.getWireIndex())) { return RouteNodeType.LAGUNA_PINFEED; From 76bc5ccba71acc4d3103fa5ab0f9bca20d909a11 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 20:54:48 -0800 Subject: [PATCH 51/64] Handle NODE_INTF_CNODE too Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 4 +++- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 9 +++------ src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 2b1a89158..498174b87 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1842,7 +1842,9 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_WEST || rnode.getType() == RouteNodeType.LOCAL_WEST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL || // [BC]NODEs are LOCAL_{EAST,WEST} since they connect to INODEs, but also service CTRL sinks - (routingGraph.isVersal && (rnode.getIntentCode() == IntentCode.NODE_CLE_BNODE || rnode.getIntentCode() == IntentCode.NODE_CLE_CNODE))); + (routingGraph.isVersal && EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE, + IntentCode.NODE_INTF_BNODE, IntentCode.NODE_INTF_CNODE) + .contains(rnode.getIntentCode()))); if (!isAccessibleSink(childRNode, connection)) { continue; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 9222dbfac..d4ebcff6c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -278,7 +278,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Tue, 12 Nov 2024 21:02:15 -0800 Subject: [PATCH 52/64] Add comment Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index d4ebcff6c..a2dbe4988 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -749,12 +749,13 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { IntentCode sinkIntentCode = sinkRnode.getIntentCode(); assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); - // Experimentally, found this to lead to runtime increases + // 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(); - // Do not allow CNODEs when not targeting a CTRL pin + // 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: From e87750371934443d5a6a1012ec64462a62db6aff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Nov 2024 23:00:32 -0800 Subject: [PATCH 53/64] Simplify if Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index e04cb4150..76e180715 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -165,7 +165,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou case NODE_CLE_BNODE: // CLE_BC_CORE*.BNODE_OUTS_[EW]* (Versal only) case NODE_INTF_BNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_BNODE_OUTS* (Versal only) case NODE_INTF_CNODE: // INTF_[LR]OCF_[TB][LR]_TILE.IF_INT_CNODE_OUTS* (Versal only) - if (routingGraph != null && routingGraph.eastWestWires != null) { + if (routingGraph != null) { BitSet[] eastWestWires = routingGraph.eastWestWires.get(tileTypeEnum); if (eastWestWires[0].get(node.getWireIndex())) { return RouteNodeType.LOCAL_EAST; From ce90eb706a3ed61b6da18699a588a39dbd596f66 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 11:03:39 -0800 Subject: [PATCH 54/64] Introduce LOCAL_RESERVED Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 36 +++++++++++++++++-- .../xilinx/rapidwright/rwroute/RouteNode.java | 1 + .../rapidwright/rwroute/RouteNodeGraph.java | 30 ++++++++-------- .../rapidwright/rwroute/RouteNodeType.java | 6 ++-- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 498174b87..288dd485e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -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() { @@ -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 diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 42bd6e5b6..19f50701c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -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) || diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index a2dbe4988..21b95e29a 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -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; } @@ -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; } @@ -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_")); @@ -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: { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index 0c024bb0b..eba37caf9 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -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; } } From 1c2b47101992ca8c47e7c1c76b16b647b174e86d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 12:08:25 -0800 Subject: [PATCH 55/64] Allow INODE and PINBOUNCE either side of CTRL sink to be used Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RouteNode.java | 5 +- .../rapidwright/rwroute/RouteNodeGraph.java | 58 +++++++++++-------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index 19f50701c..a5a7501d3 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -359,7 +359,10 @@ public void setType(RouteNodeType type) { (this.type.isExclusiveSink() && type == RouteNodeType.LOCAL) || // Or promotion from LOCAL to EXCLUSIVE_SINK (by PartialRouter when NODE_PINBOUNCE on // a newly unpreserved net becomes a sink) - (this.type == RouteNodeType.LOCAL && type.isExclusiveSink())); + (this.type == RouteNodeType.LOCAL && type.isExclusiveSink()) || + // Or promotion for any LOCAL to a LOCAL_RESERVED (by determineRoutingTargets() + // for uphills of CTRL sinks) + (this.type.isLocal() && type == RouteNodeType.LOCAL_RESERVED)); this.type = type; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 21b95e29a..e9aa46710 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -710,21 +710,39 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { } break; case EXCLUSIVE_SINK: - // This must be a CTRL sink; these can only be accessed from LOCAL nodes in the sink tile (rather than Y +/- 1 below) - if (childTile != sinkTile) { - return false; - } + // This must be a CTRL sink that can be accessed from both east/west sides + if (isVersal) { 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; + if (childTile == sinkTile) { + // CTRL sinks can be accessed directly from LOCAL_RESERVED nodes in the sink CLE_BC_CORE/INTF_* tile ... + if (type != RouteNodeType.LOCAL_RESERVED) { + return false; + } + } else { + // ... or via LOCAL nodes in the two INT tiles either side + if (childTile.getTileYCoordinate() != sinkTile.getTileYCoordinate() || + Math.abs(childTile.getTileXCoordinate() - sinkTile.getTileXCoordinate()) > 1) { + return false; + } + if (childTile.getTileTypeEnum() != TileTypeEnum.INT) { + // e.g. CLE_BC_CORE_X50Y4 and CLE_BC_CORE_1_X50Y4 on xcvc1502 + return false; + } + // Allow use of INODE + PINBOUNCEs in the two INT tiles on either side of sink + assert(childRnode.getIntentCode() == IntentCode.NODE_INODE || childRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); + return true; } } else { assert(design.getSeries() == Series.UltraScale || design.getSeries() == Series.UltraScalePlus); assert(sinkRnode.getWireName().startsWith("CTRL_")); + // CTRL sinks can only be accessed from LOCAL nodes in the sink tile (rather than Y +/- 1 below) + if (childTile != sinkTile) { + return false; + } + // Only both-sided wires (e.g. INT_NODE_GLOBAL_*) can reach a both-sided sink (CTRL_*) if (type != RouteNodeType.LOCAL) { return false; @@ -742,32 +760,22 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { } if (isVersal) { + assert(sinkRnode.getType() != RouteNodeType.EXCLUSIVE_SINK); + assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); + IntentCode childIntentCode = childRnode.getIntentCode(); switch (childIntentCode) { case NODE_INODE: // Block access to all INODEs outside the sink tile, since NODE_INODE -> NODE_IMUX -> NODE_PINFEED (or NODE_INODE -> NODE_PINBOUNCE) + assert(childTile != sinkTile); return false; - case NODE_CLE_CNODE: - case NODE_INTF_CNODE: { - IntentCode sinkIntentCode = sinkRnode.getIntentCode(); - assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); - - // 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; - } case NODE_CLE_BNODE: - case NODE_INTF_BNODE: { - // Only allow BNODEs that reach into the sink tile - IntentCode sinkIntentCode = sinkRnode.getIntentCode(); - assert(sinkIntentCode == IntentCode.NODE_IMUX || sinkIntentCode == IntentCode.NODE_PINBOUNCE); + case NODE_INTF_BNODE: + case NODE_CLE_CNODE: + case NODE_INTF_CNODE: + // Only allow [BC]NODEs that reach into the sink tile return childTile.getTileYCoordinate() == sinkTile.getTileYCoordinate() && childRnode.getEndTileXCoordinate() == sinkTile.getTileXCoordinate(); - } case NODE_PINBOUNCE: // BOUNCEs are only accessible through INODEs, so transitively this intent code is unreachable break; From 541420686c3d9243fcc0c07298e86ac2530c2aac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 12:18:54 -0800 Subject: [PATCH 56/64] Update comment Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index e9aa46710..0e0a388e9 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -716,7 +716,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { assert(sinkRnode.getIntentCode() == IntentCode.NODE_CLE_CTRL || sinkRnode.getIntentCode() == IntentCode.NODE_INTF_CTRL); if (childTile == sinkTile) { - // CTRL sinks can be accessed directly from LOCAL_RESERVED nodes in the sink CLE_BC_CORE/INTF_* tile ... + // CTRL sinks can be only accessed directly from LOCAL_RESERVED nodes in the sink CLE_BC_CORE/INTF_* tile ... if (type != RouteNodeType.LOCAL_RESERVED) { return false; } From 57ed0514e6d16bbe2a22feababd27a5a9a2b8350 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 14:27:06 -0800 Subject: [PATCH 57/64] Clearer names Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/Connection.java | 4 ++-- .../xilinx/rapidwright/rwroute/RWRoute.java | 22 +++++++++---------- .../xilinx/rapidwright/rwroute/RouteNode.java | 10 ++++----- .../rapidwright/rwroute/RouteNodeGraph.java | 12 +++++----- .../rapidwright/rwroute/RouteNodeInfo.java | 8 +++---- .../rapidwright/rwroute/RouteNodeType.java | 12 +++++----- .../rwroute/TimingAndWirelengthReport.java | 2 +- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/Connection.java b/src/com/xilinx/rapidwright/rwroute/Connection.java index 95a7f87e0..1202b46a8 100644 --- a/src/com/xilinx/rapidwright/rwroute/Connection.java +++ b/src/com/xilinx/rapidwright/rwroute/Connection.java @@ -305,7 +305,7 @@ public void addAltSinkRnode(RouteNode sinkRnode) { } else { assert(!altSinkRnodes.contains(sinkRnode)); } - assert(sinkRnode.getType().isExclusiveSink() || + assert(sinkRnode.getType().isAnyExclusiveSink() || // Can be a WIRE if node is not exclusive a sink sinkRnode.getType() == RouteNodeType.NON_LOCAL); altSinkRnodes.add(sinkRnode); @@ -487,7 +487,7 @@ public void setAllTargets(RWRoute.ConnectionState state) { // where the same physical pin services more than one logical pin if (rnode.countConnectionsOfUser(netWrapper) == 0 || // Except if it is not an EXCLUSIVE_SINK - rnode.getType().isExclusiveSink()) { + rnode.getType().isAnyExclusiveSink()) { assert(rnode.getIntentCode() != IntentCode.NODE_PINBOUNCE); rnode.markTarget(state); } diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 288dd485e..64095bd11 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -332,7 +332,7 @@ protected void determineRoutingTargets() { if (routingGraph.isVersal) { for (Connection connection : indirectConnections) { RouteNode sinkRnode = connection.getSinkRnode(); - if (sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK) { + if (sinkRnode.getType() == RouteNodeType.EXCLUSIVE_SINK_BOTH) { for (Node uphill : sinkRnode.getAllUphillNodes()) { if (uphill.isTiedToVcc()) { continue; @@ -637,8 +637,8 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); } else { - sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK); + sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_BOTH); + sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_BOTH); } connection.setSinkRnode(sinkRnode); @@ -691,7 +691,7 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { continue; } RouteNode altSinkRnode = routingGraph.getOrCreate(node, sinkRnode.getType()); - assert(altSinkRnode.getType().isExclusiveSink()); + assert(altSinkRnode.getType().isAnyExclusiveSink()); connection.addAltSinkRnode(altSinkRnode); } @@ -1838,7 +1838,7 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { } switch (childRNode.getType()) { case LOCAL_RESERVED: - case LOCAL: + case LOCAL_BOTH: case LOCAL_EAST: case LOCAL_WEST: if (!routingGraph.isAccessible(childRNode, connection)) { @@ -1847,13 +1847,13 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { // 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)); + (childRNode.getType() == RouteNodeType.LOCAL_RESERVED && connection.getSinkRnode().getType() == RouteNodeType.EXCLUSIVE_SINK_BOTH)); assert(rnode.getType() != RouteNodeType.LOCAL_WEST || childRNode.getType() == RouteNodeType.LOCAL_WEST || - (childRNode.getType() == RouteNodeType.LOCAL_RESERVED && connection.getSinkRnode().getType() == RouteNodeType.EXCLUSIVE_SINK)); + (childRNode.getType() == RouteNodeType.LOCAL_RESERVED && connection.getSinkRnode().getType() == RouteNodeType.EXCLUSIVE_SINK_BOTH)); break; case NON_LOCAL: // LOCALs cannot connect to NON_LOCALs except via a LUT routethru - assert(!rnode.getType().isLocal() || + assert(!rnode.getType().isAnyLocal() || routingGraph.lutRoutethru && rnode.getIntentCode() == IntentCode.NODE_PINFEED); if (!routingGraph.isAccessible(childRNode, connection)) { @@ -1865,12 +1865,12 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } break; - case EXCLUSIVE_SINK: + case EXCLUSIVE_SINK_BOTH: case EXCLUSIVE_SINK_EAST: case EXCLUSIVE_SINK_WEST: assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_EAST || rnode.getType() == RouteNodeType.LOCAL_EAST); assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_WEST || rnode.getType() == RouteNodeType.LOCAL_WEST); - assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK || rnode.getType() == RouteNodeType.LOCAL || + assert(childRNode.getType() != RouteNodeType.EXCLUSIVE_SINK_BOTH || rnode.getType() == RouteNodeType.LOCAL_BOTH || // [BC]NODEs are LOCAL_{EAST,WEST} since they connect to INODEs, but also service CTRL sinks (routingGraph.isVersal && EnumSet.of(IntentCode.NODE_CLE_BNODE, IntentCode.NODE_CLE_CNODE, IntentCode.NODE_INTF_BNODE, IntentCode.NODE_INTF_CNODE) @@ -1919,7 +1919,7 @@ protected boolean isAccessibleSink(RouteNode child, Connection connection) { } protected boolean isAccessibleSink(RouteNode child, Connection connection, boolean assertOnOveruse) { - assert(child.getType().isExclusiveSink()); + assert(child.getType().isAnyExclusiveSink()); assert(!assertOnOveruse || !child.isOverUsed()); if (child.isTarget()) { diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNode.java b/src/com/xilinx/rapidwright/rwroute/RouteNode.java index a5a7501d3..c8e35d909 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNode.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNode.java @@ -124,13 +124,13 @@ private void setBaseCost(Series series) { assert(length == 0 || (length <= 3 && series == Series.Versal)); break; - case EXCLUSIVE_SINK: + case EXCLUSIVE_SINK_BOTH: case EXCLUSIVE_SINK_EAST: case EXCLUSIVE_SINK_WEST: assert(length == 0 || (length == 1 && (series == Series.UltraScalePlus || series == Series.UltraScale) && getIntentCode() == IntentCode.NODE_PINBOUNCE)); break; - case LOCAL: + case LOCAL_BOTH: assert(length == 0); break; case LOCAL_EAST: @@ -356,13 +356,13 @@ public RouteNodeType getType() { public void setType(RouteNodeType type) { assert(this.type == type || // Support demotion from EXCLUSIVE_SINK to LOCAL since they have the same base cost - (this.type.isExclusiveSink() && type == RouteNodeType.LOCAL) || + (this.type.isAnyExclusiveSink() && type == RouteNodeType.LOCAL_BOTH) || // Or promotion from LOCAL to EXCLUSIVE_SINK (by PartialRouter when NODE_PINBOUNCE on // a newly unpreserved net becomes a sink) - (this.type == RouteNodeType.LOCAL && type.isExclusiveSink()) || + (this.type == RouteNodeType.LOCAL_BOTH && type.isAnyExclusiveSink()) || // Or promotion for any LOCAL to a LOCAL_RESERVED (by determineRoutingTargets() // for uphills of CTRL sinks) - (this.type.isLocal() && type == RouteNodeType.LOCAL_RESERVED)); + (this.type.isAnyLocal() && type == RouteNodeType.LOCAL_RESERVED)); this.type = type; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 0e0a388e9..8b0e45f65 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -550,9 +550,9 @@ protected boolean isExcluded(RouteNode parent, Node child) { // PINFEEDs can lead to a site pin, or into a Laguna tile RouteNode childRnode = getNode(child); if (childRnode != null) { - assert(childRnode.getType().isExclusiveSink() || + assert(childRnode.getType().isAnyExclusiveSink() || childRnode.getType() == RouteNodeType.LAGUNA_PINFEED || - (lutRoutethru && childRnode.getType().isLocal())); + (lutRoutethru && childRnode.getType().isAnyLocal())); } else if (!lutRoutethru) { // child does not already exist in our routing graph, meaning it's not a used site pin // in our design, but it could be a LAGUNA_I @@ -680,7 +680,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { // Only consider LOCAL nodes when: // (a) considering LUT routethrus RouteNodeType type = childRnode.getType(); - if (!type.isLocal() || lutRoutethru) { + if (!type.isAnyLocal() || lutRoutethru) { return true; } @@ -709,7 +709,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { return false; } break; - case EXCLUSIVE_SINK: + case EXCLUSIVE_SINK_BOTH: // This must be a CTRL sink that can be accessed from both east/west sides if (isVersal) { @@ -744,7 +744,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { } // Only both-sided wires (e.g. INT_NODE_GLOBAL_*) can reach a both-sided sink (CTRL_*) - if (type != RouteNodeType.LOCAL) { + if (type != RouteNodeType.LOCAL_BOTH) { return false; } } @@ -760,7 +760,7 @@ public boolean isAccessible(RouteNode childRnode, Connection connection) { } if (isVersal) { - assert(sinkRnode.getType() != RouteNodeType.EXCLUSIVE_SINK); + assert(sinkRnode.getType() != RouteNodeType.EXCLUSIVE_SINK_BOTH); assert(sinkRnode.getIntentCode() == IntentCode.NODE_IMUX || sinkRnode.getIntentCode() == IntentCode.NODE_PINBOUNCE); IntentCode childIntentCode = childRnode.getIntentCode(); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 76e180715..50b223b3c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -141,7 +141,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } else if (eastWestWires[1].get(node.getWireIndex())) { return RouteNodeType.LOCAL_WEST; } - return RouteNodeType.LOCAL; + return RouteNodeType.LOCAL_BOTH; } break; } @@ -149,7 +149,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou case NODE_PINFEED: if (routingGraph == null || routingGraph.isVersal) { - return RouteNodeType.LOCAL; + return RouteNodeType.LOCAL_BOTH; } if (routingGraph.lagunaI != null) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); @@ -174,12 +174,12 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou } assert(!routingGraph.isVersal && node.getWireName().startsWith("CTRL_")); } - return RouteNodeType.LOCAL; + return RouteNodeType.LOCAL_BOTH; // Versal only case NODE_CLE_CTRL: // CLE_BC_CORE*.CTRL_[LR]_B* case NODE_INTF_CTRL: // INTF_[LR]OCF_[TB][LR]_TILE.INTF_IRI* - return RouteNodeType.LOCAL; + return RouteNodeType.LOCAL_BOTH; case NODE_LAGUNA_OUTPUT: // UltraScale+ only assert(tileTypeEnum == TileTypeEnum.LAG_LAG); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java index eba37caf9..7df6c3bfe 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeType.java @@ -28,7 +28,7 @@ public enum RouteNodeType { EXCLUSIVE_SOURCE, - EXCLUSIVE_SINK, + EXCLUSIVE_SINK_BOTH, EXCLUSIVE_SINK_EAST, EXCLUSIVE_SINK_WEST, @@ -46,17 +46,17 @@ public enum RouteNodeType { NON_LOCAL, - LOCAL, + LOCAL_BOTH, LOCAL_EAST, LOCAL_WEST, LOCAL_RESERVED; - public boolean isExclusiveSink() { - return this == EXCLUSIVE_SINK || this == EXCLUSIVE_SINK_EAST || this == EXCLUSIVE_SINK_WEST; + public boolean isAnyExclusiveSink() { + return this == EXCLUSIVE_SINK_BOTH || this == EXCLUSIVE_SINK_EAST || this == EXCLUSIVE_SINK_WEST; } - public boolean isLocal() { - return this == LOCAL || this == LOCAL_EAST || this == LOCAL_WEST || this == LOCAL_RESERVED; + public boolean isAnyLocal() { + return this == LOCAL_BOTH || this == LOCAL_EAST || this == LOCAL_WEST || this == LOCAL_RESERVED; } } diff --git a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java index c51cc6789..d57747c92 100644 --- a/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java +++ b/src/com/xilinx/rapidwright/rwroute/TimingAndWirelengthReport.java @@ -128,7 +128,7 @@ private NetWrapper createNetWrapper(Net net) { if (sinkINTNode == null) { connection.setDirect(true); } else { - connection.setSinkRnode(routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK)); + connection.setSinkRnode(routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_BOTH)); if (sourceINTNode == null) { sourceINTNode = RouterHelper.projectOutputPinToINTNode(source); } From 8c0acba90a567670ee12fa9296a3efab400fb494 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 15:31:35 -0800 Subject: [PATCH 58/64] Fix Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/PartialRouter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java index 90435b794..74a5f2d4f 100644 --- a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java +++ b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java @@ -256,7 +256,7 @@ protected void determineRoutingTargets() { preservedNet = routingGraph.getPreservedNet(sinkRnode); if (preservedNet != null && preservedNet != net) { unpreserveNets.add(preservedNet); - assert(sinkRnode.getType().isExclusiveSink()); + assert(sinkRnode.getType().isAnyExclusiveSink()); } } @@ -599,7 +599,7 @@ protected void unpreserveNet(Net net) { RouteNode sourceRnode = connection.getSourceRnode(); RouteNode sinkRnode = connection.getSinkRnode(); assert(sourceRnode.getType() == RouteNodeType.EXCLUSIVE_SOURCE); - assert(sinkRnode.getType().isExclusiveSink()); + assert(sinkRnode.getType().isAnyExclusiveSink()); // Even though this connection is not expected to have any routing yet, // perform a rip up anyway in order to release any exclusive sinks From d1e843a792b8329400b9309d6012bef686a43f90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 15:57:19 -0800 Subject: [PATCH 59/64] Tidy up Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 64095bd11..b7028f901 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -627,19 +627,16 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { } indirectConnections.add(connection); - BitSet[] eastWestWires = (routingGraph.eastWestWires == null) ? null : - routingGraph.eastWestWires.get(sinkINTNode.getTile().getTileTypeEnum()); - RouteNode sinkRnode; - if (eastWestWires != null && eastWestWires[0].get(sinkINTNode.getWireIndex())) { - sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_EAST); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_EAST); - } else if (eastWestWires != null && eastWestWires[1].get(sinkINTNode.getWireIndex())) { - sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_WEST); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_WEST); - } else { - sinkRnode = routingGraph.getOrCreate(sinkINTNode, RouteNodeType.EXCLUSIVE_SINK_BOTH); - sinkRnode.setType(RouteNodeType.EXCLUSIVE_SINK_BOTH); - } + + RouteNodeInfo rni = RouteNodeInfo.get(sinkINTNode, routingGraph); + assert(rni.type.isAnyLocal()); + RouteNodeType sinkType = rni.type == RouteNodeType.LOCAL_EAST ? RouteNodeType.EXCLUSIVE_SINK_EAST : + rni.type == RouteNodeType.LOCAL_WEST ? RouteNodeType.EXCLUSIVE_SINK_WEST : + rni.type == RouteNodeType.LOCAL_BOTH ? RouteNodeType.EXCLUSIVE_SINK_BOTH : + null; + assert(sinkType != null); + RouteNode sinkRnode = routingGraph.getOrCreate(sinkINTNode, sinkType); + sinkRnode.setType(sinkType); connection.setSinkRnode(sinkRnode); // Where appropriate, allow all 6 LUT pins to be swapped to begin with From fc4499a8a54b8b5d91ad3cde69bfeda991d85abb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 23:18:38 -0800 Subject: [PATCH 60/64] Use RouteNodeInfo.getType() with ignoreLaguna param Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 13 +++++++------ .../xilinx/rapidwright/rwroute/RouteNodeInfo.java | 9 ++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index b7028f901..f3584f4c2 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -628,12 +628,13 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { indirectConnections.add(connection); - RouteNodeInfo rni = RouteNodeInfo.get(sinkINTNode, routingGraph); - assert(rni.type.isAnyLocal()); - RouteNodeType sinkType = rni.type == RouteNodeType.LOCAL_EAST ? RouteNodeType.EXCLUSIVE_SINK_EAST : - rni.type == RouteNodeType.LOCAL_WEST ? RouteNodeType.EXCLUSIVE_SINK_WEST : - rni.type == RouteNodeType.LOCAL_BOTH ? RouteNodeType.EXCLUSIVE_SINK_BOTH : - null; + boolean ignoreLaguna = true; + RouteNodeType sinkType = RouteNodeInfo.getType(sinkINTNode, null, routingGraph, ignoreLaguna); + assert(sinkType.isAnyLocal()); + sinkType = sinkType == RouteNodeType.LOCAL_EAST ? RouteNodeType.EXCLUSIVE_SINK_EAST : + sinkType == RouteNodeType.LOCAL_WEST ? RouteNodeType.EXCLUSIVE_SINK_WEST : + sinkType == RouteNodeType.LOCAL_BOTH ? RouteNodeType.EXCLUSIVE_SINK_BOTH : + null; assert(sinkType != null); RouteNode sinkRnode = routingGraph.getOrCreate(sinkINTNode, sinkType); sinkRnode.setType(sinkType); diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 50b223b3c..241fb82b0 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -65,7 +65,8 @@ public static RouteNodeInfo get(Node node, RouteNodeGraph routingGraph) { endTile = node.getTile(); } - RouteNodeType type = getType(node, endTile, routingGraph); + boolean ignoreLaguna = false; + RouteNodeType type = getType(node, endTile, routingGraph, ignoreLaguna); short endTileXCoordinate = getEndTileXCoordinate(node, type, (short) endTile.getTileXCoordinate()); short endTileYCoordinate = (short) endTile.getTileYCoordinate(); short length = getLength(baseTile, type, endTileXCoordinate, endTileYCoordinate); @@ -125,7 +126,7 @@ private static short getEndTileXCoordinate(Node node, RouteNodeType type, short return endTileXCoordinate; } - private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph routingGraph) { + public static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph routingGraph, boolean ignoreLaguna) { // NOTE: IntentCode is device-dependent IntentCode ic = node.getIntentCode(); TileTypeEnum tileTypeEnum = node.getTile().getTileTypeEnum(); @@ -151,7 +152,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou if (routingGraph == null || routingGraph.isVersal) { return RouteNodeType.LOCAL_BOTH; } - if (routingGraph.lagunaI != null) { + if (routingGraph.lagunaI != null && !ignoreLaguna) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); if (bs != null && bs.get(node.getWireIndex())) { return RouteNodeType.LAGUNA_PINFEED; @@ -190,6 +191,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou case NODE_LAGUNA_DATA: // UltraScale+ only assert(tileTypeEnum == TileTypeEnum.LAG_LAG); + assert(endTile != null); if (node.getTile() != endTile) { return RouteNodeType.SUPER_LONG_LINE; } @@ -201,6 +203,7 @@ private static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rou if (tileTypeEnum == TileTypeEnum.LAGUNA_TILE) { // UltraScale only String wireName = node.getWireName(); if (wireName.startsWith("UBUMP")) { + assert(endTile != null); assert(node.getTile() != endTile); return RouteNodeType.SUPER_LONG_LINE; } else if (wireName.endsWith("_TXOUT")) { From 976831411d87cfa74e88e7e13c5edc55c1cc117c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Nov 2024 23:22:43 -0800 Subject: [PATCH 61/64] Rename param to forceSink Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RWRoute.java | 6 ++++-- src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index f3584f4c2..6d10be3e6 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -628,8 +628,10 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { indirectConnections.add(connection); - boolean ignoreLaguna = true; - RouteNodeType sinkType = RouteNodeInfo.getType(sinkINTNode, null, routingGraph, ignoreLaguna); + // Inform RouteNodeInfo.getType() that this a sink to prevent it from returning + // RouteNodeType.LAGUNA_PINFEED and instead return LOCAL_{EAST,WEST} + boolean forceSink = true; + RouteNodeType sinkType = RouteNodeInfo.getType(sinkINTNode, null, routingGraph, forceSink); assert(sinkType.isAnyLocal()); sinkType = sinkType == RouteNodeType.LOCAL_EAST ? RouteNodeType.EXCLUSIVE_SINK_EAST : sinkType == RouteNodeType.LOCAL_WEST ? RouteNodeType.EXCLUSIVE_SINK_WEST : diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java index 241fb82b0..d867dda1c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java @@ -65,8 +65,8 @@ public static RouteNodeInfo get(Node node, RouteNodeGraph routingGraph) { endTile = node.getTile(); } - boolean ignoreLaguna = false; - RouteNodeType type = getType(node, endTile, routingGraph, ignoreLaguna); + boolean forceSink = false; + RouteNodeType type = getType(node, endTile, routingGraph, forceSink); short endTileXCoordinate = getEndTileXCoordinate(node, type, (short) endTile.getTileXCoordinate()); short endTileYCoordinate = (short) endTile.getTileYCoordinate(); short length = getLength(baseTile, type, endTileXCoordinate, endTileYCoordinate); @@ -126,7 +126,7 @@ private static short getEndTileXCoordinate(Node node, RouteNodeType type, short return endTileXCoordinate; } - public static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph routingGraph, boolean ignoreLaguna) { + public static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph routingGraph, boolean forceSink) { // NOTE: IntentCode is device-dependent IntentCode ic = node.getIntentCode(); TileTypeEnum tileTypeEnum = node.getTile().getTileTypeEnum(); @@ -152,7 +152,7 @@ public static RouteNodeType getType(Node node, Tile endTile, RouteNodeGraph rout if (routingGraph == null || routingGraph.isVersal) { return RouteNodeType.LOCAL_BOTH; } - if (routingGraph.lagunaI != null && !ignoreLaguna) { + if (routingGraph.lagunaI != null && !forceSink) { BitSet bs = routingGraph.lagunaI.get(node.getTile()); if (bs != null && bs.get(node.getWireIndex())) { return RouteNodeType.LAGUNA_PINFEED; From 7e5ff64fc74a9f98880530098dac741d54ba3e42 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Nov 2024 09:53:41 -0800 Subject: [PATCH 62/64] Address review comments Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/rwroute/RWRoute.java | 2 +- .../rapidwright/rwroute/RouteNodeGraph.java | 79 +++++++++++-------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 6d10be3e6..6eb800331 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -1837,10 +1837,10 @@ private void exploreAndExpand(ConnectionState state, RouteNode rnode) { continue; } switch (childRNode.getType()) { - case LOCAL_RESERVED: case LOCAL_BOTH: case LOCAL_EAST: case LOCAL_WEST: + case LOCAL_RESERVED: if (!routingGraph.isAccessible(childRNode, connection)) { continue; } diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 8b0e45f65..81e20e335 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -35,6 +35,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -146,6 +147,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map intTileIntentCodeCareSet; Pattern eastWestPattern; eastWestWires = new EnumMap<>(TileTypeEnum.class); BitSet wires = new BitSet(); @@ -154,6 +156,10 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); ultraScalesNonLocalWires.put(intTile.getTileTypeEnum(), wires); @@ -168,6 +174,12 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map new BitSet[]{new BitSet(), new BitSet()}); - BitSet eastWires = eastWestWires[0]; - BitSet westWires = eastWestWires[1]; - for (int wireIndex = 0; wireIndex < intfTile.getWireCount(); wireIndex++) { - IntentCode baseIntentCode = intfTile.getWireIntentCode(wireIndex); - if (baseIntentCode != IntentCode.NODE_INTF_BNODE && baseIntentCode != IntentCode.NODE_INTF_CNODE) { - continue; - } + // With NODE_CLE_[BC]NODEs being handled as part of the INT tile above, compute east/west wires + // in INTF_* tiles here + BiConsumer, Boolean> lambda = (types, east) -> { + for (TileTypeEnum tte : types) { + Tile intfTile = device.getArbitraryTileOfType(tte); + BitSet eastWestWires = this.eastWestWires.computeIfAbsent(tte, + k -> new BitSet[]{new BitSet(), new BitSet()})[east ? 0 : 1]; + for (int wireIndex = 0; wireIndex < intfTile.getWireCount(); wireIndex++) { + IntentCode baseIntentCode = intfTile.getWireIntentCode(wireIndex); + if (baseIntentCode != IntentCode.NODE_INTF_BNODE && baseIntentCode != IntentCode.NODE_INTF_CNODE) { + continue; + } + assert(Node.getNode(intfTile, wireIndex).getTile() == intfTile); - if (EnumSet.of(TileTypeEnum.INTF_LOCF_TR_TILE, - TileTypeEnum.INTF_LOCF_BR_TILE, - TileTypeEnum.INTF_ROCF_TR_TILE, - TileTypeEnum.INTF_ROCF_BR_TILE).contains(tte)) { - eastWires.set(wireIndex); - } else { - westWires.set(wireIndex); + eastWestWires.set(wireIndex); } } - } + }; + + lambda.accept(Arrays.asList( + TileTypeEnum.INTF_LOCF_TR_TILE, + TileTypeEnum.INTF_LOCF_BR_TILE, + TileTypeEnum.INTF_ROCF_TR_TILE, + TileTypeEnum.INTF_ROCF_BR_TILE), true); + lambda.accept(Arrays.asList( + TileTypeEnum.INTF_LOCF_TL_TILE, + TileTypeEnum.INTF_LOCF_BL_TILE, + TileTypeEnum.INTF_ROCF_TL_TILE, + TileTypeEnum.INTF_ROCF_BL_TILE), false); } if (lutRoutethru) { From ddbc8146c88c39bd1473f96b4ebfe77fed00ed54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Nov 2024 09:58:58 -0800 Subject: [PATCH 63/64] Fix polarity of assert Signed-off-by: Eddie Hung --- src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index 81e20e335..c3c99d582 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -232,7 +232,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map Date: Thu, 14 Nov 2024 10:08:44 -0800 Subject: [PATCH 64/64] Tidy Signed-off-by: Eddie Hung --- .../rapidwright/rwroute/RouteNodeGraph.java | 25 +++++++++---------- .../rapidwright/rwroute/RouteNodeInfo.java | 18 ++++++------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java index c3c99d582..b9cc7aa5d 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java +++ b/src/com/xilinx/rapidwright/rwroute/RouteNodeGraph.java @@ -103,10 +103,10 @@ public class RouteNodeGraph { /** Flag for whether LUT routethrus are to be considered */ protected final boolean lutRoutethru; - /** Map indicating (for UltraScale/UltraScale+ only) the wire indices that have a local intent code, - * but is what RWRoute will consider to be non-local, e.g. INT_NODE_SDQ_* + /** Map indicating (for UltraScale/UltraScale+ only) the subset wire indices of a NODE_LOCAL that are + * what RWRoute should assign a LOCAL_* type, e.g. excluding INT_NODE_SDQ_* */ - protected final Map ultraScalesNonLocalWires; + protected final Map ultraScalesLocalWires; /** Map indicating the wire indices corresponding to the east/west side of interconnect tiles */ protected final Map eastWestWires; @@ -150,7 +150,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map intTileIntentCodeCareSet; Pattern eastWestPattern; eastWestWires = new EnumMap<>(TileTypeEnum.class); - BitSet wires = new BitSet(); + BitSet localWires = new BitSet(); if (isUltraScale || isUltraScalePlus) { intTile = device.getArbitraryTileOfType(TileTypeEnum.INT); // Device.getArbitraryTileOfType() typically gives you the North-Western-most @@ -161,8 +161,8 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map(TileTypeEnum.class); - ultraScalesNonLocalWires.put(intTile.getTileTypeEnum(), wires); + ultraScalesLocalWires = new EnumMap<>(TileTypeEnum.class); + ultraScalesLocalWires.put(intTile.getTileTypeEnum(), localWires); eastWestPattern = Pattern.compile("(((BOUNCE|BYPASS|IMUX|INODE(_[12])?)_(?[EW]))|INT_NODE_IMUX_(?\\d+)_).*"); } else { @@ -181,7 +181,7 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map[EW]))|INT_NODE_IMUX_ATOM_(?\\d+)_).*"); } @@ -212,7 +212,6 @@ protected RouteNodeGraph(Design design, RWRouteConfig config, Map