mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add -x-initial-edge, bug570. by Jeremy Bennett; from BENNETT/initial-edge branch.
This commit is contained in:
parent
0e921b5dff
commit
61e8836fbd
2
Changes
2
Changes
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
19
test_regress/t/t_initial_edge.pl
Executable file
19
test_regress/t/t_initial_edge.pl
Executable 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;
|
101
test_regress/t/t_initial_edge.v
Normal file
101
test_regress/t/t_initial_edge.v
Normal 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
|
24
test_regress/t/t_initial_edge_bad.pl
Executable file
24
test_regress/t/t_initial_edge_bad.pl
Executable 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;
|
Loading…
Reference in New Issue
Block a user