In this Jupyter notebook tutorial, we illustrate how to:
Vivado provides an integrated logic analyzer (ILA) IP for providing debugging and visibility into implemented FPGA designs. The user attaches probes to existing nets in the synthesized design to observe them at runtime. Vivado offers a path to change the probes after place and route (see Vivado ECO Flow, p.153). In many cases, this is the recommended path. However, there are two scenarios where RapidWright may offer a valuable alternative:
RapidWright's ProbeRouter
mitigates these issues by providing a non-invasive un-route/re-route option and by leveraging RapidWright's speed and agility in modifying a design. The ProbeRouter
will only un-route the branch segment of a net that leads to the probe and leave all other routing intact. This is designed with minimal impact to the timing characteristics of the design.
To begin, this tutorial starts with an already placed and routed design that has already been instrumented with an ILA. We can go ahead and load the DCP in the code cell below:
# Get our imports loaded for this session
import os
import subprocess
from com.xilinx.rapidwright.debug import ProbeRouter
from com.xilinx.rapidwright.design import Design
from com.xilinx.rapidwright.util import FileTools
from java.util import Collections
from java.util import HashMap
from pprint import pprint
# read our checkpoint and keep a handle to the design
design = Design.readCheckpoint("microblaze_with_ila_routed.dcp")
# create an empty Java HashMap (to pass as a parameter later)
probesMap = HashMap()
# keep a handle to our EDIF Netlist
netlist = design.getNetlist()
print "Finished loading our design!"
If we don't know where the ILA is located in the netlist, the ProbeRouter
has a built in API that can search for it in the hierarchy:
ProbeRouter.findILAs(design)
Once we have selected an ILA (there could be more than one in the design), we can query it for its available probes.
netlist.getCellInstFromHierName("u_ila_0").getCellPorts()
If we are curious as to what that probe is currently connected to, we can query the probe's net and/or get all of its net aliases:
# Get the net connected to the probe port instance
net = netlist.getCellInstFromHierName("u_ila_0").getPortInst("probe0[4]").getNet()
# Method to traverse netlist and extract net aliases from the netlist
netAliases = netlist.getNetAliases(net.getName())
# Extra Python code to print the net and aliases
Collections.sort(netAliases)
print "Connected net = '" + str(net) + "'\\n"
print "Net aliases ="
pprint([x.encode('ascii') for x in netAliases])
We can compare this result with the same design loaded in Vivado and can see the full schematic view below:
*OPTIONAL:* To see this schematic view in Vivado, do the following:
Run these commands in Tcl:
open_checkpoint "<path_to_your_copy>/microblaze_with_ila_routed.dcp"
select_objects [get_nets 'u_ila_0_microblaze_0_axi_periph_M01_AXI_AWADDR[4]']
Then in the GUI, press
F4
to load the net into the schematic view
Right click on the blue highlighted net, chooseExpand Cone
->To Leaf Cells
You may need to zoom out (Ctrl+Minus
key) to position it properly
Suppose we want to change this probe's connect to another net, we can tell the ProbeRouter
to re-route the probe to another net such as "base_mb_i/axi_uartlite_0/U0/AXI_LITE_IPIF_I/I_SLAVE_ATTACHMENT/bus2ip_rnw_i":
# Probe input name -> Desired net name to debug
probesMap.put("u_ila_0/probe0[4]", "base_mb_i/axi_uartlite_0/U0/AXI_LITE_IPIF_I/I_SLAVE_ATTACHMENT/bus2ip_rnw_i")
# Invoke the probe re-router to un-route existing connection, route to net(s) specified
ProbeRouter.updateProbeConnections(design,probesMap)
outputFileName = "microblaze_updated_probe.dcp"
design.writeCheckpoint(outputFileName)
print "Wrote Probe re-routed DCP to: '" + os.path.join(os.getcwd(), outputFileName) + "'"
If Vivado isn't already open, we can open our probe-re-routed-design by running the code cell below:
if FileTools.isWindows():
os.system("START /B vivado " + outputFileName)
else:
os.system("vivado "+outputFileName+" &")
print "If vivado fails to open or load, you could run the following command:"
print ""
print " 'vivado " + os.path.join(os.getcwd(), outputFileName) + "'"
While Vivado is loading, we can re-run the code from above to examine the probe's new connectivity:
# Get the net connected to the probe port instance
net = netlist.getCellInstFromHierName("u_ila_0").getPortInst("probe0[4]").getNet()
# Method to traverse netlist and extract net aliases from the netlist
netAliases = netlist.getNetAliases(net.getName())
# Extra Python code to print the net and aliases
Collections.sort(netAliases)
print "Connected net = '" + str(net) + "'\\n"
print "Net aliases ="
pprint([x.encode('ascii') for x in netAliases])
Once Vivado opens our probe re-routed design (microblaze_updated_probe.dcp
) in Vivado, we can confirm the newly routed connectivity from the results above. Here is a screenshot from our Vivado view of the new probed net for comparison:
Use Vivado to choose some nets of your own to probe and add them to the probesMap
above.
Try comparing an existing probed routed net with the net after the probe has been removed (you'll need to open both DCPs in Vivado). Does the remaining part of the route stay intact?
*HINT:*
To compare the routing of two nets visually, you may want to highlight it. Follow these steps:
- Open one of the DCPs in the Vivado GUI
- Open the Device window if it is not already open (
Window->Device
)- Select the net with the Tcl command:
select_objects [get_nets <net_name>]
- Right click on the selected net in the Device window and choose
Highlight->(choose a color)
- You can also mark pins by choosing the
Cell Pins
tab in theNet Properties
window by right clicking on a pin and choosingMark->(choose a color)
. A mark will stay visible at any zoom level.Here is an example comparison: