mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7aa8820e1 | ||
|
|
2582a83376 | ||
|
|
0094cd7a81 | ||
|
|
d9b33d74a4 | ||
|
|
539a773ea7 | ||
|
|
b1831d7e33 | ||
|
|
b8ccb7a4c1 | ||
|
|
0eb75a41bb | ||
|
|
4cc47e3297 | ||
|
|
7bf3366041 | ||
|
|
c4b9f4bccf | ||
|
|
455c552132 | ||
|
|
f26fb51509 | ||
|
|
ab3c6576ed | ||
|
|
d1bd994113 | ||
|
|
d1548b1161 | ||
|
|
8a43f41ed6 | ||
|
|
42759e4011 | ||
|
|
27fa19eb94 | ||
|
|
426ed8589b |
@@ -2,6 +2,28 @@ Revision history for Verilator
|
|||||||
|
|
||||||
The contributors that suggested a given feature are shown in []. Thanks!
|
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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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
@@ -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",
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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");
|
||||||
|
|||||||
@@ -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
@@ -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";
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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])
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2003 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (clk);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
int side_effect;
|
||||||
|
|
||||||
|
function int f1;
|
||||||
|
input int in;
|
||||||
|
f1 = in + 1;
|
||||||
|
side_effect += in + 1;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int got;
|
||||||
|
side_effect = 1;
|
||||||
|
//
|
||||||
|
got = f1(10);
|
||||||
|
if (got != 11) $stop;
|
||||||
|
if (side_effect != 12) $stop;
|
||||||
|
// verilator lint_off IGNOREDRETURN
|
||||||
|
f1(20);
|
||||||
|
// verilator lint_on IGNOREDRETURN
|
||||||
|
if (side_effect != 33) $stop;
|
||||||
|
//
|
||||||
|
void'(f1(30));
|
||||||
|
if (side_effect != 64) $stop;
|
||||||
|
//
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
%Warning-IGNOREDRETURN: t/t_func_void_bad.v:25: Ignoring return value of non-void function (IEEE 2017 13.4.1)
|
||||||
|
%Warning-IGNOREDRETURN: Use "/* verilator lint_off IGNOREDRETURN */" and lint_on around source to disable this message.
|
||||||
|
%Error: Exiting due to
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2003 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (clk);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
int side_effect;
|
||||||
|
|
||||||
|
function int f1;
|
||||||
|
input int in;
|
||||||
|
f1 = in + 1;
|
||||||
|
side_effect += in + 1;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int got;
|
||||||
|
side_effect = 1;
|
||||||
|
//
|
||||||
|
got = f1(10);
|
||||||
|
if (got != 11) $stop;
|
||||||
|
if (side_effect != 12) $stop;
|
||||||
|
//
|
||||||
|
f1(20);
|
||||||
|
if (side_effect != 33) $stop;
|
||||||
|
//
|
||||||
|
// void'f1(30);
|
||||||
|
// if (side_effect != 64) $stop;
|
||||||
|
//
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
# This is a compile only test.
|
||||||
|
compile(
|
||||||
|
v_flags2 => ["+1364-2005ext+v"],
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// A test of the +verilog2001ext+ and +verilog2005ext+ flags.
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
// verilator lint_off SYMRSVDWORD
|
||||||
|
|
||||||
|
module t(input do);
|
||||||
|
t_langext_order_sub sub (.do(do));
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// A test of the +verilog2001ext+ and +verilog2005ext+ flags.
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
// verilator lint_off SYMRSVDWORD
|
||||||
|
|
||||||
|
module t_langext_order_sub(input do);
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
%Error-PORTSHORT: t/t_lint_setout_bad.v:16: Output port is connected to a constant pin, electrical short
|
||||||
|
%Error: Exiting due to
|
||||||
@@ -15,9 +15,7 @@ compile(
|
|||||||
verilator_make_gcc => 0,
|
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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
%Error-PORTSHORT: t/t_lint_subout_bad.v:11: Output port is connected to a constant pin, electrical short
|
||||||
|
%Error-PORTSHORT: t/t_lint_subout_bad.v:12: Output port is connected to a constant pin, electrical short
|
||||||
|
%Error-PORTSHORT: t/t_lint_subout_bad.v:10: Output port is connected to a constant pin, electrical short
|
||||||
|
%Error: Exiting due to
|
||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2008 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
scenarios(vlt_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
# No --lint-only as got compile error
|
||||||
|
verilator_flags2 => ["--trace"],
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
// verilator lint_off UNDRIVEN
|
||||||
|
|
||||||
|
module t();
|
||||||
|
wire sig;
|
||||||
|
sub sub0(.out(33'b0));
|
||||||
|
sub sub1(.out({32'b0, sig}));
|
||||||
|
sub sub2(.out({32'b1, sig}));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub(output reg [32 : 0] out);
|
||||||
|
endmodule
|
||||||
Executable
+17
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2019 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
fails => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
reg [63:0] crc;
|
||||||
|
reg [63:0] sum;
|
||||||
|
|
||||||
|
// Take CRC data and apply to testblock inputs
|
||||||
|
wire [3:0] a = crc[3:0];
|
||||||
|
wire [3:0] b = crc[19:16];
|
||||||
|
|
||||||
|
// TEST
|
||||||
|
wire [3:0] out1 = {a,b}[2 +: 4];
|
||||||
|
wire [3:0] out2 = {a,b}[5 -: 4];
|
||||||
|
wire [3:0] out3 = {a,b}[5 : 2];
|
||||||
|
wire [0:0] out4 = {a,b}[2];
|
||||||
|
|
||||||
|
// Aggregate outputs into a single result vector
|
||||||
|
wire [63:0] result = {51'h0, out4, out3, out2, out1};
|
||||||
|
|
||||||
|
// Test loop
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
`ifdef TEST_VERBOSE
|
||||||
|
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||||
|
`endif
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h5aef0c8d_d70a4497;
|
||||||
|
sum <= '0;
|
||||||
|
end
|
||||||
|
else if (cyc<10) begin
|
||||||
|
sum <= '0;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
|
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||||
|
// What checksum will we end up with (above print should match)
|
||||||
|
`define EXPECTED_SUM 64'h4afe43fb79d7b71e
|
||||||
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+27
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
scenarios(vlt_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
all_run_flags => ["+verilator+seed+5 +SEED=fffffff4"],
|
||||||
|
fails => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
all_run_flags => ["+verilator+seed+6 +SEED=fffffff2"],
|
||||||
|
fails => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
|
||||||
|
1;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
|
module t;
|
||||||
|
initial begin
|
||||||
|
integer r = $random;
|
||||||
|
integer ex;
|
||||||
|
if ($value$plusargs("SEED=%x", ex) !== 1) $stop;
|
||||||
|
`checkh(r, ex);
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
`define STRINGIFY(x) `"x`"
|
`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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
Dump:
|
||||||
|
r_i: 00010203
|
||||||
|
r_upb: 0e 0d 0c 0b 0a 09 08 07 06 05 04
|
||||||
|
r_dnb: 19 18 17 16 15 14 13 12 11 10 0f
|
||||||
|
r_ups: 2e2f 2c2d 2a2b 2829 2627 2425 2223 2021 1e1f 1c1d 1a1b
|
||||||
|
r_dns: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0041 0243 0445
|
||||||
|
r_upi: 6e6f7071 6a6b6c6d 66676869 62636465 5e5f6061 5a5b5c5d 56575859 52535455 4e4f5051 4a4b4c4d 46474849
|
||||||
|
r_dni: 72737475 76777879 7a7b7c7d 7e7f8081 02838485 06878889 0a8b8c8d 0e8f9091 12939495 16979899 1a9b9c9d
|
||||||
|
r_upq: 2eeff0f1f2f3f4f5 26e7e8e9eaebeced 1edfe0e1e2e3e4e5 16d7d8d9dadbdcdd 0ecfd0d1d2d3d4d5 06c7c8c9cacbcccd 3ebfc0c1c2c3c4c5 36b7b8b9babbbcbd 2eafb0b1b2b3b4b5 26a7a8a9aaabacad 1e9fa0a1a2a3a4a5
|
||||||
|
r_dnq: 36f7f8f9fafbfcfd 3eff000102030405 060708090a0b0c0d 0e0f101112131415 161718191a1b1c1d 1e1f202122232425 262728292a2b2c2d 2e2f303132333435 363738393a3b3c3d 3e3f404142434445 064748494a4b4c4d
|
||||||
|
r_upw: a8a9aaabacadaeafb0 9fa0a1a2a3a4a5a6a7 969798999a9b9c9d9e 8d8e8f909192939495 8485868788898a8b8c 7b7c7d7e7f80818283 72737475767778797a 696a6b6c6d6e6f7071 606162636465666768 5758595a5b5c5d5e5f 4e4f50515253545556
|
||||||
|
r_dnw: b1b2b3b4b5b6b7b8b9 babbbcbdbebfc0c1c2 c3c4c5c6c7c8c9cacb cccdcecfd0d1d2d3d4 d5d6d7d8d9dadbdcdd dedfe0e1e2e3e4e5e6 e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8 f9fafbfcfdfeff0001 02030405060708090a 0b0c0d0e0f10111213
|
||||||
|
|
||||||
|
Dump:
|
||||||
|
r_i: ffffffff
|
||||||
|
r_upb: 05 04 03 02 01 00 ff ff ff ff ff
|
||||||
|
r_dnb: ff ff ff ff ff ff ff ff ff ff ff
|
||||||
|
r_ups: 3fff 3fff 3fff 3fff 0809 0607 3fff 3fff 3fff 3fff 3fff
|
||||||
|
r_dns: 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff
|
||||||
|
r_upi: 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff
|
||||||
|
r_dni: 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff
|
||||||
|
r_upq: 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff
|
||||||
|
r_dnq: 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff
|
||||||
|
r_upw: ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff
|
||||||
|
r_dnw: ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff
|
||||||
|
|
||||||
|
*-* All Finished *-*
|
||||||
Executable
+38
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2019 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
use IO::File;
|
||||||
|
#use Data::Dumper;
|
||||||
|
use strict;
|
||||||
|
use vars qw($Self);
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
sub gen {
|
||||||
|
my $filename = shift;
|
||||||
|
|
||||||
|
my $fh = IO::File->new(">$filename");
|
||||||
|
for (my $copy=0; $copy<32; ++$copy) {
|
||||||
|
for (my $i=0; $i<=255; ++$i) {
|
||||||
|
$fh->print(chr($i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gen("$Self->{obj_dir}/t_sys_fread.mem");
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
`define STRINGIFY(x) `"x`"
|
||||||
|
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
module t;
|
||||||
|
integer file;
|
||||||
|
integer r_i;
|
||||||
|
byte r_upb[20:10];
|
||||||
|
byte r_dnb[20:10];
|
||||||
|
reg [13:0] r_ups[20:10];
|
||||||
|
reg [13:0] r_dns[10:20];
|
||||||
|
reg [30:0] r_upi[20:10];
|
||||||
|
reg [30:0] r_dni[10:20];
|
||||||
|
reg [61:0] r_upq[20:10];
|
||||||
|
reg [61:0] r_dnq[10:20];
|
||||||
|
reg [71:0] r_upw[20:10];
|
||||||
|
reg [71:0] r_dnw[10:20];
|
||||||
|
|
||||||
|
task clear;
|
||||||
|
// Initialize memories to zero,
|
||||||
|
// avoid differences between 2-state and 4-state.
|
||||||
|
r_i = ~0;
|
||||||
|
foreach (r_upb[i]) r_upb[i] = ~0;
|
||||||
|
foreach (r_dnb[i]) r_dnb[i] = ~0;
|
||||||
|
foreach (r_ups[i]) r_ups[i] = ~0;
|
||||||
|
foreach (r_dns[i]) r_dns[i] = ~0;
|
||||||
|
foreach (r_upi[i]) r_upi[i] = ~0;
|
||||||
|
foreach (r_dni[i]) r_dni[i] = ~0;
|
||||||
|
foreach (r_upq[i]) r_upq[i] = ~0;
|
||||||
|
foreach (r_dnq[i]) r_dnq[i] = ~0;
|
||||||
|
foreach (r_upw[i]) r_upw[i] = ~0;
|
||||||
|
foreach (r_dnw[i]) r_dnw[i] = ~0;
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
$fclose(file);
|
||||||
|
file = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_fread.mem"}, "r");
|
||||||
|
if ($feof(file)) $stop;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task dump;
|
||||||
|
$write("Dump:");
|
||||||
|
$write("\n r_i:"); $write(" %x",r_i);
|
||||||
|
$write("\n r_upb:"); foreach (r_upb[i]) $write(" %x", r_upb[i]);
|
||||||
|
$write("\n r_dnb:"); foreach (r_dnb[i]) $write(" %x", r_dnb[i]);
|
||||||
|
$write("\n r_ups:"); foreach (r_ups[i]) $write(" %x", r_ups[i]);
|
||||||
|
$write("\n r_dns:"); foreach (r_dns[i]) $write(" %x", r_dns[i]);
|
||||||
|
$write("\n r_upi:"); foreach (r_upi[i]) $write(" %x", r_upi[i]);
|
||||||
|
$write("\n r_dni:"); foreach (r_dni[i]) $write(" %x", r_dni[i]);
|
||||||
|
$write("\n r_upq:"); foreach (r_upq[i]) $write(" %x", r_upq[i]);
|
||||||
|
$write("\n r_dnq:"); foreach (r_dnq[i]) $write(" %x", r_dnq[i]);
|
||||||
|
$write("\n r_upw:"); foreach (r_upw[i]) $write(" %x", r_upw[i]);
|
||||||
|
$write("\n r_dnw:"); foreach (r_dnw[i]) $write(" %x", r_dnw[i]);
|
||||||
|
$write("\n\n");
|
||||||
|
endtask
|
||||||
|
|
||||||
|
integer code;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clear;
|
||||||
|
code = $fread(r_i, file); `checkd(code, 4);
|
||||||
|
code = $fread(r_upb, file); `checkd(code, 11);
|
||||||
|
code = $fread(r_dnb, file); `checkd(code, 11);
|
||||||
|
code = $fread(r_ups, file); `checkd(code, 22);
|
||||||
|
code = $fread(r_dns, file); `checkd(code, 22);
|
||||||
|
code = $fread(r_upi, file); `checkd(code, 44);
|
||||||
|
code = $fread(r_dni, file); `checkd(code, 44);
|
||||||
|
code = $fread(r_upq, file); `checkd(code, 88);
|
||||||
|
code = $fread(r_dnq, file); `checkd(code, 88);
|
||||||
|
code = $fread(r_upw, file); `checkd(code, 99);
|
||||||
|
code = $fread(r_dnw, file); `checkd(code, 99);
|
||||||
|
dump;
|
||||||
|
|
||||||
|
clear;
|
||||||
|
code = $fread(r_upb, file, 15); `checkd(code, 6);
|
||||||
|
code = $fread(r_ups, file, 15, 2); `checkd(code, 4);
|
||||||
|
dump;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Reference in New Issue
Block a user