Compare commits

...
20 Commits
Author SHA1 Message Date
Wilson Snyder a7aa8820e1 Version bump 2019-03-23 21:00:07 -04:00
Wilson Snyder 2582a83376 Unsupported error on select of concatenation 2019-03-13 19:52:23 -04:00
Wilson Snyder 0094cd7a81 Internals: Spacing fixes. No functional change. 2019-03-13 19:47:47 -04:00
Wilson Snyder d9b33d74a4 Support void' cast on functions called as tasks, bug1383. 2019-03-10 15:12:20 -04:00
Wilson Snyder 539a773ea7 Add IGNOREDRETURN warning. 2019-03-10 14:57:01 -04:00
Wilson Snyder b1831d7e33 Fix +1364-1995ext flags applying too late, bug1384. 2019-03-10 14:09:22 -04:00
Wilson Snyder b8ccb7a4c1 Fix maintainer test when no Parallel::Forker, msg2630. 2019-03-10 12:14:58 -04:00
Wilson Snyder 0eb75a41bb Fix perl 5.38 warning. 2019-03-10 12:14:02 -04:00
Wilson Snyder 4cc47e3297 Tests: Cleanup spacing/style. No functional change. 2019-03-10 09:25:23 -04:00
Wilson Snyder 7bf3366041 Support . 2019-03-07 20:56:53 -05:00
Wilson Snyder c4b9f4bccf Tests: Remove old verilator_file_descriptor 2019-03-07 18:29:44 -05:00
Wilson Snyder 455c552132 Fix MSVC compile error, bug1406. 2019-03-04 20:29:01 -05:00
Wilson Snyder f26fb51509 Commentary, bug1339. 2019-03-01 20:14:48 -05:00
Wilson Snyder ab3c6576ed Report PORTSHORT errors on concat constants, bug 1400. 2019-02-27 21:06:07 -05:00
Wilson Snyder d1bd994113 Commentary, bug1399. 2019-02-26 18:56:13 -05:00
Wilson Snyder d1548b1161 Commentary 2019-02-26 18:24:46 -05:00
Wilson Snyder 8a43f41ed6 Fix $value$plus$args missing verilated_heavy.h. 2019-02-15 18:33:52 -05:00
Wilson Snyder 42759e4011 Fix VERILATOR_GDB being ignored, msg2860. 2019-02-12 18:20:40 -05:00
Wilson Snyder 27fa19eb94 Add +verilator+seed, bug1396. 2019-02-04 20:28:17 -05:00
Wilson Snyder 426ed8589b devel release 2019-01-28 07:30:42 -05:00
56 changed files with 1002 additions and 226 deletions
+22
View File
@@ -2,6 +2,28 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks! 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 * Verilator 4.010 2019-01-27
+34 -14
View File
@@ -85,7 +85,7 @@ if ($opt_gdbbt && !gdb_works()) {
my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw; my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw;
if ($opt_gdb) { if ($opt_gdb) {
# Generic GDB interactive # Generic GDB interactive
run (("gdb"||$ENV{VERILATOR_GDB}) run (($ENV{VERILATOR_GDB}||"gdb")
." ".verilator_bin() ." ".verilator_bin()
# Note, uncomment to set breakpoints before running: # Note, uncomment to set breakpoints before running:
# ." -ex 'break main'" # ." -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+file+I<filename> Set profile filename
+verilator+prof+threads+start+I<value> Set profile starting point +verilator+prof+threads+start+I<value> Set profile starting point
+verilator+prof+threads+window+I<value> Set profile duration +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+V Verbose version and config
+verilator+version Show version and exit +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 =item --x-assign unique
Controls the two-state value that is replaced when an assignment to X is 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 encountered. C<--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. best for performance. C<--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 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. --x-assign=unique 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 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 all Xs to find reset bugs and is the slowest, but safest for finding reset
bugs in code. 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 Controls the two-state value that is used to initialize variables that are
not otherwise initialized. 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 which determines the value to use each initialization. This gives greatest
flexibility and allows finding reset bugs. See L</"Unknown states">. 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 a state Verilator determines is optimal. This may allow further code
optimizations, but will likely hide any code bugs relating to missing optimizations, but will likely hide any code bugs relating to missing
resets. 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 = initialization technique. 0 = Reset to zeros. 1 = Reset to all-ones. 2 =
Randomize. See L</"Unknown states">. 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 =item +verilator+V
Shows the verbose version, including configuration information. Shows the verbose version, including configuration information.
@@ -1759,8 +1765,8 @@ the examples directory in the distribution.
=head1 BENCHMARKING & OPTIMIZATION =head1 BENCHMARKING & OPTIMIZATION
For best performance, run Verilator with the "-O3 --x-assign=fast For best performance, run Verilator with the "-O3 --x-assign=fast
--x-initial=fast --noassert" flags. The -O3 flag will require longer --x-initial fast --noassert" flags. The -O3 flag will require longer
compile times, and --x-assign=fast --x-initial=fast may increase the risk 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 of reset bugs in trade for performance; see the above documentation for
these flags. 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. 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 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 value (see the --x-assign switch and +verilator+rand+reset runtime switch.)
random value should cause downstream errors. Integers also randomize, even Thus if the value is actually used, the random value should cause
though the Verilog 2001 specification says they initialize to zero. 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 All variables, depending on --x-initial setting, are typically randomly
initialized using a function. By running several random simulation runs 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 Disabled by default as this is a code style warning; it will simulate
correctly. 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 =item IMPERFECTSCH
Warns that the scheduling of the model is not absolutely perfect, and some Warns that the scheduling of the model is not absolutely perfect, and some
+1 -1
View File
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel]) #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], [https://www.veripool.org/verilator],
[verilator],[https://www.veripool.org/verilator]) [verilator],[https://www.veripool.org/verilator])
# When releasing, also update header of Changes file # When releasing, also update header of Changes file
+6 -2
View File
@@ -27,15 +27,19 @@ int main(int argc, char** argv, char** env) {
// Prevent unused variable warnings // Prevent unused variable warnings
if (0 && argc && argv && env) {} 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 // Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs
Verilated::debug(0); Verilated::debug(0);
// Randomization reset policy // Randomization reset policy
// May be overridden by commandArgs
Verilated::randReset(2); 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" // 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 Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
+6 -2
View File
@@ -24,15 +24,19 @@ int sc_main(int argc, char* argv[]) {
// Prevent unused variable warnings // Prevent unused variable warnings
if (0 && argc && argv) {} 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 // Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs
Verilated::debug(0); Verilated::debug(0);
// Randomization reset policy // Randomization reset policy
// May be overridden by commandArgs
Verilated::randReset(2); 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 // General logfile
ios::sync_with_stdio(); ios::sync_with_stdio();
+77 -9
View File
@@ -33,7 +33,7 @@
#include <cctype> #include <cctype>
#include <sys/stat.h> // mkdir #include <sys/stat.h> // mkdir
#if defined(WIN32) || defined(__MINGW32__) #if defined(_WIN32) || defined(__MINGW32__)
# include <direct.h> // mkdir # include <direct.h> // mkdir
#endif #endif
@@ -208,6 +208,7 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
Verilated::Serialized::Serialized() { Verilated::Serialized::Serialized() {
s_randReset = 0; s_randReset = 0;
s_randSeed = 0;
s_debug = 0; s_debug = 0;
s_calcUnusedSigs = false; s_calcUnusedSigs = false;
s_gotFinish = 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 bool t_seeded = false;
static VL_THREAD_LOCAL vluint64_t t_state[2]; static VL_THREAD_LOCAL vluint64_t t_state[2];
if (VL_UNLIKELY(!t_seeded)) { if (VL_UNLIKELY(!t_seeded)) {
t_seeded = true; t_seeded = true;
{ {
VerilatedLockGuard lock(s_mutex); VerilatedLockGuard lock(s_mutex);
t_state[0] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32) if (Verilated::randSeed() != 0) {
^ (static_cast<vluint64_t>(vl_sys_rand32()))); t_state[0] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
t_state[1] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32) ^ (static_cast<vluint64_t>(Verilated::randSeed())));
^ (static_cast<vluint64_t>(vl_sys_rand32()))); 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 // Fix state as algorithm is slow to randomize if many zeros
// This causes a loss of ~ 1 bit of seed entropy, no big deal // 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[0]) < 10) t_state[0] = ~t_state[0];
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1]; if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
} }
} }
// Xoroshiro128+ algorithm // Xoroshiro128+ algorithm
vluint64_t result = t_state[0] + t_state[1]; vluint64_t result = t_state[0] + t_state[1];
@@ -1376,6 +1384,59 @@ void VL_WRITEMEM_N(
fclose(fp); 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, 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 { QData filename, void* memp, IData start, IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, filename); WData fnw[2]; VL_SET_WQ(fnw, filename);
@@ -1670,6 +1731,10 @@ void Verilated::randReset(int val) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
s_s.s_randReset = val; 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 { void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
s_s.s_calcUnusedSigs = flag; 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*/)) { else if (commandArgVlValue(arg, "+verilator+rand+reset+", value/*ref*/)) {
Verilated::randReset(atoi(value.c_str())); 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") { else if (arg == "+verilator+V") {
versionDump(); // Someday more info too versionDump(); // Someday more info too
VL_FATAL_MT("COMMAND_LINE", 0, "", "Exiting due to command line argument (not an error)"); VL_FATAL_MT("COMMAND_LINE", 0, "", "Exiting due to command line argument (not an error)");
+14 -6
View File
@@ -342,7 +342,8 @@ class Verilated {
bool s_assertOn; ///< Assertions are enabled bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
// Slow path // 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();
~Serialized() {} ~Serialized() {}
} s_s; } s_s;
@@ -396,6 +397,8 @@ public:
/// 2 = Randomize all bits /// 2 = Randomize all bits
static void randReset(int val) VL_MT_SAFE; static void randReset(int val) VL_MT_SAFE;
static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value 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 /// Enable debug of internal verilated code
static void debug(int level) VL_MT_SAFE; static void debug(int level) VL_MT_SAFE;
@@ -435,7 +438,9 @@ public:
static void flushCb(VerilatedVoidCb cb) VL_MT_SAFE; static void flushCb(VerilatedVoidCb cb) VL_MT_SAFE;
static void flushCall() 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, const char** argv) VL_MT_SAFE;
static void commandArgs(int argc, char** argv) VL_MT_SAFE { static void commandArgs(int argc, char** argv) VL_MT_SAFE {
commandArgs(argc, const_cast<const char**>(argv)); } 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 /// 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 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 IData VL_RANDOM_I(int obits); ///< Randomize a signal
extern QData VL_RANDOM_Q(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 extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
/// Init time only, so slow is fine /// Init time only, so slow is fine
extern IData VL_RAND_RESET_I(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 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_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) 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 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, extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP filenamep, void* memp, IData start, IData end); WDataInP filenamep, void* memp, IData start, IData end);
extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords, extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
+10 -9
View File
@@ -558,19 +558,20 @@ int AstNodeDType::widthPow2() const {
return 1; 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 // Else AstArraySel etc; search for the base
while (nodep) { while (nodep) {
if (VN_IS(nodep, ArraySel)) { nodep=VN_CAST(nodep, ArraySel)->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; } 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 // AstNodeSelPre stashes the associated variable under an ATTROF
else if (VN_IS(nodep, AttrOf)) { nodep=VN_CAST(nodep, AttrOf)->fromp(); continue; } // 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)) { else if (VN_IS(nodep, NodePreSel)) {
if (VN_CAST(nodep, NodePreSel)->attrp()) { if (VN_CAST(nodep, NodePreSel)->attrp()) {
nodep=VN_CAST(nodep, NodePreSel)->attrp(); nodep = VN_CAST(nodep, NodePreSel)->attrp();
} else { } else {
nodep=VN_CAST(nodep, NodePreSel)->lhsp(); nodep = VN_CAST(nodep, NodePreSel)->lhsp();
} }
continue; continue;
} }
else break; else break;
+95 -59
View File
@@ -927,7 +927,7 @@ class AstSelPlus : public AstNodePreSel {
// Gets replaced during link with AstSel // Gets replaced during link with AstSel
public: public:
AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp)
:AstNodePreSel(fl, fromp, bitp, widthp) {} : AstNodePreSel(fl, fromp, bitp, widthp) {}
ASTNODE_NODE_FUNCS(SelPlus) ASTNODE_NODE_FUNCS(SelPlus)
AstNode* bitp() const { return rhsp(); } AstNode* bitp() const { return rhsp(); }
AstNode* widthp() const { return thsp(); } AstNode* widthp() const { return thsp(); }
@@ -938,7 +938,7 @@ class AstSelMinus : public AstNodePreSel {
// Gets replaced during link with AstSel // Gets replaced during link with AstSel
public: public:
AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp)
:AstNodePreSel(fl, fromp, bitp, widthp) {} : AstNodePreSel(fl, fromp, bitp, widthp) {}
ASTNODE_NODE_FUNCS(SelMinus) ASTNODE_NODE_FUNCS(SelMinus)
AstNode* bitp() const { return rhsp(); } AstNode* bitp() const { return rhsp(); }
AstNode* widthp() const { return thsp(); } AstNode* widthp() const { return thsp(); }
@@ -955,8 +955,8 @@ private:
int m_declElWidth; // If a packed array, the number of bits per element int m_declElWidth; // If a packed array, the number of bits per element
public: public:
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp) AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
:AstNodeTriop(fl, fromp, lsbp, widthp) { : AstNodeTriop(fl, fromp, lsbp, widthp) {
m_declElWidth = 1; m_declElWidth = 1;
if (VN_IS(widthp, Const)) { if (VN_IS(widthp, Const)) {
dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(), dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(),
VN_CAST(widthp, Const)->toUInt(), VN_CAST(widthp, Const)->toUInt(),
@@ -964,9 +964,9 @@ public:
} }
} }
AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth) AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
:AstNodeTriop(fl, fromp, : AstNodeTriop(fl, fromp,
new AstConst(fl,lsb), new AstConst(fl,bitwidth)) { new AstConst(fl,lsb), new AstConst(fl,bitwidth)) {
m_declElWidth = 1; m_declElWidth = 1;
dtypeSetLogicSized(bitwidth,bitwidth,AstNumeric::UNSIGNED); dtypeSetLogicSized(bitwidth,bitwidth,AstNumeric::UNSIGNED);
} }
ASTNODE_NODE_FUNCS(Sel) ASTNODE_NODE_FUNCS(Sel)
@@ -1076,9 +1076,9 @@ public:
addNOp2p(pinsp); addNOp2p(pinsp);
} }
AstMethodSel(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) AstMethodSel(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
:AstNode(fl), m_name(name) { : AstNode(fl), m_name(name) {
setOp1p(fromp); setOp1p(fromp);
addNOp2p(pinsp); addNOp2p(pinsp);
} }
ASTNODE_NODE_FUNCS(MethodSel) ASTNODE_NODE_FUNCS(MethodSel)
virtual string name() const { return m_name; } // * = Var name virtual string name() const { return m_name; } // * = Var name
@@ -1144,9 +1144,9 @@ private:
} }
public: public:
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
:AstNode(fl) : AstNode(fl)
, m_name(name), m_origName(name) { , m_name(name), m_origName(name) {
init(); init();
combineType(type); combineType(type);
childDTypep(dtp); // Only for parser childDTypep(dtp); // Only for parser
dtypep(NULL); // V3Width will resolve dtypep(NULL); // V3Width will resolve
@@ -1154,9 +1154,9 @@ public:
else m_declKwd = AstBasicDTypeKwd::LOGIC; else m_declKwd = AstBasicDTypeKwd::LOGIC;
} }
AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtp) AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtp)
:AstNode(fl) : AstNode(fl)
, m_name(name), m_origName(name) { , m_name(name), m_origName(name) {
init(); init();
combineType(type); combineType(type);
UASSERT(dtp,"AstVar created with no dtype"); UASSERT(dtp,"AstVar created with no dtype");
dtypep(dtp); dtypep(dtp);
@@ -1164,24 +1164,24 @@ public:
else m_declKwd = AstBasicDTypeKwd::LOGIC; else m_declKwd = AstBasicDTypeKwd::LOGIC;
} }
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagLogicPacked, int wantwidth) AstVar(FileLine* fl, AstVarType type, const string& name, VFlagLogicPacked, int wantwidth)
:AstNode(fl) : AstNode(fl)
, m_name(name), m_origName(name) { , m_name(name), m_origName(name) {
init(); init();
combineType(type); combineType(type);
dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED); dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED);
m_declKwd = AstBasicDTypeKwd::LOGIC; m_declKwd = AstBasicDTypeKwd::LOGIC;
} }
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagBitPacked, int wantwidth) AstVar(FileLine* fl, AstVarType type, const string& name, VFlagBitPacked, int wantwidth)
:AstNode(fl) : AstNode(fl)
, m_name(name), m_origName(name) { , m_name(name), m_origName(name) {
init(); init();
combineType(type); combineType(type);
dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED); dtypeSetLogicSized(wantwidth,wantwidth,AstNumeric::UNSIGNED);
m_declKwd = AstBasicDTypeKwd::BIT; m_declKwd = AstBasicDTypeKwd::BIT;
} }
AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep) AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep)
:AstNode(fl) : AstNode(fl)
, m_name(name), m_origName(name) { , m_name(name), m_origName(name) {
init(); init();
combineType(type); combineType(type);
if (examplep->childDTypep()) { if (examplep->childDTypep()) {
@@ -1396,9 +1396,9 @@ private:
AstNodeModule* m_modp; // Module scope corresponds to AstNodeModule* m_modp; // Module scope corresponds to
public: public:
AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope(FileLine* fl, AstNodeModule* modp, const string& name,
AstScope* aboveScopep, AstCell* aboveCellp) AstScope* aboveScopep, AstCell* aboveCellp)
:AstNode(fl) : AstNode(fl)
,m_name(name) ,m_aboveScopep(aboveScopep) ,m_aboveCellp(aboveCellp), m_modp(modp) {} ,m_name(name) ,m_aboveScopep(aboveScopep) ,m_aboveCellp(aboveCellp), m_modp(modp) {}
ASTNODE_NODE_FUNCS(Scope) ASTNODE_NODE_FUNCS(Scope)
virtual void cloneRelink(); virtual void cloneRelink();
virtual const char* broken() const; virtual const char* broken() const;
@@ -1426,8 +1426,8 @@ class AstTopScope : public AstNode {
// Children: SCOPEs // Children: SCOPEs
public: public:
AstTopScope(FileLine* fl, AstScope* ascopep) AstTopScope(FileLine* fl, AstScope* ascopep)
:AstNode(fl) : AstNode(fl)
{addNOp2p(ascopep);} {addNOp2p(ascopep);}
ASTNODE_NODE_FUNCS(TopScope) ASTNODE_NODE_FUNCS(TopScope)
AstNode* stmtsp() const { return op1p(); } AstNode* stmtsp() const { return op1p(); }
void addStmtsp(AstNode* nodep) { addOp1p(nodep); } void addStmtsp(AstNode* nodep) { addOp1p(nodep); }
@@ -1446,9 +1446,9 @@ private:
bool m_trace:1; // Tracing is turned on for this scope bool m_trace:1; // Tracing is turned on for this scope
public: public:
AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp) AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp)
:AstNode(fl) : AstNode(fl)
, m_scopep(scopep), m_varp(varp) { , m_scopep(scopep), m_varp(varp) {
m_circular = false; m_circular = false;
m_trace = true; m_trace = true;
dtypeFrom(varp); dtypeFrom(varp);
} }
@@ -1517,10 +1517,10 @@ private:
string m_inlinedDots; // Dotted hierarchy flattened out string m_inlinedDots; // Dotted hierarchy flattened out
public: public:
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue) AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
:AstNodeVarRef(fl, name, NULL, lvalue) : AstNodeVarRef(fl, name, NULL, lvalue)
, m_dotted(dotted) { } , m_dotted(dotted) { }
AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, bool lvalue) 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) { , m_dotted(dotted) {
dtypeFrom(varp); dtypeFrom(varp);
} }
@@ -1555,16 +1555,16 @@ private:
bool m_svImplicit; // Pin is SystemVerilog .name'ed bool m_svImplicit; // Pin is SystemVerilog .name'ed
public: public:
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
:AstNode(fl) : AstNode(fl)
,m_name(name), m_param(false), m_svImplicit(false) { ,m_name(name), m_param(false), m_svImplicit(false) {
m_pinNum = pinNum; m_pinNum = pinNum;
m_modVarp = NULL; m_modVarp = NULL;
m_modPTypep = NULL; m_modPTypep = NULL;
setNOp1p(exprp); setNOp1p(exprp);
} }
AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
:AstNode(fl), m_param(false), m_svImplicit(false) { : AstNode(fl), m_param(false), m_svImplicit(false) {
m_name = varname->name(); m_name = varname->name();
m_pinNum = pinNum; m_pinNum = pinNum;
m_modVarp = NULL; m_modVarp = NULL;
m_modPTypep = NULL; m_modPTypep = NULL;
@@ -1903,8 +1903,8 @@ private:
string m_name; // Name of pin string m_name; // Name of pin
public: public:
AstPort(FileLine* fl, int pinnum, const string& name) AstPort(FileLine* fl, int pinnum, const string& name)
:AstNode(fl) : AstNode(fl)
,m_pinNum(pinnum) ,m_name(name) {} ,m_pinNum(pinnum) ,m_name(name) {}
ASTNODE_NODE_FUNCS(Port) ASTNODE_NODE_FUNCS(Port)
virtual string name() const { return m_name; } // * = Port name virtual string name() const { return m_name; } // * = Port name
int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation
@@ -1939,7 +1939,7 @@ private:
string m_name; string m_name;
public: public:
AstParseRef(FileLine* fl, AstParseRefExp expect, const string& name, AstNode* lhsp, AstNodeFTaskRef* ftaskrefp) 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) ASTNODE_NODE_FUNCS(ParseRef)
virtual void dump(std::ostream& str); virtual void dump(std::ostream& str);
virtual string name() const { return m_name; } // * = Var name virtual string name() const { return m_name; } // * = Var name
@@ -1984,7 +1984,7 @@ class AstDot : public AstNode {
// These are eliminated in the link stage // These are eliminated in the link stage
public: public:
AstDot(FileLine* fl, AstNode* lhsp, AstNode* rhsp) AstDot(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
:AstNode(fl) { setOp1p(lhsp); setOp2p(rhsp); } : AstNode(fl) { setOp1p(lhsp); setOp2p(rhsp); }
ASTNODE_NODE_FUNCS(Dot) ASTNODE_NODE_FUNCS(Dot)
static AstNode* newIfPkg(FileLine*fl, AstPackage* packagep, AstNode* rhsp) { // For parser, make only if non-null package static AstNode* newIfPkg(FileLine*fl, AstPackage* packagep, AstNode* rhsp) { // For parser, make only if non-null package
if (!packagep) return rhsp; if (!packagep) return rhsp;
@@ -2003,7 +2003,7 @@ class AstTask : public AstNodeFTask {
// A task inside a module // A task inside a module
public: public:
AstTask(FileLine* fl, const string& name, AstNode* stmtp) AstTask(FileLine* fl, const string& name, AstNode* stmtp)
:AstNodeFTask(fl, name, stmtp) {} : AstNodeFTask(fl, name, stmtp) {}
ASTNODE_NODE_FUNCS(Task) ASTNODE_NODE_FUNCS(Task)
}; };
@@ -2011,8 +2011,8 @@ class AstFunc : public AstNodeFTask {
// A function inside a module // A function inside a module
public: public:
AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp) AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp)
:AstNodeFTask(fl, name, stmtp) { : AstNodeFTask(fl, name, stmtp) {
addNOp1p(fvarsp); addNOp1p(fvarsp);
} }
ASTNODE_NODE_FUNCS(Func) ASTNODE_NODE_FUNCS(Func)
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
@@ -2022,9 +2022,9 @@ class AstTaskRef : public AstNodeFTaskRef {
// A reference to a task // A reference to a task
public: public:
AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
:AstNodeFTaskRef(fl, namep, pinsp) {} : AstNodeFTaskRef(fl, namep, pinsp) {}
AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp) AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
:AstNodeFTaskRef(fl, name, pinsp) {} : AstNodeFTaskRef(fl, name, pinsp) {}
ASTNODE_NODE_FUNCS(TaskRef) ASTNODE_NODE_FUNCS(TaskRef)
virtual bool isStatement() const { return true; } // A statement, unlike FuncRef virtual bool isStatement() const { return true; } // A statement, unlike FuncRef
}; };
@@ -2033,9 +2033,9 @@ class AstFuncRef : public AstNodeFTaskRef {
// A reference to a function // A reference to a function
public: public:
AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
:AstNodeFTaskRef(fl, namep, pinsp) {} : AstNodeFTaskRef(fl, namep, pinsp) {}
AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp)
:AstNodeFTaskRef(fl, name, pinsp) {} : AstNodeFTaskRef(fl, name, pinsp) {}
ASTNODE_NODE_FUNCS(FuncRef) ASTNODE_NODE_FUNCS(FuncRef)
virtual bool isStatement() const { return false; } // Not a statement, unlike TaskRef virtual bool isStatement() const { return false; } // Not a statement, unlike TaskRef
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
@@ -2050,7 +2050,7 @@ private:
string m_cname; // Name of function on c side string m_cname; // Name of function on c side
public: public:
AstDpiExport(FileLine* fl, const string& vname, const string& cname) 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) ASTNODE_NODE_FUNCS(DpiExport)
virtual string name() const { return m_name; } virtual string name() const { return m_name; }
virtual void name(const string& name) { m_name = name; } virtual void name(const string& name) { m_name = name; }
@@ -2741,6 +2741,42 @@ public:
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } 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 { class AstFScanF : public AstNodeMath {
// Parents: expr // Parents: expr
// Children: file which must be a varref // Children: file which must be a varref
+39
View File
@@ -387,6 +387,45 @@ public:
puts(")); }\n"); 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) { virtual void visit(AstSysFuncAsTask* nodep) {
if (!nodep->lhsp()->isWide()) puts("(void)"); if (!nodep->lhsp()->isWide()) puts("(void)");
iterateAndNextNull(nodep->lhsp()); iterateAndNextNull(nodep->lhsp());
+4 -2
View File
@@ -46,9 +46,11 @@ class EmitCInlines : EmitCBaseVisitor {
v3Global.needHeavy(true); v3Global.needHeavy(true);
} }
} }
virtual void visit(AstValuePlusArgs* nodep) {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
// NOPs
virtual void visit(AstNodeStmt*) {}
// Default // Default
virtual void visit(AstNode* nodep) { virtual void visit(AstNode* nodep) {
iterateChildren(nodep); iterateChildren(nodep);
+10 -7
View File
@@ -49,8 +49,9 @@ public:
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE) I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
// Error codes: // Error codes:
E_DETECTARRAY, // Error: Unsupported: Can't detect changes on arrayed variable E_DETECTARRAY, // Error: Unsupported: Can't detect changes on arrayed variable
E_MULTITOP, // Error: Multiple top level modules E_MULTITOP, // Error: Multiple top level modules
E_TASKNSVAR, // Error: Task I/O not simple E_PORTSHORT, // Error: Output port is connected to a constant, electrical short
E_TASKNSVAR, // Error: Task I/O not simple
// //
// Warning codes: // Warning codes:
EC_FIRST_WARN, // Just a code so the program knows where to start warnings EC_FIRST_WARN, // Just a code so the program knows where to start warnings
@@ -77,7 +78,8 @@ public:
ENDLABEL, // End lable name mismatch ENDLABEL, // End lable name mismatch
GENCLK, // Generated Clock GENCLK, // Generated Clock
IFDEPTH, // If statements too deep 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 IMPLICIT, // Implicit wire
IMPORTSTAR, // Import::* in $unit IMPORTSTAR, // Import::* in $unit
IMPURE, // Impure function not being inlined IMPURE, // Impure function not being inlined
@@ -128,9 +130,9 @@ public:
" MIN", " INFO", " FATAL", " FATALSRC", " ERROR", " MIN", " INFO", " FATAL", " FATALSRC", " ERROR",
// Boolean // Boolean
" I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE", " I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE",
// Errors // Errors
"DETECTARRAY", "MULTITOP", "TASKNSVAR", "DETECTARRAY", "MULTITOP", "PORTSHORT", "TASKNSVAR",
// Warnings // Warnings
" EC_FIRST_WARN", " EC_FIRST_WARN",
"ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN", "ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN",
"BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
@@ -138,7 +140,8 @@ public:
"CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG", "CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG",
"DEFPARAM", "DECLFILENAME", "DEFPARAM", "DECLFILENAME",
"ENDLABEL", "GENCLK", "ENDLABEL", "GENCLK",
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE", "IFDEPTH", "IGNOREDRETURN",
"IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INCABSPATH", "INFINITELOOP", "INITIALDLY",
"LITENDIAN", "MODDUP", "LITENDIAN", "MODDUP",
"MULTIDRIVEN", "MULTIDRIVEN",
+1
View File
@@ -91,6 +91,7 @@ protected:
friend class V3ParseImp; friend class V3ParseImp;
friend class V3PreLex; friend class V3PreLex;
friend class V3PreProcImp; friend class V3PreProcImp;
friend class V3PreShellImp;
void lineno(int num) { m_lineno = num; } void lineno(int num) { m_lineno = num; }
void language(V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); } void language(V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); } void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
+2 -5
View File
@@ -550,14 +550,11 @@ private:
AstVar* pinNewVarp = pinOldVarp->clonep(); AstVar* pinNewVarp = pinOldVarp->clonep();
if (!pinNewVarp) pinOldVarp->v3fatalSrc("Cloning failed"); if (!pinNewVarp) pinOldVarp->v3fatalSrc("Cloning failed");
AstNode* connectRefp = pinp->exprp(); AstNode* connectRefp = pinp->exprp();
if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) { if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) {
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up"); pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
} }
if (pinNewVarp->direction() == VDirection::OUTPUT V3Inst::checkOutputShort(pinp);
&& VN_IS(connectRefp, Const)) {
pinp->v3error("Output port is connected to a constant pin, electrical short");
}
// Propagate any attributes across the interconnect // Propagate any attributes across the interconnect
pinNewVarp->propagateAttrFrom(pinOldVarp); pinNewVarp->propagateAttrFrom(pinOldVarp);
+18 -7
View File
@@ -68,10 +68,7 @@ private:
UINFO(4," PIN "<<nodep<<endl); UINFO(4," PIN "<<nodep<<endl);
if (!nodep->exprp()) return; // No-connect if (!nodep->exprp()) return; // No-connect
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: "); if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
if (nodep->modVarp()->direction() == VDirection::OUTPUT V3Inst::checkOutputShort(nodep);
&& VN_IS(nodep->exprp(), Const)) {
nodep->v3error("Output port is connected to a constant pin, electrical short");
}
// Use user1p on the PIN to indicate we created an assign for this pin // Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1SetOnce()) { if (!nodep->user1SetOnce()) {
// Simplify it // Simplify it
@@ -513,8 +510,9 @@ public:
// Done. Constant. // Done. Constant.
} else { } else {
// Make a new temp wire // Make a new temp wire
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); } //if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
AstNode* pinexprp = pinp->exprp()->unlinkFrBack(); V3Inst::checkOutputShort(pinp);
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
string newvarname = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp") string newvarname = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp")
// Prevent name conflict if both tri & non-tri add signals // Prevent name conflict if both tri & non-tri add signals
+(forTristate?"t":"") +(forTristate?"t":"")
@@ -555,10 +553,23 @@ public:
// Inst class functions // Inst class functions
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp,
bool forTristate, bool alwaysCvt) { bool forTristate, bool alwaysCvt) {
return InstStatic::pinReconnectSimple(pinp, cellp, forTristate, 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 // Inst class visitor
+1
View File
@@ -35,6 +35,7 @@ public:
static void dearrayAll(AstNetlist* nodep); static void dearrayAll(AstNetlist* nodep);
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp,
bool forTristate, bool alwaysCvt=false); bool forTristate, bool alwaysCvt=false);
static void checkOutputShort(AstPin* nodep);
}; };
#endif // Guard #endif // Guard
+9
View File
@@ -131,6 +131,15 @@ private:
} }
m_setRefLvalue = last_setRefLvalue; 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) { virtual void visit(AstFScanF* nodep) {
bool last_setRefLvalue = m_setRefLvalue; bool last_setRefLvalue = m_setRefLvalue;
{ {
+9
View File
@@ -210,6 +210,11 @@ private:
} else if (AstEnumItemRef* fromp = VN_CAST(basefromp, EnumItemRef)) { } else if (AstEnumItemRef* fromp = VN_CAST(basefromp, EnumItemRef)) {
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::ENUM_BASE, nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::ENUM_BASE,
fromp->cloneTree(false))); 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 { } else {
if (basefromp) { UINFO(1," Related node: "<<basefromp<<endl); } if (basefromp) { UINFO(1," Related node: "<<basefromp<<endl); }
nodep->v3fatalSrc("Illegal bit select; no signal/member being extracted from"); nodep->v3fatalSrc("Illegal bit select; no signal/member being extracted from");
@@ -362,6 +367,10 @@ private:
iterateChildren(nodep); iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); 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) { virtual void visit(AstFScanF* nodep) {
iterateChildren(nodep); iterateChildren(nodep);
expectFormat(nodep, nodep->text(), nodep->exprsp(), true); expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
+1 -1
View File
@@ -36,7 +36,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#if defined(WIN32) || defined(__MINGW32__) #if defined(_WIN32) || defined(__MINGW32__)
# include <direct.h> // mkdir # include <direct.h> // mkdir
#endif #endif
-11
View File
@@ -115,17 +115,6 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
m_fileline = new FileLine(fileline); m_fileline = new FileLine(fileline);
m_inLibrary = inLibrary; 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 // Preprocess into m_ppBuffer
bool ok = V3PreShell::preproc(fileline, modfilename, m_filterp, this, errmsg); bool ok = V3PreShell::preproc(fileline, modfilename, m_filterp, this, errmsg);
if (!ok) { if (!ok) {
+24 -8
View File
@@ -102,8 +102,20 @@ protected:
// Preprocess // Preprocess
s_filterp = filterp; s_filterp = filterp;
bool ok = preprocOpen(fl, s_filterp, modname, "", errmsg); string modfilename = preprocOpen(fl, s_filterp, modname, "", errmsg);
if (!ok) return false; 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()) { while (!s_preprocp->isEof()) {
string line = s_preprocp->getline(); string line = s_preprocp->getline();
@@ -116,12 +128,15 @@ protected:
if (modname[0]=='/' || modname[0]=='\\') { if (modname[0]=='/' || modname[0]=='\\') {
fl->v3warn(INCABSPATH,"Suggest `include with absolute path be made relative, and use +include: "<<modname); 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, private:
const string& errmsg) { // Error message or "" to suppress string preprocOpen(FileLine* fl, V3InFilter* filterp,
// Returns true if successful 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 // Try a pure name in case user has a bogus `filename they don't expect
string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg); string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg);
if (filename=="") { if (filename=="") {
@@ -131,13 +146,14 @@ protected:
filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg); filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg);
} }
if (filename=="") return false; // Not found if (filename=="") return ""; // Not found
UINFO(2," Reading "<<filename<<endl); UINFO(2," Reading "<<filename<<endl);
s_preprocp->openFile(fl, filterp, filename); s_preprocp->openFile(fl, filterp, filename);
return true; return filename;
} }
public:
// CONSTRUCTORS // CONSTRUCTORS
V3PreShellImp() {} V3PreShellImp() {}
~V3PreShellImp() {} ~V3PreShellImp() {}
+9 -5
View File
@@ -1170,11 +1170,15 @@ private:
nodep->replaceWith(outrefp); nodep->replaceWith(outrefp);
// Insert new statements // Insert new statements
visitp = insertBeforeStmt(nodep, beginp); visitp = insertBeforeStmt(nodep, beginp);
} else { } else {
// outvscp maybe non-NULL if calling a function in a taskref, if (nodep->taskp()->isFunction()) {
// but if so we want to simply ignore the function result nodep->v3warn(IGNOREDRETURN,
nodep->replaceWith(beginp); "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 // Cleanup
nodep->deleteTree(); VL_DANGLING(nodep); nodep->deleteTree(); VL_DANGLING(nodep);
UINFO(4," FTask REF Done.\n"); UINFO(4," FTask REF Done.\n");
+25
View File
@@ -2232,6 +2232,19 @@ private:
userIterateAndNext(nodep->strgp(), WidthVP(SELF,BOTH).p()); 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) { virtual void visit(AstFScanF* nodep) {
if (m_vup->prelim()) { if (m_vup->prelim()) {
nodep->dtypeSetSigned32(); // Spec says integer return nodep->dtypeSetSigned32(); // Spec says integer return
@@ -3172,6 +3185,18 @@ private:
underp = iterateCheck(nodep,"file_descriptor",underp,SELF,FINAL,expDTypep,EXTEND_EXP); underp = iterateCheck(nodep,"file_descriptor",underp,SELF,FINAL,expDTypep,EXTEND_EXP);
if (underp) {} // cppcheck 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) { void iterateCheckReal(AstNode* nodep, const char* side, AstNode* underp, Stage stage) {
// Coerce child to real if not already. Child is self-determined // Coerce child to real if not already. Child is self-determined
// e.g. nodep=ADDD, underp=ADD in ADDD(ADD(a,b), real-CONST) // e.g. nodep=ADDD, underp=ADD in ADDD(ADD(a,b), real-CONST)
+2 -2
View File
@@ -325,7 +325,7 @@ sub clean_input {
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ /BISONPRE_NOT/) { 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"; or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
my $endtok = $1; my $action = $2; my $endtok = $1; my $action = $2;
my @endtoks = split (/,/, $endtok); my @endtoks = split (/,/, $endtok);
@@ -412,7 +412,7 @@ sub _bisonpre_copy {
my $l = shift; my $l = shift;
my $depth = shift; my $depth = shift;
while ($text =~ /BISONPRE_COPY/) { 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"; or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
my $once = $1; my $rule = $2; my $code = $3; 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"; $Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
+1
View File
@@ -227,6 +227,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$finish" { FL; return yD_FINISH; } "$finish" { FL; return yD_FINISH; }
"$floor" { FL; return yD_FLOOR; } "$floor" { FL; return yD_FLOOR; }
"$fopen" { FL; return yD_FOPEN; } "$fopen" { FL; return yD_FOPEN; }
"$fread" { FL; return yD_FREAD; }
"$fscanf" { FL; return yD_FSCANF; } "$fscanf" { FL; return yD_FSCANF; }
"$fullskew" { FL; return yaTIMINGSPEC; } "$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; } "$fwrite" { FL; return yD_FWRITE; }
+27 -3
View File
@@ -475,6 +475,7 @@ class AstSenTree;
%token<fl> yD_FINISH "$finish" %token<fl> yD_FINISH "$finish"
%token<fl> yD_FLOOR "$floor" %token<fl> yD_FLOOR "$floor"
%token<fl> yD_FOPEN "$fopen" %token<fl> yD_FOPEN "$fopen"
%token<fl> yD_FREAD "$fread"
%token<fl> yD_FSCANF "$fscanf" %token<fl> yD_FSCANF "$fscanf"
%token<fl> yD_FWRITE "$fwrite" %token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_HIGH "$high" %token<fl> yD_HIGH "$high"
@@ -2390,8 +2391,21 @@ statement_item<nodep>: // IEEE: statement_item
// // Below under expr // // Below under expr
// //
// // IEEE: subroutine_call_statement // // IEEE: subroutine_call_statement
//UNSUP yVOID yP_TICK '(' function_subroutine_callNoMethod ')' ';' { } // // IEEE says we then expect a function call
//UNSUP yVOID yP_TICK '(' expr '.' function_subroutine_callNoMethod ')' ';' { } // // (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 included here to resolve our not knowing what is a method call
// // Expr here must result in a subroutine_call // // Expr here must result in a subroutine_call
| task_subroutine_callNoMethod ';' { $$ = $1; } | 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_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); } | yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); } | 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_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); } | yD_HIGH '(' exprOrDataType ')' { $$ = 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 // // IEEE: concatenation/constant_concatenation
// // Replicate(1) required as otherwise "{a}" would not be self-determined // // Replicate(1) required as otherwise "{a}" would not be self-determined
| '{' cateList '}' { $$ = new AstReplicate($1,$2,1); } | '{' 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
// // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id/data_type] // // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id/data_type]
// // We allow more here than the spec requires // // 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) { AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
FileLine* newfl = new FileLine (fileline); FileLine* newfl = new FileLine(fileline);
newfl->warnOff(V3ErrorCode::WIDTH, true); newfl->warnOff(V3ErrorCode::WIDTH, true);
AstNode* nodep = new AstConst(newfl, V3Number(newfl)); AstNode* nodep = new AstConst(newfl, V3Number(newfl));
// Adding a NOT is less work than figuring out how wide to make it // Adding a NOT is less work than figuring out how wide to make it
+66 -55
View File
@@ -77,8 +77,8 @@ our $Opt_Unsupported;
our $Opt_Verilation = 1; our $Opt_Verilation = 1;
our @Opt_Driver_Verilator_Flags; our @Opt_Driver_Verilator_Flags;
Getopt::Long::config ("pass_through"); Getopt::Long::config("pass_through");
if (! GetOptions ( if (! GetOptions(
"benchmark:i" => sub { $opt_benchmark = $_[1] ? $_[1] : 1; }, "benchmark:i" => sub { $opt_benchmark = $_[1] ? $_[1] : 1; },
"debug" => \&debug, "debug" => \&debug,
#debugi see parameter() #debugi see parameter()
@@ -136,6 +136,9 @@ if ($#opt_tests<0) {
if ($#opt_tests>=2 && $opt_jobs>=2) { if ($#opt_tests>=2 && $opt_jobs>=2) {
# Without this tests such as t_debug_sigsegv_bt_bad.pl will occasionally # 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. # 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"; print STDERR "== Many jobs; redirecting STDIN\n";
open(STDIN, "+>/dev/null"); 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 { sub one_test {
my @params = @_; my @params = @_;
@@ -173,9 +176,10 @@ sub one_test {
# Don't put anything other than _exit after _read, # Don't put anything other than _exit after _read,
# as may call _exit via another path # as may call _exit via another path
$test->_exit; $test->_exit;
}, },
run_on_finish => sub { run_on_finish => sub {
my $test = VTest->new(@params); # RUnning in context of parent
my $test = VTest->new(@params);
$test->_read_status; $test->_read_status;
if ($test->ok) { if ($test->ok) {
$OkCnt++; $OkCnt++;
@@ -218,7 +222,7 @@ exit(10) if $FailCnt;
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit(1);
} }
sub debug { sub debug {
@@ -310,7 +314,7 @@ use Cwd;
use Data::Dumper; use Data::Dumper;
use File::Spec; use File::Spec;
use vars qw ($Self $Self); use vars qw($Self $Self);
use strict; use strict;
sub new { sub new {
@@ -366,9 +370,9 @@ sub new {
.($opt_benchmark ? " +define+TEST_BENCHMARK=$opt_benchmark":"") .($opt_benchmark ? " +define+TEST_BENCHMARK=$opt_benchmark":"")
.($opt_trace ? " +define+WAVES=1":"") .($opt_trace ? " +define+WAVES=1":"")
))], ))],
v_flags2 => [], # Overridden in some sim files v_flags2 => [], # Overridden in some sim files
v_other_filenames => [], # After the filename so we can spec multiple files v_other_filenames => [], # After the filename so we can spec multiple files
all_run_flags => [], all_run_flags => [],
pli_flags => ["-I$ENV{VERILATOR_ROOT}/include/vltstd -fPIC -shared" pli_flags => ["-I$ENV{VERILATOR_ROOT}/include/vltstd -fPIC -shared"
.(($^O eq "darwin" ) .(($^O eq "darwin" )
? " -Wl,-undefined,dynamic_lookup" ? " -Wl,-undefined,dynamic_lookup"
@@ -390,9 +394,9 @@ sub new {
# IV # IV
iv => 0, iv => 0,
iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")], iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")],
iv_flags2 => [], # Overridden in some sim files iv_flags2 => [], # Overridden in some sim files
iv_pli => 0, # need to use pli iv_pli => 0, # need to use pli
iv_run_flags => [], iv_run_flags => [],
# VCS # VCS
vcs => 0, vcs => 0,
vcs_flags => [split(/\s+/,"+vcs+lic+wait +cli -debug_access +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")], 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_flags2 => [],
verilator_flags3 => ["--clk clk"], verilator_flags3 => ["--clk clk"],
verilator_make_gcc => 1, verilator_make_gcc => 1,
verilated_debug => $Opt_Verilated_Debug, verilated_debug => $Opt_Verilated_Debug,
stdout_filename => undef, # Redirect stdout stdout_filename => undef, # Redirect stdout
%$self}; %$self};
bless $self, $class; bless $self, $class;
$self->{vlt_all} = $self->{vlt} || $self->{vltmt}; # Any Verilator scenario $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->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
($self->{top_filename} ||= $self->{pl_filename}) =~ s/\.pl$//; ($self->{top_filename} ||= $self->{pl_filename}) =~ s/\.pl$//;
($self->{golden_filename} ||= $self->{pl_filename}) =~ s/\.pl$/.out/; ($self->{golden_filename} ||= $self->{pl_filename}) =~ s/\.pl$/.out/;
if (-e ($self->{top_filename}.".vhd")) { # If VHDL file exists if (-e ($self->{top_filename}.".vhd")) { # If VHDL file exists
$self->{vhdl} = 1; $self->{vhdl} = 1;
$self->{top_filename} .= ".vhd"; $self->{top_filename} .= ".vhd";
} else { } else {
$self->{top_filename} .= ".v"; $self->{top_filename} .= ".v";
@@ -580,7 +584,7 @@ sub _read_status {
sub compile_vlt_flags { sub compile_vlt_flags {
my $self = (ref $_[0]? shift : $Self); 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; return 1 if $self->errors || $self->skips || $self->unsupporteds;
my $checkflags = join(' ',@{$param{v_flags}}, my $checkflags = join(' ',@{$param{v_flags}},
@@ -637,7 +641,7 @@ sub compile_vlt_flags {
sub compile { sub compile {
my $self = (ref $_[0]? shift : $Self); 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; return 1 if $self->errors || $self->skips || $self->unsupporteds;
$self->oprint("Compile\n"); $self->oprint("Compile\n");
@@ -676,7 +680,7 @@ sub compile {
@{$param{ghdl_flags}}, @{$param{ghdl_flags}},
@{$param{ghdl_flags2}}, @{$param{ghdl_flags2}},
#@{$param{v_flags}}, # Not supported #@{$param{v_flags}}, # Not supported
#@{$param{v_flags2}}, # Not supported #@{$param{v_flags2}}, # Not supported
$param{top_filename}, $param{top_filename},
$param{top_shell_filename}, $param{top_shell_filename},
@{$param{v_other_filenames}}, @{$param{v_other_filenames}},
@@ -809,8 +813,8 @@ sub compile {
sub execute { sub execute {
my $self = (ref $_[0]? shift : $Self); my $self = (ref $_[0]? shift : $Self);
return 1 if $self->errors || $self->skips || $self->unsupporteds; return 1 if $self->errors || $self->skips || $self->unsupporteds;
my %param = (%{$self}, @_); # Default arguments are from $self my %param = (%{$self}, @_); # Default arguments are from $self
# params may be expect or {tool}_expect # params may be expect or {tool}_expect
$self->oprint("Run\n"); $self->oprint("Run\n");
my $run_env = $param{run_env}; my $run_env = $param{run_env};
@@ -845,10 +849,11 @@ sub execute {
@{$param{iv_run_flags}}, @{$param{iv_run_flags}},
@{$param{all_run_flags}}, @{$param{all_run_flags}},
); );
if ($param{iv_pli}) { if ($param{iv_pli}) {
unshift @cmd, "vvp -n -m $self->{obj_dir}/libvpi.so"; # don't enter command line on $stop, include vpi # 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", }
$self->_run(logfile=>"$self->{obj_dir}/iv_sim.log",
fails=>$param{fails}, fails=>$param{fails},
cmd=> \@cmd, cmd=> \@cmd,
%param, %param,
@@ -900,7 +905,7 @@ sub execute {
$param{executable} ||= "$self->{obj_dir}/$param{VM_PREFIX}"; $param{executable} ||= "$self->{obj_dir}/$param{VM_PREFIX}";
$self->_run(logfile=>"$self->{obj_dir}/vlt_sim.log", $self->_run(logfile=>"$self->{obj_dir}/vlt_sim.log",
cmd=>[($run_env cmd=>[($run_env
.($opt_gdbsim ? ("gdb"||$ENV{VERILATOR_GDB})." " : "") .($opt_gdbsim ? ($ENV{VERILATOR_GDB}||"gdb")." " : "")
.$param{executable} .$param{executable}
.($opt_gdbsim ? " -ex 'run " : "")), .($opt_gdbsim ? " -ex 'run " : "")),
@{$param{all_run_flags}}, @{$param{all_run_flags}},
@@ -921,7 +926,7 @@ sub inline_checks {
return 1 if $self->errors || $self->skips || $self->unsupporteds; return 1 if $self->errors || $self->skips || $self->unsupporteds;
return 1 if !$self->{vlt_all}; 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 $covfn = $Self->{coverage_filename};
my $contents = $self->file_contents($covfn); my $contents = $self->file_contents($covfn);
@@ -1057,9 +1062,9 @@ sub _run {
if ($param{logfile}) { if ($param{logfile}) {
$logfh = IO::File->new(">$param{logfile}") or die "%Error: Can't open $param{logfile}"; $logfh = IO::File->new(">$param{logfile}") or die "%Error: Can't open $param{logfile}";
} }
my $pid=fork(); my $pid=fork();
if ($pid) { # Parent if ($pid) { # Parent
close CHILDWR; close CHILDWR;
while (1) { while (1) {
my $buf = ''; my $buf = '';
my $got = sysread PARENTRD,$buf,10000; my $got = sysread PARENTRD,$buf,10000;
@@ -1069,9 +1074,9 @@ sub _run {
} }
close PARENTRD; close PARENTRD;
close $logfh if $logfh; close $logfh if $logfh;
} }
else { # Child else { # Child
close PARENTRD; close PARENTRD;
close $logfh if $logfh; close $logfh if $logfh;
# Reset signals # Reset signals
$SIG{ALRM} = 'DEFAULT'; $SIG{ALRM} = 'DEFAULT';
@@ -1082,9 +1087,9 @@ sub _run {
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
system "$command"; system "$command";
exit ($? ? 10 : 0); # $?<<8 misses coredumps exit($? ? 10 : 0); # $?<<8 misses coredumps
} }
waitpid($pid,0); waitpid($pid,0);
$status = $? || 0; $status = $? || 0;
} }
flush STDOUT; flush STDOUT;
@@ -1131,8 +1136,8 @@ sub _run {
$wholefile =~ s/^- [a-z.0-9]+:\d+:[^\n]+\n//mig; $wholefile =~ s/^- [a-z.0-9]+:\d+:[^\n]+\n//mig;
$wholefile =~ s/^dot [^\n]+\n//mig; $wholefile =~ s/^dot [^\n]+\n//mig;
# Compare # Compare
my $quoted = quotemeta ($param{expect}); my $quoted = quotemeta($param{expect});
my $ok = ($wholefile eq $param{expect} my $ok = ($wholefile eq $param{expect}
|| _try_regex($wholefile, $param{expect}) == 1 || _try_regex($wholefile, $param{expect}) == 1
|| $wholefile =~ /$quoted/ms); || $wholefile =~ /$quoted/ms);
@@ -1503,9 +1508,9 @@ sub _read_inputs_v {
if ($line =~ /^\s*(function|task|endmodule)/) { if ($line =~ /^\s*(function|task|endmodule)/) {
$get_sigs = 0; $get_sigs = 0;
} }
} }
if ($line =~ /^\s*module\s+t\b/) { # Ignore any earlier inputs; Module 't' has precedence if ($line =~ /^\s*module\s+t\b/) { # Ignore any earlier inputs; Module 't' has precedence
%inputs = (); %inputs = ();
$get_sigs = 1; $get_sigs = 1;
} }
} }
@@ -1685,7 +1690,7 @@ sub _vcd_read {
my $self = (ref $_[0]? shift : $Self); my $self = (ref $_[0]? shift : $Self);
my $filename = shift; my $filename = shift;
my $data = {}; my $data = {};
my $fh = IO::File->new ("<$filename"); my $fh = IO::File->new("<$filename");
if (!$fh) { warn "%Error: $! $filename\n"; return $data; } if (!$fh) { warn "%Error: $! $filename\n"; return $data; }
my @hier = ($data); my @hier = ($data);
my $lasthier; my $lasthier;
@@ -1813,8 +1818,14 @@ sub new {
sub schedule { sub schedule {
my $self = shift; my $self = shift;
my %params = (@_); 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; return $self;
} }
sub max_proc {} 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 Both C<compile> and C<execute> take an optional argument hash table to
control their behavior. For example: control their behavior. For example:
compile ( compile(
verilator_flags2 => ["--lint-only"], verilator_flags2 => ["--lint-only"],
fails => 1, 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 same name as the test, but with .cpp as suffix
(C<test_regress/t/t_EXAMPLE.cpp>). This can be specified as follows: (C<test_regress/t/t_EXAMPLE.cpp>). This can be specified as follows:
compile ( compile(
make_top_shell => 0, make_top_shell => 0,
make_main => 0, make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"], ); 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 If termination should be triggered from the C++ wrapper, the following code
can be used: can be used:
vl_fatal (__FILE__, __LINE__, "dut", "<error message goes here>"); vl_fatal(__FILE__, __LINE__, "dut", "<error message goes here>");
exit (1); exit(1);
This can be particularly useful if checking that the Verilator model has This can be particularly useful if checking that the Verilator model has
not unexpectedly terminated. not unexpectedly terminated.
if (Verilated::gotFinish ()) { if (Verilated::gotFinish()) {
vl_fatal (__FILE__, __LINE__, "dut", "<error message goes here>"); vl_fatal(__FILE__, __LINE__, "dut", "<error message goes here>");
exit (1); exit(1);
} }
Where it might be useful for a test to produce output, it should qualify Where it might be useful for a test to produce output, it should qualify
this with C<TEST_VERBOSE>. For example in Verilog: this with C<TEST_VERBOSE>. For example in Verilog:
`ifdef TEST_VERBOSE `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 `endif
Or in a hand-written C++ wrapper: Or in a hand-written C++ wrapper:
+5 -5
View File
@@ -15,8 +15,8 @@ module t (/*AUTOARG*/
input clk; input clk;
reg [63:0] crc; reg [63:0] crc;
`verilator_file_descriptor fd; integer fd;
`verilator_file_descriptor fdtmp; integer fdtmp;
t_case_write1_tasks tasks (); t_case_write1_tasks tasks ();
@@ -33,14 +33,14 @@ module t (/*AUTOARG*/
cyc <= cyc + 1; cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
if (cyc==1) begin 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"}); $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"); fdtmp = $fopen({`STRINGIFY(`TEST_OBJ_DIR), "/t_case_write1_logger.log"}, "w");
fd <= fdtmp; fd <= fdtmp;
end end
if (cyc==90) begin if (cyc==90) begin
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end
end end
+5 -5
View File
@@ -15,8 +15,8 @@ module t (/*AUTOARG*/
input clk; input clk;
reg [63:0] crc; reg [63:0] crc;
`verilator_file_descriptor fd; integer fd;
`verilator_file_descriptor fdtmp; integer fdtmp;
t_case_write2_tasks tasks (); t_case_write2_tasks tasks ();
@@ -33,14 +33,14 @@ module t (/*AUTOARG*/
cyc <= cyc + 1; cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
if (cyc==1) begin 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"}); $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"); fdtmp = $fopen({`STRINGIFY(`TEST_OBJ_DIR), "/t_case_write2_logger.log"}, "w");
fd <= fdtmp; fd <= fdtmp;
end end
if (cyc==90) begin if (cyc==90) begin
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end
end end
+2
View File
@@ -46,7 +46,9 @@ module t (/*AUTOARG*/);
// Test loop // Test loop
initial begin initial begin
// bug963 // bug963
// verilator lint_off IGNOREDRETURN
dpii_clear(); dpii_clear();
// verilator lint_on IGNOREDRETURN
j = 0; j = 0;
for (i=0; i<64; i++) begin for (i=0; i<64; i++) begin
if (i[0]) if (i[0])
+3
View File
@@ -50,12 +50,15 @@ module t;
if (n !== 10) $stop; if (n !== 10) $stop;
// Functions called as tasks // Functions called as tasks
// verilator lint_off IGNOREDRETURN
rglobal = 32'h4; rglobal = 32'h4;
if (inc_and_return(32'h2) != 32'h6) $stop; if (inc_and_return(32'h2) != 32'h6) $stop;
if (rglobal !== 32'h6) $stop; if (rglobal !== 32'h6) $stop;
rglobal = 32'h6; rglobal = 32'h6;
inc_and_return(32'h3); inc_and_return(32'h3);
if (rglobal !== 32'h9) $stop; if (rglobal !== 32'h9) $stop;
// verilator lint_on IGNOREDRETURN
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
+1
View File
@@ -6,6 +6,7 @@
module t (/*AUTOARG*/); module t (/*AUTOARG*/);
initial begin initial begin
// verilator lint_off IGNOREDRETURN
func(0, 1'b1); func(0, 1'b1);
end end
+20
View File
@@ -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;
+36
View File
@@ -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
+3
View File
@@ -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
+18
View File
@@ -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;
+35
View File
@@ -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
+18
View File
@@ -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;
+12
View File
@@ -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
+11
View File
@@ -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
+2
View File
@@ -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
+1 -3
View File
@@ -15,9 +15,7 @@ compile(
verilator_make_gcc => 0, verilator_make_gcc => 0,
make_top_shell => 0, make_top_shell => 0,
make_main => 0, make_main => 0,
expect => expect_filename => $Self->{golden_filename},
'%Error: t/t_lint_setout_bad.v:\d+: Output port is connected to a constant pin, electrical short
.*',
); );
ok(1); 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
+1 -3
View File
@@ -17,9 +17,7 @@ compile(
verilator_make_gcc => 0, verilator_make_gcc => 0,
make_top_shell => 0, make_top_shell => 0,
make_main => 0, make_main => 0,
expect => expect_filename => $Self->{golden_filename},
'%Error: t/t_lint_setout_bad.v:\d+: Output port is connected to a constant pin, electrical short
.*',
); );
ok(1); ok(1);
+4
View File
@@ -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
+21
View File
@@ -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;
+16
View File
@@ -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
+17
View File
@@ -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;
+58
View File
@@ -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
+27
View File
@@ -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;
+17
View File
@@ -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
+1 -1
View File
@@ -8,7 +8,7 @@
`define STRINGIFY(x) `"x`" `define STRINGIFY(x) `"x`"
module t; module t;
`verilator_file_descriptor file; integer file;
integer chars; integer chars;
reg [1*8:1] letterl; reg [1*8:1] letterl;
+1 -1
View File
@@ -8,7 +8,7 @@
`define STRINGIFY(x) `"x`" `define STRINGIFY(x) `"x`"
module t; module t;
`verilator_file_descriptor infile, outfile; integer infile, outfile;
integer count, a; integer count, a;
initial begin initial begin
+27
View File
@@ -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 *-*
+38
View File
@@ -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;
+87
View File
@@ -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