Merge from master
This commit is contained in:
commit
2c30aecc5b
10
Changes
10
Changes
|
|
@ -17,10 +17,20 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
|||
|
||||
*** Support trig functions ($sin() etc), bug1281. [Patrick Stewart]
|
||||
|
||||
*** Support calling system functions as tasks, bug1285. [Joel Holdsworth]
|
||||
|
||||
*** Add --no-debug-leak to reduce memory use under debug. [John Coiner]
|
||||
|
||||
**** On convergence errors, show activity. [John Coiner]
|
||||
|
||||
**** Fix GCC 8.0 issues, bug1273.
|
||||
|
||||
**** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard]
|
||||
|
||||
**** Fix verilator_coverage --annotate-min, bug1284. [Tymoteusz Blazejczyk]
|
||||
|
||||
**** Fix quoting of quoted arguments. [John Coiner]
|
||||
|
||||
|
||||
* Verilator 3.920 2018-02-01
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -270,6 +278,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
|
||||
|
|
@ -627,6 +636,18 @@ to C<--dump-treei 3>).
|
|||
Rarely needed. Enable internal debugging assertion checks, without
|
||||
changing debug verbosity. Enabled automatically when --debug specified.
|
||||
|
||||
=item --no-debug-leak
|
||||
|
||||
In --debug mode, by default Verilator intentionally leaks AstNode's
|
||||
instead of freeing them, so that each node pointer is unique in the
|
||||
resulting tree files and dot files.
|
||||
|
||||
This option disables the leak. This may avoid out-of-memory errors
|
||||
when Verilating large models in --debug mode.
|
||||
|
||||
Outside of --debug mode, AstNode's should never be leaked and this option
|
||||
has no effect.
|
||||
|
||||
=item --debugi <level>
|
||||
|
||||
=item --debugi-<srcfile> <level>
|
||||
|
|
@ -1251,8 +1272,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
|
||||
|
||||
|
|
@ -3047,13 +3069,15 @@ Simply use a different register for the flop:
|
|||
always @* foo[0] = foo_flopped[0];
|
||||
always @* foo[1] = ...
|
||||
|
||||
It is also possible to disable this error when one of the assignments is
|
||||
inside a public task.
|
||||
|
||||
This is not illegal in SystemVerilog, but a violation of good coding
|
||||
practice. Verilator reports this as an error, because ignoring this warning
|
||||
may make Verilator simulations differ from other simulators.
|
||||
|
||||
It is generally safe to disable this error (with a "// verilator lint_off
|
||||
BLKANDNBLK" metacomment or the -Wno-BLKANDNBLK option) when one of the
|
||||
assignments is inside a public task, or when the blocked and non-blocking
|
||||
assignments have non-overlapping bits and structure members.
|
||||
|
||||
=item BLKSEQ
|
||||
|
||||
This indicates that a blocking assignment (=) is used in a sequential
|
||||
|
|
|
|||
|
|
@ -430,7 +430,8 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE {
|
|||
return out;
|
||||
}
|
||||
|
||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
|
||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
|
||||
bool lsign, bool rsign) VL_MT_SAFE {
|
||||
// obits==lbits, rbits can be different
|
||||
if (rsign && VL_SIGN_W(rbits, rwp)) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
|
|
@ -450,7 +451,9 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
|
|||
}
|
||||
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
|
||||
}
|
||||
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
|
||||
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, QData rhs,
|
||||
bool lsign, bool rsign) VL_MT_SAFE {
|
||||
WData rhsw[2]; VL_SET_WQ(rhsw, rhs);
|
||||
return VL_POWSS_WWW(obits,lbits,rbits,owp,lwp,rhsw,lsign,rsign);
|
||||
}
|
||||
|
|
@ -982,7 +985,8 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE
|
|||
}
|
||||
}
|
||||
*destp = '\0'; // Terminate
|
||||
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||
// Drop trailing spaces
|
||||
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0';
|
||||
}
|
||||
|
||||
void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
|
||||
|
|
@ -1239,7 +1243,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||
while (1) {
|
||||
int c = fgetc(fp);
|
||||
if (VL_UNLIKELY(c==EOF)) break;
|
||||
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
||||
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n",
|
||||
// linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
||||
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
|
||||
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
||||
// Skip // comments and detect /* comments
|
||||
|
|
@ -1267,7 +1272,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
||||
if (VL_UNLIKELY(addr >= static_cast<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 +1302,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||
datap[0] |= value;
|
||||
}
|
||||
if (VL_UNLIKELY(value>=(1<<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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1745,7 +1752,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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
@ -576,16 +577,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 +598,26 @@ extern FILE* VL_CVT_I_FP(IData lhs);
|
|||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return void* from QData
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
|
||||
union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
|
||||
union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return double from QData (bits, not numerically)
|
||||
static inline double VL_CVT_D_Q(QData lhs) VL_PURE { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
static inline double VL_CVT_D_Q(QData lhs) VL_PURE {
|
||||
union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
/// Return QData from double (bits, not numerically)
|
||||
static inline QData VL_CVT_Q_D(double lhs) VL_PURE { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
|
||||
union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) VL_PURE { return static_cast<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 +628,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 +1414,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 +1439,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 +1453,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 +1578,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 +1660,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 +1726,75 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
|
|||
// Thus we specify inputs must be clean, so we don't need to clean the output.
|
||||
// Note the bit shifts are always constants, so the adds in these constify out.
|
||||
// Casts required, as args may be 8 bit entities, and need to shift to appropriate output size
|
||||
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) (static_cast<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 +1833,8 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
|||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
|
||||
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
|
||||
return VL_ZERO_W(obits, owp);
|
||||
|
|
@ -1807,7 +1854,8 @@ static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rw
|
|||
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
|
||||
// Important: Unlike most other funcs, the shift might well be a computed
|
||||
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
|
||||
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int,
|
||||
WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
int word_shift = VL_BITWORD_I(rd); // Maybe 0
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set
|
||||
|
|
@ -1832,7 +1880,8 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
|||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SHIFTR_WWW(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
|
||||
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
|
||||
return VL_ZERO_W(obits, owp);
|
||||
|
|
@ -1864,10 +1913,12 @@ static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData r
|
|||
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
|
||||
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
||||
}
|
||||
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits,
|
||||
QData lhs, IData rhs) VL_PURE {
|
||||
return static_cast<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 +1950,8 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
|
|||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
|
||||
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
|
||||
int lmsw = VL_WORDS_I(obits)-1;
|
||||
|
|
@ -1911,7 +1963,8 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP o
|
|||
}
|
||||
return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]);
|
||||
}
|
||||
static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits,
|
||||
IData lhs, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
|
||||
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
|
||||
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
|
||||
|
|
@ -1920,7 +1973,8 @@ static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDat
|
|||
}
|
||||
return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]);
|
||||
}
|
||||
static inline QData VL_SHIFTRS_QQW(int obits,int lbits,int rbits,QData lhs, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits,
|
||||
QData lhs, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
|
||||
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
|
||||
QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
|
||||
|
|
@ -1963,7 +2017,8 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
|
|||
#define VL_SEL_QQII(obits,lbits,rbits,tbits,lhs,lsb,width) ((lhs)>>(lsb))
|
||||
#define VL_SEL_IQII(obits,lbits,rbits,tbits,lhs,lsb,width) (static_cast<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 +2032,8 @@ static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP lwp, IData ls
|
|||
}
|
||||
}
|
||||
|
||||
static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
static inline QData VL_SEL_QWII(int, int lbits, int, int,
|
||||
WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
int msb = lsb+width-1;
|
||||
if (VL_UNLIKELY(msb>lbits)) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
|
|
@ -1998,7 +2054,8 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData ls
|
|||
}
|
||||
}
|
||||
|
||||
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int,
|
||||
WDataOutP owp, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
int msb = lsb+width-1;
|
||||
int word_shift = VL_BITWORD_I(lsb);
|
||||
if (VL_UNLIKELY(msb>lbits)) { // Outside bounds,
|
||||
|
|
@ -2121,37 +2178,41 @@ static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
|
|||
o[0]=d0;
|
||||
_END(obits,1); }
|
||||
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
|
||||
IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1;
|
||||
_END(obits,2); }
|
||||
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
|
||||
IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2;
|
||||
_END(obits,3); }
|
||||
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
|
||||
IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
||||
_END(obits,4); }
|
||||
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
|
||||
IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
||||
_END(obits,5); }
|
||||
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
|
||||
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
||||
_END(obits,6); }
|
||||
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
|
||||
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d6, IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
||||
_END(obits,7); }
|
||||
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
||||
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d7, IData d6, IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||
_END(obits,8); }
|
||||
|
|
@ -2160,7 +2221,8 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
|||
|
||||
// Partial constant, lower words of vector wider than 8*32, starting at bit number lsb
|
||||
static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
|
||||
IData d7, IData d6, IData d5, IData d4, IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
IData d7, IData d6, IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -349,6 +349,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
37
src/V3Ast.h
37
src/V3Ast.h
|
|
@ -1110,7 +1110,8 @@ public:
|
|||
AstNode* op4p() const { return m_op4p; }
|
||||
AstNodeDType* dtypep() const { return m_dtypep; }
|
||||
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
||||
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
||||
AstNode* firstAbovep() const { // Returns NULL when second or later in list
|
||||
return ((backp() && backp()->nextp()!=this) ? backp() : NULL); }
|
||||
bool brokeExists() const;
|
||||
bool brokeExistsAbove() const;
|
||||
|
||||
|
|
@ -1301,7 +1302,8 @@ public:
|
|||
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
||||
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
||||
AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it.
|
||||
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||
// Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL);
|
||||
void swapWith(AstNode* bp);
|
||||
void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead
|
||||
void cloneRelinkNode() { cloneRelink(); }
|
||||
|
|
@ -1330,17 +1332,20 @@ public:
|
|||
virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
|
||||
virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations
|
||||
virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out
|
||||
virtual bool isGateDedupable() const { return isGateOptimizable(); } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||
virtual bool isGateDedupable() const { return isGateOptimizable(); }
|
||||
virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out
|
||||
virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input
|
||||
virtual bool isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed
|
||||
virtual bool isUnlikely() const { return false; } // Else $stop or similar statement which means an above IF statement is unlikely to be taken
|
||||
// isUnlikely handles $stop or similar statement which means an above IF statement is unlikely to be taken
|
||||
virtual bool isUnlikely() const { return false; }
|
||||
virtual int instrCount() const { return 0; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
|
||||
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
|
||||
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
// Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
virtual bool maybePointedTo() const { return false; }
|
||||
virtual const char* broken() const { return NULL; }
|
||||
|
||||
// INVOKERS
|
||||
|
|
@ -1463,7 +1468,9 @@ public:
|
|||
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
||||
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
||||
// METHODS
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) = 0; // Set out to evaluation of a AstConst'ed
|
||||
// Set out to evaluation of a AstConst'ed
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs,
|
||||
const V3Number& rhs, const V3Number& ths) = 0;
|
||||
virtual bool cleanLhs() = 0; // True if LHS must have extra upper bits zero
|
||||
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero
|
||||
virtual bool cleanThs() = 0; // True if THS must have extra upper bits zero
|
||||
|
|
@ -1749,7 +1756,8 @@ public:
|
|||
bool isNosign() const { return m_numeric.isNosign(); }
|
||||
AstNumeric numeric() const { return m_numeric; }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
||||
int widthMin() const { // If sized, the size, if unsized the min digits to represent it
|
||||
return m_widthMin?m_widthMin:m_width; }
|
||||
int widthPow2() const;
|
||||
void widthMinFromWidth() { m_widthMin = m_width; }
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
|
|
@ -2089,11 +2097,16 @@ public:
|
|||
|
||||
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
||||
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
||||
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
|
||||
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
||||
inline bool AstNode::isDouble() const { return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); }
|
||||
inline bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
|
||||
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
||||
inline bool AstNode::width1() const { // V3Const uses to know it can optimize
|
||||
return dtypep() && dtypep()->width()==1; }
|
||||
inline int AstNode::widthInstrs() const {
|
||||
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
||||
inline bool AstNode::isDouble() const {
|
||||
return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); }
|
||||
inline bool AstNode::isString() const {
|
||||
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
|
||||
inline bool AstNode::isSigned() const {
|
||||
return dtypep() && dtypep()->isSigned(); }
|
||||
|
||||
inline bool AstNode::isZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqZero()); }
|
||||
inline bool AstNode::isNeqZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isNeqZero()); }
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ int AstNodeSel::bitConst() const {
|
|||
void AstNodeClassDType::repairMemberCache() {
|
||||
clearCache();
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) {
|
||||
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,26 +47,26 @@ private:
|
|||
public:
|
||||
AstConst(FileLine* fl, const V3Number& num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(num) {
|
||||
,m_num(num) {
|
||||
if (m_num.isDouble()) {
|
||||
dtypeSetDouble();
|
||||
} else if (m_num.isString()) {
|
||||
} else if (m_num.isString()) {
|
||||
dtypeSetString();
|
||||
} else {
|
||||
dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(),
|
||||
m_num.isSigned() ? AstNumeric::SIGNED
|
||||
dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(),
|
||||
m_num.isSigned() ? AstNumeric::SIGNED
|
||||
: AstNumeric::UNSIGNED);
|
||||
}
|
||||
}
|
||||
}
|
||||
AstConst(FileLine* fl, uint32_t num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { dtypeSetLogicSized(m_num.width(),
|
||||
,m_num(V3Number(fl,32,num)) { dtypeSetLogicSized(m_num.width(),
|
||||
m_num.sized()?0:m_num.widthMin(),
|
||||
AstNumeric::UNSIGNED); }
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
|
||||
AstNumeric::UNSIGNED); }
|
||||
class Signed32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
|
||||
|
|
@ -79,7 +79,7 @@ public:
|
|||
,m_num(V3Number(fl,64)) { m_num.setDouble(num); dtypeSetDouble(); }
|
||||
class String {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, String, const string& num)
|
||||
:AstNodeMath(fl)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(V3Number::String(), fl, num)) { dtypeSetString(); }
|
||||
class LogicFalse {};
|
||||
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
|
||||
|
|
@ -706,13 +706,17 @@ public:
|
|||
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
||||
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
|
||||
//
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
// (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); }
|
||||
// op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
|
||||
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
|
||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
||||
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
|
||||
// METHODS
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual void tag(const string& text) { m_tag = text;}
|
||||
|
|
@ -1183,7 +1187,8 @@ public:
|
|||
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
|
||||
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
|
||||
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
|
||||
string vlArgType(bool named, bool forReturn, bool forFunc) const; // Return Verilator internal type for argument: CData, SData, IData, WData
|
||||
// Return Verilator internal type for argument: CData, SData, IData, WData
|
||||
string vlArgType(bool named, bool forReturn, bool forFunc) const;
|
||||
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
|
||||
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
|
||||
string vlPropInit() const; // Return VerilatorVarProps initializer
|
||||
|
|
@ -1191,7 +1196,8 @@ public:
|
|||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable
|
||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
|
||||
AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
// (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
AstBasicDType* basicp() const { return subDTypep()->basicp(); }
|
||||
AstNode* valuep() const { return op3p(); } // op3 = Initial value that never changes (static const)
|
||||
void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than an AstConst
|
||||
void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
|
||||
|
|
@ -1443,11 +1449,14 @@ class AstVarRef : public AstNodeVarRef {
|
|||
// A reference to a variable (lvalue or rvalue)
|
||||
public:
|
||||
AstVarRef(FileLine* fl, const string& name, bool lvalue)
|
||||
:AstNodeVarRef(fl, name, NULL, lvalue) {}
|
||||
AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) // This form only allowed post-link
|
||||
:AstNodeVarRef(fl, varp->name(), varp, lvalue) {} // because output/wire compression may lead to deletion of AstVar's
|
||||
AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue) // This form only allowed post-link
|
||||
:AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) { // because output/wire compression may lead to deletion of AstVar's
|
||||
: AstNodeVarRef(fl, name, NULL, lvalue) {}
|
||||
// This form only allowed post-link because output/wire compression may
|
||||
// lead to deletion of AstVar's
|
||||
AstVarRef(FileLine* fl, AstVar* varp, bool lvalue)
|
||||
: AstNodeVarRef(fl, varp->name(), varp, lvalue) {}
|
||||
// This form only allowed post-link (see above)
|
||||
AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue)
|
||||
: AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) {
|
||||
varScopep(varscp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(VarRef)
|
||||
|
|
@ -2331,7 +2340,9 @@ public:
|
|||
ASTNODE_NODE_FUNCS(CoverDecl)
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists());
|
||||
if (m_dataDeclp && m_dataDeclp->m_dataDeclp) v3fatalSrc("dataDeclp should point to real data, not be a list"); // Avoid O(n^2) accessing
|
||||
if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing
|
||||
v3fatalSrc("dataDeclp should point to real data, not be a list");
|
||||
}
|
||||
return NULL; }
|
||||
virtual void cloneRelink() { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); }
|
||||
virtual void dump(std::ostream& str);
|
||||
|
|
@ -2594,6 +2605,26 @@ public:
|
|||
void lhsp(AstNode* nodep) { setOp3p(nodep); }
|
||||
};
|
||||
|
||||
class AstSysFuncAsTask : public AstNodeStmt {
|
||||
// Call what is normally a system function (with a return) in a non-return context
|
||||
// Parents: stmtlist
|
||||
// Children: a system function
|
||||
public:
|
||||
AstSysFuncAsTask(FileLine* fileline, AstNode* exprsp)
|
||||
: AstNodeStmt (fileline) { addNOp1p(exprsp); }
|
||||
ASTNODE_NODE_FUNCS(SysFuncAsTask)
|
||||
virtual string verilogKwd() const { return ""; }
|
||||
virtual bool isGateOptimizable() const { return true; }
|
||||
virtual bool isPredictOptimizable() const { return true; }
|
||||
virtual bool isPure() const { return true; }
|
||||
virtual bool isOutputter() const { return false; }
|
||||
virtual int instrCount() const { return 0; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval
|
||||
void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval
|
||||
};
|
||||
|
||||
class AstSysIgnore : public AstNodeStmt {
|
||||
// Parents: stmtlist
|
||||
// Children: varrefs or exprs
|
||||
|
|
@ -3420,10 +3451,14 @@ public:
|
|||
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstText* scopeEntrp() const { return VN_CAST(op2p(), Text); }
|
||||
void scopeEntrp(AstNode* nodep) { addOp2p(nodep); }
|
||||
string scopeSymName() const { return scopeNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
|
||||
string scopeDpiName() const { return scopeNameFormatter(scopeEntrp()); } // Name for DPI import scope
|
||||
string scopePrettySymName() const { return scopePrettyNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
|
||||
string scopePrettyDpiName() const { return scopePrettyNameFormatter(scopeEntrp()); } // Name for __Vscope variable including children
|
||||
string scopeSymName() const { // Name for __Vscope variable including children
|
||||
return scopeNameFormatter(scopeAttrp()); }
|
||||
string scopeDpiName() const { // Name for DPI import scope
|
||||
return scopeNameFormatter(scopeEntrp()); }
|
||||
string scopePrettySymName() const { // Name for __Vscope variable including children
|
||||
return scopePrettyNameFormatter(scopeAttrp()); }
|
||||
string scopePrettyDpiName() const { // Name for __Vscope variable including children
|
||||
return scopePrettyNameFormatter(scopeEntrp()); }
|
||||
bool dpiExport() const { return m_dpiExport; }
|
||||
void dpiExport(bool flag) { m_dpiExport=flag; }
|
||||
};
|
||||
|
|
@ -4606,7 +4641,9 @@ public:
|
|||
virtual string emitSimpleOperator() { return ">>"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} // LHS size might be > output size, so don't want to force size
|
||||
// LHS size might be > output size, so don't want to force size
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
class AstShiftRS : public AstNodeBiop {
|
||||
// Shift right with sign extension, >>> operator
|
||||
|
|
@ -5677,8 +5714,10 @@ public:
|
|||
BROKEN_RTN(m_evalp && !m_evalp->brokeExists());
|
||||
return NULL;
|
||||
}
|
||||
AstNodeModule* modulesp() const { return VN_CAST(op1p(), NodeModule); } // op1 = List of modules
|
||||
AstNodeModule* topModulep() const { return VN_CAST(op1p(), NodeModule); } // * = Top module in hierarchy (first one added, for now)
|
||||
AstNodeModule* modulesp() const { // op1 = List of modules
|
||||
return VN_CAST(op1p(), NodeModule); }
|
||||
AstNodeModule* topModulep() const { // * = Top module in hierarchy (first one added, for now)
|
||||
return VN_CAST(op1p(), NodeModule); }
|
||||
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
|
||||
AstCFile* filesp() const { return VN_CAST(op2p(), CFile);} // op2 = List of files
|
||||
void addFilesp(AstCFile* filep) { addOp2p(filep); }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,8 +224,10 @@ 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 (!VN_IS(nodep->dtypep(), NodeDType)) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
if (!nodep->dtypep()->brokeExists()) {
|
||||
nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
else if (!VN_IS(nodep->dtypep(), NodeDType)) {
|
||||
nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
}
|
||||
if (v3Global.assertDTypesResolved()) {
|
||||
if (nodep->hasDType()) {
|
||||
|
|
|
|||
|
|
@ -130,7 +130,8 @@ void V3CCtors::evalAsserts() {
|
|||
newp = new AstAnd(varp->fileline(), newp,
|
||||
new AstConst(varp->fileline(), num));
|
||||
AstNodeIf* ifp = new AstIf(varp->fileline(), newp,
|
||||
new AstCStmt(varp->fileline(), "Verilated::overWidthError(\""+varp->prettyName()+"\");"));
|
||||
new AstCStmt(varp->fileline(),
|
||||
"Verilated::overWidthError(\""+varp->prettyName()+"\");"));
|
||||
ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
newp = ifp;
|
||||
funcp->addStmtsp(newp);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1202,7 +1202,8 @@ private:
|
|||
AstAnd* newp = new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), val),
|
||||
fromp);
|
||||
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
|
||||
// widthMin no longer applicable if different C-expanded width
|
||||
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED);
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
||||
|
|
@ -1759,7 +1760,8 @@ private:
|
|||
// Something's out of order, sort it
|
||||
senp = NULL;
|
||||
std::vector<AstNodeSenItem*> vec;
|
||||
for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) {
|
||||
for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem);
|
||||
senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) {
|
||||
vec.push_back(senp);
|
||||
}
|
||||
stable_sort(vec.begin(), vec.end(), SenItemCmp());
|
||||
|
|
@ -2561,15 +2563,19 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
|
|||
void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<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);
|
||||
}
|
||||
|
||||
|
|
@ -2584,16 +2590,20 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
|
|||
// This only pushes constants up, doesn't make any other edits
|
||||
// IE doesn't prune dead statements, as we need to do some usability checks after this
|
||||
UINFO(2,__FUNCTION__<<": "<<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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -378,7 +378,8 @@ private:
|
|||
// members are still alive.
|
||||
if ((classp = VN_CAST((*it), NodeClassDType))) {
|
||||
bool cont = true;
|
||||
for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = VN_CAST(memberp->nextp(), MemberDType)) {
|
||||
for (AstMemberDType *memberp = classp->membersp();
|
||||
memberp; memberp = VN_CAST(memberp->nextp(), MemberDType)) {
|
||||
if (memberp->user1() != 0) {
|
||||
cont = false;
|
||||
break;
|
||||
|
|
@ -425,30 +426,40 @@ public:
|
|||
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = VN_CAST(lhsp, ArraySel);
|
||||
}
|
||||
if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?");
|
||||
if (VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType)) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
|
||||
if (VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
}
|
||||
UINFO(4,"AssignDlyArray: "<<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 = VN_CAST(oldvscp->user1p(), VarScope);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,6 +376,11 @@ public:
|
|||
puts(")); }\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSysFuncAsTask* nodep) {
|
||||
if (!nodep->lhsp()->isWide()) puts("(void)");
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
if (!nodep->lhsp()->isWide()) puts(";");
|
||||
}
|
||||
virtual void visit(AstSystemT* nodep) {
|
||||
puts("(void)VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
|
|
@ -509,31 +514,36 @@ public:
|
|||
}
|
||||
virtual void visit(AstMulS* nodep) {
|
||||
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
|
||||
nodep->v3error("Unsupported: Signed multiply of "<<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(VN_CAST(nodep, NodeBiop));
|
||||
}
|
||||
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(VN_CAST(nodep, NodeBiop));
|
||||
}
|
||||
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(VN_CAST(nodep, NodeBiop));
|
||||
}
|
||||
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(VN_CAST(nodep, NodeBiop));
|
||||
}
|
||||
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(VN_CAST(nodep, NodeBiop));
|
||||
}
|
||||
|
|
@ -978,6 +988,7 @@ class EmitCImp : EmitCStmts {
|
|||
// High level
|
||||
void emitImp(AstNodeModule* modp);
|
||||
void emitStaticDecl(AstNodeModule* modp);
|
||||
void emitSettleLoop(std::string eval_call, bool initial);
|
||||
void emitWrapEval(AstNodeModule* modp);
|
||||
void emitInt(AstNodeModule* modp);
|
||||
|
||||
|
|
@ -1550,7 +1561,8 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
|
|||
puts("\n// Coverage\n");
|
||||
// Rather than putting out VL_COVER_INSERT calls directly, we do it via this function
|
||||
// This gets around gcc slowness constructing all of the template arguments.
|
||||
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
|
||||
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable,"
|
||||
" const char* filenamep, int lineno, int column,\n");
|
||||
puts( "const char* hierp, const char* pagep, const char* commentp) {\n");
|
||||
puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant
|
||||
puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin
|
||||
|
|
@ -1729,6 +1741,29 @@ void EmitCImp::emitSensitives() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmitCImp::emitSettleLoop(std::string eval_call, bool initial) {
|
||||
putsDecoration("// Evaluate till stable\n");
|
||||
puts("int __VclockLoop = 0;\n");
|
||||
puts("QData __Vchange = 1;\n");
|
||||
puts("do {\n");
|
||||
puts( eval_call + "\n");
|
||||
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+")) {\n");
|
||||
puts( "// About to fail, so enable debug to see what's not settling.\n");
|
||||
puts( "// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n");
|
||||
puts( "int __Vsaved_debug = Verilated::debug();\n");
|
||||
puts( "Verilated::debug(1);\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "Verilated::debug(__Vsaved_debug);\n");
|
||||
puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't ");
|
||||
if (initial) puts ("DC ");
|
||||
puts( "converge\");\n");
|
||||
puts( "} else {\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "}\n");
|
||||
puts("} while (VL_UNLIKELY(__Vchange));\n");
|
||||
}
|
||||
|
||||
void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts("\nvoid "+modClassName(modp)+"::eval() {\n");
|
||||
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
|
||||
|
|
@ -1750,20 +1785,10 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
|||
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"Train starting, trainId="+cvtToStr(trainId)+"\\n\"););\n");
|
||||
puts("Verilated::trainId("+cvtToStr(trainId)+");\n");
|
||||
}
|
||||
|
||||
putsDecoration("// Evaluate till stable\n");
|
||||
puts("int __VclockLoop = 0;\n");
|
||||
puts("QData __Vchange = 1;\n");
|
||||
puts("while (VL_LIKELY(__Vchange)) {\n");
|
||||
puts( "VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("vlSymsp->__Vm_activity = true;\n");
|
||||
}
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+")) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||
puts("}\n");
|
||||
emitSettleLoop(
|
||||
(string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n")
|
||||
+ (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "")
|
||||
+ "_eval(vlSymsp);"), false);
|
||||
if (v3Global.opt.threads()) { // THREADED-TODO move to end of all trains on thread
|
||||
puts("Verilated::endOfThreadTrain(vlSymsp->__Vm_evalMsgQp);\n");
|
||||
}
|
||||
|
|
@ -1780,15 +1805,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
|||
if (v3Global.opt.trace()) {
|
||||
puts("vlSymsp->__Vm_activity = true;\n");
|
||||
}
|
||||
puts( "int __VclockLoop = 0;\n");
|
||||
puts( "QData __Vchange = 1;\n");
|
||||
puts( "while (VL_LIKELY(__Vchange)) {\n");
|
||||
puts( "_eval_settle(vlSymsp);\n");
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+")) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
|
||||
puts( "}\n");
|
||||
emitSettleLoop((string("_eval_settle(vlSymsp);\n")
|
||||
+"_eval(vlSymsp);"), true);
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
|
|
@ -2296,8 +2314,9 @@ class EmitCTrace : EmitCStmts {
|
|||
putsDecoration("// Callback from vcd->open()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("if (!Verilated::calcUnusedSigs()) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||
|
||||
puts("if (!Verilated::calcUnusedSigs()) {\n");
|
||||
puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||
puts("}\n");
|
||||
puts("vcdp->scopeEscape(' ');\n");
|
||||
puts("t->traceInitThis(vlSymsp, vcdp, code);\n");
|
||||
puts("vcdp->scopeEscape('.');\n"); // Restore so later traced files won't break
|
||||
|
|
|
|||
|
|
@ -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()<<"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(" (");
|
||||
|
|
|
|||
|
|
@ -266,8 +266,11 @@ inline void v3errorEndFatal(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr
|
|||
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||
// Note the commas are the comma operator, not separating arguments. These are needed to insure
|
||||
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
|
||||
#define v3warnCode(code,msg) v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<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,9 @@ inline void v3errorEndFatal(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr
|
|||
|
||||
#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))) { std::cerr<<"Internal Error: "<<__FILE__<<":"<<std::dec<<__LINE__<<":"<<(stmsg)<<std::endl; abort(); } }
|
||||
#define UASSERT_STATIC(condition,stmsg) \
|
||||
{ if (VL_UNLIKELY(!(condition))) { \
|
||||
std::cerr<<"Internal Error: "<<__FILE__<<":"<<std::dec<<__LINE__<<":"<<(stmsg)<<std::endl; abort(); } }
|
||||
|
||||
#define V3ERROR_NA { v3error("Internal: Unexpected Call"); v3fatalSrc("Unexpected Call"); }
|
||||
|
||||
|
|
|
|||
|
|
@ -243,7 +243,9 @@ private:
|
|||
}
|
||||
bool expandWide (AstNodeAssign* nodep, AstArraySel* rhsp) {
|
||||
UINFO(8," Wordize ASSIGN(ARRAYSEL) "<<nodep<<endl);
|
||||
if (VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
if (VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
}
|
||||
for (int w=0; 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -545,7 +545,8 @@ public:
|
|||
// Important to add statement next to cell, in case there is a generate with same named cell
|
||||
cellp->addNextHere(newvarp);
|
||||
if (pinVarp->isInout()) {
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be"
|
||||
" direct one-to-one connection (without any expression)");
|
||||
} else if (pinVarp->isOutput()) {
|
||||
// See also V3Inst
|
||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||
|
|
@ -582,12 +583,16 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
|
|||
|
||||
void V3Inst::instAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,6 +228,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -262,7 +262,8 @@ public:
|
|||
AstCell* nodep, const string& scopename) {
|
||||
if (!abovep) nodep->v3fatalSrc("Null symbol table inserting node");
|
||||
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
|
||||
UINFO(9," INSERTcel se"<<(void*)symp<<" "<<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 +284,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__");
|
||||
|
|
@ -1551,7 +1553,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1815,7 +1818,8 @@ private:
|
|||
AstCell* cellp = VN_CAST(foundp->nodep(), Cell);
|
||||
if (VN_IS(cellp->modp(), Iface)) {
|
||||
// Interfaces can be referenced like a variable for interconnect
|
||||
VSymEnt* cellEntp = m_statep->getNodeSym(cellp); if (!cellEntp) nodep->v3fatalSrc("No interface sym entry");
|
||||
VSymEnt* cellEntp = m_statep->getNodeSym(cellp);
|
||||
if (!cellEntp) nodep->v3fatalSrc("No interface sym entry");
|
||||
VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a module or generate begin
|
||||
string findName = nodep->name()+"__Viftop";
|
||||
VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName);
|
||||
|
|
@ -2011,7 +2015,8 @@ private:
|
|||
VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
|
||||
AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL;
|
||||
if (!vscp) {
|
||||
nodep->v3error("Can't find varpin scope of '"<<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
|
||||
|
|
@ -2126,7 +2131,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -2314,21 +2320,29 @@ public:
|
|||
int V3LinkDot::debug() { return LinkDotState::debug(); }
|
||||
|
||||
void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
|
||||
}
|
||||
LinkDotState state (rootp, step);
|
||||
LinkDotFindVisitor visitor(rootp,&state);
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree"));
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree"));
|
||||
}
|
||||
if (step == LDS_PRIMARY || step == LDS_PARAMED) {
|
||||
// Initial link stage, resolve parameters
|
||||
LinkDotParamVisitor visitors(rootp,&state);
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree"));
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree"));
|
||||
}
|
||||
}
|
||||
else if (step == LDS_ARRAYED) {}
|
||||
else if (step == LDS_SCOPED) {
|
||||
// Well after the initial link when we're ready to operate on the flat design,
|
||||
// process AstScope's. This needs to be separate pass after whole hierarchy graph created.
|
||||
LinkDotScopeVisitor visitors(rootp,&state);
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree"));
|
||||
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree"));
|
||||
}
|
||||
}
|
||||
else v3fatalSrc("Bad case");
|
||||
state.dump();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -430,6 +430,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -515,7 +515,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -659,6 +659,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
|||
else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD
|
||||
else if ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-sigsegv
|
||||
else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; }
|
||||
else if ( onoff (sw, "-debug-leak", flag/*ref*/) ){ m_debugLeak = flag; }
|
||||
else if ( !strcmp (sw, "-debug-sigsegv") ) { throwSigsegv(); } // Undocumented, see also --debug-abort
|
||||
else if ( !strcmp (sw, "-debug-fatalsrc") ) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort
|
||||
else if ( onoff (sw, "-decoration", flag/*ref*/) ) { m_decoration = flag; }
|
||||
|
|
@ -1218,6 +1219,7 @@ V3Options::V3Options() {
|
|||
m_coverageUnderscore = false;
|
||||
m_coverageUser = false;
|
||||
m_debugCheck = false;
|
||||
m_debugLeak = true;
|
||||
m_decoration = true;
|
||||
m_exe = false;
|
||||
m_ignc = false;
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -416,7 +416,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ class SliceVisitor : public AstNVisitor {
|
|||
// Insert an ArraySel, except for a few special cases
|
||||
AstUnpackArrayDType* arrayp = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType);
|
||||
if (!arrayp) { // V3Width should have complained, but...
|
||||
if (!m_assignError) nodep->v3error(nodep->prettyTypeName()<<" is not an unpacked array, but is in an unpacked array context");
|
||||
if (!m_assignError) {
|
||||
nodep->v3error(nodep->prettyTypeName()
|
||||
<<" is not an unpacked array, but is in an unpacked array context");
|
||||
}
|
||||
m_assignError = true;
|
||||
return nodep->cloneTree(false); // Likely will cause downstream errors
|
||||
}
|
||||
|
|
@ -241,6 +244,8 @@ public:
|
|||
|
||||
void V3Slice::sliceAll(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SliceVisitor visitor(rootp);
|
||||
{
|
||||
SliceVisitor visitor(rootp);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("slice", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1024,11 +1024,15 @@ private:
|
|||
|
||||
void V3Split::splitReorderAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ReorderVisitor visitor (nodep);
|
||||
{
|
||||
ReorderVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("reorder", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
void V3Split::splitAlwaysAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SplitVisitor visitor (nodep);
|
||||
{
|
||||
SplitVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("split", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ private:
|
|||
static inline int debug() { return 0; } // NOT runtime, too hot of a function
|
||||
#endif
|
||||
public:
|
||||
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent, int numLevels, const string& searchName) const {
|
||||
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent,
|
||||
int numLevels, const string& searchName) const {
|
||||
os<<indent<<"+ "<<std::left<<std::setw(30)<<(searchName==""?"\"\"":searchName)<<std::setw(0)<<std::right;
|
||||
os<<" se"<<(void*)(this)<<std::setw(0);
|
||||
os<<" fallb=se"<<(void*)(m_fallbackp);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ typedef std::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
|
||||
|
|
|
|||
|
|
@ -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 "<<std::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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -1341,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -477,7 +480,9 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@
|
|||
// widthSized() = true if all constants sized, else false
|
||||
// Compute size of this expression
|
||||
// Lint warn about mismatches
|
||||
// If expr size != subop fixed, bad
|
||||
// If expr size < subop unsized minimum, bad
|
||||
// If expr size != subop, edit netlist
|
||||
// For == and similar ops, if multibit underneath, add a REDOR
|
||||
// If subop larger, add a EXTRACT
|
||||
// If expr size != subop fixed, bad
|
||||
// If expr size < subop unsized minimum, bad
|
||||
// If expr size != subop, edit netlist
|
||||
// For == and similar ops, if multibit underneath, add a REDOR
|
||||
// If subop larger, add a EXTRACT
|
||||
// If subop smaller, add a EXTEND
|
||||
// Pass size to sub-expressions if required (+/-* etc)
|
||||
// FINAL = true.
|
||||
|
|
@ -48,16 +48,16 @@
|
|||
// Comparison results are unsigned
|
||||
// Bit&Part selects are unsigned, even if whole
|
||||
// Concatenates are unsigned
|
||||
// Ignore signedness of self-determined:
|
||||
// shift rhs, ** rhs, x?: lhs, concat and replicate members
|
||||
// Ignore signedness of self-determined:
|
||||
// shift rhs, ** rhs, x?: lhs, concat and replicate members
|
||||
// Else, if any operand unsigned, output unsigned
|
||||
//
|
||||
// Real number rules:
|
||||
// Real numbers are real (duh)
|
||||
// Reals convert to integers by rounding
|
||||
// Reals init to 0.0
|
||||
// Logicals convert compared to zero
|
||||
// If any operand is real, result is real
|
||||
// Logicals convert compared to zero
|
||||
// If any operand is real, result is real
|
||||
//*************************************************************************
|
||||
// V3Width is the only visitor that uses vup. We could switch to using userp,
|
||||
// though note some iterators operate on next() and so would need to pass the
|
||||
|
|
@ -1199,7 +1199,9 @@ private:
|
|||
if (nodep->valuep()->dtypep()->widthSized()) {
|
||||
width = nodep->valuep()->width();
|
||||
} else {
|
||||
if (nodep->valuep()->width()>32) nodep->valuep()->v3warn(WIDTH,"Assigning >32 bit to unranged parameter (defaults to 32 bits)");
|
||||
if (nodep->valuep()->width()>32) {
|
||||
nodep->valuep()->v3warn(WIDTH,"Assigning >32 bit to unranged parameter (defaults to 32 bits)");
|
||||
}
|
||||
width = 32;
|
||||
}
|
||||
// Can't just inherit valuep()->dtypep() as mwidth might not equal width
|
||||
|
|
@ -1244,7 +1246,8 @@ private:
|
|||
if (nodep->didWidth()) return;
|
||||
if (!nodep->varp()) {
|
||||
if (m_paramsOnly && VN_IS(nodep, VarXRef)) {
|
||||
checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: "+nodep->prettyName()); VL_DANGLING(nodep);
|
||||
checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: "
|
||||
+nodep->prettyName()); VL_DANGLING(nodep);
|
||||
return;
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unlinked varref");
|
||||
|
|
@ -1493,13 +1496,15 @@ private:
|
|||
} else {
|
||||
AstSel* newp = new AstSel(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
memberp->lsb(), memberp->width());
|
||||
newp->dtypep(memberp->subDTypep()->skipRefToEnump()); // Must skip over the member to find the union; as the member may disappear later
|
||||
// Must skip over the member to find the union; as the member may disappear later
|
||||
newp->dtypep(memberp->subDTypep()->skipRefToEnump());
|
||||
newp->didWidth(true); // Don't replace dtype with basic type
|
||||
UINFO(9," MEMBERSEL -> "<<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
|
||||
|
|
@ -1661,7 +1666,9 @@ private:
|
|||
nodep->dtypep(m_vup->dtypep());
|
||||
}
|
||||
AstNodeDType* vdtypep = nodep->dtypep();
|
||||
if (!vdtypep) nodep->v3error("Unsupported/Illegal: Assignment pattern member not underneath a supported construct: "<<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);
|
||||
|
|
@ -1721,7 +1728,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1733,7 +1741,8 @@ private:
|
|||
} else {
|
||||
std::pair<PatMap::iterator, bool> ret = patmap.insert(make_pair(memp, patp));
|
||||
if (!ret.second) {
|
||||
patp->v3error("Assignment pattern contains duplicate entry: " << VN_CAST(patp->keyp(), Text)->text());
|
||||
patp->v3error("Assignment pattern contains duplicate entry: "
|
||||
<< VN_CAST(patp->keyp(), Text)->text());
|
||||
}
|
||||
}
|
||||
// Next
|
||||
|
|
@ -2189,6 +2198,10 @@ private:
|
|||
nodep->dtypeSetSigned32(); // Spec says integer return
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSysFuncAsTask* nodep) {
|
||||
assertAtStatement(nodep);
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p());
|
||||
}
|
||||
virtual void visit(AstSystemT* nodep) {
|
||||
assertAtStatement(nodep);
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p());
|
||||
|
|
@ -2286,8 +2299,12 @@ private:
|
|||
if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(exprDTypep, IfaceRefDType)) ||
|
||||
(VN_IS(exprDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) {
|
||||
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
||||
<<" mismatch between port which is"<<(VN_CAST(modDTypep, IfaceRefDType)?"":" not")<<" an interface,"
|
||||
<<" and expression which is"<<(VN_CAST(exprDTypep, IfaceRefDType)?"":" not")<<" an interface.");
|
||||
<<" mismatch between port which is"
|
||||
<<(VN_CAST(modDTypep, IfaceRefDType)?"":" not")
|
||||
<<" an interface,"
|
||||
<<" and expression which is"
|
||||
<<(VN_CAST(exprDTypep, IfaceRefDType)?"":" not")
|
||||
<<" an interface.");
|
||||
}
|
||||
|
||||
// TODO Simple dtype checking, should be a more general check
|
||||
|
|
@ -2952,9 +2969,12 @@ private:
|
|||
bool widthBad (AstNode* nodep, AstNodeDType* expDTypep) {
|
||||
int expWidth = expDTypep->width();
|
||||
int expWidthMin = expDTypep->widthMin();
|
||||
if (!nodep->dtypep()) nodep->v3fatalSrc("Under node "<<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;
|
||||
|
|
@ -3860,12 +3880,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);
|
||||
}
|
||||
|
||||
|
|
@ -3901,6 +3923,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ 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; i < (yy_size_t)(_yybytes_len); ++i )/g;
|
||||
$line =~ s/for \( i = 0; i < _yybytes_len; \+\+i \)/for ( i = 0; (yy_size_t)(i) < (yy_size_t)(_yybytes_len); ++i )/g;
|
||||
# Fix flex 2.6.0 warning
|
||||
$line =~ s/\(\(int\) \(\(yy_n_chars\) \+ number_to_move\) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size\)/((int) ((yy_n_chars) + number_to_move) > (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size)/g;
|
||||
$line =~ s/ number_to_move == YY_MORE_ADJ / (int)number_to_move == (int)YY_MORE_ADJ /;
|
||||
|
|
|
|||
|
|
@ -1065,7 +1065,8 @@ void V3ParseImp::lexToken() {
|
|||
}
|
||||
else if (token == yGLOBAL__LEX) {
|
||||
if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
|
||||
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can
|
||||
// Avoid 2009 "global" conflicting with old code when we can
|
||||
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); }
|
||||
}
|
||||
// If add to above "else if", also add to "if (token" further above
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2663,6 +2663,8 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
|||
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); }
|
||||
//
|
||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
|
||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); }
|
||||
//
|
||||
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
|
||||
| yD_FFLUSH parenE { $1->v3error("Unsupported: $fflush of all handles does not map to C++."); }
|
||||
| yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); }
|
||||
|
|
@ -2673,7 +2675,6 @@ system_t_call<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); }
|
||||
|
|
@ -2698,6 +2699,9 @@ 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); }
|
||||
//
|
||||
// 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)
|
||||
|
|
@ -2707,7 +2711,14 @@ 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(VN_CAST($$, FuncRef)); }
|
||||
//
|
||||
| yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); }
|
||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
||||
//
|
||||
| system_f_call_or_t { $$ = $1; }
|
||||
;
|
||||
|
||||
system_f_call_or_t<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); }
|
||||
|
|
@ -2717,7 +2728,6 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
|||
| yD_BITS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
|
||||
| yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
|
||||
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
|
||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
||||
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
|
||||
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
|
||||
| yD_COS '(' expr ')' { $$ = new AstCosD($1,$3); }
|
||||
|
|
@ -2762,7 +2772,6 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
|||
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
||||
| yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); }
|
||||
| yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); }
|
||||
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--debug --no-debug-leak"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
|
@ -45,6 +45,11 @@ module t;
|
|||
$display("str='%s'",sv_str);
|
||||
if (sv_str != "T=1234") $stop;
|
||||
|
||||
sv_str = "none";
|
||||
$value$plusargs("IN%s", sv_str);
|
||||
$display("str='%s'",sv_str);
|
||||
if (sv_str != "T=1234") $stop;
|
||||
|
||||
p_in = "IN%s";
|
||||
`ifdef VERILATOR
|
||||
p_in = $c(p_in); // Prevent constant propagation
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
x,
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
`ifdef ALLOW_UNOPT
|
||||
/*verilator lint_off UNOPTFLAT*/
|
||||
`endif
|
||||
|
||||
input clk;
|
||||
output [31:0] x; // Avoid eliminating x
|
||||
|
||||
reg [31:0] x;
|
||||
always @* begin
|
||||
x = x ^ $random;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_unopt_converge_initial.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+ALLOW_UNOPT'],
|
||||
);
|
||||
|
||||
execute (
|
||||
fails=>1,
|
||||
expect=> '%Error: \S+:\d+: Verilated model didn\'t DC converge',
|
||||
) if $Self->{vlt};
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Loading…
Reference in New Issue