Skip to content

Commit

Permalink
Add Hybrid Updating Strategy (HUS) (#1043)
Browse files Browse the repository at this point in the history
* Add Hybrid Updating Strategy (HUS)

Signed-off-by: Wenhao Lin <[email protected]>

* Tab to spaces

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

* Cleanup

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

* [TestRWRoute] Add testNonTimingDrivenFullRoutingWithHUS()

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

* Move INFO message until after routing stats

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

* Update comment

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

* Refactor some variables that begin with capital letters

Signed-off-by: Wenhao Lin <[email protected]>

* Go back to 'hus' prefix; option now `--hus`

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

* Use sortedIndirectConnections.size()

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

* Emit some warnings

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

---------

Signed-off-by: Wenhao Lin <[email protected]>
Signed-off-by: Eddie Hung <[email protected]>
Co-authored-by: Eddie Hung <[email protected]>
  • Loading branch information
diriLin and eddieh-xlnx authored Aug 14, 2024
1 parent 3715835 commit 63c8bd1
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 1 deletion.
62 changes: 61 additions & 1 deletion src/com/xilinx/rapidwright/rwroute/RWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import java.util.PriorityQueue;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.xilinx.rapidwright.design.Cell;
import com.xilinx.rapidwright.design.Design;
Expand Down Expand Up @@ -122,6 +121,11 @@ public class RWRoute{
/** Flag for whether LUT routethrus are to be considered */
protected boolean lutRoutethru;

/** Flag for use of Hybrid Updating Strategy (HUS) */
private boolean hus;
/** Flag (computed at end of iteration 1) to indicate design is congested enough to consider HUS */
private boolean husInitialCongested;

/** The current routing iteration */
protected int routeIteration;
/** Timers to store runtime of different phases */
Expand Down Expand Up @@ -252,6 +256,9 @@ protected void initialize() {
nodesPopped = 0;
overUsedRnodes = new HashSet<>();

hus = config.isHus();
husInitialCongested = false;

routerTimer.getRuntimeTracker("Initialization").stop();
}

Expand Down Expand Up @@ -857,6 +864,7 @@ public void routeIndirectConnections() {
long lastIterationRnodeCount = 0;
long lastIterationRnodeTime = 0;

boolean initialHus = this.hus;
while (routeIteration < config.getMaxIterations()) {
long startIteration = System.nanoTime();
connectionsRoutedIteration = 0;
Expand Down Expand Up @@ -904,6 +912,11 @@ public void routeIndirectConnections() {
}
}

if (initialHus && !hus) {
System.out.println("INFO: Hybrid Updating Strategy (HUS) activated");
initialHus = false;
}

routeIteration++;
lastIterationRnodeCount = routingGraph.numNodes();
lastIterationRnodeTime = rnodesTimer.getTime();
Expand Down Expand Up @@ -1240,9 +1253,15 @@ private void printRoutingIterationStatisticsInfo(float iterationRuntime, float r
*/
private void updateCostFactors() {
updateCongestionCosts.start();

checkHus();

// Inflate the present congestion factor
presentCongestionFactor *= config.getPresentCongestionMultiplier();
presentCongestionFactor = Math.min(presentCongestionFactor, config.getMaxPresentCongestionFactor());

updateCost();

updateCongestionCosts.stop();
}

Expand All @@ -1266,6 +1285,47 @@ private void updateCost() {
}
}

/**
* Check whether to activate Hybrid Updating Strategy (HUS)
*/
private void checkHus() {
if (!hus) {
return;
}

if (routeIteration == 1) {
// Count the number of overused nodes
long overUseCnt = 0;
for (RouteNode rnode : routingGraph.getRnodes()) {
if (rnode.isOverUsed()) {
overUseCnt++;
}
}
husInitialCongested = (float) overUseCnt / sortedIndirectConnections.size() > config.getHusInitialCongestedThreshold();
}

if (husInitialCongested) {
float congestedConnRatio = (float) connectionsRoutedIteration / sortedIndirectConnections.size();
if (congestedConnRatio < config.getHusActivateThreshold()) {
// Activate HUS: slow down the present cost growth and increase historical cost growth instead
float husAlpha = config.getHusAlpha();
if (husAlpha >= config.getPresentCongestionMultiplier()) {
System.out.println("WARNING: HUS alpha is not less than the current present congestion multiplier.");
}
config.setPresentCongestionMultiplier(husAlpha);

float husBeta = config.getHusBeta();
if (husBeta <= historicalCongestionFactor) {
System.out.println("WARNING: HUS beta is not greater than the current historical congestion factor.");
}
historicalCongestionFactor = husBeta;

// Disable HUS from being activated again
hus = false;
}
}
}

/**
* Computes node usage of each type and the total wirelength of the design.
*/
Expand Down
133 changes: 133 additions & 0 deletions src/com/xilinx/rapidwright/rwroute/RWRouteConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ public class RWRouteConfig {
private boolean lutRoutethru;
/* true to enable GND -> VCC optimization for LUT inputs */
private boolean invertGndToVccForLutInputs;
/* true to use HUS */
private boolean hus;
/* The value of alpha in HUS*/
private float husAlpha;
/* The value of Beta in HUS*/
private float husBeta;
/* The threshold for determining whether a case is a congested design in HUS */
private float husInitialCongestedThreshold;
/* The threshold for determining whether to start using historical-centric updating in HUS */
private float husActivateThreshold;

/** Constructs a Configuration Object */
public RWRouteConfig(String[] arguments) {
Expand Down Expand Up @@ -125,6 +135,11 @@ public RWRouteConfig(String[] arguments) {
lutPinSwapping = false;
lutRoutethru = false;
invertGndToVccForLutInputs = true;
hus = false;
husAlpha = 1.1f;
husBeta = 2f;
husInitialCongestedThreshold = 0.5f;
husActivateThreshold = 0.4f;
if (arguments != null) {
parseArguments(arguments);
}
Expand Down Expand Up @@ -233,6 +248,21 @@ private void parseArguments(String[] arguments) {
case "--noInvertGndToVccForLutInputs":
setInvertGndToVccForLutInputs(false);
break;
case "--hus":
setHus(true);
break;
case "--husAlpha":
setHusAlpha(Float.parseFloat(arguments[++i]));
break;
case "--husBeta":
setHusBeta(Float.parseFloat(arguments[++i]));
break;
case "--husInitialCongestedThreshold":
setHusInitialCongestedThreshold(Float.parseFloat(arguments[++i]));
break;
case "--husActivateThreshold":
setHusActivateThreshold(Float.parseFloat(arguments[++i]));
break;
default:
throw new IllegalArgumentException("ERROR: RWRoute argument '" + arg + "' not recognized.");
}
Expand Down Expand Up @@ -886,6 +916,102 @@ public void setVerbose(boolean verbose) {
this.verbose = verbose;
}

/** Checks if the hybrid updating strategy (HUS) is enabled.
* HUS will, once its user-configurable thresholds are met, slow down the growth of present costs of used nodes and
* instead increases the growth of overused nodes' historical costs.
* Default: false.
*/
public boolean isHus() {
return hus;
}

/**
* Sets whether hybrid updating strategy (HUS) is enabled.
* HUS will, once its user-configurable thresholds are met, slow down the growth of present costs of used nodes and
* instead increases the growth of overused nodes' historical costs.
* Default: false.
* @param hus true to enable the hybrid updating strategy (HUS)
*/
public void setHus(boolean hus) {
this.hus = hus;
}

/**
* Gets the value of alpha in the hybrid updating strategy (HUS)
* Default: 1.1
* @return the value of alpha in the hybrid updating strategy (HUS)
*/
public float getHusAlpha() {
return husAlpha;
}

/**
* Sets the value of alpha in the hybrid updating strategy (HUS)
* Default: 1.1
* @param husAlpha the value of alpha in the hybrid updating strategy (HUS)
*/
public void setHusAlpha(float husAlpha) {
this.husAlpha = husAlpha;
}

/**
* Gets the value of beta in the hybrid updating strategy (HUS)
* Default: 2.0
* @return the value of beta in the hybrid updating strategy (HUS)
*/
public float getHusBeta() {
return husBeta;
}

/**
* Sets the value of beta in the hybrid updating strategy (HUS)
* Default: 2.0
* @param husBeta the value of beta in the hybrid updating strategy (HUS)
*/
public void setHusBeta(float husBeta) {
this.husBeta = husBeta;
}

/**
* Gets the threshold (number of overused nodes at the end of routing iteration 1 divided by
* total number of connections to be routed) above which a design is congested enough to consider HUS
* Default: 0.5
* @return the threshold for determining whether a design is congested enough to consider HUS
*/
public float getHusInitialCongestedThreshold() {
return husInitialCongestedThreshold;
}

/**
* Sets the threshold (number of overused nodes at the end of routing iteration 1 divided by
* total number of connections to be routed) above which a design is congested enough to consider HUS
* Default: 0.5
* @param husInitialCongestedThreshold the threshold for determining whether a design is congested enough to consider HUS
*/
public void setHusInitialCongestedThreshold(float husInitialCongestedThreshold) {
this.husInitialCongestedThreshold = husInitialCongestedThreshold;
}

/**
* Gets the threshold (number of congested connections at the end of the routing iteration divided by
* total number of connections to be routed) below which HUS will be activated
* Default: 0.4
* @return the threshold for determining whether to activate HUS
*/
public float getHusActivateThreshold() {
return husActivateThreshold;
}

/**
* Sets the threshold (number of congested connections at the end of the routing iteration divided by
* total number of connections to be routed) below which HUS will be activated
* Default: 0.4
* @param husActivateThreshold the threshold for determining whether to activate HUS
*/
public void setHusActivateThreshold(float husActivateThreshold) {
this.husActivateThreshold = husActivateThreshold;
}

@Override
public String toString() {
StringBuilder s = new StringBuilder();
Expand Down Expand Up @@ -922,6 +1048,13 @@ public String toString() {
s.append(MessageGenerator.formatString("Historical congestion factor: ", historicalCongestionFactor));
s.append(MessageGenerator.formatString("LUT pin swapping: ", isLutPinSwapping()));
s.append(MessageGenerator.formatString("LUT routethrus: ", isLutRoutethru()));
s.append(MessageGenerator.formatString("Use Hybrid Updating Strategy: ", isHus()));
if (isHus()) {
s.append(MessageGenerator.formatString("HUS alpha: ", husAlpha));
s.append(MessageGenerator.formatString("HUS beta: ", husBeta));
s.append(MessageGenerator.formatString("HUS initial congested threshold: ", husInitialCongestedThreshold));
s.append(MessageGenerator.formatString("HUS activate threshold: ", husActivateThreshold));
}

return s.toString();
}
Expand Down
14 changes: 14 additions & 0 deletions test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,20 @@ public void testNonTimingDrivenFullRoutingWithLutRoutethru(String path) {
VivadoToolsHelper.assertFullyRouted(design);
}

@ParameterizedTest
@ValueSource(strings = {
"bnn.dcp", // does not activate HUS
"optical-flow.dcp" // activates HUS
})
@LargeTest(max_memory_gb = 8)
public void testNonTimingDrivenFullRoutingWithHUS(String path) {
Design design = RapidWrightDCP.loadDCP(path);
RWRoute.routeDesignWithUserDefinedArguments(design, new String[] {"--nonTimingDriven", "--hus"});
assertAllSourcesRoutedFlagSet(design);
assertAllPinsRouted(design);
VivadoToolsHelper.assertFullyRouted(design);
}

/**
* Tests the timing driven full routing, i.e., RWRoute running in timing-driven mode.
* The bnn design from Rosetta benchmarks is used.
Expand Down

0 comments on commit 63c8bd1

Please sign in to comment.