Skip to content

Commit

Permalink
[RWRoute] Add "--lutPinSwapping" option (#895)
Browse files Browse the repository at this point in the history
* RWRoute to not create unused PINFEEDs, nor queue them unless in target tile

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

* Update TestRWRoute.testSLRCrossingNonTimingDriven

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

* Tidy

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

* Oops

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

* Refactor into RWRoute.isAccessiblePinfeedI()

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

* Connections to always be using its (single) sink rnode

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

* Cope with devices with no LAGUNA_Is

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

* Add comment

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

* RWRoute.shouldRoute() to not check first (sink) node for congestion

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

* RWRoute.ripUp/updateUsersAndPresentCongestionCost() to rip up all

Including the reserved sink node on unrouted connections

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

* Unroutable connections to undo ripUp() on sink

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

* Update comment

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

* Extend TestRouteThruHelper with SLICEM H[16] test

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

* Fix RouteThruHelper.isRouteThruPIPAvailable() for SLICEM.H[1-6]

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

* PartialRouter to use RouteNodeGraph.isExcludedTile()

instead of .isExcluded()

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

* Extend TestRouteThruHelper with SLICEM H[16] test

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

* Fix RouteThruHelper.isRouteThruPIPAvailable() for SLICEM.H[1-6]

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

* Undo verbose flag

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

* Restore original RWRoute.shouldRoute() but with extra assertion

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

* Add comment

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

* RouteNodeInfo to use RouteNodeGraph.lagunaI too

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

* Undo verbose flag

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

* Fix RouteNodeGraph's lagunaI construction

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

* Use null RouteNodeType instead of WIRE for default

Also update tests

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

* Update PartialRouter too

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

* Remove unused import

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

* RouteNode.setType() to allow demotion of PINfEED_I

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

* Tighten assertion

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

* Extend TestRouteThruHelper with SLICEM H[16] test

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

* Fix RouteThruHelper.isRouteThruPIPAvailable() for SLICEM.H[1-6]

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

* Apply suggestions from code review

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

* Add an assertion that PINFEED_I can never be overused

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

* Add RWRoute.isAccessiblePinfeedI() overload with no assertion

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

* Add TestNode.testNodeReachability()

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

* Add and use RWRoute.accessibleWireOnlySameColumnAsTarget

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

* NODE_LOCALs to be acccessible in Laguna columns for cross-SLR connections

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

* Skip if baseNode is null

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

* Print uphill/downhill

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

* Add reachability test for UltraScale too

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

* Move isAccessiblePinbounce() and make protected

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

* Tweak assertion

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

* Tidy up, add comments

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

* Update copyright year

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

* Compute RouteNodeGraph.lagunaI more accurately by going uphill from SLL

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

* Update SLR tests

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

* Also restrict NODE_LOCALs to be within one tile of sink too

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

* Update test

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

* Add support for multiple alternate sinks

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

* Fix compilation

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

* Extend TestDesignTools.testGetConnectedCells()

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

* LUT pin swapping enabled with "--lutPinSwapping"

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

* Fix flag

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

* Tidy up PinSwap and SATRouter

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

* Initial pin swap working

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

* Add testNonTimingDrivenFullRoutingWithLutPinSwapping()

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

* Add javadoc

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

* Refactor into LUTTools.swapLutPins()

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

* Add LUTTools.fixPinSwaps()

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

* Add TestLUTTools.testFixPinSwapsWithRWRoute()

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

* Add System prop rapidwright.rwroute.lutPinSwapping.deferIntraSiteRoutingUpdates

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

* Add standalone TestLUTTools.testFixPinSwaps()

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

* Add LUTTools.swapLutPins() and LUTTools.updateLutPinSwapsFromPIPs()

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

* Anticipate that no eligible pins to swap were found

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

* Rename to numberOfSwappablePins

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

* LUTTools to take Map<SitePinInst,String> for pinswaps instead

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

* LUTTools.swapLutPins() to not unroute intra-site net

Since SATRouter.processPinSwaps() will do it

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

* Add TestSATRouter

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

* Add copyright header

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

* Support and use 60 second timeout for test

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

* Fix RWRoute for new pinSwaps type

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

* Target nodes to not have occupancy > 1

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

* Revert "Support and use 60 second timeout for test"

This reverts commit a5a462b.

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

* Add TestSATRouter.testApplyResult()

Using a pre-canned solution

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

* Add LUTTools.swapLutPins() and LUTTools.updateLutPinSwapsFromPIPs()

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

* Update copyright year

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

* Refactor SATRouter.processPinSwaps() to LUTTools.swapSingleLutPins()

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

* LUTTools to take Map<SitePinInst,String> for pinswaps instead

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

Conflicts:
	src/com/xilinx/rapidwright/design/tools/LUTTools.java

* LUTTools.swapLutPins() to not unroute intra-site net

Since SATRouter.processPinSwaps() will do it

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

* Connection.setAllTargets() to not set if used by same net

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

* Allow NODE_PINBOUNCE

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

* Add assertion

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

* Print out unrouted SPIs

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

* Reset property

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

* Rename overload to swapMultipleLutPins

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

* Remove old file

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

* Revert "Print out unrouted SPIs"

This reverts commit ba7464e.

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

* Update to new overload

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

* Refactor/rename/tidy

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

* Use LUTTools.MAX_LUT_SIZE constant

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

* Add support for simulating LUT pin swaps

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

* Refactor/rename/tidy up

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

* Reduce diff with master

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

* Add missing import

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

* Add explanation for new option, tidy

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

* Add TestPhysNetlistWriter.testSimulateSwappedLutPinsWithRWRoute()

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

* Update test/src/com/xilinx/rapidwright/design/tools/TestLUTTools.java

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

* Do not pin swap fixed pins

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

* Fix tests

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

* Rename to swapLutPinsFromPIPs()

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

* Update test

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

* Update tests

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

* Fix javadoc

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

* Add assertion

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

* Fix tests

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

* Handle case where exclusive LUT sinks can be overused

(e.g. when only some pins on the LUT cell are fixed)

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

* Revert "Handle case where exclusive LUT sinks can be overused"

This reverts commit aab686b.

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

* Add comment

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

* Remove all exclusive sinks that are alternate sinks on other conn-s

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

* Revert interchange changes

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

* Fix/add comments

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

* Fix exclusive sinks for PartialRouter

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

* Cleanup

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

* Extend assertion

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

* Do not use Cell.isPinFixed() as that doesn't capture LOCK_PIN-s

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

* Update comment

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

* Update test

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

* Remove irrelevant test

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

* Allow alternate sinks that are not PINFEED_Is even if occupied

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

* Simplify early termination

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

* Skip if no rnodes

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

* Always set nodes

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

* Apply suggestions from code review

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

* Simplify assignNodesToConnections()

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

* Expand comment/assertion

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

* Do not update sinkRnode when deferring pin swaps

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

* Remove verbose

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

* Invert condition

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

* Apply suggestions from code review

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

---------

Signed-off-by: Eddie Hung <[email protected]>
Signed-off-by: eddieh-xlnx <[email protected]>
  • Loading branch information
eddieh-xlnx authored Dec 1, 2023
1 parent b273d2d commit 7097956
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/com/xilinx/rapidwright/design/DesignTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,7 @@ public static boolean stampPlacement(Design design, Module stamp, Map<String,Sit
/**
* Looks in the site instance for BEL pins connected to this site pin.
* @param pin The SitePinInst to examine for connected BEL pins
* param action Perform this action on each conncted BELPin
* @param action Perform this action on each connected BELPin.
*/
private static void foreachConnectedBELPin(SitePinInst pin, Consumer<BELPin> action) {
SiteInst si = pin.getSiteInst();
Expand Down
52 changes: 43 additions & 9 deletions src/com/xilinx/rapidwright/rwroute/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
package com.xilinx.rapidwright.rwroute;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.xilinx.rapidwright.device.IntentCode;
import com.xilinx.rapidwright.design.Net;
import com.xilinx.rapidwright.design.SitePinInst;
import com.xilinx.rapidwright.device.Node;
Expand All @@ -49,7 +51,7 @@ public class Connection implements Comparable<Connection>{
private RouteNode sourceRnode;
private RouteNode altSourceRnode;
private RouteNode sinkRnode;
private RouteNode altSinkRnode;
private List<RouteNode> altSinkRnodes;
/**
* true to indicate the source and the sink are connected through dedicated resources,
* such as the carry chain connections and connections between cascaded BRAMs.
Expand Down Expand Up @@ -294,13 +296,25 @@ public RouteNode getSinkRnode() {
return sinkRnode;
}

public void setSinkRnode(RouteNode childRnode) {
sinkRnode = childRnode;
public void setSinkRnode(RouteNode sinkRnode) {
this.sinkRnode = sinkRnode;
}

public RouteNode getAltSinkRnode() { return altSinkRnode; }
public List<RouteNode> getAltSinkRnodes() {
return altSinkRnodes == null ? Collections.emptyList() : altSinkRnodes;
}

public void setAltSinkRnode(RouteNode childRnode) { altSinkRnode = childRnode; }
public void addAltSinkRnode(RouteNode sinkRnode) {
if (altSinkRnodes == null) {
altSinkRnodes = new ArrayList<>(1);
} else {
assert(!altSinkRnodes.contains(sinkRnode));
}
assert(sinkRnode.getType() == RouteNodeType.PINFEED_I ||
// Can be a WIRE if node is not exclusive a sink
sinkRnode.getType() == RouteNodeType.WIRE);
altSinkRnodes.add(sinkRnode);
}

public short getXMinBB() {
return xMinBB;
Expand Down Expand Up @@ -467,10 +481,30 @@ public String toString() {
return s.toString();
}

public void setTarget(boolean target) {
sinkRnode.setTarget(target);
if (altSinkRnode != null) {
altSinkRnode.setTarget(target);
public void setAllTargets(boolean target) {
if (sinkRnode.countConnectionsOfUser(netWrapper) == 0 ||
sinkRnode.getNode().getIntentCode() == IntentCode.NODE_PINBOUNCE) {
// Since this connection will have been ripped up, only mark a node
// as a target if it's not already used by this net.
// This prevents -- for the case where the same net needs to be routed
// to the same LUT more than once -- the illegal case of the same
// physical pin servicing more than one logical pin
sinkRnode.setTarget(target);
} else {
assert(altSinkRnodes != null && !altSinkRnodes.isEmpty());
}
if (altSinkRnodes != null) {
for (RouteNode rnode : altSinkRnodes) {
// Same condition as above: only allow this as an alternate sink
// if it's not already in use by the current net to prevent the case
// 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) {
assert(rnode.getNode().getIntentCode() != IntentCode.NODE_PINBOUNCE);
rnode.setTarget(target);
}
}
}
}
}
37 changes: 33 additions & 4 deletions src/com/xilinx/rapidwright/rwroute/PartialRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -353,17 +354,19 @@ protected void determineRoutingTargets() {
// (it's possible for another connection to use a bounce node, but now that node is
// needed as a site pin)
for (Connection connection : netWrapper.getConnections()) {
for (RouteNode rnode : Arrays.asList(connection.getSinkRnode(), connection.getAltSinkRnode())) {
Consumer<RouteNode> action = (rnode) -> {
if (rnode == null) {
continue;
return;
}
RouteNode prev = rnode.getPrev();
if (prev == null) {
continue;
return;
}
stashedPrev.put(rnode, prev);
rnode.clearPrev();
}
};
action.accept(connection.getSinkRnode());
connection.getAltSinkRnodes().forEach(action);
}

// Create all nodes used by this net and set its previous pointer so that:
Expand Down Expand Up @@ -395,7 +398,20 @@ protected void determineRoutingTargets() {
RouteNode sinkRnode = connection.getSinkRnode();
assert(sourceRnode.getType() == RouteNodeType.PINFEED_O);
assert(sinkRnode.getType() == RouteNodeType.PINFEED_I);

// Even though this connection is not expected to have any routing yet,
// perform a rip up anyway in order to release any exclusive sinks
// ahead of finishRouteConnection()
assert(connection.getRnodes().isEmpty());
connection.getSink().setRouted(false);
ripUp(connection);

finishRouteConnection(connection, sinkRnode);
if (!connection.getSink().isRouted() && connection.getAltSinkRnodes().isEmpty()) {
// Undo what ripUp() did for this connection which has a single exclusive sink
sinkRnode.incrementUser(connection.getNetWrapper());
sinkRnode.updatePresentCongestionCost(presentCongestionFactor);
}
}

// Restore prev to avoid assertions firing
Expand Down Expand Up @@ -631,7 +647,20 @@ protected void unpreserveNet(Net net) {
RouteNode sinkRnode = connection.getSinkRnode();
assert(sourceRnode.getType() == RouteNodeType.PINFEED_O);
assert(sinkRnode.getType() == RouteNodeType.PINFEED_I);

// Even though this connection is not expected to have any routing yet,
// perform a rip up anyway in order to release any exclusive sinks
// ahead of finishRouteConnection()
assert(connection.getRnodes().isEmpty());
connection.getSink().setRouted(false);
ripUp(connection);

finishRouteConnection(connection, sinkRnode);
if (!connection.getSink().isRouted() && connection.getAltSinkRnodes().isEmpty()) {
// Undo what ripUp() did for this connection which has a single exclusive sink
sinkRnode.incrementUser(connection.getNetWrapper());
sinkRnode.updatePresentCongestionCost(presentCongestionFactor);
}
}

netToPins.put(net, net.getSinkPins());
Expand Down
Loading

0 comments on commit 7097956

Please sign in to comment.