Skip to content
Draft
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
111 changes: 111 additions & 0 deletions src/com/xilinx/rapidwright/examples/PrintVersalTimingPaths.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2026, Advanced Micro Devices, Inc.
* All rights reserved.
*
* 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.util.List;

import org.jgrapht.GraphPath;
import org.jgrapht.alg.shortestpath.KShortestSimplePaths;

import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.Net;
import com.xilinx.rapidwright.device.Node;
import com.xilinx.rapidwright.device.PIP;
import com.xilinx.rapidwright.timing.TimingEdge;
import com.xilinx.rapidwright.timing.TimingGraph;
import com.xilinx.rapidwright.timing.TimingManager;
import com.xilinx.rapidwright.timing.TimingVertex;

/**
* Loads a placed/routed DCP, builds a TimingGraph (topology-only mode on Versal),
* enumerates K simple paths between the super-source and super-sink, and prints
* each path's hierarchical pin sequence along with the carrying net's PIPs.
*
* Usage: PrintVersalTimingPaths [dcp] [numPaths]
* default dcp: test/RapidWrightDCP/picoblaze_2022.2.dcp
* default numPaths: 100
*/
public class PrintVersalTimingPaths {

public static void main(String[] args) {
String dcp = args.length > 0
? args[0]
: "test/RapidWrightDCP/picoblaze_2022.2.dcp";
int k = args.length > 1 ? Integer.parseInt(args[1]) : 100;

Design design = Design.readCheckpoint(dcp);

// On Versal this drops into topology-only mode automatically (delays = 0,
// structure intact). TimingManager.postBuild() has already wired
// superSource -> FF outputs and FF inputs -> superSink.
TimingManager tm = new TimingManager(design);
TimingGraph tg = tm.getTimingGraph();

// Enumerate K simple paths between the super-source and super-sink.
// (TimingGraph.buildGraphPaths(N) currently only returns one Bellman-Ford
// path regardless of N; calling KShortestSimplePaths directly is the
// clean way to get many paths.)
KShortestSimplePaths<TimingVertex, TimingEdge> kSP = new KShortestSimplePaths<>(tg);
List<GraphPath<TimingVertex, TimingEdge>> paths =
kSP.getPaths(tg.superSource, tg.superSink, k);

System.out.println("Enumerated " + paths.size() + " path(s).\n");

int idx = 0;
for (GraphPath<TimingVertex, TimingEdge> path : paths) {
List<TimingEdge> edges = path.getEdgeList();
System.out.println("=== Path #" + (idx++) + " (" + edges.size() + " edges) ===");

for (TimingEdge e : edges) {
TimingVertex src = e.getSrc();
TimingVertex dst = e.getDst();

// Skip the super-source / super-sink connector edges.
if ("superSource".equals(src.getName())) continue;
if ("superSink".equals(dst.getName())) continue;

System.out.println(" " + src.getName() + " -> " + dst.getName());

if (e.getFirstPin() != null) {
System.out.println(" src SitePin: " + e.getFirstPin()
+ " tile=" + e.getFirstPin().getTile());
}
if (e.getSecondPin() != null) {
System.out.println(" dst SitePin: " + e.getSecondPin()
+ " tile=" + e.getSecondPin().getTile());
}

Net net = e.getNet();
if (net != null && net.hasPIPs()) {
System.out.println(" net: " + net.getName()
+ " (" + net.getPIPs().size() + " PIPs)");
for (PIP pip : net.getPIPs()) {
Node s = pip.getStartNode();
Node t = pip.getEndNode();
System.out.println(" " + pip.getTile()
+ ": " + s + " [" + s.getIntentCode() + "]"
+ " -> " + t + " [" + t.getIntentCode() + "]");
}
}
}
System.out.println();
}
}
}
44 changes: 21 additions & 23 deletions src/com/xilinx/rapidwright/timing/DelayModelBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.xilinx.rapidwright.util.FileTools;

/**
* Build a delay model.
Expand All @@ -53,42 +57,36 @@ class DelayModelBuilder {
*/
private static String[] valid_source = {"text"};

private static DelayModel aModel = null;
private static final Map<String, DelayModel> models = new ConcurrentHashMap<>();

/**
* Prepare the appropriate input file for {@link #getDelayModel(String, String, String)}
* Returns the cached DelayModel for a series, constructing it on first access.
* When no intrasite_delay_terms.txt ships for the series (e.g., Versal), a
* topology-only NullDelayModel is returned so TimingGraph can still build a
* structural graph.
*/
public static DelayModel getDelayModel(String series) {
String fileName = TimingModel.TIMING_DATA_DIR + File.separator +series+
File.separator + "intrasite_delay_terms.txt";
return getDelayModel("small", "text", fileName);
}

/**
* The method that decides to build a new model or to return the existing one.
* Please see the method newDelayModel for parameters' description.
*/
private static DelayModel getDelayModel(String mode, String source, String fileName) {
if (aModel == null) {
synchronized (DelayModelBuilder.class) {
if (aModel == null) {
newDelayModel(mode, source, fileName);
}
return models.computeIfAbsent(series, s -> {
String fileName = TimingModel.TIMING_DATA_DIR + File.separator + s
+ File.separator + "intrasite_delay_terms.txt";
File f = new File(FileTools.getRapidWrightPath() + File.separator + fileName);
if (!f.exists()) {
return NullDelayModel.INSTANCE;
}
}
return aModel;
return newDelayModel("small", "text", fileName);
});
}

/**
* The method to build DelayModel and DelayModelSource according to the given parameters.
* Build a DelayModel and DelayModelSource according to the given parameters.
* @param mode The type of delay model. It defines how data are stored which will affect
* the memory requirement and how fast the lookup is. Currently, the only valid entry is "small".
* @param source The source of delay model. Currently, the only valid entry is "text".
* @param fileName The text file describing the delay model.
* @throws IllegalArgumentException This method throw IllegalArgumentException if the fileName
* @throws IllegalArgumentException This method throws IllegalArgumentException if the fileName
* does not exist.
*/
private static void newDelayModel(String mode, String source, String fileName) {
private static DelayModel newDelayModel(String mode, String source, String fileName) {
DelayModelSource src;
if (source.equalsIgnoreCase(valid_source[0])) {
src = new DelayModelSourceFromText(fileName);
Expand All @@ -97,7 +95,7 @@ private static void newDelayModel(String mode, String source, String fileName) {
}

if (mode.equalsIgnoreCase(valid_mode[0])) {
aModel = new SmallDelayModel(src);
return new SmallDelayModel(src);
} else {
throw new IllegalArgumentException("DelayModelBuilder: Unknown mode to newDelayModel.");
}
Expand Down
60 changes: 60 additions & 0 deletions src/com/xilinx/rapidwright/timing/NullDelayModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2026, Advanced Micro Devices, Inc.
* All rights reserved.
*
* 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.timing;

import com.xilinx.rapidwright.device.SiteTypeEnum;

/**
* Topology-only fallback DelayModel used when no per-series delay data ships
* for the device (e.g., Versal). Returns zero for every lookup so that
* TimingGraph can still build the structural graph; callers are expected to
* overwrite delays via TimingEdge.set*Delay(...) if accurate timing is needed.
*/
class NullDelayModel implements DelayModel {

static final NullDelayModel INSTANCE = new NullDelayModel();

private NullDelayModel() {}

@Override
public Short getIntraSiteDelay(SiteTypeEnum siteTypeName, String frBelPin, String toBelPin) {
return 0;
}

@Override
public short getLogicDelay(short belIdx, String frBelPin, String toBelPin, int encodedConfig) {
return 0;
}

@Override
public short getLogicDelay(short belIdx, String frBelPin, String toBelPin) {
return 0;
}

@Override
public int getEncodedConfigCode(String value) {
return 0;
}

@Override
public short getBELIndex(String belName) {
return 0;
}
}
Loading
Loading