diff --git a/bin/verilator b/bin/verilator index 55d14a92b..28f8e6094 100755 --- a/bin/verilator +++ b/bin/verilator @@ -238,7 +238,6 @@ descriptions in the next sections for more information. --trace Enable waveform creation --trace-depth Depth of tracing -U Undefine preprocessor define - --underline-zero Zero signals with leading _'s --unroll-count Tune maximum loop iterations --unroll-stmts Tune maximum loop body size -V Verbose version and config @@ -628,13 +627,6 @@ Specify the number of levels deep to enable tracing, for example entire model. Using a small number will decrease visibility, but greatly improve runtime and trace file size. -=item --underline-zero - -Rarely needed. Signals starting with a underline should be initialized to -zero, as was done in Verilator 2. Default is for all signals including -those with underlines being randomized. This option may be depreciated in -future versions. - =item --unroll-count I Rarely needed. Specifies the maximum number of loop iterations that may be diff --git a/src/V3Ast.h b/src/V3Ast.h index 9eb6da320..8a4dbcaf9 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -241,6 +241,9 @@ public: int isFourstate() const { return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT; } + int isZeroInit() const { // Otherwise initializes to X + return m_e==BIT || m_e==BYTE || m_e==INT || m_e==LONGINT || m_e==SHORTINT; + } int isSloppy() const { // Don't be as anal about width warnings return !(m_e==LOGIC || m_e==BIT); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index d554fed05..b20683d08 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -231,6 +231,7 @@ public: virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... bool isBitLogic() const { return keyword().isBitLogic(); } bool isSloppy() const { return keyword().isSloppy(); } + bool isZeroInit() const { return keyword().isZeroInit(); } int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); } int lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); } int msbEndianed() const { if (!rangep()) return 0; return littleEndian()?rangep()->lsbConst():rangep()->msbConst(); } diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 893d7b165..ec20f277c 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1238,6 +1238,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) { puts("; ++"+ivar+") {\n"); } bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen + || (varp->basicp() && varp->basicp()->isZeroInit()) || (varp->name().c_str()[0]=='_' && v3Global.opt.underlineZero())); if (varp->isWide()) { // DOCUMENT: We randomize everything. If the user wants a _var to be zero, diff --git a/src/V3Options.cpp b/src/V3Options.cpp index cdb7f048d..0c471253a 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -682,7 +682,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) { else if ( onoff (sw, "-stats", flag/*ref*/) ) { m_stats = flag; } else if ( onoff (sw, "-trace", flag/*ref*/) ) { m_trace = flag; } else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = flag; } - else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } + else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2 // Optimization else if ( !strncmp (sw, "-O", 2) ) { for (const char* cp=sw+strlen("-O"); *cp; ++cp) { diff --git a/src/V3Options.h b/src/V3Options.h index 88949633d..bbcbbed9d 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -116,7 +116,7 @@ class V3Options { bool m_stats; // main switch: --stats bool m_trace; // main switch: --trace bool m_traceDups; // main switch: --trace-dups - bool m_underlineZero;// main switch: --underline-zero + bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2 int m_errorLimit; // main switch: --error-limit int m_inlineMult; // main switch: --inline-mult diff --git a/test_regress/t/t_var_types.pl b/test_regress/t/t_var_types.pl index 7058e622f..3deae9536 100755 --- a/test_regress/t/t_var_types.pl +++ b/test_regress/t/t_var_types.pl @@ -7,6 +7,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. +$Self->{verilated_randReset} = 1; # allow checking if we initialize vars to zero only when needed + compile ( ); diff --git a/test_regress/t/t_var_types.v b/test_regress/t/t_var_types.v index 86cd084ef..bd895b90f 100644 --- a/test_regress/t/t_var_types.v +++ b/test_regress/t/t_var_types.v @@ -48,54 +48,66 @@ module t (/*AUTOARG*/); localparam logic [1:0] p_logic2= {96{1'b1}}; // verilator lint_on WIDTH + // We do this in two steps so we can check that initialization inside functions works properly // verilator lint_off WIDTH - function f_implicit; f_implicit = {96{1'b1}}; endfunction - function [89:0] f_explicit; f_explicit = {96{1'b1}}; endfunction - function byte f_byte; f_byte = {96{1'b1}}; endfunction - function shortint f_shortint; f_shortint = {96{1'b1}}; endfunction - function int f_int; f_int = {96{1'b1}}; endfunction - function longint f_longint; f_longint = {96{1'b1}}; endfunction - function integer f_integer; f_integer = {96{1'b1}}; endfunction - function reg f_reg; f_reg = {96{1'b1}}; endfunction - function bit f_bit; f_bit = {96{1'b1}}; endfunction - function logic f_logic; f_logic = {96{1'b1}}; endfunction - function reg [1:0] f_reg2; f_reg2 = {96{1'b1}}; endfunction - function bit [1:0] f_bit2; f_bit2 = {96{1'b1}}; endfunction - function logic [1:0] f_logic2; f_logic2 = {96{1'b1}}; endfunction - function time f_time; f_time = {96{1'b1}}; endfunction + function f_implicit; reg lv_implicit; f_implicit = lv_implicit; endfunction + function [89:0] f_explicit; reg [89:0] lv_explicit; f_explicit = lv_explicit; endfunction + function byte f_byte; byte lv_byte; f_byte = lv_byte; endfunction + function shortint f_shortint; shortint lv_shortint; f_shortint = lv_shortint; endfunction + function int f_int; int lv_int; f_int = lv_int; endfunction + function longint f_longint; longint lv_longint; f_longint = lv_longint; endfunction + function integer f_integer; integer lv_integer; f_integer = lv_integer; endfunction + function reg f_reg; reg lv_reg; f_reg = lv_reg; endfunction + function bit f_bit; bit lv_bit; f_bit = lv_bit; endfunction + function logic f_logic; logic lv_logic; f_logic = lv_logic; endfunction + function reg [1:0] f_reg2; reg [1:0] lv_reg2; f_reg2 = lv_reg2; endfunction + function bit [1:0] f_bit2; bit [1:0] lv_bit2; f_bit2 = lv_bit2; endfunction + function logic [1:0] f_logic2; logic [1:0] lv_logic2; f_logic2 = lv_logic2; endfunction + function time f_time; time lv_time; f_time = lv_time; endfunction // verilator lint_on WIDTH -`define CHECK_ALL(name,bits,issigned,twostate) \ +`ifdef verilator + // For verilator zeroinit detection to work properly, we need to x-rand-reset to all 1s. This is the default! + `define XINIT 1'b1 + `define ALL_TWOSTATE 1'b1 +`else + `define XINIT 1'bx + `define ALL_TWOSTATE 1'b0 +`endif + +`define CHECK_ALL(name,nbits,issigned,twostate,zeroinit) \ + if (zeroinit ? ((name & 1'b1)!==1'b0) : ((name & 1'b1)!==`XINIT)) \ + begin $display("%%Error: Bad zero/X init for %s: %b",`"name`",name); $stop; end \ name = {96{1'b1}}; \ - if (name !== {(bits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \ + if (name !== {(nbits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \ if (issigned ? (name > 0) : (name < 0)) begin $display("%%Error: Bad signed for %s",`"name`"); $stop; end \ name = {96{1'bx}}; \ - -//Everything is twostate in Verilator -// if (name !== {(bits){twostate ? 1'b0 : 1'bx}}) begin $display("%%Error: Bad twostate for %s",`"name`"); $stop; end \ + if (name !== {(nbits){`ALL_TWOSTATE ? `XINIT : (twostate ? 1'b0 : `XINIT)}}) \ + begin $display("%%Error: Bad twostate for %s: %b",`"name`",name); $stop; end \ initial begin // verilator lint_off WIDTH // verilator lint_off UNSIGNED - // name b sign twost - `CHECK_ALL(d_byte ,8 ,1'b1,1'b1); - `CHECK_ALL(d_shortint ,16,1'b1,1'b1); - `CHECK_ALL(d_int ,32,1'b1,1'b1); - `CHECK_ALL(d_longint ,64,1'b1,1'b1); - `CHECK_ALL(d_integer ,32,1'b1,1'b0); - `CHECK_ALL(d_time ,64,1'b0,1'b1); - `CHECK_ALL(d_bit ,1 ,1'b0,1'b1); - `CHECK_ALL(d_logic ,1 ,1'b0,1'b0); - `CHECK_ALL(d_reg ,1 ,1'b0,1'b0); - `CHECK_ALL(d_bit2 ,2 ,1'b0,1'b1); - `CHECK_ALL(d_logic2 ,2 ,1'b0,1'b0); - `CHECK_ALL(d_reg2 ,2 ,1'b0,1'b0); + // name b sign twost 0init + `CHECK_ALL(d_byte ,8 ,1'b1,1'b1,1'b1); + `CHECK_ALL(d_shortint ,16,1'b1,1'b1,1'b1); + `CHECK_ALL(d_int ,32,1'b1,1'b1,1'b1); + `CHECK_ALL(d_longint ,64,1'b1,1'b1,1'b1); + `CHECK_ALL(d_integer ,32,1'b1,1'b0,1'b0); + `CHECK_ALL(d_time ,64,1'b0,1'b0,1'b0); + `CHECK_ALL(d_bit ,1 ,1'b0,1'b1,1'b1); + `CHECK_ALL(d_logic ,1 ,1'b0,1'b0,1'b0); + `CHECK_ALL(d_reg ,1 ,1'b0,1'b0,1'b0); + `CHECK_ALL(d_bit2 ,2 ,1'b0,1'b1,1'b1); + `CHECK_ALL(d_logic2 ,2 ,1'b0,1'b0,1'b0); + `CHECK_ALL(d_reg2 ,2 ,1'b0,1'b0,1'b0); // verilator lint_on WIDTH // verilator lint_on UNSIGNED -`define CHECK_P(name,bits) \ - if (name !== {(bits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \ +`define CHECK_P(name,nbits) \ + if (name !== {(nbits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \ + // name b `CHECK_P(p_implicit ,96); `CHECK_P(p_explicit ,90); `CHECK_P(p_byte ,8 ); @@ -110,23 +122,24 @@ module t (/*AUTOARG*/); `CHECK_P(p_logic2 ,2 ); `CHECK_P(p_reg2 ,2 ); -`define CHECK_F(name,bits) \ - if (name() !== {(bits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \ +`define CHECK_F(fname,nbits,zeroinit) \ + if ($bits(fname()) !== nbits) begin $display("%%Error: Bad size for %s",`"fname`"); $stop; end \ - `CHECK_F(f_implicit ,1 ); // Note 1 bit, not 96 - `CHECK_F(f_explicit ,90); - `CHECK_F(f_byte ,8 ); - `CHECK_F(f_shortint ,16); - `CHECK_F(f_int ,32); - `CHECK_F(f_longint ,64); - `CHECK_F(f_integer ,32); - `CHECK_F(f_time ,64); - `CHECK_F(f_bit ,1 ); - `CHECK_F(f_logic ,1 ); - `CHECK_F(f_reg ,1 ); - `CHECK_F(f_bit2 ,2 ); - `CHECK_F(f_logic2 ,2 ); - `CHECK_F(f_reg2 ,2 ); + // name b 0init + `CHECK_F(f_implicit ,1 ,1'b0); // Note 1 bit, not 96 + `CHECK_F(f_explicit ,90,1'b0); + `CHECK_F(f_byte ,8 ,1'b1); + `CHECK_F(f_shortint ,16,1'b1); + `CHECK_F(f_int ,32,1'b1); + `CHECK_F(f_longint ,64,1'b1); + `CHECK_F(f_integer ,32,1'b0); + `CHECK_F(f_time ,64,1'b0); + `CHECK_F(f_bit ,1 ,1'b1); + `CHECK_F(f_logic ,1 ,1'b0); + `CHECK_F(f_reg ,1 ,1'b0); + `CHECK_F(f_bit2 ,2 ,1'b1); + `CHECK_F(f_logic2 ,2 ,1'b0); + `CHECK_F(f_reg2 ,2 ,1'b0); // For unpacked types we don't want width warnings for unsized numbers that fit d_byte = 2;