Skip to content

Commit

Permalink
Refactor into RouteNodeInfo class
Browse files Browse the repository at this point in the history
Signed-off-by: Eddie Hung <[email protected]>
  • Loading branch information
eddieh-xlnx committed Mar 6, 2023
1 parent 5e1e4a5 commit 088b335
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 161 deletions.
171 changes: 10 additions & 161 deletions src/com/xilinx/rapidwright/rwroute/RouteNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.Tile;
import com.xilinx.rapidwright.device.TileTypeEnum;
import com.xilinx.rapidwright.device.Wire;
import com.xilinx.rapidwright.util.RuntimeTracker;
import com.xilinx.rapidwright.util.Utils;

import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -54,12 +52,12 @@ abstract public class RouteNode implements Comparable<RouteNode> {
/** The associated {@link Node} instance */
protected Node node;
/** The type of a rnode*/
private RouteNodeType type;
private final RouteNodeType type;
/** The tileXCoordinate and tileYCoordinate of the INT tile that the associated node stops at */
private short endTileXCoordinate;
private short endTileYCoordinate;
private final short endTileXCoordinate;
private final short endTileYCoordinate;
/** The wirelength of a rnode */
private short length;
private final short length;
/** The base cost of a rnode */
private float baseCost;
/** A flag to indicate if this rnode is the target */
Expand Down Expand Up @@ -98,11 +96,12 @@ abstract public class RouteNode implements Comparable<RouteNode> {

protected RouteNode(Node node, RouteNodeType type) {
this.node = node;
NodeInfo nodeInfo = getNodeInfo(node);
setType(type, nodeInfo);
RouteNodeInfo nodeInfo = RouteNodeInfo.get(node);
this.type = (type == RouteNodeType.WIRE) ? nodeInfo.type : type;
endTileXCoordinate = nodeInfo.endTileXCoordinate;
endTileYCoordinate = nodeInfo.endTileYCoordinate;
length = nodeInfo.length;
children = null;
setLength(nodeInfo);
setEndTileXYCoordinates(nodeInfo);
setBaseCost();
presentCongestionCost = initialPresentCongestionCost;
historicalCongestionCost = initialHistoricalCongestionCost;
Expand Down Expand Up @@ -246,111 +245,8 @@ public boolean hasMultiDrivers() {
return RouteNode.capacity < uniqueDriverCount();
}

public static class NodeInfo {
public final short endTileXCoordinate;
public final short endTileYCoordinate;
public final short length;
public final boolean pinfeedIntoLaguna;

public NodeInfo(short endTileXCoordinate,
short endTileYCoordinate,
short length,
boolean laguna_i) {
this.endTileXCoordinate = endTileXCoordinate;
this.endTileYCoordinate = endTileYCoordinate;
this.length = length;
this.pinfeedIntoLaguna = laguna_i;
}
}

private static NodeInfo getNodeInfo(Node node) {
Wire[] wires = node.getAllWiresInNode();
Tile baseTile = node.getTile();
TileTypeEnum baseType = baseTile.getTileTypeEnum();
Tile endTile = null;
boolean laguna_i = false;
for (Wire w : wires) {
Tile tile = w.getTile();
TileTypeEnum tileType = tile.getTileTypeEnum();
boolean lagunaTile = false;
if (tileType == TileTypeEnum.INT ||
(lagunaTile = Utils.isLaguna(tileType))) {
if (!lagunaTile ||
// Only consider a Laguna tile as an end tile if base tile is Laguna too
// (otherwise it's a PINFEED into a Laguna)
Utils.isLaguna(baseType)) {
boolean endTileWasNotNull = (endTile != null);
endTile = tile;
// Break if this is the second INT tile
if (endTileWasNotNull) break;
} else {
assert(!Utils.isLaguna(baseType));
laguna_i = (node.getIntentCode() == IntentCode.NODE_PINFEED);
}
}
}
if (endTile == null) {
endTile = node.getTile();
}

short endTileXCoordinate = (short) endTile.getTileXCoordinate();
short endTileYCoordinate = (short) endTile.getTileYCoordinate();
short length = (short) (Math.abs(endTileXCoordinate - baseTile.getTileXCoordinate())
+ Math.abs(endTileYCoordinate - baseTile.getTileYCoordinate()));

return new NodeInfo(endTileXCoordinate, endTileYCoordinate, length, laguna_i);
}

public static short getLength(Node node) {
return getNodeInfo(node).length;
}

private void setLength(NodeInfo nodeInfo) {
length = nodeInfo.length;

TileTypeEnum tileType = node.getTile().getTileTypeEnum();
switch (tileType) {
case LAG_LAG:
case LAGUNA_TILE:
if (type == RouteNodeType.SUPER_LONG_LINE) {
assert(length == RouteNodeGraph.SUPER_LONG_LINE_LENGTH_IN_TILES);
} else {
if (length != 0) {
assert(type == RouteNodeType.WIRE);
assert(length == 1);
length = 0;
}
}
break;
case INT:
if (type == RouteNodeType.LAGUNA_I) {
assert(length == 0);
}
}
}

private void setEndTileXYCoordinates(NodeInfo nodeInfo) {
endTileXCoordinate = nodeInfo.endTileXCoordinate;
endTileYCoordinate = nodeInfo.endTileYCoordinate;

Tile tile = node.getTile();
TileTypeEnum tileType = tile.getTileTypeEnum();
if (tileType == TileTypeEnum.LAG_LAG) { // UltraScale+ only
// Correct the X coordinate of all Laguna nodes since they are accessed by the INT
// tile to its right, yet the LAG tile has a tile X coordinate one less than this.
// Do not apply this correction for NODE_LAGUNA_OUTPUT nodes (which the fanin and
// 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) &&
!node.isTiedToVcc()) {
assert(tile.getTileXCoordinate() == endTileXCoordinate);
endTileXCoordinate++;
}
} else if (tileType == TileTypeEnum.LAGUNA_TILE) { // UltraScale only
// In UltraScale, Laguna tiles have the same X as the base INT tile
assert(tile.getTileXCoordinate() == endTileXCoordinate);
}
return RouteNodeInfo.get(node).length;
}

/**
Expand Down Expand Up @@ -508,53 +404,6 @@ public void resetChildren() {
children = null;
}

private void setType(RouteNodeType type, NodeInfo nodeInfo) {
this.type = type;
if (type == RouteNodeType.WIRE) {
// NOTE: IntentCode is device-dependent
IntentCode ic = node.getIntentCode();
switch (ic) {
case NODE_PINBOUNCE:
this.type = RouteNodeType.PINBOUNCE;
break;

case NODE_PINFEED:
this.type = nodeInfo.pinfeedIntoLaguna ? RouteNodeType.LAGUNA_I : RouteNodeType.PINFEED_I;
break;

case NODE_LAGUNA_OUTPUT: // UltraScale+ only
assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG);
if (node.getWireName().endsWith("_TXOUT")) {
this.type = RouteNodeType.LAGUNA_I;
}
break;

case NODE_LAGUNA_DATA: // UltraScale+ only
assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG);
if (nodeInfo.length == RouteNodeGraph.SUPER_LONG_LINE_LENGTH_IN_TILES) {
this.type = RouteNodeType.SUPER_LONG_LINE;
} else {
// U-turn node at the boundary of the device
assert(nodeInfo.length == 0);
assert(this.type == RouteNodeType.WIRE);
}
break;

case INTENT_DEFAULT:
if (node.getTile().getTileTypeEnum() == TileTypeEnum.LAGUNA_TILE) { // UltraScale only
String wireName = node.getWireName();
if (wireName.startsWith("UBUMP")) {
this.type = RouteNodeType.SUPER_LONG_LINE;
} else if (wireName.endsWith("_TXOUT")) {
// This is the inner LAGUNA_I, mark it so it gets a base cost discount
this.type = RouteNodeType.LAGUNA_I;
}
}
break;
}
}
}

/**
* Gets the wirelength.
* @return The wirelength, i.e. the number of INT tiles that the associated {@link Node} instance spans.
Expand Down
175 changes: 175 additions & 0 deletions src/com/xilinx/rapidwright/rwroute/RouteNodeInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* Copyright (c) 2023, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Author: Eddie Hung, Advanced Micro Devices, Inc.
*
* This file is part of RapidWright.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.xilinx.rapidwright.rwroute;

import com.xilinx.rapidwright.device.IntentCode;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.Tile;
import com.xilinx.rapidwright.device.TileTypeEnum;
import com.xilinx.rapidwright.device.Wire;
import com.xilinx.rapidwright.util.Utils;

public class RouteNodeInfo {
public final RouteNodeType type;
public final short endTileXCoordinate;
public final short endTileYCoordinate;
public final short length;

private RouteNodeInfo(RouteNodeType type,
short endTileXCoordinate,
short endTileYCoordinate,
short length) {
this.type = type;
this.endTileXCoordinate = endTileXCoordinate;
this.endTileYCoordinate = endTileYCoordinate;
this.length = length;
}

public static RouteNodeInfo get(Node node) {
Wire[] wires = node.getAllWiresInNode();
Tile baseTile = node.getTile();
TileTypeEnum baseType = baseTile.getTileTypeEnum();
Tile endTile = null;
boolean pinfeedIntoLaguna = false;
for (Wire w : wires) {
Tile tile = w.getTile();
TileTypeEnum tileType = tile.getTileTypeEnum();
boolean lagunaTile = false;
if (tileType == TileTypeEnum.INT ||
(lagunaTile = Utils.isLaguna(tileType))) {
if (!lagunaTile ||
// Only consider a Laguna tile as an end tile if base tile is Laguna too
// (otherwise it's a PINFEED into a Laguna)
Utils.isLaguna(baseType)) {
boolean endTileWasNotNull = (endTile != null);
endTile = tile;
// Break if this is the second INT tile
if (endTileWasNotNull) break;
} else {
assert(!Utils.isLaguna(baseType));
pinfeedIntoLaguna = (node.getIntentCode() == IntentCode.NODE_PINFEED);
}
}
}
if (endTile == null) {
endTile = node.getTile();
}

RouteNodeType type = getType(node, endTile, pinfeedIntoLaguna);
short endTileXCoordinate = getEndTileXCoordinate(node, type, (short) endTile.getTileXCoordinate());
short endTileYCoordinate = (short) endTile.getTileYCoordinate();
short length = getLength(baseTile, type, endTileXCoordinate, endTileYCoordinate);

return new RouteNodeInfo(type, endTileXCoordinate, endTileYCoordinate, length);
}

private static short getLength(Tile baseTile, RouteNodeType type, short endTileXCoordinate, short endTileYCoordinate) {
short length = (short) (Math.abs(endTileXCoordinate - baseTile.getTileXCoordinate())
+ Math.abs(endTileYCoordinate - baseTile.getTileYCoordinate()));
switch (baseTile.getTileTypeEnum()) {
case LAG_LAG:
length--;
// Fall through
case LAGUNA_TILE:
if (type == RouteNodeType.SUPER_LONG_LINE) {
assert(length == RouteNodeGraph.SUPER_LONG_LINE_LENGTH_IN_TILES);
} else {
assert(length == 0);
}
break;
case INT:
if (type == RouteNodeType.LAGUNA_I) {
assert(length == 0);
}
}
return length;
}

private static short getEndTileXCoordinate(Node node, RouteNodeType type, short endTileXCoordinate) {
Tile baseTile = node.getTile();
TileTypeEnum baseType = baseTile.getTileTypeEnum();
switch (baseType) {
case LAG_LAG: // UltraScale+ only
// Correct the X coordinate of all Laguna nodes since they are accessed by the INT
// tile to its right, yet the LAG tile has a tile X coordinate one less than this.
// Do not apply this correction for NODE_LAGUNA_OUTPUT nodes (which the fanin and
// 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) &&
!node.isTiedToVcc()) {
assert(baseTile.getTileXCoordinate() == endTileXCoordinate);
endTileXCoordinate++;
}
break;
case LAGUNA_TILE: // UltraScale only
// In UltraScale, Laguna tiles have the same X as the base INT tile
assert(baseTile.getTileXCoordinate() == endTileXCoordinate);
break;
}
return endTileXCoordinate;
}

private static RouteNodeType getType(Node node, Tile endTile, boolean pinfeedIntoLaguna) {
// NOTE: IntentCode is device-dependent
IntentCode ic = node.getIntentCode();
switch (ic) {
case NODE_PINBOUNCE:
return RouteNodeType.PINBOUNCE;

case NODE_PINFEED:
return pinfeedIntoLaguna ? RouteNodeType.LAGUNA_I : RouteNodeType.PINFEED_I;

case NODE_LAGUNA_OUTPUT: // UltraScale+ only
assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG);
if (node.getWireName().endsWith("_TXOUT")) {
return RouteNodeType.LAGUNA_I;
}
break;

case NODE_LAGUNA_DATA: // UltraScale+ only
assert(node.getTile().getTileTypeEnum() == TileTypeEnum.LAG_LAG);
if (node.getTile() != endTile) {
return RouteNodeType.SUPER_LONG_LINE;
}

// U-turn node at the boundary of the device
break;

case INTENT_DEFAULT:
if (node.getTile().getTileTypeEnum() == TileTypeEnum.LAGUNA_TILE) { // UltraScale only
String wireName = node.getWireName();
if (wireName.startsWith("UBUMP")) {
assert(node.getTile() != endTile);
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;
}
}
break;
}

return RouteNodeType.WIRE;
}
}

0 comments on commit 088b335

Please sign in to comment.