Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RouterHelper.invertPossibleGndPinsToVccPins() to invert static LUT inputs #910

Merged
merged 61 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
57b54e6
RouterHelper.invertPossibleGndPinsToVccPins() to invert LUT inputs
eddieh-xlnx Dec 6, 2023
b204a6d
Check all connected cells are LUTs before inverting
eddieh-xlnx Dec 6, 2023
cc57b78
Add testInvertPossibleGndPinsToVccPinsLutInput()
eddieh-xlnx Dec 6, 2023
4200885
Address review comments
eddieh-xlnx Dec 7, 2023
4eae089
Merge remote-tracking branch 'upstream/master' into routerhelper_inve…
eddieh-xlnx Dec 8, 2023
fb8ab6e
Do not invert SRL16E pins
eddieh-xlnx Dec 8, 2023
f7d5bd6
EDIFCell to track instantiations via atomic int
eddieh-xlnx Dec 11, 2023
b916dee
Add test
eddieh-xlnx Dec 11, 2023
afc7115
Update src/com/xilinx/rapidwright/edif/EDIFCell.java
eddieh-xlnx Dec 11, 2023
a0c5b8f
Merge remote-tracking branch 'upstream/edifcell_instancecount' into r…
eddieh-xlnx Dec 13, 2023
5f4f2f3
Skip XDEF where possible
eddieh-xlnx Dec 13, 2023
3ae42b0
Add and test EDIFCell.isUniquified()
eddieh-xlnx Dec 13, 2023
fdbf9f8
Add and test EDIFHierCellInst.isUniquified()
eddieh-xlnx Dec 13, 2023
5aca714
Do not invert if LUT is not uniquified
eddieh-xlnx Dec 13, 2023
b461fda
Removed unused imports
eddieh-xlnx Dec 13, 2023
493d920
Remove TODO
eddieh-xlnx Dec 13, 2023
221fba5
Skip XDEF where possible
eddieh-xlnx Dec 13, 2023
697245a
Add and test EDIFCell.isUniquified()
eddieh-xlnx Dec 13, 2023
1fc8fdf
Add and test EDIFHierCellInst.isUniquified()
eddieh-xlnx Dec 13, 2023
392f3b8
{Inc,dec}rement instance count during EDIFCell.{add,remove}CellInst()
eddieh-xlnx Dec 13, 2023
1057e06
EDIFCellInst.setCellTypeRaw() to only incr instance count if parent
eddieh-xlnx Dec 13, 2023
85bf507
Improve TestEDIFCell tests
eddieh-xlnx Dec 13, 2023
9277594
Improve TestEDIF{Hier,}CellInst too
eddieh-xlnx Dec 13, 2023
f463951
Merge branch 'edifcell_instancecount' into routerhelper_invertlutgnd
eddieh-xlnx Dec 13, 2023
ffbffe8
Add null check
eddieh-xlnx Dec 13, 2023
072a07d
Merge branch 'edifcell_instancecount' into routerhelper_invertlutgnd
eddieh-xlnx Dec 13, 2023
d104126
Another null check
eddieh-xlnx Dec 13, 2023
24060ad
Merge branch 'edifcell_instancecount' into routerhelper_invertlutgnd
eddieh-xlnx Dec 13, 2023
8050e3d
EDIFCellInst.isUniquified() only true if has parent cell
eddieh-xlnx Dec 14, 2023
b885e54
EDIFHierCellInst.isUniquified() to not check top level inst
eddieh-xlnx Dec 14, 2023
a8ba24d
Expand TestEDIF{Hier,}CellInst
eddieh-xlnx Dec 14, 2023
fcfee1b
Expand TestEDIFCell including a test that currently fails
eddieh-xlnx Dec 14, 2023
0e61591
Add null check
eddieh-xlnx Dec 14, 2023
037257f
EDIFCell.decrementInstanceCount() to recursively decrement instances
eddieh-xlnx Dec 14, 2023
19d06d4
Refactor into testIsUniquifiedRemoveAndAdd()
eddieh-xlnx Dec 14, 2023
089959d
More questions than answers...
eddieh-xlnx Dec 14, 2023
3440bfc
EDIFCell.{add,remove}CellInst() to not increment instance count
eddieh-xlnx Dec 14, 2023
c9af97b
EDIFCell.addCellInst() to not increment instance count
eddieh-xlnx Dec 14, 2023
7da5e22
EDIFCell.removeCellInst() to call EDIFCellInst.setParentCell()
eddieh-xlnx Dec 14, 2023
cc40118
EDIFCellInst.setParentCell() and setCellTypeRaw() to inc/dec inst count
eddieh-xlnx Dec 14, 2023
5260c12
Update tests
eddieh-xlnx Dec 14, 2023
8ad7a75
Make EDIFCellInst.setParentCell() the only place member is written
eddieh-xlnx Dec 14, 2023
6423c54
Merge branch 'edifcell_instancecount' into routerhelper_invertlutgnd
eddieh-xlnx Dec 14, 2023
6f473da
Merge remote-tracking branch 'upstream/master' into routerhelper_inve…
eddieh-xlnx Jan 12, 2024
e3e865a
Add invertLutInputs param to invertPossibleGndPinsToVccPins()
eddieh-xlnx Jan 12, 2024
ec1bb2c
[RWRoute] Add --noInvertGndToVccForLutInputs option
eddieh-xlnx Jan 12, 2024
22cd46c
Fix/improve tests
eddieh-xlnx Jan 12, 2024
b9ca819
Add stub for VCC -> GND for testing
eddieh-xlnx Jan 12, 2024
72d618c
Adding implementation of invertVccLutPinsToGndPins()
clavin-xlnx Jan 12, 2024
9ae8f4f
Temporary workaround to clear logical netlist after Net.rename()
eddieh-xlnx Jan 12, 2024
94b3033
Merge remote-tracking branch 'upstream/routerhelper_invertlutgnd2' in…
eddieh-xlnx Jan 13, 2024
6a681fb
Add null check
eddieh-xlnx Jan 13, 2024
1f2d8ca
Merge remote-tracking branch 'upstream/master' into routerhelper_inve…
eddieh-xlnx Jan 13, 2024
9b5ed7e
Remove @Test
eddieh-xlnx Jan 13, 2024
762653e
Move invertVccLutPinsToGndPins() into RouterHelperSupport
eddieh-xlnx Jan 15, 2024
8e3cccd
Add comment about LUT6_2
eddieh-xlnx Jan 16, 2024
d0b4642
Fix comment
eddieh-xlnx Jan 16, 2024
3d97df8
Fill out testInvertPossibleGndPinsToVccPinsLutInputOnlyIfFlattenedAnd…
eddieh-xlnx Jan 16, 2024
c1c5666
Merge remote-tracking branch 'upstream/master' into routerhelper_inve…
eddieh-xlnx Jan 16, 2024
238954c
Bump year
eddieh-xlnx Jan 16, 2024
71dc48a
Skip test if !flatten && uniquify
eddieh-xlnx Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/com/xilinx/rapidwright/rwroute/RWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ protected void routeStaticNets() {

List<SitePinInst> gndPins = staticNetAndRoutingTargets.get(design.getGndNet());
if (gndPins != null) {
Set<SitePinInst> newVccPins = RouterHelper.invertPossibleGndPinsToVccPins(design, gndPins);
boolean invertGndToVccForLutInputs = config.isInvertGndToVccForLutInputs();
Set<SitePinInst> newVccPins = RouterHelper.invertPossibleGndPinsToVccPins(design, gndPins, invertGndToVccForLutInputs);
if (!newVccPins.isEmpty()) {
gndPins.removeAll(newVccPins);
staticNetAndRoutingTargets.computeIfAbsent(design.getVccNet(), (net) -> new ArrayList<>())
Expand Down
28 changes: 27 additions & 1 deletion src/com/xilinx/rapidwright/rwroute/RWRouteConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
*
* Copyright (c) 2021 Ghent University.
* Copyright (c) 2022-2023, Advanced Micro Devices, Inc.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Author: Yun Zhou, Ghent University.
Expand Down Expand Up @@ -92,6 +92,8 @@ public class RWRouteConfig {
private boolean lutPinSwapping;
/* true to enable LUT routethru */
private boolean lutRoutethru;
/* true to enable GND -> VCC optimization for LUT inputs */
private boolean invertGndToVccForLutInputs;

/** Constructs a Configuration Object */
public RWRouteConfig(String[] arguments) {
Expand Down Expand Up @@ -122,6 +124,7 @@ public RWRouteConfig(String[] arguments) {
printConnectionSpan = false;
lutPinSwapping = false;
lutRoutethru = false;
invertGndToVccForLutInputs = true;
if (arguments != null) {
parseArguments(arguments);
}
Expand Down Expand Up @@ -227,6 +230,9 @@ private void parseArguments(String[] arguments) {
case "--lutRoutethru":
setLutRoutethru(true);
break;
case "--noInvertGndToVccForLutInputs":
setInvertGndToVccForLutInputs(false);
break;
default:
throw new IllegalArgumentException("ERROR: RWRoute argument '" + arg + "' not recognized.");
}
Expand Down Expand Up @@ -737,6 +743,16 @@ public boolean isLutRoutethru() {
return lutRoutethru;
}

/**
* Gets the flag indicating if GND to VCC inversion for LUT inputs is enabled.
* Default: true.
*
* @return True if the flag is set, false otherwise.
*/
public boolean isInvertGndToVccForLutInputs() {
return invertGndToVccForLutInputs;
}

/**
* Sets critical path delay pessimism factor b. It should be greater than 0.
* Default: 100. Can be modified by using "--pessimismB" option, e.g.
Expand Down Expand Up @@ -850,6 +866,16 @@ public void setLutRoutethru(boolean lutRoutethru) {
this.lutRoutethru = lutRoutethru;
}

/**
* Sets the flag for enabling GND to VCC inversion for LUT inputs.
* Default: true.
*
* @param invertGndToVccForLutInputs true to enableGND to VCC inversion for LUT inputs.
*/
public void setInvertGndToVccForLutInputs(boolean invertGndToVccForLutInputs) {
this.invertGndToVccForLutInputs = invertGndToVccForLutInputs;
}

/**
* Sets verbose.
* If true, there will be more info in the routing log file regarding design netlist, routing statistics, and timing report.
Expand Down
125 changes: 104 additions & 21 deletions src/com/xilinx/rapidwright/rwroute/RouterHelper.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
*
* Copyright (c) 2021 Ghent University.
* Copyright (c) 2022-2023, Advanced Micro Devices, Inc.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Author: Yun Zhou, Ghent University.
Expand Down Expand Up @@ -39,17 +39,22 @@
import java.util.Queue;
import java.util.Set;

import com.xilinx.rapidwright.design.Cell;
import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.DesignTools;
import com.xilinx.rapidwright.design.Net;
import com.xilinx.rapidwright.design.SiteInst;
import com.xilinx.rapidwright.design.SitePinInst;
import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.device.BEL;
import com.xilinx.rapidwright.device.BELPin;
import com.xilinx.rapidwright.device.IntentCode;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.PIP;
import com.xilinx.rapidwright.device.Tile;
import com.xilinx.rapidwright.device.TileTypeEnum;
import com.xilinx.rapidwright.device.Wire;
import com.xilinx.rapidwright.edif.EDIFHierCellInst;
import com.xilinx.rapidwright.timing.TimingEdge;
import com.xilinx.rapidwright.timing.TimingManager;
import com.xilinx.rapidwright.timing.delayestimator.DelayEstimatorBase;
Expand Down Expand Up @@ -366,43 +371,121 @@ private static boolean isInvertibleDSPBELPin(BELPin belPin) {
/**
* Inverts all possible GND sink pins to VCC pins.
* @param design The target design.
* @param pins The static net pins.
* @param pins The GND net pins.
*/
public static Set<SitePinInst> invertPossibleGndPinsToVccPins(Design design, List<SitePinInst> pins) {
Net staticNet = design.getGndNet();
return invertPossibleGndPinsToVccPins(design, pins, true);
}

/**
* Inverts all possible GND sink pins to VCC pins.
* @param design The target design.
* @param pins The GND net pins.
* @param invertLutInputs True to invert LUT inputs.
*/
public static Set<SitePinInst> invertPossibleGndPinsToVccPins(Design design,
List<SitePinInst> pins,
boolean invertLutInputs) {
Net gndNet = design.getGndNet();
Set<SitePinInst> toInvertPins = new HashSet<>();
for (SitePinInst currSitePinInst : pins) {
if (!currSitePinInst.getNet().equals(staticNet))
throw new RuntimeException(currSitePinInst.toString());
BELPin[] belPins = currSitePinInst.getSiteInst().getSiteWirePins(currSitePinInst.getName());
if (belPins.length != 2) {
continue;
}
for (BELPin belPin : belPins) {
if (belPin.isSitePort()) {
continue;
nextSitePin: for (SitePinInst spi : pins) {
if (!spi.getNet().equals(gndNet))
throw new RuntimeException(spi.toString());
SiteInst si = spi.getSiteInst();
String siteWireName = spi.getSiteWireName();
if (invertLutInputs && spi.isLUTInputPin()) {
Collection<Cell> connectedCells = DesignTools.getConnectedCells(spi);
if (connectedCells.isEmpty()) {
for (BELPin belPin : si.getSiteWirePins(siteWireName)) {
if (belPin.isSitePort()) {
continue;
}
BEL bel = belPin.getBEL();
Cell cell = si.getCell(bel);
if (cell == null) {
continue;
}
if (cell.getType().equals("SRL16E") && siteWireName.endsWith("6")) {
// SRL16Es that have been transformed from SRLC32E (assume so here,
// since we don't always have the logical netlist to check)
// require GND on their A6 pin
// See DesignTools.createMissingStaticSitePins(BELPin, SiteInst, Cell)
continue nextSitePin;
}
}
throw new RuntimeException("ERROR: " + gndNet.getName() + " not connected to any Cells");
}
if (!belPin.getBEL().canInvert()) {
for (Cell cell : connectedCells) {
if (!LUTTools.isCellALUT(cell)) {
continue nextSitePin;
}

EDIFHierCellInst ehci = cell.getEDIFHierCellInst();
if (ehci == null) {
// No logical cell (likely encrypted)
continue nextSitePin;
}

if (!ehci.getParent().isUniquified()) {
// Parent cell (instantiating this LUT) is not unique
// This parent may be a LUT6_2 macro cell that has been expanded into LUT6+LUT5,
// and which does not get uniquified by EDIFTools.uniqueifyNetlist().
// Thus, LUT6/LUT5 inside expanded LUT6_2 macros are not eligible for inversion.
continue nextSitePin;
}
}

toInvertPins.add(spi);

for (Cell cell : connectedCells) {
// Find the logical pin name
String physicalPinName = "A" + spi.getName().charAt(1);
String logicalPinName = cell.getLogicalPinMapping(physicalPinName);

// Get the LUT equation
String lutEquation = LUTTools.getLUTEquation(cell);
assert(lutEquation.contains(logicalPinName));

// Compute a new LUT equation with that logical input inverted
String newLutEquation = lutEquation.replace(logicalPinName, "!" + logicalPinName)
// Cancel out double inversions
// (Note: LUTTools.getLUTEquation() only produces equations with '!' instead of '~')
.replace("!!", "");
LUTTools.configureLUT(cell, newLutEquation);
}
} else {
BELPin[] belPins = si.getSiteWirePins(siteWireName);
if (belPins.length != 2) {
continue;
}
if (currSitePinInst.getSite().getName().startsWith("RAM")) {
if (belPin.getBELName().startsWith("CLK")) {
for (BELPin belPin : belPins) {
if (belPin.isSitePort()) {
continue;
}
if (!belPin.getBEL().canInvert()) {
continue;
}
if (spi.getSite().getName().startsWith("RAM")) {
if (belPin.getBELName().startsWith("CLK")) {
continue;
}
}
toInvertPins.add(spi);
}
toInvertPins.add(currSitePinInst);
}
}
}

// Unroute all pins in a batch fashion
DesignTools.unroutePins(staticNet, toInvertPins);
DesignTools.unroutePins(gndNet, toInvertPins);
// Manually remove pins from net, because using DesignTools.batchRemoveSitePins()
// will cause SitePinInst.detachSiteInst() to be called, which we do not want
// as we are simply moving the SPI from one net to another
staticNet.getPins().removeAll(toInvertPins);
gndNet.getPins().removeAll(toInvertPins);

Net vccNet = design.getVccNet();
for (SitePinInst toinvert:toInvertPins) {
assert(toinvert.getSiteInst() != null);
if (!design.getVccNet().addPin(toinvert)) {
if (!vccNet.addPin(toinvert)) {
throw new RuntimeException("ERROR: Couldn't invert site pin " +
toinvert);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2024, 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.support.rwroute;

import com.xilinx.rapidwright.design.Cell;
import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.SiteInst;
import com.xilinx.rapidwright.design.SitePinInst;
import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.device.BELPin;

import java.util.Set;

public class RouterHelperSupport {
public static void invertVccLutPinsToGndPins(Design design, Set<SitePinInst> pins) {
for (SitePinInst spi : pins) {
assert (spi.getNet() == design.getVccNet());
SiteInst si = spi.getSiteInst();
for (BELPin bp : spi.getSiteWireBELPins()) {
if (bp.isSitePort() || bp.getName().charAt(0) != 'A')
continue;
if (bp.getBEL().isLUT()) {
Cell lut = si.getCell(bp.getBEL());
if (lut != null) {
String eq = LUTTools.getLUTEquation(lut);
String logInput = lut.getLogicalPinMapping(bp.getName());
if (logInput != null) {
LUTTools.configureLUT(lut, eq.replace(logInput, "(~" + logInput + ")"));
} else {
// Doesn't look like this pin is used by this [65]LUT,
// could be used by the other [56]LUT
}
}
}
}
spi.getNet().removePin(spi, true);
design.getGndNet().addPin(spi, true);
}
}
}
4 changes: 2 additions & 2 deletions test/src/com/xilinx/rapidwright/edif/TestEDIFCellInst.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Advanced Micro Devices, Inc.
* Copyright (c) 2023-2024, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Author: Eddie Hung, Advanced Micro Devices, Inc.
Expand Down Expand Up @@ -78,7 +78,7 @@ public void testIsUniquifiedFalse() {
)) {
EDIFCellInst eci = picoblazeTop.getCellInst(name);
// Only checks that this cell instance is unique (e.g. that there is only
// one instantiation) but does not check that any parents on a full
// one instantiation) but does not check that all parents on a full
// hierarchical path (e.g. "picoblaze_{0,1}_{12,13}/processor") is also
// unique --- use EDIFHierCellInst.isUniquified() for that
Assertions.assertTrue(eci.isUniquified());
Expand Down
2 changes: 1 addition & 1 deletion test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public void testRWRouteDeviceSupport(Series series) {
public void testBug701() {
Design design = RapidWrightDCP.loadDCP("bug701.dcp");

RWRoute.routeDesignFullNonTimingDriven(design);
RWRoute.routeDesignWithUserDefinedArguments(design, new String[] {"--nonTimingDriven", "--noInvertGndToVccForLutInputs"});

Net vcc = design.getVccNet();
Assertions.assertEquals(1, vcc.getPins().size());
Expand Down
Loading
Loading