The purpose of this assignment is to get some basic experience using RapidWright (https://www.rapidwright.io/), a (mostly) open-source Java tool that provides you with a programming interface to Vivado designs. RapidWright contains it’s own Java classes to represent Xilinx FPGA devices, netlists, and how a netlist is implemented on the FPGA device. RapidWright interacts with Vivado through Xilinx checkpoint (.dcp) files. You can create designs in Vivado, export them to a checkpoint and import them into RapidWright for analysis or modifications. The reverse process is also possible.

In this exercise you will create a checkpoint in Vivado, import it into RapidWright, and then do some simple analysis on the Device and the Design. You will write some code to determine a distribution of how far nets travel on the FPGA, and how many programmable connections they pass through.

Python API

Although RapidWright is written in Java (available at https://github.com/Xilinx/RapidWright), it is possible to access the Java classes and methods directly from Python, using the JPype tool. Setting up this environment takes only a few minutes, and instructions are provided here.

If you prefer to use Java that’s fine too.

Here’s a very basic Python script that opens a design and prints the number of cells and nets (assuming you have downloaded rapidwright-2021.2.1-standalone-lin64.jar):

import jpype
import jpype.imports
from jpype.types import *


from com.xilinx.rapidwright.design import Design

def main():
    d = Design.readCheckpoint("design.dcp", "design.edf")

    print("Number of Cells:", len(d.getCells()))
    print("Number of Nets:", len(d.getNets()))

if __name__ == "__main__":

When I run this, I get output like this:

==                         Reading DCP: design.dcp                          ==
Loading device from file xc7a200tsbg484-1
 XML Parse & Device Load:     0.475s
              EDIF Parse:     0.448s
        Read XDEF Header:     0.014s
        Read XDEF Caches:     0.023s
     Read XDEF Placement:     0.295s
INFO: Building uncommon Wire->Node cache...
      This might take a few seconds for large devices on the first call.  
      It is generally triggered when getting the Node from an uncommon Wire object.  
      To avoid printing this message, set Device.QUIET_MESSAGE=true or set the ENVIRONMENT variable RW_QUIET_MESSAGE=1.
INFO: Finished building uncommon Wire->Node cache
       Read XDEF Routing:     1.325s
         [No GC] *Total*:     2.581s
Number of Cells: 10185
Number of Nets: 11829


The documentation for the various RapidWright classes can be found at https://www.rapidwright.io/javadoc/.

Here are a few classes you will need (and probably others not listed here):


Generate Design

You should create a design in Vivado that you will import into RapidWright. You are free to use a design of your choosing. If you aren’t sure how to create a design in Vivado, please reach out to the instructor. Try and choose a design that isn’t too small (at least a few thousand LUTs).

In Vivado you should perform Implementation, and then export both an EDIF netlist (you can do this using write_edif) and a checkpoint (using write_checkpoint).

Make sure you can import your design into RapidWright and can print the number of Cells and Nets.

Device Exploration

Write some code that outputs the device name and number of LUTs in the device. There are different ways to do this. Don’t worry too much about whether you get the exact number correct, just try and explore the Device classes and come up with a method that seems to work.

Net Distances

Calculate and plot a histogram of distances from source to sink for all Nets. For nets with fanout, find the distance to the furthest sink.

  • Use Manhattan distance.
  • Some nets are contained entirely within a Tile and do not require intertile routing. For these nets, the getSource() function will return null/None and you can count them as 0 distance.
  • It doesn’t matter what units you use for these distances, as long as you are consistent. I used the getRow() and getColumn() functions in the Tile class, but there are other coordinate systems you could use.
  • Supposing you store the distances in a dictionary where the key is the distance and the value is the number of nets with that distance, you can use matplotlib to create a simple bar graph like so:

      plt.bar(distances.keys(), distances.values(), 1.0, color="g")

Net PIP Hops

Calculate and plot a histogram of the number of PIPs a Net traverses through from source to sink (PIPs are programmable interconnect points that connect the wires in the FPGA). For nets with fanout, calculate the maximum number of PIPs from source to any sink.

  • This is a bit harder that it sounds at first, as RapidWright does not supply this information directly. You can call Net->getPIPs(), but this returns a flattened list of all PIPs for the net, and does not represent the actual tree structure that a multi-sink net would have.
  • For example, consider this picture below showing a single Net that connects to three different sink pins. There are six total PIPs that are used to route the net, but you would count this net as having three PIP hops from source to furthest sink.
  • In the picture above, the wire segments connect between tile pins and PIPs, and between PIPs and other PIPs, and are represented in the Node class in RapidWright.
  • net.getSource().getConnectedNode() will give you the Node that the source pin connects to.
  • For PIPs, getStartNode() and getEndNote() will give you the wire segments (Nodes) that the PIP connects.
  • With this information and a bit of code, you can take the PIP list and figure out the maximum number of PIPs a net traverses through.


Write a very brief report that includes:

  • Describe what circuit you used.
  • What is the device name and number of LUTs?
  • How many Cells and Nets?
  • Include your two histograms. Send your report and code to jgoeders@byu.edu with the subject: 629 Exercise 2