From 6f987090cf44c24a0d80fe5a9fb648362fb3a653 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Wed, 5 Jul 2023 11:11:41 -0600 Subject: [PATCH 01/14] rc1 jar Signed-off-by: Chris Lavin --- .classpath | 4 ++-- .github/workflows/build.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.classpath b/.classpath index 19b9b37e6..ccbffa16f 100644 --- a/.classpath +++ b/.classpath @@ -33,9 +33,9 @@ - + - + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d51df1b2c..aaa2b206d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: pull_request: env: - RAPIDWRIGHT_VERSION: v2023.1.1-beta + RAPIDWRIGHT_VERSION: v2023.1.2-rc1-beta jobs: build: From c0f0028af60ce930785d3f08ccb07f999e502fa5 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Wed, 5 Jul 2023 12:19:37 -0600 Subject: [PATCH 02/14] Test for internal net connect (#730) * Test for internal net connect Signed-off-by: Chris Lavin * Rename net to avoid prim modification Signed-off-by: Chris Lavin --------- Signed-off-by: Chris Lavin --- .../xilinx/rapidwright/design/TestNet.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/design/TestNet.java b/test/src/com/xilinx/rapidwright/design/TestNet.java index 377514b80..2d4c6a367 100644 --- a/test/src/com/xilinx/rapidwright/design/TestNet.java +++ b/test/src/com/xilinx/rapidwright/design/TestNet.java @@ -23,16 +23,17 @@ package com.xilinx.rapidwright.design; -import com.xilinx.rapidwright.device.Device; -import com.xilinx.rapidwright.support.RapidWrightDCP; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import com.xilinx.rapidwright.device.Device; +import com.xilinx.rapidwright.support.RapidWrightDCP; public class TestNet { @Test @@ -341,4 +342,16 @@ public void testSetAlternateSourceDuplicate() { Assertions.assertThrows(RuntimeException.class, () -> net.setAlternateSource(spi2)); } + + @Test + public void testInternalConnectNet() { + Design design = new Design("test", Device.KCU105); + Cell lut0 = design.createAndPlaceCell("lut0", Unisim.LUT5, "SLICE_X0Y0/C6LUT"); + Cell f7mux0 = design.createAndPlaceCell("f7mux0", Unisim.MUXF7, "SLICE_X0Y0/F7MUX_CD"); + Net net0 = design.createNet("O"); + net0.connect(lut0, "O"); + net0.connect(f7mux0, "I1"); + + Assertions.assertEquals("I1", net0.getLogicalNet().getPortInst(f7mux0.getEDIFCellInst(), "I1").getName()); + } } From 0c2504a4c8c944b98b82fed1dc7de64e49b91b86 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Wed, 5 Jul 2023 12:19:48 -0600 Subject: [PATCH 03/14] Test for missing alternate pins (#732) Signed-off-by: Chris Lavin --- .../xilinx/rapidwright/design/TestDesign.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/src/com/xilinx/rapidwright/design/TestDesign.java b/test/src/com/xilinx/rapidwright/design/TestDesign.java index 58e2fb0eb..7f3f81ebf 100644 --- a/test/src/com/xilinx/rapidwright/design/TestDesign.java +++ b/test/src/com/xilinx/rapidwright/design/TestDesign.java @@ -308,4 +308,21 @@ private static void testDesignWithBackslashHelper(Design design) { final int extraNets = 5; // {a, b, o, GLOBAL_USEDNET, GLOBAL_LOGIC0} Assertions.assertEquals(design.getNets().size(), 2 + extraNets); } + + @Test + public void testFindDualOutputSitePins() { + Design d = RapidWrightDCP.loadDCP("microblazeAndILA_3pblocks.dcp"); + + String[] testNets = new String[] { + "base_mb_i/microblaze_0/U0/MicroBlaze_Core_I/Performance.Core/Data_Flow_I/Operand_Select_I/Gen_Bit[14].MUXF7_I1/Using_FPGA.Native_0[0]", + "base_mb_i/microblaze_0/U0/MicroBlaze_Core_I/Performance.Core/Data_Flow_I/exception_registers_I1/Using_FPGA_LUT6.Gen_Ret_Addr[20].MUXCY_XOR_I/LOCKSTEP_Out_reg[3027][0]", + "u_ila_0/inst/ila_core_inst/u_ila_regs/slaveRegDo_mux_2[15]_i_1_n_0" + }; + + for (int i = 0; i < testNets.length; i++) { + Net net = d.getNet(testNets[i]); + Assertions.assertNotNull(net.getSource()); + Assertions.assertNotNull(net.getAlternateSource()); + } + } } From af2c9a766137d01bc276b07f6add57678f337e3d Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Wed, 5 Jul 2023 12:19:59 -0600 Subject: [PATCH 04/14] Correctly update dual-output route flags when unrouting (#737) * Fixes an issue with makeBlackBox trying to remove pins from renamed nets Signed-off-by: Chris Lavin * Adding code to properly unroute site routing of a cell when removed Signed-off-by: Chris Lavin * Tweak description Signed-off-by: Chris Lavin * Add test, more fixes Signed-off-by: Chris Lavin * Fix test failure Signed-off-by: Chris Lavin * Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: eddieh-xlnx Signed-off-by: Chris Lavin * More fixes Signed-off-by: Chris Lavin * Update dual-output route when unrouting correctly Signed-off-by: Chris Lavin * Refactor test helper related to logical driver change (#739) * Refactoring to shared test area Signed-off-by: Chris Lavin * Add license header Signed-off-by: Chris Lavin --------- Signed-off-by: Chris Lavin --------- Signed-off-by: Chris Lavin Co-authored-by: eddieh-xlnx --- .../rapidwright/design/DesignTools.java | 31 ++++++++++---- .../rapidwright/design/TestDesignHelper.java | 42 +++++++++++++++++++ .../rapidwright/design/TestDesignTools.java | 31 ++++---------- .../xilinx/rapidwright/design/TestNet.java | 4 +- 4 files changed, 75 insertions(+), 33 deletions(-) create mode 100644 test/shared/com/xilinx/rapidwright/design/TestDesignHelper.java diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 53a60d248..974073350 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -1212,15 +1212,28 @@ public static Set getTrimmablePIPsFromPins(Net net, Collection curr = reverseConns.get(sink); fanoutCount = fanout.getOrDefault(sink, 0); } - if (curr == null && fanout.size() == 1 && !net.isStaticNet()) { - // We got all the way back to the source site. It is likely that - // the net is using dual exit points from the site as is common in - // SLICEs -- we should unroute the sitenet - SitePin sPin = sink.getSitePin(); - if (net.getSource() != null) { - SiteInst si = net.getSource().getSiteInst(); - BELPin belPin = sPin.getBELPin(); - si.unrouteIntraSiteNet(belPin, belPin); + if (curr == null && !net.isStaticNet()) { + if (fanoutCount == 1 && net.getAlternateSource() != null && net.getSource() != null) { + // check if this is a dual-output net and if we just removed one of the outputs + // if so, remove the logical driver flag + for (PIP pip : net.getPIPs()) { + if (pip.isLogicalDriver()) { + pip.setIsLogicalDriver(false); + break; + } + } + } + + if (fanout.size() == 1) { + // We got all the way back to the source site. It is likely that + // the net is using dual exit points from the site as is common in + // SLICEs -- we should unroute the sitenet + SitePin sPin = sink.getSitePin(); + if (net.getSource() != null) { + SiteInst si = net.getSource().getSiteInst(); + BELPin belPin = sPin.getBELPin(); + si.unrouteIntraSiteNet(belPin, belPin); + } } } } diff --git a/test/shared/com/xilinx/rapidwright/design/TestDesignHelper.java b/test/shared/com/xilinx/rapidwright/design/TestDesignHelper.java new file mode 100644 index 000000000..42f74ac02 --- /dev/null +++ b/test/shared/com/xilinx/rapidwright/design/TestDesignHelper.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Author: Chris Lavin, AMD Research and Advanced Development. + * + * 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.design; + +import com.xilinx.rapidwright.device.Device; + +public class TestDesignHelper { + + public static Net createTestNet(Design design, String netName, String[] pips) { + Net net = design.createNet(netName); + TestDesignHelper.addPIPs(net, pips); + return net; + } + + public static void addPIPs(Net net, String[] pips) { + Device device = net.getDesign().getDevice(); + for (String pip : pips) { + net.addPIP(device.getPIP(pip)); + } + } + +} diff --git a/test/src/com/xilinx/rapidwright/design/TestDesignTools.java b/test/src/com/xilinx/rapidwright/design/TestDesignTools.java index 5ffa2fe43..5c2e74e34 100644 --- a/test/src/com/xilinx/rapidwright/design/TestDesignTools.java +++ b/test/src/com/xilinx/rapidwright/design/TestDesignTools.java @@ -318,7 +318,7 @@ public void testBlackBoxCreation() { public void testGetTrimmablePIPsFromPins(String pinName) { Design design = new Design("top", "xcau10p"); Device device = design.getDevice(); - Net net = createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ "INT_X24Y92/INT.LOGIC_OUTS_E27->INT_NODE_SDQ_41_INT_OUT1", // Output pin "INT_X24Y92/INT.INT_NODE_SDQ_41_INT_OUT1->>SS1_E_BEG7", "INT_X24Y91/INT.SS1_E_END7->>INT_NODE_IMUX_25_INT_OUT1", @@ -358,7 +358,7 @@ public void testGetTrimmablePIPsFromPinsBidir(boolean unrouteAll) { Design design = new Design("test", "xcvu19p-fsva3824-1-e"); Device device = design.getDevice(); - Net net = createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ "INT_X102Y428/INT.LOGIC_OUTS_W30->>INT_NODE_IMUX_60_INT_OUT1", // EQ output "INT_X102Y428/INT.INT_NODE_IMUX_60_INT_OUT1->>BYPASS_W14", "INT_X102Y428/INT.INT_NODE_IMUX_50_INT_OUT0<<->>BYPASS_W14", // (reversed PIP) @@ -414,7 +414,7 @@ public void testGetTrimmablePIPsFromPinsBidirEndNode() { Design design = new Design("test", "xcvu19p-fsva3824-1-e"); Device device = design.getDevice(); - Net net = createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ "INT_X126Y235/INT.LOGIC_OUTS_W27->INT_NODE_SDQ_87_INT_OUT0", // DQ2 output "INT_X126Y235/INT.INT_NODE_SDQ_87_INT_OUT0->>EE4_W_BEG6", "INT_X128Y235/INT.EE4_W_END6->INT_NODE_SDQ_84_INT_OUT1", @@ -459,7 +459,7 @@ public void testGetTrimmablePIPsFromPinsBidirSinkNode() { Design design = new Design("test", "xcvu19p-fsva3824-1-e"); Device device = design.getDevice(); - Net net = createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ "INT_X115Y444/INT.LOGIC_OUTS_W30->INT_NODE_SDQ_91_INT_OUT1", // EQ "INT_X115Y444/INT.INT_NODE_SDQ_91_INT_OUT1->>INT_INT_SDQ_7_INT_OUT0", "INT_X115Y444/INT.INT_INT_SDQ_7_INT_OUT0->>INT_NODE_GLOBAL_10_INT_OUT0", @@ -507,7 +507,7 @@ public void testGetTrimmablePIPsFromPinsBidirBounceNode(boolean createBounceSink Design design = new Design("test", "xcvu19p-fsva3824-1-e"); Device device = design.getDevice(); - Net net = createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ "INT_X196Y535/INT.LOGIC_OUTS_E10->INT_NODE_SDQ_12_INT_OUT1", // DQ "INT_X196Y535/INT.INT_NODE_SDQ_12_INT_OUT1->>INT_INT_SDQ_73_INT_OUT0", "INT_X196Y535/INT.INT_INT_SDQ_73_INT_OUT0->>INT_NODE_GLOBAL_1_INT_OUT1", @@ -553,7 +553,7 @@ public void testGetTrimmablePIPsFromPinsBidirBounceNode(boolean createBounceSink public void testUnrouteSourcePinBidir() { Design design = new Design("test", "xcvu19p-fsva3824-1-e"); - Net net = createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ "INT_X193Y606/INT.LOGIC_OUTS_W27->INT_NODE_SDQ_87_INT_OUT0", "INT_X193Y606/INT.INT_NODE_SDQ_87_INT_OUT0->>NN1_W_BEG6", "INT_X193Y607/INT.NN1_W_END6->INT_NODE_SDQ_83_INT_OUT0", @@ -587,19 +587,6 @@ public void testUnrouteSourcePinBidir() { Assertions.assertTrue(net.getPIPs().isEmpty()); } - public static void addPIPs(Net net, String[] pips) { - Device device = net.getDesign().getDevice(); - for (String pip : pips) { - net.addPIP(device.getPIP(pip)); - } - } - - public static Net createTestNet(Design design, String netName, String[] pips) { - Net net = design.createNet(netName); - addPIPs(net, pips); - return net; - } - private void removeSourcePinHelper(boolean useUnroutePins, SitePinInst spi, int expectedPIPs) { if (useUnroutePins) { DesignTools.unroutePins(spi.getNet(), Arrays.asList(spi)); @@ -614,7 +601,7 @@ public void testRemoveSourcePin(boolean useUnroutePins) { Design design = new Design("test", Device.KCU105); // Net with one source (AQ2) and two sinks (A_I & FX) and a stub (INT_NODE_IMUX_71_INT_OUT) - Net net1 = createTestNet(design, "net1", new String[]{ + Net net1 = TestDesignHelper.createTestNet(design, "net1", new String[]{ // Translocated from example in // https://github.com/Xilinx/RapidWright/pull/475#issuecomment-1188337848 "INT_X63Y21/INT.LOGIC_OUTS_E12->>INT_NODE_SINGLE_DOUBLE_76_INT_OUT", @@ -644,7 +631,7 @@ public void testRemoveSourcePin(boolean useUnroutePins) { // Net with one output (HMUX) and one input (SRST_B2) - Net net2 = createTestNet(design, "net2", new String[]{ + Net net2 = TestDesignHelper.createTestNet(design, "net2", new String[]{ "INT_X42Y158/INT.LOGIC_OUTS_E16->>INT_NODE_SINGLE_DOUBLE_46_INT_OUT", "INT_X42Y158/INT.INT_NODE_SINGLE_DOUBLE_46_INT_OUT->>INT_INT_SINGLE_51_INT_OUT", "INT_X42Y158/INT.INT_INT_SINGLE_51_INT_OUT->>INT_NODE_GLOBAL_3_OUT1", @@ -669,7 +656,7 @@ public void testRemoveSourcePin(boolean useUnroutePins) { // Net with two outputs (HMUX primary and H_O alternate) and two sinks (SRST_B2 & B2) - Net net3 = createTestNet(design, "net3", new String[]{ + Net net3 = TestDesignHelper.createTestNet(design, "net3", new String[]{ // SLICE_X65Y158/HMUX-> SLICE_X64Y158/SRST_B2 "INT_X42Y158/INT.LOGIC_OUTS_E16->>INT_NODE_SINGLE_DOUBLE_46_INT_OUT", "INT_X42Y158/INT.INT_NODE_SINGLE_DOUBLE_46_INT_OUT->>INT_INT_SINGLE_51_INT_OUT", diff --git a/test/src/com/xilinx/rapidwright/design/TestNet.java b/test/src/com/xilinx/rapidwright/design/TestNet.java index 2d4c6a367..8d1c5b633 100644 --- a/test/src/com/xilinx/rapidwright/design/TestNet.java +++ b/test/src/com/xilinx/rapidwright/design/TestNet.java @@ -96,7 +96,7 @@ public void testRemovePrimarySourcePinPreserve(boolean preserveOtherRoutes) { Design design = new Design("test", Device.KCU105); // Net with two outputs (HMUX primary and H_O alternate) and two sinks (SRST_B2 & B2) - Net net = TestDesignTools.createTestNet(design, "net", new String[]{ + Net net = TestDesignHelper.createTestNet(design, "net", new String[]{ // SLICE_X65Y158/HMUX-> SLICE_X64Y158/SRST_B2 "INT_X42Y158/INT.LOGIC_OUTS_E16->>INT_NODE_SINGLE_DOUBLE_46_INT_OUT", "INT_X42Y158/INT.INT_NODE_SINGLE_DOUBLE_46_INT_OUT->>INT_INT_SINGLE_51_INT_OUT", @@ -165,7 +165,7 @@ public void testRemovePinOnStaticNet() { Net gndNet = design.getGndNet(); SitePinInst a6 = gndNet.createPin("A6", si); SitePinInst b6 = gndNet.createPin("B6", si); - TestDesignTools.addPIPs(gndNet, new String[]{ + TestDesignHelper.addPIPs(gndNet, new String[]{ "INT_X0Y0/INT.LOGIC_OUTS_E29->>INT_NODE_SINGLE_DOUBLE_101_INT_OUT", "INT_X0Y0/INT.INT_NODE_SINGLE_DOUBLE_101_INT_OUT->>SS1_E_BEG7", "INT_X0Y0/INT.INT_NODE_IMUX_64_INT_OUT->>IMUX_E16", From 7f8193e142e5cd40e16cdf8ad5d2eb6272f278e7 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Mon, 10 Jul 2023 11:57:59 -0600 Subject: [PATCH 05/14] Removes the VCC A6 pin on 5LUT usages when removing cells (#741) Signed-off-by: Chris Lavin --- .../rapidwright/design/DesignTools.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 974073350..837c85805 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -1737,6 +1737,26 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { BEL bel = c.getBEL(); SiteInst si = c.getSiteInst(); + // Check for VCC on A6 and remove if needed + if (c.getBEL().isLUT() && c.getBELName().endsWith("5LUT")) { + SitePinInst vcc = c.getSiteInst().getSitePinInst(c.getBELName().charAt(0) + "6"); + if (vcc != null && vcc.getNet().getName().equals(Net.VCC_NET)) { + boolean hasOtherSink = false; + for (BELPin otherSink : si.getSiteWirePins(vcc.getBELPin().getSiteWireIndex())) { + if (otherSink.isOutput()) + continue; + Cell otherCell = si.getCell(otherSink.getBEL()); + if (otherCell != null && otherCell.getLogicalPinMapping(otherSink.getName()) != null) { + hasOtherSink = true; + break; + } + } + if (!hasOtherSink) { + pinsToRemove.computeIfAbsent(vcc.getNet(), $ -> new HashSet<>()).add(vcc); + } + } + } + // Remove all physical nets first for (String logPin : c.getPinMappingsP2L().values()) { List removePins = unrouteCellPinSiteRouting(c, logPin); From 77500a3036a4cfd02ea8643c6484aeec5fa2da14 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Mon, 10 Jul 2023 16:47:43 -0600 Subject: [PATCH 06/14] rc2 jar Signed-off-by: Chris Lavin --- .classpath | 4 ++-- .github/workflows/build.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.classpath b/.classpath index ccbffa16f..8576a23a5 100644 --- a/.classpath +++ b/.classpath @@ -33,9 +33,9 @@ - + - + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aaa2b206d..318a2efb6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: pull_request: env: - RAPIDWRIGHT_VERSION: v2023.1.2-rc1-beta + RAPIDWRIGHT_VERSION: v2023.1.2-rc2-beta jobs: build: From 23d0ac3671c2e6260f62332521c348c5e958f70a Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Mon, 10 Jul 2023 16:52:47 -0600 Subject: [PATCH 07/14] Adds a MakeBlackBox command line tool (#747) Signed-off-by: Chris Lavin --- .../xilinx/rapidwright/MainEntrypoint.java | 2 + .../xilinx/rapidwright/util/MakeBlackBox.java | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/com/xilinx/rapidwright/util/MakeBlackBox.java diff --git a/src/com/xilinx/rapidwright/MainEntrypoint.java b/src/com/xilinx/rapidwright/MainEntrypoint.java index 52d865eb4..94403cd66 100644 --- a/src/com/xilinx/rapidwright/MainEntrypoint.java +++ b/src/com/xilinx/rapidwright/MainEntrypoint.java @@ -95,6 +95,7 @@ import com.xilinx.rapidwright.util.FileTools; import com.xilinx.rapidwright.util.JobQueue; import com.xilinx.rapidwright.util.Jython; +import com.xilinx.rapidwright.util.MakeBlackBox; import com.xilinx.rapidwright.util.PartPrinter; import com.xilinx.rapidwright.util.PerformanceExplorer; import com.xilinx.rapidwright.util.ReplaceEDIFInDCP; @@ -152,6 +153,7 @@ private static void addFunction(String name, MainStyleFunction func) { addFunction("Lesson1", Lesson1::main); addFunction("LogicalNetlistExample", LogicalNetlistExample::main); addFunction("LUTTools", LUTTools::main); + addFunction("MakeBlackBox", MakeBlackBox::main); addFunction("MergeDesigns", MergeDesigns::main); addFunction("MetadataParser", MetadataParser::main); addFunction("ModuleOptimizer", ModuleOptimizer::main); diff --git a/src/com/xilinx/rapidwright/util/MakeBlackBox.java b/src/com/xilinx/rapidwright/util/MakeBlackBox.java new file mode 100644 index 000000000..ebeddb3fc --- /dev/null +++ b/src/com/xilinx/rapidwright/util/MakeBlackBox.java @@ -0,0 +1,55 @@ +/* + * + * Copyright (c) 2023, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Author: Chris Lavin, AMD Research and Advanced Development. + * + * 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.util; + +import com.xilinx.rapidwright.design.Design; +import com.xilinx.rapidwright.design.DesignTools; +import com.xilinx.rapidwright.tests.CodePerfTracker; + +/** + * Command line wrapper to black box one or more cell instances in a design. + * + */ +public class MakeBlackBox { + + public static void main(String[] args) { + if (args.length < 3) { + System.err.println("USAGE: [another-cellinst-to-be-blackboxed] [...]"); + System.exit(1); + } + CodePerfTracker t = new CodePerfTracker("MakeBlackbox"); + + t.start("Read DCP"); + Design input = Design.readCheckpoint(args[0], CodePerfTracker.SILENT); + t.stop().start("Blackbox cell(s)"); + + for (int i = 2; i < args.length; i++) { + DesignTools.makeBlackBox(input, args[i]); + } + + t.stop().start("Write DCP"); + input.writeCheckpoint(args[1], CodePerfTracker.SILENT); + t.stop().printSummary(); + } +} From d9d1dda274ca53b5e444dbde71941da96b54988a Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Thu, 20 Jul 2023 15:54:34 -0600 Subject: [PATCH 08/14] Shell creation improvements to enable lock_design and timing closure preservation (#760) * Modifies makeBlackBox to also prohibit partially occupied half SLICEs Signed-off-by: Chris Lavin * Apply suggestions from code review Co-authored-by: eddieh-xlnx Signed-off-by: Chris Lavin * Fix compile issues from Consumer change Signed-off-by: Chris Lavin * Addresses review comments Signed-off-by: Chris Lavin --------- Signed-off-by: Chris Lavin Co-authored-by: eddieh-xlnx --- .../rapidwright/design/DesignTools.java | 311 ++++++++++++++++-- src/com/xilinx/rapidwright/edif/EDIFNet.java | 64 ++++ .../xilinx/rapidwright/edif/EDIFTools.java | 61 ++++ .../rapidwright/timing/TimingGraph.java | 5 +- .../xilinx/rapidwright/util/MakeBlackBox.java | 4 + 5 files changed, 416 insertions(+), 29 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 66e453629..961e9fe7b 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -1667,18 +1667,23 @@ public static List unrouteCellPinSiteRouting(Cell cell, String logi /** * Turns the cell named hierarchicalCell into a blackbox and removes any - * associated placement and routing information associated with that instance. In Vivado, - * this can be accomplished by running: (1) {@code update_design -cells -black_box} or (2) - * by deleting all of the cells and nets insides of a cell instance. Method (2) is - * more likely to have complications. - * @param d The current design + * associated placement and routing information associated with that instance. + * In Vivado, this can be accomplished by running: (1) + * {@code update_design -cells -black_box} or (2) by deleting all of the + * cells and nets insides of a cell instance. Method (2) is more likely to have + * complications. This also unroutes both GND and VCC nets to avoid + * implementation issues by Vivado in subsequent place and route runs. + * + * @param d The current design * @param hierarchicalCell The hierarchical cell to become a black box. */ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { - CodePerfTracker t = CodePerfTracker.SILENT;// new CodePerfTracker("makeBlackBox", true); + CodePerfTracker t = CodePerfTracker.SILENT;// new CodePerfTracker("makeBlackBox", true); t.start("Init"); EDIFCellInst futureBlackBox = hierarchicalCell.getInst(); - if (futureBlackBox == null) throw new RuntimeException("ERROR: Couldn't find cell " + hierarchicalCell + " in source design " + d.getName()); + if (futureBlackBox == null) + throw new RuntimeException( + "ERROR: Couldn't find cell " + hierarchicalCell + " in source design " + d.getName()); if (hierarchicalCell.getCellType() == d.getTopEDIFCell()) { d.unplaceDesign(); @@ -1688,7 +1693,7 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { } Set touched = new HashSet<>(); - Map boundaryNets = new HashMap<>(); + Map boundaryNets = new HashMap<>(); Map> pinsToRemove = new HashMap<>(); @@ -1696,13 +1701,15 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { // Find all the nets that connect to the cell (keep them) for (EDIFPortInst portInst : futureBlackBox.getPortInsts()) { EDIFNet net = portInst.getNet(); - EDIFHierCellInst hierParentName =hierarchicalCell.getParent(); + EDIFHierCellInst hierParentName = hierarchicalCell.getParent(); EDIFHierNet hierNetName = new EDIFHierNet(hierParentName, net); EDIFHierNet parentNetName = d.getNetlist().getParentNet(hierNetName); - boundaryNets.put(parentNetName.getHierarchicalNetName(), portInst.isOutput() ? hierNetName.getHierarchicalNetName() : null); + boundaryNets.put(parentNetName.getHierarchicalNetName(), + portInst.isOutput() ? hierNetName.getHierarchicalNetName() : null); // Remove parts of routed GND/VCC nets exiting the black box - if (portInst.isInput()) continue; + if (portInst.isInput()) + continue; NetType netType = NetType.getNetTypeFromNetName(parentNetName.getHierarchicalNetName()); if (netType.isStaticNetType()) { // Black box is supplying VCC/GND, we must unroute connected tree @@ -1711,7 +1718,8 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { // extract site wire and site pins and nodes to unroute for (EDIFHierPortInst sink : sinks) { Cell c = d.getCell(sink.getFullHierarchicalInstName()); - if (c == null || !c.isPlaced()) continue; + if (c == null || !c.isPlaced()) + continue; String logicalPinName = sink.getPortInst().getName(); // Remove all physical nets first List removePins = unrouteCellPinSiteRouting(c, logicalPinName); @@ -1726,8 +1734,8 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { List allLeafs = d.getNetlist().getAllLeafDescendants(hierarchicalCell); - - // Remove all placement and routing information related to the cell to be blackboxed + // Remove all placement and routing information related to the cell to be + // blackboxed for (EDIFHierCellInst i : allLeafs) { // Get the physical cell, make sure we can unplace/unroute it first Cell c = d.getCell(i.getFullHierarchicalInstName()); @@ -1785,7 +1793,8 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { t.stop().start("new net names"); - // Update black box output nets with new net names (those with sinks inside the black box) + // Update black box output nets with new net names (those with sinks inside the + // black box) Map netsToUpdate = new HashMap<>(); for (Net n : d.getNets()) { String newName = boundaryNets.get(n.getName()); @@ -1806,19 +1815,12 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { t.stop().start("cleanup siteinsts"); - // Keep track of site instances to remove, but keep those supplying static sources + // Keep track of site instances to remove, but keep those supplying static + // sources List siteInstsToRemove = new ArrayList<>(); for (SiteInst siteInst : touched) { if (siteInst.getCells().size() == 0) { - boolean keepSiteInst = false; - for (SitePinInst pin : siteInst.getSitePinInsts()) { - if (pin.getNet() != null && pin.getNet().isStaticNet() && pin.isOutPin()) { - keepSiteInst = true; - } - } - if (!keepSiteInst) { - siteInstsToRemove.add(siteInst); - } + siteInstsToRemove.add(siteInst); } } @@ -1838,14 +1840,17 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { t.stop().start("create bbox"); // Make EDIFCell blackbox - EDIFCell blackBox = new EDIFCell(futureBlackBox.getCellType().getLibrary(),"black_box" + - uniqueBlackBoxCount++); + EDIFCell blackBox = new EDIFCell(futureBlackBox.getCellType().getLibrary(), + "black_box" + uniqueBlackBoxCount++); for (EDIFPort port : futureBlackBox.getCellType().getPorts()) { blackBox.addPort(port); } futureBlackBox.setCellType(blackBox); futureBlackBox.addProperty(EDIFCellInst.BLACK_BOX_PROP, true); + unrouteGNDNetAndLUTSources(d); + d.getVccNet().unroute(); + t.stop().printSummary(); } @@ -3634,4 +3639,256 @@ public static boolean isNetDrivenByHierPort(Net net) { return true; } + + /** + * Locks the logical netlist of the design using the DONT_TOUCH property. This + * strives to be as close as possible to what Vivado's 'lock_design -level + * netlist' does to lock the design. {@link EDIFTools#lockNetlist(EDIFNetlist)}. + * + * @param design The design of the netlist to lock. + */ + public static void lockNetlist(Design design) { + EDIFTools.lockNetlist(design.getNetlist()); + } + + /** + * Unlocks the logical netlist of the design by removing the DONT_TOUCH + * property. This strives to be as close as possible to what Vivado's + * 'lock_design -unlock -level netlist' does to lock the + * design.{@link EDIFTools#unlockNetlist(EDIFNetlist)}. + * + * @param design The design of the netlist to unlock. + */ + public static void unlockNetlist(Design design) { + EDIFTools.unlockNetlist(design.getNetlist()); + } + + /** + * Locks or unlocks all placement of a design against changes in Vivado. It will + * also lock or unlock the netlist of the design (see + * {@link #lockNetlist(Design)}). This strives to be as close as possible to + * what Vivado's 'lock_design -level placement' does to lock the design. + * + * @param design The design to lock + * @param lock Flag indicating to lock (true) or unlock (false) the design's + * placement and netlist. + */ + public static void lockPlacement(Design design, boolean lock) { + if (lock) { + lockNetlist(design); + } else { + unlockNetlist(design); + } + for (SiteInst si : design.getSiteInsts()) { + si.setSiteLocked(lock); + for (Cell cell : si.getCells()) { + cell.setBELFixed(lock); + cell.setSiteFixed(lock); + } + } + } + + /** + * Locks placement of cells of a design against changes in Vivado. It will also + * lock the netlist the design (see {@link #lockNetlist(Design)}). This strives + * to be as close as possible to what Vivado's 'lock_design -level placement' + * does to lock the design. + * + * @param design The design to lock + */ + public static void lockPlacement(Design design) { + lockPlacement(design, true); + } + + /** + * Unlocks placement of cells of a design. It will also unlock the netlist the + * design (see {@link #unlockNetlist(Design)}). This strives to be as close as + * possible to what Vivado's 'lock_design -unlock -level placement' does to lock + * the design. + * + * @param design The design to unlock + */ + public static void unlockPlacement(Design design) { + lockPlacement(design, false); + } + + /** + * Locks or unlocks all routing of a design (except GND and VCC nets) against + * changes in Vivado. It will also lock or unlock the netlist and placement of + * the design (see {@link #lockPlacement(Design, boolean)}). This strives to be + * as close as possible to what Vivado's 'lock_design -level routing' does to + * lock the design. + * + * @param design The design to lock + * @param lock Flag indicating to lock (true) or unlock (false) the design's + * routing, placement and netlist. + */ + public static void lockRouting(Design design, boolean lock) { + lockPlacement(design, lock); + for (Net net : design.getNets()) { + if (net.isStaticNet()) + continue; + for (PIP p : net.getPIPs()) { + p.setIsPIPFixed(lock); + } + } + } + + /** + * Locks all routing of a design (except GND and VCC nets) against changes in + * Vivado. It will also lock the netlist and placement of the design. This + * strives to be as close as possible to what Vivado's 'lock_design -level + * routing' does to lock the design. + * + * @param design The design to lock + */ + public static void lockRouting(Design design) { + lockRouting(design, true); + } + + /** + * Unlocks any and all routing of a design. It will also unlock the netlist and + * placement of the design. This strives to be as close as possible to what + * Vivado's 'lock_design -unlock -level routing' does to lock the design. + * + * @param design The design to unlock + */ + public static void unlockRouting(Design design) { + lockRouting(design, false); + } + + /*** + * Unroutes the GND net of a design and unroutes the site routing of any LUT GND + * sources while leaving other site routing inputs intact. + * + * @param design The design to modify. + */ + public static void unrouteGNDNetAndLUTSources(Design design) { + // Unroute the site routing of implicit LUT GND sources + Set gndNodes = new HashSet<>(); + for (PIP p : design.getGndNet().getPIPs()) { + gndNodes.add(p.getStartNode()); + } + + for (Node n : gndNodes) { + SitePin sp = n.getSitePin(); + if (sp != null && !sp.isInput() && Utils.isSLICE(sp.getSite().getSiteTypeEnum())) { + BELPin src = sp.getBELPin().getSourcePin(); + if (src.getBEL().isLUT()) { + SiteInst si = design.getSiteInstFromSite(sp.getSite()); + if (si != null) { + si.unrouteIntraSiteNet(src, sp.getBELPin()); + } + } + } + } + + design.getGndNet().unroute(); + } + + /** + * Adds a PROHIBIT constraint for each LUT BEL supplying GND. This is useful + * when trying to preserve a partially implemented design that have additional + * logic placed and routed onto it later. The Vivado placer doesn't recognize + * the GND sources so this prevents the placer from using those BEL sites. + * + * @param design The design to which the PROHIBIT constraints are added. + */ + public static void prohibitGNDSources(Design design) { + Set gndNodes = new HashSet<>(); + for (PIP p : design.getGndNet().getPIPs()) { + gndNodes.add(p.getStartNode()); + } + + List bels = new ArrayList<>(); + for (Node n : gndNodes) { + SitePin sp = n.getSitePin(); + if (sp != null && !sp.isInput() && Utils.isSLICE(sp.getSite().getSiteTypeEnum())) { + BELPin src = sp.getBELPin().getSourcePin(); + if (src.getBEL().isLUT()) { + bels.add(sp.getSite().getName() + "/" + src.getBELName()); + } + } + } + addProhibitConstraint(design, bels); + } + + /** + * Checks the provided BEL's first letter to determine if it is in the top half + * of a SLICE or bottom half. + * + * @param bel The BEL of a SLICE to query + * @return True if the BEL resides in the top half of a SLICE (E6LUT, E5LUT, + * EFF, EFF2, ..). Returns false if it is in the bottom half and null if + * it couldn't be determined. + */ + public static Boolean isUltraScaleSliceTop(BEL bel) { + if (bel.isLUT() || bel.isFF()) { + char letter = bel.getName().charAt(0); + return letter >= 'E' && letter <= 'H'; + } + return null; + } + + /** + * This adds PROHIBIT constraints to the design (via .XDC) that will prohibit + * the use of BEL sites in the same half SLICE if there are any other cells + * placed in it. This is used for shell creation when an existing placed and + * routed implementation is desired to be preserved but to allow additional + * logic to be placed and routed on top of it without an area (pblock) + * constraint. + * + * @param design The design to which the constraints are added. + */ + public static void prohibitPartialHalfSlices(Design design) { + List bels = new ArrayList<>(); + + for (SiteInst si : design.getSiteInsts()) { + if (!Utils.isSLICE(si)) continue; + boolean bottomUsed = false; + boolean topUsed = false; + for (Cell c : si.getCells()) { + Boolean sliceHalf = isUltraScaleSliceTop(c.getBEL()); + if (sliceHalf != null) { + if (sliceHalf) { + topUsed = true; + } else { + bottomUsed = true; + } + } + } + + for (BEL bel : si.getSite().getBELs()) { + if (bel.getBELClass() == BELClass.BEL && si.getCell(bel) == null) { + Boolean isTop = isUltraScaleSliceTop(bel); + if (isTop != null) { + if ((isTop && topUsed) || (!isTop && bottomUsed)) { + bels.add(si.getSiteName() + "/" + bel.getName()); + } + } + } + } + } + addProhibitConstraint(design, bels); + } + + /** + * Adds a PROHIBIT constraint to the specified BEL Locations (ex: + * "SLICE_X10Y10/AFF") + * + * @param design The design to which the constraint should be added + * @param belLocations A list of BEL locations using the syntax + * '/'. + */ + public static void addProhibitConstraint(Design design, List belLocations) { + if (belLocations.size() > 0) { + StringBuilder sb = new StringBuilder(); + for (String bel : belLocations) { + sb.append(bel); + sb.append(" "); + } + design.addXDCConstraint(ConstraintGroup.LATE, + "set_property PROHIBIT true [get_bels { " + sb.toString() + "} ]"); + } + } } diff --git a/src/com/xilinx/rapidwright/edif/EDIFNet.java b/src/com/xilinx/rapidwright/edif/EDIFNet.java index 4993765a4..0bf626bd7 100644 --- a/src/com/xilinx/rapidwright/edif/EDIFNet.java +++ b/src/com/xilinx/rapidwright/edif/EDIFNet.java @@ -36,6 +36,7 @@ import java.util.List; import com.xilinx.rapidwright.design.Cell; +import com.xilinx.rapidwright.design.Unisim; /** * Represents a net within an EDIF netlist. @@ -358,6 +359,69 @@ protected EDIFPortInstList getEDIFPortInstList() { return portInsts; } + /** + * Checks if this net is a logical VCC net. It first checks if the net matches + * the defacto name for VCC in Vivado synthesis, "\" + * ({@link EDIFTools#LOGICAL_VCC_NET_NAME}). If there is not match, it will also + * check the source of the net to see if it is a VCC primitive. + * + * @return True if this is a logical VCC net, false otherwise. + */ + public boolean isVCC() { + return checkIsStaticSource(EDIFTools.LOGICAL_VCC_NET_NAME, Unisim.VCC.name()); + } + + /** + * Checks if this net is a logical GND net. It first checks if the net matches + * the defacto name for GND in Vivado synthesis, "\" + * ({@link EDIFTools#LOGICAL_GND_NET_NAME}). If there is not match, it will also + * check the source of the net to see if it is a GND primitive. + * + * @return True if this is a logical GND net, false otherwise. + */ + public boolean isGND() { + return checkIsStaticSource(EDIFTools.LOGICAL_GND_NET_NAME, Unisim.GND.name()); + } + + /** + * Helper method to {@link #isVCC()} and {@link #isGND()} by checking the net + * name and source if it is the queried static source net. + * + * @param name Defacto Vivado static source net name (see + * ({@link EDIFTools#LOGICAL_VCC_NET_NAME}) or + * ({@link EDIFTools#LOGICAL_GND_NET_NAME})). + * @param cellType This would be either 'VCC' or 'GND'. + * @return True if it was determined that the static net query matched, false + * otherwise. + */ + private boolean checkIsStaticSource(String name, String cellType) { + // Rely on Vivado-standardized logical names + if (!getName().equals(name)) { + // Check source + for (EDIFPortInst portInst : getSourcePortInsts(false)) { + if (portInst.getCellInst().getCellType().getName().equals(cellType)) { + return true; + } + } + return false; + } + return true; + } + + /** + * Checks if the net has all port instances (terminals) within the parent cell. + * + * @return True if all port instances are internal to this net's parent cell, + * false otherwise. If the net has not port instances, it returns true. + */ + public boolean isInternalToParent() { + for (EDIFPortInst pi : getPortInsts()) { + if (pi.isTopLevelPort()) return false; + } + return true; + } + + public static final byte[] EXPORT_CONST_NET_START = " (net ".getBytes(StandardCharsets.UTF_8); public static final byte[] EXPORT_CONST_JOINED = " (joined\n".getBytes(StandardCharsets.UTF_8); public static final byte[] EXPORT_CONST_PORT_INDENT = " ".getBytes(StandardCharsets.UTF_8); diff --git a/src/com/xilinx/rapidwright/edif/EDIFTools.java b/src/com/xilinx/rapidwright/edif/EDIFTools.java index 5ce86dfda..8aad927aa 100644 --- a/src/com/xilinx/rapidwright/edif/EDIFTools.java +++ b/src/com/xilinx/rapidwright/edif/EDIFTools.java @@ -47,6 +47,7 @@ import java.util.Queue; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import com.xilinx.rapidwright.design.Cell; import com.xilinx.rapidwright.design.Design; @@ -76,6 +77,8 @@ public class EDIFTools { public static final String EDIF_PART_PROP = "PART"; + public static final String DONT_TOUCH = "DONT_TOUCH"; + public static final Set edifKeywordSet = new HashSet<>(Arrays.asList( "abs", "acload", "actual", "after", "and", "annotate", "apply", @@ -1485,4 +1488,62 @@ Iterable> sortIfStable(Map collection, boolean stable) { } return collection.entrySet().stream().sorted(Entry.comparingByKey())::iterator; } + + /** + * Locks the netlist by applying the DONT_TOUCH property to instances and nets + * so that Vivado won't make changes to it during opt_design, place_design, + * phys_opt_design, or route_design. Note: RapidWright doesn't respect the + * DONT_TOUCH attribute. + * + * @param netlist The netlist to lock + */ + public static void lockNetlist(EDIFNetlist netlist) { + EDIFPropertyValue value = new EDIFPropertyValue("true", EDIFValueType.BOOLEAN); + lockNetlist(netlist, i -> i.addProperty(DONT_TOUCH, value)); + } + + /** + * Unlocks the netlist by removing the DONT_TOUCH property on instances and nets + * so that Vivado won't make changes to it during opt_design, place_design, + * phys_opt_design, or route_design. + * + * @param netlist The netlist to unlock + */ + public static void unlockNetlist(EDIFNetlist netlist) { + lockNetlist(netlist, i -> i.removeProperty(DONT_TOUCH)); + } + + /** + * Traversal helper method to {@link #lockNetlist(EDIFNetlist)} and + * {@link #unlockNetlist(EDIFNetlist)}. + * + * @param netlist The netlist on which to apply the action. + * @param lockAction The method of action (lock or unlock) to apply to + * {@link EDIFPropertyObject} objects. + */ + private static void lockNetlist(EDIFNetlist netlist, Consumer lockAction) { + EDIFCell top = netlist.getTopCell(); + for (EDIFLibrary lib : netlist.getLibraries()) { + if (lib.isHDIPrimitivesLibrary()) continue; + for (EDIFCell cell : lib.getCells()) { + for (EDIFCellInst inst : cell.getCellInsts()) { + EDIFCell cellType = inst.getCellType(); + if (cellType.isPrimitive() && !cellType.hasContents()) { + String type = cellType.getName(); + if (!type.equals(Unisim.GND.name()) && !type.equals(Unisim.VCC.name())) { + lockAction.accept(inst); + } + } + } + + for (EDIFNet net : cell.getNets()) { + if (net != null && !net.isGND() && !net.isVCC()) { + if (cell == top || net.isInternalToParent()) { + lockAction.accept(net); + } + } + } + } + } + } } diff --git a/src/com/xilinx/rapidwright/timing/TimingGraph.java b/src/com/xilinx/rapidwright/timing/TimingGraph.java index f60a54f77..151acfe52 100644 --- a/src/com/xilinx/rapidwright/timing/TimingGraph.java +++ b/src/com/xilinx/rapidwright/timing/TimingGraph.java @@ -52,6 +52,7 @@ import com.xilinx.rapidwright.edif.EDIFNet; import com.xilinx.rapidwright.edif.EDIFPortInst; import com.xilinx.rapidwright.edif.EDIFPropertyValue; +import com.xilinx.rapidwright.edif.EDIFTools; import com.xilinx.rapidwright.rwroute.Connection; import com.xilinx.rapidwright.rwroute.RouterHelper; import com.xilinx.rapidwright.util.Pair; @@ -1088,8 +1089,8 @@ else if (myCellName.startsWith("LUT") || myCellName.startsWith("RAM") || myCellN EDIFPortInst epiForI5 = eciParent.getPortInst("I5"); EDIFNet enForI5 = epiForI5.getNet(); - boolean pinI5ConnectedToConst0 = enForI5.getName().equals(""); - boolean pinI5ConnectedToConst1 = enForI5.getName().equals(""); + boolean pinI5ConnectedToConst0 = enForI5.getName().equals(EDIFTools.LOGICAL_GND_NET_NAME); + boolean pinI5ConnectedToConst1 = enForI5.getName().equals(EDIFTools.LOGICAL_VCC_NET_NAME); boolean thisCellIsLUT5 = c.getType().equals("LUT5"); thisCellEquation = LUTTools.getLUTEquation(eciParent); diff --git a/src/com/xilinx/rapidwright/util/MakeBlackBox.java b/src/com/xilinx/rapidwright/util/MakeBlackBox.java index ebeddb3fc..f9eef4a88 100644 --- a/src/com/xilinx/rapidwright/util/MakeBlackBox.java +++ b/src/com/xilinx/rapidwright/util/MakeBlackBox.java @@ -29,6 +29,7 @@ /** * Command line wrapper to black box one or more cell instances in a design. + * Also prohibits partially used half SLICEs from being used. * */ public class MakeBlackBox { @@ -48,6 +49,9 @@ public static void main(String[] args) { DesignTools.makeBlackBox(input, args[i]); } + // Necessary to make the design place-able by Vivado later + DesignTools.prohibitPartialHalfSlices(input); + t.stop().start("Write DCP"); input.writeCheckpoint(args[1], CodePerfTracker.SILENT); t.stop().printSummary(); From 34b118986a6698a3939fcef5fdd14a788b2f4250 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Fri, 21 Jul 2023 11:15:03 -0600 Subject: [PATCH 09/14] rc3 jar Signed-off-by: Chris Lavin --- .classpath | 4 ++-- .github/workflows/build.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.classpath b/.classpath index 8576a23a5..2826ae0e9 100644 --- a/.classpath +++ b/.classpath @@ -33,9 +33,9 @@ - + - + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 318a2efb6..153dae4bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: pull_request: env: - RAPIDWRIGHT_VERSION: v2023.1.2-rc2-beta + RAPIDWRIGHT_VERSION: v2023.1.2-rc3-beta jobs: build: From ee3cf9f9a33ebb8e5617db1183b7c2206f1d17c5 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Fri, 21 Jul 2023 16:18:05 -0600 Subject: [PATCH 10/14] Fix module relocation in the face of tile node depopulation (#763) * Fix module relocation in the fact of tile node depopulation Signed-off-by: Chris Lavin * Fix test failures Signed-off-by: Chris Lavin --------- Signed-off-by: Chris Lavin --- .../xilinx/rapidwright/design/ModuleInst.java | 7 +++++ .../rapidwright/design/TestModuleInst.java | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/com/xilinx/rapidwright/design/ModuleInst.java b/src/com/xilinx/rapidwright/design/ModuleInst.java index 4f2cb394f..7d947065c 100644 --- a/src/com/xilinx/rapidwright/design/ModuleInst.java +++ b/src/com/xilinx/rapidwright/design/ModuleInst.java @@ -34,6 +34,7 @@ import com.xilinx.rapidwright.design.blocks.PBlockRange; import com.xilinx.rapidwright.design.noc.NOCClient; import com.xilinx.rapidwright.device.Device; +import com.xilinx.rapidwright.device.Node; import com.xilinx.rapidwright.device.PIP; import com.xilinx.rapidwright.device.Site; import com.xilinx.rapidwright.device.SiteTypeEnum; @@ -389,6 +390,12 @@ public boolean place(Site newAnchorSite, boolean skipIncompatible, boolean allow if (pipSet != null) { pipSet.add(newPip); } + // Some tiles have nodes that are depopulated, we need to detect those + Node endNode = newPip.getEndNode(); + if (endNode != null && endNode.getAllDownhillPIPs().size() == 0 + && pip.getEndNode().getAllDownhillPIPs().size() != 0) { + return false; + } net.addPIP(newPip); } } diff --git a/test/src/com/xilinx/rapidwright/design/TestModuleInst.java b/test/src/com/xilinx/rapidwright/design/TestModuleInst.java index d91d90fa6..8130f2cbd 100644 --- a/test/src/com/xilinx/rapidwright/design/TestModuleInst.java +++ b/test/src/com/xilinx/rapidwright/design/TestModuleInst.java @@ -27,6 +27,7 @@ import com.xilinx.rapidwright.device.Site; import com.xilinx.rapidwright.device.Tile; import com.xilinx.rapidwright.edif.EDIFCell; +import com.xilinx.rapidwright.edif.EDIFNet; import com.xilinx.rapidwright.edif.EDIFNetlist; import com.xilinx.rapidwright.support.RapidWrightDCP; import com.xilinx.rapidwright.tests.CodePerfTracker; @@ -36,6 +37,7 @@ import org.junit.jupiter.params.provider.ValueSource; import java.util.HashSet; +import java.util.Set; public class TestModuleInst { @ParameterizedTest @@ -216,4 +218,33 @@ public void testConnectMovesPins() { Assertions.assertEquals("[OUT SLICE_X15Y237.HQ2, IN SLICE_X16Y233.A2]", net1.getPins().toString()); Assertions.assertTrue(net2.getPins().isEmpty()); } + + @Test + public void testPlaceWithDepopulatedNodes() { + Design modDesign = new Design("module", "xcvu13p-fsga2577-1-i"); + Cell src = modDesign.createAndPlaceCell("src", Unisim.LUT6, "SLICE_X148Y899/H6LUT"); + Cell snk = modDesign.createAndPlaceCell("snk", Unisim.FDCE, "SLICE_X145Y899/DFF2"); + + Net physNet = TestDesignHelper.createTestNet(modDesign, "net0", + new String[] { "INT_X94Y899/INT.LOGIC_OUTS_E28->INT_NODE_SDQ_42_INT_OUT0", + "INT_X94Y899/INT.INT_NODE_SDQ_42_INT_OUT1->>WW4_E_BEG7", + "INT_X92Y899/INT.WW4_E_END7->>INT_NODE_GLOBAL_12_INT_OUT1", // Node fanout does not exist in all + // Tiles + "INT_X92Y899/INT.INT_NODE_GLOBAL_12_INT_OUT1->>CTRL_W1", }); + + EDIFNet logNet = physNet.getLogicalNet(); + logNet.createPortInst("O", src); + logNet.createPortInst("CE", snk); + + Module module = new Module(modDesign); + + Design design = new Design("top", modDesign.getPartName()); + ModuleInst mi = design.createModuleInst("inst0", module); + + Set validAnchorSites = new HashSet<>(mi.getAllValidPlacements()); + + Assertions.assertFalse(validAnchorSites.contains(design.getDevice().getSite("SLICE_X117Y589"))); + Assertions.assertEquals(70560, validAnchorSites.size()); + + } } From 89dd36705ca3dd35bd2cfbaf8010af111ae51fdc Mon Sep 17 00:00:00 2001 From: eddieh-xlnx Date: Mon, 24 Jul 2023 08:20:22 -0700 Subject: [PATCH 11/14] Test that Cell.getProperty() returns null when no EDIFCellInst (#754) * Test that Cell.getProperty() returns null when no EDIFCellInst Signed-off-by: Eddie Hung * Update test/src/com/xilinx/rapidwright/design/TestCell.java Signed-off-by: eddieh-xlnx --------- Signed-off-by: Eddie Hung Signed-off-by: eddieh-xlnx Signed-off-by: Chris Lavin Co-authored-by: Chris Lavin --- test/src/com/xilinx/rapidwright/design/TestCell.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/design/TestCell.java b/test/src/com/xilinx/rapidwright/design/TestCell.java index 473b3881e..773961271 100644 --- a/test/src/com/xilinx/rapidwright/design/TestCell.java +++ b/test/src/com/xilinx/rapidwright/design/TestCell.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, Xilinx, Inc. - * Copyright (c) 2022, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Eddie Hung, Xilinx Research Labs. @@ -74,4 +74,11 @@ public void testGetCorrespondingSitePinName() { Assertions.assertEquals(pin.getName(), cell.getCorrespondingSitePinName("D")); } + + @Test + public void testGetPropertyNoEDIFCellInst() { + Cell cell = new Cell("cell"); + Assertions.assertNull(cell.getEDIFCellInst()); + Assertions.assertNull(cell.getProperty("any_property")); + } } From 733fba335bf3a9f6d6bad3a5318cab32c23f6747 Mon Sep 17 00:00:00 2001 From: eddieh-xlnx Date: Mon, 24 Jul 2023 10:40:24 -0700 Subject: [PATCH 12/14] Add DesignTools.updatePinsIsRouted() (#762) * GlobalSignalRouting.routeStaticNet() to create output SPIs... ... when using non-tied-node sources (e.g. LUTs) Signed-off-by: Eddie Hung * Update TestRWRoute.testBug701() Signed-off-by: Eddie Hung * Add TestGlobalSignalRouting.testRouteStaticNet() Signed-off-by: Eddie Hung * Make RWRoute.preprocess() public and use it Signed-off-by: Eddie Hung * Add DesignTools.updatePinsIsRouted() with test Signed-off-by: Eddie Hung * Fix whitespace Signed-off-by: Eddie Hung * Fix updatePinsIsRouted() for bidir PIPs Signed-off-by: Eddie Hung * TestRWRoute to re-compute SitePinInst.isRouted() Signed-off-by: Eddie Hung * Update src/com/xilinx/rapidwright/design/DesignTools.java Signed-off-by: eddieh-xlnx * Fix infinite loop when bidir PIPs Signed-off-by: Eddie Hung Conflicts: src/com/xilinx/rapidwright/design/DesignTools.java * Update src/com/xilinx/rapidwright/design/DesignTools.java Signed-off-by: eddieh-xlnx --------- Signed-off-by: Eddie Hung Signed-off-by: eddieh-xlnx --- .../rapidwright/design/DesignTools.java | 65 ++++++++++++++++++- .../rapidwright/design/TestDesignTools.java | 16 +++++ .../rapidwright/rwroute/TestRWRoute.java | 24 ++++--- 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 961e9fe7b..5054503bf 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -32,6 +32,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -3890,5 +3891,67 @@ public static void addProhibitConstraint(Design design, List belLocation design.addXDCConstraint(ConstraintGroup.LATE, "set_property PROHIBIT true [get_bels { " + sb.toString() + "} ]"); } - } + } + + /** + * Update the SitePinInst.isRouted() value of all sink pins on the given + * Net. A pin will be marked as being routed if it is reachable from the + * Net's source pins (or in the case of static nets, also from nodes + * tied to GND or VCC) when following the Net's PIPs. + * @param net Net on which pins are to be updated. + */ + public static void updatePinsIsRouted(Net net) { + Queue queue = new ArrayDeque<>(); + Map> node2fanout = new HashMap<>(); + Map> bidirNode2nodes = new HashMap<>(); + for (PIP pip : net.getPIPs()) { + boolean isReversed = pip.isReversed(); + Node startNode = isReversed ? pip.getEndNode() : pip.getStartNode(); + Node endNode = isReversed ? pip.getStartNode() : pip.getEndNode(); + node2fanout.computeIfAbsent(startNode, k -> new ArrayList<>()) + .add(endNode); + if (pip.isBidirectional()) { + bidirNode2nodes.computeIfAbsent(startNode, k -> new HashSet<>()).add(endNode); + bidirNode2nodes.computeIfAbsent(endNode, k -> new HashSet<>()).add(startNode); + node2fanout.computeIfAbsent(endNode, k -> new ArrayList<>()) + .add(startNode); + } + + if ((net.getType() == NetType.GND && startNode.isTiedToGnd()) || + (net.getType() == NetType.VCC && startNode.isTiedToVcc())) { + queue.add(startNode); + } + } + + Map node2spi = new HashMap<>(); + for (SitePinInst spi : net.getPins()) { + spi.setRouted(false); + Node node = spi.getConnectedNode(); + if (spi.isOutPin()) { + queue.add(node); + continue; + } + node2spi.put(spi.getConnectedNode(), spi); + } + + while (!queue.isEmpty()) { + Node node = queue.poll(); + SitePinInst spi = node2spi.get(node); + if (spi != null) { + spi.setRouted(true); + } + + List fanouts = node2fanout.get(node); + if (fanouts != null) { + for (Node fanout : fanouts) { + if (bidirNode2nodes.getOrDefault(fanout, Collections.emptySet()).contains(node)) { + // In the case of bidir PIPs, remove the ability to go from the fanout + // node back to this node + node2fanout.get(fanout).remove(node); + } + queue.add(fanout); + } + } + } + } } diff --git a/test/src/com/xilinx/rapidwright/design/TestDesignTools.java b/test/src/com/xilinx/rapidwright/design/TestDesignTools.java index bc695eced..6524146d5 100644 --- a/test/src/com/xilinx/rapidwright/design/TestDesignTools.java +++ b/test/src/com/xilinx/rapidwright/design/TestDesignTools.java @@ -1158,4 +1158,20 @@ public void testUnrouteCellPinSiteRouting() { Assertions.assertNull(si4.getUsedSitePIP("FFMUXB1")); Assertions.assertNull(si4.getNetFromSiteWire("B_O")); } + + @Test + public void testUpdatePinsIsRouted() { + String dcpPath = RapidWrightDCP.getString("picoblaze_ooc_X10Y235.dcp"); + Design design = Design.readCheckpoint(dcpPath); + + for (Net net : design.getNets()) { + for (SitePinInst spi : net.getPins()) { + Assertions.assertFalse(spi.isRouted()); + } + DesignTools.updatePinsIsRouted(net); + for (SitePinInst spi : net.getPins()) { + Assertions.assertTrue(spi.isOutPin() || spi.isRouted()); + } + } + } } diff --git a/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java b/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java index da6dc5a95..948e1ae69 100644 --- a/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java +++ b/test/src/com/xilinx/rapidwright/rwroute/TestRWRoute.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; +import com.xilinx.rapidwright.design.DesignTools; import com.xilinx.rapidwright.util.FileTools; import com.xilinx.rapidwright.util.ReportRouteStatusResult; import com.xilinx.rapidwright.util.VivadoTools; @@ -49,11 +50,16 @@ import com.xilinx.rapidwright.support.RapidWrightDCP; public class TestRWRoute { - private static void assertAllSinksRouted(List pins) { - for (SitePinInst spi : pins) { - if (spi.isOutPin()) - continue; - Assertions.assertTrue(spi.isRouted()); + private static void assertAllSinksRouted(Net net) { + for (SitePinInst spi : net.getPins()) { + Assertions.assertTrue(spi.isOutPin() || spi.isRouted()); + } + + // Re-compute the isRouted() state by analyzing from PIPs + DesignTools.updatePinsIsRouted(net); + + for (SitePinInst spi : net.getPins()) { + Assertions.assertTrue(spi.isOutPin() || spi.isRouted()); } } @@ -72,7 +78,7 @@ private static void assertAllSinksRouted(Design design) { // Source-less nets may exist in out-of-context design continue; } - assertAllSinksRouted(net.getPins()); + assertAllSinksRouted(net); } } @@ -155,7 +161,7 @@ public void testNonTimingDrivenPartialRouting() { Assertions.assertFalse(routed.getModifiedNets().isEmpty()); for (Net net : routed.getModifiedNets()) { - assertAllSinksRouted(net.getPins()); + assertAllSinksRouted(net); } assertVivadoFullyRouted(design); } @@ -173,11 +179,11 @@ public void testTimingDrivenPartialRouting() { design.setTrackNetChanges(true); boolean softPreserve = false; - Design routed = PartialRouter.routeDesignPartialTimingDriven(design, null, false); + Design routed = PartialRouter.routeDesignPartialTimingDriven(design, null, softPreserve); Assertions.assertFalse(routed.getModifiedNets().isEmpty()); for (Net net : routed.getModifiedNets()) { - assertAllSinksRouted(net.getPins()); + assertAllSinksRouted(net); } assertVivadoFullyRouted(design); } From 69194db267e3b2b0a83ca9fd9da976c7c7549670 Mon Sep 17 00:00:00 2001 From: eddieh-xlnx Date: Mon, 24 Jul 2023 14:16:25 -0700 Subject: [PATCH 13/14] Add DesignTools.getAllRoutedSitePinsFromPhysicalPin() (#755) * DesignTools.getRoutedSitePinFromPhysicalPin() to have no side effects Previously it would set any discovered alternate sources as the primary source. Signed-off-by: Eddie Hung * RWRoute.createNetWrapperAndConnections() to create alt source Signed-off-by: Eddie Hung * RWRoute.createNetWrapperAndConnections() to set source properly for mixed direct/indirect connection nets Signed-off-by: Eddie Hung * Update testCreateMissingSitePinInstsInPins() Since DesignTools.createMissingSitePinInsts() doesn't unused infer alternate output pins anymore Signed-off-by: Eddie Hung * Refactor into DesignTools.getAllRoutedSitePinsFromPhysicalPin() Signed-off-by: Eddie Hung * getAllRoutedSitePinsFromPhysicalPin() to not return null Signed-off-by: Eddie Hung * DesignTools.fullyUnplaceCellHelper() to use getAllRoutedSitePins...() Signed-off-by: Eddie Hung * RWRoute to accept that altSource may not reach INT tile Signed-off-by: Eddie Hung * Apply suggestions from code review Signed-off-by: eddieh-xlnx * Revert createMissingStaticSitePins() change Signed-off-by: Eddie Hung --------- Signed-off-by: Eddie Hung Signed-off-by: eddieh-xlnx --- .../rapidwright/design/DesignTools.java | 70 +++++++++---------- .../xilinx/rapidwright/rwroute/RWRoute.java | 42 +++++------ .../rapidwright/design/TestDesignTools.java | 26 +++++-- 3 files changed, 73 insertions(+), 65 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 5054503bf..49c298041 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -1314,8 +1314,7 @@ private static void fullyUnplaceCellHelper(Cell cell, Map> } if (otherUser == false) { // Unroute site routing back to pin and remove site pin - String sitePinName = getRoutedSitePinFromPhysicalPin(cell, net, pin.getName()); - if (sitePinName != null) { + for (String sitePinName : getAllRoutedSitePinsFromPhysicalPin(cell, net, pin.getName())) { BELPin sitePortBelPin = siteInst.getSite().getBELPin(sitePinName); assert(sitePortBelPin.isSitePort()); boolean outputSitePin = sitePortBelPin.isInput(); // Input BELPin means output SitePin @@ -2127,13 +2126,12 @@ public static List createMissingSitePinInsts(Design design, Net net } /** - * Gets the site pin that is currently routed to the specified cell pin. If + * Gets the first site pin that is currently routed to the specified cell pin. If * the site instance is not routed, it will return null. - * Side Effect: It will set alternative source site pins on the net if present. * @param cell The cell with the pin of interest. * @param net The physical net to which this pin belongs * @param logicalPinName The logical pin name of the cell to query. - * @return The name of the site pin on the cell's site to which the pin is routed. + * @return The name of the first site pin on the cell's site to which the pin is routed. */ public static String getRoutedSitePin(Cell cell, Net net, String logicalPinName) { String belPinName = cell.getPhysicalPinMapping(logicalPinName); @@ -2141,19 +2139,32 @@ public static String getRoutedSitePin(Cell cell, Net net, String logicalPinName) } /** - * Gets the site pin that is currently routed to the specified cell pin. If + * Gets the first site pin that is currently routed to the specified cell pin. If * the site instance is not routed, it will return null. - * Side Effect: It will set alternative source site pins on the net if present. * @param cell The cell with the pin of interest. * @param net The physical net to which this pin belongs * @param belPinName The physical pin name of the cell - * @return The name of the site pin on the cell's site to which the pin is routed. + * @return The name of the first site pin on the cell's site to which the pin is routed. */ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String belPinName) { + List sitePins = getAllRoutedSitePinsFromPhysicalPin(cell, net, belPinName); + return (!sitePins.isEmpty()) ? sitePins.get(0) : null; + } + + /** + * Gets all site pins that are currently routed to the specified cell pin. If + * the site instance is not routed, it will return null. + * @param cell The cell with the pin of interest. + * @param net The physical net to which this pin belongs + * @param belPinName The physical pin name of the cell + * @return A list of site pin names on the cell's site to which the pin is routed. + * @since 2023.1.2 + */ + public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net net, String belPinName) { SiteInst inst = cell.getSiteInst(); - if (belPinName == null) return null; + if (belPinName == null) return Collections.emptyList(); + List sitePins = new ArrayList<>(); Set siteWires = new HashSet<>(inst.getSiteWiresFromNet(net)); - String toReturn = null; Queue queue = new LinkedList<>(); queue.add(cell.getBEL().getPin(belPinName)); while (!queue.isEmpty()) { @@ -2162,18 +2173,18 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String if (!siteWires.contains(siteWireName)) { // Allow dedicated paths to pass without site routing if (siteWireName.equals("CIN") || siteWireName.equals("COUT")) { - return siteWireName; + return Collections.singletonList(siteWireName); } - return null; + return Collections.emptyList(); } if (curr.isInput()) { BELPin source = curr.getSourcePin(); - if (source == null) return null; + if (source == null) return Collections.emptyList(); if (source.isSitePort()) { - return source.getName(); + return Collections.singletonList(source.getName()); } else if (source.getBEL().getBELClass() == BELClass.RBEL) { SitePIP sitePIP = inst.getUsedSitePIP(source.getBELName()); - if (sitePIP == null) return null; + if (sitePIP == null) continue; queue.add(sitePIP.getInputPin()); } else if (source.getBEL().isLUT() || source.getBEL().getBELType().endsWith("MUX")) { Cell possibleRouteThru = inst.getCell(source.getBEL()); @@ -2182,49 +2193,32 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String queue.add(source.getBEL().getPin(routeThru)); } } else { - return null; + return Collections.emptyList(); } } else { // output for (BELPin sink : curr.getSiteConns()) { if (!siteWires.contains(sink.getSiteWireName())) continue; if (sink.isSitePort()) { - // Check if there is a dual output scenario - if (toReturn != null) { - SitePinInst source = net.getSource(); - String toCreate; - if (source != null && source.getName().equals(sink.getName())) { - toCreate = toReturn; - toReturn = sink.getName(); - } else { - toCreate = sink.getName(); - } - if (inst.getSitePinInst(toCreate) == null) - net.createPin(toCreate, inst); - // We'll return the first one we found, store the 2nd in the alternate - // reference on the net - return toReturn; - } else { - toReturn = sink.getName(); - } + sitePins.add(sink.getName()); } else if (sink.getBEL().getBELClass() == BELClass.RBEL) { // Check if the SitePIP is being used SitePIP sitePIP = inst.getUsedSitePIP(sink.getBELName()); if (sitePIP == null) continue; - // Don't proceed if its configured for a different pin + // Don't proceed if it's configured for a different pin if (!sitePIP.getInputPinName().equals(sink.getName())) continue; // Make this the new source to search from and keep looking... queue.add(sitePIP.getOutputPin()); - } else if (sink.getBELName().contains("FF")) { + } else if (sink.getBEL().isFF()) { // FF pass thru option (not a site PIP) siteWireName = sink.getBEL().getPin("Q").getSiteWireName(); if (siteWires.contains(siteWireName)) { - return siteWireName; + sitePins.add(siteWireName); } } } } } - return toReturn; + return sitePins; } /** diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index f921fa617..92d67b59c 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -509,13 +509,6 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { RouteNode altSourceINTRnode = null; for (SitePinInst sink : net.getSinkPins()) { - if (RouterHelper.isExternalConnectionToCout(source, sink)) { - source = net.getAlternateSource(); - if (source == null) { - String errMsg = "Null alternate source is for COUT-CIN connection: " + net.toStringFull(); - throw new IllegalArgumentException(errMsg); - } - } Connection connection = new Connection(numConnectionsToRoute++, source, sink, netWrapper); List nodes = RouterHelper.projectInputPinToINTNode(sink); @@ -527,14 +520,10 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { indirectConnections.add(connection); checkSinkRoutability(net, sinkINTNode); connection.setSinkRnode(getOrCreateRouteNode(sinkINTNode, RouteNodeType.PINFEED_I)); - if (sourceINTRnode == null) { + if (sourceINTRnode == null && altSourceINTRnode == null) { Node sourceINTNode = RouterHelper.projectOutputPinToINTNode(source); - if (sourceINTNode == null) { - throw new RuntimeException("ERROR: Null projected INT node for the source of net " + net.toStringFull()); - } - sourceINTRnode = getOrCreateRouteNode(sourceINTNode, RouteNodeType.PINFEED_O); - // Pre-emptively set up alternate source since we are expanding from both sources + // Pre-emptively set up alternate source since we may expand from both sources SitePinInst altSource = net.getAlternateSource(); if (altSource == null) { altSource = DesignTools.getLegalAlternativeOutputPin(net); @@ -543,18 +532,31 @@ protected NetWrapper createNetWrapperAndConnections(Net net) { DesignTools.routeAlternativeOutputSitePin(net, altSource); } } + if (altSource != null) { assert(!altSource.equals(source)); Node altSourceNode = RouterHelper.projectOutputPinToINTNode(altSource); - if (altSourceNode != null) { - altSourceINTRnode = getOrCreateRouteNode(altSourceNode, RouteNodeType.PINFEED_O); - } else { - // No projection exists -- could be a dedicated pin like COUT, for example - } + altSourceINTRnode = altSourceNode != null ? getOrCreateRouteNode(altSourceNode, RouteNodeType.PINFEED_O) : null; } + + if (sourceINTNode != null) { + sourceINTRnode = getOrCreateRouteNode(sourceINTNode, RouteNodeType.PINFEED_O); + } + + if (sourceINTRnode == null && altSourceINTRnode == null) { + throw new RuntimeException("ERROR: Null projected INT node for the source of net " + net.toStringFull()); + } + } + if (sourceINTRnode != null) { + connection.setSourceRnode(sourceINTRnode); + connection.setAltSourceRnode(altSourceINTRnode); + } else { + // Primary source does not reach the fabric (e.g. COUT) + // just use alternate source + assert(altSourceINTRnode != null); + connection.setSource(net.getAlternateSource()); + connection.setSourceRnode(altSourceINTRnode); } - connection.setSourceRnode(sourceINTRnode); - connection.setAltSourceRnode(altSourceINTRnode); connection.setDirect(false); indirect++; connection.computeHpwl(); diff --git a/test/src/com/xilinx/rapidwright/design/TestDesignTools.java b/test/src/com/xilinx/rapidwright/design/TestDesignTools.java index 6524146d5..f6c378305 100644 --- a/test/src/com/xilinx/rapidwright/design/TestDesignTools.java +++ b/test/src/com/xilinx/rapidwright/design/TestDesignTools.java @@ -212,23 +212,35 @@ public void testCreateMissingSitePinInstsInPins() { final Set dualOutputNets = new HashSet() {{ add("picoblaze_2_25/processor/alu_result_0"); - add("picoblaze_2_25/processor/alu_result_1"); add("picoblaze_2_25/processor/alu_result_2"); - add("picoblaze_8_43/processor/pc_move_is_valid"); add("picoblaze_0_43/processor/E[0]"); }}; + final Set possibleDualOutputNets = new HashSet() {{ + add("picoblaze_2_25/processor/alu_result_1"); + add("picoblaze_8_43/processor/pc_move_is_valid"); + }}; + for (Net net : design.getNets()) { Collection pins = net.getPins(); - if (net.getSource() != null) { - Assertions.assertTrue(pins.contains(net.getSource())); + SitePinInst source = net.getSource(); + if (source != null) { + Assertions.assertTrue(pins.contains(source)); } - if (net.getAlternateSource() != null) { - Assertions.assertTrue(pins.contains(net.getAlternateSource())); + SitePinInst altSource = net.getAlternateSource(); + if (altSource != null) { + Assertions.assertTrue(pins.contains(altSource)); } if (dualOutputNets.contains(net.getName())) { - Assertions.assertTrue(net.getSource() != null && net.getAlternateSource() != null); + Assertions.assertNotNull(source); + Assertions.assertNotNull(altSource); + } else if (possibleDualOutputNets.contains(net.getName())) { + Assertions.assertNotNull(source); + Assertions.assertNull(altSource); + altSource = DesignTools.getLegalAlternativeOutputPin(net); + Assertions.assertNotNull(altSource); + Assertions.assertNotEquals(altSource, source); } } } From d73091dd2c043cad462eb56c614c05424608ba41 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Mon, 24 Jul 2023 15:45:38 -0600 Subject: [PATCH 14/14] Final jar and release notes Signed-off-by: Chris Lavin --- .classpath | 4 ++-- .github/workflows/build.yml | 2 +- RELEASE_NOTES.TXT | 43 +++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/.classpath b/.classpath index 2826ae0e9..2d3b8d481 100644 --- a/.classpath +++ b/.classpath @@ -33,9 +33,9 @@ - + - + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 153dae4bc..ea24d7dcb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: pull_request: env: - RAPIDWRIGHT_VERSION: v2023.1.2-rc3-beta + RAPIDWRIGHT_VERSION: v2023.1.2-beta jobs: build: diff --git a/RELEASE_NOTES.TXT b/RELEASE_NOTES.TXT index bbb3959fb..e755b24d0 100644 --- a/RELEASE_NOTES.TXT +++ b/RELEASE_NOTES.TXT @@ -1,3 +1,46 @@ +============= RapidWright 2023.1.2-beta released on 2023-07-24 ================ +Notes: + - Shell creation improvements to enable lock_design and timing closure preservation (#760) + - Adds a MakeBlackBox command line tool (#747) + - Removes the VCC A6 pin on 5LUT usages when removing cells (#741) + - Add DesignTools.getAllRoutedSitePinsFromPhysicalPin() (#755) + - Correctly update dual-output route flags when unrouting (#737) + - [PhysNetlistReader] Set cell type of LOCKED cells (#767) + - Updates RAM32X1S property to correct default (#751) + - [Interchange] PhysNetlistReader to create STATIC_SOURCE SiteInsts (#766) + - RWRoute Fixes (#765) + - GlobalSignalRouting.routeStaticNet() to create output SPIs (#761) + - DesignTools.createCeSrRstPinsToVCC() to skip non-SLICE FFs (#744) + - [PartialRouter] Improve incremental global routing (#759) + - GlobalSignalRouting fixes for routing to non clock-pins (#757) + - DesignTools.makePhysNetNamesConsistent() to merge static nets too (#753) + - [UltraScaleClockRouting] Reset RouteNode.parent (#752) + - Created parameterizable counter with an adder as a submodule (#713) + - [RWRoute] Fix PartialRouter for when clk node already unpreserved (#746) + - [Interchange] Fix PhysicalNetlist's MultiCellPinMapping (#743) + - Unroute site routing when removing a cell (#729) + - PartialRouter's global router to not unpreserve sink nodes (#736) + - DesignTools.makePhysNetNamesConsistent() to use hier name (#735) + - DesignTools.makePhysNetNamesConsistent() to consider */ (#734) + - Add DcpToInterchange class (#704) + - Add compile step (#733) + - Add EdifToLogicalNetlist to MainEntrypoint (#731) + - Fix Javadoc warnings (#723) + - Fixes an issue with makeBlackBox trying to remove pins from renamed nets (#728) + - [PhysNetlistReader] Set Cell type for routethru cells (#727) + - Multilevel macro expansion (#726) + - TestReplaceEDIFInDCP to copy DCP before replacing in-place (#725) + - DesignTools.createMissingSitePinInsts() to skip node-less site pins (#724) + - Fix to create alternate source pins on dual output nets. + - Fixes incorrect Versal SLR corner tile entries + - Cell.getProperty() returns null if no EDIFCellInst found + - Cell.getAllSitePinsFromLogicalPin() to not return any null pins + - Cell.getAllCorrespondingSitePinNames() to not NPE if no physical pin mapping + - Cell.getCorrespondingSitePinName() to consider F?MUX routethrus +- API Additions: + - com.xilinx.rapidwright.device.PIP "public boolean isLogicalDriver()" + - com.xilinx.rapidwright.design.Cell "public String getCorrespondingSitePinName(String logicalPinName, String physPinName, List siteWires)" + ============= RapidWright 2023.1.1-beta released on 2023-06-21 ================ Notes: - UltraScale Incremental Clock Router Improvements (#540)