Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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/edif/EDIFDirection.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
public enum EDIFDirection {
INPUT,
OUTPUT,
INOUT;
INOUT,
INTERNAL;

private final byte[] arr;

Expand Down
60 changes: 60 additions & 0 deletions src/com/xilinx/rapidwright/edif/EDIFNetlist.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ public class EDIFNetlist extends EDIFName {
private String origDirectory;

private List<String> encryptedCells;

private EDIFLibrary external;

private Map<EDIFCell, EDIFCell> externalMappings;

private boolean encryptedCellsValidated = false;

Expand Down Expand Up @@ -1897,6 +1901,28 @@ public void expandMacroUnisims(Series series) {
}
}
}

public void populateExternalCells() {
externalMappings = new HashMap<>();
for (EDIFLibrary lib : getLibraries()) {
if (lib.isHDIPrimitivesLibrary()) {
continue;
}

for (EDIFCell cell : lib.getCells()) {
for (EDIFCellInst inst : cell.getCellInsts()) {
if (!inst.getCellType().isPrimitive() && inst.getCellType().isLeafCellOrBlackBox()) {
// Likely an encrypted cell, see if we have a substitute netlist in external lib
EDIFCell sub = external.getCell(inst.getCellName());
externalMappings.put(sub, inst.getCellType());
if (sub != null) {
inst.setCellType(sub);
}
}
}
}
}
}

private Boolean checkIOStandardForExpansion(EDIFCellInst inst, Pair<String, EnumSet<IOStandard>> exception) {
Boolean expand = null;
Expand Down Expand Up @@ -1994,10 +2020,33 @@ public void collapseMacroUnisims(Series series) {
for (String name : primsToRemoveOnCollapse) {
prims.removeCell(name);
}

if (external != null) {
blackBoxExternalCells();
}

// Invalidate parent net map due to macro collapses
resetParentNetMap();
}

public void blackBoxExternalCells() {
for (EDIFLibrary lib : getLibraries()) {
if (lib.isHDIPrimitivesLibrary()) {
continue;
}

for (EDIFCell cell : lib.getCells()) {
for (EDIFCellInst inst : cell.getCellInsts()) {
if (inst.getCellType().getLibrary() == external) {
EDIFCell origBB = externalMappings.get(inst.getCellType());
assert (origBB != null);
inst.setCellType(origBB);
}
}
}
}
}

/**
* Keeps track of the original source directory from where this EDIF file was loaded.
* @return Original directory path from where the EDIF file was loaded
Expand Down Expand Up @@ -2232,6 +2281,17 @@ public void resetCellInstIOStandardFallbackMap() {
cellInstIOStandardFallback = null;
}

public void setExternalLibrary(EDIFLibrary external) {
this.external = external;
if (external != null) {
populateExternalCells();
}
}

public EDIFLibrary getExternalLibrary() {
return external;
}

public static void main(String[] args) throws FileNotFoundException {
CodePerfTracker t = new CodePerfTracker("EDIF Import/Export", true);
t.start("Read EDIF");
Expand Down
4 changes: 4 additions & 0 deletions src/com/xilinx/rapidwright/edif/EDIFPortInst.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public EDIFPortInst(EDIFPort port, EDIFNet parentNet, int index, EDIFCellInst ce
throw new RuntimeException("ERROR: Use a different constructor, "
+ "need index for bussed port " + port.getName());
}
if (index != -1 && !port.isBus()) {
throw new RuntimeException("ERROR: Use a different constructor, " + "port "
+ port.getName() + " is not a bus, cannot index into a single bit signal.");
}
if (cellInst != null) {
if (!port.equals(cellInst.getPort(port.getBusName(true)))) {
// check for name collision
Expand Down
12 changes: 6 additions & 6 deletions src/com/xilinx/rapidwright/edif/EDIFTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,10 @@ public static int lengthOfNameWithoutBus(char[] name) {
}

/**
* Determines if the char[] ends with the pattern [#:#] where # are positive bus
* values (e.g., [7:0]) and then returns the length of the string without the
* bus suffix (if it exists). If the name does not end with the bus pattern, it
* returns the original length of the char[].
* Determines if the char[] ends with the pattern [#:#] where # are integer bus
* values (e.g., [7:0] or [0:-1]) and then returns the length of the string
* without the bus suffix (if it exists). If the name does not end with the bus
* pattern, it returns the original length of the char[].
*
* @param name
* @param keepOpenBracket In the case of a bussed name, this will return the
Expand All @@ -439,11 +439,11 @@ public static int lengthOfNameWithoutBus(char[] name, boolean keepOpenBracket) {
int len = name.length;
int i = len-1;
if (name[i--] != ']') return len;
while (Character.isDigit(name[i])) {
while (Character.isDigit(name[i]) || name[i] == '-') {
i--;
}
if (name[i--] != ':') return len;
while (Character.isDigit(name[i])) {
while (Character.isDigit(name[i]) || name[i] == '-') {
i--;
}
if (name[i] != '[') return len;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,22 @@ public static PBlock createPipeline(Design d, Site startingPoint, int width, int

if (i == 0) prevSite = currSlice;

if (j == 0) inputNet.createPortInst(inputPort, (width - 1) - i);
if (j == depth - 1) outputNet.createPortInst(outputPort, (width - 1) - i);
if (j == 0) {
if (inputPort.isBus()) {
inputNet.createPortInst(inputPort, (width - 1) - i);
} else {
inputNet.createPortInst(inputPort);
}

}
if (j == depth - 1) {
if (outputPort.isBus()) {
outputNet.createPortInst(outputPort, (width - 1) - i);
} else {
outputNet.createPortInst(outputPort);
}

}

clkNet.getLogicalNet().createPortInst("C", ffCell);
rstNet.getLogicalNet().createPortInst("R", ffCell);
Expand Down
4 changes: 2 additions & 2 deletions test/src/com/xilinx/rapidwright/edif/TestEDIFPort.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ public void testCreatePort() {
EDIFCell cell = new EDIFCell(netlist.getWorkLibrary(), "cell_1");
int outer = 0;
// Creates ports: {bus_output[0][3:0], bus_output[2][5:2],
// bus_output[1][0:3], bus_output[3][2:5]}
for (String range : new String[] { "3:0", "0:3", "5:2", "2:5" }) {
// bus_output[1][0:3], bus_output[3][2:5], , bus_output[4][0:-1], bus_output[5][-3:-1]}
for (String range : new String[] { "3:0", "0:3", "5:2", "2:5", "0:-1", "-3:-1" }) {
int left = Integer.parseInt(range.substring(0, range.indexOf(':')));
int right = Integer.parseInt(range.substring(range.indexOf(':') + 1));
int width = Math.abs(left - right) + 1;
Expand Down
69 changes: 66 additions & 3 deletions test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@
import java.util.Map;
import java.util.Random;

import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.eco.ECOTools;
import com.xilinx.rapidwright.util.VivadoToolsHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
Expand All @@ -51,19 +48,25 @@
import com.xilinx.rapidwright.design.SiteInst;
import com.xilinx.rapidwright.design.SitePinInst;
import com.xilinx.rapidwright.design.Unisim;
import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.device.Device;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.PIP;
import com.xilinx.rapidwright.device.Part;
import com.xilinx.rapidwright.device.PartNameTools;
import com.xilinx.rapidwright.device.Series;
import com.xilinx.rapidwright.eco.ECOTools;
import com.xilinx.rapidwright.edif.EDIFCell;
import com.xilinx.rapidwright.edif.EDIFHierCellInst;
import com.xilinx.rapidwright.edif.EDIFNetlist;
import com.xilinx.rapidwright.edif.EDIFTools;
import com.xilinx.rapidwright.interchange.Interchange;
import com.xilinx.rapidwright.support.LargeTest;
import com.xilinx.rapidwright.support.RapidWrightDCP;
import com.xilinx.rapidwright.util.FileTools;
import com.xilinx.rapidwright.util.ReportRouteStatusResult;
import com.xilinx.rapidwright.util.VivadoTools;
import com.xilinx.rapidwright.util.VivadoToolsHelper;

public class TestRWRoute {
private static void assertAllPinsRouted(Net net) {
Expand Down Expand Up @@ -613,4 +616,64 @@ public void testDiscussion1245_20250807(boolean forceLagPin) {
VivadoToolsHelper.assertFullyRouted(test_route);
}

@Test
public void testRWRouteSubstituteBlackBoxFlow(@TempDir Path dir) {
// Load an example design, make sure RWRoute can route it
Path dcp = RapidWrightDCP.getPath("optical-flow.dcp");
Design design = Design.readCheckpoint(dcp);
RWRoute.routeDesignFullNonTimingDriven(design);
// VivadoToolsHelper.assertFullyRouted(design);

// Pick a cell to blackbox
String instToBlackBox = "bd_0_i/hls_inst/inst/Loop_FRAMES_CP_OUTER_U0";
EDIFHierCellInst inst = design.getNetlist().getHierCellInstFromName(instToBlackBox);

// Create example external library, store the guts of this netlist in external lib
String cellType = "bd_0_hls_inst_0_Loop_FRAMES_CP_OUTER";
EDIFNetlist external = EDIFTools.createNewNetlist(inst.getInst());
Path externalEDIF = dir.resolve(cellType + ".edn");
external.exportEDIF(externalEDIF);

inst.getCellType().makePrimitive(); // makeBlackBox

// Write out top EDIF that now has a black boxed cell
Path opticalFlowTopEDIF = dir.resolve("optical-flow.edf");
design.getNetlist().collapseMacroUnisims(design.getSeries());
design.getNetlist().exportEDIF(opticalFlowTopEDIF);

// Re-load DCP with black boxed netlist
Design designWithBlackBox = Design.readCheckpoint(dcp, opticalFlowTopEDIF);

// Load external lib, set it as the netlist's external library
EDIFNetlist externalLib = EDIFTools.readEdifFile(externalEDIF);
EDIFCell cell = designWithBlackBox.getNetlist().getCellInstFromHierName(instToBlackBox).getCellType();
Assertions.assertTrue(cell.isLeafCellOrBlackBox() && !cell.isPrimitive());
designWithBlackBox.getNetlist().setExternalLibrary(externalLib.getLibrary("work"));
cell = designWithBlackBox.getNetlist().getCellInstFromHierName(instToBlackBox).getCellType();
Assertions.assertFalse(cell.isLeafCellOrBlackBox());

// Run RWRoute
RWRoute.routeDesignFullNonTimingDriven(designWithBlackBox);

// Sanity check on routing
for (Net net : design.getNets()) {
Net other = designWithBlackBox.getNet(net.getName());
Assertions.assertNotNull(other);
Assertions.assertEquals(net.getPins().size(), other.getPins().size());
Assertions.assertEquals(net.hasPIPs(), other.hasPIPs());
}

// Return the netlist back to its original state for Vivado to read it correctly
designWithBlackBox.getNetlist().blackBoxExternalCells();
designWithBlackBox.getNetlist().setExternalLibrary(null);
EDIFCell guts = externalLib.getCell(cellType);
EDIFHierCellInst instToRestore = designWithBlackBox.getNetlist()
.getHierCellInstFromName(instToBlackBox);
designWithBlackBox.getNetlist().getWorkLibrary().removeCell(instToRestore.getCellType());
designWithBlackBox.getNetlist().copyCellAndSubCells(guts);
guts = designWithBlackBox.getNetlist().getWorkLibrary().getCell(cellType);
instToRestore.getInst().setCellType(guts);

VivadoToolsHelper.assertFullyRouted(designWithBlackBox);
}
}