Skip to content

[CheckPhysNetlist] Verify placement & static/clock routing unchanged #64

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

Merged
merged 9 commits into from
Jan 9, 2024
Merged
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
11 changes: 8 additions & 3 deletions .github/workflows/make.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ jobs:
- env:
REPORT_ROUTE_STATUS_URL: ${{ secrets.REPORT_ROUTE_STATUS_URL }}
REPORT_ROUTE_STATUS_AUTH: ${{ secrets.REPORT_ROUTE_STATUS_AUTH }}
# For certain benchmarks, wirelength_analyzer requires more memory than that available in GitHub Actions
# For certain benchmarks, wirelength_analyzer/CheckPhysNetlist requires more memory than that available in GitHub Actions
WIRELENGTH_ANALYZER_MOCK_RESULT: ${{ matrix.benchmark == 'koios_dla_like_large' }}
CHECK_PHYS_NETLIST_DIFF_MOCK_RESULT: ${{ matrix.benchmark == 'koios_dla_like_large' }}
RWROUTE_FORCE_LUT_PIN_SWAP: ${{ matrix.router == 'rwroute' && matrix.lutpinswap }}
run: |
make ROUTER="${{ matrix.router }}" BENCHMARKS="${{ matrix.benchmark }}" VERBOSE=1
Expand All @@ -81,6 +82,8 @@ jobs:
# Allow CheckPhysNetlist to fail if no remote access to Vivado
grep -H PASS *.check || ${{ secrets.REPORT_ROUTE_STATUS_URL == '' }}
grep -H -e "# of nets with routing errors[. :]\+0" *.check.log || ${{ secrets.REPORT_ROUTE_STATUS_URL == '' }}
# But CheckPhysNetlist must have no differences
grep "INFO: No differences found between routed and unrouted netlists" *.check.log
# Check no multiple sources, no stubs
grep "UserWarning: Found [0-9]\+ sources" *.wirelength && exit 1
grep "UserWarning: Found [0-9]\+ stubs" *.wirelength && exit 1
Expand All @@ -90,9 +93,11 @@ jobs:
if: matrix.router == 'nxroute-poc'
run: |
grep -H FAIL *.check
# Allow following grep to fail if no URL
# Only expect report_route_status output if URL given
grep -H -e "# of nets with routing errors[. :]\+[1-9]" -e "# of unrouted nets[. :]\+[1-9]" *.check.log || ${{ secrets.REPORT_ROUTE_STATUS_URL == '' }}
# Check no multiple sources, but expect stubs
# But CheckPhysNetlist must have no differences (except koios because out-of-memory)
grep "INFO: No differences found between routed and unrouted netlists" *.check.log || ${{ matrix.benchmark == 'koios_dla_like_large' }}
# Check no multiple sources, but expect stubs (except koios because out-of-memory)
grep "UserWarning: Found [0-9]\+ sources" *.wirelength && exit 1
grep "UserWarning: Found [0-9]\+ stubs" *.wirelength || ${{ matrix.benchmark == 'koios_dla_like_large' }}
# Allow wirelength computation to fail since nxroute may not have routed anything or wirelength_analyzer was not run
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ BENCHMARKS ?= boom_med_pb \
ispd16_example2


BENCHMARKS_URL = https://github.com/Xilinx/fpga24_routing_contest/releases/latest/download/benchmarks.tar.gz
BENCHMARKS_URL = https://github.com/eddieh-xlnx/fpga24_routing_contest/releases/download/benchmarks/benchmarks.tar.gz

# Inherit proxy settings from the host if they exist
HTTPHOST=$(firstword $(subst :, ,$(subst http:,,$(subst /,,$(HTTP_PROXY)))))
Expand Down Expand Up @@ -90,7 +90,7 @@ fpga-interchange-schema/interchange/capnp/java.capnp:
# Gradle is used to invoke the CheckPhysNetlist class' main method with arguments
# $^ (%.netlist and %_rwroute.phys), and display/redirect all output to $@.log (%_rwroute.check.log).
# The exit code of Gradle determines if 'PASS' or 'FAIL' is written to $@ (%_rwroute.check)
%_$(ROUTER).check: %.netlist %_$(ROUTER).phys | compile-java
%_$(ROUTER).check: %.netlist %_$(ROUTER).phys %_unrouted.phys | compile-java
if ./gradlew -DjvmArgs="-Xms6g -Xmx6g" -Dmain=com.xilinx.fpga24_routing_contest.CheckPhysNetlist :run --args='$^' $(call log_and_or_display,$@.log); then \
echo "PASS" > $@; \
else \
Expand All @@ -99,7 +99,7 @@ fpga-interchange-schema/interchange/capnp/java.capnp:

%_$(ROUTER).wirelength: %_$(ROUTER).phys | setup-wirelength_analyzer
if [[ "$(WIRELENGTH_ANALYZER_MOCK_RESULT)" == "true" ]]; then \
echo "::warning file=$@::wirelength_analyzer not run because WIRELENGTH_ANALYZER_MOCK_RESULT is set"; \
echo "::warning file=$<::wirelength_analyzer not run because WIRELENGTH_ANALYZER_MOCK_RESULT is set"; \
echo "Wirelength: inf" > $@; \
else \
python3 wirelength_analyzer/wa.py $< $(call log_and_or_display,$@); \
Expand Down
37 changes: 27 additions & 10 deletions src/com/xilinx/fpga24_routing_contest/CheckPhysNetlist.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package com.xilinx.fpga24_routing_contest;

import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.compare.DesignComparator;
import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.edif.EDIFNetlist;
import com.xilinx.rapidwright.edif.EDIFTools;
Expand Down Expand Up @@ -43,8 +44,8 @@

public class CheckPhysNetlist {
public static void main(String[] args) throws IOException, InterruptedException {
if (args.length != 2) {
System.err.println("USAGE: <input.netlist> <input.phys>");
if (args.length != 3) {
System.err.println("USAGE: <input.netlist> <routed.phys> <unrouted.phys>");
return;
}

Expand All @@ -54,15 +55,31 @@ public static void main(String[] args) throws IOException, InterruptedException
PhysNetlistReader.VALIDATE_MACROS_PLACED_FULLY = false;
PhysNetlistReader.CHECK_MACROS_CONSISTENT = false;

// Read the routed and unrouted Physical Netlists
Design routedDesign = PhysNetlistReader.readPhysNetlist(args[1]);
int numDiffs = 0;
if (System.getenv("CHECK_PHYS_NETLIST_DIFF_MOCK_RESULT").equals("true")) {
System.out.println("::warning file=" + args[1] + "::CheckPhysNetlist's DesignComparator not run because CHECK_PHYS_NETLIST_DIFF_MOCK_RESULT is set");
} else {
Design unroutedDesign = PhysNetlistReader.readPhysNetlist(args[2]);

DesignComparator dc = new DesignComparator();
// Only compare PIPs on static and clock nets
dc.setComparePIPs((net) -> net.isStaticNet() || net.isClockNet());
numDiffs = dc.compareDesigns(unroutedDesign, routedDesign);
}
if (numDiffs == 0) {
System.out.println("INFO: No differences found between routed and unrouted netlists");
} else {
System.err.println("ERROR: Detected " + numDiffs + " differences between " + args[1] + " and " + args[2]);
}

// Read the Logical Netlist
EDIFNetlist netlist = LogNetlistReader.readLogNetlist(args[0]);

// Read the Physical Netlist
Design design = PhysNetlistReader.readPhysNetlist(args[1]);

// Combine Physical Netlist with Logical
design.setNetlist(netlist);
design.setName(netlist.getName());
routedDesign.setNetlist(netlist);
routedDesign.setName(netlist.getName());

// Add encrypted EDIF cells to the design if found
Path ednDirectory = Paths.get(args[0] + ".edn");
Expand All @@ -75,11 +92,11 @@ public static void main(String[] args) throws IOException, InterruptedException
}

// Examine the design routing and perform any necessary LUT pin swaps
LUTTools.swapLutPinsFromPIPs(design);
LUTTools.swapLutPinsFromPIPs(routedDesign);

// Write design to Vivado Design Checkpoint (DCP)
Path outputDcp = Paths.get(FileTools.removeFileExtension(args[1]) + ".dcp");
design.writeCheckpoint(outputDcp);
routedDesign.writeCheckpoint(outputDcp);

// Call Vivado's `report_route_status` command on this DCP
ReportRouteStatusResult rrs = null;
Expand Down Expand Up @@ -147,7 +164,7 @@ public static void main(String[] args) throws IOException, InterruptedException
}

// Exit code 0 only if Vivado reported that it was fully routed
System.exit(rrs.logicalNets > 0 && rrs.isFullyRouted() ? 0 : 1);
System.exit(numDiffs == 0 && rrs.logicalNets > 0 && rrs.isFullyRouted() ? 0 : 1);
}
}