From d4986567f3f3efa327eb99db3b9dfa81977dff99 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Thu, 6 Nov 2025 09:35:16 -0800 Subject: [PATCH 01/17] Parallelize router initialization Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index e364d0217..795fa37a2 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2282,7 +2282,9 @@ public static List createMissingSitePinInsts(Design design, Net net if (siteWireNet == null) { if (isVersal && net.isStaticNet() && bel.isLUT()) { siteWireNet = net; - si.routeIntraSiteNet(net, belPin, belPin); + synchronized (si) { + si.routeIntraSiteNet(net, belPin, belPin); + } } else { continue; } @@ -2299,16 +2301,19 @@ public static List createMissingSitePinInsts(Design design, Net net "'" + net.getName() + "'"); } } - String sitePinName = getRoutedSitePinFromPhysicalPin(c, siteWireNet, physPin); - if (sitePinName == null) continue; - SitePinInst newPin = si.getSitePinInst(sitePinName); - if (newPin != null) continue; - if (sitePinName.equals("IO") && Utils.isIOB(si)) { - // Do not create a SitePinInst for the "IO" input site pin of any IOB site, - // since the sitewire it drives is assumed to be driven by the IO PAD. - continue; + SitePinInst newPin; + synchronized (si) { + String sitePinName = getRoutedSitePinFromPhysicalPin(c, siteWireNet, physPin); + if (sitePinName == null) continue; + newPin = si.getSitePinInst(sitePinName); + if (newPin != null) continue; + if (sitePinName.equals("IO") && Utils.isIOB(si)) { + // Do not create a SitePinInst for the "IO" input site pin of any IOB site, + // since the sitewire it drives is assumed to be driven by the IO PAD. + continue; + } + newPin = net.createPin(sitePinName, si); } - newPin = net.createPin(sitePinName, si); if (newPin != null) newPins.add(newPin); } } @@ -2460,9 +2465,9 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne */ public static void createMissingSitePinInsts(Design design) { EDIFNetlist netlist = design.getNetlist(); - for (Net net : design.getNets()) { + design.getNets().parallelStream().forEach((net) -> { if (net.isUsedNet()) { - continue; + return; } EDIFHierNet ehn = net.getLogicalHierNet(); EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; @@ -2472,11 +2477,11 @@ public static void createMissingSitePinInsts(Design design) { // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) // to analyze its parent net) but that parent net also exist in the design and has been/ // will be analyzed in due course, so skip doing so here - continue; + return; } } createMissingSitePinInsts(design,net); - } + }); } private static HashSet muxPins; @@ -3308,7 +3313,7 @@ public static void printSiteInstInfo(SiteInst siteInst, PrintStream ps) { public static void makePhysNetNamesConsistent(Design design) { Map netParentMap = design.getNetlist().getParentNetMap(); EDIFNetlist netlist = design.getNetlist(); - for (Net net : new ArrayList<>(design.getNets())) { + new ArrayList<>(design.getNets()).parallelStream().forEach((net) -> { Net parentPhysNet = null; if (net.isStaticNet()) { if (net.getType() == NetType.GND) { @@ -3319,19 +3324,19 @@ public static void makePhysNetNamesConsistent(Design design) { throw new RuntimeException(); } if (parentPhysNet == net) { - continue; + return; } } else { EDIFHierNet hierNet = netlist.getHierNetFromName(net.getName()); if (hierNet == null) { // Likely an encrypted cell - continue; + return; } EDIFHierNet parentHierNet = netParentMap.get(hierNet); if (parentHierNet == null) { // System.out.println("WARNING: Couldn't find parent net for '" + // hierNet.getHierarchicalNetName() + "'"); - continue; + return; } // Check to make sure net is not improperly categorized @@ -3366,7 +3371,7 @@ public static void makePhysNetNamesConsistent(Design design) { if (parentPhysNet != null) { design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); } - } + }); } public static void createPossiblePinsToStaticNets(Design design) { From 262f4f25f3367aa45e083aeca37ccc3d9b11d87a Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Thu, 6 Nov 2025 10:25:12 -0800 Subject: [PATCH 02/17] Start improving parallelism Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 45 ++++++++++++------- .../xilinx/rapidwright/rwroute/RWRoute.java | 3 ++ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 795fa37a2..40f654733 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -38,6 +38,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Deque; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; @@ -50,6 +51,7 @@ import java.util.PriorityQueue; import java.util.Queue; import java.util.Set; +import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -85,6 +87,7 @@ import com.xilinx.rapidwright.placer.blockplacer.ImplsPath; import com.xilinx.rapidwright.router.RouteNode; import com.xilinx.rapidwright.tests.CodePerfTracker; +import com.xilinx.rapidwright.util.CountUpDownLatch; import com.xilinx.rapidwright.util.FileTools; import com.xilinx.rapidwright.util.Installer; import com.xilinx.rapidwright.util.Job; @@ -92,6 +95,7 @@ import com.xilinx.rapidwright.util.LocalJob; import com.xilinx.rapidwright.util.MessageGenerator; import com.xilinx.rapidwright.util.Pair; +import com.xilinx.rapidwright.util.ParallelismTools; import com.xilinx.rapidwright.util.StringTools; import com.xilinx.rapidwright.util.Utils; @@ -2465,23 +2469,32 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne */ public static void createMissingSitePinInsts(Design design) { EDIFNetlist netlist = design.getNetlist(); - design.getNets().parallelStream().forEach((net) -> { - if (net.isUsedNet()) { - return; - } - EDIFHierNet ehn = net.getLogicalHierNet(); - EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; - if (parentEhn != null && !parentEhn.equals(ehn)) { - Net parentNet = design.getNet(parentEhn.getHierarchicalNetName()); - if (parentNet != null) { - // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) - // to analyze its parent net) but that parent net also exist in the design and has been/ - // will be analyzed in due course, so skip doing so here - return; + final CountUpDownLatch netsOutstanding = new CountUpDownLatch(); + for (Net net : design.getNets()) { + netsOutstanding.countUp(); + ParallelismTools.submit(() -> { + try { + if (net.isUsedNet()) { + return; + } + EDIFHierNet ehn = net.getLogicalHierNet(); + EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; + if (parentEhn != null && !parentEhn.equals(ehn)) { + Net parentNet = design.getNet(parentEhn.getHierarchicalNetName()); + if (parentNet != null) { + // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) + // to analyze its parent net) but that parent net also exist in the design and has been/ + // will be analyzed in due course, so skip doing so here + return; + } + } + createMissingSitePinInsts(design, net); + } finally { + netsOutstanding.countDown(); } - } - createMissingSitePinInsts(design,net); - }); + }); + } + netsOutstanding.await(); } private static HashSet muxPins; diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 9505f9b89..c743d5725 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -226,12 +226,15 @@ public static void preprocess(Design design) { } // Pre-processing of the design regarding physical net names pins + CodePerfTracker t = new CodePerfTracker(RWRoute.class.getName()); + t.start("RWRoute Preprocess"); DesignTools.makePhysNetNamesConsistent(design); DesignTools.createPossiblePinsToStaticNets(design); DesignTools.createMissingSitePinInsts(design); if (series == Series.Versal) { DesignTools.updateVersalXPHYPinsForDMC(design); } + t.stop(); } protected void preprocess() { From e2c9b4e9c3d6c56e610a4110fa4f4e707776c0b2 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Thu, 6 Nov 2025 16:22:19 -0800 Subject: [PATCH 03/17] Parallelize createMissingSitePinInsts Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 116 ++++++++++++++---- .../rapidwright/rwroute/PartialRouter.java | 11 +- .../xilinx/rapidwright/rwroute/RWRoute.java | 6 +- 3 files changed, 107 insertions(+), 26 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 40f654733..e85882964 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -51,6 +51,8 @@ import java.util.PriorityQueue; import java.util.Queue; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -98,6 +100,7 @@ import com.xilinx.rapidwright.util.ParallelismTools; import com.xilinx.rapidwright.util.StringTools; import com.xilinx.rapidwright.util.Utils; +import org.python.google.common.collect.Lists; /** * A collection of methods to operate on {@link Design} objects. @@ -2199,7 +2202,6 @@ public static boolean placeCell(Cell c, Design design) { return false; } - /** * Creates any and all missing SitePinInsts for this net. This is common as a placed * DCP will not have SitePinInsts annotated and this information is generally necessary @@ -2208,6 +2210,18 @@ public static boolean placeCell(Cell c, Design design) { * @return The list of pins that were created or an empty list if none were created. */ public static List createMissingSitePinInsts(Design design, Net net) { + return createMissingSitePinInsts(design, net, null); + } + + /** + * Creates any and all missing SitePinInsts for this net. This is common as a placed + * DCP will not have SitePinInsts annotated and this information is generally necessary + * for routing to take place. + * @param design The current design of this net. + * @return The list of pins that were created or an empty list if none were created. + */ + public static List createMissingSitePinInsts(Design design, Net net, + Map>> siteInstToNetSiteWiresMap) { boolean isVersal = design.getSeries() == Series.Versal; EDIFNetlist n = design.getNetlist(); List physPins = n.getPhysicalPins(net); @@ -2230,7 +2244,11 @@ public static List createMissingSitePinInsts(Design design, Net net // Likely net inside encrypted IP, let's see if we can infer anything from existing // physical description for (SiteInst siteInst : new ArrayList<>(net.getSiteInsts())) { - for (String siteWire : new ArrayList<>(siteInst.getSiteWiresFromNet(net))) { + Map> netSiteWiresMap = siteInstToNetSiteWiresMap != null ? + siteInstToNetSiteWiresMap.get(siteInst) : null; + List netSiteWires = netSiteWiresMap != null ? + netSiteWiresMap.get(net) : siteInst.getSiteWiresFromNet(net); + for (String siteWire : new ArrayList<>(netSiteWires)) { for (BELPin pin : siteInst.getSiteWirePins(siteWire)) { if (!pin.isSitePort()) { continue; @@ -2306,9 +2324,10 @@ public static List createMissingSitePinInsts(Design design, Net net } } SitePinInst newPin; + String sitePinName = getRoutedSitePinFromPhysicalPin(c, siteWireNet, + physPin, siteInstToNetSiteWiresMap); + if (sitePinName == null) continue; synchronized (si) { - String sitePinName = getRoutedSitePinFromPhysicalPin(c, siteWireNet, physPin); - if (sitePinName == null) continue; newPin = si.getSitePinInst(sitePinName); if (newPin != null) continue; if (sitePinName.equals("IO") && Utils.isIOB(si)) { @@ -2347,10 +2366,32 @@ public static String getRoutedSitePin(Cell cell, Net net, String logicalPinName) * @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 getRoutedSitePinFromPhysicalPin(cell, net, belPinName, null); + } + + /** + * 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. + * @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 first site pin on the cell's site to which the pin is routed. + */ + public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String belPinName, + Map>> siteInstToNetSiteWiresMap) { + List sitePins = getAllRoutedSitePinsFromPhysicalPin(cell, net, belPinName, siteInstToNetSiteWiresMap); return (!sitePins.isEmpty()) ? sitePins.get(0) : null; } + public static Map>> getSiteInstToNetSiteWiresMap(Design design) { + ConcurrentMap>> siteInstToNetSiteWiresMap = new ConcurrentHashMap<>(); + design.getCells().parallelStream().forEach((c) -> { + SiteInst inst = c.getSiteInst(); + siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); + }); + return siteInstToNetSiteWiresMap; + } + /** * Gets all site pins that are currently routed to the specified cell pin. If * the site instance is not routed, it will return null. @@ -2361,15 +2402,35 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String * @since 2023.1.2 */ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net net, String belPinName) { + return getAllRoutedSitePinsFromPhysicalPin(cell, net, belPinName, 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, Map>> siteInstToNetSiteWiresMap) { if (belPinName == null) { return Collections.emptyList(); } SiteInst inst = cell.getSiteInst(); + Map> netSiteWiresMap = null; + if (siteInstToNetSiteWiresMap != null) { + netSiteWiresMap = siteInstToNetSiteWiresMap.get(inst); + } List sitePins = new ArrayList<>(); - Set siteWires = new HashSet<>(inst.getSiteWiresFromNet(net)); + List siteWires = netSiteWiresMap != null ? netSiteWiresMap.get(net) : inst.getSiteWiresFromNet(net); if (net.isGNDNet()) { // Since GND sitewires may be inverted for easier routing, also accept VCC sitewires - siteWires.addAll(inst.getSiteWiresFromNet(cell.getSiteInst().getDesign().getVccNet())); + Net vccNet = cell.getSiteInst().getDesign().getVccNet(); + List vccSiteWires = netSiteWiresMap != null ? + netSiteWiresMap.get(vccNet) : inst.getSiteWiresFromNet(vccNet); + siteWires.addAll(vccSiteWires); } Queue queue = new LinkedList<>(); queue.add(cell.getBEL().getPin(belPinName)); @@ -2469,32 +2530,39 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne */ public static void createMissingSitePinInsts(Design design) { EDIFNetlist netlist = design.getNetlist(); - final CountUpDownLatch netsOutstanding = new CountUpDownLatch(); - for (Net net : design.getNets()) { - netsOutstanding.countUp(); + final CountUpDownLatch threadsOutstanding = new CountUpDownLatch(); + Map>> siteInstToNetSiteWiresMap = DesignTools.getSiteInstToNetSiteWiresMap(design); + int numNets = design.getNets().size(); + int numThreads = ParallelismTools.maxParallelism(); + List designNets = new ArrayList<>(design.getNets()); + List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numThreads)); + for (List nets : partitionedNets) { + threadsOutstanding.countUp(); ParallelismTools.submit(() -> { try { - if (net.isUsedNet()) { - return; - } - EDIFHierNet ehn = net.getLogicalHierNet(); - EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; - if (parentEhn != null && !parentEhn.equals(ehn)) { - Net parentNet = design.getNet(parentEhn.getHierarchicalNetName()); - if (parentNet != null) { - // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) - // to analyze its parent net) but that parent net also exist in the design and has been/ - // will be analyzed in due course, so skip doing so here + for (Net net : nets) { + if (net.isUsedNet()) { return; } + EDIFHierNet ehn = net.getLogicalHierNet(); + EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; + if (parentEhn != null && !parentEhn.equals(ehn)) { + Net parentNet = design.getNet(parentEhn.getHierarchicalNetName()); + if (parentNet != null) { + // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) + // to analyze its parent net) but that parent net also exist in the design and has been/ + // will be analyzed in due course, so skip doing so here + return; + } + } + createMissingSitePinInsts(design, net, siteInstToNetSiteWiresMap); } - createMissingSitePinInsts(design, net); } finally { - netsOutstanding.countDown(); + threadsOutstanding.countDown(); } }); } - netsOutstanding.await(); + threadsOutstanding.await(); } private static HashSet muxPins; diff --git a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java index 4e52d3398..3cf42fb07 100644 --- a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java +++ b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java @@ -39,12 +39,14 @@ import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.design.DesignTools; import com.xilinx.rapidwright.design.Net; +import com.xilinx.rapidwright.design.SiteInst; import com.xilinx.rapidwright.design.SitePinInst; import com.xilinx.rapidwright.device.ClockRegion; import com.xilinx.rapidwright.device.IntentCode; import com.xilinx.rapidwright.device.Node; import com.xilinx.rapidwright.device.PIP; import com.xilinx.rapidwright.device.Series; +import com.xilinx.rapidwright.edif.EDIFHierNet; import com.xilinx.rapidwright.router.UltraScaleClockRouting; import com.xilinx.rapidwright.tests.CodePerfTracker; import com.xilinx.rapidwright.timing.ClkRouteTiming; @@ -853,7 +855,14 @@ public static void main(String[] args) { // Reads in a design checkpoint and routes it String[] rwrouteArgs = Arrays.copyOfRange(args, 2, args.length); - Design routed = routeDesignWithUserDefinedArguments(Design.readCheckpoint(args[0]), rwrouteArgs); + Design d = Design.readCheckpoint(args[0]); + t.start("create parent net map"); + Map parentNetMap = d.getNetlist().getParentNetMap(); + t.stop(); +// t.stop().start("create site inst to net site wires map"); +// Map>> siteInstMapMap = DesignTools.getSiteInstToNetSiteWiresMap(d); +// t.stop(); + Design routed = routeDesignWithUserDefinedArguments(d, rwrouteArgs); // Writes out the routed design checkpoint routed.writeCheckpoint(routedDCPfileName,t); diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index c743d5725..98b798da2 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -227,10 +227,14 @@ public static void preprocess(Design design) { // Pre-processing of the design regarding physical net names pins CodePerfTracker t = new CodePerfTracker(RWRoute.class.getName()); - t.start("RWRoute Preprocess"); + + t.start("make phys net names consistent"); DesignTools.makePhysNetNamesConsistent(design); + t.stop().start("create possible pins to static nets"); DesignTools.createPossiblePinsToStaticNets(design); + t.stop().start("missing site pin insts"); DesignTools.createMissingSitePinInsts(design); + t.stop().start("update Versal xphy pins"); if (series == Series.Versal) { DesignTools.updateVersalXPHYPinsForDMC(design); } From 135b83217c229739077b8d3e60694f24a553e2c7 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Fri, 7 Nov 2025 14:25:07 -0800 Subject: [PATCH 04/17] Clean up parallelization Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 146 ++++++++++-------- .../rapidwright/rwroute/PartialRouter.java | 6 - .../xilinx/rapidwright/rwroute/RWRoute.java | 7 - 3 files changed, 85 insertions(+), 74 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index e85882964..b556dd693 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2385,10 +2385,19 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String public static Map>> getSiteInstToNetSiteWiresMap(Design design) { ConcurrentMap>> siteInstToNetSiteWiresMap = new ConcurrentHashMap<>(); - design.getCells().parallelStream().forEach((c) -> { - SiteInst inst = c.getSiteInst(); - siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); - }); + CountUpDownLatch activeJobs = new CountUpDownLatch(); + for (Cell c : design.getCells()) { + activeJobs.countUp(); + ParallelismTools.submit(() -> { + try { + SiteInst inst = c.getSiteInst(); + siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); + } finally { + activeJobs.countDown(); + } + }); + } + activeJobs.await(); return siteInstToNetSiteWiresMap; } @@ -2530,12 +2539,12 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne */ public static void createMissingSitePinInsts(Design design) { EDIFNetlist netlist = design.getNetlist(); - final CountUpDownLatch threadsOutstanding = new CountUpDownLatch(); Map>> siteInstToNetSiteWiresMap = DesignTools.getSiteInstToNetSiteWiresMap(design); + final CountUpDownLatch threadsOutstanding = new CountUpDownLatch(); int numNets = design.getNets().size(); - int numThreads = ParallelismTools.maxParallelism(); + int numJobs = ParallelismTools.maxParallelism() * 100; List designNets = new ArrayList<>(design.getNets()); - List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numThreads)); + List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numJobs)); for (List nets : partitionedNets) { threadsOutstanding.countUp(); ParallelismTools.submit(() -> { @@ -3394,65 +3403,80 @@ public static void printSiteInstInfo(SiteInst siteInst, PrintStream ps) { public static void makePhysNetNamesConsistent(Design design) { Map netParentMap = design.getNetlist().getParentNetMap(); EDIFNetlist netlist = design.getNetlist(); - new ArrayList<>(design.getNets()).parallelStream().forEach((net) -> { - Net parentPhysNet = null; - if (net.isStaticNet()) { - if (net.getType() == NetType.GND) { - parentPhysNet = design.getGndNet(); - } else if (net.getType() == NetType.VCC) { - parentPhysNet = design.getVccNet(); - } else { - throw new RuntimeException(); - } - if (parentPhysNet == net) { - return; - } - } else { - EDIFHierNet hierNet = netlist.getHierNetFromName(net.getName()); - if (hierNet == null) { - // Likely an encrypted cell - return; - } - EDIFHierNet parentHierNet = netParentMap.get(hierNet); - if (parentHierNet == null) { - // System.out.println("WARNING: Couldn't find parent net for '" + - // hierNet.getHierarchicalNetName() + "'"); - return; - } + CountUpDownLatch activeJobs = new CountUpDownLatch(); + int numNets = design.getNets().size(); + int numJobs = ParallelismTools.maxParallelism() * 100; + List designNets = new ArrayList<>(design.getNets()); + List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numJobs)); + for (List nets : partitionedNets) { + activeJobs.countUp(); + ParallelismTools.submit(() -> { + try { + for (Net net : nets) { + Net parentPhysNet = null; + if (net.isStaticNet()) { + if (net.getType() == NetType.GND) { + parentPhysNet = design.getGndNet(); + } else if (net.getType() == NetType.VCC) { + parentPhysNet = design.getVccNet(); + } else { + throw new RuntimeException(); + } + if (parentPhysNet == net) { + return; + } + } else { + EDIFHierNet hierNet = netlist.getHierNetFromName(net.getName()); + if (hierNet == null) { + // Likely an encrypted cell + return; + } + EDIFHierNet parentHierNet = netParentMap.get(hierNet); + if (parentHierNet == null) { + // System.out.println("WARNING: Couldn't find parent net for '" + + // hierNet.getHierarchicalNetName() + "'"); + return; + } - // Check to make sure net is not improperly categorized - EDIFNet srcNetAlias = parentHierNet.getNet(); - if (srcNetAlias.isGND()) { - parentPhysNet = design.getGndNet(); - } else if (srcNetAlias.isVCC()) { - parentPhysNet = design.getVccNet(); - } + // Check to make sure net is not improperly categorized + EDIFNet srcNetAlias = parentHierNet.getNet(); + if (srcNetAlias.isGND()) { + parentPhysNet = design.getGndNet(); + } else if (srcNetAlias.isVCC()) { + parentPhysNet = design.getVccNet(); + } - if (!hierNet.equals(parentHierNet)) { - String parentNetName = parentHierNet.getNet().getName(); - // Assume that a net named or is always a VCC or GND net - if (parentNetName.equals(EDIFTools.LOGICAL_VCC_NET_NAME)) { - parentPhysNet = design.getVccNet(); - } else if (parentNetName.equals(EDIFTools.LOGICAL_GND_NET_NAME)) { - parentPhysNet = design.getGndNet(); - } else { - parentPhysNet = design.getNet(parentHierNet.getHierarchicalNetName()); - } + if (!hierNet.equals(parentHierNet)) { + String parentNetName = parentHierNet.getNet().getName(); + // Assume that a net named or is always a VCC or GND net + if (parentNetName.equals(EDIFTools.LOGICAL_VCC_NET_NAME)) { + parentPhysNet = design.getVccNet(); + } else if (parentNetName.equals(EDIFTools.LOGICAL_GND_NET_NAME)) { + parentPhysNet = design.getGndNet(); + } else { + parentPhysNet = design.getNet(parentHierNet.getHierarchicalNetName()); + } - if (parentPhysNet != null) { - // Fall through - } else if (net.rename(parentHierNet.getHierarchicalNetName())) { - // Fall through - } else { - System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); + if (parentPhysNet != null) { + // Fall through + } else if (net.rename(parentHierNet.getHierarchicalNetName())) { + // Fall through + } else { + System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); + } + } + } + + if (parentPhysNet != null) { + design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); + } } + } finally { + activeJobs.countDown(); } - } - - if (parentPhysNet != null) { - design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); - } - }); + }); + } + activeJobs.await(); } public static void createPossiblePinsToStaticNets(Design design) { diff --git a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java index 3cf42fb07..1ae0e02ba 100644 --- a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java +++ b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java @@ -856,12 +856,6 @@ public static void main(String[] args) { // Reads in a design checkpoint and routes it String[] rwrouteArgs = Arrays.copyOfRange(args, 2, args.length); Design d = Design.readCheckpoint(args[0]); - t.start("create parent net map"); - Map parentNetMap = d.getNetlist().getParentNetMap(); - t.stop(); -// t.stop().start("create site inst to net site wires map"); -// Map>> siteInstMapMap = DesignTools.getSiteInstToNetSiteWiresMap(d); -// t.stop(); Design routed = routeDesignWithUserDefinedArguments(d, rwrouteArgs); // Writes out the routed design checkpoint diff --git a/src/com/xilinx/rapidwright/rwroute/RWRoute.java b/src/com/xilinx/rapidwright/rwroute/RWRoute.java index 98b798da2..9505f9b89 100644 --- a/src/com/xilinx/rapidwright/rwroute/RWRoute.java +++ b/src/com/xilinx/rapidwright/rwroute/RWRoute.java @@ -226,19 +226,12 @@ public static void preprocess(Design design) { } // Pre-processing of the design regarding physical net names pins - CodePerfTracker t = new CodePerfTracker(RWRoute.class.getName()); - - t.start("make phys net names consistent"); DesignTools.makePhysNetNamesConsistent(design); - t.stop().start("create possible pins to static nets"); DesignTools.createPossiblePinsToStaticNets(design); - t.stop().start("missing site pin insts"); DesignTools.createMissingSitePinInsts(design); - t.stop().start("update Versal xphy pins"); if (series == Series.Versal) { DesignTools.updateVersalXPHYPinsForDMC(design); } - t.stop(); } protected void preprocess() { From 02242954f5841af910e16504cf0758bf32cd103b Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Fri, 7 Nov 2025 17:01:44 -0800 Subject: [PATCH 05/17] Switch to using futures to prevent accidentally hiding exceptions thrown in threads Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 186 +++++++++--------- .../rapidwright/rwroute/PartialRouter.java | 5 +- 2 files changed, 96 insertions(+), 95 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index b556dd693..518b0c1d8 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -52,11 +52,12 @@ import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.stream.Collectors; +import org.python.google.common.collect.Lists; + import com.xilinx.rapidwright.design.blocks.PBlock; import com.xilinx.rapidwright.design.blocks.UtilizationType; import com.xilinx.rapidwright.design.tools.LUTTools; @@ -100,7 +101,6 @@ import com.xilinx.rapidwright.util.ParallelismTools; import com.xilinx.rapidwright.util.StringTools; import com.xilinx.rapidwright.util.Utils; -import org.python.google.common.collect.Lists; /** * A collection of methods to operate on {@link Design} objects. @@ -2383,21 +2383,22 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String return (!sitePins.isEmpty()) ? sitePins.get(0) : null; } + @SuppressWarnings("unchecked") public static Map>> getSiteInstToNetSiteWiresMap(Design design) { - ConcurrentMap>> siteInstToNetSiteWiresMap = new ConcurrentHashMap<>(); - CountUpDownLatch activeJobs = new CountUpDownLatch(); + Map>> siteInstToNetSiteWiresMap = new ConcurrentHashMap<>(); + Deque> futures = new ArrayDeque<>(); for (Cell c : design.getCells()) { - activeJobs.countUp(); - ParallelismTools.submit(() -> { - try { - SiteInst inst = c.getSiteInst(); - siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); - } finally { - activeJobs.countDown(); - } + Future f = ParallelismTools.submit(() -> { + SiteInst inst = c.getSiteInst(); + siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); }); + if (f != null) { + futures.add((Future) f); + } + } + while (!futures.isEmpty()) { + ParallelismTools.joinFirst(futures); } - activeJobs.await(); return siteInstToNetSiteWiresMap; } @@ -2537,41 +2538,43 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne * See also {@link #createMissingSitePinInsts(Design, Net)}. * @param design The current design */ + @SuppressWarnings("unchecked") public static void createMissingSitePinInsts(Design design) { EDIFNetlist netlist = design.getNetlist(); Map>> siteInstToNetSiteWiresMap = DesignTools.getSiteInstToNetSiteWiresMap(design); - final CountUpDownLatch threadsOutstanding = new CountUpDownLatch(); int numNets = design.getNets().size(); int numJobs = ParallelismTools.maxParallelism() * 100; List designNets = new ArrayList<>(design.getNets()); List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numJobs)); + Deque> futures = new ArrayDeque<>(); for (List nets : partitionedNets) { - threadsOutstanding.countUp(); - ParallelismTools.submit(() -> { - try { - for (Net net : nets) { - if (net.isUsedNet()) { + Future f = ParallelismTools.submit(() -> { + for (Net net : nets) { + if (net.isUsedNet()) { + return; + } + EDIFHierNet ehn = net.getLogicalHierNet(); + EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; + if (parentEhn != null && !parentEhn.equals(ehn)) { + Net parentNet = design.getNet(parentEhn.getHierarchicalNetName()); + if (parentNet != null) { + // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) + // to analyze its parent net) but that parent net also exist in the design and has been/ + // will be analyzed in due course, so skip doing so here return; } - EDIFHierNet ehn = net.getLogicalHierNet(); - EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; - if (parentEhn != null && !parentEhn.equals(ehn)) { - Net parentNet = design.getNet(parentEhn.getHierarchicalNetName()); - if (parentNet != null) { - // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) - // to analyze its parent net) but that parent net also exist in the design and has been/ - // will be analyzed in due course, so skip doing so here - return; - } - } - createMissingSitePinInsts(design, net, siteInstToNetSiteWiresMap); } - } finally { - threadsOutstanding.countDown(); + createMissingSitePinInsts(design, net, siteInstToNetSiteWiresMap); } }); + if (f != null) { + futures.add((Future) f); + } + } + + while (!futures.isEmpty()) { + ParallelismTools.joinFirst(futures); } - threadsOutstanding.await(); } private static HashSet muxPins; @@ -3400,83 +3403,84 @@ public static void printSiteInstInfo(SiteInst siteInst, PrintStream ps) { * non-parent Net-s. * @param design Design object to be modified in-place. */ + @SuppressWarnings("unchecked") public static void makePhysNetNamesConsistent(Design design) { Map netParentMap = design.getNetlist().getParentNetMap(); EDIFNetlist netlist = design.getNetlist(); - CountUpDownLatch activeJobs = new CountUpDownLatch(); int numNets = design.getNets().size(); int numJobs = ParallelismTools.maxParallelism() * 100; List designNets = new ArrayList<>(design.getNets()); List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numJobs)); + Deque> futures = new ArrayDeque<>(); for (List nets : partitionedNets) { - activeJobs.countUp(); - ParallelismTools.submit(() -> { - try { - for (Net net : nets) { - Net parentPhysNet = null; - if (net.isStaticNet()) { - if (net.getType() == NetType.GND) { - parentPhysNet = design.getGndNet(); - } else if (net.getType() == NetType.VCC) { - parentPhysNet = design.getVccNet(); - } else { - throw new RuntimeException(); - } - if (parentPhysNet == net) { - return; - } + Future f = ParallelismTools.submit(() -> { + for (Net net : nets) { + Net parentPhysNet = null; + if (net.isStaticNet()) { + if (net.getType() == NetType.GND) { + parentPhysNet = design.getGndNet(); + } else if (net.getType() == NetType.VCC) { + parentPhysNet = design.getVccNet(); } else { - EDIFHierNet hierNet = netlist.getHierNetFromName(net.getName()); - if (hierNet == null) { - // Likely an encrypted cell - return; - } - EDIFHierNet parentHierNet = netParentMap.get(hierNet); - if (parentHierNet == null) { - // System.out.println("WARNING: Couldn't find parent net for '" + - // hierNet.getHierarchicalNetName() + "'"); - return; - } + throw new RuntimeException(); + } + if (parentPhysNet == net) { + return; + } + } else { + EDIFHierNet hierNet = netlist.getHierNetFromName(net.getName()); + if (hierNet == null) { + // Likely an encrypted cell + return; + } + EDIFHierNet parentHierNet = netParentMap.get(hierNet); + if (parentHierNet == null) { + // System.out.println("WARNING: Couldn't find parent net for '" + + // hierNet.getHierarchicalNetName() + "'"); + return; + } - // Check to make sure net is not improperly categorized - EDIFNet srcNetAlias = parentHierNet.getNet(); - if (srcNetAlias.isGND()) { - parentPhysNet = design.getGndNet(); - } else if (srcNetAlias.isVCC()) { + // Check to make sure net is not improperly categorized + EDIFNet srcNetAlias = parentHierNet.getNet(); + if (srcNetAlias.isGND()) { + parentPhysNet = design.getGndNet(); + } else if (srcNetAlias.isVCC()) { + parentPhysNet = design.getVccNet(); + } + + if (!hierNet.equals(parentHierNet)) { + String parentNetName = parentHierNet.getNet().getName(); + // Assume that a net named or is always a VCC or GND net + if (parentNetName.equals(EDIFTools.LOGICAL_VCC_NET_NAME)) { parentPhysNet = design.getVccNet(); + } else if (parentNetName.equals(EDIFTools.LOGICAL_GND_NET_NAME)) { + parentPhysNet = design.getGndNet(); + } else { + parentPhysNet = design.getNet(parentHierNet.getHierarchicalNetName()); } - if (!hierNet.equals(parentHierNet)) { - String parentNetName = parentHierNet.getNet().getName(); - // Assume that a net named or is always a VCC or GND net - if (parentNetName.equals(EDIFTools.LOGICAL_VCC_NET_NAME)) { - parentPhysNet = design.getVccNet(); - } else if (parentNetName.equals(EDIFTools.LOGICAL_GND_NET_NAME)) { - parentPhysNet = design.getGndNet(); - } else { - parentPhysNet = design.getNet(parentHierNet.getHierarchicalNetName()); - } - - if (parentPhysNet != null) { - // Fall through - } else if (net.rename(parentHierNet.getHierarchicalNetName())) { - // Fall through - } else { - System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); - } + if (parentPhysNet != null) { + // Fall through + } else if (net.rename(parentHierNet.getHierarchicalNetName())) { + // Fall through + } else { + System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); } } + } - if (parentPhysNet != null) { - design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); - } + if (parentPhysNet != null) { + design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); } - } finally { - activeJobs.countDown(); } }); + if (f != null) { + futures.add((Future) f); + } + } + while (!futures.isEmpty()) { + ParallelismTools.joinFirst(futures); } - activeJobs.await(); } public static void createPossiblePinsToStaticNets(Design design) { diff --git a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java index 1ae0e02ba..4e52d3398 100644 --- a/src/com/xilinx/rapidwright/rwroute/PartialRouter.java +++ b/src/com/xilinx/rapidwright/rwroute/PartialRouter.java @@ -39,14 +39,12 @@ import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.design.DesignTools; import com.xilinx.rapidwright.design.Net; -import com.xilinx.rapidwright.design.SiteInst; import com.xilinx.rapidwright.design.SitePinInst; import com.xilinx.rapidwright.device.ClockRegion; import com.xilinx.rapidwright.device.IntentCode; import com.xilinx.rapidwright.device.Node; import com.xilinx.rapidwright.device.PIP; import com.xilinx.rapidwright.device.Series; -import com.xilinx.rapidwright.edif.EDIFHierNet; import com.xilinx.rapidwright.router.UltraScaleClockRouting; import com.xilinx.rapidwright.tests.CodePerfTracker; import com.xilinx.rapidwright.timing.ClkRouteTiming; @@ -855,8 +853,7 @@ public static void main(String[] args) { // Reads in a design checkpoint and routes it String[] rwrouteArgs = Arrays.copyOfRange(args, 2, args.length); - Design d = Design.readCheckpoint(args[0]); - Design routed = routeDesignWithUserDefinedArguments(d, rwrouteArgs); + Design routed = routeDesignWithUserDefinedArguments(Design.readCheckpoint(args[0]), rwrouteArgs); // Writes out the routed design checkpoint routed.writeCheckpoint(routedDCPfileName,t); From f921a02afd23c299901f06ad89d00624e52b42c4 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Mon, 10 Nov 2025 08:54:25 -0800 Subject: [PATCH 06/17] Fix NPE Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 518b0c1d8..596c39358 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2440,7 +2440,9 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne Net vccNet = cell.getSiteInst().getDesign().getVccNet(); List vccSiteWires = netSiteWiresMap != null ? netSiteWiresMap.get(vccNet) : inst.getSiteWiresFromNet(vccNet); - siteWires.addAll(vccSiteWires); + if (vccSiteWires != null) { + siteWires.addAll(vccSiteWires); + } } Queue queue = new LinkedList<>(); queue.add(cell.getBEL().getPin(belPinName)); From 66b31e4aedc862669e7f01235b13dabd743dc7c5 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Mon, 10 Nov 2025 09:35:35 -0800 Subject: [PATCH 07/17] Fix concurrent modification issues Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 596c39358..0258a6fa3 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2293,7 +2293,10 @@ public static List createMissingSitePinInsts(Design design, Net net BEL bel = c.getBEL(); if (bel == null) continue; String logicalPinName = p.getPortInst().getName(); - Set physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); + Set physPinMappings; + synchronized (c) { + physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); + } // BRAMs can have two (or more) physical pin mappings for a logical pin if (physPinMappings != null) { SiteInst si = c.getSiteInst(); @@ -3472,7 +3475,9 @@ public static void makePhysNetNamesConsistent(Design design) { } if (parentPhysNet != null) { - design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); + synchronized (design.getNet(parentPhysNet.getName())) { + design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); + } } } }); From 48e7433e621e54a472b98e238c69427e13aa1b18 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Mon, 10 Nov 2025 09:55:01 -0800 Subject: [PATCH 08/17] Fix another concurrent modification issue Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 0258a6fa3..f82165163 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3475,7 +3475,7 @@ public static void makePhysNetNamesConsistent(Design design) { } if (parentPhysNet != null) { - synchronized (design.getNet(parentPhysNet.getName())) { + synchronized (design) { design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); } } From c3bb7ac5b312ae9b497d238a250e779cca05a095 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Mon, 10 Nov 2025 14:24:32 -0800 Subject: [PATCH 09/17] Reduce synchronization and add caching on cells and pins Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 45 ++++++++++++++----- .../xilinx/rapidwright/edif/EDIFNetlist.java | 2 +- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index f82165163..83dbc7e1b 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2287,15 +2287,25 @@ public static List createMissingSitePinInsts(Design design, Net net EDIFNetlist netlist = design.getNetlist(); EDIFHierNet parentEhn = null; + Map cellCache = new HashMap<>(); + Map> physPinMappingsCache = new HashMap<>(); for (EDIFHierPortInst p : physPins) { - Cell c = design.getCell(p.getFullHierarchicalInstName()); + Cell c = cellCache.containsKey(p) ? cellCache.get(p) : design.getCell(p.getFullHierarchicalInstName()); + if (!cellCache.containsKey(p)) { + cellCache.put(p, c); + } if (c == null) continue; BEL bel = c.getBEL(); if (bel == null) continue; String logicalPinName = p.getPortInst().getName(); Set physPinMappings; - synchronized (c) { - physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); + if (physPinMappingsCache.containsKey(c)) { + physPinMappings = physPinMappingsCache.get(c); + } else { + synchronized (design.getCell(c.getName())) { + physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); + } + physPinMappingsCache.put(c, physPinMappings); } // BRAMs can have two (or more) physical pin mappings for a logical pin if (physPinMappings != null) { @@ -2310,6 +2320,7 @@ public static List createMissingSitePinInsts(Design design, Net net synchronized (si) { si.routeIntraSiteNet(net, belPin, belPin); } + siteInstToNetSiteWiresMap.get(si).put(net, si.getSiteWiresFromNet(net)); } else { continue; } @@ -2340,7 +2351,12 @@ public static List createMissingSitePinInsts(Design design, Net net } newPin = net.createPin(sitePinName, si); } - if (newPin != null) newPins.add(newPin); + if (newPin != null) { + newPins.add(newPin); + siteInstToNetSiteWiresMap.get(si) + .computeIfAbsent(net, k -> new ArrayList<>()).add(newPin.getSiteWireName()); + + } } } } @@ -2390,10 +2406,16 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String public static Map>> getSiteInstToNetSiteWiresMap(Design design) { Map>> siteInstToNetSiteWiresMap = new ConcurrentHashMap<>(); Deque> futures = new ArrayDeque<>(); - for (Cell c : design.getCells()) { + int numCells = design.getCells().size(); + int numJobs = ParallelismTools.maxParallelism() * 100; + List designCells = new ArrayList<>(design.getCells()); + List> partitionedCells = Lists.partition(designCells, (int) Math.ceil((double) numCells / numJobs)); + for (List cells : partitionedCells) { Future f = ParallelismTools.submit(() -> { - SiteInst inst = c.getSiteInst(); - siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); + for (Cell c : cells) { + SiteInst inst = c.getSiteInst(); + siteInstToNetSiteWiresMap.put(inst, inst.getNetToSiteWiresMap()); + } }); if (f != null) { futures.add((Future) f); @@ -2438,6 +2460,9 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne } List sitePins = new ArrayList<>(); List siteWires = netSiteWiresMap != null ? netSiteWiresMap.get(net) : inst.getSiteWiresFromNet(net); + if (siteWires == null) { + throw new RuntimeException("Failed to find siteWires for net: " + net); + } if (net.isGNDNet()) { // Since GND sitewires may be inverted for easier routing, also accept VCC sitewires Net vccNet = cell.getSiteInst().getDesign().getVccNet(); @@ -3433,7 +3458,7 @@ public static void makePhysNetNamesConsistent(Design design) { return; } } else { - EDIFHierNet hierNet = netlist.getHierNetFromName(net.getName()); + EDIFHierNet hierNet = net.getLogicalHierNet(); if (hierNet == null) { // Likely an encrypted cell return; @@ -3475,9 +3500,7 @@ public static void makePhysNetNamesConsistent(Design design) { } if (parentPhysNet != null) { - synchronized (design) { - design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); - } + design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); } } }); diff --git a/src/com/xilinx/rapidwright/edif/EDIFNetlist.java b/src/com/xilinx/rapidwright/edif/EDIFNetlist.java index b8a1ba20b..b11267969 100644 --- a/src/com/xilinx/rapidwright/edif/EDIFNetlist.java +++ b/src/com/xilinx/rapidwright/edif/EDIFNetlist.java @@ -1693,7 +1693,7 @@ public List getPhysicalPins(Net net) { case VCC: return getPhysicalVccPins(); default: - final EDIFHierNet hierNet = getHierNetFromName(net.getName()); + final EDIFHierNet hierNet = net.getLogicalHierNet(); return getPhysicalNetPinMap().get(hierNet); } } From a8572cba158bfa627d1482f9921ce67992fd26ad Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Mon, 10 Nov 2025 14:55:40 -0800 Subject: [PATCH 10/17] Address comments Signed-off-by: Andrew Butt --- .../rapidwright/design/DesignTools.java | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 83dbc7e1b..8d6c81a37 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2205,8 +2205,9 @@ public static boolean placeCell(Cell c, Design design) { /** * Creates any and all missing SitePinInsts for this net. This is common as a placed * DCP will not have SitePinInsts annotated and this information is generally necessary - * for routing to take place. + * for routing to take place. See also {@link #createMissingSitePinInsts(Design, Net, Map)}. * @param design The current design of this net. + * @param net The net to create missing site pin insts for. * @return The list of pins that were created or an empty list if none were created. */ public static List createMissingSitePinInsts(Design design, Net net) { @@ -2218,6 +2219,9 @@ public static List createMissingSitePinInsts(Design design, Net net * DCP will not have SitePinInsts annotated and this information is generally necessary * for routing to take place. * @param design The current design of this net. + * @param net The net to create missing site pin insts for. + * @param siteInstToNetSiteWiresMap An optional two-level map from siteInst -> net -> siteWires. + * See {@link #getSiteInstToNetSiteWiresMap(Design)} for more information. * @return The list of pins that were created or an empty list if none were created. */ public static List createMissingSitePinInsts(Design design, Net net, @@ -2320,7 +2324,9 @@ public static List createMissingSitePinInsts(Design design, Net net synchronized (si) { si.routeIntraSiteNet(net, belPin, belPin); } - siteInstToNetSiteWiresMap.get(si).put(net, si.getSiteWiresFromNet(net)); + if (siteInstToNetSiteWiresMap != null) { + siteInstToNetSiteWiresMap.get(si).put(net, si.getSiteWiresFromNet(net)); + } } else { continue; } @@ -2353,8 +2359,10 @@ public static List createMissingSitePinInsts(Design design, Net net } if (newPin != null) { newPins.add(newPin); - siteInstToNetSiteWiresMap.get(si) - .computeIfAbsent(net, k -> new ArrayList<>()).add(newPin.getSiteWireName()); + if (siteInstToNetSiteWiresMap != null) { + siteInstToNetSiteWiresMap.get(si) + .computeIfAbsent(net, k -> new ArrayList<>()).add(newPin.getSiteWireName()); + } } } @@ -2379,6 +2387,7 @@ public static String getRoutedSitePin(Cell cell, Net net, String logicalPinName) /** * 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. + * See also {@link #getRoutedSitePinFromPhysicalPin(Cell, Net, String, Map)}. * @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 @@ -2394,6 +2403,8 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String * @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 + * @param siteInstToNetSiteWiresMap An optional two-level map from siteInst -> net -> siteWires. + * See {@link #getSiteInstToNetSiteWiresMap(Design)} for more information. * @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, @@ -2402,11 +2413,20 @@ public static String getRoutedSitePinFromPhysicalPin(Cell cell, Net net, String return (!sitePins.isEmpty()) ? sitePins.get(0) : null; } + /** + * Creates a two-level map from SiteInst -> Net -> list of SiteWires. Calculating this map ahead of time ensures + * that {@link #createMissingSitePinInsts(Design, Net, Map)} does not need to iterate over the SiteInst ctags + * for each net. Instead, this method iterates over the ctags once per SiteInst and stores the resulting + * Net -> list of SiteWires map. + * @param design The design to create a SiteInst -> Net -> list of SiteWires map for. + * @return + */ @SuppressWarnings("unchecked") public static Map>> getSiteInstToNetSiteWiresMap(Design design) { Map>> siteInstToNetSiteWiresMap = new ConcurrentHashMap<>(); Deque> futures = new ArrayDeque<>(); int numCells = design.getCells().size(); + // Experimentally best performing number of jobs int numJobs = ParallelismTools.maxParallelism() * 100; List designCells = new ArrayList<>(design.getCells()); List> partitionedCells = Lists.partition(designCells, (int) Math.ceil((double) numCells / numJobs)); @@ -2446,10 +2466,13 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne * @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 + * @param siteInstToNetSiteWiresMap An optional two-level map from siteInst -> net -> siteWires. + * See {@link #getSiteInstToNetSiteWiresMap(Design)} for more information. * @return A list of site pin names on the cell's site to which the pin is routed. - * @since 2023.1.2 + * @since 2025.2.0 */ - public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net net, String belPinName, Map>> siteInstToNetSiteWiresMap) { + public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net net, String belPinName, Map>> siteInstToNetSiteWiresMap) { if (belPinName == null) { return Collections.emptyList(); } @@ -2564,8 +2587,8 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne } /** - * Creates all missing SitePinInsts in a design, except GLOBAL_USEDNET. - * See also {@link #createMissingSitePinInsts(Design, Net)}. + * Creates all missing SitePinInsts in a design, except GLOBAL_USEDNET. This method is multi-threaded based on the + * setting in {@link ParallelismTools}. See also {@link #createMissingSitePinInsts(Design, Net)}. * @param design The current design */ @SuppressWarnings("unchecked") @@ -2573,6 +2596,7 @@ public static void createMissingSitePinInsts(Design design) { EDIFNetlist netlist = design.getNetlist(); Map>> siteInstToNetSiteWiresMap = DesignTools.getSiteInstToNetSiteWiresMap(design); int numNets = design.getNets().size(); + // Experimentally best performing number of jobs int numJobs = ParallelismTools.maxParallelism() * 100; List designNets = new ArrayList<>(design.getNets()); List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numJobs)); @@ -3436,8 +3460,8 @@ public static void printSiteInstInfo(SiteInst siteInst, PrintStream ps) { @SuppressWarnings("unchecked") public static void makePhysNetNamesConsistent(Design design) { Map netParentMap = design.getNetlist().getParentNetMap(); - EDIFNetlist netlist = design.getNetlist(); int numNets = design.getNets().size(); + // Experimentally best performing number of jobs int numJobs = ParallelismTools.maxParallelism() * 100; List designNets = new ArrayList<>(design.getNets()); List> partitionedNets = Lists.partition(designNets, (int) Math.ceil((double) numNets / numJobs)); From 16b9b596645c2fdf615a593e777621400d2e5ea9 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 08:41:59 -0800 Subject: [PATCH 11/17] Add back sync Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 8d6c81a37..c1d06b149 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3524,7 +3524,9 @@ public static void makePhysNetNamesConsistent(Design design) { } if (parentPhysNet != null) { - design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); + synchronized (design) { + design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); + } } } }); From 7e21dfeaf04343748e81c63dc5eb6f00b1c2f1c1 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 09:32:17 -0800 Subject: [PATCH 12/17] Trying to fix failing test case Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index c1d06b149..df8d8133b 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2282,6 +2282,10 @@ public static List createMissingSitePinInsts(Design design, Net net currPin = net.createPin(pin.getName(), siteInst); newPins.add(currPin); + if (siteInstToNetSiteWiresMap != null) { + siteInstToNetSiteWiresMap.get(siteInst) + .computeIfAbsent(net, k -> new ArrayList<>()).add(currPin.getSiteWireName()); + } } } } @@ -2309,7 +2313,7 @@ public static List createMissingSitePinInsts(Design design, Net net synchronized (design.getCell(c.getName())) { physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); } - physPinMappingsCache.put(c, physPinMappings); +// physPinMappingsCache.put(c, physPinMappings); } // BRAMs can have two (or more) physical pin mappings for a logical pin if (physPinMappings != null) { @@ -2618,7 +2622,7 @@ public static void createMissingSitePinInsts(Design design) { return; } } - createMissingSitePinInsts(design, net, siteInstToNetSiteWiresMap); + createMissingSitePinInsts(design, net, null); } }); if (f != null) { From 9525fca4302977b941456065206d5b23b2c3f027 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 09:55:27 -0800 Subject: [PATCH 13/17] Fix accidentally skipping some nets Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index df8d8133b..cbc852bfb 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2609,7 +2609,7 @@ public static void createMissingSitePinInsts(Design design) { Future f = ParallelismTools.submit(() -> { for (Net net : nets) { if (net.isUsedNet()) { - return; + continue; } EDIFHierNet ehn = net.getLogicalHierNet(); EDIFHierNet parentEhn = (ehn != null) ? netlist.getParentNet(ehn) : null; @@ -2619,10 +2619,10 @@ public static void createMissingSitePinInsts(Design design) { // 'net' is not a parent net (which normally causes createMissingSitePinInsts(Design, Net) // to analyze its parent net) but that parent net also exist in the design and has been/ // will be analyzed in due course, so skip doing so here - return; + continue; } } - createMissingSitePinInsts(design, net, null); + createMissingSitePinInsts(design, net, siteInstToNetSiteWiresMap); } }); if (f != null) { From 46d9c52b363478e46b56cd55c1dcf00fa7f31eb9 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 10:20:55 -0800 Subject: [PATCH 14/17] Cleanup Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index cbc852bfb..72d03e92c 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -2296,7 +2296,6 @@ public static List createMissingSitePinInsts(Design design, Net net EDIFNetlist netlist = design.getNetlist(); EDIFHierNet parentEhn = null; Map cellCache = new HashMap<>(); - Map> physPinMappingsCache = new HashMap<>(); for (EDIFHierPortInst p : physPins) { Cell c = cellCache.containsKey(p) ? cellCache.get(p) : design.getCell(p.getFullHierarchicalInstName()); if (!cellCache.containsKey(p)) { @@ -2307,13 +2306,8 @@ public static List createMissingSitePinInsts(Design design, Net net if (bel == null) continue; String logicalPinName = p.getPortInst().getName(); Set physPinMappings; - if (physPinMappingsCache.containsKey(c)) { - physPinMappings = physPinMappingsCache.get(c); - } else { - synchronized (design.getCell(c.getName())) { - physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); - } -// physPinMappingsCache.put(c, physPinMappings); + synchronized (design.getCell(c.getName())) { + physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); } // BRAMs can have two (or more) physical pin mappings for a logical pin if (physPinMappings != null) { From 05281e482c5c927d9093df2b0a67fece309d69ed Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 12:31:46 -0800 Subject: [PATCH 15/17] Add synchronization for rare case Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 72d03e92c..4da839e25 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3511,12 +3511,14 @@ public static void makePhysNetNamesConsistent(Design design) { parentPhysNet = design.getNet(parentHierNet.getHierarchicalNetName()); } - if (parentPhysNet != null) { - // Fall through - } else if (net.rename(parentHierNet.getHierarchicalNetName())) { - // Fall through - } else { - System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); + synchronized (design) { + if (parentPhysNet != null) { + // Fall through + } else if (net.rename(parentHierNet.getHierarchicalNetName())) { + // Fall through + } else { + System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); + } } } } From 7630d739870f9d9428b39364efdf2876796d6615 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 12:33:34 -0800 Subject: [PATCH 16/17] Remove fall-through if statements Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 4da839e25..323c6b09e 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3511,13 +3511,11 @@ public static void makePhysNetNamesConsistent(Design design) { parentPhysNet = design.getNet(parentHierNet.getHierarchicalNetName()); } - synchronized (design) { - if (parentPhysNet != null) { - // Fall through - } else if (net.rename(parentHierNet.getHierarchicalNetName())) { - // Fall through - } else { - System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); + if (parentPhysNet == null) { + synchronized (design) { + if (!net.rename(parentHierNet.getHierarchicalNetName())) { + System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); + } } } } From 2c1ab135d3143a36915ff14907884a63b9c69a18 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Tue, 11 Nov 2025 13:55:43 -0800 Subject: [PATCH 17/17] Fix additional early returns Signed-off-by: Andrew Butt --- src/com/xilinx/rapidwright/design/DesignTools.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 323c6b09e..2a37ac00f 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3477,19 +3477,19 @@ public static void makePhysNetNamesConsistent(Design design) { throw new RuntimeException(); } if (parentPhysNet == net) { - return; + continue; } } else { EDIFHierNet hierNet = net.getLogicalHierNet(); if (hierNet == null) { // Likely an encrypted cell - return; + continue; } EDIFHierNet parentHierNet = netParentMap.get(hierNet); if (parentHierNet == null) { // System.out.println("WARNING: Couldn't find parent net for '" + // hierNet.getHierarchicalNetName() + "'"); - return; + continue; } // Check to make sure net is not improperly categorized