Add -x-initial-edge, bug570. by Jeremy Bennett; from BENNETT/initial-edge branch.

This commit is contained in:
Wilson Snyder 2012-11-02 19:55:34 -04:00
parent 0e921b5dff
commit 61e8836fbd
9 changed files with 223 additions and 16 deletions

View File

@ -13,6 +13,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix missing var access functions when no DPI, bug572. [Amir Gonnen]
**** Add -x-initial-edge, bug570. [Jeremy Bennett]
* Verilator 3.841 2012/09/03

View File

@ -326,7 +326,8 @@ descriptions in the next sections for more information.
-Wno-lint Disable all lint warnings
-Wno-style Disable all style warnings
-Wno-fatal Disable fatal exit on warnings
-x-assign <mode> Initially assign Xs to this value
--x-assign <mode> Initially assign Xs to this value
--x-initial-edge Enable initial X->0 and X->1 edge triggers
-y <dir> Directory to search for modules
@ -359,7 +360,8 @@ with the --exe option.
Enable all assertions, includes enabling the --psl flag. (If psl is not
desired, but other assertions are, use --assert --nopsl.)
See also --x-assign; setting "--x-assign unique" may be desirable.
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
and/or "--x-initial-edge" may be desirable.
=item --autoflush
@ -1000,29 +1002,63 @@ Enable all code style related warning messages. This is equivalent to
-Wwarn-PINNOCONNECT -Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED
-Wwarn-VARHIDDEN".
=item -x-assign 0
=item --x-assign 0
=item -x-assign 1
=item --x-assign 1
=item -x-assign fast (default)
=item --x-assign fast (default)
=item -x-assign unique
=item --x-assign unique
Controls the two-state value that is replaced when an assignment to X is
encountered. -x-assign=fast, the default, converts all Xs to whatever is
best for performance. -x-assign=0 converts all Xs to 0s, and is also fast.
-x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
likely to find reset bugs as active high logic will fire. -x-assign=unique
encountered. --x-assign=fast, the default, converts all Xs to whatever is
best for performance. --x-assign=0 converts all Xs to 0s, and is also fast.
--x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
likely to find reset bugs as active high logic will fire. --x-assign=unique
will call a function to determine the value, this allows randomization of
all Xs to find reset bugs and is the slowest, but safest for finding reset
bugs in code.
If using -x-assign unique, you may want to seed your random number
If using --x-assign unique, you may want to seed your random number
generator such that each regression run gets a different randomization
sequence. Use the system's srand48() or for Windows srand() function to do
this. You'll probably also want to print any seeds selected, and code to
enable rerunning with that same seed so you can reproduce bugs.
B<Note.> This option applies only to variables which are explicitly assigned
to X in the Verilog source code. Initial values of clocks are set to 0 unless
--x-initial-edge is specified. Initial values of all other state holding
variables are set as though --x-assign unique had been specified.
=item --x-initial-edge
Enables emulation of event driven simulators which generally trigger an
edge on a transition from X to 1 (C<posedge>) or X to 0 (C<negedge>). Thus
the following code, where C<rst_n> is uninitialized would set C<res_n> to
C<1'b1> when C<rst_n> is first set to zero:
reg res_n = 1'b0;
always @(negedge rst_n) begin
if (rst_n == 1'b0) begin
res_n <= 1'b1;
end
end
In Verilator, by default, uninitialized clocks are given a value of zero,
so the above C<always> block would not trigger.
While it is not good practice, there are some designs that rely on X
E<rarr> 0 triggering a C<negedge>, particularly in reset sequences. Using
--x-initial-edge with Verilator will replicate this behaviour. It will also
ensure that X E<rarr> 1 triggers a C<posedge>.
B<Note.> Some users have reported that using this option can affect
convergence, and that it may be necessary to use --converge-limit to
increase the number of convergence iterations. This may be another
indication of problems with the modelled design that should be addressed.
=item -y I<dir>
Add the directory to the list of directories that should be searched for
@ -1183,9 +1219,9 @@ the test_sp directory in the distribution for an example.
=head1 BENCHMARKING & OPTIMIZATION
For best performance, run Verilator with the "-O3 -x-assign=fast
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
--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
@ -2267,7 +2303,7 @@ from a four state simulator. An === comparison to X will always be false,
so that Verilog code which checks for uninitialized logic will not fire.
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
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.
@ -2279,6 +2315,18 @@ 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.
B<Note.> --x-assign applies to variables explicitly initialized or assigned to
X. Unititialized clocks are initialized to zero, while all other state holding
variables are initialized to a random value.
Event driven simulators will generally trigger an edge on a transition from X
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
are initialized to zero, Verilator will not trigger an initial negedge. Some
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
runs with and without this switch will find such problems.
=head2 Tri/Inout
Verilator converts some simple tristate structures into two state. Pullup,

View File

@ -83,7 +83,7 @@ private:
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
AstVar* varp = vscp->varp();
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->name());
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
m_modp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);

View File

@ -1368,7 +1368,16 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
puts(varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
if (zeroit) {
puts(" = 0;\n");
// We want to force an initial edge on uninitialized clocks (from 'X' to
// whatever the first value is). Since the class is instantiated before
// initial blocks are evaluated, this should not clash with any initial
// block settings. Clocks are always BIT datatypes, so zeroit is true.
if (v3Global.opt.xInitialEdge()
&& (0 == varp->name().find("__Vclklast__"))) {
puts(" = 1;\n");
} else {
puts(" = 0;\n");
}
} else {
puts(" = VL_RAND_RESET_");
emitIQW(varp);

View File

@ -700,6 +700,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = flag; }
else if ( onoff (sw, "-trace-underscore", flag/*ref*/) ) { m_traceUnderscore = flag; }
else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2
else if ( onoff (sw, "-x-initial-edge", flag/*ref*/) ) { m_xInitialEdge = flag; }
else if ( onoff (sw, "-xml-only", flag/*ref*/) ) { m_xmlOnly = flag; } // Undocumented, still experimental
// Optimization
else if ( !strncmp (sw, "-O", 2) ) {
@ -1144,6 +1145,7 @@ V3Options::V3Options() {
m_traceDups = false;
m_traceUnderscore = false;
m_underlineZero = false;
m_xInitialEdge = false;
m_xmlOnly = false;
m_convergeLimit = 100;

View File

@ -124,6 +124,7 @@ class V3Options {
bool m_traceDups; // main switch: --trace-dups
bool m_traceUnderscore;// main switch: --trace-underscore
bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2
bool m_xInitialEdge; // main switch: --x-initial-edge
bool m_xmlOnly; // main switch: --xml-netlist
int m_convergeLimit;// main switch: --converge-limit
@ -252,6 +253,7 @@ class V3Options {
bool lintOnly() const { return m_lintOnly; }
bool ignc() const { return m_ignc; }
bool inhibitSim() const { return m_inhibitSim; }
bool xInitialEdge() const { return m_xInitialEdge; }
bool xmlOnly() const { return m_xmlOnly; }
int convergeLimit() const { return m_convergeLimit; }

View File

@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program 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.
compile (
verilator_flags2 => ["--x-initial-edge"]
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,101 @@
// DESCRIPTION: Verilator: initial edge issue
//
// The module initial_edge drives the output "res" high when the reset signal,
// rst, goes high.
//
// The module initial_edge_n drives the output "res_n" high when the reset
// signal, rst_n, goes low.
//
// For 4-state simulators, that edge occurs when the initial value of rst_n,
// X, goes to zero. However, by default for Verilator, being 2-state, the
// initial value is zero, so no edge is seen.
//
// This is not a bug in verilator (it is bad design to rely on an edge
// transition from an unitialized signal), but the problem is that there are
// quite a few instances of code out there that seems to be dependent on this
// behaviour to get out of reset.
//
// The Verilator --x-initial-edge flag causes these initial edges to trigger,
// thus matching the behaviour of a 4-state simulator. This is reportedly also
// the behaviour of commercial cycle accurate modelling tools as well.
//
// This file ONLY is placed into the Public Domain, for any use, without
// warranty, 2012 by Wilson Snyder.
`timescale 1ns/1ns
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
wire res;
wire res_n;
reg rst;
reg rst_n;
integer count = 0;
initial_edge i_edge (.res (res),
.rst (rst));
initial_edge_n i_edge_n (.res_n (res_n),
.rst_n (rst_n));
// run for 3 cycles, with one cycle of reset.
always @(posedge clk) begin
rst <= (count == 0) ? 1 : 0;
rst_n <= (count == 0) ? 0 : 1;
if (count == 3) begin
if ((res == 1) && (res_n == 1)) begin
$write ("*-* All Finished *-*\n");
$finish;
end
else begin
`ifdef TEST_VERBOSE
$write ("FAILED: res = %b, res_n = %b\n", res, res_n);
`endif
$stop;
end
end
count = count + 1;
end
endmodule
module initial_edge_n (res_n,
rst_n);
output res_n;
input rst_n;
reg res_n = 1'b0;
always @(negedge rst_n) begin
if (rst_n == 1'b0) begin
res_n <= 1'b1;
end
end
endmodule // initial_edge_n
module initial_edge (res,
rst);
output res;
input rst;
reg res = 1'b0;
always @(posedge rst) begin
if (rst == 1'b1) begin
res <= 1'b1;
end
end
endmodule // initial_edge

View File

@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program 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.
top_filename("t/t_initial_edge.v");
# This works with other simulators, we we don't run it for them. It should
# fail with Verilator if --x-initial-edge is not specified.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
);
execute (
fails => 1,
);
ok(1);
1;