Print Compiled Hierarchy
This example walks through a simple program that:
Compiles one or more RDL files provided from the command line
Elaborates the design register model
Uses the walker/listener traversal method to print a hierarchical text representation of the register model
The full example code can be found in the systemrdl-compiler
repository at:
examples/print_hierarchy.py
Walkthrough
First, a few classes are imported, and a list of requested input files collected from the command line arguments.
import sys
import os
from systemrdl import RDLCompiler, RDLCompileError, RDLWalker
# Collect input files from the command line arguments
input_files = sys.argv[1:]
Next, an instance of the compiler object is created. This represents a single compilation scope.
# Create an instance of the compiler
rdlc = RDLCompiler()
All the input files are compiled into the root scope, and then elaborated.
Since no top-level component name was specified in the elaborate
call, the
last addrmap
component definition is automatically chosen.
If the RDL file contains any syntax or semantic errors, the compile and
elaborate steps will raise an RDLCompileError
exception. It
is recommended to wrap this in a try/except block.
try:
# Compile all the files provided
for input_file in input_files:
rdlc.compile_file(input_file)
# Elaborate the design
root = rdlc.elaborate()
except RDLCompileError:
# A compilation error occurred. Exit with error code
sys.exit(1)
For this example, we want to print out some information about the register
model. This listener class defines callbacks that will output an indented tree
view of the register model. For field
components, some additional
information is printed about the bit range, and software access policy.
from systemrdl import RDLListener
from systemrdl.node import FieldNode
# Define a listener that will print out the register model hierarchy
class MyModelPrintingListener(RDLListener):
def __init__(self):
self.indent = 0
def enter_Component(self, node):
if not isinstance(node, FieldNode):
print("\t"*self.indent, node.get_path_segment())
self.indent += 1
def enter_Field(self, node):
# Print some stuff about the field
bit_range_str = "[%d:%d]" % (node.high, node.low)
sw_access_str = "sw=%s" % node.get_property('sw').name
print("\t"*self.indent, bit_range_str, node.get_path_segment(), sw_access_str)
def exit_Component(self, node):
if not isinstance(node, FieldNode):
self.indent -= 1
Finally, the walker is created, and is used to traverse the elaborated register model. At each node, the listener callbacks are executed.
# Traverse the register model!
walker = RDLWalker(unroll=True)
listener = MyModelPrintingListener()
walker.walk(root, listener)
Output
Below is the example’s output if it is run with the SPI controller RDL file:
$ cd examples/
$ print_hierarchy.py atxmega_spi.rdl
atxmega_spi
CTRL
[1:0] PRESCALER sw=rw
[3:2] MODE sw=rw
[4:4] MASTER sw=rw
[5:5] DORD sw=rw
[6:6] ENABLE sw=rw
[7:7] CLK2X sw=rw
INTCTRL
[1:0] INTLVL sw=rw
STATUS
[6:6] WRCOL sw=r
[7:7] IF sw=r
DATA
[7:0] WDATA sw=w
[7:0] RDATA sw=r