Verilator - Convert Verilog code to C++/SystemC
verilator --help verilator --version verilator --cc [options] [top_level.v] [opt_c_files.cpp/c/cc] verilator --sc [options] [top_level.v] [opt_c_files.cpp/c/cc] verilator --sp [options] [top_level.v] [opt_c_files.cpp/c/cc] verilator --lint-only ...
Verilator converts synthesizable (not behavioral) Verilog code, plus some Synthesis, SystemVerilog and Sugar/PSL assertions, into C++, SystemC or SystemPerl code. It is not a complete simulator, just a compiler.
Verilator is invoked with parameters similar to GCC, Cadence Verilog-XL/NC-Verilog, or Synopsys's VCS. It reads the specified Verilog code, lints it, and optionally adds coverage and waveform tracing code. For C++ and SystemC formats, it outputs .cpp and .h files. For SystemPerl format, it outputs .sp files for the SystemPerl preprocessor, which greatly simplifies writing SystemC code and is available at http://www.veripool.org.
The files created by Verilator are then compiled with C++. The user writes a little C++ wrapper file, which instantiates the top level module, and passes this filename on the command line. These C files are compiled in C++, and linked with the Verilated files.
The resulting executable will perform the actual simulation.
This is a short summary of the arguments to Verilator. See the detailed descriptions in the next sections for more information.
{file.v} Verilog top level filenames {file.c/cc/cpp} Optional C++ files to link in
--assert Enable all assertions --autoflush Flush streams after all $displays --bin <filename> Override Verilator binary --cc Create C++ output --compiler <compiler-name> Tune for specified C++ compiler --coverage Enable all coverage --coverage-line Enable line coverage --coverage-user Enable PSL/SVL user coverage -D<var>[=<value>] Set preprocessor define --debug Enable debugging --debug-check Enable debugging assertions --dump-tree Enable dumping .tree files -E Preprocess, but do not compile --error-limit <value> Abort after this number of errors --exe Link to create executable -f <file> Parse options from a file --help Display this help. -I<dir> Directory to search for includes --inhibit-sim Create function to turn off sim --inline-mult <value> Tune module inlining --language <lang> Language standard to parse --lint-only Lint, but do not make output --MMD Create .d dependency files --MP Create phony dependency targets --Mdir <directory> Name of output object directory --mod-prefix <topname> Name to prepend to lower classes --no-skip-identical Disable skipping identical output -O0 Disable optimizations -O3 High performance optimizations -O<optimization-letter> Selectable optimizations --output-split <bytes> Split .cpp files into pieces --output-split-cfuncs <statements> Split .ccp functions --pins64 Use uint64_t's for 33-64 bit sigs --prefix <topname> Name of top level class --profile-cfuncs Name functions for profiling --private Debugging; see docs --psl Enable PSL parsing --public Debugging; see docs --sc Create SystemC output --sp Create SystemPerl output --stats Create statistics file --top-module <topname> Name of top level input module --trace Enable waveform creation --trace-depth <levels> Depth of tracing -U<var> Undefine preprocessor define --underline-zero Zero signals with leading _'s -v <filename> Verilog library -Werror-<message> Convert warning to error -Wfuture-<message> Disable unknown message warnings -Wno-<message> Disable warning -x-assign <mode> Initially assign Xs to this value -y <dir> Directory to search for modules
+define+<var>+<value> Set preprocessor define +incdir+<dir> Directory to search for includes +libext+<ext>+[ext]... Extensions for finding modules
See also --x-assign; setting ``--x-assign unique'' may be desirable.
Coverage analysis adds statements at each code flow change point, which are the branches of IF and CASE statements, a super-set of normal Verilog Line Coverage. At each such branch a unique counter is incremented. At the end of a test, the counters along with the filename and line number corresponding to each counter are written into logs/coverage.pl.
After running multiple tests, the vcoverage utility (from the SystemPerl package) is executed. Vcoverage reads the logs/coverage.pl file(s), and creates an annotated source code listing showing code coverage details.
Verilator automatically disables coverage of branches that have a $stop in them, as it is assumed $stop branches contain an error check that should not occur. A /*verilator coverage_block_off*/ comment will perform a similar function on any code in that block or below.
Note Verilator may over-count combinatorial (non-clocked) blocks when those blocks receive signals which have had the UNOPTFLAT warning disabled; for most accurate results do not disable this warning when using coverage.
For an example, after running 'make test' in the Verilator distribution, see the test_sp/logs/coverage_source directory. Grep for lines starting with '%' to see what lines Verilator believes need more coverage.
For example, the following PSL statement will add a coverage point, with the comment ``DefaultClock'':
// psl default clock = posedge clk; // psl cover {cyc==9} report "DefaultClock,expect=1";
Declares all signals and modules public. This will turn off signal optimizations as if all signals had a /*verilator public*/ comments and inlining. This will also turn off inlining as if all modules had a /*verilator public_module*/, unless the module specifically enabled it with /*verilator inline_module*/.
Having tracing compiled in may result in some small performance losses, even when waveforms are not turned on during model execution.
-Werror-NOUNOPTFLAT
.
It is strongly recommended you cleanup your code rather than using this option, it is only intended to be use when running test-cases of code received from third parties.
The following arguments are compatible with GCC, VCS and most Verilog programs.
We'll compile this example into C++.
mkdir test_our cd test_our
cat <<EOF >our.v module our; initial begin \$display("Hello World"); \$finish; end endmodule EOF
cat <<EOF >sim_main.cpp #include "Vour.h" #include "verilated.h" int main(int argc, char **argv, char **env) { Vour* top = new Vour; while (!Verilated::gotFinish()) { top->eval(); } exit(0); } EOF
Now we run Verilator on our little example.
export VERILATOR_ROOT=/path/to/where/verilator/was/installed $VERILATOR_ROOT/bin/verilator --cc our.v --exe sim_main.cpp
We can see the source code under the ``obj_dir'' directory. See the FILES section below for descriptions of some of the files that were created.
ls -l obj_dir
We then can compile it
cd obj_dir make -f Vour.mk Vour
(Verilator included a default compile rule and link rule, since we used --exe and passed a .cpp file on the Verilator command line. You can also write your own compile rules, as we'll show in the SYSTEMC section.)
And now we run it
cd .. obj_dir/Vour
And we get as output
Hello World - our.v:2: Verilog $finish
Really, you're better off writing a Makefile to do all this for you. Then, when your source changes it will automatically run all of these steps. See the test_c directory in the distribution for an example.
This is an example similar to the above, but using SystemPerl.
mkdir test_our_sc cd test_our_sc
cat <<EOF >our.v module our (clk); input clk; // Clock is required to get initial activation always @ (posedge clk) begin \$display("Hello World"); \$finish; end endmodule EOF
cat <<EOF >sc_main.cpp #include "Vour.h" int sc_main(int argc, char **argv) { sc_clock clk ("clk",10, 0.5, 3, true); Vour* top; top = new Vour("top"); // SP_CELL (top, Vour); top->clk(clk); // SP_PIN (top, clk, clk); while (!Verilated::gotFinish()) { sc_start(1); } exit(0); } EOF
Now we run Verilator on our little example.
export VERILATOR_ROOT=/path/to/where/verilator/was/installed $VERILATOR_ROOT/bin/verilator --sp our.v
Then we convert the SystemPerl output to SystemC.
cd obj_dir export SYSTEMPERL=/path/to/where/systemperl/kit/came/from $SYSTEMPERL/sp_preproc --preproc *.sp
(You can also skip the above sp_preproc by getting pure SystemC from Verilator by replacing the verilator --sp flag in the previous step with -sc.)
We then can compile it
make -f Vour.mk Vour__ALL.a make -f Vour.mk ../sc_main.o make -f Vour.mk verilated.o
And link with SystemC. Note your path to the libraries may vary, depending on the operating system.
export SYSTEMC=/path/to/where/systemc/was/built/or/installed g++ -L$SYSTEMC/lib-linux ../sc_main.o Vour__ALL*.o verilated.o \ -o Vour -lsystemc
And now we run it
cd .. obj_dir/Vour
And we get the same output as the C++ example:
Hello World - our.v:2: Verilog $finish
Really, you're better off using a Makefile to do all this for you. Then, when your source changes it will automatically run all of these steps. See the test_sp directory in the distribution for an example.
For best performance, run Verilator with the ``-O3 -x-assign=fast --noassert'' flags. The -O3 flag will require longer compile times, and -x-assign=fast may increase the risk of reset bugs in trade for performance; see the above documentation for these flags.
Minor Verilog code changes can also give big wins. You should not have any UNOPTFLAT warnings from Verilator. Fixing these warnings can result in huge improvements; one user fixed their one UNOPTFLAT warning by making a simple change to a clock latch used to gate clocks and gained a 60% performance improvement.
Beyond that, the performance of a Verilated model depends mostly on your C++ compiler and size of your CPU's caches.
By default, the lib/verilated.mk file has optimization turned off. This is for the benefit of new users, as it improves compile times at the cost of runtimes. To add optimization as the default, set one of three variables, OPT, OPT_FAST, or OPT_SLOW in lib/verilated.mk. Or, just for one run, pass them on the command line to make:
make OPT_FAST="-O2" -f Vour.mk Vour__ALL.a
OPT_FAST specifies optimizations for those programs that are part of the fast path, mostly code that is executed every cycle. OPT_SLOW specifies optimizations for slow-path files (plus tracing), which execute only rarely, yet take a long time to compile with optimization on. OPT specifies overall optimization and affects all compiles, including those OPT_FAST and OPT_SLOW affect. For best results, use OPT=``-O2'', and link with ``-static''. Nearly the same results can be had with much better compile times with OPT_FAST=``-O1 -fstrict-aliasing''.
Unfortunately, using the optimizer with SystemC files can result in compiles taking several minutes. (The SystemC libraries have many little inlined functions that drive the compiler nuts.)
For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have optimization bugs around pointer aliasing detection, which can result in 2x performance losses.
If you will be running many simulations on a single compile, investigate feedback driven compilation. With GCC, using -fprofile-arcs, then -fbranch-probabilities will yield another 15% or so.
You may uncover further tuning possibilities by profiling the Verilog code. Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run either oprofile or gprof to see where in the C++ code the time is spent. Run the gprof output through verilator_profcfunc and it will tell you what Verilog line numbers on which most of the time is being spent.
When done, please let the author know the results. I like to keep tabs on how Verilator compares, and may be able to suggest additional improvements.
All output files are placed in the output directory name specified with the -Mdir option, or ``obj_dir'' if not specified.
Verilator creates the following files in the output directory:
{prefix}.mk // Make include file for compiling {prefix}_classes.mk // Make include file with class names
For -cc and -sc mode, it also creates:
{prefix}.cpp // Top level C++ file {prefix}.h // Top level header {prefix}{each_verilog_module}.cpp // Lower level internal C++ files {prefix}{each_verilog_module}.h // Lower level internal header files
For -sp mode, instead of .cpp and .h it creates:
{prefix}.sp // Top level SystemC file {prefix}{each_verilog_module}.sp // Lower level internal SC files
In certain optimization modes, it also creates:
{prefix}__Inlines.h // Inline support functions {prefix}__Slow.cpp // Constructors and infrequent routines {prefix}__Syms.cpp // Global symbol table C++ {prefix}__Syms.h // Global symbol table header {prefix}__Trace.cpp // Wave file generation code (--trace) {prefix}__stats.txt // Statistics (--stats)
It also creates internal files that can be mostly ignored:
{each_verilog_module}.vpp // Post-processed verilog (--debug) {prefix}.flags_vbin // Verilator dependencies {prefix}.flags_vpp // Pre-processor dependencies {prefix}{misc}.d // Make dependencies (-MMD) {prefix}{misc}.dot // Debugging graph files (--debug) {prefix}{misc}.tree // Debugging files (--debug)
After running Make, the C++ compiler should produce the following:
{prefix} // Final executable (w/--exe argument) {prefix}__ALL.a // Library of all Verilated objects {prefix}{misc}.o // Intermediate objects
Verilator creates a .h and .cpp file for the top level module and all modules under it. See the test_c directory in the kit for an example.
After the modules are completed, there will be a module.mk file that may be used with Make to produce a module__ALL.a file with all required objects in it. This is then linked with the user's top level to create the simulation executable.
The user must write the top level of the simulation. Here's a simple example:
#include <verilated.h> // Defines common routines #include "Vtop.h" // From Verilating "top.v"
Vtop *top; // Instantiation of module
unsigned int main_time = 0; // Current simulation time
double sc_time_stamp () { // Called by $time in Verilog return main_time; }
int main() { top = new Vtop; // Create instance
top->reset_l = 0; // Set some inputs
while (!Verilated::gotFinish()) { if (main_time > 10) { top->reset_l = 1; // Deassert reset } if ((main_time % 10) == 1) { top->clk = 1; // Toggle clock } if ((main_time % 10) == 6) { top->clk = 0; } top->eval(); // Evaluate model cout << top->out << endl; // Read a output main_time++; // Time passes... }
top->final(); // Done simulating // // (Though this example doesn't get here) }
Note signals are read and written as member variables of the lower module.
You call the eval()
method to evaluate the model. When the simulation is
complete call the final()
method to wrap up any SystemVerilog final blocks,
and complete any assertions.
Verilator will convert the top level module to a SC_MODULE. This module will plug directly into a SystemC netlist.
The SC_MODULE gets the same pinout as the Verilog module, with the following type conversions: Pins of a single bit become bool, unless they are marked with `systemc_clock, in which case they become sc_clock's (for SystemC 1.2, not needed in SystemC 2.0). Pins 2-32 bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or uint64_t's depending on the -pins64 switch. Wider pins become sc_bv's.
Lower modules are not pure SystemC code. This is a feature, as using the SystemC pin interconnect scheme everywhere would reduce performance by an order of magnitude.
Verilator supports cross-compiling Verilated code. This is generally used to run Verilator on a Linux system and produce C++ code that is then compiled on Windows.
Cross compilation involves up to three different OSes. The build system is where you configured and compiled Verilator, the host system where you run Verilator, and the target system where you compile the Verilated code and run the simulation.
Currently, Verilator requires the build and host system type to be the same, though the target system type may be different. To support this, ./configure and make Verilator on the build system. Then, run Verilator on the host system. Finally, the output of Verilator may be compiled on the different target system.
To support this, none of the files that Verilator produces will reference any configure generated build-system specific files, such as config.h (which is renamed in Verilator to config_build.h to reduce confusion.) The disadvantage of this approach is that include/verilatedos.h must self-detect the requirements of the target system, rather than using configure.
The target system may also require edits to the Makefiles, the simple Makefiles produced by Verilator presume the target system is the same type as the build system.
Verilator supports almost all Verilog 2001 language features. This includes signed numbers, ``always @*'', comma separated sensitivity lists, generate statements, multidimensional arrays, localparam, and C-style declarations inside port lists.
Verilator supports the `begin_keywords and `end_keywords compiler directives.
Verilator supports $clog2.
Verilator partially supports the uwire keyword.
Verilator currently has very minimal support for SystemVerilog. As SystemVerilog features enter common usage they will be added. Contact the author if a feature you need is missing.
Verilator implements the full SystemVerilog 1800-2005 preprocessor, including function call-like preprocessor defines.
Verilator supports ==? and !=? operators, $bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0, $warning, always_comb, always_ff, always_latch, do-while, and final.
It also supports .name and .* interconnection.
Verilator partially supports assert.
Most future work is being directed towards improving SystemVerilog assertions instead of PSL. If you are using these PSL features, please contact the author as they may be depreciated in future versions.
With the --assert switch, Verilator enables support of the Property Specification Language (PSL), specifically the simple PSL subset without time-branching primitives. Verilator currently only converts PSL assertions to simple ``if (...) error'' statements, and coverage statements to increment the line counters described in the coverage section.
Verilator implements these keywords: assert, assume (same as assert), default (for clocking), countones, cover, isunknown, onehot, onehot0, report, true.
Verilator implements these operators: -> (logical if).
Verilator does not support SEREs yet. All assertion and coverage statements must be simple expressions that complete in one cycle. PSL vmode/vprop/vunits are not supported. PSL statements must be in the module they reference, at the module level where you would put an initial... statement.
Verilator only supports (posedge CLK) or (negedge CLK), where CLK is the name of a one bit signal. You may not use arbitrary expressions as assertion clocks.
With the --assert switch, Verilator reads any ``//synopsys full_case'' or ``// synopsys parallel_case'' directives. The same applies to any ``//cadence'' or ``// ambit synthesis'' directives of the same form.
When these synthesis directives are discovered, Verilator will either formally prove the directive to be true, or failing that, will insert the appropriate code to detect failing cases at runtime and print an ``Assertion failed'' error message.
The following additional constructs are the extensions Verilator supports on top of standard Verilog code. Using these features outside of comments or `ifdef's may break other tools.
String arguments will be put directly into the output C++ code. Expression arguments will have the code to evaluate the expression inserted. Thus to call a C++ function, $c(``func('',a,``)'') will result in 'func(a)' in the output C++ code. For input arguments, rather than hard-coding variable names in the string $c(``func(a)''), instead pass the variable as an expression $c(``func('',a,``)''). This will allow the call to work inside Verilog functions where the variable is flattened out, and also enable other optimizations.
If you will be reading or writing any Verilog variables inside the C++ functions, the Verilog signals must be declared with /*verilator public*/.
You may also append a arbitrary number to $c, generally the width of the output. [signal_32_bits = $c32(``...'');] This allows for compatibility with other simulators which require a differently named PLI function name for each different output width.
If you will be reading or writing any Verilog variables in the C++ functions, the Verilog signals must be declared with /*verilator public*/. See also the public task feature; writing a accessor may result in cleaner code.
IE, with the following
reg splitme /* verilator isolate_assignments*/; always @* begin if (....) begin splitme = ....; other assignments end end
Verilator will internally split the block that assigns to ``splitme'' into two blocks:
It would then internally break it into (sort of):
// All assignments excluding those to splitme always @* begin if (....) begin other assignments end end // All assignments to splitme always @* begin if (....) begin splitme = ....; end end
// verilator lint_save // verilator lint_off SOME_WARNING ... // code needing SOME_WARNING turned off // verilator lint_restore
If SOME_WARNING was on before the lint_off, it will now be restored to on, and if it was off before the lint_off it will remain off.
Wide variables over 64 bits cannot be function returns, to avoid exposing complexities. However, wide variables can be input/outputs; they will be passed as references to an array of 32 bit numbers.
Generally, only the values of stored state (flops) should be written, as the model will NOT notice changes made to variables in these functions. (Same as when a signal is declared public.)
There are some limitations and lack of features relative to a commercial simulator, by intent. User beware.
It is strongly recommended you use a lint tool before running this program. Verilator isn't designed to easily uncover common mistakes that a lint program will find for you.
Verilator supports only the Synthesis subset with a few minor additions such as $stop, $finish and $display. That is, you cannot use hierarchical references, events or similar features of the Verilog language. It also simulates as Synopsys's Design Compiler would; namely a block of the form
always @ (x) y = x & z;
will recompute y when there is a change in x or a change in z, which is what Design Compiler will synthesize. A compliant simulator would only calculate y if x changes. (Use verilog-mode's /*AS*/ or Verilog 2001's always @* to prevent these issues.)
Verilator supports dotted references to variables, functions and tasks in different modules. However, references into named blocks and function-local variables are not supported. The portion before the dot must have a constant value; for example a[2].b is acceptable, while a[x].b is not.
References into generated and arrayed instances use the instance names specified in the Verilog standard; arrayed instances are named {cellName}[{instanceNumber}] in Verilog, which becomes {cellname}__BRA__{instanceNumber}__KET__ inside the generated C++ code.
Verilator creates numbered ``genblk'' when a begin: name is not specified around a block inside a generate statement. These numbers may differ between other simulators, but the Verilog specification does not allow users to use these names, so it should not matter.
If you are having trouble determining where a dotted path goes wrong, note that Verilator will print a list of known scopes to help your debugging.
Floating Point numbers are not synthesizable, and so not supported.
Verilator is optimized for edge sensitive (flop based) designs. It will attempt to do the correct thing for latches, but most performance optimizations will be disabled around the latch.
All delays (#) are ignored, as they are in synthesis.
Verilator is a two state simulator, not a four state simulator. However, it has two features which uncover most initialization bugs (including many that a four state simulator will miss.)
First, assigning a variable to a X will actually assign the variable to a random value (see the -x-assign switch.) Thus if the value is actually used, the random value should cause downstream errors. Integers also randomize, even though the Verilog 2001 specification says they initialize to zero.
Identity comparisons (=== or !==) are converted to standard ==/!== when neither side is a constant. This may make the expression result differ from a four state simulator.
All variables are initialized using a function. By running several random simulation runs you can determine that reset is working correctly. On the first run, the function initializes variables to zero. On the second, have it initialize variables to one. On the third and following runs have it initialize them randomly. If the results match, reset works. (Note this is what the hardware will really do.) In practice, just setting all variables to one at startup finds most problems.
As a 2 state compiler, tristate and inouts are not supported. Traditionally only chip ``cores'' are Verilated, the pad rings have been written by hand in C++.
All functions and tasks will be inlined (will not become functions in C.) The only support provided is for simple statements in tasks (which may affect global variables).
Recursive functions and tasks are not supported. All inputs and outputs are automatic, as if they had the Verilog 2001 ``automatic'' keyword prepended. (If you don't know what this means, Verilator will do what you probably expect -- what C does. The default behavior of Verilog is different.)
Verilator attempts to deal with generated clocks correctly, however new cases may turn up bugs in the scheduling algorithm. The safest option is to have all clocks as primary inputs to the model, or wires directly attached to primary inputs.
Bit ranges must be numbered with the MSB being numbered greater or the same as the LSB. Little-bit-endian busses [0:15] are not supported as they aren't easily made compatible with C++.
The division and modulus operators are limited to 32 bits. This can be easily fixed if someone contributes the appropriate wide-integer math functions.
The 2-state gate primitives (and, buf, nand, nor, not, or, xnor, xor) are directly converted to behavioral equivalents. The 3-state and MOS gate primitives are not supported. Tables are not supported.
All specify blocks and timing checks are ignored.
When initializing an array, you need to use non-delayed assignments. This is done in the interest of speed; if delayed assignments were used, the simulator would have to copy large arrays every cycle. (In smaller loops, loop unrolling allows the delayed assignment to work, though it's a bit slower than a non-delayed assignment.) Here's an example
always @ (posedge clk) if (~reset_l) begin for (i=0; i<`ARRAY_SIZE; i++) begin array[i] = 0; // Non-delayed for verilator end
Writing a memory element that is outside the bounds specified for the array may cause a different memory element inside the array to be written instead. For power-of-2 sized arrays, Verilator will give a width warning and the address. For non-power-of-2-sizes arrays, index 0 will be written.
Reading a memory element that is outside the bounds specified for the array will give a width warning and wrap around the power-of-2 size. For non-power-of-2 sizes, it will return a unspecified constant of the appropriate width.
Verilator is beginning to add support for assertions. Verilator currently only converts assertions to simple ``if (...) error'' statements, and coverage statements to increment the line counters described in the coverage section.
Verilator does not support SEREs yet. All assertion and coverage statements must be simple expressions that complete in one cycle. (Arguably SEREs are much of the point, but one must start somewhere.)
This section describes specific limitations for each language keyword.
Warnings may be disabled in two ways. First, when the warning is printed it will include a warning code. Simply surround the offending line with a warn_off/warn_on pair:
// verilator lint_off UNSIGNED if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop; // verilator lint_on UNSIGNED
Warnings may also be globally disabled by invoking Verilator with the
-Wno-warning
switch. This should be avoided, as it removes all
checking across the designs, and prevents other users from compiling your
code without knowing the magic set of disables needed to successfully
compile your design.
List of all warnings:
always @ (posedge clk) foo[0] <= ... always @* foo[1] = ...
Simply use a different register for the flop:
always @ (posedge clk) foo_flopped[0] <= ... always @* foo[0] = foo_flopped[0]; always @* foo[1] = ...
This is good coding practice anyways.
It is also possible to disable this error when one of the assignments is inside a public task.
Ignoring this warning may make Verilator simulations differ from other simulators.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
?
in place of
x
's. See
http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf
Ignoring this warning will only suppress the lint check, it will simulate correctly.
x
. Verilator is
two-state so interpret such items as always false. Note a common error is
to use a X
in a case or casez statement item; often what the user
instead insteaded is to use a casez with ?
.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
Ignoring this warning may make Verilator simulations differ from other simulators.
Ignoring this warning may make Verilator simulations differ from other simulators.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
Ignoring this warning may make Verilator simulations differ from other simulators.
Ignoring this warning will only slow simulations, it will simulate correctly.
Often this error is because some low level cell is being read in, but is not really needed. The best solution is to insure that each module is in a unique file by the same name. Otherwise, make sure all library files are read in as libraries with -v, instead of automatically with -y.
`define MACRO def1 //... `define MACRO otherdef
The best solution is to use a different name for the second macro. If this is not possible, add a undef to indicate the code is overriding the value:
`define MACRO def1 //... `undef MACRO `define MACRO otherdef
#100 $finish;
Ignoring this warning may make Verilator simulations differ from other simulators.
task foo; output sig; ... endtask always @* begin foo(bus_we_select_from[2]); // Will get TASKNSVAR error end
Change this to:
reg foo_temp_out; always @* begin foo(foo_temp_out); bus_we_select_from[2] = foo_temp_out; end
Verilator doesn't do this conversion for you, as some more complicated cases would result in simulator mismatches.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
A less obvious case of this is when a module instantiates two submodules. Inside submodule A, signal I is input and signal O is output. Likewise in submodule B, signal O is an input and I is an output. A loop exists and a UNOPT warning will result if AI & AO both come from and go to combinatorial blocks in both submodules, even if they are unrelated always blocks. This affects performance because Verilator would have to evaluate each submodule multiple times to stabilize the signals crossing between the modules.
Ignoring this warning will only slow simulations, it will simulate correctly.
Unlike the UNOPT warning, this occurs after netlist flattening, and indicates a more basic problem, as the less obvious case described under UNOPT does not apply.
Often UNOPTFLAT is caused by logic that isn't truly circular as viewed by synthesis which analyzes interconnection per-bit, but is circular to simulation which analyzes per-bus:
wire [2:0] x = {x[1:0],shift_in};
This statement needs to be evaluated multiple times, as a change in ``shift_in'' requires ``x'' to be computed 3 times before it becomes stable. This is because a change in ``x'' requires ``x'' itself to change value, which causes the warning.
For significantly better performance, split this into 2 separate signals:
wire [2:0] xout = {x[1:0],shift_in};
and change all receiving logic to instead receive ``xout''. Alternatively, change it to
wire [2:0] x = {xin[1:0],shift_in};
and change all driving logic to instead drive ``xin''.
With this change this assignment needs to be evaluated only once. These sort of changes may also speed up your traditional event driven simulator, as it will result in fewer events per cycle.
The most complicated UNOPTFLAT path we've seen was due to low bits of a bus being generated from an always statement that consumed high bits of the same bus processed by another series of always blocks. The fix is the same; split it into two separate signals generated from each block.
The UNOPTFLAT warning may also be due to clock enables, identified from the reported path going through a clock gating cell. To fix these, use the clock_enable meta comment described above.
The UNOPTFLAT warning may also occur where outputs from a block of logic are independent, but occur in the same always block. To fix this, use the isolate_assignments meta comment described above.
Ignoring this warning will only slow simulations, it will simulate correctly.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
Ignoring this warning will only suppress the lint check, it will simulate correctly.
If it's a constant 0 that's 32 bits or less, simply leave it unwidthed. Verilator considers zero to be any width needed.
Concatenate leading zeros when doing arithmetic. In the statement
wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0];
The best fix, which clarifies intent and will also make all tools happy is:
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
Ignoring this warning will only suppress the lint check, it will simulate correctly.
wire [63:0] concat = {1,2};
An example where this is technically legal (though still bad form) is:
parameter PAR = 1; wire [63:0] concat = {PAR,PAR};
The correct fix is to either size the 1 (``32'h1''), or add the width to the parameter definition (``parameter [31:0]''), or add the width to the parameter usage (``{PAR[31:0],PAR[31:0]}''.
The following describes the less obvious errors:
always @ (a) b=~a; always @ (b) a=b
will toggle forever and thus the executable will give the didn't converge error to prevent an infinite loop.
To debug this, run Verilator with --profile-cfuncs. Run make on the generated files with ``OPT=-DVL_DEBUG''. Then call Verilated::debug(1) in your main.cpp.
This will cause each change in a variable to print a message. Near the bottom you'll see the code and variable that causes the problem. For the program above:
CHANGE: filename.v:1: b CHANGE: filename.v:2: a
Note people sometimes request binaries when they are having problems with their C++ compiler. Alas, binaries won't help this, as in the end a fully working C++ compiler is required to compile the output of Verilator.
Most commercial simulators have to be Verilog compliant, meaning event driven. This prevents them from being able to reorder blocks and make netlist-style optimizations, which are where most of the gains come from.
Non-compliance shouldn't be scary. Your synthesis program isn't compliant, so your simulator shouldn't have to be -- and Verilator is closer to the synthesis interpretation, so this is a good thing for getting working silicon.
You also have the option of using the Perl Artistic License, which again does not require you release your Verilog or generated code.
Add the --trace switch to Verilator, and make sure the SystemPerl package is installed. SystemC itself does not need to be installed for C++ only tracing. You do not even need to compile SystemPerl; you may simply untar the SystemPerl kit and point the SYSTEMPERL environment variable to the untarred directory.
In your top level C code, call Verilated::traceEverOn(true). Then create a SpTraceVcdC object, and in your main loop call ``trace_object->dump(time)'' every time step, and finally call ``trace_object->close()''. For an example, see the call to SpTraceVcdC in the test_c/sim_main.cpp file of the distribution.
You also need to compile SpTraceVcdC.cpp and add it to your link. This is done for you if using the Verilator --exe flag.
In your top level C sc_main code, call Verilated::traceEverOn(true). Then create a SpTraceFile object as you would create a normal SystemC trace file. For an example, see the call to SpTraceFile in the test_sp/sc_main.cpp file of the distribution.
`ifndef verilator Something_Verilator_Dislikes; `endif
`begin_keywords "1364-2001" integer bit; initial bit = 1; `end_keywords
If you want the whole file to be parsed as Verilog 2001, just create a file with
`begin_keywords "1364-2001"
and add it before other Verilog files on the command line. (Note this will also change the default for --prefix, so if you're not using --prefix, you will now need to.)
More specifically, the common PLI-ish calls $display, $finish, $stop, $time, $write are converted to C++ equivalents. If you want something more complex, since Verilator emits standard C++ code, you can simply write your own C++ routines that can access and modify signal values without needing any PLI interface code, and call it with $c(``{any_c++_statement}'').
Verilog inputs of one bit become C++ bool inputs. Inputs 32 bits or smaller become C uint32_t inputs, 64-32 bits become C uint64_t inputs, and wider signals become arrays of 32 bits. Outputs are passed as references to bool, uint32_t, uint64_t or uint32_t[] arrays.
Signals wider than 64 bits are passed as an array of 32-bit uint32_t's. Thus to read bits 31:0, access signal[0], and for bits 63:32, access signal[1]. Unused bits (for example bit numbers 65-96 of a 65 bit vector) will always be zero. if you change the value you must make sure to pack zeros in the unused bits or core-dumps may result. (Because Verilator strips array bound checks where it believes them to be unnecessary.)
In the SYSTEMC example above, if you had in our.v:
task publicSetBool; // verilator public input in_bool; var_bool = in_bool; endtask
From the sc_main.cpp file, you'd then:
#include "Vour.h" #include "Vour_our.h" top->v.publicSetBool(value);
See additional notes under the /*verilator public*/ section.
If you really want raw access to the signals, declare the signals you will be accessing with a /*verilator public*/ comment before the closing semicolon. Then scope into the C++ class to read the value of the signal, as you would any other member variable.
Signals are the smallest of 8 bit chars, 16 bit shorts, 32 bit longs, or 64 bit long longs that fits the width of the signal. Generally, you can use just uint32_t's for 1 to 32 bits, or uint64_t for 1 to 64 bits, and the compiler will properly up-convert smaller entities.
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's. Thus to read bits 31:0, access signal[0], and for bits 63:32, access signal[1]. Unused bits (for example bit numbers 65-96 of a 65 bit vector) will always be zero. if you change the value you must make sure to pack zeros in the unused bits or core-dumps may result. (Because Verilator strips array bound checks where it believes them to be unnecessary.)
In the SYSTEMC example above, if you had in our.v:
input clk /*verilator public*/;
From the sc_main.cpp file, you'd then:
#include "Vour.h" #include "Vour_our.h" cout << "clock is " << top->v.clk << endl;
In this example, clk is a bool you can read or set as any other variable. The value of normal signals may be set, though clocks shouldn't be changed by your code or you'll get strange results.
A module with only SystemC cells below must be SystemC.
A module with a mix of Verilog and SystemC cells below must be SystemC. (As Verilator cannot connect to lower-level SystemC cells.)
A module with only Verilog cells below can be either, but for best performance should be Verilog. (The exception is if you have a design that is instantiated many times; in this case Verilating one of the lower modules and instantiating that Verilated cells multiple times into a SystemC module *may* be faster.)
First, check the the coding limitations section.
Next, try the --debug switch. This will enable additional internal assertions, and may help identify the problem.
Finally, reduce your code to the smallest possible routine that exhibits the bug. Even better, create a test in the test_regress/t directory, as follows:
cd test_regress cp -p t/t_EXAMPLE.pl t/t_BUG.pl cp -p t/t_EXAMPLE.v t/t_BUG.v
Edit t/t_BUG.pl to suit your example; you can do anything you want in the Verilog code there; just make sure it retains the single clk input and no outputs. Now, the following should fail:
cd test_regress t/t_BUG.pl
Finally, report the bug using the bug tracker at
http://www.veripool.org/verilator. The bug will become publicly
visible; if this is unacceptable, mail the bug report to
wsnyder@wsnyder.org
.
Verilator was conceived in 1994 by Paul Wasson at the Core Logic Group at Digital Equipment Corporation. The Verilog code that was converted to C was then merged with a C based CPU model of the Alpha processor and simulated in a C based environment called CCLI.
In 1995 Verilator started being used also for Multimedia and Network Processor development inside Digital. Duane Galbi took over active development of Verilator, and added several performance enhancements. CCLI was still being used as the shell.
In 1998, through the efforts of existing DECies, mainly Duane Galbi, Digital graciously agreed to release the source code. (Subject to the code not being resold, which is compatible with the GNU Public License.)
In 2001, Wilson Snyder took the kit, and added a SystemC mode, and called it Verilator2. This was the first packaged public release.
In 2002, Wilson Snyder created Verilator3 by rewriting Verilator from scratch in C++. This added many optimizations, yielding about a 2-5x performance gain.
Currently, various language features and performance enhancements are added as the need arises. Verilator is now about 2x faster than in 2002, and is faster than many popular commercial simulators.
Many people have provided ideas and other assistance with Verilator.
The major corporate sponsors of Verilator, by providing funds or equipment grants, are Compaq Corporation, Digital Equipment Corporation, Maker Communications, Sun Microsystems, Nauticus Networks, and SiCortex.
The people who have contributed code or other major functionality are Paul Wasson, Duane Galbi, and Wilson Snyder. Major testers include Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
Some of the people who have provided ideas and feedback for Verilator include Hans Van Antwerpen, Jens Arm, David Black, Gregg Bouchard, Chris Boumenot, John Brownlee, Lauren Carlson, Robert A. Clark, John Deroo, Danny Ding, Jeff Dutton, Eugen Fekete, Sam Gladstone, Thomas Hawkins, Mike Kagen, Ralf Karge, Dan Katz, Sol Katzman, Gernot Koch, Steve Kolecki, Steve Lang, Charlie Lind, Dan Lussier, Fred Ma, Wim Michiels, John Murphy, Richard Myers, Paul Nitza, Lisa Noack, Renga Sundararajan, Shawn Wang, Greg Waters, Eugene Weber, Leon Wildman, and Mat Zeno.
The latest version is available from http://www.veripool.org/.
Copyright 2003-2008 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 or the Perl Artistic License.
Wilson Snyder <wsnyder@wsnyder.org>
Major concepts by Paul Wasson and Duane Galbi.
verilator_profcfunc, systemperl, vcoverage, make