Compare commits

...
32 Commits
Author SHA1 Message Date
Wilson Snyder df3d1a4da9 Version bump 2018-03-17 11:56:37 -04:00
Wilson Snyder 3963fe4384 Fix GCC-8 compile error. 2018-03-17 11:33:47 -04:00
Wilson Snyder 38261ac649 Tests: Ignore history file. 2018-03-17 09:25:38 -04:00
Wilson Snyder e49539fb4c Internals: Put cell assigns near cell. No functional change intended except statement order. 2018-03-17 08:43:19 -04:00
Wilson Snyder 3cd96cf558 Tests: Print error line in summary file. 2018-03-16 19:54:25 -04:00
Wilson Snyder 1bcaaa0f0d Internals: Cleanup V3Inst unused argument. No functional change intended. 2018-03-15 23:19:43 -04:00
Wilson Snyder 7922a1de28 Internals: Misc cleanups related to V3LinkDot. No functional change intended. 2018-03-15 19:46:05 -04:00
John Coiner e897c862f2 Tests: t_foreach now checks that all foreach loops get unrolled and evaluated statically. 2018-03-15 19:06:32 -04:00
John Coiner f55040a38b Fix severe runtime performance bug in certain foreach loops. 2018-03-15 08:59:52 -04:00
Wilson Snyder 2d580e6939 Support IEEE 1800-2017 as default language. 2018-03-12 22:26:34 -04:00
John Coiner fc48008c1c Support 2018-03-12 16:44:01 -04:00
Wilson Snyder 4cf2e4024f verilator_difftree: Better error. 2018-03-11 16:49:40 -04:00
Wilson Snyder 57c7d77af3 Tests: Future reduction or test. 2018-03-11 16:33:38 -04:00
Wilson Snyder c8cf2afb15 Support assert properties, bug785, bug1290. 2018-03-11 10:37:20 -04:00
Wilson Snyder 770045676f Internals: Split some extremely long lines. No functional change. 2018-03-10 16:32:04 -05:00
Wilson Snyder 68cca0e114 Commentary, bug1288 2018-03-10 14:16:37 -05:00
Wilson Snyder 0a1b775ed6 Fix various small node leaks. 2018-03-10 14:10:41 -05:00
Wilson Snyder 54a101acbe Internals: Fix -DLEAK_CHECKS failing due to visitor destructor being too late. 2018-03-10 12:57:50 -05:00
John Coiner db1af07d72 On convergence errors, show activity. 2018-03-10 12:52:11 -05:00
John Coiner ff82f75023 Add --no-debug-leak to reduce memory use under debug. 2018-03-10 12:18:19 -05:00
Wilson Snyder 9ae54786e4 Commentary, bug1288. 2018-03-09 00:04:00 -05:00
Wilson Snyder 22ff760f0b Support calling system functions as tasks, bug1285. 2018-03-08 23:40:19 -05:00
John Coiner 86fe6ac3a8 Fix quoting of quoted arguments.
Signed-off-by: Wilson Snyder <[email protected]>
2018-03-08 22:43:29 -05:00
Tymoteusz Blazejczyk 9f52e23158 Fix verilator_coverage --annotate-min, bug1284. 2018-03-07 19:52:29 -05:00
Wilson Snyder e1410775fb Fix CC warning with flex 2.5.35. 2018-02-28 06:34:03 -05:00
John Coiner a7a790416e Internals: Fix passing bool as int. No functional change.
Signed-off-by: Wilson Snyder <[email protected]>
2018-02-27 07:16:16 -05:00
Patrick Stewart fe5c4df079 Support trig functions (() etc), bug1281.
Signed-off-by: Wilson Snyder <[email protected]>
2018-02-26 04:25:07 -05:00
Wilson Snyder 1376e5de92 Fix pullup/pulldowns on bit selects, bug1274. 2018-02-10 19:08:07 -05:00
Wilson Snyder 7f5b1a402c Internals: Part of last change, spacing. 2018-02-07 20:29:58 -05:00
Wilson Snyder 22573d238b Internals: Fix GCC8 cppcheck warnings. No functional change. 2018-02-07 20:16:53 -05:00
Wilson Snyder 32859d9fc2 Fix GCC 8.0 issues 2018-02-07 18:58:21 -05:00
Wilson Snyder 1b12800b8f devel release 2018-02-01 20:14:40 -05:00
137 changed files with 2286 additions and 717 deletions
+1
View File
@@ -23,6 +23,7 @@ dddrun*
doxygen-doc
gdbrun*
gmon.out
ncverilog.history
internals.txt
verilator.txt
verilator_bin*
+27
View File
@@ -2,6 +2,33 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 3.922 2018-03-17
** Support IEEE 1800-2017 as default language.
*** Support trig functions ($sin() etc), bug1281. [Patrick Stewart]
*** Support calling system functions as tasks, bug1285. [Joel Holdsworth]
*** Support assert properties, bug785, bug1290. [John Coiner, et al]
*** Support $writememh. [John Coiner]
*** Add --no-debug-leak to reduce memory use under debug. [John Coiner]
**** Fix severe runtime performance bug in certain foreach loops. [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
** Moving forward, use the git "stable" branch to track the latest release,
+1
View File
@@ -34,6 +34,7 @@ verilator.pc$
verilator_bin.*
verilator_coverage_bin.*
.vcsmx_rebuild$
ncverilog.history
autom4te\.cache/
nodist/
/simv$
+58 -26
View File
@@ -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 <switches>")
# and not single ('run <switches>') 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;
@@ -251,6 +259,7 @@ descriptions in the next sections for more information.
+1800-2005ext+<ext> Use SystemVerilog 2005 with file extension <ext>
+1800-2009ext+<ext> Use SystemVerilog 2009 with file extension <ext>
+1800-2012ext+<ext> Use SystemVerilog 2012 with file extension <ext>
+1800-2017ext+<ext> Use SystemVerilog 2017 with file extension <ext>
--assert Enable all assertions
--autoflush Flush streams after all $displays
--bbox-sys Blackbox unknown $system calls
@@ -270,6 +279,7 @@ descriptions in the next sections for more information.
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
--no-debug-leak Disable leaking memory in --debug mode
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
@@ -336,7 +346,7 @@ descriptions in the next sections for more information.
--stats Create statistics file
--stats-vars Provide statistics on variables
-sv Enable SystemVerilog parsing
+systemverilogext+<ext> Synonym for +1800-2012ext+<ext>
+systemverilogext+<ext> Synonym for +1800-2017ext+<ext>
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
@@ -403,6 +413,8 @@ with the --exe option.
=item +1800-2012ext+I<ext>
=item +1800-2017ext+I<ext>
Specifies the language standard to be used with a specific filename
extension, I<ext>.
@@ -627,6 +639,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 <level>
=item --debugi-<srcfile> <level>
@@ -640,7 +664,7 @@ produce more detailed messages.
Select the language to be used by default when first processing each
Verilog file. The language value must be "1364-1995", "1364-2001",
"1364-2005", "1800-2005", "1800-2009" or "1800-2012".
"1364-2005", "1800-2005", "1800-2009", "1800-2012" or "1800-2017".
Any language associated with a particular file extension (see the various
+I<lang>ext+ options) will be used in preference to the language specified
@@ -653,7 +677,7 @@ legacy mixed language designs, the various +I<lang>ext+ options should be
used.
If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used.
then the latest SystemVerilog language (IEEE 1800-2017) is used.
=item +define+I<var>=I<value>
@@ -1131,7 +1155,7 @@ compatibility with other simulators.
=item +systemverilogext+I<ext>
A synonym for C<+1800-2012ext+>I<ext>.
A synonym for C<+1800-2017ext+>I<ext>.
=item --top-module I<topname>
@@ -1251,8 +1275,9 @@ supports which the older version does not support.
=item -Wno-I<message>
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
@@ -2194,6 +2219,11 @@ Verilator currently has some support for SystemVerilog synthesis
constructs. As SystemVerilog features enter common usage they are added;
please file a bug if a feature you need is missing.
=head2 SystemVerilog 2017 (IEEE 1800-2017) Support
Verilator supports the 2017 "for" loop constructs, and several minor
cleanups made in 1800-2017.
=head2 Verilog AMS Support
Verilator implements a very small subset of Verilog AMS (Verilog Analog and
@@ -3047,13 +3077,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
+2 -1
View File
@@ -85,7 +85,8 @@ sub diff_dir {
diff_file($a,$b);
$any = 1;
}
$any or warn "%Warning: No .tree files found\n";
$any or warn ("%Warning: No .tree files found that have similar base names:\n "
.join("\n ", sort keys %files),"\n");
}
sub diff_file {
+3 -1
View File
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.920 2018-02-01])
AC_INIT([Verilator],[3.922 2018-03-17])
# When releasing, also update header of Changes file
# and commit using "devel release" or "Version bump" message
@@ -77,6 +77,8 @@ AC_PROG_CXX
AC_PROG_INSTALL
AC_LANG_PUSH(C++)
cxx_version=$($CXX --version | head -1)
AC_MSG_RESULT([compiler is $CXX --version = $cxx_version])
AC_MSG_CHECKING([that C++ compiler can compile simple program])
AC_RUN_IFELSE(
[AC_LANG_SOURCE([int main() { return 0; }])],
+155 -12
View File
@@ -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 {
@@ -1201,10 +1205,134 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
return got;
}
void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData ofilename, const void* memp, IData start,
IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
return VL_WRITEMEM_W(hex, width,depth,array_lsb,2,fnw,memp,start,end);
}
void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilenamep, const void* memp, IData start,
IData end) VL_MT_SAFE {
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
std::string ofilenames(ofilenamez);
return VL_WRITEMEM_N(hex, width,depth,array_lsb,ofilenames,memp,start,end);
}
const char* memhFormat(int nBits) {
assert((nBits >= 1) && (nBits <= 32));
static char buf[32];
switch ((nBits - 1) / 4) {
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
default: assert(false); break;
}
return buf;
}
void VL_WRITEMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& ofilenamep, // Output file name
const void* memp, // Array state
IData start, // First array row address to write
IData end // Last address to write
) VL_MT_SAFE {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
"VL_WRITEMEM_N only supports hex format for now, sorry!");
return;
}
FILE* fp = fopen(ofilenamep.c_str(), "w");
if (VL_UNLIKELY(!fp)) {
VL_FATAL_MT(ofilenamep.c_str(), 0, "", "$writemem file not found");
return;
}
for (int row_addr = start; row_addr <= end; ++row_addr) {
if ((row_addr < array_lsb)
|| (row_addr > array_lsb + depth - 1)) {
vluint32_t endmax = ~0;
if (end != endmax) {
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
"$writemem specified address out-of-bounds");
}
// else, it's not an error to overflow due to end == endmax,
// just return cleanly.
goto cleanup;
}
// Compute the offset into the memp array.
int row_offset = row_addr - array_lsb;
if (width <= 8) {
const CData* datap
= &(reinterpret_cast<const CData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 16) {
const SData* datap
= &(reinterpret_cast<const SData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 32) {
const IData* datap
= &(reinterpret_cast<const IData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 64) {
const QData* datap
= &(reinterpret_cast<const QData*>(memp))[row_offset];
vluint64_t value = VL_MASK_Q(width) & *datap;
vluint32_t lo = value & 0xffffffff;
vluint32_t hi = value >> 32;
fprintf(fp, memhFormat(width - 32), hi);
fprintf(fp, "%08x\n", lo);
} else {
WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)];
// output as a sequence of VL_WORDSIZE'd words
// from MSB to LSB. Mask off the MSB word which could
// contain junk above the top of valid data.
int word_idx = ((width - 1) / VL_WORDSIZE);
bool first = true;
while (word_idx >= 0) {
IData data = datap[word_idx];
if (first) {
data &= VL_MASK_I(width);
int top_word_nbits = ((width - 1) & 0x1f) + 1;
fprintf(fp, memhFormat(top_word_nbits), data);
} else {
fprintf(fp, "%08x", data);
}
word_idx--;
first = false;
}
fprintf(fp, "\n");
}
}
cleanup:
fclose(fp);
}
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
return VL_READMEM_W(hex,width,depth,array_lsb,2,fnw,memp,start,end);
}
void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
@@ -1212,12 +1340,20 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
std::string ofilenames(ofilenamez);
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
return VL_READMEM_N(hex,width,depth,array_lsb,ofilenames,memp,start,end);
}
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const std::string& ofilenamep, void* memp, IData start, IData end) VL_MT_SAFE {
if (fnwords) {}
void VL_READMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& ofilenamep, // Input file name
void* memp, // Array state
IData start, // First array row address to read
IData end // Last row address to read
) VL_MT_SAFE {
FILE* fp = fopen(ofilenamep.c_str(), "r");
if (VL_UNLIKELY(!fp)) {
// We don't report the Verilog source filename as it slow to have to pass it down
@@ -1239,7 +1375,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 +1404,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<IData>(depth+array_lsb)
|| addr < static_cast<IData>(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 +1434,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
datap[0] |= value;
}
if (VL_UNLIKELY(value>=(1<<shift))) {
VL_FATAL_MT (ofilenamep.c_str(), linenum, "", "$readmemb (binary) file contains hex characters");
VL_FATAL_MT (ofilenamep.c_str(), linenum, "",
"$readmemb (binary) file contains hex characters");
}
}
}
@@ -1529,6 +1668,8 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
void Verilated::flushCall() VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
if (s_flushCb) (*s_flushCb)();
fflush(stderr);
fflush(stdout);
}
void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
@@ -1743,7 +1884,9 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
VL_FATAL_MT(__FILE__,__LINE__,"",(std::string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
VL_FATAL_MT(__FILE__,__LINE__,"",
(std::string("Unsupported multi-dimensional public varInsert: ")
+ namep).c_str());
}
}
va_end(ap);
+136 -66
View File
@@ -373,7 +373,8 @@ public:
#endif
/// Enable calculation of unused signals
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
static bool calcUnusedSigs() VL_MT_SAFE { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
static bool calcUnusedSigs() VL_MT_SAFE { ///< Return calcUnusedSigs value
return s_s.s_calcUnusedSigs; }
/// Did the simulation $finish?
static void gotFinish(bool flag) VL_MT_SAFE;
static bool gotFinish() VL_MT_SAFE { return s_s.s_gotFinish; } ///< Return if got a $finish
@@ -535,8 +536,8 @@ extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
inline IData VL_FOPEN_II(IData ofilename, IData mode) VL_MT_SAFE { return VL_FOPEN_QI(ofilename,mode); }
inline IData VL_FOPEN_II(IData ofilename, IData mode) VL_MT_SAFE {
return VL_FOPEN_QI(ofilename,mode); }
extern void VL_FCLOSE_I(IData fdi);
@@ -548,6 +549,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
IData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilename, const void* memp, IData start, IData end);
extern void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
QData ofilename, const void* memp, IData start, IData end);
inline void VL_WRITEMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
IData ofilename, const void* memp, IData start, IData end) VL_MT_SAFE {
VL_WRITEMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
@@ -576,16 +585,20 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSETLIMIT_W(data,width,bit) \
(((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
/// Shift appropriate word by bit. Does not account for wrapping between two words
#define VL_BITRSHIFT_W(data,bit) (data[VL_BITWORD_I(bit)] >> 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<IData>(data); owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
#define VL_SET_WQ(owp,data) { owp[0]=static_cast<IData>(data); \
owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
#define VL_SET_WI(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=0; }
#define VL_SET_QW(lwp) ( (static_cast<QData>(lwp[0])) | (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
#define VL_SET_QW(lwp) \
( (static_cast<QData>(lwp[0])) \
| (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
#define _VL_SET_QII(ld,rd) ( (static_cast<QData>(ld)<<VL_ULL(32)) | static_cast<QData>(rd) )
/// Return FILE* from IData
@@ -593,19 +606,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<double>(static_cast<vlsint32_t>(lhs)); }
static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
return static_cast<double>(static_cast<vlsint32_t>(lhs)); }
/// Return QData from double (numeric)
static inline IData VL_RTOI_I_D(double lhs) VL_PURE { return static_cast<vlsint32_t>(VL_TRUNC(lhs)); }
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
return static_cast<vlsint32_t>(VL_TRUNC(lhs)); }
/// Return QData from double (numeric)
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE {
return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input)
@@ -616,8 +636,10 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast<v
// Sign bit extended up to MSB, doesn't include unsigned portion
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE {
return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE {
return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
// Debugging prints
extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
@@ -1400,13 +1422,19 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDa
WDataOutP VL_POW_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs);
QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp);
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) \
VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) \
VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
static inline IData VL_POWSS_III(int obits, int, int rbits,
IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
@@ -1419,7 +1447,8 @@ static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs
}
return VL_POW_III(obits, rbits, rbits, lhs, rhs);
}
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
static inline QData VL_POWSS_QQQ(int obits, int, int rbits,
QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
@@ -1432,9 +1461,12 @@ static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs
}
return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs);
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWW(int obits, int, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits,
WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
QData VL_POWSS_QQW(int obits, int, int rbits,
QData lhs, WDataInP rwp, bool lsign, bool rsign);
//===================================================================
// Concat/replication
@@ -1554,21 +1586,24 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) V
}
return (returndata);
}
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int,
WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
owp[0] = ld;
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WI(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int,
WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
VL_SET_WQ(owp,ld);
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WQ(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int,
WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WW(obits,owp,lwp,i*lbits+lbits-1,i*lbits);
@@ -1633,15 +1668,20 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_
}
switch (rd_log2) {
case 0:
ret = ((ret >> 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 +1734,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<IData>(ld)<<(rbits) | static_cast<IData>(rd))
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) \
(static_cast<IData>(ld)<<(rbits) | static_cast<IData>(rd))
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(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 +1841,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 +1862,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<IData>(obits)) { // rd may be huge with MSB set
@@ -1832,7 +1888,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 +1921,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<IData>(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 +1958,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 +1971,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 +1981,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 +2025,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<IData>((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 +2040,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 +2062,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 +2186,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 +2229,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; }
+6 -3
View File
@@ -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<const VerilatedDpiOpenVar*>(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;
}
+9 -4
View File
@@ -56,17 +56,22 @@ inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData
for (unsigned times=0; times<rep; ++times) out += lhs;
return out;
}
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const std::string& lhs, IData rep) VL_PURE {
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits,
const std::string& lhs, IData rep) VL_PURE {
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
}
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const std::string& ofilename, void* memp, IData start, IData end) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
const std::string& ofilename,
void* memp, IData start, IData end) VL_MT_SAFE;
extern void VL_WRITEMEM_N(bool hex, int width, int depth, int array_lsb,
const std::string& ofilename,
const void* memp, IData start, IData end) VL_MT_SAFE;
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...) VL_MT_SAFE;
extern void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...) VL_MT_SAFE;
extern void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE;
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rdp) VL_MT_SAFE;
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE {
+1 -1
View File
@@ -54,7 +54,7 @@ class VerilatedMsg {
public:
// TYPES
struct Cmp {
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) {
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) const {
return a.trainId() < b.trainId(); }
};
private:
+2 -1
View File
@@ -138,7 +138,8 @@ public:
}
// Read a datum and compare with expected value
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE { return readAssert(&data, sizeof(data)); }
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE {
return readAssert(&data, sizeof(data)); }
private:
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
+20 -10
View File
@@ -52,7 +52,8 @@ public:
int right() const { return m_right; }
int low() const { return (m_left < m_right) ? m_left : m_right; }
int high() const { return (m_left > 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<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR); }
VerilatedVarFlags vldir() const {
return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR); }
vluint32_t entSize() const;
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
/// DPI compatible C standard layout
+4 -2
View File
@@ -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 ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeUnit = timescaleToDouble(unitp);
}
void VerilatedVcd::set_time_resolution (const char* unitp) {
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeRes = timescaleToDouble(unitp);
}
+61 -28
View File
@@ -91,7 +91,8 @@ public:
t_freeHead = oldp;
}
// MEMBERS
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
static inline VerilatedVpio* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
inline vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
// ACCESSORS
virtual const char* name() const { return "<null>"; }
@@ -117,7 +118,8 @@ public:
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
static inline VerilatedVpioCb* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioCb*>((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<VerilatedVpioConst*>((VerilatedVpio*)h); }
static inline VerilatedVpioConst* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioConst*>((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<VerilatedVpioRange*>((VerilatedVpio*)h); }
static inline VerilatedVpioRange* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioRange*>((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<VerilatedVpioScope*>((VerilatedVpio*)h); }
static inline VerilatedVpioScope* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioScope*>((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<VerilatedVpioVar*>((VerilatedVpio*)h); }
static inline VerilatedVpioVar* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioVar*>((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<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWord*>((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<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
static inline VerilatedVpioVarIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioVarIter*>((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<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWordIter*>((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) {
@@ -459,7 +473,7 @@ public:
m_errorInfo.level = level;
return this;
}
void setMessage(std::string file, PLI_INT32 line, std::string message, ...) {
void setMessage(std::string file, PLI_INT32 line, const std::string& message, ...) {
static VL_THREAD_LOCAL std::string filehold;
va_list args;
va_start(args, message);
@@ -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<bits; ++i) {
char val = (datap[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<chars; ++i) {
@@ -1368,8 +1391,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<chars; ++i) {
@@ -1406,7 +1431,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
int i;
if (bytes > 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<CData*>(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<CData*>(vop->varDatap()));
for (int i=0; i<bytes; ++i) {
datap[i] = (i < len)?value_p->value.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;
}
+21 -21
View File
@@ -7,7 +7,7 @@
* This file contains the constant definitions, structure definitions,
* and routine declarations used by SystemVerilog DPI.
*
* This file is from the SystemVerilog IEEE 1800-2012 Annex I.
* This file is from the SystemVerilog IEEE 1800-2017 Annex I.
*/
#ifndef INCLUDED_SVDPI
@@ -117,7 +117,7 @@ typedef uint32_t svBitVecVal;
/*
* Return implementation version information string ("1800-2005" or "SV3.1a").
*/
XXTERN const char* svDpiVersion();
XXTERN const char* svDpiVersion( void );
/* a handle to a scope (an instance of a module or interface) */
XXTERN typedef void* svScope;
@@ -241,28 +241,28 @@ XXTERN void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s
XXTERN void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3);
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
...);
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2);
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2, int indx3);
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
int indx2);
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
int indx2, int indx3);
/* Functions for working with DPI context */
@@ -273,7 +273,7 @@ XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1
* is the scope of the function's declaration site, not call site.
* Returns NULL if called from C code that is *not* an imported function.
*/
XXTERN svScope svGetScope();
XXTERN svScope svGetScope( void );
/*
* Set context for subsequent export function execution.
@@ -337,7 +337,7 @@ XXTERN int svGetCallerInfo(const char** fileName, int *lineNumber);
* Returns 1 if the current execution thread is in the disabled state.
* Disable protocol must be adhered to if in the disabled state.
*/
XXTERN int svIsDisabledState();
XXTERN int svIsDisabledState( void );
/*
* Imported functions call this API function during disable processing to
@@ -345,7 +345,7 @@ XXTERN int svIsDisabledState();
* This function must be called before returning from an imported function that is
* in the disabled state.
*/
XXTERN void svAckDisabledState();
XXTERN void svAckDisabledState( void );
/*
**********************************************************
+3 -3
View File
@@ -1,7 +1,7 @@
/*******************************************************************************
* vpi_user.h
*
* IEEE Std 1800-2012 Programming Language Interface (PLI)
* IEEE Std 1800-2017 Programming Language Interface (PLI)
*
* This file contains the constant definitions, structure definitions, and
* routine declarations used by the SystemVerilog Verification Procedural
@@ -251,7 +251,7 @@ typedef PLI_UINT32 *vpiHandle;
#define vpiModPathOut 96 /* output terminal of a module path */
#define vpiOperand 97 /* operand of expression */
#define vpiPortInst 98 /* connected port instance */
#define vpiProcess 99 /* process in module */
#define vpiProcess 99 /* process in module, program or interface */
#define vpiVariables 100 /* variables in module */
#define vpiUse 101 /* usage */
@@ -978,7 +978,7 @@ XXTERN vpiHandle vpi_handle_by_multi_index PROTO_PARAMS((vpiHandle obj,
/****************************** GLOBAL VARIABLES ******************************/
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])();
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])( void );
/* array of function pointers, last pointer should be null */
+7 -3
View File
@@ -174,11 +174,13 @@ private:
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
if (m_check == CT_INITIAL) {
nodep->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__<<": "<<endl);
ActiveVisitor visitor (nodep);
{
ActiveVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -159,6 +159,8 @@ public:
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveTopVisitor visitor (nodep);
{
ActiveTopVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+34 -9
View File
@@ -88,11 +88,17 @@ private:
return newp;
}
AstNode* newFireAssert(AstNode* nodep, const string& message) {
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
// Like newFireAssert() but omits the asserts-on check
AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop (nodep->fileline()));
return bodysp;
}
AstNode* newFireAssert(AstNode* nodep, const string& message) {
AstNode* bodysp = newFireAssertUnchecked(nodep, message);
bodysp = newIfAssertOn(bodysp);
return bodysp;
}
@@ -105,7 +111,9 @@ private:
//
AstNode* bodysp = NULL;
bool selfDestruct = false;
AstIf* ifp = NULL;
if (AstPslCover* snodep = nodep->castPslCover()) {
++m_statAsCover;
if (!v3Global.opt.coverageUser()) {
selfDestruct = true;
} else {
@@ -116,14 +124,30 @@ private:
if (message!="") covincp->declp()->comment(message);
bodysp = covincp;
}
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
} else if (nodep->castPslAssert()) {
++m_statAsPsl;
// Insert an automatic error message and $stop after
// any user-supplied statements.
AstNode* autoMsgp = newFireAssertUnchecked(nodep, "'assert property' failed.");
if (stmtsp) {
stmtsp->addNext(autoMsgp);
} else {
stmtsp = autoMsgp;
}
ifp = new AstIf(nodep->fileline(), propp, NULL, stmtsp);
// It's more LIKELY that we'll take the NULL if clause
// than the sim-killing else clause:
ifp->branchPred(AstBranchPred::BP_LIKELY);
bodysp = newIfAssertOn(ifp);
} else {
nodep->v3fatalSrc("Unknown node type");
}
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
//
AstNode* newp = new AstAlways (nodep->fileline(),
VAlwaysKwd::ALWAYS,
sentreep,
@@ -294,12 +318,11 @@ private:
}
}
virtual void visit(AstPslCover* nodep) {
virtual void visit(AstNodePslCoverOrAssert* nodep) {
nodep->iterateChildren(*this);
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep);
++m_statAsCover;
}
virtual void visit(AstVAssert* nodep) {
nodep->iterateChildren(*this);
@@ -349,6 +372,8 @@ public:
void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertVisitor visitor (nodep);
{
AssertVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+4 -2
View File
@@ -86,7 +86,7 @@ private:
pushDeletep(nodep); VL_DANGLING(nodep);
}
virtual void visit(AstPslCover* nodep) {
virtual void visit(AstNodePslCoverOrAssert* nodep) {
if (nodep->sentreep()) return; // Already processed
clearAssertInfo();
nodep->iterateChildren(*this);
@@ -136,6 +136,8 @@ public:
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertPreVisitor visitor (nodep);
{
AssertPreVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+14 -3
View File
@@ -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:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "
// <<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// // Commenting out the section below may crash, as the tree state
@@ -677,9 +678,17 @@ void AstNode::deleteNode() {
this->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<<endl); // niterp maybe NULL, so need cast
// niterp maybe NULL, so need cast if printing
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep
// <<" now into "<<(void*)niterp<<endl);
if (!niterp) return; // Perhaps node deleted inside accept
niterp->m_iterpp = NULL;
if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept
+27 -14
View File
@@ -1101,7 +1101,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;
@@ -1287,12 +1288,13 @@ public:
static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
void addNextHere(AstNode* newp); // Adds after speced node
void addNextHere(AstNode* newp); // Insert newp at this->nextp
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
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(); }
@@ -1321,17 +1323,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
@@ -1454,7 +1459,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
@@ -1740,7 +1747,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; }
@@ -1958,7 +1966,7 @@ class AstNodeFTaskRef : public AstNode {
private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
string m_name; // Name of variable
string m_dotted; // Dotted part of scope to task or ""
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
AstPackage* m_packagep; // Package hierarchy
public:
@@ -2078,11 +2086,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() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->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() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->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() { return (this->castConst() && this->castConst()->num().isEqZero()); }
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
+4 -3
View File
@@ -64,7 +64,8 @@ int AstNodeSel::bitConst() const {
void AstNodeClassDType::repairMemberCache() {
clearCache();
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
if (m_members.find(itemp->name())!=m_members.end()) {
itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
else m_members.insert(make_pair(itemp->name(), itemp));
}
}
@@ -1023,7 +1024,7 @@ void AstVarXRef::dump(ostream& str) {
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
str<<dotted()<<". - ";
str<<".="<<dotted()<<" ";
if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
if (varScopep()) { varScopep()->dump(str); }
else if (varp()) { varp()->dump(str); }
@@ -1094,7 +1095,7 @@ void AstNodeFTaskRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
str<<" -> ";
if (dotted()!="") { str<<dotted()<<". - "; }
if (dotted()!="") { str<<".="<<dotted()<<" "; }
if (taskp()) { taskp()->dump(str); }
else { str<<"UNLINKED"; }
}
+289 -101
View File
@@ -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 op1p()->castNodeDType(); } // 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)
@@ -1475,7 +1484,7 @@ class AstVarXRef : public AstNodeVarRef {
// A VarRef to something in another module before AstScope.
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
private:
string m_dotted; // Scope name to connected to
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
public:
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
@@ -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(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
@@ -2742,17 +2773,16 @@ public:
void fromp(AstNode* nodep) { setOp2p(nodep); }
};
class AstReadMem : public AstNodeStmt {
class AstNodeReadWriteMem : public AstNodeStmt {
private:
bool m_isHex; // readmemh, not readmemb
public:
AstReadMem(FileLine* fileline, bool hex,
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
AstNodeReadWriteMem(FileLine* fileline, bool hex,
AstNode* filenamep, AstNode* memp,
AstNode* lsbp, AstNode* msbp)
: AstNodeStmt (fileline), m_isHex(hex) {
setOp1p(filenamep); setOp2p(memp); setNOp3p(lsbp); setNOp4p(msbp);
}
ASTNODE_NODE_FUNCS(ReadMem)
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isPure() const { return false; }
@@ -2760,12 +2790,35 @@ public:
virtual bool isUnlikely() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const {
return isHex()==static_cast<const AstReadMem*>(samep)->isHex(); }
return isHex()==static_cast<const AstNodeReadWriteMem*>(samep)->isHex();
}
bool isHex() const { return m_isHex; }
AstNode* filenamep() const { return op1p(); }
AstNode* memp() const { return op2p(); }
AstNode* lsbp() const { return op3p(); }
AstNode* msbp() const { return op4p(); }
virtual const char* cFuncPrefixp() const = 0;
};
class AstReadMem : public AstNodeReadWriteMem {
public:
AstReadMem(FileLine* fileline, bool hex,
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
: AstNodeReadWriteMem(fileline, hex, filenamep, memp, lsbp, msbp)
{ }
ASTNODE_NODE_FUNCS(ReadMem);
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
virtual const char* cFuncPrefixp() const { return "VL_READMEM_"; }
};
class AstWriteMem : public AstNodeReadWriteMem {
public:
AstWriteMem(FileLine* fileline,
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
: AstNodeReadWriteMem(fileline, true, filenamep, memp, lsbp, msbp) { }
ASTNODE_NODE_FUNCS(WriteMem)
virtual string verilogKwd() const { return (isHex()?"$writememh":"$writememb"); }
virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; }
};
class AstSystemT : public AstNodeStmt {
@@ -3420,10 +3473,14 @@ public:
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
AstText* scopeEntrp() const { return op2p()->castText(); }
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; }
};
@@ -3947,94 +4004,176 @@ public:
AstNode* filep() const { return lhsp(); }
};
class AstCeilD : public AstNodeUniop {
class AstNodeSystemUniop : public AstNodeUniop {
public:
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_NODE_FUNCS(CeilD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(ceil(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ceil(%l)"; }
virtual string emitC() { return "ceil(%li)"; }
AstNodeSystemUniop(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_BASE_FUNCS(NodeSystemUniop)
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstExpD : public AstNodeUniop {
class AstLogD : public AstNodeSystemUniop {
public:
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_NODE_FUNCS(ExpD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(exp(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$exp(%l)"; }
virtual string emitC() { return "exp(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstFloorD : public AstNodeUniop {
public:
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_NODE_FUNCS(FloorD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(floor(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$floor(%l)"; }
virtual string emitC() { return "floor(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstLogD : public AstNodeUniop {
public:
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(LogD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(log(lhs.toDouble())); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ln(%l)"; }
virtual string emitC() { return "log(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstLog10D : public AstNodeUniop {
class AstLog10D : public AstNodeSystemUniop {
public:
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(Log10D)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(log10(lhs.toDouble())); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log10(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$log10(%l)"; }
virtual string emitC() { return "log10(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstSqrtD : public AstNodeUniop {
class AstExpD : public AstNodeSystemUniop {
public:
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(ExpD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(exp(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$exp(%l)"; }
virtual string emitC() { return "exp(%li)"; }
};
class AstSqrtD : public AstNodeSystemUniop {
public:
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SqrtD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(sqrt(lhs.toDouble())); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sqrt(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sqrt(%l)"; }
virtual string emitC() { return "sqrt(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstFloorD : public AstNodeSystemUniop {
public:
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(FloorD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(floor(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$floor(%l)"; }
virtual string emitC() { return "floor(%li)"; }
};
class AstCeilD : public AstNodeSystemUniop {
public:
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CeilD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(ceil(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ceil(%l)"; }
virtual string emitC() { return "ceil(%li)"; }
};
class AstSinD : public AstNodeSystemUniop {
public:
AstSinD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SinD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sin(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sin(%l)"; }
virtual string emitC() { return "sin(%li)"; }
};
class AstCosD : public AstNodeSystemUniop {
public:
AstCosD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CosD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cos(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$cos(%l)"; }
virtual string emitC() { return "cos(%li)"; }
};
class AstTanD : public AstNodeSystemUniop {
public:
AstTanD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TanD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tan(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$tan(%l)"; }
virtual string emitC() { return "tan(%li)"; }
};
class AstAsinD : public AstNodeSystemUniop {
public:
AstAsinD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AsinD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asin(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$asin(%l)"; }
virtual string emitC() { return "asin(%li)"; }
};
class AstAcosD : public AstNodeSystemUniop {
public:
AstAcosD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AcosD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acos(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$acos(%l)"; }
virtual string emitC() { return "acos(%li)"; }
};
class AstAtanD : public AstNodeSystemUniop {
public:
AstAtanD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AtanD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atan(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$atan(%l)"; }
virtual string emitC() { return "atan(%li)"; }
};
class AstSinhD : public AstNodeSystemUniop {
public:
AstSinhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SinhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sinh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sinh(%l)"; }
virtual string emitC() { return "sinh(%li)"; }
};
class AstCoshD : public AstNodeSystemUniop {
public:
AstCoshD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CoshD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cosh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$cosh(%l)"; }
virtual string emitC() { return "cosh(%li)"; }
};
class AstTanhD : public AstNodeSystemUniop {
public:
AstTanhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TanhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tanh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$tanh(%l)"; }
virtual string emitC() { return "tanh(%li)"; }
};
class AstAsinhD : public AstNodeSystemUniop {
public:
AstAsinhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AsinhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asinh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$asinh(%l)"; }
virtual string emitC() { return "asinh(%li)"; }
};
class AstAcoshD : public AstNodeSystemUniop {
public:
AstAcoshD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AcoshD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acosh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$acosh(%l)"; }
virtual string emitC() { return "acosh(%li)"; }
};
class AstAtanhD : public AstNodeSystemUniop {
public:
AstAtanhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AtanhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atanh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$atanh(%l)"; }
virtual string emitC() { return "atanh(%li)"; }
};
//======================================================================
@@ -4525,7 +4664,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
@@ -5004,6 +5145,39 @@ public:
AstNode* filep() const { return rhsp(); }
};
class AstNodeSystemBiop : public AstNodeBiop {
public:
AstNodeSystemBiop(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeSetDouble(); }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstAtan2D : public AstNodeSystemBiop {
public:
AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeSystemBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(Atan2D)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAtan2D(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
out.setDouble(atan2(lhs.toDouble(), rhs.toDouble())); }
virtual string emitVerilog() { return "%f$atan2(%l,%r)"; }
virtual string emitC() { return "atan2(%li,%ri)"; }
};
class AstHypotD : public AstNodeSystemBiop {
public:
AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeSystemBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(HypotD)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstHypotD(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
out.setDouble(hypot(lhs.toDouble(), rhs.toDouble())); }
virtual string emitVerilog() { return "%f$hypot(%l,%r)"; }
virtual string emitC() { return "hypot(%li,%ri)"; }
};
class AstPattern : public AstNodeMath {
// Verilog '{a,b,c,d...}
// Parents: AstNodeAssign, AstPattern, ...
@@ -5109,30 +5283,44 @@ public:
AstNode* propp() const { return op3p(); } // op3 = property
};
class AstPslCover : public AstNodeStmt {
class AstNodePslCoverOrAssert : public AstNodeStmt {
// Psl Cover
// Parents: {statement list}
// Children: expression, report string
private:
string m_name; // Name to report
public:
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
AstNodePslCoverOrAssert(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodeStmt(fl)
, m_name(name) {
addOp1p(propp);
addNOp4p(stmtsp);
}
ASTNODE_NODE_FUNCS(PslCover)
virtual string name() const { return m_name; } // * = Var name
ASTNODE_BASE_FUNCS(NodePslCoverOrAssert)
virtual string name() const { return m_name; } // * = Var name
virtual V3Hash sameHash() const { return V3Hash(name()); }
virtual bool same(const AstNode* samep) const { return samep->name() == name(); }
virtual void name(const string& name) { m_name = name; }
AstNode* propp() const { return op1p(); } // op1 = property
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
AstNode* stmtsp() const { return op4p(); } // op4 = statements
AstNode* propp() const { return op1p(); } // op1 = property
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
AstNode* stmtsp() const { return op4p(); } // op4 = statements
};
class AstPslCover : public AstNodePslCoverOrAssert {
public:
ASTNODE_NODE_FUNCS(PslCover)
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodePslCoverOrAssert(fl, propp, stmtsp, name) {}
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
};
class AstPslAssert : public AstNodePslCoverOrAssert {
public:
ASTNODE_NODE_FUNCS(PslAssert)
AstPslAssert(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodePslCoverOrAssert(fl, propp, stmtsp, name) {}
};
//======================================================================
+7 -5
View File
@@ -291,10 +291,12 @@ public:
void V3Begin::debeginAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
BeginState state;
{ BeginVisitor bvisitor (nodep,&state); }
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
{
BeginState state;
{ BeginVisitor bvisitor (nodep,&state); }
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
} // Destruct before checking
V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+5 -2
View File
@@ -224,8 +224,11 @@ private:
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
}
if (nodep->dtypep()) {
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
else if (!nodep->dtypep()->castNodeDType()) { 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 (!nodep->dtypep()->castNodeDType()) {
nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep());
}
}
if (v3Global.assertDTypesResolved()) {
if (nodep->hasDType()) {
+4 -2
View File
@@ -77,7 +77,8 @@ public:
m_numStmts += 1;
}
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="",
V3CCtorsVisitor(AstNodeModule* nodep, const string& basename,
const string& argsp="", const string& callargsp="",
const string& stmt="") {
m_basename = basename;
m_argsp = argsp;
@@ -129,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);
+3 -1
View File
@@ -488,7 +488,9 @@ public:
void V3Case::caseAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CaseVisitor visitor (nodep);
{
CaseVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Case::caseLint(AstNodeCase* nodep) {
+3 -1
View File
@@ -187,6 +187,8 @@ public:
void V3Cast::castAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CastVisitor visitor (nodep);
{
CastVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+10 -4
View File
@@ -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): "<<m_vscp->varp()->prettyName());
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
" (probably with UNOPTFLAT warning suppressed): "
<<m_vscp->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): "<<m_vscp->varp()->prettyName());
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
" (probably with UNOPTFLAT warning suppressed): "
<<m_vscp->varp()->prettyName());
}
public:
// CONSTUCTORS
@@ -300,7 +304,9 @@ public:
void V3Changed::changedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ChangedState state;
ChangedVisitor visitor (nodep, &state);
{
ChangedState state;
ChangedVisitor visitor (nodep, &state);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -297,6 +297,8 @@ public:
void V3Clean::cleanAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CleanVisitor visitor (nodep);
{
CleanVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+4 -2
View File
@@ -912,8 +912,10 @@ public:
void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
// While the gater does well at some modules, it seems to slow down many others
UINFO(5,"ClkGater is disabled due to performance issues\n");
{
// While the gater does well at some modules, it seems to slow down many others
UINFO(5,"ClkGater is disabled due to performance issues\n");
} // Destruct before checking
//GaterVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clkgater", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -406,6 +406,8 @@ public:
void V3Clock::clockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ClockVisitor visitor (nodep);
{
ClockVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -473,6 +473,8 @@ public:
void V3Combine::combineAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CombineVisitor visitor (nodep);
{
CombineVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -144,7 +144,7 @@ V3ConfigIgnores V3ConfigIgnores::s_singleton;
//######################################################################
// V3Config
void V3Config::addIgnore(V3ErrorCode code, bool on, string filename, int min, int max) {
void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max) {
if (filename=="*") {
FileLine::globalWarnOff(code,!on);
} else {
+1 -1
View File
@@ -30,7 +30,7 @@
class V3Config {
public:
static void addIgnore(V3ErrorCode code, bool on, string filename, int min, int max);
static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max);
static void applyIgnores(FileLine* filelinep);
};
+18 -9
View File
@@ -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: ");
@@ -2559,15 +2560,19 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
void V3Const::constifyAllLint(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep);
{
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep);
{
ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("const_cpp", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
@@ -2582,16 +2587,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__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep);
{
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Const::constifyAll(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep);
{
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -395,6 +395,8 @@ public:
void V3Coverage::coverage(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
CoverageVisitor visitor (rootp);
{
CoverageVisitor visitor (rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -134,6 +134,8 @@ public:
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
CoverageJoinVisitor visitor (rootp);
{
CoverageJoinVisitor visitor (rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+15 -5
View File
@@ -425,30 +425,40 @@ public:
void V3Dead::deadifyModules(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, false, false, false);
{
DeadVisitor visitor (nodep, false, false, false, false);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deadModules", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true, false, false);
{
DeadVisitor visitor (nodep, false, true, false, false);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deadDtypes", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true, true, false);
{
DeadVisitor visitor (nodep, false, true, true, false);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true, false, true);
{
DeadVisitor visitor (nodep, true, true, false, true);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deadAll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true, true, true);
{
DeadVisitor visitor (nodep, true, true, true, true);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+13 -6
View File
@@ -115,7 +115,8 @@ private:
//UINFO(4," MVU "<<flags<<" "<<nodep<<endl);
nodep->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: "<<nodep->varp()->prettyName());
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "
<<nodep->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: "<<varrefp->varp()->prettyName()<<endl
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks with different clocking: "
<<varrefp->varp()->prettyName()<<endl
<<varrefp->warnMore()<<"... Location of first driving block"<<endl
<<oldactivep->warnMore()<<"... Location of other driving block");
varrefp->varp()->user2(true);
@@ -195,8 +197,9 @@ private:
arrayselp = lhsp->castArraySel();
}
if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?");
if (arrayselp->dtypep()->skipRefp()->castUnpackArrayDType()) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
if (arrayselp->dtypep()->skipRefp()->castUnpackArrayDType()) {
nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
}
UINFO(4,"AssignDlyArray: "<<nodep<<endl);
//
//=== Dimensions: __Vdlyvdim__
@@ -391,7 +394,9 @@ private:
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
markVarUsage(nodep->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 = oldvscp->user1p()->castVarScope();
@@ -470,6 +475,8 @@ public:
void V3Delayed::delayedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DelayedVisitor visitor (nodep);
{
DelayedVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("delayed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -174,6 +174,8 @@ public:
void V3Depth::depthAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DepthVisitor visitor (nodep);
{
DepthVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+3 -1
View File
@@ -139,6 +139,8 @@ public:
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DepthBlockVisitor visitor (nodep);
{
DepthBlockVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -311,6 +311,8 @@ public:
void V3Descope::descopeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DescopeVisitor visitor (nodep);
{
DescopeVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+62 -39
View File
@@ -322,8 +322,8 @@ public:
nodep->modep()->iterateAndNext(*this);
puts(");\n");
}
virtual void visit(AstReadMem* nodep) {
puts("VL_READMEM_");
virtual void visit(AstNodeReadWriteMem* nodep) {
puts(nodep->cFuncPrefixp());
emitIQW(nodep->filenamep());
puts(" ("); // We take a void* rather than emitIQW(nodep->memp());
puts(nodep->isHex()?"true":"false");
@@ -333,21 +333,26 @@ public:
uint32_t array_lsb = 0;
{
AstVarRef* varrefp = nodep->memp()->castVarRef();
if (!varrefp) { nodep->v3error("Readmem loading non-variable"); }
if (!varrefp) {
nodep->v3error(nodep->verilogKwd() << " loading non-variable");
}
else if (AstUnpackArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castUnpackArrayDType()) {
puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements()));
array_lsb = adtypep->lsb();
}
else {
nodep->v3error("Readmem loading other than unpacked-array variable");
nodep->v3error(nodep->verilogKwd()
<< " loading other than unpacked-array variable");
}
}
putbs(", ");
puts(cvtToStr(array_lsb));
putbs(",");
puts(cvtToStr(nodep->filenamep()->widthWords()));
checkMaxWords(nodep->filenamep());
putbs(", ");
if (!nodep->filenamep()->dtypep()->isString()) {
puts(cvtToStr(nodep->filenamep()->widthWords()));
checkMaxWords(nodep->filenamep());
putbs(", ");
}
nodep->filenamep()->iterateAndNext(*this);
putbs(", ");
nodep->memp()->iterateAndNext(*this);
@@ -374,6 +379,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());
@@ -507,31 +517,36 @@ public:
}
virtual void visit(AstMulS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
nodep->v3error("Unsupported: Signed multiply of "<<nodep->width()
<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPow* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
nodep->v3error("Unsupported: Power of "<<nodep->width()
<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowSS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
nodep->v3error("Unsupported: Power of "<<nodep->width()
<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowSU* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
nodep->v3error("Unsupported: Power of "<<nodep->width()
<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowUS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
nodep->v3error("Unsupported: Power of "<<nodep->width()
<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
@@ -976,9 +991,9 @@ 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);
void writeMakefile(string filename);
public:
EmitCImp() {
@@ -1548,7 +1563,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
@@ -1725,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");
@@ -1746,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");
}
@@ -1776,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);
}
@@ -2291,8 +2313,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
+2 -1
View File
@@ -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: '"<<nodep->prettyName()<<"'");
nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter,"
" should have hit SYMRSVDWORD: '"<<nodep->prettyName()<<"'");
}
}
}
+5 -1
View File
@@ -268,7 +268,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
if (nodep->stmtsp()) nodep->stmtsp()->iterateAndNext(*this);
puts("end\n");
}
virtual void visit(AstReadMem* nodep) {
virtual void visit(AstNodeReadWriteMem* nodep) {
putfs(nodep,nodep->verilogKwd());
putbs(" (");
if (nodep->filenamep()) nodep->filenamep()->iterateAndNext(*this);
@@ -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(" (");
+7 -3
View File
@@ -266,8 +266,11 @@ inline void v3errorEndFatal(ostringstream& sstr) { V3Error::v3errorEnd(sstr); as
// 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()<<msg), V3Error::v3errorStr()));
#define v3warnCodeFatal(code,msg) v3errorEndFatal((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
#define v3warnCode(code,msg) \
v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
#define v3warnCodeFatal(code,msg) \
v3errorEndFatal((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), \
V3Error::v3errorStr()));
#define v3warn(code,msg) v3warnCode(V3ErrorCode::code, msg)
#define v3info(msg) v3warnCode(V3ErrorCode::EC_INFO, msg)
#define v3error(msg) v3warnCode(V3ErrorCode::EC_ERROR, msg)
@@ -286,7 +289,8 @@ inline void v3errorEndFatal(ostringstream& sstr) { V3Error::v3errorEnd(sstr); as
#define UASSERT(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { v3fatalSrc(stmsg); }}
// For use in V3Ast static functions only
#define UASSERT_STATIC(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<":"<<(stmsg)<<endl; abort(); } }
#define UASSERT_STATIC(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { \
cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<":"<<(stmsg)<<endl; abort(); } }
#define V3ERROR_NA { v3error("Internal: Unexpected Call"); v3fatalSrc("Unexpected Call"); }
+6 -2
View File
@@ -243,7 +243,9 @@ private:
}
bool expandWide (AstNodeAssign* nodep, AstArraySel* rhsp) {
UINFO(8," Wordize ASSIGN(ARRAYSEL) "<<nodep<<endl);
if (nodep->dtypep()->skipRefp()->castUnpackArrayDType()) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
if (nodep->dtypep()->skipRefp()->castUnpackArrayDType()) {
nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
}
for (int w=0; w<nodep->widthWords(); w++) {
addWordAssign(nodep, w, newAstWordSelClone (rhsp, w));
}
@@ -936,6 +938,8 @@ public:
void V3Expand::expandAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ExpandVisitor visitor (nodep);
{
ExpandVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("expand", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -1
View File
@@ -238,7 +238,8 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm
UINFO(2," --check-times failed: missing "<<chkFilename<<endl);
return false;
}
//UINFO(9," got d="<<chkDir<<" s="<<chkSize<<" ct="<<chkCstime<<"."<<chkCnstime<<" mt="<<chkMstime<<"."<<chkMnstime<<" fn = "<<chkFilename<<endl);
//UINFO(9," got d="<<chkDir<<" s="<<chkSize<<" ct="<<chkCstime<<"."
// <<chkCnstime<<" mt="<<chkMstime<<"."<<chkMnstime<<" fn = "<<chkFilename<<endl);
//UINFO(9," nowSt s="<<chkStat.st_size<<" mt="<<chkStat.st_mtime<<" ct="<<chkStat.st_ctime<<" fn = "<<chkFilename<<endl);
if (filename != chkFilename) { // Other then the .dat file itself, as we were writing it at the time...
// We'd like this rule:
+4 -2
View File
@@ -1496,7 +1496,9 @@ public:
void V3Gate::gateAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
GateVisitor visitor (nodep);
GateDeassignVisitor deassign (nodep);
{
GateVisitor visitor (nodep);
GateDeassignVisitor deassign (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("gate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -242,6 +242,8 @@ public:
void V3GenClk::genClkAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
GenClkReadVisitor visitor (nodep);
{
GenClkReadVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("genclk", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+5
View File
@@ -69,7 +69,12 @@ private:
// MEMBERS
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
#ifdef VL_CPPCHECK
static int debug() { return 9; }
#else
static int debug() { return 0; }
#endif
// METHODS
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
+9 -12
View File
@@ -42,6 +42,7 @@
#include "V3Inst.h"
#include "V3Stats.h"
#include "V3Ast.h"
#include "V3String.h"
// CONFIG
static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can always inline it
@@ -270,14 +271,14 @@ public:
class InlineRelinkVisitor : public AstNVisitor {
private:
typedef vl_unordered_set<string> RenamedInterfacesSet;
typedef vl_unordered_set<string> StringSet;
// NODE STATE
// Input:
// See InlineVisitor
// STATE
RenamedInterfacesSet m_renamedInterfaces; // Name of renamed interface variables
StringSet m_renamedInterfaces; // Name of renamed interface variables
AstNodeModule* m_modp; // Current module
AstCell* m_cellp; // Cell being cloned
@@ -410,9 +411,8 @@ private:
}
virtual void visit(AstVarXRef* nodep) {
// Track what scope it was originally under so V3LinkDot can resolve it
string newname = m_cellp->name();
if (nodep->inlinedDots() != "") { newname += "." + nodep->inlinedDots(); }
nodep->inlinedDots(newname);
string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots());
nodep->inlinedDots(newdots);
for (string tryname = nodep->dotted(); 1;) {
if (m_renamedInterfaces.count(tryname)) {
nodep->dotted(m_cellp->name() + "__DOT__" + nodep->dotted());
@@ -430,9 +430,8 @@ private:
}
virtual void visit(AstNodeFTaskRef* nodep) {
// Track what scope it was originally under so V3LinkDot can resolve it
string newname = m_cellp->name();
if (nodep->inlinedDots() != "") { newname += "." + nodep->inlinedDots(); }
nodep->inlinedDots(newname);
string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots());
nodep->inlinedDots(newdots);
if (m_renamedInterfaces.count(nodep->dotted())) {
nodep->dotted(m_cellp->name() + "__DOT__" + nodep->dotted());
}
@@ -459,9 +458,7 @@ private:
}
virtual void visit(AstCoverDecl* nodep) {
// Fix path in coverage statements
nodep->hier(m_cellp->prettyName()
+ (nodep->hier()!="" ? ".":"")
+ nodep->hier());
nodep->hier(VString::dot(m_cellp->prettyName(), ".", nodep->hier()));
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep) {
@@ -537,7 +534,7 @@ private:
// this loop as it clone()s itself.
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (!pinp->exprp()) continue;
V3Inst::pinReconnectSimple(pinp, nodep, m_modp, false);
V3Inst::pinReconnectSimple(pinp, nodep, false);
}
// Clone original module
+19 -22
View File
@@ -49,8 +49,7 @@ private:
AstUser1InUse m_inuser1;
// STATE
AstNodeModule* m_modp; // Current module
AstCell* m_cellp; // Current cell
AstCell* m_cellp; // Current cell
static int debug() {
static int level = -1;
@@ -60,13 +59,6 @@ private:
//int m_debug; int debug() { return m_debug; }
// VISITORS
virtual void visit(AstNodeModule* nodep) {
UINFO(4," MOD "<<nodep<<endl);
//if (nodep->name() == "t_chg") m_debug = 9; else m_debug=0;
m_modp = nodep;
nodep->iterateChildren(*this);
m_modp = NULL;
}
virtual void visit(AstCell* nodep) {
UINFO(4," CELL "<<nodep<<endl);
m_cellp = nodep;
@@ -86,9 +78,9 @@ private:
// Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1SetOnce()) {
// Simplify it
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
// Make a ASSIGNW (expr, pin)
AstNode* exprp = nodep->exprp()->cloneTree(false);
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
// Make an ASSIGNW (expr, pin)
AstNode* exprp = nodep->exprp()->cloneTree(false);
if (exprp->width() != nodep->modVarp()->width())
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
if (nodep->modVarp()->isInout()) {
@@ -96,7 +88,7 @@ private:
} else if (nodep->modVarp()->isOutput()) {
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
m_modp->addStmtp(assp);
m_cellp->addNextHere(assp);
} else if (nodep->modVarp()->isInput()) {
// Don't bother moving constants now,
// we'll be pushing the const down to the cell soon enough.
@@ -104,7 +96,7 @@ private:
(exprp->fileline(),
new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), true),
exprp);
m_modp->addStmtp(assp);
m_cellp->addNextHere(assp);
if (debug()>=9) assp->dumpTree(cout," _new: ");
} else if (nodep->modVarp()->isIfaceRef()
|| (nodep->modVarp()->subDTypep()->castUnpackArrayDType()
@@ -115,7 +107,7 @@ private:
AstVarXRef* xrefp = exprp->castVarXRef();
if (!refp && !xrefp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef or VarXRef");
AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, exprp);
m_modp->addStmtp(assp);
m_cellp->addNextHere(assp);
} else {
nodep->v3error("Assigned pin is neither input nor output");
}
@@ -133,6 +125,7 @@ private:
}
// Save some time
virtual void visit(AstNodeMath*) {}
virtual void visit(AstNodeAssign*) {}
virtual void visit(AstAlways*) {}
@@ -144,7 +137,6 @@ private:
public:
// CONSTUCTORS
explicit InstVisitor(AstNetlist* nodep) {
m_modp=NULL;
m_cellp=NULL;
//
nodep->accept(*this);
@@ -496,7 +488,7 @@ private:
}
public:
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp,
bool forTristate, bool alwaysCvt) {
// If a pin connection is "simple" leave it as-is
// Else create a intermediate wire to perform the interconnect
@@ -545,7 +537,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);
@@ -572,9 +565,9 @@ public:
//######################################################################
// Inst class functions
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp,
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp,
bool forTristate, bool alwaysCvt) {
return InstStatic::pinReconnectSimple(pinp, cellp, modp, forTristate, alwaysCvt);
return InstStatic::pinReconnectSimple(pinp, cellp, forTristate, alwaysCvt);
}
//######################################################################
@@ -582,12 +575,16 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
void V3Inst::instAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
InstVisitor visitor (nodep);
{
InstVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("inst", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Inst::dearrayAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
InstDeVisitor visitor (nodep);
{
InstDeVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("dearray", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+1 -1
View File
@@ -31,7 +31,7 @@ class V3Inst {
public:
static void instAll(AstNetlist* nodep);
static void dearrayAll(AstNetlist* nodep);
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp,
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp,
bool forTristate, bool alwaysCvt=false);
};
+6 -3
View File
@@ -42,6 +42,7 @@ public:
L1800_2005,
L1800_2009,
L1800_2012,
L1800_2017,
// ***Add new elements below also***
_ENUM_END
};
@@ -54,12 +55,14 @@ public:
"1364-2005",
"1800-2005",
"1800-2009",
"1800-2012"
"1800-2012",
"1800-2017"
};
return names[m_e];
};
static V3LangCode mostRecent() { return V3LangCode(L1800_2012); }
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009 || m_e == L1800_2012; }
static V3LangCode mostRecent() { return V3LangCode(L1800_2017); }
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009
|| m_e == L1800_2012 || m_e == L1800_2017; }
bool legal() const { return m_e != L_ERROR; }
//
enum en m_e;
+4 -2
View File
@@ -518,7 +518,9 @@ public:
void V3Life::lifeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
LifeState state;
LifeTopVisitor visitor (nodep, &state);
{
LifeState state;
LifeTopVisitor visitor (nodep, &state);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("life", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -213,6 +213,8 @@ public:
void V3LifePost::lifepostAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
// Mark redundant AssignPost
LifePostDlyVisitor visitor (nodep);
{
LifePostDlyVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("life_post", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -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 {
+32 -23
View File
@@ -78,6 +78,7 @@
#include "V3Graph.h"
#include "V3Ast.h"
#include "V3ParseImp.h"
#include "V3String.h"
//######################################################################
// LinkDot state, as a visitor of each AstNode
@@ -262,7 +263,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<<" "<<scopename<<" above=se"<<(void*)abovep<<" mods=se"<<(void*)modSymp<<" node="<<nodep<<endl);
UINFO(9," INSERTcel se"<<(void*)symp<<" "<<scopename<<" above=se"<<(void*)abovep
<<" mods=se"<<(void*)modSymp<<" node="<<nodep<<endl);
symp->parentp(abovep);
symp->fallbackp(dunitEntp()); // Needed so can find $unit stuff
nodep->user1p(symp);
@@ -283,7 +285,8 @@ public:
// This refrences to another Sym, and eventually resolves to a module with a prefix
if (!abovep) nodep->v3fatalSrc("Null symbol table inserting node");
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
UINFO(9," INSERTinl se"<<(void*)symp<<" "<<basename<<" above=se"<<(void*)abovep<<" mods=se"<<(void*)modSymp<<" node="<<nodep<<endl);
UINFO(9," INSERTinl se"<<(void*)symp<<" "<<basename<<" above=se"<<(void*)abovep
<<" mods=se"<<(void*)modSymp<<" node="<<nodep<<endl);
symp->parentp(abovep);
symp->fallbackp(modSymp);
symp->symPrefix(nodep->name()+"__DOT__");
@@ -604,7 +607,7 @@ class LinkDotFindVisitor : public AstNVisitor {
// METHODS
int debug() { return LinkDotState::debug(); }
virtual AstConst* parseParamLiteral(FileLine* fl, string literal) {
virtual AstConst* parseParamLiteral(FileLine* fl, const string& literal) {
bool success = false;
if (literal[0] == '"') {
// This is a string
@@ -1551,7 +1554,8 @@ private:
inline void checkNoDot(AstNode* nodep) {
if (VL_UNLIKELY(m_ds.m_dotPos != DP_NONE)) {
//UINFO(9,"ds="<<m_ds.ascii()<<endl);
nodep->v3error("Syntax Error: Not expecting "<<nodep->type()<<" under a "<<nodep->backp()->type()<<" in dotted expression");
nodep->v3error("Syntax Error: Not expecting "<<nodep->type()<<" under a "
<<nodep->backp()->type()<<" in dotted expression");
m_ds.m_dotErr = true;
}
}
@@ -1804,8 +1808,7 @@ private:
|| foundp->nodep()->castModule()) { // if top
if (allowScope) {
ok = true;
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
m_ds.m_dotText += nodep->name();
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
m_ds.m_dotSymp = foundp;
m_ds.m_dotPos = DP_SCOPE;
// Upper AstDot visitor will handle it from here
@@ -1815,7 +1818,8 @@ private:
AstCell* cellp = foundp->nodep()->castCell();
if (cellp->modp()->castIface()) {
// 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);
@@ -1823,8 +1827,7 @@ private:
if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "<<findName);
//
ok = true;
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
m_ds.m_dotText += nodep->name();
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
m_ds.m_dotSymp = foundp;
m_ds.m_dotPos = DP_SCOPE;
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
@@ -1841,8 +1844,7 @@ private:
if (!ifacerefp->ifaceViaCellp()) ifacerefp->v3fatalSrc("Unlinked interface");
// Really this is a scope reference into an interface
UINFO(9,"varref-ifaceref "<<m_ds.m_dotText<<" "<<nodep<<endl);
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
m_ds.m_dotText += nodep->name();
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
m_ds.m_dotSymp = m_statep->getNodeSym(ifacerefp->ifaceViaCellp());
m_ds.m_dotPos = DP_SCOPE;
ok = true;
@@ -1893,8 +1895,7 @@ private:
if (!cellp) nodep->v3fatalSrc("Modport not referenced from a cell");
AstIface* ifacep = cellp->modp()->castIface();
//string cellName = m_ds.m_dotText; // Use cellp->name
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
m_ds.m_dotText += nodep->name();
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
m_ds.m_dotSymp = m_statep->getNodeSym(modportp);
m_ds.m_dotPos = DP_SCOPE;
ok = true;
@@ -2011,7 +2012,8 @@ private:
VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
AstVarScope* vscp = foundp ? foundp->nodep()->castVarScope() : NULL;
if (!vscp) {
nodep->v3error("Can't find varpin scope of '"<<baddot<<"' in dotted signal: "<<nodep->dotted()+"."+nodep->prettyName());
nodep->v3error("Can't find varpin scope of '"<<baddot
<<"' in dotted signal: "<<nodep->dotted()+"."+nodep->prettyName());
okSymp->cellErrorScopes(nodep);
} else {
while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal
@@ -2110,10 +2112,8 @@ private:
}
dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, okSymp); // Maybe NULL
}
VSymEnt* foundp = NULL;
AstNodeFTask* taskp = NULL;
foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
taskp = foundp ? foundp->nodep()->castNodeFTask() : NULL; // Maybe NULL
VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
AstNodeFTask* taskp = foundp ? foundp->nodep()->castNodeFTask() : NULL; // Maybe NULL
if (taskp) {
nodep->taskp(taskp);
nodep->packagep(foundp->packagep());
@@ -2128,7 +2128,8 @@ private:
} else if (nodep->dotted() == "") {
nodep->v3error("Can't find definition of task/function: "<<nodep->prettyName());
} else {
nodep->v3error("Can't find definition of '"<<baddot<<"' in dotted task/function: "<<nodep->dotted()+"."+nodep->prettyName());
nodep->v3error("Can't find definition of '"<<baddot
<<"' in dotted task/function: "<<nodep->dotted()+"."+nodep->prettyName());
okSymp->cellErrorScopes(nodep);
}
}
@@ -2316,21 +2317,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();
+8 -4
View File
@@ -35,19 +35,23 @@ private:
static void linkDotGuts(AstNetlist* nodep, VLinkDotStep step);
public:
static void linkDotPrimary(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PRIMARY);
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_PRIMARY);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
static void linkDotParamed(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PARAMED);
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_PARAMED);
V3Global::dumpCheckGlobalTree("paramlink", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
static void linkDotArrayed(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_ARRAYED);
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_ARRAYED);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
static void linkDotScope(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_SCOPED);
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_SCOPED);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
};
+3 -1
View File
@@ -262,6 +262,8 @@ public:
void V3LinkJump::linkJump(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
LinkJumpVisitor bvisitor (nodep);
{
LinkJumpVisitor bvisitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("link", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -278,7 +278,9 @@ public:
void V3LinkLValue::linkLValue(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkLValueVisitor visitor(rootp, false);
{
LinkLValueVisitor visitor(rootp, false);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
void V3LinkLValue::linkLValueSet(AstNode* nodep) {
+24 -14
View File
@@ -340,6 +340,7 @@ private:
FileLine* fl = varsp->fileline();
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
varsp->name(), nodep->findSigned32DType());
// These will be the left and right dimensions of the array:
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
@@ -347,19 +348,26 @@ private:
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
AstNode* stmtsp = varp;
stmtsp->addNext(new AstAssign(fl, new AstVarRef(fl, varp->name(), true), leftp));
AstNode* comparep =
new AstCond(fl, new AstLte(fl, leftp->cloneTree(true), rightp->cloneTree(true)),
// left increments up to right
new AstLte(fl, new AstVarRef(fl, varp->name(), false), rightp->cloneTree(true)),
// left decrements down to right
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
AstNode* incp =
new AstAssign(fl, new AstVarRef(fl, varp->name(), true),
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
new AstNegate(fl, new AstAttrOf(fl, AstAttrType::DIM_INCREMENT,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension)))));
// Assign left-dimension into the loop var:
stmtsp->addNext(new AstAssign
(fl, new AstVarRef(fl, varp->name(), true), leftp));
// This will turn into a bool constant, indicating whether
// we count the loop variable up or down:
AstNode* countupp = new AstLte(fl, leftp->cloneTree(true),
rightp->cloneTree(true));
AstNode* comparep = new AstCond(
fl, countupp->cloneTree(true),
// Left increments up to right
new AstLte(fl, new AstVarRef(fl, varp->name(), false),
rightp->cloneTree(true)),
// Left decrements down to right
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
AstNode* incp = new AstAssign(
fl, new AstVarRef(fl, varp->name(), true),
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
new AstCond(fl, countupp,
new AstConst(fl, 1),
new AstConst(fl, -1))));
stmtsp->addNext(new AstWhile(fl, comparep, newp, incp));
newp = new AstBegin(nodep->fileline(),"",stmtsp);
dimension--;
@@ -430,6 +438,8 @@ public:
void V3LinkParse::linkParse(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkParseVisitor visitor(rootp);
{
LinkParseVisitor visitor(rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("linkparse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+4 -2
View File
@@ -514,7 +514,9 @@ public:
void V3LinkResolve::linkResolve(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkResolveVisitor visitor(rootp);
LinkBotupVisitor visitorb(rootp);
{
LinkResolveVisitor visitor(rootp);
LinkBotupVisitor visitorb(rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("linkresolve", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+6 -3
View File
@@ -66,6 +66,7 @@ protected:
int m_stdFuncAsn:1; // Found simple assignment
int m_done:1; // Removed
};
// cppcheck-suppress unusedStructMember
uint32_t m_flags;
VarFlags(AstNode* nodep) { m_flags = nodep->user2(); }
void setNodeFlags(AstNode* nodep) { nodep->user2(m_flags); }
@@ -247,8 +248,10 @@ public:
void V3Localize::localizeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
LocalizeVisitor visitor (nodep);
// Fix up hiernames
LocalizeDehierVisitor dvisitor (nodep);
{
LocalizeVisitor visitor (nodep);
// Fix up hiernames
LocalizeDehierVisitor dvisitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+3 -1
View File
@@ -148,6 +148,8 @@ public:
void V3Name::nameAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
NameVisitor visitor (nodep);
{
NameVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+1 -1
View File
@@ -142,7 +142,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
if (!m_sized) {
static int warned = false;
if (!warned++) {
m_fileline->v3error("As that number was unsized ('d...) it is limited to 32 bits (IEEE 2012 5.7.1)");
m_fileline->v3error("As that number was unsized ('d...) it is limited to 32 bits (IEEE 2017 5.7.1)");
}
}
while (*(cp+1)) cp++; // Skip ahead so don't get multiple warnings
+8 -5
View File
@@ -155,11 +155,11 @@ void V3Options::addParameter(const string& paramline, bool allowPlus) {
}
}
bool V3Options::hasParameter(string name) {
bool V3Options::hasParameter(const string& name) {
return m_parameters.find(name) != m_parameters.end();
}
string V3Options::parameter(string name) {
string V3Options::parameter(const string& name) {
string value = m_parameters.find(name)->second;
m_parameters.erase(m_parameters.find(name));
return value;
@@ -604,7 +604,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( !strncmp (sw, "+incdir+", 8)) {
addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+"))));
}
else if (parseLangExt(sw, "+systemverilogext+", V3LangCode::L1800_2012)
else if (parseLangExt(sw, "+systemverilogext+", V3LangCode::L1800_2017)
|| parseLangExt(sw, "+verilog1995ext+", V3LangCode::L1364_1995)
|| parseLangExt(sw, "+verilog2001ext+", V3LangCode::L1364_2001)
|| parseLangExt(sw, "+1364-1995ext+", V3LangCode::L1364_1995)
@@ -612,7 +612,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|| parseLangExt(sw, "+1364-2005ext+", V3LangCode::L1364_2005)
|| parseLangExt(sw, "+1800-2005ext+", V3LangCode::L1800_2005)
|| parseLangExt(sw, "+1800-2009ext+", V3LangCode::L1800_2009)
|| parseLangExt(sw, "+1800-2012ext+", V3LangCode::L1800_2012)) {
|| parseLangExt(sw, "+1800-2012ext+", V3LangCode::L1800_2012)
|| parseLangExt(sw, "+1800-2017ext+", V3LangCode::L1800_2017)) {
// Nothing to do here - all done in the test
}
@@ -659,6 +660,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 +1220,7 @@ V3Options::V3Options() {
m_coverageUnderscore = false;
m_coverageUser = false;
m_debugCheck = false;
m_debugLeak = true;
m_decoration = true;
m_exe = false;
m_ignc = false;
@@ -1284,7 +1287,7 @@ V3Options::V3Options() {
VName::maxLength(128); // Linux filename limits 256; leave half for prefix
optimize(true);
optimize(1);
// Default +libext+
addLibExtV(""); // So include "filename.v" will find the same file
addLibExtV(".v");
+4 -2
View File
@@ -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; }
@@ -293,8 +295,8 @@ class V3Options {
const V3StringList& forceIncs() const { return m_forceIncs; }
const V3LangCode& defaultLanguage() const { return m_defaultLanguage; }
bool hasParameter(string name);
string parameter(string name);
bool hasParameter(const string& name);
string parameter(const string& name);
void checkParameters();
bool isFuture(const string& flag) const;
+9 -5
View File
@@ -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__<<": "<<endl);
OrderClkMarkVisitor markVisitor(nodep);
OrderVisitor visitor;
visitor.main(nodep);
{
OrderClkMarkVisitor markVisitor(nodep);
OrderVisitor visitor;
visitor.main(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("order", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -1
View File
@@ -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
+3 -1
View File
@@ -782,6 +782,8 @@ void ParamVisitor::visitCell(AstCell* nodep) {
void V3Param::param(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
ParamVisitor visitor (rootp);
{
ParamVisitor visitor (rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("param", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+3 -1
View File
@@ -427,6 +427,8 @@ public:
void V3Premit::premitAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
PremitVisitor visitor (nodep);
{
PremitVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("premit", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+10 -5
View File
@@ -33,6 +33,8 @@
#include <algorithm>
#include <iomanip>
#include <map>
#include VL_INCLUDE_UNORDERED_MAP
#include VL_INCLUDE_UNORDERED_SET
#include "V3Global.h"
#include "V3Scope.h"
@@ -50,9 +52,10 @@ private:
AstUser2InUse m_inuser2;
// TYPES
typedef map<AstPackage*, AstScope*> PackageScopeMap;
typedef map<pair<AstVar*, AstScope*>, AstVarScope*> VarScopeMap;
typedef set<pair<AstVarRef*, AstScope*> > VarRefScopeSet;
typedef vl_unordered_map<AstPackage*, AstScope*> PackageScopeMap;
// These cannot be unordered unless make a specialized hashing pair (gcc-8)
typedef std::map<std::pair<AstVar*, AstScope*>, AstVarScope*> VarScopeMap;
typedef std::set<std::pair<AstVarRef*, AstScope*> > VarRefScopeSet;
// STATE, inside processing a single module
AstNodeModule* m_modp; // Current module
@@ -416,7 +419,9 @@ public:
void V3Scope::scopeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ScopeVisitor visitor (nodep);
ScopeCleanupVisitor cleanVisitor (nodep);
{
ScopeVisitor visitor (nodep);
ScopeCleanupVisitor cleanVisitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("scope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+5 -2
View File
@@ -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;
}
}
+7 -2
View File
@@ -74,7 +74,10 @@ class SliceVisitor : public AstNVisitor {
// Insert an ArraySel, except for a few special cases
AstUnpackArrayDType* arrayp = nodep->dtypep()->skipRefp()->castUnpackArrayDType();
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
}
@@ -239,6 +242,8 @@ public:
void V3Slice::sliceAll(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
SliceVisitor visitor(rootp);
{
SliceVisitor visitor(rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("slice", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+6 -2
View File
@@ -578,11 +578,15 @@ public:
void V3Split::splitReorderAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
SplitVisitor visitor (nodep, true);
{
SplitVisitor visitor (nodep, true);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("reorder", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Split::splitAlwaysAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
SplitVisitor visitor (nodep, false);
{
SplitVisitor visitor (nodep, false);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("split", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+3 -1
View File
@@ -215,6 +215,8 @@ public:
void V3SplitAs::splitAsAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
SplitAsVisitor visitor (nodep);
{
SplitAsVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("splitas", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+7 -1
View File
@@ -69,6 +69,12 @@ bool VString::wildmatch(const char* s, const char* p) {
return (*s == '\0');
}
string VString::dot(const string& a, const string& dot, const string& b) {
if (b=="") return a;
if (a=="") return b;
return a+dot+b;
}
string VString::downcase(const string& str) {
string out = str;
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
@@ -205,7 +211,7 @@ string VHashSha1::digestBinary() {
finalize();
string out; out.reserve(20);
for (size_t i=0; i<20; ++i) {
out[i] = (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff;
out += (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff;
}
return out;
}
+5
View File
@@ -33,8 +33,13 @@ class VString {
static bool wildmatchi(const char* s, const char* p);
public:
// METHODS (generic string utilities)
// Return true if p with ? or *'s matches s
static bool wildmatch(const char* s, const char* p);
// Return {a}{dot}{b}, omitting dot if a or b are empty
static string dot(const string& a, const string& dot, const string& b);
// Convert string to lowercase
static string downcase(const string& str);
// Replace any %'s with %%
static string quotePercent(const string& str);
};
+3 -1
View File
@@ -400,6 +400,8 @@ public:
void V3Subst::substituteAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
SubstVisitor visitor (nodep);
{
SubstVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("subst", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -66,10 +66,12 @@ private:
static inline int debug() { return 0; } // NOT runtime, too hot of a function
#endif
public:
void dumpIterate(ostream& os, VSymConstMap& doneSymsr, const string& indent, int numLevels, const string& searchName) const {
void dumpIterate(ostream& os, VSymConstMap& doneSymsr, const string& indent,
int numLevels, const string& searchName) const {
os<<indent<<"+ "<<left<<setw(30)<<(searchName==""?"\"\"":searchName)<<setw(0)<<right;
os<<" se"<<(void*)(this)<<setw(0);
os<<" fallb=se"<<(void*)(m_fallbackp);
if (m_symPrefix!="") os<<" symPrefix="<<m_symPrefix;
os<<" n="<<nodep();
os<<endl;
if (doneSymsr.find(this) != doneSymsr.end()) {
+7 -2
View File
@@ -305,7 +305,10 @@ private:
// Simulate
simvis.mainTableEmulate(nodep);
if (!simvis.optimizable()) simvis.whyNotNodep()->v3fatalSrc("Optimizable cleared, even though earlier test run said not: "<<simvis.whyNotMessage());
if (!simvis.optimizable()) {
simvis.whyNotNodep()->v3fatalSrc("Optimizable cleared, even though earlier test run said not: "
<<simvis.whyNotMessage());
}
// If a output changed, add it to table
int outnum = 0;
@@ -465,6 +468,8 @@ void TableSimulateVisitor::varRefCb(AstVarRef* nodep) {
void V3Table::tableAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
TableVisitor visitor (nodep);
{
TableVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("table", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+8 -5
View File
@@ -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: "<<portp->prettyName());
portp->v3error("DPI functions cannot return > 32 bits or four-state;"
" use a two-state type or task instead: "<<portp->prettyName());
// Code below works, but won't compile right, and IEEE illegal
}
string stmt;
@@ -795,7 +796,7 @@ private:
makePortList(nodep, rtnvarp, dpip);
}
bool duplicatedDpiProto(AstNodeFTask* nodep, string dpiproto) {
bool duplicatedDpiProto(AstNodeFTask* nodep, const string& dpiproto) {
// Only create one DPI extern prototype for each specified cname
// as it's legal for the user to attach multiple tasks to one dpi cname
DpiNames::iterator iter = m_dpiNames.find(nodep->cname());
@@ -927,7 +928,7 @@ private:
&& portp->dtypep()->basicp()
&& portp->dtypep()->basicp()->keyword().isDpiUnreturnable()) {
portp->v3error("DPI function may not return type "<<portp->basicp()->prettyTypeName()
<<" (IEEE 2012 35.5.5)");
<<" (IEEE 2017 35.5.5)");
}
portp->unlinkFrBack();
rtnvarp = portp;
@@ -1395,7 +1396,9 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
void V3Task::taskAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
TaskStateVisitor visitors (nodep);
TaskVisitor visitor (nodep, &visitors);
{
TaskStateVisitor visitors (nodep);
TaskVisitor visitor (nodep, &visitors);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("task", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -1
View File
@@ -36,7 +36,8 @@ typedef vector<V3TaskConnect> 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
+7 -2
View File
@@ -205,7 +205,10 @@ private:
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(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 "<<hex<<hashed.nodeHash(nodep->valuep())<<" "<<nodep<<endl);
@@ -712,6 +715,8 @@ public:
void V3Trace::traceAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
TraceVisitor visitor (nodep);
{
TraceVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("trace", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -325,6 +325,8 @@ public:
void V3TraceDecl::traceDeclAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
TraceDeclVisitor visitor (nodep);
{
TraceDeclVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("tracedecl", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+40 -32
View File
@@ -221,7 +221,8 @@ public:
TristateVertex* vvertexp = static_cast<TristateVertex*>(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): "<<vvertexp->nodep()->prettyTypeName());
vvertexp->nodep()->v3error("Unsupported tristate construct"
" (in graph; not converted): "<<vvertexp->nodep()->prettyTypeName());
}
}
m_graph.clear();
@@ -984,32 +985,37 @@ class TristateVisitor : public TristateBaseVisitor {
virtual void visit(AstPull* nodep) {
UINFO(9,dbgState()<<nodep<<endl);
if (m_graphing) {
if (AstVarRef* lhsp = nodep->lhsp()->castVarRef()) {
lhsp->lvalue(true);
m_logicp = nodep;
m_tgraph.setTristate(nodep);
associateLogic(nodep, lhsp->varp());
m_logicp = NULL;
} else {
nodep->v3error("Unsupported pullup/down (weak driver) construct.");
}
} else {
// Replace any pullup/pulldowns with assignw logic and set the
// direction of the pull in the user3() data on the var. Given
// the complexity of merging tristate drivers at any level, the
// current limitation of this implementation is that a pullup/down
// gets applied to all bits of a bus and a bus cannot have drivers
// in opposite directions on indvidual pins.
if (AstVarRef* lhsp = nodep->lhsp()->castVarRef()) {
lhsp->lvalue(true);
m_tgraph.didProcess(nodep);
m_tgraph.didProcess(lhsp->varp());
AstVar* varp = lhsp->varp();
setPullDirection(varp, nodep);
} else {
nodep->v3error("Unsupported pullup/down (weak driver) construct.");
}
AstVarRef* varrefp = NULL;
if (nodep->lhsp()->castVarRef()) {
varrefp = nodep->lhsp()->castVarRef();
} else if (nodep->lhsp()->castSel()
&& nodep->lhsp()->castSel()->fromp()->castVarRef()) {
varrefp = nodep->lhsp()->castSel()->fromp()->castVarRef();
}
if (!varrefp) {
if (debug()>=4) nodep->dumpTree(cout, "- ");
nodep->v3error("Unsupported pullup/down (weak driver) construct.");
} else {
if (m_graphing) {
varrefp->lvalue(true);
m_logicp = nodep;
m_tgraph.setTristate(nodep);
associateLogic(nodep, varrefp->varp());
m_logicp = NULL;
} else {
// Replace any pullup/pulldowns with assignw logic and set the
// direction of the pull in the user3() data on the var. Given
// the complexity of merging tristate drivers at any level, the
// current limitation of this implementation is that a pullup/down
// gets applied to all bits of a bus and a bus cannot have drivers
// in opposite directions on indvidual pins.
varrefp->lvalue(true);
m_tgraph.didProcess(nodep);
m_tgraph.didProcess(varrefp->varp());
setPullDirection(varrefp->varp(), nodep);
}
}
if (!m_graphing) {
nodep->unlinkFrBack();
pushDeletep(nodep); VL_DANGLING(nodep); // Node must persist as user3p points to it
}
@@ -1060,7 +1066,7 @@ class TristateVisitor : public TristateBaseVisitor {
if (!enModVarp) {
if (nodep->exprp()) {
// May have an output only that later connects to a tristate, so simplify now.
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
}
iteratePinGuts(nodep);
return; // No __en signals on this pin
@@ -1086,7 +1092,7 @@ class TristateVisitor : public TristateBaseVisitor {
} else if (inDeclProcessing) { // Not an input that was a converted tristate
// Input only may have driver in underneath module which would stomp
// the input value. So make a temporary connection.
AstAssignW* reAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, true, true);
AstAssignW* reAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, true, true);
UINFO(5,"Input pin buffering: "<<reAssignp<<endl);
m_tgraph.setTristate(reAssignp->lhsp());
}
@@ -1140,7 +1146,7 @@ class TristateVisitor : public TristateBaseVisitor {
TristatePinVisitor visitor (outexprp, m_tgraph, true);
}
if (debug()>=9) outpinp->dumpTree(cout,"-pin-opr: ");
outAssignp = V3Inst::pinReconnectSimple(outpinp, m_cellp, m_modp, true); // Note may change outpinp->exprp()
outAssignp = V3Inst::pinReconnectSimple(outpinp, m_cellp, true); // Note may change outpinp->exprp()
if (debug()>=9) outpinp->dumpTree(cout,"-pin-out: ");
if (debug()>=9 && outAssignp) outAssignp->dumpTree(cout,"-pin-out: ");
// Must still iterate the outAssignp, as need to build output equation
@@ -1148,7 +1154,7 @@ class TristateVisitor : public TristateBaseVisitor {
// Existing pin becomes an input, and we mark each resulting signal as tristate
TristatePinVisitor visitor (nodep->exprp(), m_tgraph, false);
AstNode* inAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, true); // Note may change nodep->exprp()
AstNode* inAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, true); // Note may change nodep->exprp()
if (debug()>=9) nodep->dumpTree(cout,"-pin-in: ");
if (debug()>=9 && inAssignp) inAssignp->dumpTree(cout,"-pin-as: ");
@@ -1336,6 +1342,8 @@ public:
void V3Tristate::tristateAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
TristateVisitor visitor (nodep);
{
TristateVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("tristate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -479,6 +479,8 @@ public:
void V3Unknown::unknownAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
UnknownVisitor visitor (nodep);
{
UnknownVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("unknown", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+13 -8
View File
@@ -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 "<<unrollCount());
nodep->v3error("Loop unrolling took too long;"
" probably this is an infinite loop, or set --unroll-count above "
<<unrollCount());
break;
}
@@ -455,7 +458,7 @@ private:
public:
// CONSTUCTORS
UnrollVisitor(AstNode* nodep, bool generate, string beginName) {
UnrollVisitor(AstNode* nodep, bool generate, const string& beginName) {
m_forVarp = NULL;
m_forVscp = NULL;
m_ignoreIncp = NULL;
@@ -477,11 +480,13 @@ public:
void V3Unroll::unrollAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
UnrollVisitor visitor (nodep, false, "");
{
UnrollVisitor visitor (nodep, false, "");
} // Destruct before checking
V3Global::dumpCheckGlobalTree("unroll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Unroll::unrollGen(AstNodeFor* nodep, string beginName) {
void V3Unroll::unrollGen(AstNodeFor* nodep, const string& beginName) {
UINFO(2,__FUNCTION__<<": "<<endl);
UnrollVisitor visitor (nodep, true, beginName);
}
+1 -1
View File
@@ -30,7 +30,7 @@
class V3Unroll {
public:
static void unrollAll(AstNetlist* nodep);
static void unrollGen(AstNodeFor* nodep, string beginName);
static void unrollGen(AstNodeFor* nodep, const string& beginName);
};
#endif // Guard
+51 -31
View File
@@ -299,14 +299,10 @@ private:
virtual void visit(AstDivD* nodep) { visit_real_add_sub(nodep); }
virtual void visit(AstMulD* nodep) { visit_real_add_sub(nodep); }
virtual void visit(AstPowD* nodep) { visit_real_add_sub(nodep); }
virtual void visit(AstNodeSystemBiop* nodep) { visit_real_add_sub(nodep); }
// Real: Output real
virtual void visit(AstNegateD* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstCeilD* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstExpD* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstFloorD* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstLogD* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstLog10D* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstSqrtD* nodep) { visit_real_neg_ceil(nodep); }
virtual void visit(AstNodeSystemUniop* nodep) { visit_real_neg_ceil(nodep); }
// Widths: out signed/unsigned width = lhs width, input un|signed
virtual void visit(AstSigned* nodep) { visit_signed_unsigned(nodep, AstNumeric::SIGNED); }
@@ -450,7 +446,7 @@ private:
if (!constp) { nodep->v3error("Replication value isn't a constant."); return; }
uint32_t times = constp->toUInt();
if (times==0 && !nodep->backp()->castConcat()) { // Concat Visitor will clean it up.
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2012 11.4.12.1)"); times=1;
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2017 11.4.12.1)"); times=1;
}
if (nodep->lhsp()->isString()) {
AstNode* newp = new AstReplicateN(nodep->fileline(),nodep->lhsp()->unlinkFrBack(),
@@ -481,7 +477,7 @@ private:
if (!constp) { nodep->v3error("Replication value isn't a constant."); return; }
uint32_t times = constp->toUInt();
if (times==0 && !nodep->backp()->castConcat()) { // Concat Visitor will clean it up.
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2012 11.4.12.1)");
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2017 11.4.12.1)");
}
nodep->dtypeSetString();
}
@@ -556,6 +552,7 @@ private:
// LSB is self-determined (IEEE 2012 11.5.1)
// We also use SELs to shorten a signed constant etc, in this case they are signed.
if (nodep->didWidth()) return;
if (!m_vup) nodep->v3fatalSrc("Select under an unexpected context");
if (m_vup->prelim()) {
if (debug()>=9) nodep->dumpTree(cout,"-selWidth: ");
userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT,PRELIM).p());
@@ -949,6 +946,10 @@ private:
}
m_attrp = oldAttr;
}
virtual void visit(AstPull* nodep) {
// May have select underneath, let seek natural size
userIterateChildren(nodep, WidthVP(SELF,BOTH).p());
}
virtual void visit(AstText* nodep) {
// Only used in CStmts which don't care....
}
@@ -1197,7 +1198,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
@@ -1242,7 +1245,8 @@ private:
if (nodep->didWidth()) return;
if (!nodep->varp()) {
if (m_paramsOnly && nodep->castVarXRef()) {
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");
@@ -1294,7 +1298,7 @@ private:
}
if (!itemp->valuep()) {
if (num.isEqZero() && itemp != nodep->itemsp())
itemp->v3error("Enum value illegally wrapped around (IEEE 2012 6.19)");
itemp->v3error("Enum value illegally wrapped around (IEEE 2017 6.19)");
if (!nodep->dtypep()->basicp()
&& !nodep->dtypep()->basicp()->keyword().isIntNumeric()) {
itemp->v3error("Enum names without values only allowed on numeric types");
@@ -1491,13 +1495,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 -> "<<newp<<endl);
UINFO(9," dt-> "<<newp->dtypep()<<endl);
nodep->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
@@ -1659,7 +1665,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: "<<nodep->backp()->prettyTypeName());
if (!vdtypep) nodep->v3error("Unsupported/Illegal: Assignment pattern"
" member not underneath a supported construct: "
<<nodep->backp()->prettyTypeName());
{
vdtypep = vdtypep->skipRefp();
nodep->dtypep(vdtypep);
@@ -1719,7 +1727,8 @@ private:
continue;
}
} else {
patp->keyp()->v3error("Assignment pattern key not supported/understood: "<<patp->keyp()->prettyTypeName());
patp->keyp()->v3error("Assignment pattern key not"
" supported/understood: "<<patp->keyp()->prettyTypeName());
}
}
}
@@ -2187,16 +2196,21 @@ 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());
}
virtual void visit(AstReadMem* nodep) {
virtual void visit(AstNodeReadWriteMem* nodep) {
assertAtStatement(nodep);
userIterateAndNext(nodep->filenamep(), WidthVP(SELF,BOTH).p());
userIterateAndNext(nodep->memp(), WidthVP(SELF,BOTH).p());
if (!nodep->memp()->dtypep()->skipRefp()->castUnpackArrayDType()) {
nodep->memp()->v3error("Unsupported: $readmem into other than unpacked array");
nodep->memp()->v3error("Unsupported: " << nodep->verilogKwd()
<< " into other than unpacked array");
}
userIterateAndNext(nodep->lsbp(), WidthVP(SELF,BOTH).p());
userIterateAndNext(nodep->msbp(), WidthVP(SELF,BOTH).p());
@@ -2213,7 +2227,7 @@ private:
assertAtStatement(nodep);
userIterateChildren(nodep, WidthVP(SELF,BOTH).p());
}
virtual void visit(AstPslCover* nodep) {
virtual void visit(AstNodePslCoverOrAssert* nodep) {
assertAtStatement(nodep);
iterateCheckBool(nodep,"Property",nodep->propp(),BOTH); // it's like an if() condition.
userIterateAndNext(nodep->stmtsp(), NULL);
@@ -2949,9 +2963,12 @@ private:
bool widthBad (AstNode* nodep, AstNodeDType* expDTypep) {
int expWidth = expDTypep->width();
int expWidthMin = expDTypep->widthMin();
if (!nodep->dtypep()) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no dtype?? Missing Visitor func?");
if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
if (!nodep->dtypep()) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()
<<" has no dtype?? Missing Visitor func?");
if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()
<<" has no expected width?? Missing Visitor func?");
if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->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;
@@ -3155,8 +3172,7 @@ private:
} else {
bool bad = widthBad(underp,nodep->findLogicBoolDType());
if (bad) {
bool warnOn = true; // Not used
if (warnOn) {
{ // if (warnOn), but not needed here
if (debug()>4) nodep->backp()->dumpTree(cout," back: ");
nodep->v3warn(WIDTH,"Logical Operator "<<nodep->prettyTypeName()
<<" expects 1 bit on the "<<side<<", but "<<side<<"'s "
@@ -3653,7 +3669,7 @@ private:
// Find valid values and populate
if (!nodep->itemsp()) nodep->v3fatalSrc("enum without items");
vector<AstNode*> values;
values.reserve(msbdim+1);
values.resize(msbdim+1);
for (unsigned i=0; i<(msbdim+1); ++i) {
values[i] = NULL;
}
@@ -3858,12 +3874,14 @@ int V3Width::debug() {
void V3Width::width(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
// We should do it in bottom-up module order, but it works in any order.
WidthClearVisitor cvisitor (nodep);
WidthVisitor visitor (false, false);
(void)visitor.mainAcceptEdit(nodep);
WidthRemoveVisitor rvisitor;
(void)rvisitor.mainAcceptEdit(nodep);
{
// We should do it in bottom-up module order, but it works in any order.
WidthClearVisitor cvisitor (nodep);
WidthVisitor visitor (false, false);
(void)visitor.mainAcceptEdit(nodep);
WidthRemoveVisitor rvisitor;
(void)rvisitor.mainAcceptEdit(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("width", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
@@ -3899,6 +3917,8 @@ AstNode* V3Width::widthGenerateParamsEdit(
void V3Width::widthCommit(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
WidthCommitVisitor visitor (nodep);
{
WidthCommitVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("widthcommit", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+4
View File
@@ -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)<argc ) {
shift;
m_annotateMin = atoi(argv[i]);
}
else if ( !strcmp (sw, "-annotate") && (i+1)<argc ) {
shift;
m_annotateOut = argv[i];
+2
View File
@@ -18,6 +18,8 @@
my $Opt_Prefix = $ARGV[0] or die "%Error: No prefix specified,";
foreach my $line (<STDIN>) {
# Fix flex 2.6.1 warning
$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 /;
+52 -32
View File
@@ -32,7 +32,7 @@
extern void yyerror(const char*);
extern void yyerrorf(const char* format, ...);
#define STATE_VERILOG_RECENT S12 // State name for most recent Verilog Version
#define STATE_VERILOG_RECENT S17 // State name for most recent Verilog Version
#define PARSEP V3ParseImp::parsep()
#define SYMP PARSEP->symp()
@@ -126,7 +126,7 @@ void yyerror(const char* errmsg) {
static int warned = false;
if (!warned++) {
PARSEP->fileline()->v3error("Perhaps '"+*PARSEP->prevBisonVal().strp
+"' is a package which needs to be predeclared? (IEEE 2012 26.3)");
+"' is a package which needs to be predeclared? (IEEE 2017 26.3)");
}
}
}
@@ -154,7 +154,7 @@ void yyerrorf(const char* format, ...) {
%a 15000
%o 25000
%s V95 V01 V05 S05 S09 S12
%s V95 V01 V05 S05 S09 S12 S17
%s STRING ATTRMODE TABLE
%s VA5 SAX VLT
%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
@@ -200,14 +200,23 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/************************************************************************/
/* Verilog 1995 */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
{ws} { } /* otherwise ignore white-space */
{crnl} { NEXTLINE(); } /* Count line numbers */
/* Extensions to Verilog set, some specified by PSL */
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
/* System Tasks */
"$acos" { FL; return yD_ACOS; }
"$acosh" { FL; return yD_ACOSH; }
"$asin" { FL; return yD_ASIN; }
"$asinh" { FL; return yD_ASINH; }
"$atan" { FL; return yD_ATAN; }
"$atan2" { FL; return yD_ATAN2; }
"$atanh" { FL; return yD_ATANH; }
"$bitstoreal" { FL; return yD_BITSTOREAL; }
"$ceil" { FL; return yD_CEIL; }
"$cos" { FL; return yD_COS; }
"$cosh" { FL; return yD_COSH; }
"$display" { FL; return yD_DISPLAY; }
"$exp" { FL; return yD_EXP; }
"$fclose" { FL; return yD_FCLOSE; }
@@ -223,6 +232,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; }
"$hypot" { FL; return yD_HYPOT; }
"$itor" { FL; return yD_ITOR; }
"$ln" { FL; return yD_LN; }
"$log10" { FL; return yD_LOG10; }
@@ -242,6 +252,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$setuphold" { FL; return yaTIMINGSPEC; }
"$sformat" { FL; return yD_SFORMAT; }
"$sformatf" { FL; return yD_SFORMATF; }
"$sin" { FL; return yD_SIN; }
"$sinh" { FL; return yD_SINH; }
"$skew" { FL; return yaTIMINGSPEC; }
"$sqrt" { FL; return yD_SQRT; }
"$sscanf" { FL; return yD_SSCANF; }
@@ -249,12 +261,15 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$stop" { FL; return yD_STOP; }
"$swrite" { FL; return yD_SWRITE; }
"$system" { FL; return yD_SYSTEM; }
"$tan" { FL; return yD_TAN; }
"$tanh" { FL; return yD_TANH; }
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
"$time" { FL; return yD_TIME; }
"$timeskew" { FL; return yaTIMINGSPEC; }
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
"$width" { FL; return yaTIMINGSPEC; }
"$write" { FL; return yD_WRITE; }
"$writememh" { FL; return yD_WRITEMEMH; }
/* Keywords */
"always" { FL; return yALWAYS; }
"and" { FL; return yAND; }
@@ -375,7 +390,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* Verilog 2001 */
<V01,V05,VA5,S05,S09,S12,SAX>{
<V01,V05,VA5,S05,S09,S12,S17,SAX>{
/* System Tasks */
"$signed" { FL; return yD_SIGNED; }
"$unsigned" { FL; return yD_UNSIGNED; }
@@ -406,13 +421,13 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* Verilog 2005 */
<V05,S05,S09,S12,SAX>{
<V05,S05,S09,S12,S17,SAX>{
/* Keywords */
"uwire" { FL; return yWIRE; }
}
/* System Verilog 2005 */
<S05,S09,S12,SAX>{
<S05,S09,S12,S17,SAX>{
/* System Tasks */
"$bits" { FL; return yD_BITS; }
"$clog2" { FL; return yD_CLOG2; }
@@ -537,7 +552,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* SystemVerilog 2009 */
<S09,S12,SAX>{
<S09,S12,S17,SAX>{
/* Keywords */
"global" { FL; return yGLOBAL__LEX; }
"unique0" { FL; return yUNIQUE0; }
@@ -566,7 +581,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* System Verilog 2012 */
<S12,SAX>{
<S12,S17,SAX>{
/* Keywords */
"implements" { yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
"interconnect" { yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
@@ -574,8 +589,11 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"soft" { yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
}
/* System Verilog 2017 */
/* No new keywords */
/* Default PLI rule */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext,yyleng);
yylval.strp = PARSEP->newString(AstNode::encodeName(str));
// Lookup unencoded name including the $, to avoid hitting normal signals
@@ -601,20 +619,20 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"aliasparam" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"analog" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"analysis" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"asin" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"asinh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"asin" { FL; return yD_ASIN; }
"asinh" { FL; return yD_ASINH; }
"assert" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atan" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atan2" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atanh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atan" { FL; return yD_ATAN; }
"atan2" { FL; return yD_ATAN2; }
"atanh" { FL; return yD_ATANH; }
"branch" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ceil" { FL; return yD_CEIL; }
"connect" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"connectmodule" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"connectrules" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"continuous" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"cos" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"cosh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"cos" { FL; return yD_COS; }
"cosh" { FL; return yD_COSH; }
"cross" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ddt" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ddt_nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
@@ -635,7 +653,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"flow" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"from" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ground" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"hypot" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"hypot" { FL; return yD_HYPOT; }
"idt" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"idt_nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"idtmod" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
@@ -659,14 +677,14 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"potential" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"pow" { FL; return yD_POW; }
"resolveto" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sin" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sinh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sin" { FL; return yD_SIN; }
"sinh" { FL; return yD_SINH; }
"slew" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"split" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sqrt" { FL; return yD_SQRT; }
"string" { FL; return ySTRING; }
"tan" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"tanh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"tan" { FL; return yD_TAN; }
"tanh" { FL; return yD_TANH; }
"timer" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"transition" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"units" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
@@ -682,7 +700,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/* Meta comments */
/* Converted from //{cmt}verilator ...{cmt} by preprocessor */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
"/*verilator"{ws}*"*/" {} /* Ignore empty comments, may be `endif // verilator */
"/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; }
"/*verilator coverage_block_off*/" { FL; return yVL_COVERAGE_BLOCK_OFF; }
@@ -720,7 +738,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/************************************************************************/
/* Single character operator thingies */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
"{" { FL; return yytext[0]; }
"}" { FL; return yytext[0]; }
"!" { FL; return yytext[0]; }
@@ -754,7 +772,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/* Operators and multi-character symbols */
/* Verilog 1995 Operators */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
"&&" { FL; return yP_ANDAND; }
"||" { FL; return yP_OROR; }
"<=" { FL; return yP_LTE; }
@@ -776,7 +794,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* Verilog 2001 Operators */
<V01,V05,VA5,S05,S09,S12,SAX>{
<V01,V05,VA5,S05,S09,S12,S17,SAX>{
"<<<" { FL; return yP_SLEFT; }
">>>" { FL; return yP_SSRIGHT; }
"**" { FL; return yP_POW; }
@@ -789,7 +807,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* SystemVerilog Operators */
<S05,S09,S12,SAX>{
<S05,S09,S12,S17,SAX>{
"'" { FL; return yP_TICK; }
"'{" { FL; return yP_TICKBRA; }
"==?" { FL; return yP_WILDEQUAL; }
@@ -823,7 +841,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
}
/* Identifiers and numbers */
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT>{
{escid} { FL; yylval.strp = PARSEP->newString
(AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash
return yaID__LEX;
@@ -896,7 +914,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/************************************************************************/
/* Attributes */
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } /* Doesn't match (*), but (* attr_spec */
}
@@ -913,7 +931,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/* Preprocessor */
/* Common for all SYSC header states */
/* OPTIMIZE: we return one per line, make it one for the entire block */
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
"`accelerate" { } // Verilog-XL compatibility
"`autoexpand_vectornets" { } // Verilog-XL compatibility
"`celldefine" { PARSEP->inCellDefine(true); }
@@ -957,6 +975,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800-2009\" { yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800-2012\" { yy_push_state(S12); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800-2017\" { yy_push_state(S17); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800[+]VAMS\" { yy_push_state(SAX); PARSEP->pushBeginKeywords(YY_START); } /*Latest SV*/
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
@@ -988,7 +1007,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/************************************************************************/
/* Default rules - leave last */
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT>{
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT>{
"`"[a-zA-Z_0-9]+ { FL; yyerrorf("Define or directive not defined: %s",yytext); }
"//"[^\n]* { } /* throw away single line comments */
. { FL; return yytext[0]; } /* return single char ops. */
@@ -1051,7 +1070,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
}
+64 -10
View File
@@ -442,11 +442,20 @@ class AstSenTree;
%token<fl> yXNOR "xnor"
%token<fl> yXOR "xor"
%token<fl> yD_ACOS "$acos"
%token<fl> yD_ACOSH "$acosh"
%token<fl> yD_ASIN "$asin"
%token<fl> yD_ASINH "$asinh"
%token<fl> yD_ATAN "$atan"
%token<fl> yD_ATAN2 "$atan2"
%token<fl> yD_ATANH "$atanh"
%token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_C "$c"
%token<fl> yD_CEIL "$ceil"
%token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COS "$cos"
%token<fl> yD_COSH "$cosh"
%token<fl> yD_COUNTONES "$countones"
%token<fl> yD_DIMENSIONS "$dimensions"
%token<fl> yD_DISPLAY "$display"
@@ -465,6 +474,7 @@ class AstSenTree;
%token<fl> yD_FSCANF "$fscanf"
%token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_HIGH "$high"
%token<fl> yD_HYPOT "$hypot"
%token<fl> yD_INCREMENT "$increment"
%token<fl> yD_INFO "$info"
%token<fl> yD_ISUNKNOWN "$isunknown"
@@ -486,6 +496,8 @@ class AstSenTree;
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SFORMATF "$sformatf"
%token<fl> yD_SIGNED "$signed"
%token<fl> yD_SIN "$sin"
%token<fl> yD_SINH "$sinh"
%token<fl> yD_SIZE "$size"
%token<fl> yD_SQRT "$sqrt"
%token<fl> yD_SSCANF "$sscanf"
@@ -493,6 +505,8 @@ class AstSenTree;
%token<fl> yD_STOP "$stop"
%token<fl> yD_SWRITE "$swrite"
%token<fl> yD_SYSTEM "$system"
%token<fl> yD_TAN "$tan"
%token<fl> yD_TANH "$tanh"
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_UNIT "$unit"
@@ -501,6 +515,7 @@ class AstSenTree;
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
%token<fl> yD_WARNING "$warning"
%token<fl> yD_WRITE "$write"
%token<fl> yD_WRITEMEMH "$writememh"
%token<fl> yVL_CLOCK "/*verilator sc_clock*/"
%token<fl> yVL_CLOCKER "/*verilator clocker*/"
@@ -728,7 +743,6 @@ package_or_generate_item_declaration<nodep>: // ==IEEE: package_or_generate_item
| local_parameter_declaration ';' { $$ = $1; }
| parameter_declaration ';' { $$ = $1; }
//UNSUP covergroup_declaration { $$ = $1; }
//UNSUP overload_declaration { $$ = $1; }
//UNSUP assertion_item_declaration { $$ = $1; }
| ';' { $$ = NULL; }
;
@@ -2260,7 +2274,6 @@ block_item_declaration<nodep>: // ==IEEE: block_item_declaration
data_declaration { $$ = $1; }
| local_parameter_declaration ';' { $$ = $1; }
| parameter_declaration ';' { $$ = $1; }
//UNSUP overload_declaration { $$ = $1; }
//UNSUP let_declaration { $$ = $1; }
;
@@ -2359,8 +2372,7 @@ statement_item<nodep>: // IEEE: statement_item
| yREPEAT '(' expr ')' stmtBlock { $$ = new AstRepeat($1,$3,$5);}
| yWHILE '(' expr ')' stmtBlock { $$ = new AstWhile($1,$3,$5);}
// // for's first ';' is in for_initalization
| yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
{ $$ = new AstBegin($1,"",$3); $3->addNext(new AstWhile($1, $4,$8,$6)); }
| statementFor { $$ = $1; }
| yDO stmtBlock yWHILE '(' expr ')' ';' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
// // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009
| yFOREACH '(' idClassForeach '[' loop_variables ']' ')' stmtBlock { $$ = new AstForeach($1,$3,$5,$8); }
@@ -2408,6 +2420,15 @@ statement_item<nodep>: // IEEE: statement_item
| error ';' { $$ = NULL; }
;
statementFor<beginp>: // IEEE: part of statement
yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
{ $$ = new AstBegin($1,"",$3);
$$->addStmtsp(new AstWhile($1, $4,$8,$6)); }
| yFOR '(' for_initialization ';' for_stepE ')' stmtBlock
{ $$ = new AstBegin($1,"",$3);
$$->addStmtsp(new AstWhile($1, new AstConst($1,AstConst::LogicTrue()),$7,$5)); }
;
statementVerilatorPragmas<nodep>:
yVL_COVERAGE_BLOCK_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
;
@@ -2582,6 +2603,7 @@ for_initialization<nodep>: // ==IEEE: for_initialization + for_variable_declarat
$$ = VARDONEA($<fl>2,*$2,NULL,NULL);
$$->addNext(new AstAssign($3,new AstVarRef($3,*$2,true),$4));}
| varRefBase '=' expr ';' { $$ = new AstAssign($2,$1,$3); }
| ';' { $$ = NULL; }
//UNSUP: List of initializations
;
@@ -2649,6 +2671,8 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList($$->castTaskRef()); }
//
| 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); }
@@ -2659,7 +2683,6 @@ system_t_call<nodep>: // 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); }
@@ -2684,6 +2707,13 @@ system_t_call<nodep>: // 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); }
//
| yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1,$3,$5,NULL,NULL); }
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1,$3,$5,$7,NULL); }
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1,$3,$5,$7,$9); }
//
// Any system function as a task
| system_f_call_or_t { $$ = new AstSysFuncAsTask($<fl>1, $1); }
;
system_f_call<nodep>: // IEEE: system_tf_call (as func)
@@ -2693,12 +2723,27 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList($$->castFuncRef()); }
//
| 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<nodep>: // 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); }
| yD_ATAN '(' expr ')' { $$ = new AstAtanD($1,$3); }
| yD_ATAN2 '(' expr ',' expr ')' { $$ = new AstAtan2D($1,$3,$5); }
| yD_ATANH '(' expr ')' { $$ = new AstAtanhD($1,$3); }
| 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); }
| yD_COSH '(' expr ')' { $$ = new AstCoshD($1,$3); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
| yD_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_DIMENSIONS,$3); }
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
@@ -2709,6 +2754,7 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
| yD_HIGH '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); }
| yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD($1,$3,$5); }
| yD_INCREMENT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,NULL); }
| yD_INCREMENT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,$5); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
@@ -2731,12 +2777,15 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); }
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_SIN '(' expr ')' { $$ = new AstSinD($1,$3); }
| yD_SINH '(' expr ')' { $$ = new AstSinhD($1,$3); }
| yD_SIZE '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,NULL); }
| yD_SIZE '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,$5); }
| 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); }
| yD_TIME parenE { $$ = new AstTime($1); }
| yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
@@ -3078,7 +3127,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
//
// // IEEE: "... hierarchical_identifier select" see below
//
// // IEEE: empty_queue
// // IEEE: empty_queue (IEEE 1800-2017 empty_unpacked_array_concatenation)
//UNSUP '{' '}'
//
// // IEEE: concatenation/constant_concatenation
@@ -3679,9 +3728,14 @@ concurrent_assertion_item<nodep>: // IEEE: concurrent_assertion_item
;
concurrent_assertion_statement<nodep>: // ==IEEE: concurrent_assertion_statement
//UNSUP: assert/assume
yASSERT yPROPERTY '(' property_spec ')' elseStmtBlock { $$ = new AstPslAssert($1,$4,$6); }
// // IEEE: cover_property_statement
yCOVER yPROPERTY '(' property_spec ')' stmtBlock { $$ = new AstPslCover($1,$4,$6); }
| yCOVER yPROPERTY '(' property_spec ')' stmtBlock { $$ = new AstPslCover($1,$4,$6); }
;
elseStmtBlock<nodep>: // Part of concurrent_assertion_statement
';' { $$ = NULL; }
| yELSE stmtBlock { $$ = $2; }
;
property_spec<nodep>: // IEEE: property_spec
+6 -1
View File
@@ -978,7 +978,12 @@ sub _run {
flush STDERR;
if (!$param{fails} && $status) {
$self->error("Exec of $param{cmd}[0] failed\n");
my $firstline = "";
if (my $fh = IO::File->new("<$param{logfile}")) {
$firstline = $fh->getline;
chomp $firstline;
}
$self->error("Exec of $param{cmd}[0] failed: $firstline\n");
}
if ($param{fails} && $status) {
print "(Exec expected to fail, and did.)\n";

Some files were not shown because too many files have changed in this diff Show More