Exporting and Importing Designs¶
Exporting Hardware Designs¶
- pyrtl.output_to_verilog(dest_file, add_reset=True, block=None, initialize_registers=False, module_name='toplevel')[source]¶
A function to walk the
blockand output it in Verilog format to the open file.The Verilog module will be named
toplevel, with a clock input namedclk.When possible, wires keep their names in the Verilog output. Wire names that do not satisfy Verilog’s naming requirements, and wires that conflict with Verilog keywords are given new temporary names in the Verilog output.
- Parameters:
dest_file (
IO) – Open file where the Verilog output will be written.add_reset (
bool|str, default:True) – If reset logic should be added. Allowable options are:False(meaning no reset logic is added),True(default, for adding synchronous reset logic), and'asynchronous'(for adding asynchronous reset logic). The reset input will be namedrst, and whenrstis high, registers will be reset to theirreset_value.initialize_registers (
bool, default:False) – Initialize Verilog registers to theirreset_value. When this argument isTrue, a register likeRegister(name='foo', bitwidth=8, reset_value=4)generates Verilog likereg[7:0] foo = 8'd4;.block (
Block, default:None) – Block to be walked and exported. Defaults to the working_block.module_name (
str, default:'toplevel') – name of the module. Defaults to toplevel if the user puts nothing.
Exporting Testbenches¶
- pyrtl.output_verilog_testbench(dest_file, simulation_trace=None, toplevel_include=None, vcd='waveform.vcd', cmd=None, add_reset=True, block=None, module_name='toplevel')[source]¶
Output a Verilog testbench for the block/inputs used in the simulation trace.
If
add_resetisTrue, arstinput wire is added to the instantiatedtoplevelmodule. Therstwire will be held low in the testbench, because initialization here occurs via theinitialblock.add_resetis provided for consistency withoutput_to_verilog().This function only generates the Verilog testbench. The Verilog module must be generated separately by calling
output_to_verilog(), see thetoplevel_includeparameter and Example 2 below.The test bench does not return any values.
Example 1, writing testbench to a string:
with io.StringIO() as tbfile: pyrtl.output_verilog_testbench(dest_file=tbfile, simulation_trace=sim_trace)
Example 2, testbench in same file as Verilog:
with open('hardware.v', 'w') as fp: output_to_verilog(fp) output_verilog_testbench( fp, sim.tracer, vcd=None, cmd='$display("%d", out);')
- Parameters:
dest_file (
IO) – An open file to which the test bench will be printed.simulation_trace (
SimulationTrace, default:None) – A trace from which the inputs will be extracted for inclusion in the test bench. This is typicallySimulation.tracer. The generated test bench will replay theSimulation’sInputscycle by cycle. The default values for all registers and memories will be based on the trace, otherwise they will be initialized to 0.toplevel_include (
str|None, default:None) – Name of the file containing thetoplevelmodule this testbench is testing. If notNone, anincludedirective will be added for this file.vcd (
str, default:'waveform.vcd') – By default, the testbench generator will generate a command to write the output of the testbench execution to a.vcdfile, via$dumpfile, andvcdis the name of the file to write. IfNone, then nodumpfilewill be used.cmd (
str|None, default:None) –The string passed as
cmdwill be copied verbatim into the testbench just before the end of each cycle. This is useful for doing things like printing specific values during testbench evaluation. For example:cmd='$display("%d", out);'
will instruct the testbench to print the value of
outevery cycle.add_reset (
bool|str, default:True) – If reset logic should be added. Allowable options are:False(meaning no reset logic is added),True(default, for adding synchronous reset logic), and'asynchronous'(for adding asynchronous reset logic). The value passed in here should match the argument passed tooutput_to_verilog().block (
Block, default:None) – Block containing design to test. Defaults to the working_block.module_name (
str, default:'toplevel') – Name of the module the user chooses. Defaults to toplevel if nothing is inputted.
Importing Verilog¶
- pyrtl.input_from_blif(blif, block=None, merge_io_vectors=True, clock_name='clk', top_model=None)[source]¶
Read an open BLIF file or string as input, updating the block appropriately.
If
merge_io_vectorsisTrue, then given 1-bitInputwiresa[0]anda[1], these wires will be combined into a single 2-bitInputwireathat can be accessed by nameain the block. Otherwise ifmerge_io_vectorsisFalse, the original 1-bit wires will beInputwires of the block. This holds similarly forOutput.input_from_blifassumes the following:There is only one single shared clock and reset
Output is generated by Yosys with formals in a particular order
input_from_blifcurrently supports multi-module (unflattened) BLIF, though we recommend importing a flattened BLIF with a single module when possible. It currently ignores the reset signal (which it assumes is input only to the flip flops).- Parameters:
blif – An open BLIF file to read.
block (
Block, default:None) – The block where the logic will be added. Defaults to the working_block.merge_io_vectors (
bool, default:True) – IfTrue,Input/Outputwires whose names differ only by a indexing subscript (e.g. 1-bit wiresa[0]anda[1]) will be combined into a singleInput/Output(e.g. a 2-bit wirea).clock_name (
str, default:'clk') – The name of the clock (defaults toclk).top_model (
str|None, default:None) – name of top-level model to instantiate; ifNone, defaults to first model listed in the BLIF.
- pyrtl.input_from_verilog(verilog, clock_name='clk', toplevel=None, leave_in_dir=None, block=None)[source]¶
Read an open Verilog file or string as input via Yosys conversion, updating the block.
This function is essentially a wrapper for
input_from_blif(), with the added convenience of turning the Verilog into BLIF for import for you. This function passes a set of commands to Yosys as a script that normally produces BLIF files that can be successfully imported into PyRTL viainput_from_blif().If the Yosys conversion fails, we recommend you create your own custom Yosys script to try and produce BLIF yourself. Then you can import BLIF directly via
input_from_blif().- Parameters:
verilog – An open Verilog file to read.
clock_name (
str, default:'clk') – The name of the clock (defaults to"clk").toplevel (
str|None, default:None) – Name of top-level module to instantiate; ifNone, defaults to first model defined in the Verilog file.leave_in_dir (
bool|None, default:None) – IfTrue, save the intermediate BLIF file created in the given directory.block (
Block, default:None) – The block where the logic will be added. Defaults to the working_block.
Outputting for Visualization¶
- pyrtl.output_to_trivialgraph(file, namer=<function _trivialgraph_default_namer>, block=None, split_state=False)[source]¶
Walk the block and output it in trivial graph format to the open file.
- Parameters:
file – Open file to write to.
namer (
Callable[[WireVector|LogicNet,bool],str], default:<function _trivialgraph_default_namer at 0x722a9c321c70>) – A function that takes in an object (aWireVectororLogicNet) as the first argument and a booleanis_edgeas the second that is setTrueif the object is aWireVector, and returns a string representing that object.block (
Block, default:None) –Blockto use (defaults to current working_block).split_state (
bool, default:False) – IfTrue, split connections to/from a register update net; this means that registers will be appear as source nodes of the network, andrLogicNets(i.e. the logic for settingRegister.next) will be treated as sink nodes of the network.
- pyrtl.output_to_graphviz(file, block=None, namer=<function _graphviz_default_namer>, split_state=True, maintain_arg_order=False)[source]¶
Walk the
Blockand output it in Graphviz format to the open file.output_to_graphvizwrites a file containing a directed graph in the format expected by Graphviz, specifically in the dot format. Once Graphviz is installed, the resulting graph file can be rendered to a.pdffile with:dot -Tpdf output.dot > output.pdf
- Parameters:
file – Open file to write to.
block (
Block, default:None) –Blockto use (defaults to current working_block)namer (default:
<function _graphviz_default_namer at 0x722a9c3221f0>) – Function used to label each edge and node; seeblock_to_graphviz_string()for more information.split_state (
bool, default:True) – IfTrue, visually split the connections to/from aRegisterupdate net.maintain_arg_order (
bool, default:False) – IfTrue, add ordering constraints so incoming edges are ordered left-to-right for nets where argument order matters (e.g.<). Keeping this asFalseresults in a cleaner, though less visually precise, graphical output.
- pyrtl.graphviz_detailed_namer(extra_node_info=None, extra_edge_info=None)[source]¶
Returns a detailed Graphviz namer that prints extra information about nodes/edges in the given maps.
If both
dictarguments areNone, the returned namer behaves identically to the default Graphviz namer.- Parameters:
extra_node_info (
dict|None, default:None) – Adictfrom node to additional data about that node. The additional data will be converted tostrand printed next to the node’s label.extra_edge_info (
dict|None, default:None) – Adictfrom edge to additional data about that edge. The additional data will be converted tostrand printed next to the edge’s label.
- Returns:
A function to label each element in the graph, which can be used as
output_to_graphviz()orblock_to_graphviz_string()’snamer.
- pyrtl.output_to_svg(file, block=None, split_state=True)[source]¶
Output the block as an SVG to the open file.
- Parameters:
file – Open file to write to.
block (
Block, default:None) –Blockto use (defaults to current working_block).split_state (
bool, default:True) – IfTrue, visually split the connections to/from a register update net.
- pyrtl.block_to_graphviz_string(block=None, namer=<function _graphviz_default_namer>, split_state=True, maintain_arg_order=False)[source]¶
Return a Graphviz string for the
block.The normal namer function will label user-named wires with their names and label the nodes (
LogicNetsorInput/Output/Constterminals) with their operator symbol or name/value, respectively. If custom information about each node in the graph is desired, you can pass in a custom namer function which must have the same signature as the default namer,_graphviz_default_namer().However, we recommend you instead pass in a call to
graphviz_detailed_namer(), supplying it with your owndictsmapping wires and nodes to labels. For any wire/node found in these maps, that additional information will be printed in parentheses alongside the node in thegraphvizgraph.For example, if you wanted to print the delay of each wire and the fanout of each gate, you could pass in two maps to the
graphviz_detailed_namer()call, which returns a namer function that can subsequently be passed tooutput_to_graphviz()orblock_to_graphviz_string():node_fanout = {n: f"Fanout: {my_fanout_func(n)}" for n in working_block().logic} wire_delay = {w: f"Delay: {my_delay_func(w):.2f}" for w in working_block().wirevector_set} with open("out.gv", "w") as f: output_to_graphviz( f, namer=graphviz_detailed_namer(node_fanout, wire_delay))
- Parameters:
namer (default:
<function _graphviz_default_namer at 0x722a9c3221f0>) – A function mapping graph objects (wires/logic nets) to labels. If you want a more detailed namer, pass in a call tographviz_detailed_namer().block (
Block, default:None) –Blockto use (defaults to current working_block)split_state (bool) – If
True, split connections to/from aRegisterupdate net; this means that registers will be appear as source nodes of the network, andrnets (i.e. the logic for settingRegister.next) will be treated as sink nodes of the network.maintain_arg_order (bool) – If
True, will add ordering constraints so incoming edges are ordered left-to-right for nets where argument order matters (e.g.<). Keeping this asFalseresults in a cleaner, though less visually precise, graphical output.
- pyrtl.block_to_svg(block=None, split_state=True, maintain_arg_order=False)[source]¶
Return an SVG for the block.
- Parameters:
block (
Block, default:None) –Blockto use (defaults to current working_block).split_state (
bool, default:True) – IfTrue, visually split the connections to/from a register update net.maintain_arg_order (
bool, default:False) – IfTrue, will add ordering constraints so incoming edges are ordered left-to-right for nets where argument order matters (e.g.<). Keeping this asFalseresults in a cleaner, though less visually precise, graphical output.
- Returns:
The SVG representation of the
Block.
- pyrtl.trace_to_html(simtrace, trace_list=None, sortkey=None, repr_func=<built-in function hex>, repr_per_name=None)[source]¶
Return a HTML block showing the trace.
- Parameters:
simtrace (
SimulationTrace) – A trace to render in HTML.trace_list (
list[str] |None, default:None) – (optional) A list of wires to display.sortkey (default:
None) – (optional) The key with which to sort thetrace_list.repr_func (
Callable[[int],str], default:<built-in function hex>) – Function to use for representing each value in the trace. Examples includehex(),oct(),bin(), andstr(for decimal),val_to_signed_integer()(for signed decimal) or the function returned byenum_name()(forIntEnum). Defaults tohex().repr_per_name (
dict[str,Callable[[int],str]] |None, default:None) – Map from signal name to a function that takes in the signal’s value and returns a user-defined representation. If a signal name is not found in the map, the argumentrepr_funcwill be used instead.
- Return type:
- Returns:
An HTML block showing the trace.
- pyrtl.net_graph(block=None, split_state=False)[source]¶
Return a graph representation of the given
Block.The graph has the following form:
{ node1: { nodeA: [edge1A_1, edge1A_2], nodeB: [edge1B]}, node2: { nodeB: [edge2B], nodeC: [edge2C_1, edge2C_2]}, ... }
aka:
edges = graph[source][dest]Each node can be either a
LogicNetor aWireVector(e.g. anInput, anOutput, aConstor even an undrivenWireVector(which acts as a source or sink in the network). Each edge is aWireVectoror derived type (Input,Output,Register, etc.). Note thatInputs,Consts, andOutputswill be both “node” and “edge”.WireVectorsthat are not connected to any nets are not returned as part of the graph.Note
Consider using GateGraphs instead.
- Parameters:
block (
Block, default:None) –Blockto use (defaults to current working_block).split_state (
bool, default:False) – IfTrue, split connections to/from a register update net; this means that registers will be appear as source nodes of the network, andrnets (i.e. the logic for settingRegister.next) will be treated as sink nodes of the network.