mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add --x-initial option
This commit is contained in:
commit
33780a09df
4
Changes
4
Changes
@ -7,7 +7,9 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
** Added new examples/ directory with appropriate examples. This replaces the
|
||||
old test_c and test_sc directories.
|
||||
|
||||
*** Add --getenv option.
|
||||
*** Add --getenv option for simplifying Makefiles.
|
||||
|
||||
*** Add --x-initial option for specifying initial value assignment behavior.
|
||||
|
||||
**** The internal test_verilated test directory is moved to be part of test_regress.
|
||||
|
||||
|
@ -359,7 +359,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> Assign non-initial Xs to this value
|
||||
--x-initial <mode> Assign initial Xs to this value
|
||||
--x-initial-edge Enable initial X->0 and X->1 edge triggers
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
@ -429,9 +430,6 @@ C<+1364-1995ext+> etc. specify both the syntax I<and> semantics to be used.
|
||||
|
||||
Enable all assertions.
|
||||
|
||||
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
|
||||
and/or "--x-initial-edge" may be desirable.
|
||||
|
||||
=item --autoflush
|
||||
|
||||
After every $display or $fdisplay, flush the output stream. This insures
|
||||
@ -1307,7 +1305,30 @@ 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.
|
||||
variables are controlled with --x-initial.
|
||||
|
||||
=item --x-initial 0
|
||||
|
||||
=item --x-initial fast
|
||||
|
||||
=item --x-initial unique (default)
|
||||
|
||||
Controls the two-state value that is used to initialize variables that are
|
||||
not otherwise initialized.
|
||||
|
||||
--x-initial=0, initializes all otherwise uninitialized variables to zero.
|
||||
|
||||
--x-initial=unique, the default, initializes variables using a function,
|
||||
which determines the value to use each initialization. This gives greatest
|
||||
flexibility and allows finding reset bugs. See L</"Unknown states">
|
||||
|
||||
--x-initial=fast, is best for performance, and initializes all variables to
|
||||
a state Verilator determines is optimal. This may allow further code
|
||||
optimizations, but will likely hide any code bugs relating to missing
|
||||
resets.
|
||||
|
||||
B<Note.> This option applies only to initial values of variables. Initial
|
||||
values of clocks are set to 0 unless --x-initial-edge is specified.
|
||||
|
||||
=item --x-initial-edge
|
||||
|
||||
@ -1502,9 +1523,10 @@ the examples directory in the distribution.
|
||||
=head1 BENCHMARKING & OPTIMIZATION
|
||||
|
||||
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.
|
||||
--x-initial=fast --noassert" flags. The -O3 flag will require longer
|
||||
compile times, and --x-assign=fast --x-initial=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
|
||||
@ -2647,24 +2669,25 @@ 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.
|
||||
|
||||
All variables are randomly 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.
|
||||
All variables, depending on --x-initial setting, are typically randomly
|
||||
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 (since typically control signals are
|
||||
active-high).
|
||||
|
||||
B<Note.> --x-assign applies to variables explicitly initialized or assigned to
|
||||
X. Uninitialized 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 (particularly 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.
|
||||
--x-assign applies to variables explicitly initialized or assigned to
|
||||
X. Uninitialized 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 (particularly for reset) may rely on X->0 triggering an edge. The
|
||||
--x-initial-edge switch enables this behavior. Comparing runs with and
|
||||
without this switch will find such problems.
|
||||
|
||||
|
||||
=head2 Tri/Inout
|
||||
|
@ -1464,7 +1464,8 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero())
|
||||
|| (v3Global.opt.xInitial() == "fast" || v3Global.opt.xInitial() == "0"));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
|
@ -864,6 +864,9 @@ void GateVisitor::optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode*
|
||||
// optimizing away this assignment, etc.
|
||||
consumerp = V3Const::constifyEdit(consumerp);
|
||||
if (debug()>=5) consumerp->dumpTree(cout,"\telimUseDne: ");
|
||||
// Some previous input edges may have disappeared, perhaps all of them.
|
||||
// If we remove the edges we can further optimize
|
||||
// See e.g t_var_overzero.v.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -993,6 +993,15 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
fl->v3fatal("Unknown setting for --x-assign: "<<argv[i]);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (sw, "-x-initial") && (i+1)<argc) {
|
||||
shift;
|
||||
if (!strcmp (argv[i], "0")) { m_xInitial="0"; }
|
||||
else if (!strcmp (argv[i], "fast")) { m_xInitial="fast"; }
|
||||
else if (!strcmp (argv[i], "unique")) { m_xInitial="unique"; }
|
||||
else {
|
||||
fl->v3fatal("Unknown setting for --x-initial: "<<argv[i]);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (sw, "-y") && (i+1)<argc ) {
|
||||
shift; addIncDirUser (parseFileArg(optdir,string (argv[i])));
|
||||
}
|
||||
|
@ -133,6 +133,7 @@ class V3Options {
|
||||
string m_topModule; // main switch: --top-module
|
||||
string m_unusedRegexp; // main switch: --unused-regexp
|
||||
string m_xAssign; // main switch: --x-assign
|
||||
string m_xInitial; // main switch: --x-initial
|
||||
|
||||
// Language is now held in FileLine, on a per-node basis. However we still
|
||||
// have a concept of the default language at a global level.
|
||||
@ -274,6 +275,7 @@ class V3Options {
|
||||
string topModule() const { return m_topModule; }
|
||||
string unusedRegexp() const { return m_unusedRegexp; }
|
||||
string xAssign() const { return m_xAssign; }
|
||||
string xInitial() const { return m_xInitial; }
|
||||
|
||||
const V3StringSet& cppFiles() const { return m_cppFiles; }
|
||||
const V3StringList& cFlags() const { return m_cFlags; }
|
||||
|
21
test_regress/t/t_flag_xinitial_0.pl
Executable file
21
test_regress/t/t_flag_xinitial_0.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/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 0"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
file_grep_not ("$Self->{obj_dir}/$Self->{VM_PREFIX}.cpp", qr/VL_RAND_RESET/);
|
||||
|
||||
ok(1);
|
||||
1;
|
23
test_regress/t/t_flag_xinitial_0.v
Normal file
23
test_regress/t/t_flag_xinitial_0.v
Normal file
@ -0,0 +1,23 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
value
|
||||
);
|
||||
|
||||
output reg [63:0] value;
|
||||
|
||||
initial begin
|
||||
`ifdef VERILATOR
|
||||
// Default is all ones, so we assume that here
|
||||
if (value != '0) $stop;
|
||||
`else
|
||||
if (value != {64{1'bx}}) $stop;
|
||||
`endif
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
21
test_regress/t/t_flag_xinitial_unique.pl
Executable file
21
test_regress/t/t_flag_xinitial_unique.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/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 unique"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.cpp", qr/VL_RAND_RESET/);
|
||||
|
||||
ok(1);
|
||||
1;
|
17
test_regress/t/t_flag_xinitial_unique.v
Normal file
17
test_regress/t/t_flag_xinitial_unique.v
Normal file
@ -0,0 +1,17 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
value
|
||||
);
|
||||
|
||||
output reg [63:0] value;
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
19
test_regress/t/t_var_overzero.pl
Executable file
19
test_regress/t/t_var_overzero.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 fast"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
172
test_regress/t/t_var_overzero.v
Normal file
172
test_regress/t/t_var_overzero.v
Normal file
@ -0,0 +1,172 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
dout,
|
||||
// Inputs
|
||||
clk, rstn, dval0, dval1
|
||||
);
|
||||
|
||||
input clk;
|
||||
input rstn;
|
||||
output wire [7:0] dout;
|
||||
|
||||
input [7:0] dval0;
|
||||
input [7:0] dval1;
|
||||
wire [7:0] dbgsel_w = '0;
|
||||
|
||||
tsub tsub (/*AUTOINST*/
|
||||
// Outputs
|
||||
.dout (dout[7:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.rstn (rstn),
|
||||
.dval0 (dval0[7:0]),
|
||||
.dval1 (dval1[7:0]),
|
||||
.dbgsel_w (dbgsel_w[7:0]));
|
||||
|
||||
endmodule
|
||||
|
||||
module tsub (/*AUTOARG*/
|
||||
// Outputs
|
||||
dout,
|
||||
// Inputs
|
||||
clk, rstn, dval0, dval1, dbgsel_w
|
||||
);
|
||||
|
||||
input clk;
|
||||
input rstn;
|
||||
input [7:0] dval0;
|
||||
input [7:0] dval1;
|
||||
input [7:0] dbgsel_w;
|
||||
output [7:0] dout;
|
||||
|
||||
wire [7:0] dout = dout0 | dout1;
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [7:0] dout0; // From sub0 of sub0.v
|
||||
wire [7:0] dout1; // From sub1 of sub1.v
|
||||
// End of automatics
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
reg [7:0] dbgsel_msk;
|
||||
always_comb begin
|
||||
reg [7:0] mask;
|
||||
mask = 8'hff;
|
||||
dbgsel_msk = (dbgsel_w & mask);
|
||||
end
|
||||
|
||||
// TODO this should optimize away, but presently does not because
|
||||
// V3Gate constifies then doesn't see all other input edges have disappeared
|
||||
reg [7:0] dbgsel;
|
||||
always @(posedge clk) begin
|
||||
if ((rstn == 0)) begin
|
||||
dbgsel <= 0;
|
||||
end
|
||||
else begin
|
||||
dbgsel <= dbgsel_msk;
|
||||
end
|
||||
end
|
||||
|
||||
sub0 sub0 (/*AUTOINST*/
|
||||
// Outputs
|
||||
.dout0 (dout0[7:0]),
|
||||
// Inputs
|
||||
.rstn (rstn),
|
||||
.clk (clk),
|
||||
.dval0 (dval0[7:0]),
|
||||
.dbgsel (dbgsel[7:0]));
|
||||
sub1 sub1 (/*AUTOINST*/
|
||||
// Outputs
|
||||
.dout1 (dout1[7:0]),
|
||||
// Inputs
|
||||
.rstn (rstn),
|
||||
.clk (clk),
|
||||
.dval1 (dval1[7:0]),
|
||||
.dbgsel (dbgsel[7:0]));
|
||||
|
||||
endmodule
|
||||
|
||||
module sub0
|
||||
(
|
||||
/*AUTOARG*/
|
||||
// Outputs
|
||||
dout0,
|
||||
// Inputs
|
||||
rstn, clk, dval0, dbgsel
|
||||
);
|
||||
|
||||
input rstn;
|
||||
input clk;
|
||||
input [7:0] dval0;
|
||||
input [7:0] dbgsel;
|
||||
output reg [7:0] dout0;
|
||||
|
||||
reg [7:0] dbgsel_d1r;
|
||||
|
||||
always_comb begin
|
||||
// verilator lint_off WIDTH
|
||||
if (((dbgsel_d1r >= 34) && (dbgsel_d1r < 65))) begin
|
||||
// verilator lint_on WIDTH
|
||||
dout0 = dval0;
|
||||
end
|
||||
else begin
|
||||
dout0 = 0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if ((rstn == 0)) begin
|
||||
dbgsel_d1r <= 0;
|
||||
end
|
||||
else begin
|
||||
dbgsel_d1r <= dbgsel;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module sub1
|
||||
(
|
||||
/*AUTOARG*/
|
||||
// Outputs
|
||||
dout1,
|
||||
// Inputs
|
||||
rstn, clk, dval1, dbgsel
|
||||
);
|
||||
|
||||
input rstn;
|
||||
input clk;
|
||||
input [7:0] dval1;
|
||||
input [7:0] dbgsel;
|
||||
output reg [7:0] dout1;
|
||||
|
||||
reg [7:0] dbgsel_d1r;
|
||||
|
||||
always_comb begin
|
||||
if (((dbgsel_d1r >= 84) && (dbgsel_d1r < 95))) begin
|
||||
dout1 = dval1;
|
||||
end
|
||||
else begin
|
||||
dout1 = 0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if ((rstn == 0)) begin
|
||||
dbgsel_d1r <= 0;
|
||||
end
|
||||
else begin
|
||||
dbgsel_d1r <= dbgsel;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user