diff --git a/Changes b/Changes index e3bcd9482..b71ce4471 100644 --- a/Changes +++ b/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 diff --git a/bin/verilator b/bin/verilator index 98739f877..6e2dcf474 100755 --- a/bin/verilator +++ b/bin/verilator @@ -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 Initially assign Xs to this value + --x-assign Initially assign Xs to this value + --x-initial-edge Enable initial X->0 and X->1 edge triggers -y 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 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) or X to 0 (C). Thus +the following code, where C is uninitialized would set C to +C<1'b1> when C 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 block would not trigger. + +While it is not good practice, there are some designs that rely on X +E 0 triggering a C, particularly in reset sequences. Using +--x-initial-edge with Verilator will replicate this behaviour. It will also +ensure that X E 1 triggers a C. + +B 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 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 --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) or X to 0 (C). 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, diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 946b4ada5..99a71ed65 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -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: "<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); diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 9aa214a8c..46356f464 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1368,7 +1368,16 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) { puts(varp->name()); for (int v=0; vname().find("__Vclklast__"))) { + puts(" = 1;\n"); + } else { + puts(" = 0;\n"); + } } else { puts(" = VL_RAND_RESET_"); emitIQW(varp); diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 53e40dd57..37ab6c8f1 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -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; diff --git a/src/V3Options.h b/src/V3Options.h index c4136e58f..fd7f4fc24 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -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; } diff --git a/test_regress/t/t_initial_edge.pl b/test_regress/t/t_initial_edge.pl new file mode 100755 index 000000000..8a07c2001 --- /dev/null +++ b/test_regress/t/t_initial_edge.pl @@ -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; diff --git a/test_regress/t/t_initial_edge.v b/test_regress/t/t_initial_edge.v new file mode 100644 index 000000000..f45fce583 --- /dev/null +++ b/test_regress/t/t_initial_edge.v @@ -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 diff --git a/test_regress/t/t_initial_edge_bad.pl b/test_regress/t/t_initial_edge_bad.pl new file mode 100755 index 000000000..f8eccd9c8 --- /dev/null +++ b/test_regress/t/t_initial_edge_bad.pl @@ -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;