mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 01:23:37 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7aa8820e1 | ||
|
|
2582a83376 | ||
|
|
0094cd7a81 | ||
|
|
d9b33d74a4 | ||
|
|
539a773ea7 | ||
|
|
b1831d7e33 | ||
|
|
b8ccb7a4c1 | ||
|
|
0eb75a41bb | ||
|
|
4cc47e3297 | ||
|
|
7bf3366041 | ||
|
|
c4b9f4bccf | ||
|
|
455c552132 | ||
|
|
f26fb51509 | ||
|
|
ab3c6576ed | ||
|
|
d1bd994113 | ||
|
|
d1548b1161 | ||
|
|
8a43f41ed6 | ||
|
|
42759e4011 | ||
|
|
27fa19eb94 | ||
|
|
426ed8589b |
@@ -2,6 +2,28 @@ Revision history for Verilator
|
||||
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
* Verilator 4.012 2019-3-23
|
||||
|
||||
*** Add +verilator+seed, bug1396. [Stan Sokorac]
|
||||
|
||||
*** Support $fread. [Leendert van Doorn]
|
||||
|
||||
*** Support void' cast on functions called as tasks, bug1383. [Al Grant]
|
||||
|
||||
*** Add IGNOREDRETURN warning, bug1383.
|
||||
|
||||
**** Report PORTSHORT errors on concat constants, bug 1400. [Will Korteland]
|
||||
|
||||
**** Fix VERILATOR_GDB being ignored, msg2860. [Yu Sheng Lin]
|
||||
|
||||
**** Fix $value$plus$args missing verilated_heavy.h. [Yi-Chung Chen]
|
||||
|
||||
**** Fix MSVC compile error, bug1406. [Benjamin Gartner]
|
||||
|
||||
**** Fix maintainer test when no Parallel::Forker, msg2630. [Enzo Chi]
|
||||
|
||||
**** Fix +1364-1995ext flags applying too late, bug1384. [Al Grant]
|
||||
|
||||
|
||||
* Verilator 4.010 2019-01-27
|
||||
|
||||
|
||||
+34
-14
@@ -85,7 +85,7 @@ if ($opt_gdbbt && !gdb_works()) {
|
||||
my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw;
|
||||
if ($opt_gdb) {
|
||||
# Generic GDB interactive
|
||||
run (("gdb"||$ENV{VERILATOR_GDB})
|
||||
run (($ENV{VERILATOR_GDB}||"gdb")
|
||||
." ".verilator_bin()
|
||||
# Note, uncomment to set breakpoints before running:
|
||||
# ." -ex 'break main'"
|
||||
@@ -399,7 +399,8 @@ detailed descriptions in L</"RUNTIME ARGUMENTS"> for more information.
|
||||
+verilator+prof+threads+file+I<filename> Set profile filename
|
||||
+verilator+prof+threads+start+I<value> Set profile starting point
|
||||
+verilator+prof+threads+window+I<value> Set profile duration
|
||||
+verilator+rand+reset+<value> Set random reset technique
|
||||
+verilator+rand+reset+I<value> Set random reset technique
|
||||
+verilator+seed+I<value> Set random seed
|
||||
+verilator+V Verbose version and config
|
||||
+verilator+version Show version and exit
|
||||
|
||||
@@ -1455,10 +1456,10 @@ Enable all code style related warning messages. This is equivalent to
|
||||
=item --x-assign unique
|
||||
|
||||
Controls the two-state value that is replaced when an assignment to X is
|
||||
encountered. --x-assign=fast, the default, converts all Xs to whatever is
|
||||
best for performance. --x-assign=0 converts all Xs to 0s, and is also fast.
|
||||
--x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
|
||||
likely to find reset bugs as active high logic will fire. --x-assign=unique
|
||||
encountered. C<--x-assign fast>, the default, converts all Xs to whatever is
|
||||
best for performance. C<--x-assign 0> converts all Xs to 0s, and is also fast.
|
||||
C<--x-assign 1> converts all Xs to 1s, this is nearly as fast as 0, but more
|
||||
likely to find reset bugs as active high logic will fire. C<--x-assign unique>
|
||||
will call a function to determine the value, this allows randomization of
|
||||
all Xs to find reset bugs and is the slowest, but safest for finding reset
|
||||
bugs in code.
|
||||
@@ -1483,13 +1484,13 @@ variables are controlled with --x-initial.
|
||||
Controls the two-state value that is used to initialize variables that are
|
||||
not otherwise initialized.
|
||||
|
||||
--x-initial=0, initializes all otherwise uninitialized variables to zero.
|
||||
C<--x-initial 0>, initializes all otherwise uninitialized variables to zero.
|
||||
|
||||
--x-initial=unique, the default, initializes variables using a function,
|
||||
C<--x-initial unique>, the default, initializes variables using a function,
|
||||
which determines the value to use each initialization. This gives greatest
|
||||
flexibility and allows finding reset bugs. See L</"Unknown states">.
|
||||
|
||||
--x-initial=fast, is best for performance, and initializes all variables to
|
||||
C<--x-initial fast>, is best for performance, and initializes all variables to
|
||||
a state Verilator determines is optimal. This may allow further code
|
||||
optimizations, but will likely hide any code bugs relating to missing
|
||||
resets.
|
||||
@@ -1599,6 +1600,11 @@ When a model was Verilated using "-x-inital unique", sets the
|
||||
initialization technique. 0 = Reset to zeros. 1 = Reset to all-ones. 2 =
|
||||
Randomize. See L</"Unknown states">.
|
||||
|
||||
=item +verilator+seed+I<value>
|
||||
|
||||
For $random and "-x-initial unique", set the random seed value. If zero or
|
||||
not specified picks a value from the system random number generator.
|
||||
|
||||
=item +verilator+V
|
||||
|
||||
Shows the verbose version, including configuration information.
|
||||
@@ -1759,8 +1765,8 @@ the examples directory in the distribution.
|
||||
=head1 BENCHMARKING & OPTIMIZATION
|
||||
|
||||
For best performance, run Verilator with the "-O3 --x-assign=fast
|
||||
--x-initial=fast --noassert" flags. The -O3 flag will require longer
|
||||
compile times, and --x-assign=fast --x-initial=fast may increase the risk
|
||||
--x-initial fast --noassert" flags. The -O3 flag will require longer
|
||||
compile times, and "--x-assign fast --x-initial fast" may increase the risk
|
||||
of reset bugs in trade for performance; see the above documentation for
|
||||
these flags.
|
||||
|
||||
@@ -3018,9 +3024,10 @@ from a four state simulator. An === comparison to X will always be false,
|
||||
so that Verilog code which checks for uninitialized logic will not fire.
|
||||
|
||||
Assigning a variable to a X will actually assign the variable to a random
|
||||
value (see the --x-assign switch.) Thus if the value is actually used, the
|
||||
random value should cause downstream errors. Integers also randomize, even
|
||||
though the Verilog 2001 specification says they initialize to zero.
|
||||
value (see the --x-assign switch and +verilator+rand+reset runtime switch.)
|
||||
Thus if the value is actually used, the random value should cause
|
||||
downstream errors. Integers also randomize, even though the Verilog 2001
|
||||
specification says they initialize to zero.
|
||||
|
||||
All variables, depending on --x-initial setting, are typically randomly
|
||||
initialized using a function. By running several random simulation runs
|
||||
@@ -3573,6 +3580,19 @@ code to a case statement, or a SystemVerilog 'unique if' or 'priority if'.
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item IGNOREDRETURN
|
||||
|
||||
Warns that a non-void function is being called as a task, and hence the
|
||||
return value is being ignored.
|
||||
|
||||
This warning is required by IEEE. The portable way to suppress this warning
|
||||
(in SystemVerilog) is to use a void cast, e.g.
|
||||
|
||||
void'(function_being_called_as_task());
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item IMPERFECTSCH
|
||||
|
||||
Warns that the scheduling of the model is not absolutely perfect, and some
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[4.010 2019-01-27],
|
||||
AC_INIT([Verilator],[4.012 2019-03-23],
|
||||
[https://www.veripool.org/verilator],
|
||||
[verilator],[https://www.veripool.org/verilator])
|
||||
# When releasing, also update header of Changes file
|
||||
|
||||
@@ -27,15 +27,19 @@ int main(int argc, char** argv, char** env) {
|
||||
|
||||
// Prevent unused variable warnings
|
||||
if (0 && argc && argv && env) {}
|
||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
// Set debug level, 0 is off, 9 is highest presently used
|
||||
// May be overridden by commandArgs
|
||||
Verilated::debug(0);
|
||||
|
||||
// Randomization reset policy
|
||||
// May be overridden by commandArgs
|
||||
Verilated::randReset(2);
|
||||
|
||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
||||
// This needs to be called before you create any model
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
|
||||
|
||||
|
||||
@@ -24,15 +24,19 @@ int sc_main(int argc, char* argv[]) {
|
||||
|
||||
// Prevent unused variable warnings
|
||||
if (0 && argc && argv) {}
|
||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
// Set debug level, 0 is off, 9 is highest presently used
|
||||
// May be overridden by commandArgs
|
||||
Verilated::debug(0);
|
||||
|
||||
// Randomization reset policy
|
||||
// May be overridden by commandArgs
|
||||
Verilated::randReset(2);
|
||||
|
||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
||||
// This needs to be called before you create any model
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
// General logfile
|
||||
ios::sync_with_stdio();
|
||||
|
||||
|
||||
+77
-9
@@ -33,7 +33,7 @@
|
||||
#include <cctype>
|
||||
#include <sys/stat.h> // mkdir
|
||||
|
||||
#if defined(WIN32) || defined(__MINGW32__)
|
||||
#if defined(_WIN32) || defined(__MINGW32__)
|
||||
# include <direct.h> // mkdir
|
||||
#endif
|
||||
|
||||
@@ -208,6 +208,7 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
|
||||
|
||||
Verilated::Serialized::Serialized() {
|
||||
s_randReset = 0;
|
||||
s_randSeed = 0;
|
||||
s_debug = 0;
|
||||
s_calcUnusedSigs = false;
|
||||
s_gotFinish = false;
|
||||
@@ -245,18 +246,25 @@ vluint64_t vl_rand64() VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL bool t_seeded = false;
|
||||
static VL_THREAD_LOCAL vluint64_t t_state[2];
|
||||
if (VL_UNLIKELY(!t_seeded)) {
|
||||
t_seeded = true;
|
||||
{
|
||||
VerilatedLockGuard lock(s_mutex);
|
||||
t_state[0] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
t_state[1] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
t_seeded = true;
|
||||
{
|
||||
VerilatedLockGuard lock(s_mutex);
|
||||
if (Verilated::randSeed() != 0) {
|
||||
t_state[0] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
|
||||
^ (static_cast<vluint64_t>(Verilated::randSeed())));
|
||||
t_state[1] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
|
||||
^ (static_cast<vluint64_t>(Verilated::randSeed())));
|
||||
} else {
|
||||
t_state[0] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
t_state[1] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
}
|
||||
// Fix state as algorithm is slow to randomize if many zeros
|
||||
// This causes a loss of ~ 1 bit of seed entropy, no big deal
|
||||
if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0];
|
||||
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Xoroshiro128+ algorithm
|
||||
vluint64_t result = t_state[0] + t_state[1];
|
||||
@@ -1376,6 +1384,59 @@ void VL_WRITEMEM_N(
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
IData VL_FREAD_I(int width, int array_lsb, int array_size,
|
||||
void* memp, IData fpi, IData start, IData count) VL_MT_SAFE {
|
||||
// While threadsafe, each thread can only access different file handles
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
if (count > (array_size - (start - array_lsb))) count = array_size - (start - array_lsb);
|
||||
// Prep for reading
|
||||
IData read_count = 0;
|
||||
IData read_elements = 0;
|
||||
int start_shift = (width-1) & ~7; // bit+7:bit gets first character
|
||||
int shift = start_shift;
|
||||
// Read the data
|
||||
// We process a character at a time, as then we don't need to deal
|
||||
// with changing buffer sizes dynamically, etc.
|
||||
while (1) {
|
||||
int c = fgetc(fp);
|
||||
if (VL_UNLIKELY(c==EOF)) break;
|
||||
// Shift value in
|
||||
IData entry = read_elements + start - array_lsb;
|
||||
if (width <= 8) {
|
||||
CData* datap = &(reinterpret_cast<CData*>(memp))[entry];
|
||||
if (shift == start_shift) { *datap = 0; }
|
||||
*datap |= (c << shift) & VL_MASK_I(width);
|
||||
} else if (width <= 16) {
|
||||
SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
|
||||
if (shift == start_shift) { *datap = 0; }
|
||||
*datap |= (c << shift) & VL_MASK_I(width);
|
||||
} else if (width <= VL_WORDSIZE) {
|
||||
IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
|
||||
if (shift == start_shift) { *datap = 0; }
|
||||
*datap |= (c << shift) & VL_MASK_I(width);
|
||||
} else if (width <= VL_QUADSIZE) {
|
||||
QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
|
||||
if (shift == start_shift) { *datap = 0; }
|
||||
*datap |= ((static_cast<QData>(c) << static_cast<QData>(shift))
|
||||
& VL_MASK_Q(width));
|
||||
} else {
|
||||
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[ entry*VL_WORDS_I(width) ];
|
||||
if (shift == start_shift) { VL_ZERO_RESET_W(width, datap); }
|
||||
datap[VL_BITWORD_I(shift)] |= (c << VL_BITBIT_I(shift));
|
||||
}
|
||||
// Prep for next
|
||||
++read_count;
|
||||
shift -= 8;
|
||||
if (shift < 0) {
|
||||
shift = start_shift;
|
||||
++read_elements;
|
||||
if (VL_UNLIKELY(read_elements >= count)) break;
|
||||
}
|
||||
}
|
||||
return read_count;
|
||||
}
|
||||
|
||||
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||
QData filename, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
WData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
@@ -1670,6 +1731,10 @@ void Verilated::randReset(int val) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_randReset = val;
|
||||
}
|
||||
void Verilated::randSeed(int val) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_randSeed = val;
|
||||
}
|
||||
void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_calcUnusedSigs = flag;
|
||||
@@ -1879,6 +1944,9 @@ void VerilatedImp::commandArgVl(const std::string& arg) {
|
||||
else if (commandArgVlValue(arg, "+verilator+rand+reset+", value/*ref*/)) {
|
||||
Verilated::randReset(atoi(value.c_str()));
|
||||
}
|
||||
else if (commandArgVlValue(arg, "+verilator+seed+", value/*ref*/)) {
|
||||
Verilated::randSeed(atoi(value.c_str()));
|
||||
}
|
||||
else if (arg == "+verilator+V") {
|
||||
versionDump(); // Someday more info too
|
||||
VL_FATAL_MT("COMMAND_LINE", 0, "", "Exiting due to command line argument (not an error)");
|
||||
|
||||
+14
-6
@@ -342,7 +342,8 @@ class Verilated {
|
||||
bool s_assertOn; ///< Assertions are enabled
|
||||
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
|
||||
// Slow path
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
int s_randSeed; ///< Random seed: 0=random
|
||||
Serialized();
|
||||
~Serialized() {}
|
||||
} s_s;
|
||||
@@ -396,6 +397,8 @@ public:
|
||||
/// 2 = Randomize all bits
|
||||
static void randReset(int val) VL_MT_SAFE;
|
||||
static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value
|
||||
static void randSeed(int val) VL_MT_SAFE;
|
||||
static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value
|
||||
|
||||
/// Enable debug of internal verilated code
|
||||
static void debug(int level) VL_MT_SAFE;
|
||||
@@ -435,7 +438,9 @@ public:
|
||||
static void flushCb(VerilatedVoidCb cb) VL_MT_SAFE;
|
||||
static void flushCall() VL_MT_SAFE;
|
||||
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs,
|
||||
/// and for parsing +verilator+ run-time arguments.
|
||||
/// This should be called before the first model is created.
|
||||
static void commandArgs(int argc, const char** argv) VL_MT_SAFE;
|
||||
static void commandArgs(int argc, char** argv) VL_MT_SAFE {
|
||||
commandArgs(argc, const_cast<const char**>(argv)); }
|
||||
@@ -560,13 +565,13 @@ extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||
/// Print a debug message from internals with standard prefix, with printf style format
|
||||
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||
|
||||
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||
|
||||
/// Init time only, so slow is fine
|
||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
||||
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
||||
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal (slow - else use VL_ZERO_W)
|
||||
|
||||
@@ -589,6 +594,9 @@ inline IData VL_FOPEN_II(IData filename, IData mode) VL_MT_SAFE {
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
extern IData VL_FREAD_I(int width, int array_lsb, int array_size,
|
||||
void* memp, IData fpi, IData start, IData count);
|
||||
|
||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP filenamep, void* memp, IData start, IData end);
|
||||
extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
|
||||
+10
-9
@@ -558,19 +558,20 @@ int AstNodeDType::widthPow2() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
||||
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
||||
// Else AstArraySel etc; search for the base
|
||||
while (nodep) {
|
||||
if (VN_IS(nodep, ArraySel)) { nodep=VN_CAST(nodep, ArraySel)->fromp(); continue; }
|
||||
else if (VN_IS(nodep, Sel)) { nodep=VN_CAST(nodep, Sel)->fromp(); continue; }
|
||||
// AstNodeSelPre stashes the associated variable under an ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
|
||||
else if (VN_IS(nodep, AttrOf)) { nodep=VN_CAST(nodep, AttrOf)->fromp(); continue; }
|
||||
if (VN_IS(nodep, ArraySel)) { nodep = VN_CAST(nodep, ArraySel)->fromp(); continue; }
|
||||
else if (VN_IS(nodep, Sel)) { nodep = VN_CAST(nodep, Sel)->fromp(); continue; }
|
||||
// AstNodeSelPre stashes the associated variable under an ATTROF
|
||||
// of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
|
||||
else if (VN_IS(nodep, AttrOf)) { nodep = VN_CAST(nodep, AttrOf)->fromp(); continue; }
|
||||
else if (VN_IS(nodep, NodePreSel)) {
|
||||
if (VN_CAST(nodep, NodePreSel)->attrp()) {
|
||||
nodep=VN_CAST(nodep, NodePreSel)->attrp();
|
||||
} else {
|
||||
nodep=VN_CAST(nodep, NodePreSel)->lhsp();
|
||||
}
|
||||
nodep = VN_CAST(nodep, NodePreSel)->attrp();
|
||||
} else {
|
||||
nodep = VN_CAST(nodep, NodePreSel)->lhsp();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
|
||||
+95
-59
@@ -927,7 +927,7 @@ class AstSelPlus : public AstNodePreSel {
|
||||
// Gets replaced during link with AstSel
|
||||
public:
|
||||
AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp)
|
||||
:AstNodePreSel(fl, fromp, bitp, widthp) {}
|
||||
: AstNodePreSel(fl, fromp, bitp, widthp) {}
|
||||
ASTNODE_NODE_FUNCS(SelPlus)
|
||||
AstNode* bitp() const { return rhsp(); }
|
||||
AstNode* widthp() const { return thsp(); }
|
||||
@@ -938,7 +938,7 @@ class AstSelMinus : public AstNodePreSel {
|
||||
// Gets replaced during link with AstSel
|
||||
public:
|
||||
AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp)
|
||||
:AstNodePreSel(fl, fromp, bitp, widthp) {}
|
||||
: AstNodePreSel(fl, fromp, bitp, widthp) {}
|
||||
ASTNODE_NODE_FUNCS(SelMinus)
|
||||
AstNode* bitp() const { return rhsp(); }
|
||||
AstNode* widthp() const { return thsp(); }
|
||||
@@ -955,8 +955,8 @@ private:
|
||||
int m_declElWidth; // If a packed array, the number of bits per element
|
||||
public:
|
||||
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
|
||||
:AstNodeTriop(fl, fromp, lsbp, widthp) {
|
||||
m_declElWidth = 1;
|
||||
: AstNodeTriop(fl, fromp, lsbp, widthp) {
|
||||
m_declElWidth = 1;
|
||||
if (VN_IS(widthp, Const)) {
|
||||
dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(),
|
||||
VN_CAST(widthp, Const)->toUInt(),
|
||||
@@ -964,9 +964,9 @@ public:
|
||||
}
|
||||
}
|
||||
AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
|
||||
:AstNodeTriop(fl, fromp,
|
||||
new AstConst(fl,lsb), new AstConst(fl,bitwidth)) {
|
||||
m_declElWidth = 1;
|
||||
: AstNodeTriop(fl, fromp,
|
||||
new AstConst(fl,lsb), new AstConst(fl,bitwidth)) {
|
||||
m_declElWidth = 1;
|
||||
dtypeSetLogicSized(bitwidth,bitwidth,AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Sel)
|
||||
@@ -1076,9 +1076,9 @@ public:
|
||||
addNOp2p(pinsp);
|
||||
}
|
||||
AstMethodSel(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
|
||||
:AstNode(fl), m_name(name) {
|
||||
setOp1p(fromp);
|
||||
addNOp2p(pinsp);
|
||||
: AstNode(fl), m_name(name) {
|
||||
setOp1p(fromp);
|
||||
addNOp2p(pinsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(MethodSel)
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
@@ -1144,9 +1144,9 @@ private:
|
||||
}
|
||||
public:
|
||||
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
|
||||
:AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
: AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
childDTypep(dtp); // Only for parser
|
||||
dtypep(NULL); // V3Width will resolve
|
||||
@@ -1154,9 +1154,9 @@ public:
|
||||
else m_declKwd = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtp)
|
||||
:AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
: AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
UASSERT(dtp,"AstVar created with no dtype");
|
||||
dtypep(dtp);
|
||||
@@ -1164,24 +1164,24 @@ public:
|
||||
else m_declKwd = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagLogicPacked, int wantwidth)
|
||||
:AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED);
|
||||
: AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED);
|
||||
m_declKwd = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagBitPacked, int wantwidth)
|
||||
:AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED);
|
||||
: AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED);
|
||||
m_declKwd = AstBasicDTypeKwd::BIT;
|
||||
}
|
||||
AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep)
|
||||
:AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
: AstNode(fl)
|
||||
, m_name(name), m_origName(name) {
|
||||
init();
|
||||
combineType(type);
|
||||
if (examplep->childDTypep()) {
|
||||
@@ -1396,9 +1396,9 @@ private:
|
||||
AstNodeModule* m_modp; // Module scope corresponds to
|
||||
public:
|
||||
AstScope(FileLine* fl, AstNodeModule* modp, const string& name,
|
||||
AstScope* aboveScopep, AstCell* aboveCellp)
|
||||
:AstNode(fl)
|
||||
,m_name(name) ,m_aboveScopep(aboveScopep) ,m_aboveCellp(aboveCellp), m_modp(modp) {}
|
||||
AstScope* aboveScopep, AstCell* aboveCellp)
|
||||
: AstNode(fl)
|
||||
,m_name(name) ,m_aboveScopep(aboveScopep) ,m_aboveCellp(aboveCellp), m_modp(modp) {}
|
||||
ASTNODE_NODE_FUNCS(Scope)
|
||||
virtual void cloneRelink();
|
||||
virtual const char* broken() const;
|
||||
@@ -1426,8 +1426,8 @@ class AstTopScope : public AstNode {
|
||||
// Children: SCOPEs
|
||||
public:
|
||||
AstTopScope(FileLine* fl, AstScope* ascopep)
|
||||
:AstNode(fl)
|
||||
{addNOp2p(ascopep);}
|
||||
: AstNode(fl)
|
||||
{addNOp2p(ascopep);}
|
||||
ASTNODE_NODE_FUNCS(TopScope)
|
||||
AstNode* stmtsp() const { return op1p(); }
|
||||
void addStmtsp(AstNode* nodep) { addOp1p(nodep); }
|
||||
@@ -1446,9 +1446,9 @@ private:
|
||||
bool m_trace:1; // Tracing is turned on for this scope
|
||||
public:
|
||||
AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp)
|
||||
:AstNode(fl)
|
||||
, m_scopep(scopep), m_varp(varp) {
|
||||
m_circular = false;
|
||||
: AstNode(fl)
|
||||
, m_scopep(scopep), m_varp(varp) {
|
||||
m_circular = false;
|
||||
m_trace = true;
|
||||
dtypeFrom(varp);
|
||||
}
|
||||
@@ -1517,10 +1517,10 @@ private:
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
public:
|
||||
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
|
||||
:AstNodeVarRef(fl, name, NULL, lvalue)
|
||||
, m_dotted(dotted) { }
|
||||
: AstNodeVarRef(fl, name, NULL, lvalue)
|
||||
, m_dotted(dotted) { }
|
||||
AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, bool lvalue)
|
||||
:AstNodeVarRef(fl, varp->name(), varp, lvalue)
|
||||
: AstNodeVarRef(fl, varp->name(), varp, lvalue)
|
||||
, m_dotted(dotted) {
|
||||
dtypeFrom(varp);
|
||||
}
|
||||
@@ -1555,16 +1555,16 @@ private:
|
||||
bool m_svImplicit; // Pin is SystemVerilog .name'ed
|
||||
public:
|
||||
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
|
||||
:AstNode(fl)
|
||||
,m_name(name), m_param(false), m_svImplicit(false) {
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
setNOp1p(exprp);
|
||||
: AstNode(fl)
|
||||
,m_name(name), m_param(false), m_svImplicit(false) {
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
setNOp1p(exprp);
|
||||
}
|
||||
AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
|
||||
:AstNode(fl), m_param(false), m_svImplicit(false) {
|
||||
m_name = varname->name();
|
||||
: AstNode(fl), m_param(false), m_svImplicit(false) {
|
||||
m_name = varname->name();
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
@@ -1903,8 +1903,8 @@ private:
|
||||
string m_name; // Name of pin
|
||||
public:
|
||||
AstPort(FileLine* fl, int pinnum, const string& name)
|
||||
:AstNode(fl)
|
||||
,m_pinNum(pinnum) ,m_name(name) {}
|
||||
: AstNode(fl)
|
||||
,m_pinNum(pinnum) ,m_name(name) {}
|
||||
ASTNODE_NODE_FUNCS(Port)
|
||||
virtual string name() const { return m_name; } // * = Port name
|
||||
int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation
|
||||
@@ -1939,7 +1939,7 @@ private:
|
||||
string m_name;
|
||||
public:
|
||||
AstParseRef(FileLine* fl, AstParseRefExp expect, const string& name, AstNode* lhsp, AstNodeFTaskRef* ftaskrefp)
|
||||
:AstNode(fl), m_expect(expect), m_name(name) { setNOp1p(lhsp); setNOp2p(ftaskrefp); }
|
||||
: AstNode(fl), m_expect(expect), m_name(name) { setNOp1p(lhsp); setNOp2p(ftaskrefp); }
|
||||
ASTNODE_NODE_FUNCS(ParseRef)
|
||||
virtual void dump(std::ostream& str);
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
@@ -1984,7 +1984,7 @@ class AstDot : public AstNode {
|
||||
// These are eliminated in the link stage
|
||||
public:
|
||||
AstDot(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
:AstNode(fl) { setOp1p(lhsp); setOp2p(rhsp); }
|
||||
: AstNode(fl) { setOp1p(lhsp); setOp2p(rhsp); }
|
||||
ASTNODE_NODE_FUNCS(Dot)
|
||||
static AstNode* newIfPkg(FileLine*fl, AstPackage* packagep, AstNode* rhsp) { // For parser, make only if non-null package
|
||||
if (!packagep) return rhsp;
|
||||
@@ -2003,7 +2003,7 @@ class AstTask : public AstNodeFTask {
|
||||
// A task inside a module
|
||||
public:
|
||||
AstTask(FileLine* fl, const string& name, AstNode* stmtp)
|
||||
:AstNodeFTask(fl, name, stmtp) {}
|
||||
: AstNodeFTask(fl, name, stmtp) {}
|
||||
ASTNODE_NODE_FUNCS(Task)
|
||||
};
|
||||
|
||||
@@ -2011,8 +2011,8 @@ class AstFunc : public AstNodeFTask {
|
||||
// A function inside a module
|
||||
public:
|
||||
AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp)
|
||||
:AstNodeFTask(fl, name, stmtp) {
|
||||
addNOp1p(fvarsp);
|
||||
: AstNodeFTask(fl, name, stmtp) {
|
||||
addNOp1p(fvarsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Func)
|
||||
virtual bool hasDType() const { return true; }
|
||||
@@ -2022,9 +2022,9 @@ class AstTaskRef : public AstNodeFTaskRef {
|
||||
// A reference to a task
|
||||
public:
|
||||
AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
|
||||
:AstNodeFTaskRef(fl, namep, pinsp) {}
|
||||
: AstNodeFTaskRef(fl, namep, pinsp) {}
|
||||
AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
|
||||
:AstNodeFTaskRef(fl, name, pinsp) {}
|
||||
: AstNodeFTaskRef(fl, name, pinsp) {}
|
||||
ASTNODE_NODE_FUNCS(TaskRef)
|
||||
virtual bool isStatement() const { return true; } // A statement, unlike FuncRef
|
||||
};
|
||||
@@ -2033,9 +2033,9 @@ class AstFuncRef : public AstNodeFTaskRef {
|
||||
// A reference to a function
|
||||
public:
|
||||
AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
|
||||
:AstNodeFTaskRef(fl, namep, pinsp) {}
|
||||
: AstNodeFTaskRef(fl, namep, pinsp) {}
|
||||
AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp)
|
||||
:AstNodeFTaskRef(fl, name, pinsp) {}
|
||||
: AstNodeFTaskRef(fl, name, pinsp) {}
|
||||
ASTNODE_NODE_FUNCS(FuncRef)
|
||||
virtual bool isStatement() const { return false; } // Not a statement, unlike TaskRef
|
||||
virtual bool hasDType() const { return true; }
|
||||
@@ -2050,7 +2050,7 @@ private:
|
||||
string m_cname; // Name of function on c side
|
||||
public:
|
||||
AstDpiExport(FileLine* fl, const string& vname, const string& cname)
|
||||
:AstNode(fl), m_name(vname), m_cname(cname) { }
|
||||
: AstNode(fl), m_name(vname), m_cname(cname) { }
|
||||
ASTNODE_NODE_FUNCS(DpiExport)
|
||||
virtual string name() const { return m_name; }
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
@@ -2741,6 +2741,42 @@ public:
|
||||
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
|
||||
};
|
||||
|
||||
class AstFRead : public AstNodeMath {
|
||||
// Parents: expr
|
||||
// Children: varrefs to load
|
||||
// Children: file which must be a varref
|
||||
// Children: low index
|
||||
// Children: count
|
||||
public:
|
||||
AstFRead(FileLine* fileline, AstNode* memp, AstNode* filep,
|
||||
AstNode* startp, AstNode* countp)
|
||||
: AstNodeMath(fileline) {
|
||||
setOp1p(memp);
|
||||
setOp2p(filep);
|
||||
setNOp3p(startp);
|
||||
setNOp4p(countp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(FRead)
|
||||
virtual string verilogKwd() const { return "$fread"; }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering
|
||||
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
|
||||
virtual bool cleanOut() { return false; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
AstNode* memp() const { return op1p(); }
|
||||
void memp(AstNode* nodep) { setOp1p(nodep); }
|
||||
AstNode* filep() const { return op2p(); }
|
||||
void filep(AstNode* nodep) { setOp2p(nodep); }
|
||||
AstNode* startp() const { return op3p(); }
|
||||
void startp(AstNode* nodep) { setNOp3p(nodep); }
|
||||
AstNode* countp() const { return op4p(); }
|
||||
void countp(AstNode* nodep) { setNOp4p(nodep); }
|
||||
};
|
||||
|
||||
class AstFScanF : public AstNodeMath {
|
||||
// Parents: expr
|
||||
// Children: file which must be a varref
|
||||
|
||||
@@ -387,6 +387,45 @@ public:
|
||||
puts(")); }\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFRead* nodep) {
|
||||
puts("VL_FREAD_I(");
|
||||
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
|
||||
putbs(",");
|
||||
bool memory = false;
|
||||
uint32_t array_lsb = 0;
|
||||
uint32_t array_size = 0;
|
||||
{
|
||||
const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef);
|
||||
if (!varrefp) { nodep->v3error(nodep->verilogKwd() << " loading non-variable"); }
|
||||
else if (VN_CAST(varrefp->varp()->dtypeSkipRefp(), BasicDType)) { }
|
||||
else if (const AstUnpackArrayDType* adtypep
|
||||
= VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||
memory = true;
|
||||
array_lsb = adtypep->lsb();
|
||||
array_size = adtypep->elementsConst();
|
||||
}
|
||||
else {
|
||||
nodep->v3error(nodep->verilogKwd()
|
||||
<< " loading other than unpacked-array variable");
|
||||
}
|
||||
}
|
||||
puts(cvtToStr(array_lsb));
|
||||
putbs(",");
|
||||
puts(cvtToStr(array_size));
|
||||
putbs(", ");
|
||||
if (!memory) puts("&(");
|
||||
iterateAndNextNull(nodep->memp());
|
||||
if (!memory) puts(")");
|
||||
putbs(", ");
|
||||
iterateAndNextNull(nodep->filep());
|
||||
putbs(", ");
|
||||
if (nodep->startp()) iterateAndNextNull(nodep->startp());
|
||||
else puts(cvtToStr(array_lsb));
|
||||
putbs(", ");
|
||||
if (nodep->countp()) iterateAndNextNull(nodep->countp());
|
||||
else puts(cvtToStr(array_size));
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstSysFuncAsTask* nodep) {
|
||||
if (!nodep->lhsp()->isWide()) puts("(void)");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
|
||||
@@ -46,9 +46,11 @@ class EmitCInlines : EmitCBaseVisitor {
|
||||
v3Global.needHeavy(true);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstValuePlusArgs* nodep) {
|
||||
v3Global.needHeavy(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// NOPs
|
||||
virtual void visit(AstNodeStmt*) {}
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) {
|
||||
iterateChildren(nodep);
|
||||
|
||||
+10
-7
@@ -49,8 +49,9 @@ public:
|
||||
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
|
||||
// Error codes:
|
||||
E_DETECTARRAY, // Error: Unsupported: Can't detect changes on arrayed variable
|
||||
E_MULTITOP, // Error: Multiple top level modules
|
||||
E_TASKNSVAR, // Error: Task I/O not simple
|
||||
E_MULTITOP, // Error: Multiple top level modules
|
||||
E_PORTSHORT, // Error: Output port is connected to a constant, electrical short
|
||||
E_TASKNSVAR, // Error: Task I/O not simple
|
||||
//
|
||||
// Warning codes:
|
||||
EC_FIRST_WARN, // Just a code so the program knows where to start warnings
|
||||
@@ -77,7 +78,8 @@ public:
|
||||
ENDLABEL, // End lable name mismatch
|
||||
GENCLK, // Generated Clock
|
||||
IFDEPTH, // If statements too deep
|
||||
IMPERFECTSCH, // Imperfect schedule (disabled by default)
|
||||
IGNOREDRETURN, // Ignoring return value (funcation as task)
|
||||
IMPERFECTSCH, // Imperfect schedule (disabled by default)
|
||||
IMPLICIT, // Implicit wire
|
||||
IMPORTSTAR, // Import::* in $unit
|
||||
IMPURE, // Impure function not being inlined
|
||||
@@ -128,9 +130,9 @@ public:
|
||||
" MIN", " INFO", " FATAL", " FATALSRC", " ERROR",
|
||||
// Boolean
|
||||
" I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE",
|
||||
// Errors
|
||||
"DETECTARRAY", "MULTITOP", "TASKNSVAR",
|
||||
// Warnings
|
||||
// Errors
|
||||
"DETECTARRAY", "MULTITOP", "PORTSHORT", "TASKNSVAR",
|
||||
// Warnings
|
||||
" EC_FIRST_WARN",
|
||||
"ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN",
|
||||
"BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
|
||||
@@ -138,7 +140,8 @@ public:
|
||||
"CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG",
|
||||
"DEFPARAM", "DECLFILENAME",
|
||||
"ENDLABEL", "GENCLK",
|
||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
|
||||
"IFDEPTH", "IGNOREDRETURN",
|
||||
"IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY",
|
||||
"LITENDIAN", "MODDUP",
|
||||
"MULTIDRIVEN",
|
||||
|
||||
@@ -91,6 +91,7 @@ protected:
|
||||
friend class V3ParseImp;
|
||||
friend class V3PreLex;
|
||||
friend class V3PreProcImp;
|
||||
friend class V3PreShellImp;
|
||||
void lineno(int num) { m_lineno = num; }
|
||||
void language(V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
|
||||
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
|
||||
|
||||
+2
-5
@@ -550,14 +550,11 @@ private:
|
||||
AstVar* pinNewVarp = pinOldVarp->clonep();
|
||||
if (!pinNewVarp) pinOldVarp->v3fatalSrc("Cloning failed");
|
||||
|
||||
AstNode* connectRefp = pinp->exprp();
|
||||
AstNode* connectRefp = pinp->exprp();
|
||||
if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) {
|
||||
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
|
||||
}
|
||||
if (pinNewVarp->direction() == VDirection::OUTPUT
|
||||
&& VN_IS(connectRefp, Const)) {
|
||||
pinp->v3error("Output port is connected to a constant pin, electrical short");
|
||||
}
|
||||
V3Inst::checkOutputShort(pinp);
|
||||
|
||||
// Propagate any attributes across the interconnect
|
||||
pinNewVarp->propagateAttrFrom(pinOldVarp);
|
||||
|
||||
+18
-7
@@ -68,10 +68,7 @@ private:
|
||||
UINFO(4," PIN "<<nodep<<endl);
|
||||
if (!nodep->exprp()) return; // No-connect
|
||||
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
|
||||
if (nodep->modVarp()->direction() == VDirection::OUTPUT
|
||||
&& VN_IS(nodep->exprp(), Const)) {
|
||||
nodep->v3error("Output port is connected to a constant pin, electrical short");
|
||||
}
|
||||
V3Inst::checkOutputShort(nodep);
|
||||
// Use user1p on the PIN to indicate we created an assign for this pin
|
||||
if (!nodep->user1SetOnce()) {
|
||||
// Simplify it
|
||||
@@ -513,8 +510,9 @@ public:
|
||||
// Done. Constant.
|
||||
} else {
|
||||
// Make a new temp wire
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||
V3Inst::checkOutputShort(pinp);
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
string newvarname = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp")
|
||||
// Prevent name conflict if both tri & non-tri add signals
|
||||
+(forTristate?"t":"")
|
||||
@@ -555,10 +553,23 @@ public:
|
||||
// Inst class functions
|
||||
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
return InstStatic::pinReconnectSimple(pinp, cellp, forTristate, alwaysCvt);
|
||||
}
|
||||
|
||||
void V3Inst::checkOutputShort(AstPin* nodep) {
|
||||
if (nodep->modVarp()->direction() == VDirection::OUTPUT) {
|
||||
if (VN_IS(nodep->exprp(), Const)
|
||||
|| VN_IS(nodep->exprp(), Extend)
|
||||
|| (VN_IS(nodep->exprp(), Concat)
|
||||
&& (VN_IS(VN_CAST(nodep->exprp(), Concat)->lhsp(), Const)))) {
|
||||
// Uses v3warn for error, as might be found multiple times
|
||||
nodep->v3warn(E_PORTSHORT, "Output port is connected to a constant pin,"
|
||||
" electrical short");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Inst class visitor
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
static void dearrayAll(AstNetlist* nodep);
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp,
|
||||
bool forTristate, bool alwaysCvt=false);
|
||||
static void checkOutputShort(AstPin* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -131,6 +131,15 @@ private:
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstFRead* nodep) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
m_setRefLvalue = true;
|
||||
iterateAndNextNull(nodep->memp());
|
||||
iterateAndNextNull(nodep->filep());
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
|
||||
@@ -210,6 +210,11 @@ private:
|
||||
} else if (AstEnumItemRef* fromp = VN_CAST(basefromp, EnumItemRef)) {
|
||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::ENUM_BASE,
|
||||
fromp->cloneTree(false)));
|
||||
} else if (VN_IS(basefromp, Replicate)) {
|
||||
// From {...}[...] syntax in IEEE 2017
|
||||
if (basefromp) { UINFO(1," Related node: "<<basefromp<<endl); }
|
||||
nodep->v3error("Unsupported: Select of concatenation");
|
||||
nodep = NULL;
|
||||
} else {
|
||||
if (basefromp) { UINFO(1," Related node: "<<basefromp<<endl); }
|
||||
nodep->v3fatalSrc("Illegal bit select; no signal/member being extracted from");
|
||||
@@ -362,6 +367,10 @@ private:
|
||||
iterateChildren(nodep);
|
||||
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
||||
}
|
||||
virtual void visit(AstFRead* nodep) {
|
||||
iterateChildren(nodep);
|
||||
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep) {
|
||||
iterateChildren(nodep);
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(WIN32) || defined(__MINGW32__)
|
||||
#if defined(_WIN32) || defined(__MINGW32__)
|
||||
# include <direct.h> // mkdir
|
||||
#endif
|
||||
|
||||
|
||||
@@ -115,17 +115,6 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||
m_fileline = new FileLine(fileline);
|
||||
m_inLibrary = inLibrary;
|
||||
|
||||
// Set language standard up front
|
||||
if (!v3Global.opt.preprocOnly()) {
|
||||
// Leting lex parse this saves us from having to specially en/decode
|
||||
// from the V3LangCode to the various Lex BEGIN states. The language
|
||||
// of this source file is updated here, in case there have been any
|
||||
// intervening +<lang>ext+ options since it was first ecountered.
|
||||
FileLine *modfileline = new FileLine(modfilename, 0);
|
||||
modfileline->language(v3Global.opt.fileLanguage(modfilename));
|
||||
ppPushText(string("`begin_keywords \"")+modfileline->language().ascii()+"\"\n");
|
||||
}
|
||||
|
||||
// Preprocess into m_ppBuffer
|
||||
bool ok = V3PreShell::preproc(fileline, modfilename, m_filterp, this, errmsg);
|
||||
if (!ok) {
|
||||
|
||||
+24
-8
@@ -102,8 +102,20 @@ protected:
|
||||
|
||||
// Preprocess
|
||||
s_filterp = filterp;
|
||||
bool ok = preprocOpen(fl, s_filterp, modname, "", errmsg);
|
||||
if (!ok) return false;
|
||||
string modfilename = preprocOpen(fl, s_filterp, modname, "", errmsg);
|
||||
if (modfilename.empty()) return false;
|
||||
|
||||
// Set language standard up front
|
||||
if (!v3Global.opt.preprocOnly()) {
|
||||
// Leting lex parse this saves us from having to specially en/decode
|
||||
// from the V3LangCode to the various Lex BEGIN states. The language
|
||||
// of this source file is updated here, in case there have been any
|
||||
// intervening +<lang>ext+ options since it was first ecountered.
|
||||
FileLine* modfileline = new FileLine(modfilename, 0);
|
||||
modfileline->language(v3Global.opt.fileLanguage(modfilename));
|
||||
V3Parse::ppPushText(parsep, (string("`begin_keywords \"")
|
||||
+modfileline->language().ascii()+"\"\n"));
|
||||
}
|
||||
|
||||
while (!s_preprocp->isEof()) {
|
||||
string line = s_preprocp->getline();
|
||||
@@ -116,12 +128,15 @@ protected:
|
||||
if (modname[0]=='/' || modname[0]=='\\') {
|
||||
fl->v3warn(INCABSPATH,"Suggest `include with absolute path be made relative, and use +include: "<<modname);
|
||||
}
|
||||
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()), "Cannot find include file: ");
|
||||
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()),
|
||||
"Cannot find include file: ");
|
||||
}
|
||||
|
||||
bool preprocOpen(FileLine* fl, V3InFilter* filterp, const string& modname, const string& lastpath,
|
||||
const string& errmsg) { // Error message or "" to suppress
|
||||
// Returns true if successful
|
||||
private:
|
||||
string preprocOpen(FileLine* fl, V3InFilter* filterp,
|
||||
const string& modname, const string& lastpath,
|
||||
const string& errmsg) { // Error message or "" to suppress
|
||||
// Returns filename if successful
|
||||
// Try a pure name in case user has a bogus `filename they don't expect
|
||||
string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg);
|
||||
if (filename=="") {
|
||||
@@ -131,13 +146,14 @@ protected:
|
||||
|
||||
filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg);
|
||||
}
|
||||
if (filename=="") return false; // Not found
|
||||
if (filename=="") return ""; // Not found
|
||||
|
||||
UINFO(2," Reading "<<filename<<endl);
|
||||
s_preprocp->openFile(fl, filterp, filename);
|
||||
return true;
|
||||
return filename;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
V3PreShellImp() {}
|
||||
~V3PreShellImp() {}
|
||||
|
||||
+9
-5
@@ -1170,11 +1170,15 @@ private:
|
||||
nodep->replaceWith(outrefp);
|
||||
// Insert new statements
|
||||
visitp = insertBeforeStmt(nodep, beginp);
|
||||
} else {
|
||||
// outvscp maybe non-NULL if calling a function in a taskref,
|
||||
// but if so we want to simply ignore the function result
|
||||
nodep->replaceWith(beginp);
|
||||
}
|
||||
} else {
|
||||
if (nodep->taskp()->isFunction()) {
|
||||
nodep->v3warn(IGNOREDRETURN,
|
||||
"Ignoring return value of non-void function (IEEE 2017 13.4.1)");
|
||||
}
|
||||
// outvscp maybe non-NULL if calling a function in a taskref,
|
||||
// but if so we want to simply ignore the function result
|
||||
nodep->replaceWith(beginp);
|
||||
}
|
||||
// Cleanup
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
UINFO(4," FTask REF Done.\n");
|
||||
|
||||
@@ -2232,6 +2232,19 @@ private:
|
||||
userIterateAndNext(nodep->strgp(), WidthVP(SELF,BOTH).p());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFRead* nodep) {
|
||||
if (m_vup->prelim()) {
|
||||
nodep->dtypeSetSigned32(); // Spec says integer return
|
||||
userIterateAndNext(nodep->memp(), WidthVP(SELF,BOTH).p());
|
||||
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
|
||||
if (nodep->startp()) {
|
||||
iterateCheckSigned32(nodep, "$fread start", nodep->startp(), BOTH);
|
||||
}
|
||||
if (nodep->countp()) {
|
||||
iterateCheckSigned32(nodep, "$fread count", nodep->countp(), BOTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep) {
|
||||
if (m_vup->prelim()) {
|
||||
nodep->dtypeSetSigned32(); // Spec says integer return
|
||||
@@ -3172,6 +3185,18 @@ private:
|
||||
underp = iterateCheck(nodep,"file_descriptor",underp,SELF,FINAL,expDTypep,EXTEND_EXP);
|
||||
if (underp) {} // cppcheck
|
||||
}
|
||||
void iterateCheckSigned32(AstNode* nodep, const char* side, AstNode* underp, Stage stage) {
|
||||
// Coerce child to signed32 if not already. Child is self-determined
|
||||
// underp may change as a result of replacement
|
||||
if (stage & PRELIM) {
|
||||
underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p());
|
||||
}
|
||||
if (stage & FINAL) {
|
||||
AstNodeDType* expDTypep = nodep->findSigned32DType();
|
||||
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
||||
}
|
||||
if (underp) {} // cppcheck
|
||||
}
|
||||
void iterateCheckReal(AstNode* nodep, const char* side, AstNode* underp, Stage stage) {
|
||||
// Coerce child to real if not already. Child is self-determined
|
||||
// e.g. nodep=ADDD, underp=ADD in ADDD(ADD(a,b), real-CONST)
|
||||
|
||||
+2
-2
@@ -325,7 +325,7 @@ sub clean_input {
|
||||
foreach my $line (@linesin) {
|
||||
$l++;
|
||||
if ($line =~ /BISONPRE_NOT/) {
|
||||
($line =~ s/BISONPRE_NOT\((\S+)\)\s*({[^}]+})\s*$//)
|
||||
($line =~ s/BISONPRE_NOT\((\S+)\)\s*(\{[^}]+})\s*$//)
|
||||
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
|
||||
my $endtok = $1; my $action = $2;
|
||||
my @endtoks = split (/,/, $endtok);
|
||||
@@ -412,7 +412,7 @@ sub _bisonpre_copy {
|
||||
my $l = shift;
|
||||
my $depth = shift;
|
||||
while ($text =~ /BISONPRE_COPY/) {
|
||||
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
|
||||
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*\{([^}]*)}\s*\)/{HERE}/)
|
||||
or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
|
||||
my $once = $1; my $rule = $2; my $code = $3;
|
||||
$Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
|
||||
|
||||
@@ -227,6 +227,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"$finish" { FL; return yD_FINISH; }
|
||||
"$floor" { FL; return yD_FLOOR; }
|
||||
"$fopen" { FL; return yD_FOPEN; }
|
||||
"$fread" { FL; return yD_FREAD; }
|
||||
"$fscanf" { FL; return yD_FSCANF; }
|
||||
"$fullskew" { FL; return yaTIMINGSPEC; }
|
||||
"$fwrite" { FL; return yD_FWRITE; }
|
||||
|
||||
+27
-3
@@ -475,6 +475,7 @@ class AstSenTree;
|
||||
%token<fl> yD_FINISH "$finish"
|
||||
%token<fl> yD_FLOOR "$floor"
|
||||
%token<fl> yD_FOPEN "$fopen"
|
||||
%token<fl> yD_FREAD "$fread"
|
||||
%token<fl> yD_FSCANF "$fscanf"
|
||||
%token<fl> yD_FWRITE "$fwrite"
|
||||
%token<fl> yD_HIGH "$high"
|
||||
@@ -2390,8 +2391,21 @@ statement_item<nodep>: // IEEE: statement_item
|
||||
// // Below under expr
|
||||
//
|
||||
// // IEEE: subroutine_call_statement
|
||||
//UNSUP yVOID yP_TICK '(' function_subroutine_callNoMethod ')' ';' { }
|
||||
//UNSUP yVOID yP_TICK '(' expr '.' function_subroutine_callNoMethod ')' ';' { }
|
||||
// // IEEE says we then expect a function call
|
||||
// // (function_subroutine_callNoMethod), but rest of
|
||||
// // the code expects an AstTask when used as a statement,
|
||||
// // so parse as if task
|
||||
// // Alternative would be shim with new AstVoidStmt.
|
||||
| yVOID yP_TICK '(' task_subroutine_callNoMethod ')' ';'
|
||||
{ $$ = $4;
|
||||
FileLine* newfl = new FileLine($$->fileline());
|
||||
newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true);
|
||||
$$->fileline(newfl); }
|
||||
| yVOID yP_TICK '(' expr '.' task_subroutine_callNoMethod ')' ';'
|
||||
{ $$ = new AstDot($5, $4, $6);
|
||||
FileLine* newfl = new FileLine($6->fileline());
|
||||
newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true);
|
||||
$6->fileline(newfl); }
|
||||
// // Expr included here to resolve our not knowing what is a method call
|
||||
// // Expr here must result in a subroutine_call
|
||||
| task_subroutine_callNoMethod ';' { $$ = $1; }
|
||||
@@ -2815,6 +2829,9 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
|
||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
||||
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||
| yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,NULL,NULL); }
|
||||
| yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,NULL); }
|
||||
| yD_FREAD '(' idClassSel ',' expr ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,$9); }
|
||||
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
|
||||
@@ -3278,6 +3295,13 @@ exprOkLvalue<nodep>: // expression that's also OK to use as a variable_lvalue
|
||||
// // IEEE: concatenation/constant_concatenation
|
||||
// // Replicate(1) required as otherwise "{a}" would not be self-determined
|
||||
| '{' cateList '}' { $$ = new AstReplicate($1,$2,1); }
|
||||
| '{' cateList '}' '[' expr ']' { $$ = new AstSelBit($4, new AstReplicate($1,$2,1), $5); }
|
||||
| '{' cateList '}' '[' constExpr ':' constExpr ']'
|
||||
{ $$ = new AstSelExtract($4, new AstReplicate($1,$2,1), $5, $7); }
|
||||
| '{' cateList '}' '[' expr yP_PLUSCOLON constExpr ']'
|
||||
{ $$ = new AstSelPlus($4, new AstReplicate($1,$2,1), $5, $7); }
|
||||
| '{' cateList '}' '[' expr yP_MINUSCOLON constExpr ']'
|
||||
{ $$ = new AstSelMinus($4, new AstReplicate($1,$2,1), $5, $7); }
|
||||
// // IEEE: assignment_pattern_expression
|
||||
// // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id/data_type]
|
||||
// // We allow more here than the spec requires
|
||||
@@ -3961,7 +3985,7 @@ void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) {
|
||||
}
|
||||
|
||||
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
|
||||
FileLine* newfl = new FileLine (fileline);
|
||||
FileLine* newfl = new FileLine(fileline);
|
||||
newfl->warnOff(V3ErrorCode::WIDTH, true);
|
||||
AstNode* nodep = new AstConst(newfl, V3Number(newfl));
|
||||
// Adding a NOT is less work than figuring out how wide to make it
|
||||
|
||||
+66
-55
@@ -77,8 +77,8 @@ our $Opt_Unsupported;
|
||||
our $Opt_Verilation = 1;
|
||||
our @Opt_Driver_Verilator_Flags;
|
||||
|
||||
Getopt::Long::config ("pass_through");
|
||||
if (! GetOptions (
|
||||
Getopt::Long::config("pass_through");
|
||||
if (! GetOptions(
|
||||
"benchmark:i" => sub { $opt_benchmark = $_[1] ? $_[1] : 1; },
|
||||
"debug" => \&debug,
|
||||
#debugi see parameter()
|
||||
@@ -136,6 +136,9 @@ if ($#opt_tests<0) {
|
||||
if ($#opt_tests>=2 && $opt_jobs>=2) {
|
||||
# Without this tests such as t_debug_sigsegv_bt_bad.pl will occasionally
|
||||
# block on input and cause a SIGSTOP, then a "fg" was needed to resume testing.
|
||||
if (!$::Have_Forker) {
|
||||
print STDERR "driver.pl: NO_FORKER: For faster testing 'sudo cpan install Parallel::Forker'\n";
|
||||
}
|
||||
print STDERR "== Many jobs; redirecting STDIN\n";
|
||||
open(STDIN, "+>/dev/null");
|
||||
}
|
||||
@@ -153,7 +156,7 @@ foreach my $testpl (@opt_tests) {
|
||||
}
|
||||
}
|
||||
|
||||
$Fork->wait_all(); # Wait for all children to finish
|
||||
$Fork->wait_all(); # Wait for all children to finish
|
||||
|
||||
sub one_test {
|
||||
my @params = @_;
|
||||
@@ -173,9 +176,10 @@ sub one_test {
|
||||
# Don't put anything other than _exit after _read,
|
||||
# as may call _exit via another path
|
||||
$test->_exit;
|
||||
},
|
||||
run_on_finish => sub {
|
||||
my $test = VTest->new(@params);
|
||||
},
|
||||
run_on_finish => sub {
|
||||
# RUnning in context of parent
|
||||
my $test = VTest->new(@params);
|
||||
$test->_read_status;
|
||||
if ($test->ok) {
|
||||
$OkCnt++;
|
||||
@@ -218,7 +222,7 @@ exit(10) if $FailCnt;
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub debug {
|
||||
@@ -310,7 +314,7 @@ use Cwd;
|
||||
use Data::Dumper;
|
||||
use File::Spec;
|
||||
|
||||
use vars qw ($Self $Self);
|
||||
use vars qw($Self $Self);
|
||||
use strict;
|
||||
|
||||
sub new {
|
||||
@@ -366,9 +370,9 @@ sub new {
|
||||
.($opt_benchmark ? " +define+TEST_BENCHMARK=$opt_benchmark":"")
|
||||
.($opt_trace ? " +define+WAVES=1":"")
|
||||
))],
|
||||
v_flags2 => [], # Overridden in some sim files
|
||||
v_other_filenames => [], # After the filename so we can spec multiple files
|
||||
all_run_flags => [],
|
||||
v_flags2 => [], # Overridden in some sim files
|
||||
v_other_filenames => [], # After the filename so we can spec multiple files
|
||||
all_run_flags => [],
|
||||
pli_flags => ["-I$ENV{VERILATOR_ROOT}/include/vltstd -fPIC -shared"
|
||||
.(($^O eq "darwin" )
|
||||
? " -Wl,-undefined,dynamic_lookup"
|
||||
@@ -390,9 +394,9 @@ sub new {
|
||||
# IV
|
||||
iv => 0,
|
||||
iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")],
|
||||
iv_flags2 => [], # Overridden in some sim files
|
||||
iv_pli => 0, # need to use pli
|
||||
iv_run_flags => [],
|
||||
iv_flags2 => [], # Overridden in some sim files
|
||||
iv_pli => 0, # need to use pli
|
||||
iv_run_flags => [],
|
||||
# VCS
|
||||
vcs => 0,
|
||||
vcs_flags => [split(/\s+/,"+vcs+lic+wait +cli -debug_access +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")],
|
||||
@@ -420,9 +424,9 @@ sub new {
|
||||
verilator_flags2 => [],
|
||||
verilator_flags3 => ["--clk clk"],
|
||||
verilator_make_gcc => 1,
|
||||
verilated_debug => $Opt_Verilated_Debug,
|
||||
stdout_filename => undef, # Redirect stdout
|
||||
%$self};
|
||||
verilated_debug => $Opt_Verilated_Debug,
|
||||
stdout_filename => undef, # Redirect stdout
|
||||
%$self};
|
||||
bless $self, $class;
|
||||
|
||||
$self->{vlt_all} = $self->{vlt} || $self->{vltmt}; # Any Verilator scenario
|
||||
@@ -435,8 +439,8 @@ sub new {
|
||||
$self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
|
||||
($self->{top_filename} ||= $self->{pl_filename}) =~ s/\.pl$//;
|
||||
($self->{golden_filename} ||= $self->{pl_filename}) =~ s/\.pl$/.out/;
|
||||
if (-e ($self->{top_filename}.".vhd")) { # If VHDL file exists
|
||||
$self->{vhdl} = 1;
|
||||
if (-e ($self->{top_filename}.".vhd")) { # If VHDL file exists
|
||||
$self->{vhdl} = 1;
|
||||
$self->{top_filename} .= ".vhd";
|
||||
} else {
|
||||
$self->{top_filename} .= ".v";
|
||||
@@ -580,7 +584,7 @@ sub _read_status {
|
||||
|
||||
sub compile_vlt_flags {
|
||||
my $self = (ref $_[0]? shift : $Self);
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
return 1 if $self->errors || $self->skips || $self->unsupporteds;
|
||||
|
||||
my $checkflags = join(' ',@{$param{v_flags}},
|
||||
@@ -637,7 +641,7 @@ sub compile_vlt_flags {
|
||||
|
||||
sub compile {
|
||||
my $self = (ref $_[0]? shift : $Self);
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
return 1 if $self->errors || $self->skips || $self->unsupporteds;
|
||||
$self->oprint("Compile\n");
|
||||
|
||||
@@ -676,7 +680,7 @@ sub compile {
|
||||
@{$param{ghdl_flags}},
|
||||
@{$param{ghdl_flags2}},
|
||||
#@{$param{v_flags}}, # Not supported
|
||||
#@{$param{v_flags2}}, # Not supported
|
||||
#@{$param{v_flags2}}, # Not supported
|
||||
$param{top_filename},
|
||||
$param{top_shell_filename},
|
||||
@{$param{v_other_filenames}},
|
||||
@@ -809,8 +813,8 @@ sub compile {
|
||||
sub execute {
|
||||
my $self = (ref $_[0]? shift : $Self);
|
||||
return 1 if $self->errors || $self->skips || $self->unsupporteds;
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
# params may be expect or {tool}_expect
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
# params may be expect or {tool}_expect
|
||||
$self->oprint("Run\n");
|
||||
|
||||
my $run_env = $param{run_env};
|
||||
@@ -845,10 +849,11 @@ sub execute {
|
||||
@{$param{iv_run_flags}},
|
||||
@{$param{all_run_flags}},
|
||||
);
|
||||
if ($param{iv_pli}) {
|
||||
unshift @cmd, "vvp -n -m $self->{obj_dir}/libvpi.so"; # don't enter command line on $stop, include vpi
|
||||
}
|
||||
$self->_run(logfile=>"$self->{obj_dir}/iv_sim.log",
|
||||
if ($param{iv_pli}) {
|
||||
# don't enter command line on $stop, include vpi
|
||||
unshift @cmd, "vvp -n -m $self->{obj_dir}/libvpi.so";
|
||||
}
|
||||
$self->_run(logfile=>"$self->{obj_dir}/iv_sim.log",
|
||||
fails=>$param{fails},
|
||||
cmd=> \@cmd,
|
||||
%param,
|
||||
@@ -900,7 +905,7 @@ sub execute {
|
||||
$param{executable} ||= "$self->{obj_dir}/$param{VM_PREFIX}";
|
||||
$self->_run(logfile=>"$self->{obj_dir}/vlt_sim.log",
|
||||
cmd=>[($run_env
|
||||
.($opt_gdbsim ? ("gdb"||$ENV{VERILATOR_GDB})." " : "")
|
||||
.($opt_gdbsim ? ($ENV{VERILATOR_GDB}||"gdb")." " : "")
|
||||
.$param{executable}
|
||||
.($opt_gdbsim ? " -ex 'run " : "")),
|
||||
@{$param{all_run_flags}},
|
||||
@@ -921,7 +926,7 @@ sub inline_checks {
|
||||
return 1 if $self->errors || $self->skips || $self->unsupporteds;
|
||||
return 1 if !$self->{vlt_all};
|
||||
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
my %param = (%{$self}, @_); # Default arguments are from $self
|
||||
|
||||
my $covfn = $Self->{coverage_filename};
|
||||
my $contents = $self->file_contents($covfn);
|
||||
@@ -1057,9 +1062,9 @@ sub _run {
|
||||
if ($param{logfile}) {
|
||||
$logfh = IO::File->new(">$param{logfile}") or die "%Error: Can't open $param{logfile}";
|
||||
}
|
||||
my $pid=fork();
|
||||
if ($pid) { # Parent
|
||||
close CHILDWR;
|
||||
my $pid=fork();
|
||||
if ($pid) { # Parent
|
||||
close CHILDWR;
|
||||
while (1) {
|
||||
my $buf = '';
|
||||
my $got = sysread PARENTRD,$buf,10000;
|
||||
@@ -1069,9 +1074,9 @@ sub _run {
|
||||
}
|
||||
close PARENTRD;
|
||||
close $logfh if $logfh;
|
||||
}
|
||||
else { # Child
|
||||
close PARENTRD;
|
||||
}
|
||||
else { # Child
|
||||
close PARENTRD;
|
||||
close $logfh if $logfh;
|
||||
# Reset signals
|
||||
$SIG{ALRM} = 'DEFAULT';
|
||||
@@ -1082,9 +1087,9 @@ sub _run {
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
system "$command";
|
||||
exit ($? ? 10 : 0); # $?<<8 misses coredumps
|
||||
}
|
||||
waitpid($pid,0);
|
||||
exit($? ? 10 : 0); # $?<<8 misses coredumps
|
||||
}
|
||||
waitpid($pid,0);
|
||||
$status = $? || 0;
|
||||
}
|
||||
flush STDOUT;
|
||||
@@ -1131,8 +1136,8 @@ sub _run {
|
||||
$wholefile =~ s/^- [a-z.0-9]+:\d+:[^\n]+\n//mig;
|
||||
$wholefile =~ s/^dot [^\n]+\n//mig;
|
||||
|
||||
# Compare
|
||||
my $quoted = quotemeta ($param{expect});
|
||||
# Compare
|
||||
my $quoted = quotemeta($param{expect});
|
||||
my $ok = ($wholefile eq $param{expect}
|
||||
|| _try_regex($wholefile, $param{expect}) == 1
|
||||
|| $wholefile =~ /$quoted/ms);
|
||||
@@ -1503,9 +1508,9 @@ sub _read_inputs_v {
|
||||
if ($line =~ /^\s*(function|task|endmodule)/) {
|
||||
$get_sigs = 0;
|
||||
}
|
||||
}
|
||||
if ($line =~ /^\s*module\s+t\b/) { # Ignore any earlier inputs; Module 't' has precedence
|
||||
%inputs = ();
|
||||
}
|
||||
if ($line =~ /^\s*module\s+t\b/) { # Ignore any earlier inputs; Module 't' has precedence
|
||||
%inputs = ();
|
||||
$get_sigs = 1;
|
||||
}
|
||||
}
|
||||
@@ -1685,7 +1690,7 @@ sub _vcd_read {
|
||||
my $self = (ref $_[0]? shift : $Self);
|
||||
my $filename = shift;
|
||||
my $data = {};
|
||||
my $fh = IO::File->new ("<$filename");
|
||||
my $fh = IO::File->new("<$filename");
|
||||
if (!$fh) { warn "%Error: $! $filename\n"; return $data; }
|
||||
my @hier = ($data);
|
||||
my $lasthier;
|
||||
@@ -1813,8 +1818,14 @@ sub new {
|
||||
sub schedule {
|
||||
my $self = shift;
|
||||
my %params = (@_);
|
||||
&{$params{run_on_start}}();
|
||||
&{$params{run_on_finish}}();
|
||||
|
||||
if (my $pid = fork()) { # Parent
|
||||
waitpid($pid, 0);
|
||||
} else { # Child
|
||||
$params{run_on_start}->($self);
|
||||
exit(0); # Don't close anything
|
||||
}
|
||||
$params{run_on_finish}->($self);
|
||||
return $self;
|
||||
}
|
||||
sub max_proc {}
|
||||
@@ -1865,7 +1876,7 @@ successful tests and then returns 1 as its result.
|
||||
Both C<compile> and C<execute> take an optional argument hash table to
|
||||
control their behavior. For example:
|
||||
|
||||
compile (
|
||||
compile(
|
||||
verilator_flags2 => ["--lint-only"],
|
||||
fails => 1,
|
||||
);
|
||||
@@ -1981,7 +1992,7 @@ require their own C++ or SystemC test harness. This is commonly given the
|
||||
same name as the test, but with .cpp as suffix
|
||||
(C<test_regress/t/t_EXAMPLE.cpp>). This can be specified as follows:
|
||||
|
||||
compile (
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"], );
|
||||
@@ -1994,22 +2005,22 @@ Verilog C<$stop>) as that signals an error.
|
||||
If termination should be triggered from the C++ wrapper, the following code
|
||||
can be used:
|
||||
|
||||
vl_fatal (__FILE__, __LINE__, "dut", "<error message goes here>");
|
||||
exit (1);
|
||||
vl_fatal(__FILE__, __LINE__, "dut", "<error message goes here>");
|
||||
exit(1);
|
||||
|
||||
This can be particularly useful if checking that the Verilator model has
|
||||
not unexpectedly terminated.
|
||||
|
||||
if (Verilated::gotFinish ()) {
|
||||
vl_fatal (__FILE__, __LINE__, "dut", "<error message goes here>");
|
||||
exit (1);
|
||||
if (Verilated::gotFinish()) {
|
||||
vl_fatal(__FILE__, __LINE__, "dut", "<error message goes here>");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Where it might be useful for a test to produce output, it should qualify
|
||||
this with C<TEST_VERBOSE>. For example in Verilog:
|
||||
|
||||
`ifdef TEST_VERBOSE
|
||||
$write ("Conditional generate if MASK [%1d] = %d\n", g, MASK[g]);
|
||||
$write("Conditional generate if MASK [%1d] = %d\n", g, MASK[g]);
|
||||
`endif
|
||||
|
||||
Or in a hand-written C++ wrapper:
|
||||
|
||||
@@ -15,8 +15,8 @@ module t (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
reg [63:0] crc;
|
||||
`verilator_file_descriptor fd;
|
||||
`verilator_file_descriptor fdtmp;
|
||||
integer fd;
|
||||
integer fdtmp;
|
||||
|
||||
t_case_write1_tasks tasks ();
|
||||
|
||||
@@ -33,14 +33,14 @@ module t (/*AUTOARG*/
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
if (cyc==1) begin
|
||||
crc <= 64'h00000000_00000097;
|
||||
crc <= 64'h00000000_00000097;
|
||||
$write("%s", {"Open ", `STRINGIFY(`TEST_OBJ_DIR), "/t_case_write1_logger.log\n"});
|
||||
fdtmp = $fopen({`STRINGIFY(`TEST_OBJ_DIR), "/t_case_write1_logger.log"}, "w");
|
||||
fd <= fdtmp;
|
||||
end
|
||||
if (cyc==90) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ module t (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
reg [63:0] crc;
|
||||
`verilator_file_descriptor fd;
|
||||
`verilator_file_descriptor fdtmp;
|
||||
integer fd;
|
||||
integer fdtmp;
|
||||
|
||||
t_case_write2_tasks tasks ();
|
||||
|
||||
@@ -33,14 +33,14 @@ module t (/*AUTOARG*/
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
if (cyc==1) begin
|
||||
crc <= 64'h00000000_00000097;
|
||||
crc <= 64'h00000000_00000097;
|
||||
$write("%s", {"Open ", `STRINGIFY(`TEST_OBJ_DIR), "/t_case_write2_logger.log\n"});
|
||||
fdtmp = $fopen({`STRINGIFY(`TEST_OBJ_DIR), "/t_case_write2_logger.log"}, "w");
|
||||
fd <= fdtmp;
|
||||
end
|
||||
if (cyc==90) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -46,7 +46,9 @@ module t (/*AUTOARG*/);
|
||||
// Test loop
|
||||
initial begin
|
||||
// bug963
|
||||
// verilator lint_off IGNOREDRETURN
|
||||
dpii_clear();
|
||||
// verilator lint_on IGNOREDRETURN
|
||||
j = 0;
|
||||
for (i=0; i<64; i++) begin
|
||||
if (i[0])
|
||||
|
||||
@@ -50,12 +50,15 @@ module t;
|
||||
if (n !== 10) $stop;
|
||||
|
||||
// Functions called as tasks
|
||||
// verilator lint_off IGNOREDRETURN
|
||||
rglobal = 32'h4;
|
||||
if (inc_and_return(32'h2) != 32'h6) $stop;
|
||||
if (rglobal !== 32'h6) $stop;
|
||||
rglobal = 32'h6;
|
||||
|
||||
inc_and_return(32'h3);
|
||||
if (rglobal !== 32'h9) $stop;
|
||||
// verilator lint_on IGNOREDRETURN
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
initial begin
|
||||
// verilator lint_off IGNOREDRETURN
|
||||
func(0, 1'b1);
|
||||
end
|
||||
|
||||
|
||||
Executable
+20
@@ -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 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,36 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
|
||||
module t (clk);
|
||||
input clk;
|
||||
|
||||
int side_effect;
|
||||
|
||||
function int f1;
|
||||
input int in;
|
||||
f1 = in + 1;
|
||||
side_effect += in + 1;
|
||||
endfunction
|
||||
|
||||
initial begin
|
||||
int got;
|
||||
side_effect = 1;
|
||||
//
|
||||
got = f1(10);
|
||||
if (got != 11) $stop;
|
||||
if (side_effect != 12) $stop;
|
||||
// verilator lint_off IGNOREDRETURN
|
||||
f1(20);
|
||||
// verilator lint_on IGNOREDRETURN
|
||||
if (side_effect != 33) $stop;
|
||||
//
|
||||
void'(f1(30));
|
||||
if (side_effect != 64) $stop;
|
||||
//
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,3 @@
|
||||
%Warning-IGNOREDRETURN: t/t_func_void_bad.v:25: Ignoring return value of non-void function (IEEE 2017 13.4.1)
|
||||
%Warning-IGNOREDRETURN: Use "/* verilator lint_off IGNOREDRETURN */" and lint_on around source to disable this message.
|
||||
%Error: Exiting due to
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,35 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
|
||||
module t (clk);
|
||||
input clk;
|
||||
|
||||
int side_effect;
|
||||
|
||||
function int f1;
|
||||
input int in;
|
||||
f1 = in + 1;
|
||||
side_effect += in + 1;
|
||||
endfunction
|
||||
|
||||
initial begin
|
||||
int got;
|
||||
side_effect = 1;
|
||||
//
|
||||
got = f1(10);
|
||||
if (got != 11) $stop;
|
||||
if (side_effect != 12) $stop;
|
||||
//
|
||||
f1(20);
|
||||
if (side_effect != 33) $stop;
|
||||
//
|
||||
// void'f1(30);
|
||||
// if (side_effect != 64) $stop;
|
||||
//
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
# This is a compile only test.
|
||||
compile(
|
||||
v_flags2 => ["+1364-2005ext+v"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,12 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// A test of the +verilog2001ext+ and +verilog2005ext+ flags.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
// verilator lint_off SYMRSVDWORD
|
||||
|
||||
module t(input do);
|
||||
t_langext_order_sub sub (.do(do));
|
||||
endmodule
|
||||
@@ -0,0 +1,11 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// A test of the +verilog2001ext+ and +verilog2005ext+ flags.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
// verilator lint_off SYMRSVDWORD
|
||||
|
||||
module t_langext_order_sub(input do);
|
||||
endmodule
|
||||
@@ -0,0 +1,2 @@
|
||||
%Error-PORTSHORT: t/t_lint_setout_bad.v:16: Output port is connected to a constant pin, electrical short
|
||||
%Error: Exiting due to
|
||||
@@ -15,9 +15,7 @@ compile(
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
expect =>
|
||||
'%Error: t/t_lint_setout_bad.v:\d+: Output port is connected to a constant pin, electrical short
|
||||
.*',
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
%Error-PORTSHORT: t/t_lint_setout_bad.v:16: Output port is connected to a constant pin, electrical short
|
||||
%Error: Exiting due to
|
||||
@@ -17,9 +17,7 @@ compile(
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
expect =>
|
||||
'%Error: t/t_lint_setout_bad.v:\d+: Output port is connected to a constant pin, electrical short
|
||||
.*',
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
%Error-PORTSHORT: t/t_lint_subout_bad.v:11: Output port is connected to a constant pin, electrical short
|
||||
%Error-PORTSHORT: t/t_lint_subout_bad.v:12: Output port is connected to a constant pin, electrical short
|
||||
%Error-PORTSHORT: t/t_lint_subout_bad.v:10: Output port is connected to a constant pin, electrical short
|
||||
%Error: Exiting due to
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 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.
|
||||
|
||||
scenarios(vlt_all => 1);
|
||||
|
||||
compile(
|
||||
# No --lint-only as got compile error
|
||||
verilator_flags2 => ["--trace"],
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
// verilator lint_off UNDRIVEN
|
||||
|
||||
module t();
|
||||
wire sig;
|
||||
sub sub0(.out(33'b0));
|
||||
sub sub1(.out({32'b0, sig}));
|
||||
sub sub2(.out({32'b1, sig}));
|
||||
endmodule
|
||||
|
||||
module sub(output reg [32 : 0] out);
|
||||
endmodule
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2019 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.
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,58 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [3:0] a = crc[3:0];
|
||||
wire [3:0] b = crc[19:16];
|
||||
|
||||
// TEST
|
||||
wire [3:0] out1 = {a,b}[2 +: 4];
|
||||
wire [3:0] out2 = {a,b}[5 -: 4];
|
||||
wire [3:0] out3 = {a,b}[5 : 2];
|
||||
wire [0:0] out4 = {a,b}[2];
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {51'h0, out4, out3, out2, out1};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h4afe43fb79d7b71e
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
scenarios(vlt_all => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
all_run_flags => ["+verilator+seed+5 +SEED=fffffff4"],
|
||||
fails => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
all_run_flags => ["+verilator+seed+6 +SEED=fffffff2"],
|
||||
fails => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,17 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
integer r = $random;
|
||||
integer ex;
|
||||
if ($value$plusargs("SEED=%x", ex) !== 1) $stop;
|
||||
`checkh(r, ex);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -8,7 +8,7 @@
|
||||
`define STRINGIFY(x) `"x`"
|
||||
|
||||
module t;
|
||||
`verilator_file_descriptor file;
|
||||
integer file;
|
||||
|
||||
integer chars;
|
||||
reg [1*8:1] letterl;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
`define STRINGIFY(x) `"x`"
|
||||
|
||||
module t;
|
||||
`verilator_file_descriptor infile, outfile;
|
||||
integer infile, outfile;
|
||||
integer count, a;
|
||||
|
||||
initial begin
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
Dump:
|
||||
r_i: 00010203
|
||||
r_upb: 0e 0d 0c 0b 0a 09 08 07 06 05 04
|
||||
r_dnb: 19 18 17 16 15 14 13 12 11 10 0f
|
||||
r_ups: 2e2f 2c2d 2a2b 2829 2627 2425 2223 2021 1e1f 1c1d 1a1b
|
||||
r_dns: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0041 0243 0445
|
||||
r_upi: 6e6f7071 6a6b6c6d 66676869 62636465 5e5f6061 5a5b5c5d 56575859 52535455 4e4f5051 4a4b4c4d 46474849
|
||||
r_dni: 72737475 76777879 7a7b7c7d 7e7f8081 02838485 06878889 0a8b8c8d 0e8f9091 12939495 16979899 1a9b9c9d
|
||||
r_upq: 2eeff0f1f2f3f4f5 26e7e8e9eaebeced 1edfe0e1e2e3e4e5 16d7d8d9dadbdcdd 0ecfd0d1d2d3d4d5 06c7c8c9cacbcccd 3ebfc0c1c2c3c4c5 36b7b8b9babbbcbd 2eafb0b1b2b3b4b5 26a7a8a9aaabacad 1e9fa0a1a2a3a4a5
|
||||
r_dnq: 36f7f8f9fafbfcfd 3eff000102030405 060708090a0b0c0d 0e0f101112131415 161718191a1b1c1d 1e1f202122232425 262728292a2b2c2d 2e2f303132333435 363738393a3b3c3d 3e3f404142434445 064748494a4b4c4d
|
||||
r_upw: a8a9aaabacadaeafb0 9fa0a1a2a3a4a5a6a7 969798999a9b9c9d9e 8d8e8f909192939495 8485868788898a8b8c 7b7c7d7e7f80818283 72737475767778797a 696a6b6c6d6e6f7071 606162636465666768 5758595a5b5c5d5e5f 4e4f50515253545556
|
||||
r_dnw: b1b2b3b4b5b6b7b8b9 babbbcbdbebfc0c1c2 c3c4c5c6c7c8c9cacb cccdcecfd0d1d2d3d4 d5d6d7d8d9dadbdcdd dedfe0e1e2e3e4e5e6 e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8 f9fafbfcfdfeff0001 02030405060708090a 0b0c0d0e0f10111213
|
||||
|
||||
Dump:
|
||||
r_i: ffffffff
|
||||
r_upb: 05 04 03 02 01 00 ff ff ff ff ff
|
||||
r_dnb: ff ff ff ff ff ff ff ff ff ff ff
|
||||
r_ups: 3fff 3fff 3fff 3fff 0809 0607 3fff 3fff 3fff 3fff 3fff
|
||||
r_dns: 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff
|
||||
r_upi: 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff
|
||||
r_dni: 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff
|
||||
r_upq: 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff
|
||||
r_dnq: 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff
|
||||
r_upw: ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff
|
||||
r_dnw: ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff
|
||||
|
||||
*-* All Finished *-*
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2019 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.
|
||||
use IO::File;
|
||||
#use Data::Dumper;
|
||||
use strict;
|
||||
use vars qw($Self);
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
sub gen {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new(">$filename");
|
||||
for (my $copy=0; $copy<32; ++$copy) {
|
||||
for (my $i=0; $i<=255; ++$i) {
|
||||
$fh->print(chr($i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gen("$Self->{obj_dir}/t_sys_fread.mem");
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,87 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
//======================================================================
|
||||
|
||||
module t;
|
||||
integer file;
|
||||
integer r_i;
|
||||
byte r_upb[20:10];
|
||||
byte r_dnb[20:10];
|
||||
reg [13:0] r_ups[20:10];
|
||||
reg [13:0] r_dns[10:20];
|
||||
reg [30:0] r_upi[20:10];
|
||||
reg [30:0] r_dni[10:20];
|
||||
reg [61:0] r_upq[20:10];
|
||||
reg [61:0] r_dnq[10:20];
|
||||
reg [71:0] r_upw[20:10];
|
||||
reg [71:0] r_dnw[10:20];
|
||||
|
||||
task clear;
|
||||
// Initialize memories to zero,
|
||||
// avoid differences between 2-state and 4-state.
|
||||
r_i = ~0;
|
||||
foreach (r_upb[i]) r_upb[i] = ~0;
|
||||
foreach (r_dnb[i]) r_dnb[i] = ~0;
|
||||
foreach (r_ups[i]) r_ups[i] = ~0;
|
||||
foreach (r_dns[i]) r_dns[i] = ~0;
|
||||
foreach (r_upi[i]) r_upi[i] = ~0;
|
||||
foreach (r_dni[i]) r_dni[i] = ~0;
|
||||
foreach (r_upq[i]) r_upq[i] = ~0;
|
||||
foreach (r_dnq[i]) r_dnq[i] = ~0;
|
||||
foreach (r_upw[i]) r_upw[i] = ~0;
|
||||
foreach (r_dnw[i]) r_dnw[i] = ~0;
|
||||
|
||||
// Open file
|
||||
$fclose(file);
|
||||
file = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_fread.mem"}, "r");
|
||||
if ($feof(file)) $stop;
|
||||
endtask
|
||||
|
||||
task dump;
|
||||
$write("Dump:");
|
||||
$write("\n r_i:"); $write(" %x",r_i);
|
||||
$write("\n r_upb:"); foreach (r_upb[i]) $write(" %x", r_upb[i]);
|
||||
$write("\n r_dnb:"); foreach (r_dnb[i]) $write(" %x", r_dnb[i]);
|
||||
$write("\n r_ups:"); foreach (r_ups[i]) $write(" %x", r_ups[i]);
|
||||
$write("\n r_dns:"); foreach (r_dns[i]) $write(" %x", r_dns[i]);
|
||||
$write("\n r_upi:"); foreach (r_upi[i]) $write(" %x", r_upi[i]);
|
||||
$write("\n r_dni:"); foreach (r_dni[i]) $write(" %x", r_dni[i]);
|
||||
$write("\n r_upq:"); foreach (r_upq[i]) $write(" %x", r_upq[i]);
|
||||
$write("\n r_dnq:"); foreach (r_dnq[i]) $write(" %x", r_dnq[i]);
|
||||
$write("\n r_upw:"); foreach (r_upw[i]) $write(" %x", r_upw[i]);
|
||||
$write("\n r_dnw:"); foreach (r_dnw[i]) $write(" %x", r_dnw[i]);
|
||||
$write("\n\n");
|
||||
endtask
|
||||
|
||||
integer code;
|
||||
|
||||
initial begin
|
||||
clear;
|
||||
code = $fread(r_i, file); `checkd(code, 4);
|
||||
code = $fread(r_upb, file); `checkd(code, 11);
|
||||
code = $fread(r_dnb, file); `checkd(code, 11);
|
||||
code = $fread(r_ups, file); `checkd(code, 22);
|
||||
code = $fread(r_dns, file); `checkd(code, 22);
|
||||
code = $fread(r_upi, file); `checkd(code, 44);
|
||||
code = $fread(r_dni, file); `checkd(code, 44);
|
||||
code = $fread(r_upq, file); `checkd(code, 88);
|
||||
code = $fread(r_dnq, file); `checkd(code, 88);
|
||||
code = $fread(r_upw, file); `checkd(code, 99);
|
||||
code = $fread(r_dnw, file); `checkd(code, 99);
|
||||
dump;
|
||||
|
||||
clear;
|
||||
code = $fread(r_upb, file, 15); `checkd(code, 6);
|
||||
code = $fread(r_ups, file, 15, 2); `checkd(code, 4);
|
||||
dump;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user