Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .classpath
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
<classpathentry kind="lib" path="jars/kryo-5.2.1.jar"/>
<classpathentry kind="lib" path="jars/minlog-1.3.1.jar"/>
<classpathentry kind="lib" path="jars/jython-standalone-2.7.2.jar"/>
<classpathentry kind="lib" path="jars/rapidwright-api-lib-2025.2.1.jar">
<classpathentry kind="lib" path="jars/rapidwright-api-lib-2025.2.2.jar">
<attributes>
<attribute name="javadoc_location" value="jar:platform:/resource/RapidWright/jars/rapidwright-api-lib-2025.2.1-javadoc.jar!/"/>
<attribute name="javadoc_location" value="jar:platform:/resource/RapidWright/jars/rapidwright-api-lib-2025.2.2-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="jars/jgrapht-core-1.3.0.jar"/>
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
pull_request:

env:
RAPIDWRIGHT_VERSION: v2025.2.1-beta
RAPIDWRIGHT_VERSION: v2025.2.2-beta


jobs:
Expand Down
23 changes: 23 additions & 0 deletions RELEASE_NOTES.TXT
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
============= RapidWright 2025.2.2-beta released on 2026-06-04 ================
Notes:
- [Params] Adds parameters to control how readable EDIF is extracted when DCP is loaded (#1374)
- Enable {dis,}connectNet() to operate on macro port insts (#1367)
- Array Builder Tool - Replicate Optimized Kernels in an Array (#1163)
- [RWRoute] On Versal, preserve node uphill of sink SPIs (#1369)
- [Clock Routing]Fix isse related to Versal clock routing to NoC sinks (#1370)
- Add test case for fixes to getCorrespondingTile when called on certain SLL tiles (#1360)
- Correctly handle NOC clock pins when routing (#1365)
- Fix IBUF creation for UltraScale+ (#1357)
- [DesignTools] Fix NPE in fullyUnplaceCell() (#1358)
- [PathExtractor] Fix unconnected static inputs (#1352)
- Auto extract readable EDIFs from DCPs to enable parallel parsing
- Fix create IOB on UltraScale+
- Fixes to allow Vivado 2025.2 designs with NOC components to be loaded in RapidWright
- Fixes for site routing
- Adds several missing IDCodes for UltraScale+ parts
- Fix SLL module relocation for Versal

API Additions:
- com.xilinx.rapidwright.design.noc.NOCDesign "public void clearSolution()"


============= RapidWright 2025.2.1-beta released on 2026-02-18 ================
Notes:
- Fixes Issues with PathExtractor#1350
Expand Down
2 changes: 2 additions & 0 deletions src/com/xilinx/rapidwright/MainEntrypoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.xilinx.rapidwright.design.blocks.PBlockGenerator;
import com.xilinx.rapidwright.design.compare.DesignComparator;
import com.xilinx.rapidwright.design.merge.MergeDesigns;
import com.xilinx.rapidwright.design.tools.ArrayBuilder;
import com.xilinx.rapidwright.design.tools.CopyImplementation;
import com.xilinx.rapidwright.design.tools.DesignObfuscator;
import com.xilinx.rapidwright.design.tools.LUTTools;
Expand Down Expand Up @@ -136,6 +137,7 @@ private static void addFunction(String name, MainStyleFunction<?> func) {

static {
addFunction("AddSubGenerator", AddSubGenerator::main);
addFunction("ArrayBuilder", ArrayBuilder::main);
addFunction("BlockCreator", BlockCreator::main);
addFunction("BlockStitcher", BlockStitcher::main);
addFunction("BlockUpdater", BlockUpdater::main);
Expand Down
102 changes: 102 additions & 0 deletions src/com/xilinx/rapidwright/design/ClockTools.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
*
* Copyright (c) 2025, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Author: Chris Lavin, AMD Advanced Research and Development.
*
* This file is part of RapidWright.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.xilinx.rapidwright.design;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.xilinx.rapidwright.edif.EDIFHierCellInst;
import com.xilinx.rapidwright.edif.EDIFHierNet;
import com.xilinx.rapidwright.edif.EDIFHierPortInst;
import com.xilinx.rapidwright.edif.EDIFNetlist;

public class ClockTools {

public static Map<String, String> unisimFFs;

public static Map<String, String> unisimLatches;

public static Map<String, String> clbRegTypes;

static {
unisimFFs = new HashMap<>();
unisimFFs.put("FDRE", "C");
unisimFFs.put("FDSE", "C");
unisimFFs.put("FDCE", "C");
unisimFFs.put("FDPE", "C");

unisimLatches = new HashMap<>();
unisimLatches.put("LDCE", "G");
unisimLatches.put("LDPE", "G");

clbRegTypes = new HashMap<>();
clbRegTypes.putAll(unisimFFs);
clbRegTypes.putAll(unisimLatches);
}

/**
* If the provided instance is a CLB register (flip-flop or latch), it will get
* the net of the connected net to the clock pin of the cell and return it.
*
* @param i The instance in question.
* @return The clock net connected to this instance's clock pin, or null if none
* is found.
*/
public static EDIFHierNet getClockNet(EDIFHierCellInst i) {
String clkInput = clbRegTypes.get(i.getCellName());
EDIFHierPortInst portInst = clkInput != null ? i.getPortInst(clkInput) : null;
return portInst != null ? portInst.getHierarchicalNet() : null;
}

/**
* Gets the clock net from the provided design. If the design has more than one
* net, it gets the net with the most CLB register fan out.
*
* @param design The design to query.
* @return The biggest CLB register fan out net in the design.
*/
public static EDIFHierNet getClockFromDesign(Design design) {
EDIFNetlist netlist = design.getNetlist();
Map<EDIFHierNet, Integer> clockSinkCounts = new HashMap<>();
for (EDIFHierCellInst i : netlist.getAllLeafHierCellInstances()) {
EDIFHierNet clk = ClockTools.getClockNet(i);
clk = netlist.getParentNet(clk);
if (clk != null) {
clockSinkCounts.compute(clk, (k, v) -> v == null ? 1 : 1 + v);
}
}

int largestFanout = 0;
EDIFHierNet clkLargestFanout = null;
for (Entry<EDIFHierNet, Integer> e : clockSinkCounts.entrySet()) {
if (e.getValue() > largestFanout) {
largestFanout = e.getValue();
clkLargestFanout = e.getKey();
}
}

return clkLargestFanout;
}

}
58 changes: 58 additions & 0 deletions src/com/xilinx/rapidwright/design/DesignTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -3451,6 +3451,64 @@ public static void makePhysNetNamesConsistent(Design design) {
ParallelismTools.join(futures);
}

/**
* Make a single physical Net's name consistent with its logical (EDIF) netlist.
* @param design Design containing the net
* @param net The physical Net to make consistent
* @return The parent physical Net or null if already consistent
*/
public static Net makePhysNetNameConsistent(Design design, Net net) {
if (net.isStaticNet()) {
Net staticNet = design.getStaticNet(net.getType());
if (staticNet != net) {
design.movePinsToNewNetDeleteOldNet(net, staticNet, true);
return staticNet;
}
return null;
}

EDIFHierNet hierNet = net.getLogicalHierNet();
if (hierNet == null) {
return null; // Likely an encrypted cell
}

Map<EDIFHierNet, EDIFHierNet> netParentMap = design.getNetlist().getParentNetMap();
EDIFHierNet parentHierNet = netParentMap.get(hierNet);
if (parentHierNet == null) {
return null;
}

// Check for static net aliases
EDIFNet srcNetAlias = parentHierNet.getNet();
if (srcNetAlias.isGND()) {
Net gndNet = design.getGndNet();
design.movePinsToNewNetDeleteOldNet(net, gndNet, true);
return gndNet;
} else if (srcNetAlias.isVCC()) {
Net vccNet = design.getVccNet();
design.movePinsToNewNetDeleteOldNet(net, vccNet, true);
return vccNet;
}

if (!hierNet.equals(parentHierNet)) {
String parentNetName = parentHierNet.getHierarchicalNetName();
Net parentPhysNet = design.getNet(parentNetName);

if (parentPhysNet == null) {
// No existing parent net - just rename this one
if (!net.rename(parentNetName)) {
System.out.println("WARNING: Failed to change physical net name " + net.getName());
}
} else {
// Parent net exists - merge into it
design.movePinsToNewNetDeleteOldNet(net, parentPhysNet, true);
return parentPhysNet;
}
}

return null;
}

public static void createPossiblePinsToStaticNets(Design design) {
createA1A6ToStaticNets(design);
createCeClkOfRoutethruFFToVCC(design);
Expand Down
87 changes: 87 additions & 0 deletions src/com/xilinx/rapidwright/design/NetTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@
import java.util.Set;
import java.util.function.Function;

import com.xilinx.rapidwright.design.blocks.PBlock;
import com.xilinx.rapidwright.device.IntentCode;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.PIP;
import com.xilinx.rapidwright.device.SiteTypeEnum;
import com.xilinx.rapidwright.edif.EDIFHierNet;
import com.xilinx.rapidwright.edif.EDIFPort;
import com.xilinx.rapidwright.edif.EDIFPortInst;

public class NetTools {
public static final String CONTINUE_ELBOW = "\u251c\u2500 ";
Expand Down Expand Up @@ -262,6 +266,52 @@ public static boolean hasClockSinks(Net net) {
return false;
}

/**
* Unroutes routed nets that have one or more overlapping or conflicting nodes
* with another route in the design. The choice between which of two or more
* nets gets unrouted is arbitrary and nets are unrouted until the set of routed
* nets do not overlap.
*
* @param design The design to evaluate for conflicting nodes.
* @return The list of nets that were unrouted.
*/
public static List<Net> unrouteNetsWithOverlappingNodes(Design design) {
List<Net> overlappingNets = getNetsWithOverlappingNodes(design);
for (Net net : overlappingNets) {
net.unroute();
}
return overlappingNets;
}

/**
* Returns a list of nets with overlapping nodes without unrouting them.
*
* @param design The design to evaluate for conflicting nodes.
* @return The list of nets that overlap.
*/
public static List<Net> getNetsWithOverlappingNodes(Design design) {
List<Net> overlappingNets = new ArrayList<>();
Map<Node, Net> used = new HashMap<>();
for (Net net : design.getNets()) {
for (PIP pip : net.getPIPs()) {
for (Node node : new Node[] { pip.getStartNode(), pip.getEndNode() }) {
if (node == null)
continue;
Net existing = used.putIfAbsent(node, net);
if (existing != null && existing != net) {
for (PIP oldPip : new ArrayList<>(existing.getPIPs())) {
for (Node oldNode : new Node[] { oldPip.getStartNode(), oldPip.getEndNode() }) {
used.remove(oldNode);
}
}
overlappingNets.add(existing);
}
}
}
}
return overlappingNets;
}

/**
* Returns a string representation of the net's routing tree using tree
* characters (├─, └─).
Expand Down Expand Up @@ -471,4 +521,41 @@ public static Node findClockRootVRoute(Net net) {

return deepestVRoute;
}

/**
* Unroute top-level port nets that have PIPs outside the specified PBlock. Vivado can potentially create designs
* where the top-level port nets leave the PBlock if the InlineFlopTools flop harness was used and the top-level
* port net also has a sink inside the PBlock. Physical net names must be consistent and macro unisims must be
* expanded before calling this method.
*
* @param d The design to unroute nets from.
* @param pBlock The bounding box for the placed and routed design.
*/
public static List<Net> unrouteTopLevelNetsThatLeavePBlock(Design d, PBlock pBlock) {
List<Net> unroutedNets = new ArrayList<>();
for (EDIFPort p : d.getNetlist().getTopCell().getPorts()) {
for (int i : p.getBitBlastedIndices()) {
EDIFPortInst portInst = p.getInternalPortInstFromIndex(i);
if (portInst == null) {
continue;
}
EDIFHierNet hierNet = new EDIFHierNet(d.getNetlist().getTopHierCellInst(), portInst.getNet());
EDIFHierNet parentNet = d.getNetlist().getParentNet(hierNet);
Net net = d.getNet(parentNet.getHierarchicalNetName());

boolean leavesPBlock = false;
for (PIP pip : net.getPIPs()) {
if (!pBlock.containsTile(pip.getTile())) {
leavesPBlock = true;
break;
}
}
if (leavesPBlock) {
net.unroute();
unroutedNets.add(net);
}
}
}
return unroutedNets;
}
}
Loading
Loading