mirror of
https://github.com/verilator/verilator.git
synced 2025-01-03 21:27:35 +00:00
87e8736823
Adds dtype() to every node, keep global table of dtypes and remove duplicates. Final merge from dtype branch.
562 lines
20 KiB
Plaintext
562 lines
20 KiB
Plaintext
# DESCRIPTION: DOCUMENT source run through perl to produce internals.txt file
|
|
# Use 'make internals.txt' to produce the output file
|
|
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
Verilator Internals
|
|
|
|
=head1 INTRODUCTION
|
|
|
|
This file discusses internal and programming details for Verilator. It's
|
|
the first for reference for developers and debugging problems.
|
|
|
|
See also the Verilator internals presentation at http://www.veripool.org.
|
|
|
|
=head1 ADDING A NEW FEATURE
|
|
|
|
Generally what would you do to add a new feature?
|
|
|
|
=over 4
|
|
|
|
File a bug (if there isn't already) so others know what you're working on.
|
|
|
|
Make a testcase in the test_regress/t/t_EXAMPLE format, see TESTING Below.
|
|
|
|
If grammar changes are needed, look at the git version of VerilogPerl's
|
|
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
|
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
|
the appropriate rules to src/verilog.y and modify the productions.
|
|
|
|
If a new Ast type is needed, add it to V3AstNodes.h.
|
|
|
|
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
|
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
|
file which you can examine to see if the parsing worked. See also the
|
|
sections below on debugging.
|
|
|
|
Modify the later visitor functions to process the new feature as needed.
|
|
|
|
=back
|
|
|
|
=head1 CODE FLOWS
|
|
|
|
=head2 Verilator Flow
|
|
|
|
The main flow of Verilator can be followed by reading the Verilator.cpp
|
|
process() function:
|
|
|
|
First, the files specified on the command line are read. Reading involves
|
|
preprocessing, then lexical analysis with Flex and parsing with Bison.
|
|
This produces an abstract syntax tree (AST) representation of the design,
|
|
which is what is visible in the .tree files described below.
|
|
|
|
Verilator then makes a series of passes over the AST, progressively refining
|
|
and optimizing it.
|
|
|
|
Cells in the AST first linked, which will read and parse additional files as
|
|
above.
|
|
|
|
Functions, variable and other references are linked to their definitions.
|
|
|
|
Parameters are resolved and the design is elaborated.
|
|
|
|
Verilator then performs many additional edits and optimizations on the
|
|
hierarchical design. This includes coverage, assertions, X elimination,
|
|
inlining, constant propagation, and dead code elimination.
|
|
|
|
References in the design are then psudo-flattened. Each module's variables
|
|
and functions get "Scope" references. A scope reference is an occurrence of
|
|
that un-flattened variable in the flattened hierarchy. A module that occurs
|
|
only once in the hierarchy will have a single scope and single VarScope for
|
|
each variable. A module that occurs twice will have a scope for each
|
|
occurrence, and two VarScopes for each variable. This allows optimizations
|
|
to proceed across the flattened design, while still preserving the
|
|
hierarchy.
|
|
|
|
Additional edits and optimizations proceed on the psudo-flat design. These
|
|
include module references, function inlining, loop unrolling, variable
|
|
lifetime analysis, lookup table creation, always splitting, and logic gate
|
|
simplifications (pushing inverters, etc).
|
|
|
|
Verilator orders the code. Best case, this results in a single "eval"
|
|
function which has all always statements flowing from top to bottom with no
|
|
loops.
|
|
|
|
Verilator mostly removes the flattening, so that code may be shared between
|
|
multiple invocations of the same module. It localizes variables, combines
|
|
identical functions, expands macros to C primitives, adds branch prediction
|
|
hints, and performs additional constant propagation.
|
|
|
|
Verilator finally writes the C++ modules.
|
|
|
|
=head2 Key Classes Used in the Verilator Flow
|
|
|
|
The AST is represented at the top level by the class C<AstNode>. This abstract
|
|
class has derived classes for the individual components (e.g. C<AstGenerate>
|
|
for a generate block) or groups of components (e.g. C<AstNodeFTask> for
|
|
functions and tasks, which in turn has C<AstFunc> and C<AstTask> as derived
|
|
classes).
|
|
|
|
Each C<AstNode> has pointers to up to four children, accessed by the
|
|
C<op1p> through C<op4p> methods. These methods are then abstracted in a
|
|
specific Ast* node class to a more specific name. For example with the
|
|
C<AstIf> node (for C<if> statements), C<ifsp> calls C<op1p> to give the
|
|
pointer to the AST for the "then" block, while C<elsesp> calls C<op2p> to
|
|
give the pointer to the AST for the "else" block, or NULL if there is not
|
|
one.
|
|
|
|
C<AstNode> has the concept of a next and previous AST - for example the
|
|
next and previous statements in a block. Pointers to the AST for these
|
|
statements (if they exist) can be obtained using the C<back> and C<next>
|
|
methods.
|
|
|
|
It is useful to remember that the derived class C<AstNetlist> is at the top
|
|
of the tree, so checking for this class is the standard way to see if you
|
|
are at the top of the tree.
|
|
|
|
By convention, each function/method uses the variable C<nodep> as a pointer
|
|
to the C<AstNode> currently being processed.
|
|
|
|
The passes are implemented by AST visitor classes (see L</Visitor
|
|
Functions>). These are implemented by subclasses of the abstract class,
|
|
C<AstNVisitor>. Each pass creates an instance of the visitor class, which
|
|
in turn implements a method to perform the pass.
|
|
|
|
=head2 Verilated Flow
|
|
|
|
The evaluation loop outputted by Verilator is designed to allow a single
|
|
function to perform evaluation under most situations.
|
|
|
|
On the first evaluation, the Verilated code calls initial blocks, and then
|
|
"settles" the modules, by evaluating functions (from always statements)
|
|
until all signals are stable.
|
|
|
|
On other evaluations, the Verilated code detects what input signals have
|
|
changes. If any are clocks, it calls the appropriate sequential functions
|
|
(from always @ posedge statements). Interspersed with sequential functions
|
|
it calls combo functions (from always @*). After this is complete, it
|
|
detects any changes due to combo loops or internally generated clocks, and
|
|
if one is found must reevaluate the model again.
|
|
|
|
For SystemC code, the eval() function is wrapped in a SystemC SC_METHOD,
|
|
sensitive to all inputs. (Ideally it would only be sensitive to clocks and
|
|
combo inputs, but tracing requires all signals to cause evaluation, and the
|
|
performance difference is small.)
|
|
|
|
If tracing is enabled, a callback examines all variables in the design for
|
|
changes, and writes the trace for each change. To accelerate this process
|
|
the evaluation process records a bitmask of variables that might have
|
|
changed; if clear, checking those signals for changes may be skipped.
|
|
|
|
=head1 CODING CONVENTIONS
|
|
|
|
=head2 Indentation style
|
|
|
|
To match the indentation of Verilator C++ sources, use 4 spaces per level,
|
|
and leave tabs at 8 columns, so every other indent level is a tab stop.
|
|
|
|
All files should contain the magic header to insure standard indentation:
|
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
This sets indentation to the cc-mode defaults. (Verilator predates a
|
|
CC-mode change of several years ago which overrides the defaults with GNU
|
|
style indentation; the c-set-style undoes that.)
|
|
|
|
=head2 The C<astgen> script
|
|
|
|
Some of the code implementing passes is extremely repetitive, and must be
|
|
implemented for each sub-class of C<AstNode>. However, while repetitive,
|
|
there is more variability than can be handled in C++ macros.
|
|
|
|
In Verilator this is implemented by using a Perl script, C<astgen> to
|
|
pre-process the C++ code. For example in C<V3Const.cpp> this is used to
|
|
implement the C<visit()> functions for each binary operation using the
|
|
TREEOP macro.
|
|
|
|
The original C++ source code is transformed into C++ code in the C<obj_opt>
|
|
and C<obj_dbg> sub-directories (the former for the optimized version of
|
|
verilator, the latter for the debug version). So for example C<V3Const.cpp>
|
|
into C<V3Const__gen.cpp>.
|
|
|
|
=head2 Visitor Functions
|
|
|
|
The verilator uses the I<Visitor> design pattern to implement its
|
|
refinement and optimization passes. This allows separation of the pass
|
|
algorithm from the AST on which it operates. Wikipedia provides an
|
|
introduction to the concept at
|
|
L<http://en.wikipedia.org/wiki/Visitor_pattern>.
|
|
|
|
As noted above, all visitors are derived classes of C<AstNvisitor>. All
|
|
derived classes of C<AstNode> implement the C<accept> method, which takes
|
|
as argument a reference to an instance or a C<AstNVisitor> derived class
|
|
and applies the visit method of the C<AstNVisitor> to the invoking AstNode
|
|
instance (i.e. C<this>).
|
|
|
|
One possible difficulty is that a call to C<accept> may perform an edit
|
|
which destroys the node it receives as argument. The
|
|
C<acceptSubtreeReturnEdits> method of C<AstNode> is provided to apply
|
|
C<accept> and return the resulting node, even if the original node is
|
|
destroyed (if it is not destroyed it will just return the original node).
|
|
|
|
The behavior of the visitor classes is achieved by overloading the C<visit>
|
|
function for the different C<AstNode> derived classes. If a specific
|
|
implementation is not found, the system will look in turn for overloaded
|
|
implementations up the inheritance hierarchy. For example calling C<accept>
|
|
on C<AstIf> will look in turn for:
|
|
|
|
void visit (AstIf* nodep, AstNUser* vup)
|
|
void visit (AstNodeIf* nodep, AstNUser* vup)
|
|
void visit (AstNodeStmt* nodep, AstNUser* vup)
|
|
void visit (AstNode* nodep, AstNUser* vup)
|
|
|
|
There are three ways data is passed between visitor functions.
|
|
|
|
=over 4
|
|
|
|
=item 1.
|
|
|
|
A visitor-class member variable. This is generally for passing "parent"
|
|
information down to children. C<m_modp> is a common example. It's set to
|
|
NULL in the constructor, where that node (C<AstModule> visitor) sets it,
|
|
then the children are iterated, then it's cleared. Children under an
|
|
C<AstModule> will see it set, while nodes elsewhere will see it clear. If
|
|
there can be nested items (for example an C<AstFor> under an C<AstFor>) the
|
|
variable needs to be save-set-restored in the C<AstFor> visitor, otherwise
|
|
exiting the lower for will lose the upper for's setting.
|
|
|
|
=item 2.
|
|
|
|
User attributes. Each C<AstNode> (B<Note.> The AST node, not the visitor)
|
|
has five user attributes, which may be accessed as an integer using the
|
|
C<user1()> through C<user5()> methods, or as a pointer (of type
|
|
C<AstNuser>) using the C<user1p()> through C<user5p()> methods (a common
|
|
technique lifted from graph traversal packages).
|
|
|
|
A visitor first clears the one it wants to use by calling
|
|
C<AstNode::user#ClearTree()>, then it can mark any node's user() with whatever
|
|
data it wants. Readers just call C<< nodep->user() >>, but may need to cast
|
|
appropriately, so you'll often see C<< nodep->userp()->castSOMETYPE() >>. At
|
|
the top of each visitor are comments describing how the C<user()> stuff
|
|
applies to that visitor class. For example:
|
|
|
|
// NODE STATE
|
|
// Cleared entire netlist
|
|
// AstModule::user1p() // bool. True to inline this module
|
|
|
|
This says that at the C<AstNetlist> C<user1ClearTree()> is called. Each
|
|
C<AstModule>'s C<user1()> is used to indicate if we're going to inline it.
|
|
|
|
These comments are important to make sure a C<user#()> on a given C<AstNode>
|
|
type is never being used for two different purposes.
|
|
|
|
Note that calling C<user#ClearTree> is fast, it doesn't walk the tree, so
|
|
it's ok to call fairly often. For example, it's commonly called on every
|
|
module.
|
|
|
|
=item 3.
|
|
|
|
Parameters can be passed between the visitors in close to the "normal"
|
|
function caller to callee way. This is the second C<vup> parameter of type
|
|
C<AstNuser> that is ignored on most of the visitor functions. V3Width does
|
|
this, but it proved more messy than the above and is deprecated. (V3Width
|
|
was nearly the first module written. Someday this scheme may be removed,
|
|
as it slows the program down to have to pass vup everywhere.)
|
|
|
|
=back
|
|
|
|
=head2 Iterators
|
|
|
|
C<AstNode> provides a set of iterators to facilitate walking over the
|
|
tree. Each takes two arguments, a visitor, C<v>, of type C<AstNVisitor> and
|
|
an optional pointer user data, C<vup>, of type C<AstNuser*>. The second is
|
|
one of the ways to pass parameters to visitors described in L</Visitor
|
|
Functions>, but its use is no deprecated and should be used for new visitor
|
|
classes.
|
|
|
|
=over 4
|
|
|
|
=item C<iterate()>
|
|
|
|
This just applies the C<accept> method of the C<AstNode> to the visitor
|
|
function.
|
|
|
|
=item C<iterateAndNextIgnoreEdit>
|
|
|
|
Applies the C<accept> method of each C<AstNode> in a list (i.e. connected
|
|
by C<nextp> and C<backp> pointers).
|
|
|
|
=item C<iterateAndNext>
|
|
|
|
Applies the C<accept> method of each C<AstNode> in a list. If a node is
|
|
edited by the call to C<accept>, apply C<accept> again, until the node does
|
|
not change.
|
|
|
|
=item C<iterateListBackwards>
|
|
|
|
Applies the C<accept> method of each C<AstNode> in a list, starting with
|
|
the last one.
|
|
|
|
=item C<iterateChildren>
|
|
|
|
Apply the C<iterateAndNext> method on each child C<op1p> through C<op4p> in
|
|
turn.
|
|
|
|
=item C<iterateChildrenBackwards>
|
|
|
|
Apply the C<iterateListBackwards> method on each child C<op1p> through
|
|
C<op4p> in turn.
|
|
|
|
=back
|
|
|
|
=head2 Identifying derived classes
|
|
|
|
A common requirement is to identify the specific C<AstNode> class we are
|
|
dealing with. For example a visitor might not implement separate C<visit>
|
|
methods for C<AstIf> and C<AstGenIf>, but just a single method for the base
|
|
class:
|
|
|
|
void visit (AstNodeIf* nodep, AstNUser* vup)
|
|
|
|
However that method might want to specify additional code if it is called
|
|
for C<AstGenIf>. Verilator does this by providing a C<castSOMETYPE()>
|
|
method for each possible node type, using C++ C<dynamic_cast>. This either
|
|
returns a pointer to the object cast to that type (if it is of class
|
|
C<SOMETYPE>, or a derived class of C<SOMETYPE>) or else NULL. So our
|
|
C<visit> method could use:
|
|
|
|
if (nodep->castAstGenIf()) {
|
|
<code specific to AstGenIf>
|
|
}
|
|
|
|
A common test is for C<AstNetlist>, which is the node at the root of the
|
|
AST.
|
|
|
|
=head1 TESTING
|
|
|
|
To write a test see the BUGS section of the Verilator primary manual, and
|
|
the documentation in:
|
|
|
|
test_regress/t/driver.pl --help
|
|
|
|
=head1 DEBUGGING
|
|
|
|
=head2 --debug
|
|
|
|
When you run with --debug there are two primary output file types placed into
|
|
the obj_dir, .tree and .dot files.
|
|
|
|
=head2 .dot output
|
|
|
|
Dot files are dumps of internal graphs in Graphviz
|
|
L<http://www.graphviz.org/> dot format. When a dot file is dumped,
|
|
Verilator will also print a line on stdout that can be used to format the
|
|
output, for example:
|
|
|
|
dot -Tps -o ~/a.ps obj_dir/Vtop_foo.dot
|
|
|
|
You can then print a.ps. You may prefer gif format, which doesn't get
|
|
scaled so can be more useful with large graphs.
|
|
|
|
For dynamic graph viewing consider ZGRViewer
|
|
L<http://zvtm.sourceforge.net/zgrviewer.html>. If you know of better
|
|
viewers let us know; ZGRViewer isn't great for large graphs.
|
|
|
|
=head2 .tree output
|
|
|
|
Tree files are dumps of the AST Tree and are produced between every major
|
|
algorithmic stage. An example:
|
|
|
|
NETLIST 0x90fb00 <e1> {a0}
|
|
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
|
|
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
|
|
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
|
|
|
|
=over 4
|
|
|
|
"1:2:" indicates the hierarchy of the C<VAR> is the C<op2p> pointer under
|
|
the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
|
|
|
|
"VAR" is the AstNodeType.
|
|
|
|
"0x91a780" is the address of this node.
|
|
|
|
"<e74>" means the 74th edit to the netlist was the last modification to
|
|
this node.
|
|
|
|
"{a22}" indicates this node is related to line 22 in the source filename
|
|
"a", where "a" is the first file read, "z" the 26th, and "aa" the 27th.
|
|
|
|
"@dt=0x..." indicates the address of the data type this node contains.
|
|
|
|
"w32" indicates the width is 32 bits.
|
|
|
|
"out_wide" is the name of the node, in this case the name of the variable.
|
|
|
|
"[O]" are flags which vary with the type of node, in this case it means the
|
|
variable is an output.
|
|
|
|
=back
|
|
|
|
In more detail the following fields are dumped common to all nodes. They
|
|
are produced by the C<AstNode::dump()> method:
|
|
|
|
=over 4
|
|
|
|
=item Tree Hierarchy
|
|
|
|
The dump lines begin with numbers and colons to indicate the child node
|
|
hierarchy. As noted above in L</Key Classes Used in the Verilator Flow>,
|
|
C<AstNode> has lists of items at the same level in the AST, connected by
|
|
the C<nextp()> and C<prevp()> pointers. These appear as nodes at the same
|
|
level. For example after inlining:
|
|
|
|
NETLIST 0x929c1c8 <e1> {a0} w0
|
|
1: MODULE 0x92bac80 <e3144> {e14} w0 TOP_t L1 [P]
|
|
1:1: CELLINLINE 0x92bab18 <e3686#> {e14} w0 v -> t
|
|
1:1: CELLINLINE 0x92bc1d8 <e3688#> {e24} w0 v__DOT__i_test_gen -> test_gen
|
|
...
|
|
1: MODULE 0x92b9bb0 <e503> {e47} w0 test_gen L3
|
|
...
|
|
|
|
=item AstNode type
|
|
|
|
The textual name of this node AST type (always in capitals). Many of these
|
|
correspond directly to Verilog entities (for example C<MODULE> and
|
|
C<TASK>), but others are internal to Verialtor (for example C<NETLIST> and
|
|
C<BASICDTYPE>).
|
|
|
|
=item Address of the node
|
|
|
|
A hexadecimal address of the node in memory. Useful for examining with the
|
|
debugger.
|
|
|
|
=item Last edit number
|
|
|
|
Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
|
|
of the last edit to modify this node. The trailing C<#> indicates the node
|
|
has been edited since the last tree dump (which typically means in the last
|
|
refinement or optimization pass). GDB can watch for this, see L</Debugging
|
|
with GDB> below.
|
|
|
|
=item Source file and line
|
|
|
|
Of the form C<< {xxnnnn} >>, where C{xx} is the filename letter (or
|
|
letters) and C<nnnn> is the line number within that file. The first file is
|
|
C<a>, the 26th is C<z>, the 27th is C<aa> and so on.
|
|
|
|
=item User pointers
|
|
|
|
Shows the value of the node's user1p...user5p, if non-NULL.
|
|
|
|
=item Data type
|
|
|
|
Many nodes have an explicit data type. "@dt=0x..." indicates the address
|
|
of the data type (AstNodeDType) this node uses.
|
|
|
|
If a data type is present and is numberic, it then prints the width of the
|
|
item. This field is a squence of flag characters and width data as follows:
|
|
|
|
C<s> if the node is signed.
|
|
|
|
C<d> if the node is a double (i.e a floating point entity).
|
|
|
|
C<w> always present, indicating this is the width field.
|
|
|
|
C<u> if the node is unsized.
|
|
|
|
C</nnnn> if the node is unsized, where C<nnnn> is the minimum width.
|
|
|
|
=item Name of the entity represented by the node if it exists
|
|
|
|
For example for a C<VAR> it is the name of the variable.
|
|
|
|
=back
|
|
|
|
Many nodes follow these fields with additional node specific
|
|
information. Thus the C<VARREF> node will print either C<[LV]> or C<[RV]>
|
|
to indicate a left value or right value, followed by the node of the
|
|
variable being referred to. For example:
|
|
|
|
1:2:1:1: VARREF 0x92c2598 <e509> {e24} w0 clk [RV] <- VAR 0x92a2e90 <e79> {e18} w0 clk [I] INPUT
|
|
|
|
In general, examine the C<dump()> method in C<V3AstNodes.cpp> of the node
|
|
type in question to determine additional fields that may be printed.
|
|
|
|
The C<MODULE> has a list of C<CELLINLINE> nodes referred to by its
|
|
C<op1p()> pointer, connected by C<nextp()> and C<prevp()> pointers.
|
|
|
|
Similarly the C<NETLIST> has a list of modules referred to by its C<op1p()>
|
|
pointer.
|
|
|
|
=head2 Debugging with GDB
|
|
|
|
The test_regress/driver.pl script accepts --debug --gdb to start Verilator
|
|
under gdb and break when an error is hit or the program is about to exit.
|
|
You can also use --debug --gdbbt to just backtrace and then exit gdb. To
|
|
debug the Verilated executable, use --gdbsim.
|
|
|
|
If you wish to start verilator under GDB (or another debugger), then you
|
|
can use --debug and look at the underlying invocation of verilator_dgb. For
|
|
example
|
|
|
|
t/t_alw_dly.pl --debug
|
|
|
|
shows it invokes the command:
|
|
|
|
../verilator_bin_dbg --prefix Vt_alw_dly --x-assign unique --debug
|
|
-cc -Mdir obj_dir/t_alw_dly --debug-check -f input.vc t/t_alw_dly.v
|
|
|
|
Start GDB, then C<start> with the remaining arguments.
|
|
|
|
gdb ../verilator_bin_dbg
|
|
...
|
|
(gdb) start --prefix Vt_alw_dly --x-assign unique --debug -cc -Mdir
|
|
obj_dir/t_alw_dly --debug-check -f input.vc t/t_alw_dly.v
|
|
> obj_dir/t_alw_dly/vlt_compile.log
|
|
...
|
|
Temporary breakpoint 1, main (argc=13, argv=0xbfffefa4, env=0xbfffefdc)
|
|
at ../Verilator.cpp:615
|
|
615 ios::sync_with_stdio();
|
|
(gdb)
|
|
|
|
You can then continue execution with breakpoints as required.
|
|
|
|
To break at a specific edit number which changed a node (presumably to find
|
|
what made a <e####> line in the tree dumps):
|
|
|
|
watch AstNode::s_editCntGbl==####
|
|
|
|
To print a node:
|
|
|
|
pn nodep
|
|
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
|
|
pnt nodep
|
|
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
|
|
|
|
When GDB halts, it is useful to understand that the backtrace will commonly
|
|
show the iterator functions between each invocation of C<visit> in the
|
|
backtrace. You will typically see a frame sequence something like
|
|
|
|
...
|
|
visit()
|
|
iterateChildren()
|
|
iterateAndNext()
|
|
accept()
|
|
visit()
|
|
...
|
|
|
|
=head1 DISTRIBUTION
|
|
|
|
The latest version is available from L<http://www.veripool.org/>.
|
|
|
|
Copyright 2008-2012 by Wilson Snyder. Verilator is free software; you can
|
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
|
|
|
=cut
|
|
|
|
######################################################################
|