Skip to content
27 changes: 18 additions & 9 deletions src/com/xilinx/rapidwright/interchange/DeviceResourcesExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,28 @@
public class DeviceResourcesExample {

public static final String SKIP_ROUTE_RESOURCES_OPTION = "--skip_route_resources";
public static final String VERIFY_OPTION = "--verify";

public static void main(String[] args) throws IOException {
if (args.length != 1 && args.length != 2) {
System.out.println("USAGE: <device name> [" + SKIP_ROUTE_RESOURCES_OPTION + "]");
if (args.length < 1 || args.length > 3) {
System.out.println("USAGE: <device name> [" + SKIP_ROUTE_RESOURCES_OPTION + "] [" + VERIFY_OPTION + "]");
System.out.println(" Example dump of device information for interchange format.");
return;
}

boolean skipRouteResources = false;
if (args.length == 2 && args[1].equals(SKIP_ROUTE_RESOURCES_OPTION)) {
skipRouteResources = true;
boolean verify = false;
for (int i = 1; i < args.length; i++) {
if (args[i].equals(SKIP_ROUTE_RESOURCES_OPTION)) {
skipRouteResources = true;
} else if (args[i].equals(VERIFY_OPTION)) {
verify = true;
}
}

CodePerfTracker t = new CodePerfTracker("Device Resources Dump: " + args[0]);
t.useGCToTrackMemory(true);
t.setReportingCurrOSMemUsage(true);
t.setTrackOSMemUsage(true);

// Create device resource file if it doesn't exist
String capnProtoFileName = args[0] + ".device";
Expand All @@ -56,10 +63,12 @@ public static void main(String[] args) throws IOException {
DeviceResourcesWriter.writeDeviceResourcesFile(args[0], device, t, capnProtoFileName, skipRouteResources);
Device.releaseDeviceReferences();

t.start("Verify file");
// Verify device resources
DeviceResourcesVerifier.verifyDeviceResources(capnProtoFileName, args[0]);
if (verify) {
// Verify device resources
DeviceResourcesVerifier.verifyDeviceResources(capnProtoFileName, args[0], t);
}

t.stop().printSummary();
t.printSummary();
System.out.println("Device resources file '" + capnProtoFileName + "' written successfully");
}
}
100 changes: 93 additions & 7 deletions src/com/xilinx/rapidwright/interchange/DeviceResourcesVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@

package com.xilinx.rapidwright.interchange;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.ReadableByteChannel;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -55,6 +59,7 @@
import com.xilinx.rapidwright.device.Device;
import com.xilinx.rapidwright.device.Grade;
import com.xilinx.rapidwright.device.IOStandard;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.PIP;
import com.xilinx.rapidwright.device.PIPType;
import com.xilinx.rapidwright.device.Package;
Expand All @@ -66,6 +71,7 @@
import com.xilinx.rapidwright.device.SiteTypeEnum;
import com.xilinx.rapidwright.device.Tile;
import com.xilinx.rapidwright.device.TileTypeEnum;
import com.xilinx.rapidwright.device.Wire;
import com.xilinx.rapidwright.edif.EDIFCell;
import com.xilinx.rapidwright.edif.EDIFCellInst;
import com.xilinx.rapidwright.edif.EDIFDesign;
Expand All @@ -90,6 +96,7 @@
import com.xilinx.rapidwright.interchange.LogicalNetlist.Netlist;
import com.xilinx.rapidwright.interchange.LogicalNetlist.Netlist.Direction;
import com.xilinx.rapidwright.interchange.LogicalNetlist.Netlist.PropertyMap;
import com.xilinx.rapidwright.tests.CodePerfTracker;
import com.xilinx.rapidwright.util.Pair;

public class DeviceResourcesVerifier {
Expand Down Expand Up @@ -130,7 +137,9 @@ private static void verifyBelPin(StructList.Reader<DeviceResources.Device.BELPin
expect(pin.getBEL().getName(), allStrings.get(belPin.getBel()));
}

public static boolean verifyDeviceResources(String devResFileName, String deviceName) throws IOException {
public static boolean verifyDeviceResources(String devResFileName, String deviceName, CodePerfTracker t)
throws IOException {
t.start("*Verify Init");
allStrings = new StringEnumerator();
verifiedSiteTypes = new HashSet<SiteTypeEnum>();

Expand All @@ -143,11 +152,13 @@ public static boolean verifyDeviceResources(String devResFileName, String device
DeviceResources.Device.Reader dReader = null;
ReaderOptions readerOptions = new ReaderOptions(1024L * 1024L * 1024L * 64L, 64);
MessageReader readMsg = null;
readMsg = Interchange.readInterchangeFile(devResFileName, readerOptions);
ReadableByteChannel rbc = Interchange.getReadableByteChannel(devResFileName);

readMsg = Interchange.readMessageFromChannel(rbc, readerOptions);

dReader = readMsg.getRoot(DeviceResources.Device.factory);

boolean containsRoutingResources = dReader.getNodes().size() > 0;
boolean containsMultiMessageRoutingResources = !dReader.hasNodes();

int strCount = dReader.getStrList().size();
TextList.Reader reader = dReader.getStrList();
Expand All @@ -156,6 +167,8 @@ public static boolean verifyDeviceResources(String devResFileName, String device
allStrings.addObject(str);
}

t.stop().start("*Verify Tiles & Sites");

// Create a lookup map for tile types
Map<String,TileType.Reader> tileTypeMap = new HashMap<String, TileType.Reader>();
Map<TileTypeEnum, TileType.Reader> tileTypeEnumMap = new HashMap<TileTypeEnum, TileType.Reader>();
Expand Down Expand Up @@ -477,13 +490,15 @@ public static boolean verifyDeviceResources(String devResFileName, String device
}
}

t.stop().start("*Verify Libraries");

Netlist.Reader primLibs = dReader.getPrimLibs();
LogNetlistReader netlistReader = new LogNetlistReader(allStrings, new HashMap<String, String>() {{
put(LogNetlistWriter.DEVICE_PRIMITIVES_LIB, EDIFTools.EDIF_LIBRARY_HDI_PRIMITIVES_NAME);
}}
);
EDIFNetlist primsAndMacros = netlistReader.readLogNetlist(primLibs,
/*skipTopStuff=*/true, /*expandMacros=*/false);
/* skipTopStuff= */true, /* expandMacros= */false, CodePerfTracker.SILENT);

Set<String> libsFound = new HashSet<String>();
libsFound.addAll(primsAndMacros.getLibrariesMap().keySet());
Expand Down Expand Up @@ -617,16 +632,87 @@ public static boolean verifyDeviceResources(String devResFileName, String device
}
}

t.stop().start("*Verify CellBelPins");
verifyCellBelPinMaps(allStrings, dReader, design);
t.stop().start("*Verify Packages");
verifyPackages(allStrings, dReader, device);

if (containsRoutingResources) {
ConstantDefinitions.verifyConstants(allStrings, device, design, siteTypes, dReader.getConstants(), tileTypeEnumMap);
t.stop();

if (containsMultiMessageRoutingResources) {
t.start("*Verify Constants");
ConstantDefinitions.verifyConstants(allStrings, device, design, siteTypes,
dReader.getConstants(), tileTypeEnumMap);
t.stop().start("*Verify Nodes & Wires");
verifyWireAndNodeMultiMessage(device, allStrings, rbc, readerOptions);
t.stop();
}


rbc.close();
return true;
}

private static void verifyWireAndNodeMultiMessage(Device device, StringEnumerator allStrings,
ReadableByteChannel rbc, ReaderOptions options) {
int numOfMessages = device.getRows();

for (int row = 0; row < numOfMessages; row++) {
LongEnumerator allWires = new LongEnumerator();
DeviceResources.Device.Reader deviceReader = null;
try {
MessageReader mReader = Interchange.readMessageFromChannel(rbc, options);
deviceReader = mReader.getRoot(DeviceResources.Device.factory);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
StructList.Reader<DeviceResources.Device.Wire.Reader> wires = deviceReader.getWires();
StructList.Reader<DeviceResources.Device.Node.Reader> nodeList = deviceReader.getNodes();

int wireIdx = 0;
int nodeIdx = 0;
for (Tile tile : device.getTiles()[row]) {
for (int i = 0; i < tile.getWireCount(); i++) {
Node node = Node.getNode(tile, i);
if (node == null) {
long nodeWireKey = DeviceResourcesWriter.makeKey(tile, i);
Integer test = allWires.maybeGetIndex(nodeWireKey);
if (test == null) {
allWires.addObject(nodeWireKey);
DeviceResources.Device.Wire.Reader readWire = wires.get(wireIdx++);
expect(tile.getName(), allStrings.get(readWire.getTile()));
expect(tile.getWireName(i), allStrings.get(readWire.getWire()));
expect(tile.getWireIntentCode(i).ordinal(), readWire.getType());
}
}else if (node.getTile() == tile && node.getWireIndex() == i) {
Wire[] nodeWires = node.getAllWiresInNode();
for (Wire w : nodeWires) {
long nodeWireKey = DeviceResourcesWriter.makeKey(w.getTile(), w.getWireIndex());
Integer test = allWires.maybeGetIndex(nodeWireKey);
if (test == null) {
allWires.addObject(nodeWireKey);
DeviceResources.Device.Wire.Reader readWire = wires.get(wireIdx++);
expect(w.getTile().getName(), allStrings.get(readWire.getTile()));
expect(w.getWireName(), allStrings.get(readWire.getWire()));
expect(w.getIntentCode().ordinal(), readWire.getType());
}
}
DeviceResources.Device.Node.Reader readNode = nodeList.get(nodeIdx++);
PrimitiveList.Int.Reader readNodeWires = readNode.getWires();
expect(nodeWires.length, readNodeWires.size());
for (int j = 0; j < nodeWires.length; j++) {
int wireKey = readNodeWires.get(j);
Long wireEntry = allWires.get(wireKey);
int tIdx = (int) (wireEntry >>> 32);
int wIdx = (int) (wireEntry & 0xFFFFFFFF);
expect(nodeWires[j].getTile().getUniqueAddress(), tIdx);
expect(nodeWires[j].getWireIndex(), wIdx);
}
}
}
}
}
}


private static HashSet<SiteTypeEnum> verifiedSiteTypes;

Expand Down
89 changes: 83 additions & 6 deletions src/com/xilinx/rapidwright/interchange/DeviceResourcesWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
package com.xilinx.rapidwright.interchange;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -297,10 +299,17 @@ public static void writeDeviceResourcesFile(String part, Device device, CodePerf
t.stop().start("Tiles");
writeAllTilesToBuilder(device, devBuilder, tileTypeIndicies);

t.stop().start("Wires&Nodes");
writeAllWiresAndNodesToBuilder(device, devBuilder, skipRouteResources);
if (skipRouteResources) {
// Let's set wires and nodes to size 0
devBuilder.initWires(0);
devBuilder.initNodes(0);
} else {
// We'll add them as multiple messages after the main device message, one row of
// tiles' worth of wires and nodes at a time. We'll leave the wires and node
// field as an indicator that more messages will be present.
}

t.stop().start("Prims&Macros");
t.stop().start("Prims & Macros");
// Create an EDIFNetlist populated with just primitive and macro libraries
EDIFLibrary prims = Design.getPrimitivesLibrary(device.getName());
EDIFLibrary macros = Design.getMacroPrimitives(series);
Expand Down Expand Up @@ -469,8 +478,15 @@ public static void writeDeviceResourcesFile(String part, Device device, CodePerf
t.stop().start("Strings");
writeAllStringsToBuilder(devBuilder);

t.stop().start("Write File");
Interchange.writeInterchangeFile(fileName, message);
t.stop().start("Write Device (single message)");
WritableByteChannel wbc = Interchange.getWritableByteChannel(fileName);
Interchange.writeMessageToChannel(wbc, message);

if (!skipRouteResources) {
t.stop().start("Write Wires & Nodes (multi-message)");
writeAllWiresAndNodesToMultipleMessages(device, wbc);
}
wbc.close();
t.stop();
}

Expand Down Expand Up @@ -809,12 +825,72 @@ public static void writeAllTilesToBuilder(Device device, DeviceResources.Device.

}

private static long makeKey(Tile tile, int wire) {
protected static long makeKey(Tile tile, int wire) {
long key = wire;
key = (((long)tile.getUniqueAddress()) << 32) | key;
return key;
}

public static void writeAllWiresAndNodesToMultipleMessages(Device device, WritableByteChannel wbc) {
// Write one message for each row of tiles in the device
int numOfMessages = device.getRows();

for (int m = 0; m < numOfMessages; m++) {
MessageBuilder message = new MessageBuilder();
DeviceResources.Device.Builder devBuilder = message.initRoot(DeviceResources.Device.factory);

LongEnumerator allWires = new LongEnumerator();
ArrayList<Long> allNodes = new ArrayList<>();

for (Tile tile : device.getTiles()[m]) {
for (int i = 0; i < tile.getWireCount(); i++) {
Node node = Node.getNode(tile, i);
if (node == null) {
allWires.addObject(makeKey(tile, i));
} else if (node.getTile() == tile && node.getWireIndex() == i) {
allNodes.add(makeKey(node.getTile(), node.getWireIndex()));
Wire[] nodeWires = node.getAllWiresInNode();
for (Wire w : nodeWires) {
allWires.addObject(makeKey(w.getTile(), w.getWireIndex()));
}
}
}
}

StructList.Builder<DeviceResources.Device.Wire.Builder> wireBuilders = devBuilder
.initWires(allWires.size());

for (int i = 0; i < allWires.size(); i++) {
DeviceResources.Device.Wire.Builder wireBuilder = wireBuilders.get(i);
long wireKey = allWires.get(i);
Wire wire = new Wire(device.getTile((int) (wireKey >>> 32)), (int) (wireKey & 0xffffffff));
// Wire wire = allWires.get(i);
wireBuilder.setTile(allStrings.getIndex(wire.getTile().getName()));
wireBuilder.setWire(allStrings.getIndex(wire.getWireName()));
wireBuilder.setType(wire.getIntentCode().ordinal());
}

StructList.Builder<DeviceResources.Device.Node.Builder> nodeBuilders = devBuilder
.initNodes(allNodes.size());
for (int i = 0; i < allNodes.size(); i++) {
DeviceResources.Device.Node.Builder nodeBuilder = nodeBuilders.get(i);
long nodeKey = allNodes.get(i);
Node node = Node.getNode(device.getTile((int) (nodeKey >>> 32)), (int) (nodeKey & 0xffffffff));
Wire[] wires = node.getAllWiresInNode();
PrimitiveList.Int.Builder wBuilders = nodeBuilder.initWires(wires.length);
for (int k = 0; k < wires.length; k++) {
wBuilders.set(k, allWires.maybeGetIndex(makeKey(wires[k].getTile(), wires[k].getWireIndex())));
}
}

try {
Interchange.writeMessageToChannel(wbc, message);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}

public static void writeAllWiresAndNodesToBuilder(Device device, DeviceResources.Device.Builder devBuilder,
boolean skipRouteResources) {
LongEnumerator allWires = new LongEnumerator();
Expand Down Expand Up @@ -862,6 +938,7 @@ public static void writeAllWiresAndNodesToBuilder(Device device, DeviceResources
}
}
}

private static void populatePackages(StringEnumerator allStrings, Device device, DeviceResources.Device.Builder devBuilder) {
Set<String> packages = device.getPackages();
List<String> packagesList = new ArrayList<String>();
Expand Down
Loading