diff --git a/Changes b/Changes index 808fe968a..aac16af60 100644 --- a/Changes +++ b/Changes @@ -17,10 +17,20 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support trig functions ($sin() etc), bug1281. [Patrick Stewart] +*** Support calling system functions as tasks, bug1285. [Joel Holdsworth] + +*** Add --no-debug-leak to reduce memory use under debug. [John Coiner] + +**** On convergence errors, show activity. [John Coiner] + **** Fix GCC 8.0 issues, bug1273. **** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard] +**** Fix verilator_coverage --annotate-min, bug1284. [Tymoteusz Blazejczyk] + +**** Fix quoting of quoted arguments. [John Coiner] + * Verilator 3.920 2018-02-01 diff --git a/bin/verilator b/bin/verilator index 6071840c0..eed2f9a31 100755 --- a/bin/verilator +++ b/bin/verilator @@ -54,18 +54,6 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||""); # We sneak a look at the flags so we can do some pre-environment checks # All flags will hit verilator... foreach my $sw (@ARGV) { - # Some special treatment for parameters to allow verilog literals for numbers - if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) { - # If there is a single quote in the parameter put it double quotes , - # else just put it in double quotes - if ($sw =~ m![\']!) { - $sw = "\"$sw\""; - } else { - $sw = "'$sw'"; - } - } else { - $sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!; - } push @Opt_Verilator_Sw, $sw; } @@ -84,16 +72,27 @@ if (! GetOptions ( pod2usage(-exitstatus=>2, -verbose=>0); } -# Determine runtime flags and run if ($opt_gdbbt && !gdb_works()) { warn "-Info: --gdbbt ignored: gdb doesn't seem to be working\n" if $Debug; $opt_gdbbt = 0; } + +# Determine runtime flags and run +# Opt_Verilator_Sw is what we want verilator to see on its argc/argv. +# Starting with that, escape all special chars for the shell; +# The shell will undo the escapes and the verilator binary should +# then see exactly the contents of @Opt_Verilator_Sw. +my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw; if ($opt_gdb) { # Generic GDB interactive run (("gdb"||$ENV{VERILATOR_GDB}) ." ".verilator_bin() - ." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'" + # Note, we must use double-quotes ("run ") + # and not single ('run ') below. Bash swallows + # escapes as you would expect in a double-quoted string. + # That's not true for a single-quoted string, where \' + # actually terminates the string -- not what we want! + ." -ex \"run ".join(' ', @quoted_sw)."\"" ." -ex 'set width 0'" ." -ex 'bt'"); } elsif ($opt_gdbbt && $Debug) { @@ -101,13 +100,12 @@ if ($opt_gdb) { run ("gdb" ." ".verilator_bin() ." --batch --quiet --return-child-result" - ." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'" + ." -ex \"run ".join(' ', @quoted_sw)."\"" ." -ex 'set width 0'" ." -ex 'bt'"); } else { # Normal, non gdb - run (verilator_bin() - ." ".join(' ',@Opt_Verilator_Sw)); + run (verilator_bin()." ".join(' ',@quoted_sw)); } #---------------------------------------------------------------------- @@ -196,6 +194,16 @@ sub run { } } +sub sh_escape { + my ($arg) = @_; + + # This is similar to quotemeta() but less aggressive. + # There's no need to escape hyphens, periods, or forward slashes + # for the shell as these have no special meaning to the shell. + $arg =~ s/([^0-9a-zA-Z_\-\.\/])/\\$1/g; + return $arg; +} + ####################################################################### ####################################################################### package main; @@ -270,6 +278,7 @@ descriptions in the next sections for more information. -D[=] Set preprocessor define --debug Enable debugging --debug-check Enable debugging assertions + --no-debug-leak Disable leaking memory in --debug mode --debugi Enable debugging at a specified level --debugi- Enable debugging a source file at a level --default-language Default language to parse @@ -627,6 +636,18 @@ to C<--dump-treei 3>). Rarely needed. Enable internal debugging assertion checks, without changing debug verbosity. Enabled automatically when --debug specified. +=item --no-debug-leak + +In --debug mode, by default Verilator intentionally leaks AstNode's +instead of freeing them, so that each node pointer is unique in the +resulting tree files and dot files. + +This option disables the leak. This may avoid out-of-memory errors +when Verilating large models in --debug mode. + +Outside of --debug mode, AstNode's should never be leaked and this option +has no effect. + =item --debugi =item --debugi- @@ -1251,8 +1272,9 @@ supports which the older version does not support. =item -Wno-I -Disable the specified warning message. This will override any lint_on -directives in the source, i.e. the warning will still not be printed. +Disable the specified warning message, or in some cases where noted here +disable an error. This will override any lint_on directives in the source, +i.e. the warning will still not be printed. =item -Wno-lint @@ -3047,13 +3069,15 @@ Simply use a different register for the flop: always @* foo[0] = foo_flopped[0]; always @* foo[1] = ... -It is also possible to disable this error when one of the assignments is -inside a public task. - This is not illegal in SystemVerilog, but a violation of good coding practice. Verilator reports this as an error, because ignoring this warning may make Verilator simulations differ from other simulators. +It is generally safe to disable this error (with a "// verilator lint_off +BLKANDNBLK" metacomment or the -Wno-BLKANDNBLK option) when one of the +assignments is inside a public task, or when the blocked and non-blocking +assignments have non-overlapping bits and structure members. + =item BLKSEQ This indicates that a blocking assignment (=) is used in a sequential diff --git a/include/verilated.cpp b/include/verilated.cpp index 6d7dfc82d..fda1c1a3a 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -430,7 +430,8 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { return out; } -WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE { +WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, + bool lsign, bool rsign) VL_MT_SAFE { // obits==lbits, rbits can be different if (rsign && VL_SIGN_W(rbits, rwp)) { int words = VL_WORDS_I(obits); @@ -450,7 +451,9 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W } return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp); } -WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) VL_MT_SAFE { +WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, QData rhs, + bool lsign, bool rsign) VL_MT_SAFE { WData rhsw[2]; VL_SET_WQ(rhsw, rhs); return VL_POWSS_WWW(obits,lbits,rbits,owp,lwp,rhsw,lsign,rsign); } @@ -982,7 +985,8 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE } } *destp = '\0'; // Terminate - if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces + // Drop trailing spaces + if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; } void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE { @@ -1239,7 +1243,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords, while (1) { int c = fgetc(fp); if (VL_UNLIKELY(c==EOF)) break; - //printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc); + //printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", + // linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc); if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; } else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; } // Skip // comments and detect /* comments @@ -1267,7 +1272,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords, //printf(" Value width=%d @%x = %c\n", width, addr, c); if (VL_UNLIKELY(addr >= static_cast(depth+array_lsb) || addr < static_cast(array_lsb))) { - VL_FATAL_MT (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array"); + VL_FATAL_MT (ofilenamep.c_str(), linenum, "", + "$readmem file address beyond bounds of array"); } else { int entry = addr - array_lsb; QData shift = hex ? VL_ULL(4) : VL_ULL(1); @@ -1296,7 +1302,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords, datap[0] |= value; } if (VL_UNLIKELY(value>=(1<> VL_BITBIT_I(bit)) /// Create two 32-bit words from quadword /// WData is always at least 2 words; does not clean upper bits -#define VL_SET_WQ(owp,data) { owp[0]=static_cast(data); owp[1]=static_cast((data)>>VL_WORDSIZE); } +#define VL_SET_WQ(owp,data) { owp[0]=static_cast(data); \ + owp[1]=static_cast((data)>>VL_WORDSIZE); } #define VL_SET_WI(owp,data) { owp[0]=static_cast(data); owp[1]=0; } -#define VL_SET_QW(lwp) ( (static_cast(lwp[0])) | (static_cast(lwp[1])<<(static_cast(VL_WORDSIZE)) )) +#define VL_SET_QW(lwp) \ + ( (static_cast(lwp[0])) \ + | (static_cast(lwp[1])<<(static_cast(VL_WORDSIZE)) )) #define _VL_SET_QII(ld,rd) ( (static_cast(ld)<(rd) ) /// Return FILE* from IData @@ -593,19 +598,26 @@ extern FILE* VL_CVT_I_FP(IData lhs); // Use a union to avoid cast-to-different-size warnings /// Return void* from QData -static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE { union { void* fp; QData q; } u; u.q=lhs; return u.fp; } +static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE { + union { void* fp; QData q; } u; u.q=lhs; return u.fp; } /// Return QData from void* -static inline QData VL_CVT_VP_Q(void* fp) VL_PURE { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; } +static inline QData VL_CVT_VP_Q(void* fp) VL_PURE { + union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; } /// Return double from QData (bits, not numerically) -static inline double VL_CVT_D_Q(QData lhs) VL_PURE { union { double d; QData q; } u; u.q=lhs; return u.d; } +static inline double VL_CVT_D_Q(QData lhs) VL_PURE { + union { double d; QData q; } u; u.q=lhs; return u.d; } /// Return QData from double (bits, not numerically) -static inline QData VL_CVT_Q_D(double lhs) VL_PURE { union { double d; QData q; } u; u.d=lhs; return u.q; } +static inline QData VL_CVT_Q_D(double lhs) VL_PURE { + union { double d; QData q; } u; u.d=lhs; return u.q; } /// Return double from QData (numeric) -static inline double VL_ITOR_D_I(IData lhs) VL_PURE { return static_cast(static_cast(lhs)); } +static inline double VL_ITOR_D_I(IData lhs) VL_PURE { + return static_cast(static_cast(lhs)); } /// Return QData from double (numeric) -static inline IData VL_RTOI_I_D(double lhs) VL_PURE { return static_cast(VL_TRUNC(lhs)); } +static inline IData VL_RTOI_I_D(double lhs) VL_PURE { + return static_cast(VL_TRUNC(lhs)); } /// Return QData from double (numeric) -static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast(VL_ROUND(lhs)); } +static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { + return static_cast(VL_ROUND(lhs)); } // Sign extend such that if MSB set, we get ffff_ffff, else 0s // (Requires clean input) @@ -616,8 +628,10 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast> 1) & VL_ULL(0x5555555555555555)) | ((ret & VL_ULL(0x5555555555555555)) << 1); // FALLTHRU + ret = (((ret >> 1) & VL_ULL(0x5555555555555555)) + | ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU case 1: - ret = ((ret >> 2) & VL_ULL(0x3333333333333333)) | ((ret & VL_ULL(0x3333333333333333)) << 2); // FALLTHRU + ret = (((ret >> 2) & VL_ULL(0x3333333333333333)) + | ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU case 2: - ret = ((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4); // FALLTHRU + ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) + | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU case 3: - ret = ((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8); // FALLTHRU + ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) + | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU case 4: - ret = ((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16); // FALLTHRU + ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) + | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU case 5: ret = ((ret >> 32) | (ret << 32)); } @@ -1694,61 +1726,75 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData // Thus we specify inputs must be clean, so we don't need to clean the output. // Note the bit shifts are always constants, so the adds in these constify out. // Casts required, as args may be 8 bit entities, and need to shift to appropriate output size -#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) (static_cast(ld)<<(rbits) | static_cast(rd)) -#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) (static_cast(ld)<<(rbits) | static_cast(rd)) -#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) (static_cast(ld)<<(rbits) | static_cast(rd)) -#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) (static_cast(ld)<<(rbits) | static_cast(rd)) -#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) (static_cast(ld)<<(rbits) | static_cast(rd)) +#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) \ + (static_cast(ld)<<(rbits) | static_cast(rd)) +#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) \ + (static_cast(ld)<<(rbits) | static_cast(rd)) +#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) \ + (static_cast(ld)<<(rbits) | static_cast(rd)) +#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) \ + (static_cast(ld)<<(rbits) | static_cast(rd)) +#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) \ + (static_cast(ld)<<(rbits) | static_cast(rd)) -static inline WDataOutP VL_CONCAT_WII(int obits,int lbits,int rbits,WDataOutP owp,IData ld,IData rd) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits, + WDataOutP owp, IData ld,IData rd) VL_MT_SAFE { owp[0] = rd; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WWI(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { owp[0] = rd; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WIW(int obits,int lbits,int rbits,WDataOutP owp,IData ld, WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits, + WDataOutP owp, IData ld, WDataInP rwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i]; for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WIQ(int obits,int lbits,int rbits,WDataOutP owp,IData ld,QData rd) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits, + WDataOutP owp, IData ld, QData rd) VL_MT_SAFE { VL_SET_WQ(owp,rd); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WQI(int obits,int lbits,int rbits,WDataOutP owp,QData ld,IData rd) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits, + WDataOutP owp, QData ld, IData rd) VL_MT_SAFE { owp[0] = rd; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WQQ(int obits,int lbits,int rbits,WDataOutP owp,QData ld,QData rd) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits, + WDataOutP owp, QData ld, QData rd) VL_MT_SAFE { VL_SET_WQ(owp,rd); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WWQ(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, QData rd) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE { VL_SET_WQ(owp,rd); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WQW(int obits,int lbits,int rbits,WDataOutP owp,QData ld, WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits, + WDataOutP owp, QData ld, WDataInP rwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i]; for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits); return(owp); } -static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i]; for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; _VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits); @@ -1787,7 +1833,8 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l } return(owp); } -static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more return VL_ZERO_W(obits, owp); @@ -1807,7 +1854,8 @@ static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rw // EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean; // Important: Unlike most other funcs, the shift might well be a computed // expression. Thus consider this when optimizing. (And perhaps have 2 funcs?) -static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE { +static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int, + WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE { int word_shift = VL_BITWORD_I(rd); // Maybe 0 int bit_shift = VL_BITBIT_I(rd); if (rd >= static_cast(obits)) { // rd may be huge with MSB set @@ -1832,7 +1880,8 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l } return(owp); } -static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_SHIFTR_WWW(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more return VL_ZERO_W(obits, owp); @@ -1864,10 +1913,12 @@ static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData r QData signext = ~(VL_MASK_Q(lbits) >> rhs); return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext)); } -static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) VL_PURE { +static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, + QData lhs, IData rhs) VL_PURE { return static_cast(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs)); } -static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE { +static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int, + WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { int word_shift = VL_BITWORD_I(rd); int bit_shift = VL_BITBIT_I(rd); int lmsw = VL_WORDS_I(obits)-1; @@ -1899,7 +1950,8 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa } return(owp); } -static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits, + WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more int lmsw = VL_WORDS_I(obits)-1; @@ -1911,7 +1963,8 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP o } return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]); } -static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) VL_MT_SAFE { +static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, + IData lhs, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative @@ -1920,7 +1973,8 @@ static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDat } return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]); } -static inline QData VL_SHIFTRS_QQW(int obits,int lbits,int rbits,QData lhs, WDataInP rwp) VL_MT_SAFE { +static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, + QData lhs, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative @@ -1963,7 +2017,8 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData #define VL_SEL_QQII(obits,lbits,rbits,tbits,lhs,lsb,width) ((lhs)>>(lsb)) #define VL_SEL_IQII(obits,lbits,rbits,tbits,lhs,lsb,width) (static_cast((lhs)>>(lsb))) -static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE { +static inline IData VL_SEL_IWII(int, int lbits, int, int, + WDataInP lwp, IData lsb, IData width) VL_MT_SAFE { int msb = lsb+width-1; if (VL_UNLIKELY(msb>lbits)) { return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. @@ -1977,7 +2032,8 @@ static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP lwp, IData ls } } -static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE { +static inline QData VL_SEL_QWII(int, int lbits, int, int, + WDataInP lwp, IData lsb, IData width) VL_MT_SAFE { int msb = lsb+width-1; if (VL_UNLIKELY(msb>lbits)) { return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. @@ -1998,7 +2054,8 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData ls } } -static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) VL_MT_SAFE { +static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int, + WDataOutP owp, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE { int msb = lsb+width-1; int word_shift = VL_BITWORD_I(lsb); if (VL_UNLIKELY(msb>lbits)) { // Outside bounds, @@ -2121,37 +2178,41 @@ static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase, o[0]=d0; _END(obits,1); } static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase, - IData d1,IData d0) VL_MT_SAFE { + IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; _END(obits,2); } static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase, - IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; _END(obits,3); } static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase, - IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; _END(obits,4); } static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase, - IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; _END(obits,5); } static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase, - IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; _END(obits,6); } static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase, - IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d6, IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; _END(obits,7); } static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase, - IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d7, IData d6, IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; _END(obits,8); } @@ -2160,7 +2221,8 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase, // Partial constant, lower words of vector wider than 8*32, starting at bit number lsb static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase, - IData d7, IData d6, IData d5, IData d4, IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { + IData d7, IData d6, IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; } diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index fc90dd8af..dce9f6eac 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -192,11 +192,13 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) { if (VL_UNLIKELY(!h)) { - VL_FATAL_MT(__FILE__,__LINE__,"","%%Error: DPI svOpenArrayHandle function called with NULL handle"); + VL_FATAL_MT(__FILE__, __LINE__, "", + "%%Error: DPI svOpenArrayHandle function called with NULL handle"); } const VerilatedDpiOpenVar* varp = reinterpret_cast(h); if (VL_UNLIKELY(!varp->magicOk())) { - VL_FATAL_MT(__FILE__,__LINE__,"","%%Error: DPI svOpenArrayHandle function called with non-Verilator handle"); + VL_FATAL_MT(__FILE__, __LINE__, "", + "%%Error: DPI svOpenArrayHandle function called with non-Verilator handle"); } return varp; } @@ -246,7 +248,8 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, int indx1, int indx2, int indx3) { void* datap = varp->datap(); if (VL_UNLIKELY(nargs != varp->udims())) { - _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on %d dimensional array using %d dimensional function.\n", + _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on" + " %d dimensional array using %d dimensional function.\n", varp->udims(), nargs); return NULL; } diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 94759fe1a..aed7683c7 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -56,7 +56,8 @@ inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData for (unsigned times=0; times m_right) ? m_left : m_right; } - int elements() const { return (VL_LIKELY(m_left>=m_right) ? (m_left-m_right+1) : (m_right-m_left+1)); } + int elements() const { + return (VL_LIKELY(m_left>=m_right) ? (m_left-m_right+1) : (m_right-m_left+1)); } int increment() const { return (m_left >= m_right) ? 1 : -1; } }; @@ -81,45 +82,54 @@ public: class Unpacked {}; // Without packed VerilatedVarProps(VerilatedVarType vltype, int vlflags) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) { } + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) { } VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) { + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) { m_unpacked[0].init(u0l, u0r); } VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l, int u1r) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) { + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) { m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); } VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) { + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) { m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); } // With packed class Packed {}; VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) { } + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) { } VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked, int u0l, int u0r) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) { + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) { m_unpacked[0].init(u0l, u0r); } VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked, int u0l, int u0r, int u1l, int u1r) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(2), m_packed(pl,pr) { + : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), + m_pdims(1), m_udims(2), m_packed(pl,pr) { m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); } VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r) - : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) { + : m_magic(MAGIC), m_vltype(vltype), + m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) { m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); } public: ~VerilatedVarProps() {} // METHODS bool magicOk() const { return m_magic==MAGIC; } VerilatedVarType vltype() const { return m_vltype; } - VerilatedVarFlags vldir() const { return static_cast(static_cast(m_vlflags) & VLVF_MASK_DIR); } + VerilatedVarFlags vldir() const { + return static_cast(static_cast(m_vlflags) & VLVF_MASK_DIR); } vluint32_t entSize() const; bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); } /// DPI compatible C standard layout diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index 087dcc121..7899da295 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -382,12 +382,14 @@ void VerilatedVcd::bufferFlush () VL_MT_UNSAFE_ONE { // Simple methods void VerilatedVcd::set_time_unit (const char* unitp) { - //cout<<" set_time_unit ("<((VerilatedVpio*)h); } + static inline VerilatedVpio* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } inline vpiHandle castVpiHandle() { return reinterpret_cast(this); } // ACCESSORS virtual const char* name() const { return ""; } @@ -117,7 +118,8 @@ public: m_cbData.value = &m_value; } virtual ~VerilatedVpioCb() {} - static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioCb* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiCallback; } vluint32_t reason() const { return m_cbData.reason; } VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; } @@ -130,7 +132,8 @@ class VerilatedVpioConst : public VerilatedVpio { public: explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {} virtual ~VerilatedVpioConst() {} - static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioConst* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiUndefined; } vlsint32_t num() const { return m_num; } }; @@ -141,7 +144,8 @@ class VerilatedVpioRange : public VerilatedVpio { public: explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {} virtual ~VerilatedVpioRange() {} - static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioRange* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiRange; } virtual vluint32_t size() const { return m_range->elements(); } virtual const VerilatedRange* rangep() const { return m_range; } @@ -164,7 +168,8 @@ public: explicit VerilatedVpioScope(const VerilatedScope* scopep) : m_scopep(scopep) {} virtual ~VerilatedVpioScope() {} - static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioScope* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiScope; } const VerilatedScope* scopep() const { return m_scopep; } virtual const char* name() const { return m_scopep->name(); } @@ -198,7 +203,8 @@ public: virtual ~VerilatedVpioVar() { if (m_prevDatap) { delete [] m_prevDatap; m_prevDatap = NULL; } } - static inline VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioVar* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } const VerilatedVar* varp() const { return m_varp; } const VerilatedScope* scopep() const { return m_scopep; } vluint32_t mask() const { return m_mask.u32; } @@ -236,7 +242,8 @@ public: m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset; } virtual ~VerilatedVpioMemoryWord() {} - static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiMemoryWord; } virtual vluint32_t size() const { return varp()->packed().elements(); } virtual const VerilatedRange* rangep() const { return &(varp()->packed()); } @@ -256,7 +263,8 @@ public: explicit VerilatedVpioVarIter(const VerilatedScope* scopep) : m_scopep(scopep), m_started(false) { } virtual ~VerilatedVpioVarIter() {} - static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioVarIter* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiIterator; } virtual vpiHandle dovpi_scan() { if (VL_LIKELY(m_scopep->varsp())) { @@ -281,9 +289,13 @@ class VerilatedVpioMemoryWordIter : public VerilatedVpio { bool m_done; public: VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp) - : m_handle(handle), m_varp(varp), m_iteration(varp->unpacked().right()), m_direction(VL_LIKELY(varp->unpacked().left()>varp->unpacked().right())?1:-1), m_done(false) { } + : m_handle(handle), m_varp(varp), m_iteration(varp->unpacked().right()), + m_direction(VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) + ? 1 : -1), + m_done(false) { } virtual ~VerilatedVpioMemoryWordIter() {} - static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast((VerilatedVpio*)h); } + static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { + return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiIterator; } void iterationInc() { if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration+=m_direction; @@ -337,7 +349,9 @@ public: varop->createPrevDatap(); } } - if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large"); + if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) { + VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large"); + } s_s.m_cbObjLists[vop->reason()].push_back(vop); } static void cbTimedAdd(VerilatedVpioCb* vop) { @@ -921,7 +935,8 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) { QData time = 0; if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time); - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n",cb_data_p->reason,vop,time);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n", + cb_data_p->reason, vop, time);); VerilatedVpiImp::cbTimedAdd(vop); return vop->castVpiHandle(); } @@ -1016,12 +1031,14 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) { if (VL_LIKELY(varop)) { if (varop->varp()->dims()<2) return 0; if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) { - if (VL_UNLIKELY(indx > varop->varp()->unpacked().left() || indx < varop->varp()->unpacked().right())) return 0; + if (VL_UNLIKELY(indx > varop->varp()->unpacked().left() + || indx < varop->varp()->unpacked().right())) return 0; return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, indx - varop->varp()->unpacked().right())) ->castVpiHandle(); } else { - if (VL_UNLIKELY(indx < varop->varp()->unpacked().left() || indx > varop->varp()->unpacked().right())) return 0; + if (VL_UNLIKELY(indx < varop->varp()->unpacked().left() + || indx > varop->varp()->unpacked().right())) return 0; return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, indx - varop->varp()->unpacked().left())) ->castVpiHandle(); @@ -1206,7 +1223,8 @@ void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) { // value processing void vpi_get_value(vpiHandle object, p_vpi_value value_p) { - static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination + // Maximum required size is for binary string, one byte per bit plus null termination + static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32]; // cppcheck-suppress variableScope static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1; VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n",object);); @@ -1274,8 +1292,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { if (bits > outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. bits = outStrSz; - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits); + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" + " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits); } for (i=0; i>3]>>(i&7))&1; @@ -1286,7 +1306,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { } default: _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname()); return; } } else if (value_p->format == vpiOctStrVal) { @@ -1303,8 +1324,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { int i; if (chars > outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" + " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); chars = outStrSz; } for (i=0; i outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" + " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); chars = outStrSz; } for (i=0; i outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" + " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes); bytes = outStrSz; @@ -1478,7 +1504,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", vop->varp()->datap(), vop->varDatap());); if (VL_UNLIKELY(!vop->varp()->isPublicRW())) { - _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: ", vop->fullname()); + _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only," + " use public_flat_rw instead: ", + vop->fullname()); return 0; } if (value_p->format == vpiVectorVal) { @@ -1615,7 +1643,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, } if (success > 1) { _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s", - VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + VL_FUNC, remainder, value_p->value.str, + VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname()); } switch (vop->varp()->vltype()) { case VLVT_UINT8 : *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; @@ -1655,7 +1685,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10; else { _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non hex character '%c' in '%s' as value %s for %s", - VL_FUNC, digit, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + VL_FUNC, digit, value_p->value.str, + VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname()); hex = 0; } } else { @@ -1688,7 +1720,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, int len = strlen(value_p->value.str); CData* datap = (reinterpret_cast(vop->varDatap())); for (int i=0; ivalue.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes + // prepend with 0 values before placing string the least signifcant bytes + datap[i] = (i < len)?value_p->value.str[len-i-1]:0; } return object; } diff --git a/src/V3Active.cpp b/src/V3Active.cpp index a6687fe43..01b3f33bf 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -174,11 +174,13 @@ private: // Convert to a non-delayed assignment UINFO(5," ASSIGNDLY "<v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=)."); + nodep->v3warn(INITIALDLY, "Delayed assignments (<=) in initial" + " or final block; suggest blocking assignments (=)."); } else if (m_check == CT_LATCH) { // Suppress. Shouldn't matter that the interior of the latch races } else { - nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=)."); + nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked" + " (non flop or latch) block; suggest blocking assignments (=)."); } AstNode* newp = new AstAssign (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), @@ -437,6 +439,8 @@ public: void V3Active::activeAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index e4e923418..5497b9cd6 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -159,6 +159,8 @@ public: void V3ActiveTop::activeTopAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 44fbec8f0..571acba02 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -349,6 +349,8 @@ public: void V3Assert::assertAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 513531d9e..20bfcd1ec 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -136,6 +136,8 @@ public: void V3AssertPre::assertPreAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 4e79c8873..5e4cb149e 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -229,7 +229,8 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next) // Called on all major tree changers. // Only for use for those really nasty bugs relating to internals // Note this may be null. - //if (debug()) cout<<"-treeChange: V3Ast.cpp:"<"<"<m_op2p = (AstNode*)1; this->m_op3p = (AstNode*)1; this->m_op4p = (AstNode*)1; + if ( #if !defined(VL_DEBUG) || defined(VL_LEAK_CHECKS) - delete this; // Leak massively, so each pointer is unique and we can debug easier + 1 +#else + !v3Global.opt.debugLeak() #endif + ) { + delete this; + } + // Else leak massively, so each pointer is unique + // and we can debug easier. } AstNode::~AstNode() { @@ -779,7 +788,9 @@ void AstNode::iterateAndNext(AstNVisitor& v) { niterp->m_iterpp = &niterp; niterp->accept(v); // accept may do a replaceNode and change niterp on us... - //if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<m_iterpp = NULL; if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept diff --git a/src/V3Ast.h b/src/V3Ast.h index 44c77426b..11edd1ea6 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1110,7 +1110,8 @@ public: AstNode* op4p() const { return m_op4p; } AstNodeDType* dtypep() const { return m_dtypep; } AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); } - AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list + AstNode* firstAbovep() const { // Returns NULL when second or later in list + return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } bool brokeExists() const; bool brokeExistsAbove() const; @@ -1301,7 +1302,8 @@ public: void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it. - AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node + // Unlink this from whoever points to it, keep entire next list with unlinked node + AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); void swapWith(AstNode* bp); void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead void cloneRelinkNode() { cloneRelink(); } @@ -1330,17 +1332,20 @@ public: virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out - virtual bool isGateDedupable() const { return isGateOptimizable(); } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf) + // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf) + virtual bool isGateDedupable() const { return isGateOptimizable(); } virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input virtual bool isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed - virtual bool isUnlikely() const { return false; } // Else $stop or similar statement which means an above IF statement is unlikely to be taken + // isUnlikely handles $stop or similar statement which means an above IF statement is unlikely to be taken + virtual bool isUnlikely() const { return false; } virtual int instrCount() const { return 0; } virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it virtual bool same(const AstNode*) const { return true; } virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function - virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc. + // Another AstNode* may have a pointer into this node, other then normal front/back/etc. + virtual bool maybePointedTo() const { return false; } virtual const char* broken() const { return NULL; } // INVOKERS @@ -1463,7 +1468,9 @@ public: void rhsp(AstNode* nodep) { return setOp2p(nodep); } void thsp(AstNode* nodep) { return setOp3p(nodep); } // METHODS - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) = 0; // Set out to evaluation of a AstConst'ed + // Set out to evaluation of a AstConst'ed + virtual void numberOperate(V3Number& out, const V3Number& lhs, + const V3Number& rhs, const V3Number& ths) = 0; virtual bool cleanLhs() = 0; // True if LHS must have extra upper bits zero virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero virtual bool cleanThs() = 0; // True if THS must have extra upper bits zero @@ -1749,7 +1756,8 @@ public: bool isNosign() const { return m_numeric.isNosign(); } AstNumeric numeric() const { return m_numeric; } int widthWords() const { return VL_WORDS_I(width()); } - int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it + int widthMin() const { // If sized, the size, if unsized the min digits to represent it + return m_widthMin?m_widthMin:m_width; } int widthPow2() const; void widthMinFromWidth() { m_widthMin = m_width; } bool widthSized() const { return !m_widthMin || m_widthMin==m_width; } @@ -2089,11 +2097,16 @@ public: inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } -inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize -inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); } -inline bool AstNode::isDouble() const { return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); } -inline bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); } -inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); } +inline bool AstNode::width1() const { // V3Const uses to know it can optimize + return dtypep() && dtypep()->width()==1; } +inline int AstNode::widthInstrs() const { + return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); } +inline bool AstNode::isDouble() const { + return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); } +inline bool AstNode::isString() const { + return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); } +inline bool AstNode::isSigned() const { + return dtypep() && dtypep()->isSigned(); } inline bool AstNode::isZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqZero()); } inline bool AstNode::isNeqZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isNeqZero()); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 942505d71..255c7dce8 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -65,7 +65,8 @@ int AstNodeSel::bitConst() const { void AstNodeClassDType::repairMemberCache() { clearCache(); for (AstMemberDType* itemp = membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { - if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<prettyName()); } + if (m_members.find(itemp->name())!=m_members.end()) { + itemp->v3error("Duplicate declaration of member name: "<prettyName()); } else m_members.insert(make_pair(itemp->name(), itemp)); } } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 7bc7d7dad..d4f35a8b3 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -47,26 +47,26 @@ private: public: AstConst(FileLine* fl, const V3Number& num) :AstNodeMath(fl) - ,m_num(num) { + ,m_num(num) { if (m_num.isDouble()) { dtypeSetDouble(); - } else if (m_num.isString()) { + } else if (m_num.isString()) { dtypeSetString(); } else { - dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(), - m_num.isSigned() ? AstNumeric::SIGNED + dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(), + m_num.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); - } + } } AstConst(FileLine* fl, uint32_t num) :AstNodeMath(fl) - ,m_num(V3Number(fl,32,num)) { dtypeSetLogicSized(m_num.width(), + ,m_num(V3Number(fl,32,num)) { dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(), AstNumeric::UNSIGNED); } - class Unsized32 {}; // for creator type-overload selection + class Unsized32 {}; // for creator type-overload selection AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value - :AstNodeMath(fl) - ,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(), + :AstNodeMath(fl) + ,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(), AstNumeric::UNSIGNED); } class Signed32 {}; // for creator type-overload selection AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value @@ -79,7 +79,7 @@ public: ,m_num(V3Number(fl,64)) { m_num.setDouble(num); dtypeSetDouble(); } class String {}; // for creator type-overload selection AstConst(FileLine* fl, String, const string& num) - :AstNodeMath(fl) + :AstNodeMath(fl) ,m_num(V3Number(V3Number::String(), fl, num)) { dtypeSetString(); } class LogicFalse {}; AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1 @@ -706,13 +706,17 @@ public: virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } // - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType) - AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) + // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType) + virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } + // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) + AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // METHODS virtual void name(const string& name) { m_name = name; } virtual void tag(const string& text) { m_tag = text;} @@ -1183,7 +1187,8 @@ public: string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument - string vlArgType(bool named, bool forReturn, bool forFunc) const; // Return Verilator internal type for argument: CData, SData, IData, WData + // Return Verilator internal type for argument: CData, SData, IData, WData + string vlArgType(bool named, bool forReturn, bool forFunc) const; string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc string vlPropInit() const; // Return VerilatorVarProps initializer @@ -1191,7 +1196,8 @@ public: AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType) + // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType) + AstBasicDType* basicp() const { return subDTypep()->basicp(); } AstNode* valuep() const { return op3p(); } // op3 = Initial value that never changes (static const) void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than an AstConst void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } @@ -1443,11 +1449,14 @@ class AstVarRef : public AstNodeVarRef { // A reference to a variable (lvalue or rvalue) public: AstVarRef(FileLine* fl, const string& name, bool lvalue) - :AstNodeVarRef(fl, name, NULL, lvalue) {} - AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) // This form only allowed post-link - :AstNodeVarRef(fl, varp->name(), varp, lvalue) {} // because output/wire compression may lead to deletion of AstVar's - AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue) // This form only allowed post-link - :AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) { // because output/wire compression may lead to deletion of AstVar's + : AstNodeVarRef(fl, name, NULL, lvalue) {} + // This form only allowed post-link because output/wire compression may + // lead to deletion of AstVar's + AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) + : AstNodeVarRef(fl, varp->name(), varp, lvalue) {} + // This form only allowed post-link (see above) + AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue) + : AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) { varScopep(varscp); } ASTNODE_NODE_FUNCS(VarRef) @@ -2331,7 +2340,9 @@ public: ASTNODE_NODE_FUNCS(CoverDecl) virtual const char* broken() const { BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); - if (m_dataDeclp && m_dataDeclp->m_dataDeclp) v3fatalSrc("dataDeclp should point to real data, not be a list"); // Avoid O(n^2) accessing + if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing + v3fatalSrc("dataDeclp should point to real data, not be a list"); + } return NULL; } virtual void cloneRelink() { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); } virtual void dump(std::ostream& str); @@ -2594,6 +2605,26 @@ public: void lhsp(AstNode* nodep) { setOp3p(nodep); } }; +class AstSysFuncAsTask : public AstNodeStmt { + // Call what is normally a system function (with a return) in a non-return context + // Parents: stmtlist + // Children: a system function +public: + AstSysFuncAsTask(FileLine* fileline, AstNode* exprsp) + : AstNodeStmt (fileline) { addNOp1p(exprsp); } + ASTNODE_NODE_FUNCS(SysFuncAsTask) + virtual string verilogKwd() const { return ""; } + virtual bool isGateOptimizable() const { return true; } + virtual bool isPredictOptimizable() const { return true; } + virtual bool isPure() const { return true; } + virtual bool isOutputter() const { return false; } + virtual int instrCount() const { return 0; } + virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool same(const AstNode* samep) const { return true; } + AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval + void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval +}; + class AstSysIgnore : public AstNodeStmt { // Parents: stmtlist // Children: varrefs or exprs @@ -3420,10 +3451,14 @@ public: void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } AstText* scopeEntrp() const { return VN_CAST(op2p(), Text); } void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } - string scopeSymName() const { return scopeNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children - string scopeDpiName() const { return scopeNameFormatter(scopeEntrp()); } // Name for DPI import scope - string scopePrettySymName() const { return scopePrettyNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children - string scopePrettyDpiName() const { return scopePrettyNameFormatter(scopeEntrp()); } // Name for __Vscope variable including children + string scopeSymName() const { // Name for __Vscope variable including children + return scopeNameFormatter(scopeAttrp()); } + string scopeDpiName() const { // Name for DPI import scope + return scopeNameFormatter(scopeEntrp()); } + string scopePrettySymName() const { // Name for __Vscope variable including children + return scopePrettyNameFormatter(scopeAttrp()); } + string scopePrettyDpiName() const { // Name for __Vscope variable including children + return scopePrettyNameFormatter(scopeEntrp()); } bool dpiExport() const { return m_dpiExport; } void dpiExport(bool flag) { m_dpiExport=flag; } }; @@ -4606,7 +4641,9 @@ public: virtual string emitSimpleOperator() { return ">>"; } virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} - virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} // LHS size might be > output size, so don't want to force size + // LHS size might be > output size, so don't want to force size + virtual bool sizeMattersLhs() {return false;} + virtual bool sizeMattersRhs() {return false;} }; class AstShiftRS : public AstNodeBiop { // Shift right with sign extension, >>> operator @@ -5677,8 +5714,10 @@ public: BROKEN_RTN(m_evalp && !m_evalp->brokeExists()); return NULL; } - AstNodeModule* modulesp() const { return VN_CAST(op1p(), NodeModule); } // op1 = List of modules - AstNodeModule* topModulep() const { return VN_CAST(op1p(), NodeModule); } // * = Top module in hierarchy (first one added, for now) + AstNodeModule* modulesp() const { // op1 = List of modules + return VN_CAST(op1p(), NodeModule); } + AstNodeModule* topModulep() const { // * = Top module in hierarchy (first one added, for now) + return VN_CAST(op1p(), NodeModule); } void addModulep(AstNodeModule* modulep) { addOp1p(modulep); } AstCFile* filesp() const { return VN_CAST(op2p(), CFile);} // op2 = List of files void addFilesp(AstCFile* filep) { addOp2p(filep); } diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 35aacbcf3..ee3ec6f77 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -291,10 +291,12 @@ public: void V3Begin::debeginAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index eb98d1a55..6f83f2d83 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -224,8 +224,10 @@ private: nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<dtypep()) { - if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); } - else if (!VN_IS(nodep->dtypep(), NodeDType)) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); } + if (!nodep->dtypep()->brokeExists()) { + nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); } + else if (!VN_IS(nodep->dtypep(), NodeDType)) { + nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); } } if (v3Global.assertDTypesResolved()) { if (nodep->hasDType()) { diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index d4a3ce4ef..f16040979 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -130,7 +130,8 @@ void V3CCtors::evalAsserts() { newp = new AstAnd(varp->fileline(), newp, new AstConst(varp->fileline(), num)); AstNodeIf* ifp = new AstIf(varp->fileline(), newp, - new AstCStmt(varp->fileline(), "Verilated::overWidthError(\""+varp->prettyName()+"\");")); + new AstCStmt(varp->fileline(), + "Verilated::overWidthError(\""+varp->prettyName()+"\");")); ifp->branchPred(AstBranchPred::BP_UNLIKELY); newp = ifp; funcp->addStmtsp(newp); diff --git a/src/V3Case.cpp b/src/V3Case.cpp index bc59131bd..bf77151cc 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -488,7 +488,9 @@ public: void V3Case::caseAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } void V3Case::caseLint(AstNodeCase* nodep) { diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index a37a73c79..131a5b984 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -187,6 +187,8 @@ public: void V3Cast::castAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index f69b27575..3b15ccab2 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -175,13 +175,17 @@ private: newChangeDet(); } else { if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-class-"); - m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<varp()->prettyName()); + m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable" + " (probably with UNOPTFLAT warning suppressed): " + <varp()->prettyName()); } } virtual void visit(AstNode* nodep) { nodep->iterateChildren(*this); if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-"); - m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<varp()->prettyName()); + m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable" + " (probably with UNOPTFLAT warning suppressed): " + <varp()->prettyName()); } public: // CONSTUCTORS @@ -300,7 +304,9 @@ public: void V3Changed::changedAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 0b652ac73..3b93a6d54 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -297,6 +297,8 @@ public: void V3Clean::cleanAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3ClkGater.cpp b/src/V3ClkGater.cpp index 23a7ede9e..5a64eb6d0 100644 --- a/src/V3ClkGater.cpp +++ b/src/V3ClkGater.cpp @@ -912,8 +912,10 @@ public: void V3ClkGater::clkGaterAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 6b59a4b27..936414b22 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -406,6 +406,8 @@ public: void V3Clock::clockAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index 79cd7311c..671e5b9ab 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -473,6 +473,8 @@ public: void V3Combine::combineAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 5224ca99f..93ba7154f 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1202,7 +1202,8 @@ private: AstAnd* newp = new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), val), fromp); - newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width + // widthMin no longer applicable if different C-expanded width + newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); if (debug()>=9) newp->dumpTree(cout," _new: "); @@ -1759,7 +1760,8 @@ private: // Something's out of order, sort it senp = NULL; std::vector vec; - for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); + senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { vec.push_back(senp); } stable_sort(vec.begin(), vec.end(), SenItemCmp()); @@ -2561,15 +2563,19 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) { void V3Const::constifyAllLint(AstNetlist* nodep) { // Only call from Verilator.cpp, as it uses user#'s UINFO(2,__FUNCTION__<<": "<= 3); } void V3Const::constifyCpp(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } @@ -2584,16 +2590,20 @@ void V3Const::constifyAllLive(AstNetlist* nodep) { // This only pushes constants up, doesn't make any other edits // IE doesn't prune dead statements, as we need to do some usability checks after this UINFO(2,__FUNCTION__<<": "<= 3); } void V3Const::constifyAll(AstNetlist* nodep) { // Only call from Verilator.cpp, as it uses user#'s UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 7235253f6..68523042d 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -395,6 +395,8 @@ public: void V3Coverage::coverage(AstNetlist* rootp) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index ee1bbe2e8..96a76e3d6 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -134,6 +134,8 @@ public: void V3CoverageJoin::coverageJoin(AstNetlist* rootp) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index ec93f11a7..22d87781d 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -378,7 +378,8 @@ private: // members are still alive. if ((classp = VN_CAST((*it), NodeClassDType))) { bool cont = true; - for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = VN_CAST(memberp->nextp(), MemberDType)) { + for (AstMemberDType *memberp = classp->membersp(); + memberp; memberp = VN_CAST(memberp->nextp(), MemberDType)) { if (memberp->user1() != 0) { cont = false; break; @@ -425,30 +426,40 @@ public: void V3Dead::deadifyModules(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 6); } void V3Dead::deadifyDTypes(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } void V3Dead::deadifyAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } void V3Dead::deadifyAllScoped(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 3812ff355..bac6ac22e 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -115,7 +115,8 @@ private: //UINFO(4," MVU "<user5( nodep->user5() | flags ); if ((nodep->user5() & VU_DLY) && (nodep->user5() & VU_NONDLY)) { - nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<varp()->prettyName()); + nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: " + <varp()->prettyName()); } } AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/, AstNodeDType* newdtypep) { @@ -158,7 +159,8 @@ private: if (oldactivep->sensesp() != m_activep->sensesp()) { if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN) && !varrefp->varp()->user2()) { - varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks with different clocking: "<varp()->prettyName()<varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks with different clocking: " + <varp()->prettyName()<warnMore()<<"... Location of first driving block"<warnMore()<<"... Location of other driving block"); varrefp->varp()->user2(true); @@ -195,8 +197,9 @@ private: arrayselp = VN_CAST(lhsp, ArraySel); } if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?"); - if (VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType)) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); - + if (VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType)) { + nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); + } UINFO(4,"AssignDlyArray: "<varScopep(), VU_DLY); if (!m_activep) nodep->v3fatalSrc("<= not under sensitivity block"); - if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active"); + if (!m_activep->hasClocked()) { + nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active"); + } AstVarScope* oldvscp = nodep->varScopep(); if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); AstVarScope* dlyvscp = VN_CAST(oldvscp->user1p(), VarScope); @@ -470,6 +475,8 @@ public: void V3Delayed::delayedAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index e9cddfcd7..50750dd79 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -174,6 +174,8 @@ public: void V3Depth::depthAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 8fe6e821c..0c1fe0ecf 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -139,6 +139,8 @@ public: void V3DepthBlock::depthBlockAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index f1915b297..7edac914c 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -311,6 +311,8 @@ public: void V3Descope::descopeAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 6e9db1e78..23d3bf348 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -376,6 +376,11 @@ public: puts(")); }\n"); } } + virtual void visit(AstSysFuncAsTask* nodep) { + if (!nodep->lhsp()->isWide()) puts("(void)"); + nodep->lhsp()->iterateAndNext(*this); + if (!nodep->lhsp()->isWide()) puts(";"); + } virtual void visit(AstSystemT* nodep) { puts("(void)VL_SYSTEM_I"); emitIQW(nodep->lhsp()); @@ -509,31 +514,36 @@ public: } virtual void visit(AstMulS* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Signed multiply of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Signed multiply of "<width() + <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPow* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of "<width() + <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowSS* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of "<width() + <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowSU* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of "<width() + <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowUS* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of "<width() + <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } @@ -978,6 +988,7 @@ class EmitCImp : EmitCStmts { // High level void emitImp(AstNodeModule* modp); void emitStaticDecl(AstNodeModule* modp); + void emitSettleLoop(std::string eval_call, bool initial); void emitWrapEval(AstNodeModule* modp); void emitInt(AstNodeModule* modp); @@ -1550,7 +1561,8 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) { puts("\n// Coverage\n"); // Rather than putting out VL_COVER_INSERT calls directly, we do it via this function // This gets around gcc slowness constructing all of the template arguments. - puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n"); + puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable," + " const char* filenamep, int lineno, int column,\n"); puts( "const char* hierp, const char* pagep, const char* commentp) {\n"); puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin @@ -1729,6 +1741,29 @@ void EmitCImp::emitSensitives() { } } +void EmitCImp::emitSettleLoop(std::string eval_call, bool initial) { + putsDecoration("// Evaluate till stable\n"); + puts("int __VclockLoop = 0;\n"); + puts("QData __Vchange = 1;\n"); + puts("do {\n"); + puts( eval_call + "\n"); + puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit()) + +")) {\n"); + puts( "// About to fail, so enable debug to see what's not settling.\n"); + puts( "// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n"); + puts( "int __Vsaved_debug = Verilated::debug();\n"); + puts( "Verilated::debug(1);\n"); + puts( "__Vchange = _change_request(vlSymsp);\n"); + puts( "Verilated::debug(__Vsaved_debug);\n"); + puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't "); + if (initial) puts ("DC "); + puts( "converge\");\n"); + puts( "} else {\n"); + puts( "__Vchange = _change_request(vlSymsp);\n"); + puts( "}\n"); + puts("} while (VL_UNLIKELY(__Vchange));\n"); +} + void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("\nvoid "+modClassName(modp)+"::eval() {\n"); puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n"); @@ -1750,20 +1785,10 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("VL_DEBUG_IF(VL_DBG_MSGF(\"Train starting, trainId="+cvtToStr(trainId)+"\\n\"););\n"); puts("Verilated::trainId("+cvtToStr(trainId)+");\n"); } - - putsDecoration("// Evaluate till stable\n"); - puts("int __VclockLoop = 0;\n"); - puts("QData __Vchange = 1;\n"); - puts("while (VL_LIKELY(__Vchange)) {\n"); - puts( "VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n"); - if (v3Global.opt.trace()) { - puts("vlSymsp->__Vm_activity = true;\n"); - } - puts( "_eval(vlSymsp);\n"); - puts( "__Vchange = _change_request(vlSymsp);\n"); - puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit()) - +")) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n"); - puts("}\n"); + emitSettleLoop( + (string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n") + + (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "") + + "_eval(vlSymsp);"), false); if (v3Global.opt.threads()) { // THREADED-TODO move to end of all trains on thread puts("Verilated::endOfThreadTrain(vlSymsp->__Vm_evalMsgQp);\n"); } @@ -1780,15 +1805,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { if (v3Global.opt.trace()) { puts("vlSymsp->__Vm_activity = true;\n"); } - puts( "int __VclockLoop = 0;\n"); - puts( "QData __Vchange = 1;\n"); - puts( "while (VL_LIKELY(__Vchange)) {\n"); - puts( "_eval_settle(vlSymsp);\n"); - puts( "_eval(vlSymsp);\n"); - puts( "__Vchange = _change_request(vlSymsp);\n"); - puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit()) - +")) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n"); - puts( "}\n"); + emitSettleLoop((string("_eval_settle(vlSymsp);\n") + +"_eval(vlSymsp);"), true); puts("}\n"); splitSizeInc(10); } @@ -2296,8 +2314,9 @@ class EmitCTrace : EmitCStmts { putsDecoration("// Callback from vcd->open()\n"); puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n"); puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n"); - puts("if (!Verilated::calcUnusedSigs()) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n"); - + puts("if (!Verilated::calcUnusedSigs()) {\n"); + puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n"); + puts("}\n"); puts("vcdp->scopeEscape(' ');\n"); puts("t->traceInitThis(vlSymsp, vcdp, code);\n"); puts("vcdp->scopeEscape('.');\n"); // Restore so later traced files won't break diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 5ca387100..262d070e8 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -103,7 +103,8 @@ class EmitCSyms : EmitCBaseVisitor { if (rsvd != "") { // Generally V3Name should find all of these and throw SYMRSVDWORD. // We'll still check here because the compiler errors resulting if we miss this warning are SO nasty - nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter, should have hit SYMRSVDWORD: '"<prettyName()<<"'"); + nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter," + " should have hit SYMRSVDWORD: '"<prettyName()<<"'"); } } } diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 35a09da0a..70663dc9e 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -278,6 +278,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { if (nodep->msbp()) { putbs(","); nodep->msbp()->iterateAndNext(*this); } puts(");\n"); } + virtual void visit(AstSysFuncAsTask* nodep) { + nodep->lhsp()->iterateAndNext(*this); + puts(";\n"); + } virtual void visit(AstSysIgnore* nodep) { putfs(nodep,nodep->verilogKwd()); putbs(" ("); diff --git a/src/V3Error.h b/src/V3Error.h index e8593e8b3..4ca9df783 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -266,8 +266,11 @@ inline void v3errorEndFatal(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr // Careful, you can't put () around msg, as you would in most macro definitions // Note the commas are the comma operator, not separating arguments. These are needed to insure // evaluation order as otherwise we couldn't insure v3errorPrep is called first. -#define v3warnCode(code,msg) v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<dtypep()->skipRefp(), UnpackArrayDType)) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); + if (VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) { + nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); + } for (int w=0; wwidthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone (rhsp, w)); } @@ -936,6 +938,8 @@ public: void V3Expand::expandAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3File.cpp b/src/V3File.cpp index 285ea8b42..a98a79d12 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -238,7 +238,8 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm UINFO(2," --check-times failed: missing "<= 3); } diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 599bfe65f..75c91195c 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -242,6 +242,8 @@ public: void V3GenClk::genClkAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 5b591b4e4..fc2a7e2b2 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -545,7 +545,8 @@ public: // Important to add statement next to cell, in case there is a generate with same named cell cellp->addNextHere(newvarp); if (pinVarp->isInout()) { - pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)"); + pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be" + " direct one-to-one connection (without any expression)"); } else if (pinVarp->isOutput()) { // See also V3Inst AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false); @@ -582,12 +583,16 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu void V3Inst::instAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } void V3Inst::dearrayAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3Life.cpp b/src/V3Life.cpp index c5bfc9587..bfc55a9a7 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -518,7 +518,9 @@ public: void V3Life::lifeAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index afa0c5691..a7f981e73 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -228,6 +228,8 @@ public: void V3LifePost::lifepostAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 3d54ef133..a5bba8e46 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -413,7 +413,9 @@ private: idtypep->cellp(nodep); // Only set when real parent cell known. AstVar* varp; if (nodep->rangep()) { - AstNodeArrayDType* arrp = new AstUnpackArrayDType(nodep->fileline(),VFlagChildDType(), idtypep, nodep->rangep()->cloneTree(true)); + AstNodeArrayDType* arrp + = new AstUnpackArrayDType(nodep->fileline(), VFlagChildDType(), + idtypep, nodep->rangep()->cloneTree(true)); varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName, VFlagChildDType(), arrp); } else { diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 7068fe4b7..e7e3a5c12 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -262,7 +262,8 @@ public: AstCell* nodep, const string& scopename) { if (!abovep) nodep->v3fatalSrc("Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); - UINFO(9," INSERTcel se"<<(void*)symp<<" "<type()<<" under a "<backp()->type()<<" in dotted expression"); + nodep->v3error("Syntax Error: Not expecting "<type()<<" under a " + <backp()->type()<<" in dotted expression"); m_ds.m_dotErr = true; } } @@ -1815,7 +1818,8 @@ private: AstCell* cellp = VN_CAST(foundp->nodep(), Cell); if (VN_IS(cellp->modp(), Iface)) { // Interfaces can be referenced like a variable for interconnect - VSymEnt* cellEntp = m_statep->getNodeSym(cellp); if (!cellEntp) nodep->v3fatalSrc("No interface sym entry"); + VSymEnt* cellEntp = m_statep->getNodeSym(cellp); + if (!cellEntp) nodep->v3fatalSrc("No interface sym entry"); VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a module or generate begin string findName = nodep->name()+"__Viftop"; VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName); @@ -2011,7 +2015,8 @@ private: VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL; if (!vscp) { - nodep->v3error("Can't find varpin scope of '"<dotted()+"."+nodep->prettyName()); + nodep->v3error("Can't find varpin scope of '"<dotted()+"."+nodep->prettyName()); okSymp->cellErrorScopes(nodep); } else { while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal @@ -2126,7 +2131,8 @@ private: } else if (nodep->dotted() == "") { nodep->v3error("Can't find definition of task/function: "<prettyName()); } else { - nodep->v3error("Can't find definition of '"<dotted()+"."+nodep->prettyName()); + nodep->v3error("Can't find definition of '"<dotted()+"."+nodep->prettyName()); okSymp->cellErrorScopes(nodep); } } @@ -2314,21 +2320,29 @@ public: int V3LinkDot::debug() { return LinkDotState::debug(); } void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); + } LinkDotState state (rootp, step); LinkDotFindVisitor visitor(rootp,&state); - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree")); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree")); + } if (step == LDS_PRIMARY || step == LDS_PARAMED) { // Initial link stage, resolve parameters LinkDotParamVisitor visitors(rootp,&state); - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree")); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree")); + } } else if (step == LDS_ARRAYED) {} else if (step == LDS_SCOPED) { // Well after the initial link when we're ready to operate on the flat design, // process AstScope's. This needs to be separate pass after whole hierarchy graph created. LinkDotScopeVisitor visitors(rootp,&state); - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); + } } else v3fatalSrc("Bad case"); state.dump(); diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index 5d4dbbb59..3592e79a5 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -35,19 +35,23 @@ private: static void linkDotGuts(AstNetlist* nodep, VLinkDotStep step); public: static void linkDotPrimary(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 6); } static void linkDotParamed(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } static void linkDotArrayed(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 6); } static void linkDotScope(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } }; diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 6dde64548..aa46601ed 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -262,6 +262,8 @@ public: void V3LinkJump::linkJump(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 74fe776ff..73d9c2949 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -278,7 +278,9 @@ public: void V3LinkLValue::linkLValue(AstNetlist* rootp) { UINFO(4,__FUNCTION__<<": "<= 6); } void V3LinkLValue::linkLValueSet(AstNode* nodep) { diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index e39983223..b56367af0 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -430,6 +430,8 @@ public: void V3LinkParse::linkParse(AstNetlist* rootp) { UINFO(4,__FUNCTION__<<": "<= 6); } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index d64e1b479..1c41e8064 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -515,7 +515,9 @@ public: void V3LinkResolve::linkResolve(AstNetlist* rootp) { UINFO(4,__FUNCTION__<<": "<= 6); } diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 7ddf2de98..d34ca5345 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -248,8 +248,10 @@ public: void V3Localize::localizeAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3Name.cpp b/src/V3Name.cpp index bb64ed8ce..9ffb03593 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -148,6 +148,8 @@ public: void V3Name::nameAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 9444e90a5..50d46dee2 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -659,6 +659,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD else if ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-sigsegv else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; } + else if ( onoff (sw, "-debug-leak", flag/*ref*/) ){ m_debugLeak = flag; } else if ( !strcmp (sw, "-debug-sigsegv") ) { throwSigsegv(); } // Undocumented, see also --debug-abort else if ( !strcmp (sw, "-debug-fatalsrc") ) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort else if ( onoff (sw, "-decoration", flag/*ref*/) ) { m_decoration = flag; } @@ -1218,6 +1219,7 @@ V3Options::V3Options() { m_coverageUnderscore = false; m_coverageUser = false; m_debugCheck = false; + m_debugLeak = true; m_decoration = true; m_exe = false; m_ignc = false; diff --git a/src/V3Options.h b/src/V3Options.h index adf55c5c1..828c8cb34 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -75,6 +75,7 @@ class V3Options { bool m_coverageUnderscore;// main switch: --coverage-underscore bool m_coverageUser; // main switch: --coverage-func bool m_debugCheck; // main switch: --debug-check + bool m_debugLeak; // main switch: --debug-leak bool m_decoration; // main switch: --decoration bool m_exe; // main switch: --exe bool m_ignc; // main switch: --ignc @@ -229,6 +230,7 @@ class V3Options { bool coverageUnderscore() const { return m_coverageUnderscore; } bool coverageUser() const { return m_coverageUser; } bool debugCheck() const { return m_debugCheck; } + bool debugLeak() const { return m_debugLeak; } bool decoration() const { return m_decoration; } bool exe() const { return m_exe; } bool trace() const { return m_trace; } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 60212b853..85e174b4b 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -1566,14 +1566,16 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d processMoveDoneOne (vertexp); } -inline void OrderMoveDomScope::ready(OrderVisitor* ovp) { // Check the domScope is on ready list, add if not +// Check the domScope is on ready list, add if not +inline void OrderMoveDomScope::ready(OrderVisitor* ovp) { if (!m_onReadyList) { m_onReadyList = true; m_readyDomScopeE.pushBack(ovp->m_pomReadyDomScope, this); } } -inline void OrderMoveDomScope::movedVertex(OrderVisitor* ovp, OrderMoveVertex* vertexp) { // Mark one vertex as finished, remove from ready list if done +// Mark one vertex as finished, remove from ready list if done +inline void OrderMoveDomScope::movedVertex(OrderVisitor* ovp, OrderMoveVertex* vertexp) { UASSERT(m_onReadyList, "Moving vertex from ready when nothing was on que as ready."); if (m_readyVertices.empty()) { // Else more work to get to later m_onReadyList = false; @@ -1645,8 +1647,10 @@ void OrderVisitor::process() { void V3Order::orderAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Os.h b/src/V3Os.h index 8f20b408a..4cfe1b0c7 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -38,7 +38,8 @@ public: static string filenameFromDirBase (const string& dir, const string& basename); static string filenameNonDir (const string& filename); ///< Return non-directory part of filename static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename - static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename + static string filenameNonDirExt (const string& filename) { ///< Return basename of filename + return filenameNonExt(filenameNonDir(filename)); } static string filenameDir (const string& filename); ///< Return directory part of filename static string filenameSubstitute (const string& filename); ///< Return filename with env vars removed static string filenameRealPath(const string& fn); ///< Return realpath of filename diff --git a/src/V3Param.cpp b/src/V3Param.cpp index b4a9a364e..020096a5f 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -782,6 +782,8 @@ void ParamVisitor::visitCell(AstCell* nodep) { void V3Param::param(AstNetlist* rootp) { UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index aaea9b51c..23e837ac9 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -427,6 +427,8 @@ public: void V3Premit::premitAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 1b0b28c5d..2b3b11dcd 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -416,7 +416,9 @@ public: void V3Scope::scopeAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 1a4369b32..38373652d 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -718,7 +718,9 @@ private: nodep->bodysp()->iterateAndNext(*this); nodep->incsp()->iterateAndNext(*this); if (loops++ > unrollCount()*16) { - clearOptimizable(nodep, "Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "+cvtToStr(unrollCount())); + clearOptimizable(nodep, "Loop unrolling took too long; probably this is an" + "infinite loop, or set --unroll-count above " + + cvtToStr(unrollCount())); break; } } @@ -752,7 +754,8 @@ private: // Prep for next loop if (loops++ > unrollCount()*16) { - clearOptimizable(nodep, "Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "+cvtToStr(unrollCount())); + clearOptimizable(nodep, "Loop unrolling took too long; probably this is an infinite" + " loop, or set --unroll-count above "+cvtToStr(unrollCount())); break; } } diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 357e77341..5c8893990 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -74,7 +74,10 @@ class SliceVisitor : public AstNVisitor { // Insert an ArraySel, except for a few special cases AstUnpackArrayDType* arrayp = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType); if (!arrayp) { // V3Width should have complained, but... - if (!m_assignError) nodep->v3error(nodep->prettyTypeName()<<" is not an unpacked array, but is in an unpacked array context"); + if (!m_assignError) { + nodep->v3error(nodep->prettyTypeName() + <<" is not an unpacked array, but is in an unpacked array context"); + } m_assignError = true; return nodep->cloneTree(false); // Likely will cause downstream errors } @@ -241,6 +244,8 @@ public: void V3Slice::sliceAll(AstNetlist* rootp) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 818ae2a8e..65ca8b845 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -1024,11 +1024,15 @@ private: void V3Split::splitReorderAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } void V3Split::splitAlwaysAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index 2178efcb5..9898279ef 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -215,6 +215,8 @@ public: void V3SplitAs::splitAsAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index f0ae9cb7a..a28f22871 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -400,6 +400,8 @@ public: void V3Subst::substituteAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index b93212afb..f189bd3d7 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -66,7 +66,8 @@ private: static inline int debug() { return 0; } // NOT runtime, too hot of a function #endif public: - void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent, int numLevels, const string& searchName) const { + void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent, + int numLevels, const string& searchName) const { os<v3fatalSrc("Optimizable cleared, even though earlier test run said not: "<v3fatalSrc("Optimizable cleared, even though earlier test run said not: " + <= 3); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 3fe320742..6ed950b8e 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -600,7 +600,8 @@ private: bool bitvec = (portp->basicp()->keyword().isDpiBitVal() && portp->width() > 32); bool logicvec = (portp->basicp()->keyword().isDpiLogicVal() && portp->width() > 1); if (isRtn && (bitvec || logicvec)) { - portp->v3error("DPI functions cannot return > 32 bits or four-state; use a two-state type or task instead: "<prettyName()); + portp->v3error("DPI functions cannot return > 32 bits or four-state;" + " use a two-state type or task instead: "<prettyName()); // Code below works, but won't compile right, and IEEE illegal } string stmt; @@ -1395,7 +1396,9 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) void V3Task::taskAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Task.h b/src/V3Task.h index d2eecfb65..354a989dc 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -36,7 +36,8 @@ typedef std::vector V3TaskConnects; // [ [port, pin-connects-to] class V3Task { public: static void taskAll(AstNetlist* nodep); - static V3TaskConnects taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp); // Return vector of [port, pin-connects-to] (SLOW) + /// Return vector of [port, pin-connects-to] (SLOW) + static V3TaskConnects taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp); }; #endif // Guard diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 7d8d9c06e..e859a53e3 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -205,7 +205,10 @@ private: if (TraceTraceVertex* vvertexp = dynamic_cast(itp)) { AstTraceInc* nodep = vvertexp->nodep(); if (nodep->valuep()) { - if (nodep->valuep()->backp() != nodep) nodep->v3fatalSrc("Trace duplicate back needs consistency, so we can map duplicates back to TRACEINCs"); + if (nodep->valuep()->backp() != nodep) { + nodep->v3fatalSrc("Trace duplicate back needs consistency," + " so we can map duplicates back to TRACEINCs"); + } hashed.hash(nodep->valuep()); UINFO(8, " Hashed "<valuep())<<" "<= 3); } diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 98201b0b3..18119ac61 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -325,6 +325,8 @@ public: void V3TraceDecl::traceDeclAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 322d3c1db..67e05d769 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -221,7 +221,8 @@ public: TristateVertex* vvertexp = static_cast(itp); if (vvertexp->isTristate() && !vvertexp->processed()) { // Not v3errorSrc as no reason to stop the world - vvertexp->nodep()->v3error("Unsupported tristate construct (in graph; not converted): "<nodep()->prettyTypeName()); + vvertexp->nodep()->v3error("Unsupported tristate construct" + " (in graph; not converted): "<nodep()->prettyTypeName()); } } m_graph.clear(); @@ -1341,6 +1342,8 @@ public: void V3Tristate::tristateAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 2b6173050..56955c1bc 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -479,6 +479,8 @@ public: void V3Unknown::unknownAll(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index f0425e2f2..c34884c39 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -185,10 +185,11 @@ private: } bool canSimulate(AstNode *nodep) { - SimulateVisitor simvis; - AstNode* clone = nodep->cloneTree(true); - simvis.mainCheckTree(clone); - return simvis.optimizable(); + SimulateVisitor simvis; + AstNode* clonep = nodep->cloneTree(true); + simvis.mainCheckTree(clonep); + pushDeletep(clonep); clonep = NULL; + return simvis.optimizable(); } bool simulateTree(AstNode *nodep, const V3Number *loopValue, AstNode *dtypep, V3Number &outNum) { @@ -333,7 +334,9 @@ private: ++m_statIters; if (++times > unrollCount()*3) { - nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<v3error("Loop unrolling took too long;" + " probably this is an infinite loop, or set --unroll-count above " + <= 3); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 3ddd6c26e..7031ddedb 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -31,11 +31,11 @@ // widthSized() = true if all constants sized, else false // Compute size of this expression // Lint warn about mismatches -// If expr size != subop fixed, bad -// If expr size < subop unsized minimum, bad -// If expr size != subop, edit netlist -// For == and similar ops, if multibit underneath, add a REDOR -// If subop larger, add a EXTRACT +// If expr size != subop fixed, bad +// If expr size < subop unsized minimum, bad +// If expr size != subop, edit netlist +// For == and similar ops, if multibit underneath, add a REDOR +// If subop larger, add a EXTRACT // If subop smaller, add a EXTEND // Pass size to sub-expressions if required (+/-* etc) // FINAL = true. @@ -48,16 +48,16 @@ // Comparison results are unsigned // Bit&Part selects are unsigned, even if whole // Concatenates are unsigned -// Ignore signedness of self-determined: -// shift rhs, ** rhs, x?: lhs, concat and replicate members +// Ignore signedness of self-determined: +// shift rhs, ** rhs, x?: lhs, concat and replicate members // Else, if any operand unsigned, output unsigned // // Real number rules: // Real numbers are real (duh) // Reals convert to integers by rounding // Reals init to 0.0 -// Logicals convert compared to zero -// If any operand is real, result is real +// Logicals convert compared to zero +// If any operand is real, result is real //************************************************************************* // V3Width is the only visitor that uses vup. We could switch to using userp, // though note some iterators operate on next() and so would need to pass the @@ -1199,7 +1199,9 @@ private: if (nodep->valuep()->dtypep()->widthSized()) { width = nodep->valuep()->width(); } else { - if (nodep->valuep()->width()>32) nodep->valuep()->v3warn(WIDTH,"Assigning >32 bit to unranged parameter (defaults to 32 bits)"); + if (nodep->valuep()->width()>32) { + nodep->valuep()->v3warn(WIDTH,"Assigning >32 bit to unranged parameter (defaults to 32 bits)"); + } width = 32; } // Can't just inherit valuep()->dtypep() as mwidth might not equal width @@ -1244,7 +1246,8 @@ private: if (nodep->didWidth()) return; if (!nodep->varp()) { if (m_paramsOnly && VN_IS(nodep, VarXRef)) { - checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: "+nodep->prettyName()); VL_DANGLING(nodep); + checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: " + +nodep->prettyName()); VL_DANGLING(nodep); return; } else { nodep->v3fatalSrc("Unlinked varref"); @@ -1493,13 +1496,15 @@ private: } else { AstSel* newp = new AstSel(nodep->fileline(), nodep->fromp()->unlinkFrBack(), memberp->lsb(), memberp->width()); - newp->dtypep(memberp->subDTypep()->skipRefToEnump()); // Must skip over the member to find the union; as the member may disappear later + // Must skip over the member to find the union; as the member may disappear later + newp->dtypep(memberp->subDTypep()->skipRefToEnump()); newp->didWidth(true); // Don't replace dtype with basic type UINFO(9," MEMBERSEL -> "< "<dtypep()<replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); - // Should be able to treat it as a normal-ish nodesel - maybe. The lhsp() will be strange until this stage; create the number here? + // Should be able to treat it as a normal-ish nodesel - maybe. + // The lhsp() will be strange until this stage; create the number here? } } if (!memberp) { // Very bogus, but avoids core dump @@ -1661,7 +1666,9 @@ private: nodep->dtypep(m_vup->dtypep()); } AstNodeDType* vdtypep = nodep->dtypep(); - if (!vdtypep) nodep->v3error("Unsupported/Illegal: Assignment pattern member not underneath a supported construct: "<backp()->prettyTypeName()); + if (!vdtypep) nodep->v3error("Unsupported/Illegal: Assignment pattern" + " member not underneath a supported construct: " + <backp()->prettyTypeName()); { vdtypep = vdtypep->skipRefp(); nodep->dtypep(vdtypep); @@ -1721,7 +1728,8 @@ private: continue; } } else { - patp->keyp()->v3error("Assignment pattern key not supported/understood: "<keyp()->prettyTypeName()); + patp->keyp()->v3error("Assignment pattern key not" + " supported/understood: "<keyp()->prettyTypeName()); } } } @@ -1733,7 +1741,8 @@ private: } else { std::pair ret = patmap.insert(make_pair(memp, patp)); if (!ret.second) { - patp->v3error("Assignment pattern contains duplicate entry: " << VN_CAST(patp->keyp(), Text)->text()); + patp->v3error("Assignment pattern contains duplicate entry: " + << VN_CAST(patp->keyp(), Text)->text()); } } // Next @@ -2189,6 +2198,10 @@ private: nodep->dtypeSetSigned32(); // Spec says integer return } } + virtual void visit(AstSysFuncAsTask* nodep) { + assertAtStatement(nodep); + userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p()); + } virtual void visit(AstSystemT* nodep) { assertAtStatement(nodep); userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p()); @@ -2286,8 +2299,12 @@ private: if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(exprDTypep, IfaceRefDType)) || (VN_IS(exprDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) { nodep->v3error("Illegal "<prettyOperatorName()<<"," - <<" mismatch between port which is"<<(VN_CAST(modDTypep, IfaceRefDType)?"":" not")<<" an interface," - <<" and expression which is"<<(VN_CAST(exprDTypep, IfaceRefDType)?"":" not")<<" an interface."); + <<" mismatch between port which is" + <<(VN_CAST(modDTypep, IfaceRefDType)?"":" not") + <<" an interface," + <<" and expression which is" + <<(VN_CAST(exprDTypep, IfaceRefDType)?"":" not") + <<" an interface."); } // TODO Simple dtype checking, should be a more general check @@ -2952,9 +2969,12 @@ private: bool widthBad (AstNode* nodep, AstNodeDType* expDTypep) { int expWidth = expDTypep->width(); int expWidthMin = expDTypep->widthMin(); - if (!nodep->dtypep()) nodep->v3fatalSrc("Under node "<prettyTypeName()<<" has no dtype?? Missing Visitor func?"); - if (nodep->width()==0) nodep->v3fatalSrc("Under node "<prettyTypeName()<<" has no expected width?? Missing Visitor func?"); - if (expWidth==0) nodep->v3fatalSrc("Node "<prettyTypeName()<<" has no expected width?? Missing Visitor func?"); + if (!nodep->dtypep()) nodep->v3fatalSrc("Under node "<prettyTypeName() + <<" has no dtype?? Missing Visitor func?"); + if (nodep->width()==0) nodep->v3fatalSrc("Under node "<prettyTypeName() + <<" has no expected width?? Missing Visitor func?"); + if (expWidth==0) nodep->v3fatalSrc("Node "<prettyTypeName() + <<" has no expected width?? Missing Visitor func?"); if (expWidthMin==0) expWidthMin = expWidth; if (nodep->dtypep()->width() == expWidth) return false; if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true; @@ -3860,12 +3880,14 @@ int V3Width::debug() { void V3Width::width(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 3); } @@ -3901,6 +3923,8 @@ AstNode* V3Width::widthGenerateParamsEdit( void V3Width::widthCommit(AstNetlist* nodep) { UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp index 1a5a081d9..8e50cd085 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -77,6 +77,10 @@ void VlcOptions::parseOptsList(int argc, char** argv) { else if ( onoff (sw, "-rank", flag/*ref*/) ) { m_rank = flag; } else if ( onoff (sw, "-unlink", flag/*ref*/) ) { m_unlink = flag; } // Parameterized switches + else if ( !strcmp (sw, "-annotate-min") && (i+1)) { # Fix flex 2.6.1 warning - $line =~ s/for \( i = 0; i < _yybytes_len; \+\+i \)/for ( i = 0; i < (yy_size_t)(_yybytes_len); ++i )/g; + $line =~ s/for \( i = 0; i < _yybytes_len; \+\+i \)/for ( i = 0; (yy_size_t)(i) < (yy_size_t)(_yybytes_len); ++i )/g; # Fix flex 2.6.0 warning $line =~ s/\(\(int\) \(\(yy_n_chars\) \+ number_to_move\) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size\)/((int) ((yy_n_chars) + number_to_move) > (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size)/g; $line =~ s/ number_to_move == YY_MORE_ADJ / (int)number_to_move == (int)YY_MORE_ADJ /; diff --git a/src/verilog.l b/src/verilog.l index cb91fc9e8..680042c1b 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -1065,7 +1065,8 @@ void V3ParseImp::lexToken() { } else if (token == yGLOBAL__LEX) { if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING; - else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can + // Avoid 2009 "global" conflicting with old code when we can + else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } } // If add to above "else if", also add to "if (token" further above } diff --git a/src/verilog.y b/src/verilog.y index 80bcc825e..484884506 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2663,6 +2663,8 @@ system_t_call: // IEEE: system_tf_call (as task) | yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); } + | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); } + // | yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); } | yD_FFLUSH parenE { $1->v3error("Unsupported: $fflush of all handles does not map to C++."); } | yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); } @@ -2673,7 +2675,6 @@ system_t_call: // IEEE: system_tf_call (as task) // | yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } | yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } - | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); } // | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,NULL,NULL); } | yD_DISPLAY '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,NULL,$3); } @@ -2698,6 +2699,9 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_READMEMH '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); } | yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); } | yD_READMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); } + // + // Any system function as a task + | system_f_call_or_t { $$ = new AstSysFuncAsTask($1, $1); } ; system_f_call: // IEEE: system_tf_call (as func) @@ -2707,7 +2711,14 @@ system_f_call: // IEEE: system_tf_call (as func) | yaD_DPI parenE { $$ = new AstFuncRef($1,*$1,NULL); } | yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, FuncRef)); } // - | yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); } + | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); } + | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } + // + | system_f_call_or_t { $$ = $1; } + ; + +system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) + yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); } | yD_ACOSH '(' expr ')' { $$ = new AstAcoshD($1,$3); } | yD_ASIN '(' expr ')' { $$ = new AstAsinD($1,$3); } | yD_ASINH '(' expr ')' { $$ = new AstAsinhD($1,$3); } @@ -2717,7 +2728,6 @@ system_f_call: // IEEE: system_tf_call (as func) | yD_BITS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); } | yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); } | yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); } - | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); } | yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); } | yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); } | yD_COS '(' expr ')' { $$ = new AstCosD($1,$3); } @@ -2762,7 +2772,6 @@ system_f_call: // IEEE: system_tf_call (as func) | yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } | yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); } - | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } | yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); } | yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); } | yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); } diff --git a/test_regress/t/t_flag_debug_noleak.pl b/test_regress/t/t_flag_debug_noleak.pl new file mode 100755 index 000000000..97e7d9366 --- /dev/null +++ b/test_regress/t/t_flag_debug_noleak.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2008 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. + +$Self->{vlt} or $Self->skip("Verilator only test"); + +compile ( + v_flags2 => ["--debug --no-debug-leak"], + verilator_make_gcc => 0, + make_top_shell => 0, + make_main => 0, + ); + +ok(1); +1; diff --git a/test_regress/t/t_flag_debug_noleak.v b/test_regress/t/t_flag_debug_noleak.v new file mode 100644 index 000000000..92add3b4e --- /dev/null +++ b/test_regress/t/t_flag_debug_noleak.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2008 by Wilson Snyder. + +module t; + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + diff --git a/test_regress/t/t_sys_plusargs.v b/test_regress/t/t_sys_plusargs.v index f0956f3fb..8de3437ae 100644 --- a/test_regress/t/t_sys_plusargs.v +++ b/test_regress/t/t_sys_plusargs.v @@ -45,6 +45,11 @@ module t; $display("str='%s'",sv_str); if (sv_str != "T=1234") $stop; + sv_str = "none"; + $value$plusargs("IN%s", sv_str); + $display("str='%s'",sv_str); + if (sv_str != "T=1234") $stop; + p_in = "IN%s"; `ifdef VERILATOR p_in = $c(p_in); // Prevent constant propagation diff --git a/test_regress/t/t_unopt_converge_initial.v b/test_regress/t/t_unopt_converge_initial.v new file mode 100644 index 000000000..7806042a4 --- /dev/null +++ b/test_regress/t/t_unopt_converge_initial.v @@ -0,0 +1,25 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2007 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Outputs + x, + // Inputs + clk + ); + +`ifdef ALLOW_UNOPT + /*verilator lint_off UNOPTFLAT*/ +`endif + + input clk; + output [31:0] x; // Avoid eliminating x + + reg [31:0] x; + always @* begin + x = x ^ $random; + end + +endmodule diff --git a/test_regress/t/t_unopt_converge_initial_run_bad.pl b/test_regress/t/t_unopt_converge_initial_run_bad.pl new file mode 100755 index 000000000..497906511 --- /dev/null +++ b/test_regress/t/t_unopt_converge_initial_run_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2007 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_unopt_converge_initial.v"); + +compile ( + v_flags2 => ['+define+ALLOW_UNOPT'], + ); + +execute ( + fails=>1, + expect=> '%Error: \S+:\d+: Verilated model didn\'t DC converge', + ) if $Self->{vlt}; + +ok(1); +1;