From 22c48859574431800bc2528db79e52b316de1d61 Mon Sep 17 00:00:00 2001 From: Hayden Cook Date: Fri, 16 Jun 2023 09:00:08 -0700 Subject: [PATCH 01/20] Created parameterizable counter with an adder as a submodule Signed-off-by: Hayden Cook --- .../examples/ParamCounterModule.java | 257 ++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 src/com/xilinx/rapidwright/examples/ParamCounterModule.java diff --git a/src/com/xilinx/rapidwright/examples/ParamCounterModule.java b/src/com/xilinx/rapidwright/examples/ParamCounterModule.java new file mode 100644 index 000000000..7957a60d6 --- /dev/null +++ b/src/com/xilinx/rapidwright/examples/ParamCounterModule.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2019-2022, Xilinx, Inc. + * Copyright (c) 2022, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Author: Chris Lavin, Xilinx Research Labs. + * + * 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.examples; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import com.xilinx.rapidwright.design.ConstraintGroup; +import com.xilinx.rapidwright.design.Design; +import com.xilinx.rapidwright.design.Module; +import com.xilinx.rapidwright.design.ModuleInst; +import com.xilinx.rapidwright.design.Net; +import com.xilinx.rapidwright.design.NetType; +import com.xilinx.rapidwright.design.Port; +import com.xilinx.rapidwright.design.PortType; +import com.xilinx.rapidwright.device.Device; +import com.xilinx.rapidwright.device.Part; +import com.xilinx.rapidwright.device.PartNameTools; +import com.xilinx.rapidwright.device.Site; +import com.xilinx.rapidwright.edif.EDIFCell; +import com.xilinx.rapidwright.edif.EDIFCellInst; +import com.xilinx.rapidwright.edif.EDIFDirection; +import com.xilinx.rapidwright.edif.EDIFNet; +import com.xilinx.rapidwright.edif.EDIFPort; +import com.xilinx.rapidwright.edif.EDIFPortInst; +import com.xilinx.rapidwright.edif.EDIFTools; +import com.xilinx.rapidwright.rwroute.RWRoute; +import com.xilinx.rapidwright.tests.CodePerfTracker; +import com.xilinx.rapidwright.util.MessageGenerator; +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +import static com.xilinx.rapidwright.examples.ArithmeticGenerator.INPUT_A_NAME; +import static com.xilinx.rapidwright.examples.ArithmeticGenerator.INPUT_B_NAME; +import static com.xilinx.rapidwright.examples.ArithmeticGenerator.RESULT_NAME; + +/** + * A class that implements a counter using the + */ +public class ParamCounterModule { + + protected static final String PART_OPT = "p"; + protected static final String DESIGN_NAME_OPT = "d"; + protected static final String ADDER_NAME_OPT = "a"; + protected static final String OUT_DCP_OPT = "o"; + protected static final String CLK_NAME_OPT = "c"; + protected static final String CLK_CONSTRAINT_OPT = "x"; + protected static final String WIDTH_OPT = "w"; + protected static final String VERBOSE_OPT = "v"; + protected static final String HELP_OPT = "h"; + private static final String SLICE_SITES_OPT = "s"; + private static final String COUNT_DOWN_OPT = "m"; + private static final String STEP_OPT = "t"; + private static final String INIT_OPT = "i"; + + private static OptionParser createOptionParser() { + // Defaults + String partName = "xczu3eg-sbva484-1-i"; + String designName = "counter"; + String adderName = "adder"; + String outputDCPFileName = System.getProperty("user.dir") + File.separator + designName +".dcp"; + String clkName = "clk"; + double clkPeriodConstraint = 1.291; // 775 MHz + int width = 32; + String sliceSite = "SLICE_X3Y3"; + boolean verbose = true; + boolean countDown = false; + long initValue = 0; + long step = 1; + + OptionParser p = new OptionParser() {{ + accepts(PART_OPT).withOptionalArg().defaultsTo(partName).describedAs("UltraScale+ Part Name"); + accepts(DESIGN_NAME_OPT).withOptionalArg().defaultsTo(designName).describedAs("Design Name"); + accepts(DESIGN_NAME_OPT).withOptionalArg().defaultsTo(designName).describedAs("Name of counter design"); + accepts(ADDER_NAME_OPT).withOptionalArg().defaultsTo(adderName).describedAs("Name of adder submodule"); + accepts(OUT_DCP_OPT).withOptionalArg().defaultsTo(outputDCPFileName).describedAs("Output DCP File Name"); + accepts(CLK_NAME_OPT).withOptionalArg().defaultsTo(clkName).describedAs("Clk net name"); + accepts(CLK_CONSTRAINT_OPT).withOptionalArg().ofType(Double.class).defaultsTo(clkPeriodConstraint).describedAs("Clk period constraint (ns)"); + accepts(WIDTH_OPT).withOptionalArg().ofType(Integer.class).defaultsTo(width).describedAs("Operand width"); + accepts(SLICE_SITES_OPT).withOptionalArg().defaultsTo(sliceSite).describedAs("Lower left slice to be used for adder/subtracter"); + accepts(COUNT_DOWN_OPT).withOptionalArg().ofType(Boolean.class).defaultsTo(countDown).describedAs("Counts down instead of up"); + accepts(STEP_OPT).withOptionalArg().ofType(Long.class).defaultsTo(step).describedAs("Counts down instead of up"); + accepts(INIT_OPT).withOptionalArg().ofType(Long.class).defaultsTo(initValue).describedAs("Counts down instead of up"); + accepts(VERBOSE_OPT).withOptionalArg().ofType(Boolean.class).defaultsTo(verbose).describedAs("Print verbose output"); + acceptsAll( Arrays.asList(HELP_OPT, "?"), "Print Help" ).forHelp(); + }}; + + return p; + } + + private static void printHelp(OptionParser p) { + MessageGenerator.printHeader("Adder/Subtractor Generator"); + System.out.println("This RapidWright program creates a placed and routed DCP for UltraScale+ devices that contains \n" + + "imported into UltraScale+ designs to perform addition or subtraction. See \n" + + "RapidWright documentation for more information.\n"); + try { + p.accepts(OUT_DCP_OPT).withOptionalArg().defaultsTo("slr_crosser.dcp").describedAs("Output DCP File Name"); + p.printHelpOn(System.out); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + // Extract program options + OptionParser p = createOptionParser(); + OptionSet opts = p.parse(args); + boolean verbose = (boolean) opts.valueOf(VERBOSE_OPT); + if (opts.has(HELP_OPT)) { + printHelp(p); + return; + } + + CodePerfTracker t = verbose ? new CodePerfTracker(AddSubGenerator.class.getSimpleName(),true).start("Init") : null; + + String partName = (String) opts.valueOf(PART_OPT); + String designName = (String) opts.valueOf(DESIGN_NAME_OPT); + String adderName = (String) opts.valueOf(ADDER_NAME_OPT); + String outputDCPFileName = (String) opts.valueOf(OUT_DCP_OPT); + String clkName = (String) opts.valueOf(CLK_NAME_OPT); + double clkPeriodConstraint = (double) opts.valueOf(CLK_CONSTRAINT_OPT); + int width = (int) opts.valueOf(WIDTH_OPT); + String sliceName = (String) opts.valueOf(SLICE_SITES_OPT); + boolean countDown = (boolean) opts.valueOf(COUNT_DOWN_OPT); + long step = (long) opts.valueOf(STEP_OPT); + long initValue = (long) opts.valueOf(INIT_OPT); + + + // Perform some error checking on inputs + Part part = PartNameTools.getPart(partName); + if (part == null || part.isSeries7()) { + throw new RuntimeException("ERROR: Invalid/unsupport part " + partName + "."); + } + + if (verbose) t.stop().start("Create Add/Sub Module"); + + Design adderDesign = new Design(adderName, partName); + + adderDesign.setAutoIOBuffers(false); + Device dev = adderDesign.getDevice(); + + Site slice = dev.getSite(sliceName); + AddSubGenerator.createAddSub(adderDesign, slice, width, countDown, false, true, false); + + //set init value on counter + String initBin = Long.toBinaryString(initValue); + String initFormatStr = "%0"+(width-initBin.length()) + "d%s"; + initBin = String.format(initFormatStr, 0, initBin); + String invInitBin = new StringBuilder(initBin).reverse().toString(); + for (int i = 0; i < width; i++) { + EDIFCellInst ff = adderDesign.getTopEDIFCell().getCellInst("sum"+i); + ff.addProperty("INIT", "1'b" + invInitBin.charAt(i)); + } + + // Add a clock constraint + String tcl = "create_clock -name "+clkName+" -period "+clkPeriodConstraint+" [get_ports "+clkName+"]"; + adderDesign.addXDCConstraint(ConstraintGroup.LATE,tcl); + adderDesign.setAutoIOBuffers(false); + + // Create module for adder and populate ports + Module adderModule = new Module(adderDesign); + for (Net net : adderModule.getNets()) { + EDIFNet edifNet = net.getLogicalNet(); + for(EDIFPortInst portInst : edifNet.getPortInsts()) { + if (portInst.isTopLevelPort()) { + Port port = new Port(portInst.getName(), net.getPins()); + port.setType(PortType.SIGNAL); + adderModule.addPort(port); + } + } + } + + if (verbose) t.stop().start("Create Counter"); + + // Create design for counter + Design cntrDesign = new Design(designName, partName); + cntrDesign.setAutoIOBuffers(false); + + // Add adder as submodule and replace. + ModuleInst mi = cntrDesign.createModuleInst(adderName, adderModule); + mi.placeOnOriginalAnchor(); + + EDIFCell cntrTop = cntrDesign.getTopEDIFCell(); + String bus = "["+(width-1)+":0]"; + + // Create port for the output of the counter. + EDIFPort outPort = cntrTop.createPort("cntrOut" + bus, EDIFDirection.OUTPUT, width); + + // Get gnd and static nets to connect to b port of adder + EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, cntrTop, cntrDesign.getNetlist()); + EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, cntrTop, cntrDesign.getNetlist()); + + //busNames for adder ports + String aBusName = adderDesign.getTopEDIFCell().getPort(INPUT_A_NAME + "[").getBusName(); + String bBusName = adderDesign.getTopEDIFCell().getPort(INPUT_B_NAME + "[").getBusName(); + String resultBusName = adderDesign.getTopEDIFCell().getPort(RESULT_NAME + "[").getBusName(); + + String stepBin = Long.toBinaryString(step); + String stepFormatStr = "%0"+(width-stepBin.length()) + "d%s"; + stepBin = String.format(stepFormatStr, 0, stepBin); + EDIFCellInst adderCell = cntrTop.getCellInst(adderName); + + //connect ports of adder modules + for(int i = 0; i Date: Wed, 26 Jul 2023 10:01:05 -0700 Subject: [PATCH 02/20] added function that creates physical nets from a finalized logical netlist Signed-off-by: Hayden Cook --- .../rapidwright/design/DesignTools.java | 131 +++++++-- .../examples/ParamCounterModule.java | 257 ------------------ 2 files changed, 113 insertions(+), 275 deletions(-) delete mode 100644 src/com/xilinx/rapidwright/examples/ParamCounterModule.java diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 49c298041..25c498510 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -1509,7 +1509,7 @@ public static void makeBlackBox(Design d, String hierarchicalCellName) { * Preserves other parts of the net if used by other sinks in the site if an * input. For the unrouting to be successful, this method depends on the site * routing to be consistent. - * + * * @param cell The cell of the pin * @param logicalPinName The logical pin name source or sink to have routing * removed. @@ -1587,9 +1587,9 @@ public static List unrouteCellPinSiteRouting(Cell cell, String logi } } else { // site routing terminates here or is invalid - } + } } - + } else if (otherCell != cell && otherCell.getLogicalPinMapping(pin.getName()) != null) { // Don't search farther, we don't need to unroute anything else if (pin.isInput() && belPin.isInput()) { @@ -1673,7 +1673,7 @@ public static List unrouteCellPinSiteRouting(Cell cell, String logi * 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. */ @@ -1857,7 +1857,7 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { /** * Helper method for makeBlackBox(). When cutting out nets that used to be * source'd from something inside a black box, the net names need to be updated. - * + * * @param d The current design * @param currNet Current net that requires a name change * @param newSource The source net (probably a pin on the black box) @@ -3639,7 +3639,7 @@ public static boolean isNetDrivenByHierPort(Net net) { * 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) { @@ -3651,7 +3651,7 @@ public static void lockNetlist(Design design) { * 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) { @@ -3663,7 +3663,7 @@ public static void unlockNetlist(Design design) { * 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. @@ -3688,7 +3688,7 @@ public static void lockPlacement(Design design, boolean lock) { * 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) { @@ -3700,7 +3700,7 @@ public static void lockPlacement(Design design) { * 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) { @@ -3713,7 +3713,7 @@ public static void unlockPlacement(Design design) { * 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. @@ -3734,7 +3734,7 @@ public static void lockRouting(Design design, boolean lock) { * 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) { @@ -3745,7 +3745,7 @@ public static void lockRouting(Design design) { * 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) { @@ -3755,7 +3755,7 @@ public static void unlockRouting(Design design) { /*** * 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) { @@ -3786,7 +3786,7 @@ public static void unrouteGNDNetAndLUTSources(Design design) { * 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) { @@ -3811,7 +3811,7 @@ public static void prohibitGNDSources(Design design) { /** * 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 @@ -3832,7 +3832,7 @@ public static Boolean isUltraScaleSliceTop(BEL bel) { * 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) { @@ -3870,7 +3870,7 @@ public static void prohibitPartialHalfSlices(Design design) { /** * 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 * '/'. @@ -3948,4 +3948,99 @@ public static void updatePinsIsRouted(Net net) { } } } + + /** + * Creates physical nets from all the logical EDIF nets. Assumes that the EDIF netlist is finalized. + * @param d The design that contains the complete logical netlist and where the physical nets will be created. + */ + static public void createPhysNetsFromLogical(Design d) { + EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()); + EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()); + + // Iterate through all canonical nets + Map parentNetMap = d.getNetlist().getParentNetMap(); + for( EDIFHierNet n : parentNetMap.values()) { + if(n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents + createPhysNetFromLogical(d, n); + } + } + + /** + * Creates a physical nets from the provided logical EDIF net. Assumes that the EDIF netlist is finalized. + * @param d The design that contains the complete logical netlist and where the physical net will be created. + * @param edifNet The EDIF Net to create into a physical net. + */ + static public List createPhysNetFromLogical(Design d, EDIFHierNet edifNet) { + //check whether net already exists + if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; + + Net net = d.createNet(edifNet); //create physical net + + // Get source EDIF port inst + EDIFHierPortInst srcPort = null; + for (EDIFHierPortInst hierPortInst : d.getNetlist().getPhysicalPins(edifNet)) { + EDIFPortInst portInst = hierPortInst.getPortInst(); + if (portInst.isOutput() && portInst.getCellInst() != null) { + srcPort = hierPortInst; + break; + } + } + + // Get cell connected to port inst + Cell srcCell = d.getCell(srcPort.getFullHierarchicalInstName()); + + // Connect physical net to the physical cell pins corresponding to the logical ports + List sitePins = new ArrayList<>(); + for(EDIFHierPortInst hierPortInst: d.getNetlist().getPhysicalPins(edifNet)) { + EDIFPortInst portInst = hierPortInst.getPortInst(); + if (portInst.equals(srcPort)) continue; + + EDIFCellInst cellInst = portInst.getCellInst(); + Cell cell = cellInst == null ? null : d.getCell(cellInst.getName()); + if (cell == null) continue; + + // Only create connection if the net goes outside the site. This prevents sitePins instances from + // erroneously being created. + if(!isIntraSiteConnection(srcCell, srcPort.getPortInst(), cell, portInst)) + sitePins.add(net.connect(cell, portInst.getName())); + } + + if (srcCell != null && sitePins.size() > 0) { + net.connect(srcCell, srcPort.getPortInst().getName()); + } + + return sitePins; + } + + /** + * checks if the two provided ports of two cells can be connected without leaving the site. + * @param srcCell source cell + * @param srcPort port of source Cell + * @param dstCell destination cell + * @param dstPort port of destination cell + * @return true if the ports can be connected without leaving the site. False otherwise. + */ + private static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, Cell dstCell, EDIFPortInst dstPort) { + if (dstCell.getSite().equals(srcCell.getSite())) { + Queue queue = new LinkedList<>(); + queue.add(srcCell.getBELPin(srcPort)); + BELPin dstPin = dstCell.getBELPin(dstPort); + while(!queue.isEmpty()) { + ArrayList conns = queue.poll().getSiteConns(); + for(BELPin pin : conns) { + if (pin.equals(dstPin)) { + return true; + } + else if(pin.isInput() && pin.getBEL().getBELClass().equals(BELClass.RBEL)) { + for(BELPin nextPin : pin.getBEL().getPins()) { + if (nextPin.isOutput()) { + queue.add(nextPin); + } + } + } + } + } + } + return false; + } } diff --git a/src/com/xilinx/rapidwright/examples/ParamCounterModule.java b/src/com/xilinx/rapidwright/examples/ParamCounterModule.java deleted file mode 100644 index 7957a60d6..000000000 --- a/src/com/xilinx/rapidwright/examples/ParamCounterModule.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2019-2022, Xilinx, Inc. - * Copyright (c) 2022, Advanced Micro Devices, Inc. - * All rights reserved. - * - * Author: Chris Lavin, Xilinx Research Labs. - * - * 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.examples; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; - -import com.xilinx.rapidwright.design.ConstraintGroup; -import com.xilinx.rapidwright.design.Design; -import com.xilinx.rapidwright.design.Module; -import com.xilinx.rapidwright.design.ModuleInst; -import com.xilinx.rapidwright.design.Net; -import com.xilinx.rapidwright.design.NetType; -import com.xilinx.rapidwright.design.Port; -import com.xilinx.rapidwright.design.PortType; -import com.xilinx.rapidwright.device.Device; -import com.xilinx.rapidwright.device.Part; -import com.xilinx.rapidwright.device.PartNameTools; -import com.xilinx.rapidwright.device.Site; -import com.xilinx.rapidwright.edif.EDIFCell; -import com.xilinx.rapidwright.edif.EDIFCellInst; -import com.xilinx.rapidwright.edif.EDIFDirection; -import com.xilinx.rapidwright.edif.EDIFNet; -import com.xilinx.rapidwright.edif.EDIFPort; -import com.xilinx.rapidwright.edif.EDIFPortInst; -import com.xilinx.rapidwright.edif.EDIFTools; -import com.xilinx.rapidwright.rwroute.RWRoute; -import com.xilinx.rapidwright.tests.CodePerfTracker; -import com.xilinx.rapidwright.util.MessageGenerator; -import joptsimple.OptionParser; -import joptsimple.OptionSet; - -import static com.xilinx.rapidwright.examples.ArithmeticGenerator.INPUT_A_NAME; -import static com.xilinx.rapidwright.examples.ArithmeticGenerator.INPUT_B_NAME; -import static com.xilinx.rapidwright.examples.ArithmeticGenerator.RESULT_NAME; - -/** - * A class that implements a counter using the - */ -public class ParamCounterModule { - - protected static final String PART_OPT = "p"; - protected static final String DESIGN_NAME_OPT = "d"; - protected static final String ADDER_NAME_OPT = "a"; - protected static final String OUT_DCP_OPT = "o"; - protected static final String CLK_NAME_OPT = "c"; - protected static final String CLK_CONSTRAINT_OPT = "x"; - protected static final String WIDTH_OPT = "w"; - protected static final String VERBOSE_OPT = "v"; - protected static final String HELP_OPT = "h"; - private static final String SLICE_SITES_OPT = "s"; - private static final String COUNT_DOWN_OPT = "m"; - private static final String STEP_OPT = "t"; - private static final String INIT_OPT = "i"; - - private static OptionParser createOptionParser() { - // Defaults - String partName = "xczu3eg-sbva484-1-i"; - String designName = "counter"; - String adderName = "adder"; - String outputDCPFileName = System.getProperty("user.dir") + File.separator + designName +".dcp"; - String clkName = "clk"; - double clkPeriodConstraint = 1.291; // 775 MHz - int width = 32; - String sliceSite = "SLICE_X3Y3"; - boolean verbose = true; - boolean countDown = false; - long initValue = 0; - long step = 1; - - OptionParser p = new OptionParser() {{ - accepts(PART_OPT).withOptionalArg().defaultsTo(partName).describedAs("UltraScale+ Part Name"); - accepts(DESIGN_NAME_OPT).withOptionalArg().defaultsTo(designName).describedAs("Design Name"); - accepts(DESIGN_NAME_OPT).withOptionalArg().defaultsTo(designName).describedAs("Name of counter design"); - accepts(ADDER_NAME_OPT).withOptionalArg().defaultsTo(adderName).describedAs("Name of adder submodule"); - accepts(OUT_DCP_OPT).withOptionalArg().defaultsTo(outputDCPFileName).describedAs("Output DCP File Name"); - accepts(CLK_NAME_OPT).withOptionalArg().defaultsTo(clkName).describedAs("Clk net name"); - accepts(CLK_CONSTRAINT_OPT).withOptionalArg().ofType(Double.class).defaultsTo(clkPeriodConstraint).describedAs("Clk period constraint (ns)"); - accepts(WIDTH_OPT).withOptionalArg().ofType(Integer.class).defaultsTo(width).describedAs("Operand width"); - accepts(SLICE_SITES_OPT).withOptionalArg().defaultsTo(sliceSite).describedAs("Lower left slice to be used for adder/subtracter"); - accepts(COUNT_DOWN_OPT).withOptionalArg().ofType(Boolean.class).defaultsTo(countDown).describedAs("Counts down instead of up"); - accepts(STEP_OPT).withOptionalArg().ofType(Long.class).defaultsTo(step).describedAs("Counts down instead of up"); - accepts(INIT_OPT).withOptionalArg().ofType(Long.class).defaultsTo(initValue).describedAs("Counts down instead of up"); - accepts(VERBOSE_OPT).withOptionalArg().ofType(Boolean.class).defaultsTo(verbose).describedAs("Print verbose output"); - acceptsAll( Arrays.asList(HELP_OPT, "?"), "Print Help" ).forHelp(); - }}; - - return p; - } - - private static void printHelp(OptionParser p) { - MessageGenerator.printHeader("Adder/Subtractor Generator"); - System.out.println("This RapidWright program creates a placed and routed DCP for UltraScale+ devices that contains \n" - + "imported into UltraScale+ designs to perform addition or subtraction. See \n" - + "RapidWright documentation for more information.\n"); - try { - p.accepts(OUT_DCP_OPT).withOptionalArg().defaultsTo("slr_crosser.dcp").describedAs("Output DCP File Name"); - p.printHelpOn(System.out); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static void main(String[] args) { - // Extract program options - OptionParser p = createOptionParser(); - OptionSet opts = p.parse(args); - boolean verbose = (boolean) opts.valueOf(VERBOSE_OPT); - if (opts.has(HELP_OPT)) { - printHelp(p); - return; - } - - CodePerfTracker t = verbose ? new CodePerfTracker(AddSubGenerator.class.getSimpleName(),true).start("Init") : null; - - String partName = (String) opts.valueOf(PART_OPT); - String designName = (String) opts.valueOf(DESIGN_NAME_OPT); - String adderName = (String) opts.valueOf(ADDER_NAME_OPT); - String outputDCPFileName = (String) opts.valueOf(OUT_DCP_OPT); - String clkName = (String) opts.valueOf(CLK_NAME_OPT); - double clkPeriodConstraint = (double) opts.valueOf(CLK_CONSTRAINT_OPT); - int width = (int) opts.valueOf(WIDTH_OPT); - String sliceName = (String) opts.valueOf(SLICE_SITES_OPT); - boolean countDown = (boolean) opts.valueOf(COUNT_DOWN_OPT); - long step = (long) opts.valueOf(STEP_OPT); - long initValue = (long) opts.valueOf(INIT_OPT); - - - // Perform some error checking on inputs - Part part = PartNameTools.getPart(partName); - if (part == null || part.isSeries7()) { - throw new RuntimeException("ERROR: Invalid/unsupport part " + partName + "."); - } - - if (verbose) t.stop().start("Create Add/Sub Module"); - - Design adderDesign = new Design(adderName, partName); - - adderDesign.setAutoIOBuffers(false); - Device dev = adderDesign.getDevice(); - - Site slice = dev.getSite(sliceName); - AddSubGenerator.createAddSub(adderDesign, slice, width, countDown, false, true, false); - - //set init value on counter - String initBin = Long.toBinaryString(initValue); - String initFormatStr = "%0"+(width-initBin.length()) + "d%s"; - initBin = String.format(initFormatStr, 0, initBin); - String invInitBin = new StringBuilder(initBin).reverse().toString(); - for (int i = 0; i < width; i++) { - EDIFCellInst ff = adderDesign.getTopEDIFCell().getCellInst("sum"+i); - ff.addProperty("INIT", "1'b" + invInitBin.charAt(i)); - } - - // Add a clock constraint - String tcl = "create_clock -name "+clkName+" -period "+clkPeriodConstraint+" [get_ports "+clkName+"]"; - adderDesign.addXDCConstraint(ConstraintGroup.LATE,tcl); - adderDesign.setAutoIOBuffers(false); - - // Create module for adder and populate ports - Module adderModule = new Module(adderDesign); - for (Net net : adderModule.getNets()) { - EDIFNet edifNet = net.getLogicalNet(); - for(EDIFPortInst portInst : edifNet.getPortInsts()) { - if (portInst.isTopLevelPort()) { - Port port = new Port(portInst.getName(), net.getPins()); - port.setType(PortType.SIGNAL); - adderModule.addPort(port); - } - } - } - - if (verbose) t.stop().start("Create Counter"); - - // Create design for counter - Design cntrDesign = new Design(designName, partName); - cntrDesign.setAutoIOBuffers(false); - - // Add adder as submodule and replace. - ModuleInst mi = cntrDesign.createModuleInst(adderName, adderModule); - mi.placeOnOriginalAnchor(); - - EDIFCell cntrTop = cntrDesign.getTopEDIFCell(); - String bus = "["+(width-1)+":0]"; - - // Create port for the output of the counter. - EDIFPort outPort = cntrTop.createPort("cntrOut" + bus, EDIFDirection.OUTPUT, width); - - // Get gnd and static nets to connect to b port of adder - EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, cntrTop, cntrDesign.getNetlist()); - EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, cntrTop, cntrDesign.getNetlist()); - - //busNames for adder ports - String aBusName = adderDesign.getTopEDIFCell().getPort(INPUT_A_NAME + "[").getBusName(); - String bBusName = adderDesign.getTopEDIFCell().getPort(INPUT_B_NAME + "[").getBusName(); - String resultBusName = adderDesign.getTopEDIFCell().getPort(RESULT_NAME + "[").getBusName(); - - String stepBin = Long.toBinaryString(step); - String stepFormatStr = "%0"+(width-stepBin.length()) + "d%s"; - stepBin = String.format(stepFormatStr, 0, stepBin); - EDIFCellInst adderCell = cntrTop.getCellInst(adderName); - - //connect ports of adder modules - for(int i = 0; i Date: Wed, 26 Jul 2023 10:35:51 -0700 Subject: [PATCH 03/20] added return to the javadoc string for createPhysNetFromLogical() Signed-off-by: Hayden Cook --- src/com/xilinx/rapidwright/design/DesignTools.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 25c498510..b8e2b0c7a 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3969,6 +3969,7 @@ static public void createPhysNetsFromLogical(Design d) { * Creates a physical nets from the provided logical EDIF net. Assumes that the EDIF netlist is finalized. * @param d The design that contains the complete logical netlist and where the physical net will be created. * @param edifNet The EDIF Net to create into a physical net. + * @return A list of the SitePinInsts added to the newly created physical net */ static public List createPhysNetFromLogical(Design d, EDIFHierNet edifNet) { //check whether net already exists From f9b2ba72740261011dbad6c6742e1d965fe3cc3c Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:56:59 -0600 Subject: [PATCH 04/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 b8e2b0c7a..c22345040 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4021,7 +4021,7 @@ static public List createPhysNetFromLogical(Design d, EDIFHierNet e * @param dstPort port of destination cell * @return true if the ports can be connected without leaving the site. False otherwise. */ - private static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, Cell dstCell, EDIFPortInst dstPort) { + public static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, Cell dstCell, EDIFPortInst dstPort) { if (dstCell.getSite().equals(srcCell.getSite())) { Queue queue = new LinkedList<>(); queue.add(srcCell.getBELPin(srcPort)); From 3998094a1d2ecbc36dd774a4090081ef1c570824 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:57:10 -0600 Subject: [PATCH 05/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 c22345040..02c07e727 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4014,7 +4014,7 @@ static public List createPhysNetFromLogical(Design d, EDIFHierNet e } /** - * checks if the two provided ports of two cells can be connected without leaving the site. + * Checks if the two provided ports of two cells can be connected without leaving the site. * @param srcCell source cell * @param srcPort port of source Cell * @param dstCell destination cell From 6012c8f435d31bfe34b7789ebc2e85a58051ecba Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:57:21 -0600 Subject: [PATCH 06/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 02c07e727..66e8625ed 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4026,7 +4026,7 @@ public static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, Queue queue = new LinkedList<>(); queue.add(srcCell.getBELPin(srcPort)); BELPin dstPin = dstCell.getBELPin(dstPort); - while(!queue.isEmpty()) { + while (!queue.isEmpty()) { ArrayList conns = queue.poll().getSiteConns(); for(BELPin pin : conns) { if (pin.equals(dstPin)) { From 76f0a47fdef20215651f0c91fdc56f348c071223 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:57:34 -0600 Subject: [PATCH 07/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 66e8625ed..84b795ba5 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4028,7 +4028,7 @@ public static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, BELPin dstPin = dstCell.getBELPin(dstPort); while (!queue.isEmpty()) { ArrayList conns = queue.poll().getSiteConns(); - for(BELPin pin : conns) { + for (BELPin pin : conns) { if (pin.equals(dstPin)) { return true; } From 8df8183da6fb8f286c1f0419d9369d68edd246c7 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:58:20 -0600 Subject: [PATCH 08/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 84b795ba5..611fb905b 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3959,7 +3959,7 @@ static public void createPhysNetsFromLogical(Design d) { // Iterate through all canonical nets Map parentNetMap = d.getNetlist().getParentNetMap(); - for( EDIFHierNet n : parentNetMap.values()) { + for (EDIFHierNet n : parentNetMap.values()) { if(n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents createPhysNetFromLogical(d, n); } From a11c6ff078e71f9662669918361d52a980a9c38d Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:58:48 -0600 Subject: [PATCH 09/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 611fb905b..dc2af8d8d 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4032,7 +4032,7 @@ public static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, if (pin.equals(dstPin)) { return true; } - else if(pin.isInput() && pin.getBEL().getBELClass().equals(BELClass.RBEL)) { + else if (pin.isInput() && pin.getBEL().getBELClass() == BELClass.RBEL) { for(BELPin nextPin : pin.getBEL().getPins()) { if (nextPin.isOutput()) { queue.add(nextPin); From 243ce4275277a513346c2369cc06dbd67be2cd32 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:59:01 -0600 Subject: [PATCH 10/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 dc2af8d8d..846697d73 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4033,7 +4033,7 @@ public static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, return true; } else if (pin.isInput() && pin.getBEL().getBELClass() == BELClass.RBEL) { - for(BELPin nextPin : pin.getBEL().getPins()) { + for (BELPin nextPin : pin.getBEL().getPins()) { if (nextPin.isOutput()) { queue.add(nextPin); } From 7468f014fea2bc641e657b3607bd9b1e4c2b45fb Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:59:15 -0600 Subject: [PATCH 11/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 846697d73..d85647da6 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3971,7 +3971,7 @@ static public void createPhysNetsFromLogical(Design d) { * @param edifNet The EDIF Net to create into a physical net. * @return A list of the SitePinInsts added to the newly created physical net */ - static public List createPhysNetFromLogical(Design d, EDIFHierNet edifNet) { + public static List createPhysNetFromLogical(Design d, EDIFHierNet edifNet) { //check whether net already exists if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; From 1b824fa7eeb4d1637633e69063d61688814e23b6 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:03:12 -0600 Subject: [PATCH 12/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 d85647da6..f718dba69 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3960,7 +3960,7 @@ static public void createPhysNetsFromLogical(Design d) { // Iterate through all canonical nets Map parentNetMap = d.getNetlist().getParentNetMap(); for (EDIFHierNet n : parentNetMap.values()) { - if(n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents + if (n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents createPhysNetFromLogical(d, n); } } From 3b5bc74eaa241660631951eb05b2cd397929cc98 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:03:19 -0600 Subject: [PATCH 13/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 f718dba69..f36e04017 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3973,7 +3973,7 @@ static public void createPhysNetsFromLogical(Design d) { */ public static List createPhysNetFromLogical(Design d, EDIFHierNet edifNet) { //check whether net already exists - if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; + if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; Net net = d.createNet(edifNet); //create physical net From b1c01cf59bf1c53a64d2fd6e71d7b7e07cf25383 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:03:30 -0600 Subject: [PATCH 14/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 f36e04017..be9910725 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -4002,7 +4002,7 @@ public static List createPhysNetFromLogical(Design d, EDIFHierNet e // Only create connection if the net goes outside the site. This prevents sitePins instances from // erroneously being created. - if(!isIntraSiteConnection(srcCell, srcPort.getPortInst(), cell, portInst)) + if (!isIntraSiteConnection(srcCell, srcPort.getPortInst(), cell, portInst)) sitePins.add(net.connect(cell, portInst.getName())); } From f63c9547f68bcd76b0a44b1839aa3c77dce1f9f1 Mon Sep 17 00:00:00 2001 From: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:45:09 -0600 Subject: [PATCH 15/20] Update src/com/xilinx/rapidwright/design/DesignTools.java Co-authored-by: Chris Lavin Signed-off-by: haydenc-amd <133905095+haydenc-amd@users.noreply.github.com> --- 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 be9910725..5dace071d 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3953,7 +3953,7 @@ public static void updatePinsIsRouted(Net net) { * Creates physical nets from all the logical EDIF nets. Assumes that the EDIF netlist is finalized. * @param d The design that contains the complete logical netlist and where the physical nets will be created. */ - static public void createPhysNetsFromLogical(Design d) { + public static void createPhysNetsFromLogical(Design d) { EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()); EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()); From a5db30ef7e0d849797d239487ed56dcfa4fed288 Mon Sep 17 00:00:00 2001 From: Hayden Cook Date: Wed, 16 Aug 2023 15:54:10 -0700 Subject: [PATCH 16/20] fixed indentation Signed-off-by: Hayden Cook --- .../rapidwright/design/DesignTools.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 5dace071d..0ad42c844 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3949,21 +3949,21 @@ public static void updatePinsIsRouted(Net net) { } } - /** - * Creates physical nets from all the logical EDIF nets. Assumes that the EDIF netlist is finalized. - * @param d The design that contains the complete logical netlist and where the physical nets will be created. - */ - public static void createPhysNetsFromLogical(Design d) { - EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()); - EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()); + /** + * Creates physical nets from all the logical EDIF nets. Assumes that the EDIF netlist is finalized. + * @param d The design that contains the complete logical netlist and where the physical nets will be created. + */ + public static void createPhysNetsFromLogical(Design d) { + EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()); + EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()); - // Iterate through all canonical nets - Map parentNetMap = d.getNetlist().getParentNetMap(); - for (EDIFHierNet n : parentNetMap.values()) { - if (n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents - createPhysNetFromLogical(d, n); - } + // Iterate through all canonical nets + Map parentNetMap = d.getNetlist().getParentNetMap(); + for (EDIFHierNet n : parentNetMap.values()) { + if (n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents + createPhysNetFromLogical(d, n); } + } /** * Creates a physical nets from the provided logical EDIF net. Assumes that the EDIF netlist is finalized. From 218aa373e62c2f29385126457482a57eb8f86099 Mon Sep 17 00:00:00 2001 From: Hayden Cook Date: Thu, 17 Aug 2023 05:28:32 -0700 Subject: [PATCH 17/20] removed white space changes Signed-off-by: Hayden Cook --- .../rapidwright/design/DesignTools.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 0ad42c844..2743ae549 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -1509,7 +1509,7 @@ public static void makeBlackBox(Design d, String hierarchicalCellName) { * Preserves other parts of the net if used by other sinks in the site if an * input. For the unrouting to be successful, this method depends on the site * routing to be consistent. - * + * * @param cell The cell of the pin * @param logicalPinName The logical pin name source or sink to have routing * removed. @@ -1587,9 +1587,9 @@ public static List unrouteCellPinSiteRouting(Cell cell, String logi } } else { // site routing terminates here or is invalid - } + } } - + } else if (otherCell != cell && otherCell.getLogicalPinMapping(pin.getName()) != null) { // Don't search farther, we don't need to unroute anything else if (pin.isInput() && belPin.isInput()) { @@ -1673,7 +1673,7 @@ public static List unrouteCellPinSiteRouting(Cell cell, String logi * 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. */ @@ -1857,7 +1857,7 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { /** * Helper method for makeBlackBox(). When cutting out nets that used to be * source'd from something inside a black box, the net names need to be updated. - * + * * @param d The current design * @param currNet Current net that requires a name change * @param newSource The source net (probably a pin on the black box) @@ -3639,7 +3639,7 @@ public static boolean isNetDrivenByHierPort(Net net) { * 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) { @@ -3651,7 +3651,7 @@ public static void lockNetlist(Design design) { * 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) { @@ -3663,7 +3663,7 @@ public static void unlockNetlist(Design design) { * 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. @@ -3688,7 +3688,7 @@ public static void lockPlacement(Design design, boolean lock) { * 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) { @@ -3700,7 +3700,7 @@ public static void lockPlacement(Design design) { * 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) { @@ -3713,7 +3713,7 @@ public static void unlockPlacement(Design design) { * 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. @@ -3734,7 +3734,7 @@ public static void lockRouting(Design design, boolean lock) { * 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) { @@ -3745,7 +3745,7 @@ public static void lockRouting(Design design) { * 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) { @@ -3755,7 +3755,7 @@ public static void unlockRouting(Design design) { /*** * 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) { @@ -3786,7 +3786,7 @@ public static void unrouteGNDNetAndLUTSources(Design design) { * 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) { @@ -3811,7 +3811,7 @@ public static void prohibitGNDSources(Design design) { /** * 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 @@ -3832,7 +3832,7 @@ public static Boolean isUltraScaleSliceTop(BEL bel) { * 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) { @@ -3870,7 +3870,7 @@ public static void prohibitPartialHalfSlices(Design design) { /** * 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 * '/'. From 6b6582595e3b33001bb0324eb872c033288a12d2 Mon Sep 17 00:00:00 2001 From: Hayden Cook Date: Mon, 21 Aug 2023 10:13:28 -0700 Subject: [PATCH 18/20] createPhysNetFromLogical() now works with GND and VCC nets Signed-off-by: Hayden Cook --- src/com/xilinx/rapidwright/design/DesignTools.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 2743ae549..d3a88caaa 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3960,7 +3960,7 @@ public static void createPhysNetsFromLogical(Design d) { // Iterate through all canonical nets Map parentNetMap = d.getNetlist().getParentNetMap(); for (EDIFHierNet n : parentNetMap.values()) { - if (n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents +// if (n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents createPhysNetFromLogical(d, n); } } @@ -3975,7 +3975,13 @@ public static List createPhysNetFromLogical(Design d, EDIFHierNet e //check whether net already exists if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; - Net net = d.createNet(edifNet); //create physical net + Net net; //create physical net + if(edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()))) + net = d.getGndNet(); + else if(edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()))) + net = d.getVccNet(); + else + net = d.createNet(edifNet); // Get source EDIF port inst EDIFHierPortInst srcPort = null; From af02d4f1ad9f54e800daf9aca9269ab3a60bbdc3 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Mon, 15 Jan 2024 18:17:43 -0700 Subject: [PATCH 19/20] Apply suggestions from code review Signed-off-by: Chris Lavin --- src/com/xilinx/rapidwright/design/DesignTools.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index 675bb1bfd..fb6a4fdd2 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -3973,13 +3973,12 @@ public static void createPhysNetsFromLogical(Design d) { // Iterate through all canonical nets Map parentNetMap = d.getNetlist().getParentNetMap(); for (EDIFHierNet n : parentNetMap.values()) { -// if (n.getNet().equals(gnd) || n.getNet().equals(vcc)) continue; // Static nets do not have physical equivalents createPhysNetFromLogical(d, n); } } /** - * Creates a physical nets from the provided logical EDIF net. Assumes that the EDIF netlist is finalized. + * Creates a physical net from the provided logical EDIF net. Assumes that the EDIF netlist is finalized. * @param d The design that contains the complete logical netlist and where the physical net will be created. * @param edifNet The EDIF Net to create into a physical net. * @return A list of the SitePinInsts added to the newly created physical net @@ -3989,12 +3988,13 @@ public static List createPhysNetFromLogical(Design d, EDIFHierNet e if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; Net net; //create physical net - if(edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()))) + if (edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()))) { net = d.getGndNet(); - else if(edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()))) + } else if (edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()))) { net = d.getVccNet(); - else + } else { net = d.createNet(edifNet); + } // Get source EDIF port inst EDIFHierPortInst srcPort = null; @@ -4011,7 +4011,7 @@ else if(edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIF // Connect physical net to the physical cell pins corresponding to the logical ports List sitePins = new ArrayList<>(); - for(EDIFHierPortInst hierPortInst: d.getNetlist().getPhysicalPins(edifNet)) { + for (EDIFHierPortInst hierPortInst: d.getNetlist().getPhysicalPins(edifNet)) { EDIFPortInst portInst = hierPortInst.getPortInst(); if (portInst.equals(srcPort)) continue; From 4e26415bb79fbee46f3b2e2cf9a31f693cd1d09c Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Mon, 15 Jan 2024 18:52:59 -0700 Subject: [PATCH 20/20] Updates Signed-off-by: Chris Lavin --- .../rapidwright/design/DesignTools.java | 429 +++++++++++++----- 1 file changed, 316 insertions(+), 113 deletions(-) diff --git a/src/com/xilinx/rapidwright/design/DesignTools.java b/src/com/xilinx/rapidwright/design/DesignTools.java index fb6a4fdd2..d740cbd08 100644 --- a/src/com/xilinx/rapidwright/design/DesignTools.java +++ b/src/com/xilinx/rapidwright/design/DesignTools.java @@ -50,6 +50,7 @@ import java.util.PriorityQueue; import java.util.Queue; import java.util.Set; +import java.util.function.Consumer; import java.util.stream.Collectors; import com.xilinx.rapidwright.design.blocks.PBlock; @@ -67,6 +68,7 @@ import com.xilinx.rapidwright.device.SiteTypeEnum; import com.xilinx.rapidwright.device.Tile; import com.xilinx.rapidwright.device.Wire; +import com.xilinx.rapidwright.eco.ECOTools; import com.xilinx.rapidwright.edif.EDIFCell; import com.xilinx.rapidwright.edif.EDIFCellInst; import com.xilinx.rapidwright.edif.EDIFHierCellInst; @@ -79,6 +81,7 @@ import com.xilinx.rapidwright.edif.EDIFPortInst; import com.xilinx.rapidwright.edif.EDIFPropertyValue; import com.xilinx.rapidwright.edif.EDIFTools; +import com.xilinx.rapidwright.interchange.PhysNetlistWriter; import com.xilinx.rapidwright.placer.blockplacer.BlockPlacer2Impls; import com.xilinx.rapidwright.placer.blockplacer.ImplsInstancePort; import com.xilinx.rapidwright.placer.blockplacer.ImplsPath; @@ -853,7 +856,7 @@ public static String resolveNetNameFromSiteWire(SiteInst inst, int siteWire) { } } String logPinName = c.getLogicalPinMapping(pin.getName()); - EDIFPortInst portInst = c.getEDIFCellInst().getPortInst(logPinName); + EDIFPortInst portInst = logPinName == null ? null : c.getEDIFCellInst().getPortInst(logPinName); if (portInst == null) continue; EDIFNet net = portInst.getNet(); String netName = c.getParentHierarchicalInstName() + EDIFTools.EDIF_HIER_SEP + net.getName(); @@ -1421,6 +1424,7 @@ public static void fullyRemoveCell(Design design, Cell cell, Map> deferRemovals) { if (deferRemovals != null) { + assert(spi.getNet() != null); Set pins = deferRemovals.computeIfAbsent(spi.getNet(), p -> new HashSet<>()); pins.add(spi); } else { @@ -1815,10 +1819,13 @@ public static void makeBlackBox(Design d, EDIFHierCellInst hierarchicalCell) { Set netsToKeep = new HashSet<>(); for (Entry e : netsToUpdate.entrySet()) { EDIFHierNet newSource = d.getNetlist().getHierNetFromName(e.getValue()); - Net updatedNet = DesignTools.updateNetName(d, e.getKey(), newSource.getNet(), e.getValue()); - if (updatedNet != null) { - netsToKeep.add(updatedNet.getName()); + Net net = e.getKey(); + if (!net.rename(e.getValue())) { + throw new RuntimeException("ERROR: Failed to rename net '" + net.getName() + "'"); } + // TODO: Remove workaround below when >2023.2.1 + net.setLogicalHierNet(null); + netsToKeep.add(net.getName()); } t.stop().start("cleanup siteinsts"); @@ -1996,38 +2003,83 @@ public static boolean stampPlacement(Design design, Module stamp, Map getConnectedCells(SitePinInst pin) { - HashSet cells = new HashSet(); - SiteInst si = pin.getSiteInst(); - if (si == null) return cells; - for (BELPin p : pin.getBELPin().getSiteConns()) { + private static void foreachConnectedBELPin(BELPin pin, SiteInst si, Consumer action) { + if (si == null) { + return; + } + for (BELPin p : pin.getSiteConns()) { if (p.getBEL().getBELClass() == BELClass.RBEL) { SitePIP pip = si.getUsedSitePIP(p.getBELName()); if (pip == null) continue; if (p.isOutput()) { p = pip.getInputPin().getSiteConns().get(0); - Cell c = si.getCell(p.getBELName()); - if (c != null) cells.add(c); + action.accept(p); } else { for (BELPin snk : pip.getOutputPin().getSiteConns()) { - Cell c = si.getCell(snk.getBELName()); - if (c != null) cells.add(c); + action.accept(snk); } } } else { Cell c = si.getCell(p.getBELName()); if (c != null && c.getLogicalPinMapping(p.getName()) != null) { - cells.add(c); + action.accept(p); } } } + } + + /** + * Looks in the site instance for cells connected to this BEL pin and SiteInst. + * @param pin The BELPin to examine for connected cells. + * @param si The SiteInst to examine for connected cells. + * @return Set of connected cells to this pin. + */ + public static Set getConnectedCells(BELPin pin, SiteInst si) { + final Set cells = new HashSet<>(); + foreachConnectedBELPin(pin, si, (p) -> { + Cell c = si.getCell(p.getBELName()); + if (c != null) { + cells.add(c); + } + }); return cells; } + /** + * Looks in the site instance for cells connected to this site pin. + * @param pin The SitePinInst to examine for connected cells. + * @return Set of connected cells to this pin. + */ + public static Set getConnectedCells(SitePinInst pin) { + return getConnectedCells(pin.getBELPin(), pin.getSiteInst()); + } + + /** + * Looks in the site instance for BEL pins connected to this BEL pin and SiteInst. + * @param pin The SitePinInst to examine for connected BEL pins. + * @param si The SiteInst to examine for connected cells. + * @return Set of BEL pins to this site pin. + */ + public static Set getConnectedBELPins(BELPin pin, SiteInst si) { + final Set pins = new HashSet<>(); + foreachConnectedBELPin(pin, si, pins::add); + return pins; + } + + /** + * Looks in the site instance for BEL pins connected to this site pin. + * @param pin The SitePinInst to examine for connected BEL pins. + * @return Set of BEL pins to this site pin. + */ + public static Set getConnectedBELPins(SitePinInst pin) { + return getConnectedBELPins(pin.getBELPin(), pin.getSiteInst()); + } + /** * Quick and dumb placement of a cell. Does not attempt * any optimization and will not change the placement @@ -2090,13 +2142,34 @@ public static List createMissingSitePinInsts(Design design, Net net for (SiteInst siteInst : new ArrayList<>(net.getSiteInsts())) { for (String siteWire : new ArrayList<>(siteInst.getSiteWiresFromNet(net))) { for (BELPin pin : siteInst.getSiteWirePins(siteWire)) { - if (pin.isSitePort()) { - SitePinInst currPin = siteInst.getSitePinInst(pin.getName()); - if (currPin == null) { - currPin = net.createPin(pin.getName(), siteInst); - newPins.add(currPin); + if (!pin.isSitePort()) { + continue; + } + + SitePinInst currPin = siteInst.getSitePinInst(pin.getName()); + if (currPin != null) { + // SitePinInst already exists + continue; + } + + if (pin.isInput()) { + // Input BELPin means output site port; check that this site port is driven + // by a cell, rather than coming from an input site port + boolean foundOutputPin = false; + for (BELPin connectedBELPin : getConnectedBELPins(pin, siteInst)) { + if (connectedBELPin.isInput()) { + continue; + } + foundOutputPin = true; + break; + } + if (!foundOutputPin) { + continue; } } + + currPin = net.createPin(pin.getName(), siteInst); + newPins.add(currPin); } } } @@ -2104,23 +2177,44 @@ public static List createMissingSitePinInsts(Design design, Net net return newPins; } + EDIFNetlist netlist = design.getNetlist(); + EDIFHierNet parentEhn = null; for (EDIFHierPortInst p : physPins) { Cell c = design.getCell(p.getFullHierarchicalInstName()); - if (c == null || c.getBEL() == null) continue; + if (c == null) continue; + BEL bel = c.getBEL(); + if (bel == null) continue; String logicalPinName = p.getPortInst().getName(); Set physPinMappings = c.getAllPhysicalPinMappings(logicalPinName); // BRAMs can have two (or more) physical pin mappings for a logical pin if (physPinMappings != null) { SiteInst si = c.getSiteInst(); for (String physPin : physPinMappings) { - String sitePinName = getRoutedSitePinFromPhysicalPin(c, net, physPin); + BELPin belPin = bel.getPin(physPin); + // Use the net attached to the phys pin + Net siteWireNet = si.getNetFromSiteWire(belPin.getSiteWireName()); + if (siteWireNet == null) { + continue; + } + if (siteWireNet != net && !siteWireNet.isStaticNet()) { + if (parentEhn == null) { + parentEhn = netlist.getParentNet(net.getLogicalHierNet()); + } + EDIFHierNet parentSiteWireEhn = netlist.getParentNet(siteWireNet.getLogicalHierNet()); + if (!parentSiteWireEhn.equals(parentEhn)) { + // Site wire net is not an alias of the net + throw new RuntimeException("ERROR: Net on " + si.getSiteName() + "/" + belPin + + "'" + siteWireNet.getName() + "' is not an alias of " + + "'" + net.getName() + "'"); + } + } + String sitePinName = getRoutedSitePinFromPhysicalPin(c, siteWireNet, physPin); if (sitePinName == null) continue; SitePinInst newPin = si.getSitePinInst(sitePinName); if (newPin != null) continue; - int wireIndex = si.getSite().getTileWireIndexFromPinName(sitePinName); - if (Node.getNode(si.getTile(), wireIndex) == null) { - // It's possible that the discovered site pin (e.g. as for some IOB tiles) - // is not actually connected to the global routing fabric; skip those + 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); @@ -2226,11 +2320,27 @@ public static List getAllRoutedSitePinsFromPhysicalPin(Cell cell, Net ne } /** - * Creates all missing SitePinInsts in a design. See also {@link #createMissingSitePinInsts(Design, Net)} + * Creates all missing SitePinInsts in a design, except GLOBAL_USEDNET. + * See also {@link #createMissingSitePinInsts(Design, Net)}. * @param design The current design */ public static void createMissingSitePinInsts(Design design) { + EDIFNetlist netlist = design.getNetlist(); for (Net net : design.getNets()) { + if (net.isUsedNet()) { + continue; + } + 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 + continue; + } + } createMissingSitePinInsts(design,net); } } @@ -3032,22 +3142,16 @@ public static void makePhysNetNamesConsistent(Design design) { if (parentPhysNet != null) { // Fall through - } else if (!net.rename(parentHierNet.getHierarchicalNetName())) { + } else if (net.rename(parentHierNet.getHierarchicalNetName())) { + // TODO: Remove workaround below when >2023.2.1 + net.setLogicalHierNet(null); + } else { System.out.println("WARNING: Failed to adjust physical net name " + net.getName()); } } } if (parentPhysNet != null) { - // Merge both physical nets together - for (SiteInst si : new ArrayList<>(net.getSiteInsts())) { - List siteWires = new ArrayList<>(si.getSiteWiresFromNet(net)); - for (String siteWire : siteWires) { - BELPin[] pins = si.getSiteWirePins(siteWire); - si.unrouteIntraSiteNet(pins[0], pins[0]); - si.routeIntraSiteNet(parentPhysNet, pins[0], pins[0]); - } - } design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true); } } @@ -3065,38 +3169,30 @@ public static void createCeClkOfRoutethruFFToVCC(Design design) { for (SiteInst si : design.getSiteInsts()) { if (!Utils.isSLICE(si)) continue; for (BEL bel : si.getBELs()) { - if (si.getCell(bel) != null) continue; - BELPin q = bel.getPin("Q"); - if (q != null) { - Net netQ = si.getNetFromSiteWire(q.getSiteWireName()); - if (netQ == null) continue; - BELPin dPin = bel.getPin("D"); - if (dPin != null) { - Net netD = si.getNetFromSiteWire(dPin.getSiteWireName()); - if (netQ == netD) { - //System.out.println(si.getSiteName() + "/" + bel + ": " + netQ); - // Need VCC at CE - BELPin ceInput = bel.getPin("CE"); - String ceInputSitePinName = ceInput.getConnectedSitePinName(); - SitePinInst ceSitePin = si.getSitePinInst(ceInputSitePinName); - if (ceSitePin == null) { - ceSitePin = vcc.createPin(ceInputSitePinName, si); - } - si.routeIntraSiteNet(vcc, ceSitePin.getBELPin(), ceInput); - // ...and GND at CLK - BELPin clkInput = bel.getPin("CLK"); - BELPin clkInvOut = clkInput.getSourcePin(); - si.routeIntraSiteNet(gnd, clkInvOut, clkInput); - BELPin clkInvIn = clkInvOut.getBEL().getPin(0); - String clkInputSitePinName = clkInvIn.getConnectedSitePinName(); - SitePinInst clkInputSitePin = si.getSitePinInst(clkInputSitePinName); - if (clkInputSitePin == null) { - clkInputSitePin = vcc.createPin(clkInputSitePinName, si); - } - si.routeIntraSiteNet(vcc, clkInputSitePin.getBELPin(), clkInvIn); - } - } + Cell cell = si.getCell(bel); + if (cell == null || !cell.isFFRoutethruCell()) { + continue; + } + + // Need VCC at CE + BELPin ceInput = bel.getPin("CE"); + String ceInputSitePinName = ceInput.getConnectedSitePinName(); + SitePinInst ceSitePin = si.getSitePinInst(ceInputSitePinName); + if (ceSitePin == null) { + ceSitePin = vcc.createPin(ceInputSitePinName, si); + } + si.routeIntraSiteNet(vcc, ceSitePin.getBELPin(), ceInput); + // ...and GND at CLK + BELPin clkInput = bel.getPin("CLK"); + BELPin clkInvOut = clkInput.getSourcePin(); + si.routeIntraSiteNet(gnd, clkInvOut, clkInput); + BELPin clkInvIn = clkInvOut.getBEL().getPin(0); + String clkInputSitePinName = clkInvIn.getConnectedSitePinName(); + SitePinInst clkInputSitePin = si.getSitePinInst(clkInputSitePinName); + if (clkInputSitePin == null) { + clkInputSitePin = vcc.createPin(clkInputSitePinName, si); } + si.routeIntraSiteNet(vcc, clkInputSitePin.getBELPin(), clkInvIn); } } } @@ -3258,6 +3354,7 @@ private static boolean isUnisimFlipFlopType(String cellType) { return unisimFlipFlopTypes.contains(cellType); } + /** Mapping from device Series to another mapping from FF BEL name to CKEN/SRST site pin name **/ static public final Map>> belTypeSitePinNameMapping; static{ belTypeSitePinNameMapping = new EnumMap(Series.class); @@ -3325,8 +3422,21 @@ private static boolean isUnisimFlipFlopType(String cellType) { public static List getConnectionPIPs(SitePinInst sinkPin) { if (sinkPin.isOutPin() || sinkPin.getNet() == null) return Collections.emptyList(); Map reverseNodeToPIPMap = new HashMap<>(); + List biDirs = null; for (PIP p : sinkPin.getNet().getPIPs()) { - reverseNodeToPIPMap.put(p.getEndNode(), p); + PIP collision = reverseNodeToPIPMap.put(p.getEndNode(), p); + if (collision != null) { + if (p.isBidirectional()) { + // Put back the original if trying to add a bi-directional PIP + reverseNodeToPIPMap.put(collision.getEndNode(), collision); + } + } + if (p.isBidirectional()) { + if (biDirs == null) { + biDirs = new ArrayList<>(1); + } + biDirs.add(p); + } } Node sinkNode = sinkPin.getConnectedNode(); @@ -3334,8 +3444,17 @@ public static List getConnectionPIPs(SitePinInst sinkPin) { Node curr = sinkNode; List path = new ArrayList<>(); - while (!curr.equals(srcNode)) { + loop: while (!curr.equals(srcNode)) { PIP pip = reverseNodeToPIPMap.get(curr); + if (pip == null) { + for (PIP biDirPIP : biDirs) { + if (biDirPIP.getStartNode().equals(curr)) { + path.add(biDirPIP); + curr = biDirPIP.getEndNode(); + continue loop; + } + } + } path.add(pip); curr = pip.getStartNode(); } @@ -3832,21 +3951,34 @@ public static Boolean isUltraScaleSliceTop(BEL bel) { /** * 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. + * placed in it. It also detects unroutable situations on flip flop inputs and + * inserts LUT1-routethrus into the netlist. It will also add PROHIBIT + * constraints onto flip flop sites that are unroutable. 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) { + public static void prepareShellBlackBoxForRouting(Design design) { List bels = new ArrayList<>(); + // Keep track of used nodes to detect unroutable situations + Set used = new HashSet<>(); + Set routedTiles = new HashSet(); + for (Net net : design.getNets()) { + for (PIP p : net.getPIPs()) { + routedTiles.add(p.getTile()); + used.add(p.getStartNode()); + used.add(p.getEndNode()); + } + } + for (SiteInst si : design.getSiteInsts()) { if (!Utils.isSLICE(si)) continue; boolean bottomUsed = false; boolean topUsed = false; - for (Cell c : si.getCells()) { + for (Cell c : new ArrayList<>(si.getCells())) { Boolean sliceHalf = isUltraScaleSliceTop(c.getBEL()); if (sliceHalf != null) { if (sliceHalf) { @@ -3855,47 +3987,131 @@ public static void prohibitPartialHalfSlices(Design design) { bottomUsed = true; } } + if (c.getBEL().isFF()) { + if(c.getName().equals(PhysNetlistWriter.LOCKED)) continue; + String belName = c.getBELName(); + char letter = belName.charAt(0); + boolean isFF2 = belName.charAt(belName.length() - 1) == '2'; + String sitePinName = letter + (isFF2 ? "_I" : "X"); + Node n = si.getSite().getConnectedNode(sitePinName); + if (used.contains(n)) { + if (si.getCell(letter + "6LUT") == null && si.getCell(letter + "5LUT") == null) { + // Add a 'user-routethru' cell to make input path available + BELPin input = c.getBEL().getPin("D"); + Net net = si.getNetFromSiteWire(input.getSiteWireName()); + if (net == null) { + EDIFHierCellInst inst = c.getEDIFHierCellInst(); + if (inst != null) { + EDIFHierPortInst portInst = inst.getPortInst("D"); + if (portInst != null) { + EDIFHierNet logNet = portInst.getHierarchicalNet(); + if (logNet != null) { + net = design.createNet(logNet); + } + } + } + } + if (net != null) { + SitePinInst spi = si.getSitePinInst(sitePinName); + if (spi == null || (spi != null && !spi.getNet().equals(net))) { + BELPin lutInput = si.getBEL(letter + "6LUT").getPin("A6"); + EDIFHierPortInst ffInput = c.getEDIFHierCellInst().getPortInst("D"); + Cell lut1 = ECOTools.createAndPlaceInlineCellOnInputPin(design, ffInput, + Unisim.LUT1, + si.getSite(), lutInput.getBEL(), "I0", "O"); + lut1.addProperty("INIT", "2'h1"); + } + } + } else { + BELPin muxOutput = c.getBEL().getPin("D").getSourcePin(); + SitePIP sitePIP = si.getUsedSitePIP(muxOutput); + if (sitePIP == null) { + System.err.println( + "ERROR: Unable to insert a LUT1 routethru to route an input path for the FF " + + c.getName() + " placed on " + si.getSiteName() + "/" + belName); + } + } + } + } } + 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()); + continue; + } + } + if (bel.isFF()) { + // check if the FF BEL output is routable, if not prohibit it from being used + if (isFFQOutputBlocked(si.getSite(), bel, used)) { + bels.add(si.getSiteName() + "/" + bel.getName()); + } + } + } + } + } + + // Check unused SLICEs FF outputs for unroutable situations and prohibit if + // needed + for (Tile tile : routedTiles) { + Tile left = tile.getTileNeighbor(-1, 0); + Tile right = tile.getTileNeighbor(1, 0); + for (Tile neighbor : Arrays.asList(left, right)) { + if (neighbor != null && Utils.isCLB(neighbor.getTileTypeEnum())) { + Site slice = neighbor.getSites()[0]; + if (design.getSiteInstFromSite(slice) == null) { + for (BEL bel : slice.getBELs()) { + if (bel.isFF() && isFFQOutputBlocked(slice, bel, used)) { + bels.add(slice.getName() + "/" + bel.getName()); + } } } } } } + addProhibitConstraint(design, bels); } + private static boolean isFFQOutputBlocked(Site site, BEL bel, Set used) { + String sitePinName = bel.getPin("Q").getConnectedSitePinName(); + Node n = site.getConnectedNode(sitePinName); + boolean blocked = true; + for (Node n2 : n.getAllDownhillNodes()) { + if (!used.contains(n2)) { + blocked = false; + break; + } + } + return blocked; + } + /** * 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 - * '/'. + * {@literal '/'}. */ 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(" "); - } + for (String bel : belLocations) { design.addXDCConstraint(ConstraintGroup.LATE, - "set_property PROHIBIT true [get_bels { " + sb.toString() + "} ]"); + "set_property PROHIBIT true [get_bels { " + bel + "} ]"); + } } /** - * 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 + * Update the SitePinInst.isRouted() value of all pins on the given + * Net. A sink 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. + * A source pin will be marked as being routed if it drives at least one PIP. * @param net Net on which pins are to be updated. */ public static void updatePinsIsRouted(Net net) { @@ -3908,7 +4124,6 @@ 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(); @@ -3916,8 +4131,6 @@ public static void updatePinsIsRouted(Net net) { 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); } @@ -3932,13 +4145,13 @@ public static void updatePinsIsRouted(Net net) { for (SitePinInst spi : net.getPins()) { Node node = spi.getConnectedNode(); if (spi.isOutPin()) { - queue.add(node); - - if (node2fanout.get(spi.getConnectedNode()) == null) { + if (node2fanout.get(node) == null) { + // Skip source pins with no fanout continue; } + queue.add(node); } - node2spi.put(spi.getConnectedNode(), spi); + node2spi.put(node, spi); } while (!queue.isEmpty()) { @@ -3948,16 +4161,9 @@ public static void updatePinsIsRouted(Net net) { spi.setRouted(true); } - List fanouts = node2fanout.get(node); + List fanouts = node2fanout.remove(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); - } + queue.addAll(fanouts); } } } @@ -3967,9 +4173,6 @@ public static void updatePinsIsRouted(Net net) { * @param d The design that contains the complete logical netlist and where the physical nets will be created. */ public static void createPhysNetsFromLogical(Design d) { - EDIFNet gnd = EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()); - EDIFNet vcc = EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()); - // Iterate through all canonical nets Map parentNetMap = d.getNetlist().getParentNetMap(); for (EDIFHierNet n : parentNetMap.values()) { @@ -3988,9 +4191,9 @@ public static List createPhysNetFromLogical(Design d, EDIFHierNet e if (d.getNet(edifNet.getHierarchicalNetName()) != null) return null; Net net; //create physical net - if (edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.GND, d.getTopEDIFCell(), d.getNetlist()))) { + if (edifNet.getNet().isGND()) { net = d.getGndNet(); - } else if (edifNet.getNet().equals(EDIFTools.getStaticNet(NetType.VCC, d.getTopEDIFCell(), d.getNetlist()))) { + } else if (edifNet.getNet().isVCC()) { net = d.getVccNet(); } else { net = d.createNet(edifNet); @@ -4005,7 +4208,8 @@ public static List createPhysNetFromLogical(Design d, EDIFHierNet e break; } } - + assert(srcPort != null); + // Get cell connected to port inst Cell srcCell = d.getCell(srcPort.getFullHierarchicalInstName()); @@ -4013,7 +4217,7 @@ public static List createPhysNetFromLogical(Design d, EDIFHierNet e List sitePins = new ArrayList<>(); for (EDIFHierPortInst hierPortInst: d.getNetlist().getPhysicalPins(edifNet)) { EDIFPortInst portInst = hierPortInst.getPortInst(); - if (portInst.equals(srcPort)) continue; + if (portInst.equals(srcPort.getPortInst())) continue; EDIFCellInst cellInst = portInst.getCellInst(); Cell cell = cellInst == null ? null : d.getCell(cellInst.getName()); @@ -4046,8 +4250,7 @@ public static boolean isIntraSiteConnection(Cell srcCell, EDIFPortInst srcPort, queue.add(srcCell.getBELPin(srcPort)); BELPin dstPin = dstCell.getBELPin(dstPort); while (!queue.isEmpty()) { - ArrayList conns = queue.poll().getSiteConns(); - for (BELPin pin : conns) { + for (BELPin pin : queue.poll().getSiteConns()) { if (pin.equals(dstPin)) { return true; }