Compare commits

...
36 Commits
Author SHA1 Message Date
Wilson Snyder 55f0d4ddd8 Version bump 2014-11-15 08:38:44 -05:00
Wilson Snyder 6d66fcaa57 Fix +define+A+B to define A and B to match other simulators, bug847. 2014-11-13 19:05:07 -05:00
Wilson Snyder 26e79ca889 Fix quoted comment slashes in defines, bug845. 2014-11-12 16:37:51 -05:00
Wilson Snyder 62eb247c1e Optimize SUB/ADD together. 2014-11-09 18:33:54 -05:00
Wilson Snyder c5fd583b2c Fix select when partially out-of-bound, bug823. 2014-11-09 18:29:52 -05:00
Wilson Snyder 117db3e11c Trace_off now operates on cells, bug826. 2014-11-08 14:15:10 -05:00
Wilson Snyder 3f82fd2f37 Add public enums, bug833. 2014-11-07 07:50:11 -05:00
Wilson Snyder e9c46afcf7 Fix public parameters in unused packages, bug804. 2014-11-06 17:53:01 -05:00
Wilson Snyder 3234fa15ef Fix trace overflow on huge arrays, bug834. 2014-11-05 22:22:27 -05:00
Jie Xu 7ef84df852 Add optimization of wires from arrayed cells, msg1447.
Signed-off-by: Wilson Snyder <[email protected]>
2014-11-05 21:09:35 -05:00
Jie Xu 4e2884b509 Optimize e.g. {(b<<4)[7:4], (b<<4)[3:0]}. From assignmerge tree.
Signed-off-by: Wilson Snyder <[email protected]>
2014-11-05 20:58:36 -05:00
Wilson Snyder 03100020ab Fix not tracing modules following primitives, bug837. 2014-11-04 07:49:03 -05:00
Wilson Snyder 8bfb5cc5e9 Internals: Add sameGateTree. 2014-11-02 19:52:49 -05:00
Wilson Snyder cf6d07aafa Add optimization of operators between concats, msg1447. 2014-10-22 21:44:41 -04:00
Wilson Snyder 85c3179dbd Commentary 2014-10-21 19:11:46 -04:00
Wilson Snyder bfbca34eb0 Fix cast-to-size context-determined sizing, bug828. 2014-10-17 19:01:04 -04:00
Wilson Snyder b73edc0564 Fix generate unrolling with function call, bug830. 2014-10-15 21:29:37 -04:00
Wilson Snyder 6ba90e3a50 devel release 2014-09-21 09:06:40 -04:00
Wilson Snyder e8edbad18c Version bump 2014-09-21 09:04:36 -04:00
Wilson Snyder c86fec5307 Fix string formats under deep expressions, bug820. 2014-09-21 08:52:09 -04:00
Wilson Snyder 6e476255ca Support power operator with real, bug809. 2014-09-21 08:24:44 -04:00
Wilson Snyder 27af9b6b06 Fix clang warnings, bug818. 2014-09-11 21:28:53 -04:00
Wilson Snyder f8208fa961 Print Aborting before aborting, bug819 2014-09-05 21:40:04 -04:00
Wilson Snyder 87b9cb49ad Fix / multi-argument ordering, bug816. 2014-09-04 22:25:19 -04:00
Wilson Snyder b2da0772e6 Commentary 2014-09-04 22:15:11 -04:00
Wilson Snyder 4f73e0850e Improve verilator_profcfunc time attributions. 2014-08-28 22:10:39 -04:00
Wilson Snyder b6a39db627 Fix optional parameter keyword in module #(), bug810. 2014-08-27 07:57:20 -04:00
Wilson Snyder 3a83b06572 Fix over-shift structure optimization error, bug803. 2014-07-28 07:31:01 -04:00
Wilson Snyder fe5bf01b25 Fix dpiGetContext in dotted scopes, bug740. 2014-07-21 20:55:52 -04:00
Wilson Snyder 5559ec903b Fix error when tracing public parameters, bug722. 2014-07-21 20:44:33 -04:00
Wilson Snyder 18750028b2 Fix mis-optimization of bit-swap in wide signal, bug800. 2014-07-04 09:13:59 -04:00
Wilson Snyder 6b88648c67 Commentary, bug799 2014-07-02 21:04:51 -04:00
Wilson Snyder 58ee803cb4 Fix test GCC warning, bug794. 2014-06-26 21:45:14 -04:00
Wilson Snyder 894ff73c7d Internals: Fix clang warning, bug791. 2014-06-19 18:02:42 -04:00
Wilson Snyder 8031f0ed7f Fix duplicate anonymous structures in , bug788. 2014-06-15 11:18:47 -04:00
Wilson Snyder 3a56b5da47 devel release 2014-06-10 20:43:10 -04:00
91 changed files with 2456 additions and 451 deletions
+52
View File
@@ -3,6 +3,58 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.866 2014-11-15
*** Fix +define+A+B to define A and B to match other simulators, bug847. [Adam Krolnik]
*** Add optimization of wires from arrayed cells, msg1447. [Jie Xu]
*** Add optimization of operators between concats, msg1447. [Jie Xu]
*** Add public enums, bug833. [Jonathon Donaldson]
*** Trace_off now operates on cells, bug826. [Lane Brooks]
**** Fix public parameters in unused packages, bug804. [Jonathon Donaldson]
**** Fix select when partially out-of-bound, bug823. [Cliffort Wolf]
**** Fix generate unrolling with function call, bug830. [Steven Slatter]
**** Fix cast-to-size context-determined sizing, bug828. [Geoff Barrett]
**** Fix not tracing modules following primitives, bug837. [Jie Xu]
**** Fix trace overflow on huge arrays, bug834. [Geoff Barrett]
**** Fix quoted comment slashes in defines, bug845. [Adam Krolnik]
* Verilator 3.864 2014-09-21
*** Support power operator with real, bug809. [Jonathon Donaldson]
**** Improve verilator_profcfunc time attributions. [Jonathon Donaldson]
**** Fix duplicate anonymous structures in $root, bug788. [Bob Newgard]
**** Fix mis-optimization of bit-swap in wide signal, bug800. [Jie Xu]
**** Fix error when tracing public parameters, bug722. [Jonathon Donaldson]
**** Fix dpiGetContext in dotted scopes, bug740. [Geoff Barrett]
**** Fix over-shift structure optimization error, bug803. [Jeff Bush]
**** Fix optional parameter keyword in module #(), bug810. [Iztok Jeras]
**** Fix $warning/$error multi-argument ordering, bug816. [Jonathon Donaldson]
**** Fix clang warnings, bug818. [Iztok Jeras]
**** Fix string formats under deep expressions, bug820. [Iztok Jeras]
* Verilator 3.862 2014-06-10 * Verilator 3.862 2014-06-10
*** Using command line -Wno-{WARNING} now overrides file-local lint_on. *** Using command line -Wno-{WARNING} now overrides file-local lint_on.
+35 -17
View File
@@ -267,7 +267,7 @@ descriptions in the next sections for more information.
--debugi <level> Enable debugging at a specified level --debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level --debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse --default-language <lang> Default language to parse
+define+<var>+<value> Set preprocessor define +define+<var>=<value> Set preprocessor define
--dump-tree Enable dumping .tree files --dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level --dump-treei <level> Enable dumping .tree files at a level
-E Preprocess, but do not compile -E Preprocess, but do not compile
@@ -572,13 +572,16 @@ the comment "DefaultClock":
=item -DI<var>=I<value> =item -DI<var>=I<value>
Defines the given preprocessor symbol. Same as +define; +define is fairly Defines the given preprocessor symbol, without allowing. Similar to
standard across Verilog tools while -D is an alias for GCC compatibility. +define; +define is fairly standard across Verilog tools while -D is an
alias for GCC compatibility.
=item --debug =item --debug
Select the debug built image of Verilator (if available), and enable more Select the debug built image of Verilator (if available), and enable more
internal assertions, debugging messages, and intermediate form dump files. internal assertions (equivelent to C<--debug-check>), debugging messages
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
to C<--dump-tree>).
=item --debug-check =item --debug-check
@@ -590,9 +593,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi-<srcfile> <level> =item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally Rarely needed - for developer use. Set internal debugging level globally
to the specified debug level (1-10) or set the specified source file to the to the specified debug level (1-10) or set the specified Verilator source
specified level. Higher levels produce more detailed messages (plain file to the specified level (e.g. C<--debugi-V3Width 9>). Higher levels
C<--debug> is equivalent to C<--debugi 4>). produce more detailed messages.
=item --default-language I<value> =item --default-language I<value>
@@ -613,10 +616,13 @@ used.
If no language is specified, either by this flag or +I<lang>ext+ options, If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used. then the latest SystemVerilog language (IEEE 1800-2012) is used.
=item +define+I<var>+I<value> =item +define+I<var>=I<value>
Defines the given preprocessor symbol. Same as -D; +define is fairly =item +define+I<var>=I<value>+I<var2>=I<value2>...
standard across Verilog tools while -D is an alias for GCC compatibility.
Defines the given preprocessor symbol, or multiple symbols if separated by
plusses. Similar to -D; +define is fairly standard across Verilog tools
while -D is an alias for GCC compatibility.
=item --dump-tree =item --dump-tree
@@ -782,8 +788,10 @@ Disables optimization of the model.
=item -O3 =item -O3
Enables slow optimizations. This may reduce simulation runtimes at the Enables slow optimizations for the code Verilator itself generates (as
cost of compile time. This currently sets --inline-mult -1. opposed to "-CFLAGS -O3" which effects the C compiler's optimization. -O3
may reduce simulation runtimes at the cost of compile time. This currently
sets --inline-mult -1.
=item -OI<optimization-letter> =item -OI<optimization-letter>
@@ -2247,6 +2255,14 @@ reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself. be pure; they cannot reference any variables outside the task itself.
=item /*verilator public*/ (typedef enum)
Used after an enum typedef declaration to indicate the emitted C code
should have the enum values visible. Due to C++ language restrictions, this
may only be used on 64-bit or narrower integral enumerations.
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
=item /*verilator public*/ (variable) =item /*verilator public*/ (variable)
Used after an input, output, register, or wire declaration to indicate the Used after an input, output, register, or wire declaration to indicate the
@@ -2334,12 +2350,14 @@ behavior. See the test_regress/t/t_dpi_display.v file for an example.
=item /*verilator tracing_off*/ =item /*verilator tracing_off*/
Disable waveform tracing for all future signals that are declared in this Disable waveform tracing for all future signals that are declared in this
module. Often this is placed just after a primitive's module statement, so module, or cells below this module. Often this is placed just after a
that the entire module is not traced. primitive's module statement, so that the entire module and cells below it
are not traced.
=item /*verilator tracing_on*/ =item /*verilator tracing_on*/
Re-enable waveform tracing for all future signals that are declared. Re-enable waveform tracing for all future signals or cells that are
declared.
=back =back
@@ -2968,8 +2986,8 @@ simulators.
Warns that an `include filename specifies an absolute path. This means the Warns that an `include filename specifies an absolute path. This means the
code will not work on any other system with a different file system layout. code will not work on any other system with a different file system layout.
Instead of using absolute paths, relative paths (preferably without any Instead of using absolute paths, relative paths (preferably without any
directory specified whatever) should be used, and +include used on the directory specified whatever) should be used, and +incdir used on the
command line to specify the top include source directory. command line to specify the top include source directories.
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.
+15 -1
View File
@@ -118,6 +118,18 @@ sub profcfunc {
$groups{type}{"Common code under $design"} += $pct; $groups{type}{"Common code under $design"} += $pct;
$groups{design}{$design} += $pct; $groups{design}{$design} += $pct;
$groups{module}{$design." common code"} += $pct; $groups{module}{$design." common code"} += $pct;
} elsif ($func =~ /^VL_[A-Z0-9_]+/
|| $func =~ /^_?vl_[a-zA-Z0-9_]+/
|| $func =~ /^verilated/i) {
$vfunc = sprintf("VLib %s", $func);
$groups{type}{'VLib'} += $pct;
$groups{design}{'VLib'} += $pct;
$groups{module}{'VLib'} += $pct;
} elsif ($func =~ /^_mcount_private/) {
$vfunc = sprintf("Prof %s", $func);
$groups{type}{'Prof'} += $pct;
$groups{design}{'Prof'} += $pct;
$groups{module}{'Prof'} += $pct;
} else { } else {
$vfunc = sprintf("C++ %s", $func); $vfunc = sprintf("C++ %s", $func);
$groups{type}{'C++'} += $pct; $groups{type}{'C++'} += $pct;
@@ -129,7 +141,7 @@ sub profcfunc {
} }
foreach my $type qw(type design module) { foreach my $type (qw(type design module)) {
my $missing = 100; my $missing = 100;
foreach (sort (keys %{$groups{$type}})) { foreach (sort (keys %{$groups{$type}})) {
$missing -= $groups{$type}{$_}; $missing -= $groups{$type}{$_};
@@ -150,8 +162,10 @@ sub profcfunc {
print("Verilog code profile:\n"); print("Verilog code profile:\n");
print(" These are split into three categories:\n"); print(" These are split into three categories:\n");
print(" C++: Time in non-Verilated C++ code\n"); print(" C++: Time in non-Verilated C++ code\n");
print(" Prof: Time in profile overhead\n");
print(" VBlock: Time attributable to a block in a Verilog file and line\n"); print(" VBlock: Time attributable to a block in a Verilog file and line\n");
print(" VCommon: Time in a Verilated module, due to all parts of the design\n"); print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
print(" VLib: Time in Verilated common libraries, called by the Verilated code\n");
print("\n"); print("\n");
print(" % cumulative self \n"); print(" % cumulative self \n");
+4 -2
View File
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel]) #AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.862 2014-06-10]) AC_INIT([Verilator],[3.866 2014-11-15])
AC_CONFIG_HEADER(src/config_build.h) AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h) AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
@@ -122,15 +122,17 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
# For example, -Wno-div-by-zero isn't in 4.1.2 # For example, -Wno-div-by-zero isn't in 4.1.2
_MY_CXX_CHECK_OPT(-Wno-char-subscripts) _MY_CXX_CHECK_OPT(-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(-Wno-parentheses-equality)
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn # Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
# without this flag, even though there's a conditional to prevent the divide. # without this flag, even though there's a conditional to prevent the divide.
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die. # We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero) #_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
_MY_CXX_CHECK_OPT(-Wno-sign-compare) _MY_CXX_CHECK_OPT(-Wno-sign-compare)
_MY_CXX_CHECK_OPT(-Wno-uninitialized) _MY_CXX_CHECK_OPT(-Wno-uninitialized)
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
_MY_CXX_CHECK_OPT(-Wno-unused-parameter) _MY_CXX_CHECK_OPT(-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(-Wno-unused-variable) _MY_CXX_CHECK_OPT(-Wno-unused-variable)
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable) _MY_CXX_CHECK_OPT(-fbracket-depth=4096)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED) AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Checks for library functions. # Checks for library functions.
+3
View File
@@ -74,6 +74,9 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
Verilated::gotFinish(true); Verilated::gotFinish(true);
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg); VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
Verilated::flushCall(); Verilated::flushCall();
VL_PRINTF("Aborting...\n");
Verilated::flushCall(); // Second flush in case VL_PRINTF does something needing a flush
abort(); abort();
} }
#endif #endif
+3 -2
View File
@@ -43,14 +43,14 @@ VK_CPPFLAGS_ALWAYS += \
-DVL_PRINTF=printf \ -DVL_PRINTF=printf \
-DVM_TRACE=$(VM_TRACE) \ -DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \ -DVM_COVERAGE=$(VM_COVERAGE) \
$(CFG_CXXFLAGS_NO_UNUSED) \
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
VK_CPPFLAGS_WALL += -Wall \ VK_CPPFLAGS_WALL += -Wall \
$(CFG_CXXFLAGS_NO_UNUSED) \
-Werror -Werror
endif endif
CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL) CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
VPATH += .. VPATH += ..
VPATH += $(VERILATOR_ROOT)/include VPATH += $(VERILATOR_ROOT)/include
@@ -195,6 +195,7 @@ debug-make::
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW) @echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST) @echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW) @echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
@echo CPPFLAGS: $(CPPFLAGS)
@echo @echo
###################################################################### ######################################################################
+20 -3
View File
@@ -261,6 +261,20 @@ void VerilatedVcd::printTime (vluint64_t timeui) {
printQuad(timeui); printQuad(timeui);
} }
void VerilatedVcd::bufferResize(vluint64_t minsize) {
// minsize is size of largest write. We buffer at least 8 times as much data,
// writing when we are 3/4 full (with thus 2*minsize remaining free)
if (VL_UNLIKELY(minsize > m_wrChunkSize)) {
char* oldbufp = m_wrBufp;
m_wrChunkSize = minsize*2;
m_wrBufp = new char [m_wrChunkSize * 8];
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
m_writep = m_wrBufp + (m_writep - oldbufp);
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
delete oldbufp; oldbufp=NULL;
}
}
void VerilatedVcd::bufferFlush () { void VerilatedVcd::bufferFlush () {
// We add output data to m_writep. // We add output data to m_writep.
// When it gets nearly full we dump it using this routine which calls write() // When it gets nearly full we dump it using this routine which calls write()
@@ -444,6 +458,9 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
} }
// Make sure write buffer is large enough (one character per bit), plus header
bufferResize(bits+1024);
// Save declaration info // Save declaration info
VerilatedVcdSig sig = VerilatedVcdSig(code, bits); VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
m_sigs.push_back(sig); m_sigs.push_back(sig);
@@ -522,7 +539,7 @@ void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) { void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
(*((double*)&m_sigs_oldvalp[code])) = newval; (*((double*)&m_sigs_oldvalp[code])) = newval;
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes) // Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", newval); sprintf(m_writep, "r%.16g", newval);
m_writep += strlen(m_writep); m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++=' '; printCode(code); *m_writep++='\n';
@@ -530,7 +547,7 @@ void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
} }
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) { void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
(*((float*)&m_sigs_oldvalp[code])) = newval; (*((float*)&m_sigs_oldvalp[code])) = newval;
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes) // Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", (double)newval); sprintf(m_writep, "r%.16g", (double)newval);
m_writep += strlen(m_writep); m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++=' '; printCode(code); *m_writep++='\n';
@@ -703,5 +720,5 @@ main() {
//******************************************************************** //********************************************************************
// Local Variables: // Local Variables:
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && g++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd" // compile-command: "mkdir -p ../test_dir && cd ../test_dir && c++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
// End: // End:
+10 -7
View File
@@ -77,7 +77,9 @@ private:
vluint64_t m_timeLastDump; ///< Last time we did a dump vluint64_t m_timeLastDump; ///< Last time we did a dump
char* m_wrBufp; ///< Output buffer char* m_wrBufp; ///< Output buffer
char* m_wrFlushp; ///< Output buffer flush trigger location
char* m_writep; ///< Write pointer into output buffer char* m_writep; ///< Write pointer into output buffer
vluint64_t m_wrChunkSize; ///< Output buffer size
vluint64_t m_wroteBytes; ///< Number of bytes written to this file vluint64_t m_wroteBytes; ///< Number of bytes written to this file
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
@@ -87,13 +89,12 @@ private:
NameMap* m_namemapp; ///< List of names for the header NameMap* m_namemapp; ///< List of names for the header
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation void bufferResize(vluint64_t minsize);
inline static size_t bufferInsertSize() { return 16*1024; }
void bufferFlush(); void bufferFlush();
void bufferCheck() { inline void bufferCheck() {
// Flush the write buffer if there's not enough space left for new information // Flush the write buffer if there's not enough space left for new information
// We only call this once per vector, so we need enough slop for a very wide "b###" line // We only call this once per vector, so we need enough slop for a very wide "b###" line
if (VL_UNLIKELY(m_writep > (m_wrBufp+(bufferSize()-bufferInsertSize())))) { if (VL_UNLIKELY(m_writep > m_wrFlushp)) {
bufferFlush(); bufferFlush();
} }
} }
@@ -135,17 +136,19 @@ protected:
public: public:
// CREATORS // CREATORS
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) { VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
m_wrBufp = new char [bufferSize()];
m_writep = m_wrBufp;
m_namemapp = NULL; m_namemapp = NULL;
m_timeRes = m_timeUnit = 1e-9; m_timeRes = m_timeUnit = 1e-9;
m_timeLastDump = 0; m_timeLastDump = 0;
m_sigs_oldvalp = NULL; m_sigs_oldvalp = NULL;
m_evcd = false; m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility m_scopeEscape = '.'; // Backward compatibility
m_wroteBytes = 0;
m_fd = 0; m_fd = 0;
m_fullDump = true; m_fullDump = true;
m_wrChunkSize = 8*1024;
m_wrBufp = new char [m_wrChunkSize*8];
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
m_writep = m_wrBufp;
m_wroteBytes = 0;
} }
~VerilatedVcd(); ~VerilatedVcd();
+11 -11
View File
@@ -97,8 +97,8 @@ public:
virtual const char* fullname() { return "<null>"; } virtual const char* fullname() { return "<null>"; }
virtual const char* defname() { return "<null>"; } virtual const char* defname() { return "<null>"; }
virtual const vluint32_t type() { return 0; } virtual const vluint32_t type() { return 0; }
virtual const vluint32_t size() { return 0; } virtual const vluint32_t size() const { return 0; }
virtual const VerilatedRange* rangep() { return 0; } virtual const VerilatedRange* rangep() const { return NULL; }
virtual vpiHandle dovpi_scan() { return 0; } virtual vpiHandle dovpi_scan() { return 0; }
}; };
@@ -136,7 +136,7 @@ public:
class VerilatedVpioRange : public VerilatedVpio { class VerilatedVpioRange : public VerilatedVpio {
const VerilatedRange* m_range; const VerilatedRange* m_range;
bool m_iteration; vlsint32_t m_iteration;
public: public:
VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {} VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
virtual ~VerilatedVpioRange() {} virtual ~VerilatedVpioRange() {}
@@ -182,7 +182,7 @@ class VerilatedVpioVar : public VerilatedVpio {
protected: protected:
void* m_varDatap; // varp()->datap() adjusted for array entries void* m_varDatap; // varp()->datap() adjusted for array entries
vlsint32_t m_index; vlsint32_t m_index;
const VerilatedRange& get_range() { const VerilatedRange& get_range() const {
// Determine number of dimensions and return outermost // Determine number of dimensions and return outermost
return (m_varp->dims()>1) ? m_varp->array() : m_varp->range(); return (m_varp->dims()>1) ? m_varp->array() : m_varp->range();
} }
@@ -208,8 +208,8 @@ public:
if (varp()->vldir() != vpiNoDirection) return vpiPort; if (varp()->vldir() != vpiNoDirection) return vpiPort;
return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */ return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
} }
virtual const vluint32_t size() { return get_range().elements(); } virtual const vluint32_t size() const { return get_range().elements(); }
virtual const VerilatedRange* rangep() { return &get_range(); } virtual const VerilatedRange* rangep() const { return &get_range(); }
virtual const char* name() { return m_varp->name(); } virtual const char* name() { return m_varp->name(); }
virtual const char* fullname() { virtual const char* fullname() {
VL_STATIC_OR_THREAD string out; VL_STATIC_OR_THREAD string out;
@@ -237,8 +237,8 @@ public:
virtual ~VerilatedVpioMemoryWord() {} virtual ~VerilatedVpioMemoryWord() {}
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); } static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiMemoryWord; } virtual const vluint32_t type() { return vpiMemoryWord; }
virtual const vluint32_t size() { return varp()->range().elements(); } virtual const vluint32_t size() const { return varp()->range().elements(); }
virtual const VerilatedRange* rangep() { return &(varp()->range()); } virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
virtual const char* fullname() { virtual const char* fullname() {
VL_STATIC_OR_THREAD string out; VL_STATIC_OR_THREAD string out;
char num[20]; sprintf(num,"%d",m_index); char num[20]; sprintf(num,"%d",m_index);
@@ -919,9 +919,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
value_p->value.str = outStr; value_p->value.str = outStr;
switch (vop->varp()->vltype()) { switch (vop->varp()->vltype()) {
// outStrSz does not include NULL termination so add one // outStrSz does not include NULL termination so add one
case VLVT_UINT8 : snprintf(outStr, outStrSz+1, "%hhu", (unsigned int)*((CData*)(vop->varDatap()))); return; case VLVT_UINT8 : snprintf(outStr, outStrSz+1, "%hhu", (unsigned char )*((CData*)(vop->varDatap()))); return;
case VLVT_UINT16: snprintf(outStr, outStrSz+1, "%hu", (unsigned int)*((SData*)(vop->varDatap()))); return; case VLVT_UINT16: snprintf(outStr, outStrSz+1, "%hu", (unsigned short)*((SData*)(vop->varDatap()))); return;
case VLVT_UINT32: snprintf(outStr, outStrSz+1, "%u", (unsigned int)*((IData*)(vop->varDatap()))); return; case VLVT_UINT32: snprintf(outStr, outStrSz+1, "%u", (unsigned int )*((IData*)(vop->varDatap()))); return;
case VLVT_UINT64: snprintf(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return; case VLVT_UINT64: snprintf(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return;
default: default:
strcpy(outStr, "-1"); strcpy(outStr, "-1");
+6 -3
View File
@@ -61,10 +61,13 @@ private:
void replaceDisplay(AstDisplay* nodep, const string& prefix) { void replaceDisplay(AstDisplay* nodep, const string& prefix) {
nodep->displayType(AstDisplayType::DT_WRITE); nodep->displayType(AstDisplayType::DT_WRITE);
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text())); nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
// cppcheck-suppress nullPointer // cppcheck-suppress nullPointer
timesp = timesp->addNext(new AstTime(nodep->fileline())); AstNode* timenewp = new AstTime(nodep->fileline());
nodep->fmtp()->exprsp(timesp); if (AstNode* timesp = nodep->fmtp()->exprsp()) {
timesp->unlinkFrBackWithNext();
timenewp->addNext(timesp);
}
nodep->fmtp()->exprsp(timenewp);
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) { if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline())); nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
} }
+8 -11
View File
@@ -884,24 +884,21 @@ void AstNode::cloneRelinkTree() {
//====================================================================== //======================================================================
// Comparison // Comparison
bool AstNode::sameTree(AstNode* node2p) { bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
return sameTreeIter(node2p, true);
}
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
// Return true if the two trees are identical // Return true if the two trees are identical
if (this==NULL && node2p==NULL) return true; if (this==NULL && node2p==NULL) return true;
if (this==NULL || node2p==NULL) return false; if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type() if (this->type() != node2p->type()
|| this->dtypep() != node2p->dtypep() || this->dtypep() != node2p->dtypep()
|| !this->same(node2p)) { || !this->same(node2p)
|| (gateOnly && !this->isGateOptimizable())) {
return false; return false;
} }
return (this->op1p()->sameTreeIter(node2p->op1p(),false) return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
&& this->op2p()->sameTreeIter(node2p->op2p(),false) && this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
&& this->op3p()->sameTreeIter(node2p->op3p(),false) && this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
&& this->op4p()->sameTreeIter(node2p->op4p(),false) && this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false)) && (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
); );
} }
+55 -28
View File
@@ -236,6 +236,8 @@ public:
DIM_SIZE, // V3Width processes DIM_SIZE, // V3Width processes
DIM_UNPK_DIMENSIONS, // V3Width converts to constant DIM_UNPK_DIMENSIONS, // V3Width converts to constant
// //
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
//
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
// //
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@@ -255,6 +257,7 @@ public:
"%E-AT", "%E-AT",
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT", "DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS", "DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
"DT_PUBLIC",
"MEMBER_BASE", "MEMBER_BASE",
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW", "VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
@@ -932,7 +935,7 @@ class AstNode {
AstNode* cloneTreeIterList(); AstNode* cloneTreeIterList();
void checkTreeIter(AstNode* backp); void checkTreeIter(AstNode* backp);
void checkTreeIterList(AstNode* backp); void checkTreeIterList(AstNode* backp);
bool sameTreeIter(AstNode* node2p, bool ignNext); bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
void deleteTreeIter(); void deleteTreeIter();
void deleteNode(); void deleteNode();
static void relinkOneLink(AstNode*& pointpr, AstNode* newp); static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
@@ -1158,6 +1161,7 @@ public:
// METHODS - Iterate on a tree // METHODS - Iterate on a tree
AstNode* cloneTree(bool cloneNextLink); AstNode* cloneTree(bool cloneNextLink);
bool sameTree(AstNode* node2p); // Does tree of this == node2p? bool sameTree(AstNode* node2p); // Does tree of this == node2p?
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
void deleteTree(); // Always deletes the next link void deleteTree(); // Always deletes the next link
void checkTree(); // User Interface version void checkTree(); // User Interface version
void checkIter() const; void checkIter() const;
@@ -1216,8 +1220,9 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
virtual ~Ast ##name() {} \ virtual ~Ast ##name() {} \
Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##name(); } Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##name(); }
struct AstNodeMath : public AstNode { class AstNodeMath : public AstNode {
// Math -- anything that's part of an expression tree // Math -- anything that's part of an expression tree
public:
AstNodeMath(FileLine* fl) AstNodeMath(FileLine* fl)
: AstNode(fl) {} : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeMath) ASTNODE_BASE_FUNCS(NodeMath)
@@ -1232,8 +1237,9 @@ struct AstNodeMath : public AstNode {
bool isOpaque() { return castCvtPackString()!=NULL; } bool isOpaque() { return castCvtPackString()!=NULL; }
}; };
struct AstNodeTermop : public AstNodeMath { class AstNodeTermop : public AstNodeMath {
// Terminal operator -- a operator with no "inputs" // Terminal operator -- a operator with no "inputs"
public:
AstNodeTermop(FileLine* fl) AstNodeTermop(FileLine* fl)
: AstNodeMath(fl) {} : AstNodeMath(fl) {}
ASTNODE_BASE_FUNCS(NodeTermop) ASTNODE_BASE_FUNCS(NodeTermop)
@@ -1243,8 +1249,9 @@ struct AstNodeTermop : public AstNodeMath {
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
struct AstNodeUniop : public AstNodeMath { class AstNodeUniop : public AstNodeMath {
// Unary math // Unary math
public:
AstNodeUniop(FileLine* fl, AstNode* lhsp) AstNodeUniop(FileLine* fl, AstNode* lhsp)
: AstNodeMath(fl) { : AstNodeMath(fl) {
dtypeFrom(lhsp); dtypeFrom(lhsp);
@@ -1263,8 +1270,9 @@ struct AstNodeUniop : public AstNodeMath {
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeBiop : public AstNodeMath { class AstNodeBiop : public AstNodeMath {
// Binary math // Binary math
public:
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs) AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeMath(fl) { : AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); } setOp1p(lhs); setOp2p(rhs); }
@@ -1286,8 +1294,9 @@ struct AstNodeBiop : public AstNodeMath {
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeTriop : public AstNodeMath { class AstNodeTriop : public AstNodeMath {
// Trinary math // Trinary math
public:
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNodeMath(fl) { : AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); } setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
@@ -1311,20 +1320,23 @@ struct AstNodeTriop : public AstNodeMath {
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeBiCom : public AstNodeBiop { class AstNodeBiCom : public AstNodeBiop {
// Binary math with commutative properties // Binary math with commutative properties
public:
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs) AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiop(fl, lhs, rhs) {} : AstNodeBiop(fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiCom) ASTNODE_BASE_FUNCS(NodeBiCom)
}; };
struct AstNodeBiComAsv : public AstNodeBiCom { class AstNodeBiComAsv : public AstNodeBiCom {
// Binary math with commutative & associative properties // Binary math with commutative & associative properties
public:
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs) AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiCom(fl, lhs, rhs) {} : AstNodeBiCom(fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiComAsv) ASTNODE_BASE_FUNCS(NodeBiComAsv)
}; };
struct AstNodeCond : public AstNodeTriop { class AstNodeCond : public AstNodeTriop {
public:
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop(fl, condp, expr1p, expr2p) { : AstNodeTriop(fl, condp, expr1p, expr2p) {
if (expr1p) dtypeFrom(expr1p); if (expr1p) dtypeFrom(expr1p);
@@ -1346,8 +1358,9 @@ struct AstNodeCond : public AstNodeTriop {
virtual int instrCount() const { return instrCountBranch(); } virtual int instrCount() const { return instrCountBranch(); }
}; };
struct AstNodePreSel : public AstNode { class AstNodePreSel : public AstNode {
// Something that becomes an AstSel // Something that becomes an AstSel
public:
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNode(fl) { : AstNode(fl) {
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); } setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
@@ -1366,8 +1379,9 @@ struct AstNodePreSel : public AstNode {
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeStmt : public AstNode { class AstNodeStmt : public AstNode {
// Statement -- anything that's directly under a function // Statement -- anything that's directly under a function
public:
AstNodeStmt(FileLine* fl) AstNodeStmt(FileLine* fl)
: AstNode(fl) {} : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeStmt) ASTNODE_BASE_FUNCS(NodeStmt)
@@ -1376,7 +1390,8 @@ struct AstNodeStmt : public AstNode {
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
}; };
struct AstNodeAssign : public AstNodeStmt { class AstNodeAssign : public AstNodeStmt {
public:
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp) AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt(fl) { : AstNodeStmt(fl) {
setOp1p(rhsp); setOp2p(lhsp); setOp1p(rhsp); setOp2p(lhsp);
@@ -1397,7 +1412,8 @@ struct AstNodeAssign : public AstNodeStmt {
virtual string verilogKwd() const { return "="; } virtual string verilogKwd() const { return "="; }
}; };
struct AstNodeFor : public AstNodeStmt { class AstNodeFor : public AstNodeStmt {
public:
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp, AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* incsp, AstNode* bodysp) AstNode* incsp, AstNode* bodysp)
: AstNodeStmt(fileline) { : AstNodeStmt(fileline) {
@@ -1414,7 +1430,7 @@ struct AstNodeFor : public AstNodeStmt {
virtual bool same(AstNode* samep) const { return true; } virtual bool same(AstNode* samep) const { return true; }
}; };
struct AstNodeIf : public AstNodeStmt { class AstNodeIf : public AstNodeStmt {
private: private:
AstBranchPred m_branchPred; // Branch prediction as taken/untaken? AstBranchPred m_branchPred; // Branch prediction as taken/untaken?
public: public:
@@ -1438,7 +1454,8 @@ public:
AstBranchPred branchPred() const { return m_branchPred; } AstBranchPred branchPred() const { return m_branchPred; }
}; };
struct AstNodeCase : public AstNodeStmt { class AstNodeCase : public AstNodeStmt {
public:
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp) AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
: AstNodeStmt(fl) { : AstNodeStmt(fl) {
setOp1p(exprp); addNOp2p(casesp); setOp1p(exprp); addNOp2p(casesp);
@@ -1452,8 +1469,9 @@ struct AstNodeCase : public AstNodeStmt {
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
}; };
struct AstNodeSenItem : public AstNode { class AstNodeSenItem : public AstNode {
// An AstSenItem or AstSenGate // An AstSenItem or AstSenGate
public:
AstNodeSenItem(FileLine* fl) : AstNode(fl) {} AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeSenItem) ASTNODE_BASE_FUNCS(NodeSenItem)
virtual bool isClocked() const = 0; virtual bool isClocked() const = 0;
@@ -1511,7 +1529,7 @@ public:
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
struct AstNodeText : public AstNode { class AstNodeText : public AstNode {
private: private:
string m_text; string m_text;
public: public:
@@ -1528,11 +1546,11 @@ public:
const string& text() const { return m_text; } const string& text() const { return m_text; }
}; };
struct AstNodeDType : public AstNode { class AstNodeDType : public AstNode {
private:
// Ideally width() would migrate to BasicDType as that's where it makes sense, // Ideally width() would migrate to BasicDType as that's where it makes sense,
// but it's currently so prevalent in the code we leave it here. // but it's currently so prevalent in the code we leave it here.
// Note the below members are included in AstTypeTable::Key lookups // Note the below members are included in AstTypeTable::Key lookups
private:
int m_width; // (also in AstTypeTable::Key) Bit width of operation int m_width; // (also in AstTypeTable::Key) Bit width of operation
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
@@ -1550,8 +1568,9 @@ public:
virtual void dumpSmall(ostream& str); virtual void dumpSmall(ostream& str);
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs/const/enum to next non-typeref type
virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type
virtual AstNodeDType* skipRefToEnump() const = 0; // recurses over typedefs/const to next non-typeref-or-enum/struct type
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
@@ -1581,7 +1600,7 @@ public:
static int uniqueNumInc() { return ++s_uniqueNum; } static int uniqueNumInc() { return ++s_uniqueNum; }
}; };
struct AstNodeClassDType : public AstNodeDType { class AstNodeClassDType : public AstNodeDType {
private: private:
// TYPES // TYPES
typedef map<string,AstMemberDType*> MemberNameMap; typedef map<string,AstMemberDType*> MemberNameMap;
@@ -1602,6 +1621,7 @@ public:
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); } virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// op1 = members // op1 = members
@@ -1620,7 +1640,7 @@ public:
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); } VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
}; };
struct AstNodeArrayDType : public AstNodeDType { class AstNodeArrayDType : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]" // Array data type, ie "some_dtype var_name [2:0]"
// Children: DTYPE (moved to refDTypep() in V3Width) // Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds) // Children: RANGE (array bounds)
@@ -1658,6 +1678,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
int msb() const; int msb() const;
@@ -1666,8 +1687,9 @@ public:
VNumRange declRange() const; VNumRange declRange() const;
}; };
struct AstNodeSel : public AstNodeBiop { class AstNodeSel : public AstNodeBiop {
// Single bit range extraction, perhaps with non-constant selection or array selection // Single bit range extraction, perhaps with non-constant selection or array selection
public:
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp) AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeBiop(fl, fromp, bitp) {} :AstNodeBiop(fl, fromp, bitp) {}
ASTNODE_BASE_FUNCS(NodeSel) ASTNODE_BASE_FUNCS(NodeSel)
@@ -1679,8 +1701,9 @@ struct AstNodeSel : public AstNodeBiop {
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
}; };
struct AstNodeStream : public AstNodeBiop { class AstNodeStream : public AstNodeBiop {
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
public:
AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp->dtypep()) { if (lhsp->dtypep()) {
dtypeSetLogicSized(lhsp->dtypep()->width(), lhsp->dtypep()->width(), AstNumeric::UNSIGNED); dtypeSetLogicSized(lhsp->dtypep()->width(), lhsp->dtypep()->width(), AstNumeric::UNSIGNED);
@@ -1692,7 +1715,7 @@ struct AstNodeStream : public AstNodeBiop {
//###################################################################### //######################################################################
// Tasks/functions common handling // Tasks/functions common handling
struct AstNodeFTask : public AstNode { class AstNodeFTask : public AstNode {
private: private:
string m_name; // Name of task string m_name; // Name of task
string m_cname; // Name of task if DPI import string m_cname; // Name of task if DPI import
@@ -1750,7 +1773,7 @@ public:
bool pure() const { return m_pure; } bool pure() const { return m_pure; }
}; };
struct AstNodeFTaskRef : public AstNode { class AstNodeFTaskRef : public AstNode {
// A reference to a task (or function) // A reference to a task (or function)
private: private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
@@ -1796,7 +1819,7 @@ public:
void scopeNamep(AstNode* nodep) { setNOp3p(nodep); } void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
}; };
struct AstNodeModule : public AstNode { class AstNodeModule : public AstNode {
// A module, package, program or interface declaration; // A module, package, program or interface declaration;
// something that can live directly under the TOP, // something that can live directly under the TOP,
// excluding $unit package stuff // excluding $unit package stuff
@@ -1810,12 +1833,13 @@ private:
bool m_internal:1; // Internally created bool m_internal:1; // Internally created
int m_level; // 1=top module, 2=cell off top module, ... int m_level; // 1=top module, 2=cell off top module, ...
int m_varNum; // Incrementing variable number int m_varNum; // Incrementing variable number
int m_typeNum; // Incrementing implicit type number
public: public:
AstNodeModule(FileLine* fl, const string& name) AstNodeModule(FileLine* fl, const string& name)
: AstNode (fl) : AstNode (fl)
,m_name(name), m_origName(name) ,m_name(name), m_origName(name)
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false) ,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false)
,m_level(0), m_varNum(0) { } ,m_level(0), m_varNum(0), m_typeNum(0) { }
ASTNODE_BASE_FUNCS(NodeModule) ASTNODE_BASE_FUNCS(NodeModule)
virtual void dump(ostream& str); virtual void dump(ostream& str);
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
@@ -1835,6 +1859,7 @@ public:
int level() const { return m_level; } int level() const { return m_level; }
bool isTop() const { return level()==1; } bool isTop() const { return level()==1; }
int varNumGetInc() { return ++m_varNum; } int varNumGetInc() { return ++m_varNum; }
int typeNumGetInc() { return ++m_typeNum; }
void modPublic(bool flag) { m_modPublic = flag; } void modPublic(bool flag) { m_modPublic = flag; }
bool modPublic() const { return m_modPublic; } bool modPublic() const { return m_modPublic; }
void modTrace(bool flag) { m_modTrace = flag; } void modTrace(bool flag) { m_modTrace = flag; }
@@ -1868,6 +1893,8 @@ inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); } inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); } inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); } inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(node2p, true, false); }
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(node2p, true, true); }
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); } inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
+22
View File
@@ -515,6 +515,24 @@ string AstScopeName::scopeSymName() const {
return out; return out;
} }
string AstScopeName::scopeDpiName() const {
string out;
for (AstText* textp=scopeEntrp(); textp; textp=textp->nextp()->castText()) {
out += textp->text();
}
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
if (out.substr(0,1) == ".") out.replace(0,1,"");
string::size_type pos;
while ((pos=out.find(".")) != string::npos) {
out.replace(pos, 1, "__");
}
while ((pos=out.find("__DOT__")) != string::npos) {
out.replace(pos, 7, "__");
}
return out;
}
bool AstSenTree::hasClocked() { bool AstSenTree::hasClocked() {
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
@@ -801,6 +819,10 @@ void AstPin::dump(ostream& str) {
else { str<<" ->UNLINKED"; } else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]"; if (svImplicit()) str<<" [.SV]";
} }
void AstTypedef::dump(ostream& str) {
this->AstNode::dump(str);
if (attrPublic()) str<<" [PUBLIC]";
}
void AstRange::dump(ostream& str) { void AstRange::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (littleEndian()) str<<" [LITTLE]"; if (littleEndian()) str<<" [LITTLE]";
+439 -248
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -238,6 +238,10 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->valuep()); insureCleanAndNext (nodep->valuep());
} }
virtual void visit(AstTypedef* nodep, AstNUser*) {
// No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this);
}
// Control flow operators // Control flow operators
virtual void visit(AstNodeCond* nodep, AstNUser*) { virtual void visit(AstNodeCond* nodep, AstNUser*) {
+142 -6
View File
@@ -173,6 +173,16 @@ private:
if (rnodep->width() != bnodep->width()) return false; if (rnodep->width() != bnodep->width()) return false;
return rnodep->lhsp()->castConst(); return rnodep->lhsp()->castConst();
} }
static bool operandSubAdd(AstNode* nodep) {
// SUB( ADD(CONSTx,y), CONSTz) -> ADD(SUB(CONSTx,CONSTz), y)
AstNodeBiop* np = nodep->castNodeBiop();
AstNodeBiop* lp = np->lhsp()->castNodeBiop();
return (lp
&& lp->lhsp()->castConst()
&& np->rhsp()->castConst()
&& lp->width()==np->width());
}
static bool operandAndOrSame(AstNode* nodep) { static bool operandAndOrSame(AstNode* nodep) {
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y)) // OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL) // OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
@@ -418,12 +428,12 @@ private:
static bool operandsSame(AstNode* node1p, AstNode* node2p) { static bool operandsSame(AstNode* node1p, AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic // For now we just detect constants & simple vars, though it could be more generic
if (node1p->castConst() && node2p->castConst()) { if (node1p->castConst() && node2p->castConst()) {
return node1p->sameTree(node2p); return node1p->sameGateTree(node2p);
} }
else if (node1p->castVarRef() && node2p->castVarRef()) { else if (node1p->castVarRef() && node2p->castVarRef()) {
// Avoid comparing widthMin's, which results in lost optimization attempts // Avoid comparing widthMin's, which results in lost optimization attempts
// If cleanup sameTree to be smarter, this can be restored. // If cleanup sameGateTree to be smarter, this can be restored.
//return node1p->sameTree(node2p); //return node1p->sameGateTree(node2p);
return node1p->same(node2p); return node1p->same(node2p);
} else { } else {
return false; return false;
@@ -439,7 +449,7 @@ private:
AstVarRef* elsevarp = elsep->lhsp()->castVarRef(); AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
if (!ifvarp || !elsevarp) return false; if (!ifvarp || !elsevarp) return false;
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
if (!ifvarp->sameTree(elsevarp)) return false; if (!ifvarp->sameGateTree(elsevarp)) return false;
return true; return true;
} }
bool operandIfIf(AstNodeIf* nodep) { bool operandIfIf(AstNodeIf* nodep) {
@@ -450,6 +460,89 @@ private:
if (afterComment(lowerIfp->elsesp())) return false; if (afterComment(lowerIfp->elsesp())) return false;
return true; return true;
} }
bool ifConcatMergeableBiop(AstNode* nodep) {
return (nodep->castAnd()
|| nodep->castOr()
|| nodep->castXor()
|| nodep->castXnor());
}
bool ifAdjacentSel(AstSel* lhsp, AstSel* rhsp) {
if (!v3Global.opt.oAssemble()) return false; // opt disabled
if (!lhsp || !rhsp) return false;
AstNode* lfromp = lhsp->fromp();
AstNode* rfromp = rhsp->fromp();
if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
AstConst* lstart = lhsp->lsbp()->castConst();
AstConst* rstart = rhsp->lsbp()->castConst();
AstConst* lwidth = lhsp->widthp()->castConst();
AstConst* rwidth = rhsp->widthp()->castConst();
if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated
int rend = (rstart->toSInt() + rwidth->toSInt());
if (rend == lstart->toSInt()) return true;
return false;
}
bool ifMergeAdjacent(AstNode* lhsp, AstNode* rhsp) {
// called by concatmergeable to determine if {lhsp, rhsp} make sense
if (!v3Global.opt.oAssemble()) return false; // opt disabled
// two same varref
if (operandsSame(lhsp, rhsp)) return true;
AstSel* lselp = lhsp->castSel();
AstSel* rselp = rhsp->castSel();
// a[i:0] a
if (lselp && !rselp && rhsp->sameGateTree(lselp->fromp()))
rselp = new AstSel(rhsp->fileline(), rhsp->cloneTree(false), 0, rhsp->width());
// a[i:j] {a[j-1:k], b}
if (lselp && !rselp && rhsp->castConcat())
return ifMergeAdjacent(lhsp, rhsp->castConcat()->lhsp());
// a a[msb:j]
if (rselp && !lselp && lhsp->sameGateTree(rselp->fromp()))
lselp = new AstSel(lhsp->fileline(), lhsp->cloneTree(false), 0, lhsp->width());
// {b, a[j:k]} a[k-1:i]
if (rselp && !lselp && lhsp->castConcat())
return ifMergeAdjacent(lhsp->castConcat()->rhsp(), rhsp);
if (!lselp || !rselp) return false;
// a[a:b] a[b-1:c] are adjacent
AstNode* lfromp = lselp->fromp();
AstNode* rfromp = rselp->fromp();
if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
AstConst* lstart = lselp->lsbp()->castConst();
AstConst* rstart = rselp->lsbp()->castConst();
AstConst* lwidth = lselp->widthp()->castConst();
AstConst* rwidth = rselp->widthp()->castConst();
if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated
int rend = (rstart->toSInt() + rwidth->toSInt());
// a[i:j] a[j-1:k]
if (rend == lstart->toSInt()) return true;
// a[i:0] a[msb:j]
if (rend == rfromp->width() && lstart->toSInt() == 0) return true;
return false;
}
bool concatMergeable(AstNode* lhsp, AstNode* rhsp) {
// determine if {a OP b, c OP d} => {a, c} OP {b, d} is advantagous
if (!v3Global.opt.oAssemble()) return false; // opt disabled
if (lhsp->type() != rhsp->type()) return false;
if (!ifConcatMergeableBiop(lhsp)) return false;
AstNodeBiop* lp = lhsp->castNodeBiop();
AstNodeBiop* rp = rhsp->castNodeBiop();
if (!lp || !rp) return false;
// {a[]&b[], a[]&b[]}
bool lad = ifMergeAdjacent(lp->lhsp(), rp->lhsp());
bool rad = ifMergeAdjacent(lp->rhsp(), rp->rhsp());
if (lad && rad) return true;
// {a[] & b[]&c[], a[] & b[]&c[]}
else if (lad && concatMergeable(lp->rhsp(), rp->rhsp())) return true;
// {a[]&b[] & c[], a[]&b[] & c[]}
else if (rad && concatMergeable(lp->lhsp(), rp->lhsp())) return true;
else {
// {(a[]&b[])&(c[]&d[]), (a[]&b[])&(c[]&d[])}
if (concatMergeable(lp->lhsp(), rp->lhsp())
&& concatMergeable(lp->rhsp(), rp->rhsp()))
return true;
}
return false;
}
//---------------------------------------- //----------------------------------------
// Constant Replacement functions. // Constant Replacement functions.
@@ -668,6 +761,45 @@ private:
rrp->deleteTree(); rrp->deleteTree();
//nodep->dumpTree(cout, " repShiftSame_new: "); //nodep->dumpTree(cout, " repShiftSame_new: ");
} }
void replaceConcatSel(AstConcat* nodep) {
// {a[1], a[0]} -> a[1:0]
AstSel* lselp = nodep->lhsp()->unlinkFrBack()->castSel();
AstSel* rselp = nodep->rhsp()->unlinkFrBack()->castSel();
int lstart = lselp->lsbConst();
int lwidth = lselp->widthConst();
int rstart = rselp->lsbConst();
int rwidth = rselp->widthConst();
if ((rstart + rwidth) != lstart) nodep->v3fatalSrc("tried to merge two selects which are not adjacent");
AstSel* newselp = new AstSel(lselp->fromp()->fileline(), rselp->fromp()->cloneTree(false), rstart, lwidth+rwidth);
UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
nodep->replaceWith(newselp);
lselp->deleteTree(); lselp = NULL;
rselp->deleteTree(); rselp = NULL;
nodep->deleteTree(); nodep = NULL;
}
void replaceConcatMerge(AstConcat* nodep) {
AstNodeBiop* lp = nodep->lhsp()->castNodeBiop();
AstNodeBiop* rp = nodep->rhsp()->castNodeBiop();
AstNode* llp = lp->lhsp()->cloneTree(false);
AstNode* lrp = lp->rhsp()->cloneTree(false);
AstNode* rlp = rp->lhsp()->cloneTree(false);
AstNode* rrp = rp->rhsp()->cloneTree(false);
if (concatMergeable(lp, rp)) {
AstConcat* newlp = new AstConcat(rlp->fileline(), llp, rlp);
AstConcat* newrp = new AstConcat(rrp->fileline(), lrp, rrp);
// use the lhs to replace the parent concat
lp->lhsp()->replaceWith(newlp);
lp->rhsp()->replaceWith(newrp);
lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::fromBool(true));
UINFO(5, "merged "<< nodep <<endl);
rp->unlinkFrBack()->deleteTree(); rp = NULL;
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); nodep = NULL;
lp->lhsp()->accept(*this);
lp->rhsp()->accept(*this);
} else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
}
void replaceExtend (AstNode* nodep, AstNode* arg0p) { void replaceExtend (AstNode* nodep, AstNode* arg0p) {
// -> EXTEND(nodep) // -> EXTEND(nodep)
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node // like a AstExtend{$rhsp}, but we need to set the width correctly from base node
@@ -792,7 +924,7 @@ private:
AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false; AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false;
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false; AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false;
AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false; AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false;
if (!varref1p->sameTree(varref2p)) return false; if (!varref1p->sameGateTree(varref2p)) return false;
AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false; AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false;
AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false; AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
// We need to make sure there's no self-references involved in either // We need to make sure there's no self-references involved in either
@@ -1539,7 +1671,7 @@ private:
AstSenItem* litemp = senp->castSenItem(); AstSenItem* litemp = senp->castSenItem();
AstSenItem* ritemp = cmpp->castSenItem(); AstSenItem* ritemp = cmpp->castSenItem();
if (litemp && ritemp) { if (litemp && ritemp) {
if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameTree(ritemp->varrefp())) if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameGateTree(ritemp->varrefp()))
|| (!litemp->varrefp() && !ritemp->varrefp())) { || (!litemp->varrefp() && !ritemp->varrefp())) {
// We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders // We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders
if (( litemp->edgeType()==AstEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY if (( litemp->edgeType()==AstEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY
@@ -1910,6 +2042,7 @@ private:
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP ("AstSub {$lhsp.castAdd, operandSubAdd(nodep)}", "AstAdd{AstSub{$lhsp->castAdd()->lhsp(),$rhsp}, $lhsp->castAdd()->rhsp()}"); // ((a+x)-y) -> (a+(x-y))
// Trinary ops // Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump! // Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)"); TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
@@ -2064,6 +2197,9 @@ private:
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c})) // CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)"); TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())"); TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
// CONCAT(a[1],a[0]) -> a[1:0]
TREEOPV("AstConcat{$lhsp->castSel(), $rhsp->castSel(), ifAdjacentSel($lhsp->castSel(),,$rhsp->castSel())}", "replaceConcatSel(nodep)");
TREEOPV("AstConcat{ifConcatMergeableBiop($lhsp), concatMergeable($lhsp,,$rhsp)}", "replaceConcatMerge(nodep)");
// Common two-level operations that can be simplified // Common two-level operations that can be simplified
TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
+16
View File
@@ -81,6 +81,7 @@ private:
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap; typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE // STATE
AstNodeModule* m_modp; // Current module
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
AssignMap m_assignMap; // List of all simple assignments for each variable AssignMap m_assignMap; // List of all simple assignments for each variable
@@ -112,6 +113,12 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) {
m_modp = nodep;
nodep->iterateChildren(*this);
checkAll(nodep);
m_modp = NULL;
}
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
@@ -158,6 +165,13 @@ private:
nodep->packagep()->user1Inc(); nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstTypedef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
// Don't let packages with only public variables disappear
// Normal modules may disappear, e.g. if they are parameterized then removed
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
}
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
@@ -168,6 +182,7 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
if (mightElim(nodep)) { if (mightElim(nodep)) {
m_varEtcsp.push_back(nodep); m_varEtcsp.push_back(nodep);
} }
@@ -253,6 +268,7 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) { DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
m_modp = NULL;
m_elimUserVars = elimUserVars; m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes; m_elimDTypes = elimDTypes;
m_sideEffect = false; m_sideEffect = false;
+40 -2
View File
@@ -96,6 +96,38 @@ public:
} }
} }
void emitTypedefs(AstNode* firstp) {
bool first = true;
for (AstNode* loopp=firstp; loopp; loopp = loopp->nextp()) {
if (AstTypedef* nodep = loopp->castTypedef()) {
if (nodep->attrPublic()) {
if (first) {
first = false;
puts("\n// TYPEDEFS\n");
puts("// That were declared public\n");
} else {
puts("\n");
}
if (AstEnumDType* adtypep = nodep->dtypep()->skipRefToEnump()->castEnumDType()) {
if (adtypep->width()>64) {
puts("// enum "+nodep->name()+" // Ignored: Too wide for C++\n");
} else {
puts("enum "+nodep->name()+" {\n");
for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp=itemp->nextp()->castEnumItem()) {
puts(itemp->name());
puts(" = ");
itemp->valuep()->iterateAndNext(*this);
if (nodep->nextp()) puts(",");
puts("\n");
}
puts("};\n");
}
}
}
}
}
}
// VISITORS // VISITORS
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep, AstNUser*) {
bool paren = true; bool decind = false; bool paren = true; bool decind = false;
@@ -226,7 +258,9 @@ public:
virtual void visit(AstScopeName* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// For use under AstCCalls for dpiImports. ScopeNames under displays are handled in AstDisplay // For use under AstCCalls for dpiImports. ScopeNames under displays are handled in AstDisplay
if (!nodep->dpiExport()) { if (!nodep->dpiExport()) {
putbs("(&(vlSymsp->__Vscope_"+nodep->scopeSymName()+"))"); // this is where the DPI import context scope is set
string scope = nodep->scopeDpiName();
putbs("(&(vlSymsp->__Vscope_"+scope+"))");
} }
} }
virtual void visit(AstSFormat* nodep, AstNUser*) { virtual void visit(AstSFormat* nodep, AstNUser*) {
@@ -661,6 +695,7 @@ public:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// NOPs // NOPs
virtual void visit(AstTypedef*, AstNUser*) {}
virtual void visit(AstPragma*, AstNUser*) {} virtual void visit(AstPragma*, AstNUser*) {}
virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstVar*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstVar*, AstNUser*) {} // Handled outside the Visit class
@@ -668,7 +703,6 @@ public:
virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTypedef*, AstNUser*) {} // Nothing needed presently
// Default // Default
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n"); puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
@@ -783,6 +817,7 @@ class EmitCImp : EmitCStmts {
//--------------------------------------- //---------------------------------------
// VISITORS // VISITORS
using EmitCStmts::visit; // Suppress hidden overloaded virtual function warnng
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep, AstNUser*) {
// TRACE_* and DPI handled elsewhere // TRACE_* and DPI handled elsewhere
if (nodep->funcType().isTrace()) return; if (nodep->funcType().isTrace()) return;
@@ -1842,6 +1877,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
} }
} }
emitTypedefs(modp->stmtsp());
puts("\n// PORTS\n"); puts("\n// PORTS\n");
if (modp->isTop()) puts("// The application code writes and reads these signals to\n"); if (modp->isTop()) puts("// The application code writes and reads these signals to\n");
if (modp->isTop()) puts("// propagate new values into/out from the Verilated model.\n"); if (modp->isTop()) puts("// propagate new values into/out from the Verilated model.\n");
@@ -2303,6 +2340,7 @@ class EmitCTrace : EmitCStmts {
} }
// VISITORS // VISITORS
using EmitCStmts::visit; // Suppress hidden overloaded virtual function warnng
virtual void visit(AstNetlist* nodep, AstNUser*) { virtual void visit(AstNetlist* nodep, AstNUser*) {
// Top module only // Top module only
nodep->topModulep()->accept(*this); nodep->topModulep()->accept(*this);
+1 -2
View File
@@ -685,7 +685,6 @@ public:
class EmitVPrefixedVisitor : public EmitVBaseVisitor { class EmitVPrefixedVisitor : public EmitVBaseVisitor {
// MEMBERS // MEMBERS
EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the inheritance is another unused V3OutFormatter) EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the inheritance is another unused V3OutFormatter)
bool m_user3mark; // nodep->user3() if set means mark with %%
// METHODS // METHODS
virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); } virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); }
virtual void puts(const string& str) { m_formatter.puts(str); } virtual void puts(const string& str) { m_formatter.puts(str); }
@@ -706,7 +705,7 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor {
public: public:
EmitVPrefixedVisitor(AstNode* nodep, ostream& os, const string& prefix, int flWidth, EmitVPrefixedVisitor(AstNode* nodep, ostream& os, const string& prefix, int flWidth,
AstSenTree* domainp, bool user3mark) AstSenTree* domainp, bool user3mark)
: EmitVBaseVisitor(domainp), m_formatter(os, prefix, flWidth), m_user3mark(user3mark) { : EmitVBaseVisitor(domainp), m_formatter(os, prefix, flWidth) {
if (user3mark) { AstUser3InUse::check(); } if (user3mark) { AstUser3InUse::check(); }
nodep->accept(*this); nodep->accept(*this);
} }
+5 -1
View File
@@ -583,11 +583,15 @@ private:
newSelBitBit(lhsp->lsbp()), newSelBitBit(lhsp->lsbp()),
VL_WORDSIZE)), VL_WORDSIZE)),
oldvalp); oldvalp);
// Restrict the shift amount to 0-31, see bug804.
AstNode* shiftp = new AstAnd(nodep->fileline(), lhsp->lsbp()->cloneTree(true),
new AstConst(nodep->fileline(), VL_WORDSIZE-1));
AstNode* newp = new AstOr (lhsp->fileline(), AstNode* newp = new AstOr (lhsp->fileline(),
oldvalp, oldvalp,
new AstShiftL (lhsp->fileline(), new AstShiftL (lhsp->fileline(),
rhsp, rhsp,
lhsp->lsbp()->cloneTree(true), shiftp,
VL_WORDSIZE)); VL_WORDSIZE));
newp = new AstAssign (nodep->fileline(), newp = new AstAssign (nodep->fileline(),
new AstWordSel (nodep->fileline(), new AstWordSel (nodep->fileline(),
+1 -1
View File
@@ -567,7 +567,7 @@ const char* V3OutFormatter::indentStr(int num) {
static char str[MAXSPACE+20]; static char str[MAXSPACE+20];
char* cp = str; char* cp = str;
if (num>MAXSPACE) num=MAXSPACE; if (num>MAXSPACE) num=MAXSPACE;
if (!m_lang==LA_VERILOG) { // verilogPrefixedTree doesn't want tabs if (m_lang!=LA_VERILOG) { // verilogPrefixedTree doesn't want tabs
while (num>=8) { while (num>=8) {
*cp++ = '\t'; *cp++ = '\t';
num -= 8; num -= 8;
+130 -1
View File
@@ -303,6 +303,7 @@ private:
V3Double0 m_statSigs; // Statistic tracking V3Double0 m_statSigs; // Statistic tracking
V3Double0 m_statRefs; // Statistic tracking V3Double0 m_statRefs; // Statistic tracking
V3Double0 m_statDedupLogic; // Statistic tracking V3Double0 m_statDedupLogic; // Statistic tracking
V3Double0 m_statAssignMerged; // Statistic tracking
// METHODS // METHODS
void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, const char* consumeReason) { void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, const char* consumeReason) {
@@ -352,6 +353,7 @@ private:
void consumedMove(); void consumedMove();
void replaceAssigns(); void replaceAssigns();
void dedupe(); void dedupe();
void mergeAssigns();
// VISITORS // VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) { virtual void visit(AstNetlist* nodep, AstNUser*) {
@@ -368,6 +370,7 @@ private:
optimizeSignals(true); optimizeSignals(true);
// Remove redundant logic // Remove redundant logic
if (v3Global.opt.oDedupe()) dedupe(); if (v3Global.opt.oDedupe()) dedupe();
if (v3Global.opt.oAssemble()) mergeAssigns();
// Warn // Warn
warnSignals(); warnSignals();
consumedMark(); consumedMark();
@@ -506,6 +509,7 @@ public:
V3Stats::addStat("Optimizations, Gate sigs deleted", m_statSigs); V3Stats::addStat("Optimizations, Gate sigs deleted", m_statSigs);
V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs); V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs);
V3Stats::addStat("Optimizations, Gate sigs deduped", m_statDedupLogic); V3Stats::addStat("Optimizations, Gate sigs deduped", m_statDedupLogic);
V3Stats::addStat("Optimizations, Gate assign merged", m_statAssignMerged);
} }
}; };
@@ -1009,7 +1013,6 @@ private:
lvertexp->user(true); lvertexp->user(true);
} }
} }
return NULL; return NULL;
} }
@@ -1063,6 +1066,132 @@ void GateVisitor::dedupe() {
m_statDedupLogic += deduper.numDeduped(); m_statDedupLogic += deduper.numDeduped();
} }
//######################################################################
// Recurse through the graph, try to merge assigns
class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor {
private:
// NODE STATE
AstNodeAssign* m_assignp;
AstActive* m_activep;
GateLogicVertex* m_logicvp;
V3Graph* m_graphp;
V3Double0 m_numMergedAssigns; // Statistic tracking
// assemble two Sel into one if possible
AstSel* merge(AstSel* pre, AstSel* cur) {
AstVarRef* preVarRefp = pre->fromp()->castVarRef();
AstVarRef* curVarRefp = cur->fromp()->castVarRef();
if (!preVarRefp || !curVarRefp || !curVarRefp->same(preVarRefp)) return NULL; // not the same var
AstConst* pstart = pre->lsbp()->castConst();
AstConst* pwidth = pre->widthp()->castConst();
AstConst* cstart = cur->lsbp()->castConst();
AstConst* cwidth = cur->widthp()->castConst();
if (!pstart || !pwidth || !cstart || !cwidth) return NULL; // too complicated
if (cur->lsbConst()+cur->widthConst() == pre->lsbConst())
return new AstSel(curVarRefp->fileline(), curVarRefp->cloneTree(false), cur->lsbConst(), pre->widthConst()+cur->widthConst());
else return NULL;
}
virtual AstNUser* visit(GateVarVertex *vvertexp, AstNUser*) {
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; ) {
V3GraphEdge* oldedgep = edgep;
edgep = edgep->inNextp(); // for recursive since the edge could be deleted
if (GateLogicVertex* lvertexp = dynamic_cast<GateLogicVertex*>(oldedgep->fromp())) {
if (AstNodeAssign* assignp = lvertexp->nodep()->castNodeAssign()) {
//if (lvertexp->outSize1() && assignp->lhsp()->castSel()) {
if (assignp->lhsp()->castSel() && lvertexp->outSize1()) {
UINFO(9, "assing to the nodep["<<assignp->lhsp()->castSel()->lsbConst()<<"]"<<endl);
// first assign with Sel-lhs
if (!m_activep) m_activep = lvertexp->activep();
if (!m_logicvp) m_logicvp = lvertexp;
if (!m_assignp) m_assignp = assignp;
// not under the same active
if (m_activep != lvertexp->activep()) {
m_activep = lvertexp->activep();
m_logicvp = lvertexp;
m_assignp = assignp;
continue;
}
AstSel* preselp = m_assignp->lhsp()->castSel();
AstSel* curselp = assignp->lhsp()->castSel();
if (!preselp || !curselp) continue;
if (AstSel* newselp = merge(preselp, curselp)) {
UINFO(5, "assemble to new sel: "<<newselp<<endl);
// replace preSel with newSel
preselp->replaceWith(newselp); preselp->deleteTree(); preselp = NULL;
// create new rhs for pre assignment
AstNode* newrhsp = new AstConcat(m_assignp->rhsp()->fileline(), m_assignp->rhsp()->cloneTree(false), assignp->rhsp()->cloneTree(false));
AstNode* oldrhsp = m_assignp->rhsp();
oldrhsp->replaceWith(newrhsp); oldrhsp->deleteTree(); oldrhsp = NULL;
m_assignp->dtypeChgWidthSigned(m_assignp->width()+assignp->width(), m_assignp->width()+assignp->width(), AstNumeric::fromBool(true));
// don't need to delete, will be handled
//assignp->unlinkFrBack(); assignp->deleteTree(); assignp = NULL;
// update the graph
{
// delete all inedges to lvertexp
if (!lvertexp->inEmpty()) {
for (V3GraphEdge* ledgep = lvertexp->inBeginp(); ledgep; ) {
V3GraphEdge* oedgep = ledgep;
ledgep = ledgep->inNextp();
GateEitherVertex* fromvp = dynamic_cast<GateEitherVertex*>(oedgep->fromp());
new V3GraphEdge(m_graphp, fromvp, m_logicvp, 1);
oedgep->unlinkDelete(); oedgep = NULL;
}
}
// delete all outedges to lvertexp, only one
oldedgep->unlinkDelete(); oldedgep = NULL;
}
++m_numMergedAssigns;
} else {
m_assignp = assignp;
m_logicvp = lvertexp;
}
}
}
}
}
return NULL;
}
virtual AstNUser* visit(GateLogicVertex* lvertexp, AstNUser* vup) {
return NULL;
}
public:
GateMergeAssignsGraphVisitor(V3Graph* graphp) {
m_assignp = NULL;
m_activep = NULL;
m_logicvp = NULL;
m_numMergedAssigns = 0;
m_graphp = graphp;
}
void mergeAssignsTree(GateVarVertex* vvertexp) {
vvertexp->accept(*this);
}
V3Double0 numMergedAssigns() { return m_numMergedAssigns; }
};
//----------------------------------------------------------------------
void GateVisitor::mergeAssigns() {
GateMergeAssignsGraphVisitor merger(&m_graph);
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
merger.mergeAssignsTree(vvertexp);
}
}
m_statAssignMerged += merger.numMergedAssigns();
}
//###################################################################### //######################################################################
// Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default) // Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default)
+1
View File
@@ -96,6 +96,7 @@ public:
DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false) DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false)
: V3GraphVertex(graphp) : V3GraphVertex(graphp)
, m_start(start), m_accepting(accepting) {} , m_start(start), m_accepting(accepting) {}
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
virtual DfaVertex* clone(DfaGraph* graphp) { virtual DfaVertex* clone(DfaGraph* graphp) {
return new DfaVertex(graphp, start(), accepting()); } return new DfaVertex(graphp, start(), accepting()); }
virtual ~DfaVertex() {} virtual ~DfaVertex() {}
+5
View File
@@ -314,6 +314,7 @@ private:
// Also clear I/O bits, as it is now local. // Also clear I/O bits, as it is now local.
string name = m_cellp->name() + "__DOT__" + nodep->name(); string name = m_cellp->name() + "__DOT__" + nodep->name();
if (!nodep->isFuncLocal()) nodep->inlineAttrReset(name); if (!nodep->isFuncLocal()) nodep->inlineAttrReset(name);
if (!m_cellp->isTrace()) nodep->trace(false);
if (debug()>=9) { nodep->dumpTree(cout,"varchanged:"); } if (debug()>=9) { nodep->dumpTree(cout,"varchanged:"); }
if (debug()>=9) { nodep->valuep()->dumpTree(cout,"varchangei:"); } if (debug()>=9) { nodep->valuep()->dumpTree(cout,"varchangei:"); }
// Iterate won't hit AstIfaceRefDType directly as it is no longer underneath the module // Iterate won't hit AstIfaceRefDType directly as it is no longer underneath the module
@@ -387,6 +388,10 @@ private:
if (afterp) afterp->unlinkFrBackWithNext(); if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeAttrp(new AstText(nodep->fileline(), (string)"__DOT__"+m_cellp->name())); nodep->scopeAttrp(new AstText(nodep->fileline(), (string)"__DOT__"+m_cellp->name()));
if (afterp) nodep->scopeAttrp(afterp); if (afterp) nodep->scopeAttrp(afterp);
afterp = nodep->scopeEntrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeEntrp(new AstText(nodep->fileline(), (string)"__DOT__"+m_cellp->name()));
if (afterp) nodep->scopeEntrp(afterp);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstCoverDecl* nodep, AstNUser*) { virtual void visit(AstCoverDecl* nodep, AstNUser*) {
+19 -2
View File
@@ -62,6 +62,7 @@ private:
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
AstNodeModule* m_modp; // Current module AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current task AstNodeFTask* m_ftaskp; // Current task
AstNodeDType* m_dtypep; // Current data type
// METHODS // METHODS
static int debug() { static int debug() {
@@ -104,6 +105,15 @@ private:
m_valueModp = upperValueModp; m_valueModp = upperValueModp;
} }
} }
virtual void visit(AstNodeDType* nodep, AstNUser*) {
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
AstNodeDType* upperDtypep = m_dtypep;
m_dtypep = nodep;
nodep->iterateChildren(*this);
m_dtypep = upperDtypep;
}
}
virtual void visit(AstEnumItem* nodep, AstNUser*) { virtual void visit(AstEnumItem* nodep, AstNUser*) {
// Expand ranges // Expand ranges
cleanFileline(nodep); cleanFileline(nodep);
@@ -176,7 +186,13 @@ private:
virtual void visit(AstAttrOf* nodep, AstNUser*) { virtual void visit(AstAttrOf* nodep, AstNUser*) {
cleanFileline(nodep); cleanFileline(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->attrType() == AstAttrType::VAR_CLOCK) { if (nodep->attrType() == AstAttrType::DT_PUBLIC) {
AstTypedef* typep = nodep->backp()->castTypedef();
if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef");
typep->attrPublic(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScClocked(true); m_varp->attrScClocked(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
@@ -265,7 +281,7 @@ private:
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
return; return;
} else { } else {
defp = new AstTypedef(nodep->fileline(), nodep->name(), VFlagChildDType(), dtypep); defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), dtypep);
m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp)); m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp));
backp->addNextHere(defp); backp->addNextHere(defp);
} }
@@ -327,6 +343,7 @@ public:
m_varp = NULL; m_varp = NULL;
m_modp = NULL; m_modp = NULL;
m_ftaskp = NULL; m_ftaskp = NULL;
m_dtypep = NULL;
m_inAlways = false; m_inAlways = false;
m_inGenerate = false; m_inGenerate = false;
m_needStart = false; m_needStart = false;
+1 -1
View File
@@ -97,7 +97,7 @@ private:
bool bitIsXZ(int bit) const { bool bitIsXZ(int bit) const {
if (bit<0) return false; if (bit<0) return false;
if (bit>=m_width) return bitIsXZ(m_width-1); if (bit>=m_width) return bitIsXZ(m_width-1);
return ( (m_valueX[bit/32] & (1UL<<(bit&31))) && 1); return ( (m_valueX[bit/32] & (1UL<<(bit&31))));
} }
bool bitIsZ (int bit) const { bool bitIsZ (int bit) const {
if (bit<0) return false; if (bit<0) return false;
+23 -11
View File
@@ -107,17 +107,27 @@ void V3Options::addLangExt(const string& langext, const V3LangCode& lc) {
void V3Options::addLibExtV(const string& libext) { void V3Options::addLibExtV(const string& libext) {
m_impp->addLibExtV(libext); m_impp->addLibExtV(libext);
} }
void V3Options::addDefine(const string& defline) { void V3Options::addDefine(const string& defline, bool allowPlus) {
// Split +define+foo=value into the appropriate parts and parse // Split +define+foo=value into the appropriate parts and parse
string def = defline; // Optional + says to allow multiple defines on the line
string value; // + is not quotable, as other simulators do not allow that
string::size_type pos; string left = defline;
if ( ((pos=defline.find("+")) != string::npos) while (left != "") {
|| ((pos=defline.find("=")) != string::npos)) { string def = left;
value = def.substr(pos+1); string::size_type pos;
def.erase(pos); if (allowPlus && ((pos=left.find("+")) != string::npos)) {
left = left.substr(pos+1);
def.erase(pos);
} else {
left = "";
}
string value;
if ((pos=def.find("=")) != string::npos) {
value = def.substr(pos+1);
def.erase(pos);
}
V3PreShell::defineCmdLine(def,value);
} }
V3PreShell::defineCmdLine(def,value);
} }
void V3Options::addCppFile(const string& filename) { void V3Options::addCppFile(const string& filename) {
@@ -668,7 +678,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
if (argv[i][0]=='+') { if (argv[i][0]=='+') {
char *sw = argv[i]; char *sw = argv[i];
if ( !strncmp (sw, "+define+", 8)) { if ( !strncmp (sw, "+define+", 8)) {
addDefine (string (sw+strlen("+define+"))); addDefine (string (sw+strlen("+define+")), true);
} }
else if ( !strncmp (sw, "+incdir+", 8)) { else if ( !strncmp (sw, "+incdir+", 8)) {
addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+")))); addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+"))));
@@ -774,6 +784,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
case 'b': m_oCombine = flag; break; case 'b': m_oCombine = flag; break;
case 'c': m_oConst = flag; break; case 'c': m_oConst = flag; break;
case 'd': m_oDedupe = flag; break; case 'd': m_oDedupe = flag; break;
case 'm': m_oAssemble = flag; break;
case 'e': m_oCase = flag; break; case 'e': m_oCase = flag; break;
case 'f': m_oFlopGater = flag; break; case 'f': m_oFlopGater = flag; break;
case 'g': m_oGate = flag; break; case 'g': m_oGate = flag; break;
@@ -802,7 +813,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
m_convergeLimit = atoi(argv[i]); m_convergeLimit = atoi(argv[i]);
} }
else if ( !strncmp (sw, "-D", 2)) { else if ( !strncmp (sw, "-D", 2)) {
addDefine (string (sw+strlen("-D"))); addDefine (string (sw+strlen("-D")), false);
} }
else if ( !strcmp (sw, "-debug") ) { else if ( !strcmp (sw, "-debug") ) {
setDebugMode(3); setDebugMode(3);
@@ -1319,6 +1330,7 @@ void V3Options::optimize(int level) {
m_oSubstConst = flag; m_oSubstConst = flag;
m_oTable = flag; m_oTable = flag;
m_oDedupe = flag; m_oDedupe = flag;
m_oAssemble = flag;
// And set specific optimization levels // And set specific optimization levels
if (level >= 3) { if (level >= 3) {
m_inlineMult = -1; // Maximum inlining m_inlineMult = -1; // Maximum inlining
+3 -1
View File
@@ -139,6 +139,7 @@ class V3Options {
bool m_oCombine; // main switch: -Ob: common icode packing bool m_oCombine; // main switch: -Ob: common icode packing
bool m_oConst; // main switch: -Oc: constant folding bool m_oConst; // main switch: -Oc: constant folding
bool m_oDedupe; // main switch: -Od: logic deduplication bool m_oDedupe; // main switch: -Od: logic deduplication
bool m_oAssemble; // main switch: -Om: assign assemble
bool m_oExpand; // main switch: -Ox: expansion of C macros bool m_oExpand; // main switch: -Ox: expansion of C macros
bool m_oFlopGater; // main switch: -Of: flop gater detection bool m_oFlopGater; // main switch: -Of: flop gater detection
bool m_oGate; // main switch: -Og: gate wire elimination bool m_oGate; // main switch: -Og: gate wire elimination
@@ -155,7 +156,7 @@ class V3Options {
private: private:
// METHODS // METHODS
void addArg(const string& flag); void addArg(const string& flag);
void addDefine(const string& defline); void addDefine(const string& defline, bool allowPlus);
void addFuture(const string& flag); void addFuture(const string& flag);
void addIncDirUser(const string& incdir); // User requested void addIncDirUser(const string& incdir); // User requested
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
@@ -282,6 +283,7 @@ class V3Options {
bool oCombine() const { return m_oCombine; } bool oCombine() const { return m_oCombine; }
bool oConst() const { return m_oConst; } bool oConst() const { return m_oConst; }
bool oDedupe() const { return m_oDedupe; } bool oDedupe() const { return m_oDedupe; }
bool oAssemble() const { return m_oAssemble; }
bool oExpand() const { return m_oExpand; } bool oExpand() const { return m_oExpand; }
bool oFlopGater() const { return m_oFlopGater; } bool oFlopGater() const { return m_oFlopGater; }
bool oGate() const { return m_oGate; } bool oGate() const { return m_oGate; }
+2 -1
View File
@@ -210,7 +210,8 @@ private:
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep, AstNUser*) {
if (nodep->dead()) { if (nodep->dead()) {
UINFO(4," MOD-dead. "<<nodep<<endl); // Marked by LinkDot UINFO(4," MOD-dead. "<<nodep<<endl); // Marked by LinkDot
} else if (nodep->level() <= 2) { // Haven't added top yet, so level 2 is the top } else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top
|| nodep->castPackage()) { // Likewise haven't done wrapTopPackages yet
// Add request to END of modules left to process // Add request to END of modules left to process
m_todoModps.insert(make_pair(nodep->level(),nodep)); m_todoModps.insert(make_pair(nodep->level(),nodep));
visitModules(); visitModules();
+2
View File
@@ -169,6 +169,7 @@ class V3PreLex {
int m_pslParenLevel;// PSL Parenthesis (){} counting, so we can find final ; int m_pslParenLevel;// PSL Parenthesis (){} counting, so we can find final ;
bool m_pslMoreNeeded;// Next // comment is really psl bool m_pslMoreNeeded;// Next // comment is really psl
bool m_defCmtSlash; // /*...*/ comment in define had \ ending bool m_defCmtSlash; // /*...*/ comment in define had \ ending
bool m_defQuote; // Definition value inside quote
string m_defValue; // Definition value being built. string m_defValue; // Definition value being built.
int m_enterExit; // For VL_LINE, the enter/exit level int m_enterExit; // For VL_LINE, the enter/exit level
@@ -181,6 +182,7 @@ class V3PreLex {
m_pedantic = false; m_pedantic = false;
m_formalLevel = 0; m_formalLevel = 0;
m_parenLevel = 0; m_parenLevel = 0;
m_defQuote = false;
m_defCmtSlash = false; m_defCmtSlash = false;
m_tokFilelinep = filelinep; m_tokFilelinep = filelinep;
m_enterExit = 0; m_enterExit = 0;
+4 -3
View File
@@ -125,7 +125,7 @@ psl [p]sl
<STRMODE>{backslash}{crnl} { linenoInc(); yymore(); } <STRMODE>{backslash}{crnl} { linenoInc(); yymore(); }
<STRMODE>{backslash}. { yymore(); } <STRMODE>{backslash}. { yymore(); }
<STRMODE>{quote} { yy_pop_state(); <STRMODE>{quote} { yy_pop_state();
if (LEXP->m_parenLevel || LEXP->m_formalLevel) { appendDefValue(yytext,yyleng); yyleng=0; } if (LEXP->m_parenLevel || LEXP->m_defQuote) { LEXP->m_defQuote=false; appendDefValue(yytext,yyleng); yyleng=0; }
else return (VP_STRING); } else return (VP_STRING); }
/* Stringification */ /* Stringification */
@@ -162,7 +162,7 @@ psl [p]sl
<DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; } <DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; }
<DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */ <DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
<DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Include return so can maintain output line count */ <DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Include return so can maintain output line count */
<DEFFORM>{quote} { yy_push_state(STRMODE); yymore(); } /* Legal only in default values */ <DEFFORM>{quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } /* Legal only in default values */
<DEFFORM>"`\\`\"" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */ <DEFFORM>"`\\`\"" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
<DEFFORM>{tickquote} { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */ <DEFFORM>{tickquote} { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
<DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); } <DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); }
@@ -179,7 +179,8 @@ psl [p]sl
<DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */ <DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */
<DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } <DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); }
<DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Return, AND \ is part of define value */ <DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Return, AND \ is part of define value */
<DEFVAL>[^\/\*\n\r\\]+ | <DEFVAL>{quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); }
<DEFVAL>[^\/\*\n\r\\\"]+ |
<DEFVAL>[\\][^\n\r] | <DEFVAL>[\\][^\n\r] |
<DEFVAL>. { appendDefValue(yytext,yyleng); } <DEFVAL>. { appendDefValue(yytext,yyleng); }
+67 -2
View File
@@ -40,6 +40,60 @@
#include "V3Premit.h" #include "V3Premit.h"
#include "V3Ast.h" #include "V3Ast.h"
//######################################################################
// Structure for global state
class PremitAssignVisitor : public AstNVisitor {
private:
// NODE STATE
// AstVar::user4() // bool; occurs on LHS of current assignment
AstUser4InUse m_inuser4;
// STATE
bool m_noopt; // Disable optimization of variables in this block
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
//AstNode::user4ClearTree(); // Implied by AstUser4InUse
// LHS first as fewer varrefs
nodep->lhsp()->iterateAndNext(*this);
// Now find vars marked as lhs
nodep->rhsp()->iterateAndNext(*this);
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
// it's LHS var is used so need a deep temporary
if (nodep->lvalue()) {
nodep->varp()->user4(true);
} else {
if (nodep->varp()->user4()) {
if (!m_noopt) UINFO(4, "Block has LHS+RHS var: "<<nodep<<endl);
m_noopt = true;
}
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTRUCTORS
PremitAssignVisitor(AstNodeAssign* nodep) {
UINFO(4," PremitAssignVisitor on "<<nodep<<endl);
m_noopt = false;
nodep->accept(*this);
}
virtual ~PremitAssignVisitor() {}
bool noOpt() const { return m_noopt; }
};
//###################################################################### //######################################################################
// Premit state, as a visitor of each AstNode // Premit state, as a visitor of each AstNode
@@ -49,6 +103,7 @@ private:
// AstNodeMath::user() -> bool. True if iterated already // AstNodeMath::user() -> bool. True if iterated already
// AstShiftL::user2() -> bool. True if converted to conditional // AstShiftL::user2() -> bool. True if converted to conditional
// AstShiftR::user2() -> bool. True if converted to conditional // AstShiftR::user2() -> bool. True if converted to conditional
// *::user4() -> See PremitAssignVisitor
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2; AstUser2InUse m_inuser2;
@@ -115,11 +170,13 @@ private:
m_inWhilep->addPrecondsp(newp); m_inWhilep->addPrecondsp(newp);
} else if (m_inTracep) { } else if (m_inTracep) {
m_inTracep->addPrecondsp(newp); m_inTracep->addPrecondsp(newp);
} else { } else if (m_stmtp) {
AstNRelinker linker; AstNRelinker linker;
m_stmtp->unlinkFrBack(&linker); m_stmtp->unlinkFrBack(&linker);
newp->addNext(m_stmtp); newp->addNext(m_stmtp);
linker.relink(newp); linker.relink(newp);
} else {
newp->v3fatalSrc("No statement insertion point.");
} }
} }
@@ -174,6 +231,14 @@ private:
} }
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep, AstNUser*) {
startStatement(nodep); startStatement(nodep);
{
bool noopt = PremitAssignVisitor(nodep).noOpt();
if (noopt && !nodep->user1()) {
// Need to do this even if not wide, as e.g. a select may be on a wide operator
UINFO(4,"Deep temp for LHS/RHS\n");
createDeepTemp(nodep->rhsp());
}
}
nodep->rhsp()->iterateAndNext(*this); nodep->rhsp()->iterateAndNext(*this);
m_assignLhs = true; m_assignLhs = true;
nodep->lhsp()->iterateAndNext(*this); nodep->lhsp()->iterateAndNext(*this);
@@ -287,7 +352,7 @@ private:
while (searchp && searchp->castComment()) searchp = searchp->nextp(); while (searchp && searchp->castComment()) searchp = searchp->nextp();
if (searchp if (searchp
&& searchp->castDisplay() && searchp->castDisplay()
&& nodep->filep()->sameTree(searchp->castDisplay()->filep())) { && nodep->filep()->sameGateTree(searchp->castDisplay()->filep())) {
// There's another display next; we can just wait to flush // There's another display next; we can just wait to flush
} else { } else {
UINFO(4,"Autoflush "<<nodep<<endl); UINFO(4,"Autoflush "<<nodep<<endl);
+7 -2
View File
@@ -241,6 +241,7 @@ private:
if (!nodep->user1p()) { if (!nodep->user1p()) {
AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep); AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
UINFO(6," New scope "<<varscp<<endl); UINFO(6," New scope "<<varscp<<endl);
if (m_aboveCellp && !m_aboveCellp->isTrace()) varscp->trace(false);
nodep->user1p(varscp); nodep->user1p(varscp);
if (!m_scopep) nodep->v3fatalSrc("No scope for var"); if (!m_scopep) nodep->v3fatalSrc("No scope for var");
m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp)); m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp));
@@ -258,8 +259,8 @@ private:
// the var's referenced package etc might not be created yet. // the var's referenced package etc might not be created yet.
// So push to a list and post-correct // So push to a list and post-correct
m_varRefScopes.insert(make_pair(nodep, m_scopep)); m_varRefScopes.insert(make_pair(nodep, m_scopep));
} }
} }
virtual void visit(AstScopeName* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
string prefix = (string)("__DOT__")+m_scopep->name(); string prefix = (string)("__DOT__")+m_scopep->name();
@@ -270,6 +271,10 @@ private:
if (afterp) afterp->unlinkFrBackWithNext(); if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix)); nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->scopeAttrp(afterp); if (afterp) nodep->scopeAttrp(afterp);
afterp = nodep->scopeEntrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeEntrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->scopeEntrp(afterp);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep, AstNUser*) {
-1
View File
@@ -233,7 +233,6 @@ private:
SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering
V3Graph m_graph; // Scoreboard of var usages/dependencies V3Graph m_graph; // Scoreboard of var usages/dependencies
bool m_inDly; // Inside ASSIGNDLY bool m_inDly; // Inside ASSIGNDLY
uint32_t m_stepNum; // Step number we need to ignore a edge in
V3Double0 m_statSplits; // Statistic tracking V3Double0 m_statSplits; // Statistic tracking
// METHODS // METHODS
+1 -1
View File
@@ -353,7 +353,7 @@ private:
== var2p->dtypep()->arrayUnpackedElements())) { == var2p->dtypep()->arrayUnpackedElements())) {
AstNode* init1p = var1p->valuep()->castInitArray(); AstNode* init1p = var1p->valuep()->castInitArray();
AstNode* init2p = var2p->valuep()->castInitArray(); AstNode* init2p = var2p->valuep()->castInitArray();
if (init1p->sameTree(init2p)) { if (init1p->sameGateTree(init2p)) {
UINFO(8," Duplicate table var "<<vsc2p<<" == "<<vsc1p<<endl); UINFO(8," Duplicate table var "<<vsc2p<<" == "<<vsc1p<<endl);
vsc1p->unlinkFrBack()->deleteTree(); vsc1p->unlinkFrBack()->deleteTree();
return vsc2p; return vsc2p;
+9 -6
View File
@@ -43,7 +43,6 @@ private:
// NODE STATE // NODE STATE
// STATE // STATE
AstNodeModule* m_modp; // Current module
AstScope* m_scopetopp; // Current top scope AstScope* m_scopetopp; // Current top scope
AstCFunc* m_initFuncp; // Trace function being built AstCFunc* m_initFuncp; // Trace function being built
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init) AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
@@ -65,13 +64,17 @@ private:
return level; return level;
} }
const char* varIgnoreTrace(AstVar* nodep) { const char* vscIgnoreTrace(AstVarScope* nodep) {
// Return true if this shouldn't be traced // Return true if this shouldn't be traced
// See also similar rule in V3Coverage::varIgnoreToggle // See also similar rule in V3Coverage::varIgnoreToggle
string prettyName = nodep->prettyName(); AstVar* varp = nodep->varp();
if (!nodep->isTrace()) { string prettyName = varp->prettyName();
if (!varp->isTrace()) {
return "Verilator trace_off"; return "Verilator trace_off";
} }
else if (!nodep->isTrace()) {
return "Verilator cell trace_off";
}
else if (!v3Global.opt.traceUnderscore()) { else if (!v3Global.opt.traceUnderscore()) {
if (prettyName.size()>=1 && prettyName[0] == '_') if (prettyName.size()>=1 && prettyName[0] == '_')
return "Leading underscore"; return "Leading underscore";
@@ -164,8 +167,8 @@ private:
m_traVscp = nodep; m_traVscp = nodep;
m_traValuep = NULL; m_traValuep = NULL;
if (varIgnoreTrace(varp)) { if (vscIgnoreTrace(nodep)) {
addIgnore(varIgnoreTrace(varp)); addIgnore(vscIgnoreTrace(nodep));
} else { } else {
++m_statSigs; ++m_statSigs;
if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true); if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true);
+5 -5
View File
@@ -337,14 +337,14 @@ private:
// Find range of dtype we are selecting from // Find range of dtype we are selecting from
// Similar code in V3Const::warnSelect // Similar code in V3Const::warnSelect
int maxmsb = nodep->fromp()->dtypep()->width()-1; int maxmsb = nodep->fromp()->dtypep()->width()-1;
int maxlsb = maxmsb - nodep->width() + 1;
if (debug()>=9) nodep->dumpTree(cout,"sel_old: "); if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb); V3Number maxmsbnum (nodep->fileline(), nodep->lsbp()->width(), maxmsb);
// See if the condition is constant true // If (maxmsb >= selected), we're in bound
AstNode* condp = new AstGte (nodep->fileline(), AstNode* condp = new AstGte (nodep->fileline(),
new AstConst(nodep->fileline(), maxlsbnum), new AstConst(nodep->fileline(), maxmsbnum),
nodep->lsbp()->cloneTree(false)); nodep->lsbp()->cloneTree(false));
// See if the condition is constant true (e.g. always in bound due to constant select)
// Note below has null backp(); the Edit function knows how to deal with that. // Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp); condp = V3Const::constifyEdit(condp);
if (condp->isOne()) { if (condp->isOne()) {
@@ -352,7 +352,7 @@ private:
condp->deleteTree(); condp->deleteTree();
} }
else if (!lvalue) { else if (!lvalue) {
// SEL(...) -> COND(LTE(bit<=maxlsb), ARRAYSEL(...), {width{1'bx}}) // SEL(...) -> COND(LTE(bit<=maxmsb), ARRAYSEL(...), {width{1'bx}})
AstNRelinker replaceHandle; AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle); nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep->fileline(), nodep->width()); V3Number xnum (nodep->fileline(), nodep->width());
+28 -12
View File
@@ -164,15 +164,27 @@ private:
bool gt = condp->castGt() || condp->castGtS(); bool gt = condp->castGt() || condp->castGtS();
bool gte = condp->castGte() || condp->castGteS(); bool gte = condp->castGte() || condp->castGteS();
if (!lt && !lte && !gt && !gte) if (!lt && !lte && !gt && !gte)
return cantUnroll(nodep, "condition not <= or <"); return cantUnroll(nodep, "condition not <=, <, >= or >");
AstNodeBiop* condBip = condp->castNodeBiop(); AstNodeBiop* cmpInstrp = condp->castNodeBiop();
if (!condBip->rhsp()->castVarRef()) bool cmpVarLhs;
if (cmpInstrp->lhsp()->castVarRef()
&& cmpInstrp->lhsp()->castVarRef()->varp() == m_forVarp
&& cmpInstrp->lhsp()->castVarRef()->varScopep() == m_forVscp) {
cmpVarLhs = true;
} else if (cmpInstrp->rhsp()->castVarRef()
&& cmpInstrp->rhsp()->castVarRef()->varp() == m_forVarp
&& cmpInstrp->rhsp()->castVarRef()->varScopep() == m_forVscp) {
cmpVarLhs = false;
} else if (!cmpInstrp->rhsp()->castVarRef()) {
return cantUnroll(nodep, "no variable on rhs of condition"); return cantUnroll(nodep, "no variable on rhs of condition");
if (condBip->rhsp()->castVarRef()->varp() != m_forVarp } else {
|| condBip->rhsp()->castVarRef()->varScopep() != m_forVscp)
return cantUnroll(nodep, "different variable in condition"); return cantUnroll(nodep, "different variable in condition");
if (m_generate) V3Const::constifyParamsEdit(condBip->lhsp()); // rhsp may change }
AstConst* constStopp = condBip->lhsp()->castConst();
if (m_generate) V3Const::constifyParamsEdit(cmpVarLhs ? cmpInstrp->rhsp()
: cmpInstrp->lhsp()); // rhsp/lhsp may change
AstConst* constStopp = (cmpVarLhs ? cmpInstrp->rhsp()->castConst()
: cmpInstrp->lhsp()->castConst());
if (!constStopp) return cantUnroll(nodep, "non-constant final value"); if (!constStopp) return cantUnroll(nodep, "non-constant final value");
UINFO(8, " Stop expr ok: "<<constStopp<<endl); UINFO(8, " Stop expr ok: "<<constStopp<<endl);
// //
@@ -217,9 +229,9 @@ private:
if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop"); if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop");
// //
// Finally, we can do it // Finally, we can do it
forUnroller(nodep, initp, precondsp, condp, incp, bodysp, forUnroller(nodep, initp, precondsp, incp, bodysp,
constInitp->num(), constInitp->num(),
condBip, constStopp->num(), cmpInstrp, constStopp->num(), cmpVarLhs,
incInstrp, constIncp->num()); nodep = NULL; incInstrp, constIncp->num()); nodep = NULL;
// Cleanup // Cleanup
return true; return true;
@@ -227,10 +239,10 @@ private:
void forUnroller(AstNode* nodep, void forUnroller(AstNode* nodep,
AstNode* initp, AstNode* initp,
AstNode* precondsp, AstNode* condp, AstNode* precondsp,
AstNode* incp, AstNode* bodysp, AstNode* incp, AstNode* bodysp,
const V3Number& numInit, const V3Number& numInit,
AstNodeBiop* cmpInstrp, const V3Number& numStop, AstNodeBiop* cmpInstrp, const V3Number& numStop, bool cmpVarLhs,
AstNodeBiop* incInstrp, const V3Number& numInc) { AstNodeBiop* incInstrp, const V3Number& numInc) {
UINFO(4, " Unroll for var="<<numInit<<"; var<"<<numStop<<"; var+="<<numInc<<endl); UINFO(4, " Unroll for var="<<numInit<<"; var<"<<numStop<<"; var+="<<numInc<<endl);
UINFO(6, " cmpI "<<cmpInstrp<<endl); UINFO(6, " cmpI "<<cmpInstrp<<endl);
@@ -270,7 +282,11 @@ private:
UINFO(8," Looping "<<loopValue<<endl); UINFO(8," Looping "<<loopValue<<endl);
// if loopValue<valStop // if loopValue<valStop
V3Number contin (nodep->fileline(), 1); V3Number contin (nodep->fileline(), 1);
cmpInstrp->numberOperate(contin, numStop, loopValue); if (cmpVarLhs) {
cmpInstrp->numberOperate(contin, loopValue, numStop);
} else {
cmpInstrp->numberOperate(contin, numStop, loopValue);
}
if (contin.isEqZero()) { if (contin.isEqZero()) {
break; // Done with the loop break; // Done with the loop
} else { } else {
+12 -5
View File
@@ -690,15 +690,21 @@ private:
// Pow is special, output sign only depends on LHS sign, but function result depends on both signs // Pow is special, output sign only depends on LHS sign, but function result depends on both signs
// RHS is self-determined (IEEE) // RHS is self-determined (IEEE)
// Real if either side is real (as with AstAdd) // Real if either side is real (as with AstAdd)
iterate_shift_prelim(nodep, vup); // Iterate rhsp() as self-determined
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(CONTEXT,PRELIM).p());
nodep->rhsp()->iterateAndNext(*this,WidthVP(CONTEXT,PRELIM).p());
if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) { if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) {
spliceCvtD(nodep->lhsp()); spliceCvtD(nodep->lhsp());
spliceCvtD(nodep->rhsp()); spliceCvtD(nodep->rhsp());
replaceWithDVersion(nodep); nodep=NULL; replaceWithDVersion(nodep); nodep=NULL;
return;
} }
checkCvtUS(nodep->lhsp());
iterateCheckSizedSelf(nodep,"RHS",nodep->rhsp(),SELF,BOTH);
nodep->dtypeFrom(nodep->lhsp());
} }
if (vup->c()->final()) { if (vup->c()->final()) {
AstNodeDType* expDTypep = vup->c()->dtypeOverridep(nodep->dtypep()); AstNodeDType* expDTypep = vup->c()->dtypeOverridep(nodep->dtypep());
nodep->dtypeFrom(expDTypep); nodep->dtypeFrom(expDTypep);
@@ -902,7 +908,7 @@ private:
} else if (!basicp->isSigned() && newp->isSigned()) { } else if (!basicp->isSigned() && newp->isSigned()) {
newp = new AstUnsigned(nodep->fileline(), newp); newp = new AstUnsigned(nodep->fileline(), newp);
} else { } else {
newp = newp; // Can just remove cast //newp = newp; // Can just remove cast
} }
nodep->replaceWith(newp); nodep->replaceWith(newp);
pushDeletep(nodep); nodep=NULL; pushDeletep(nodep); nodep=NULL;
@@ -925,7 +931,7 @@ private:
: nodep->findBitDType(width, width, underDtp->numeric())); : nodep->findBitDType(width, width, underDtp->numeric()));
nodep->dtypep(newDtp); nodep->dtypep(newDtp);
// We ignore warnings as that is sort of the point of a cast // We ignore warnings as that is sort of the point of a cast
iterateCheck(nodep,"Cast LHS",nodep->lhsp(),SELF,FINAL,newDtp,EXTEND_EXP,false); iterateCheck(nodep,"Cast LHS",nodep->lhsp(),CONTEXT,FINAL,newDtp,EXTEND_EXP,false);
} }
if (vup->c()->final()) { if (vup->c()->final()) {
// CastSize not needed once sizes determined // CastSize not needed once sizes determined
@@ -2297,7 +2303,7 @@ private:
if (newp) {} // Ununused if (newp) {} // Ununused
} }
void iterate_shift_prelim(AstNodeBiop* nodep, AstNUser* vup) { void iterate_shift_prelim(AstNodeBiop* nodep, AstNUser* vup) {
// Shifts, Pow // Shifts
// See IEEE-2012 11.4.10 and Table 11-21. // See IEEE-2012 11.4.10 and Table 11-21.
// RHS is self-determined. RHS is always treated as unsigned, has no effect on result. // RHS is self-determined. RHS is always treated as unsigned, has no effect on result.
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
@@ -2885,6 +2891,7 @@ private:
switch (nodep->type()) { switch (nodep->type()) {
case AstType::atADD: newp = new AstAddD (fl,lhsp,rhsp); break; case AstType::atADD: newp = new AstAddD (fl,lhsp,rhsp); break;
case AstType::atSUB: newp = new AstSubD (fl,lhsp,rhsp); break; case AstType::atSUB: newp = new AstSubD (fl,lhsp,rhsp); break;
case AstType::atPOW: newp = new AstPowD (fl,lhsp,rhsp); break;
case AstType::atEQ: case AstType::atEQCASE: newp = new AstEqD (fl,lhsp,rhsp); break; case AstType::atEQ: case AstType::atEQCASE: newp = new AstEqD (fl,lhsp,rhsp); break;
case AstType::atNEQ: case AstType::atNEQCASE: newp = new AstNeqD (fl,lhsp,rhsp); break; case AstType::atNEQ: case AstType::atNEQCASE: newp = new AstNeqD (fl,lhsp,rhsp); break;
case AstType::atGT: case AstType::atGTS: newp = new AstGtD (fl,lhsp,rhsp); break; case AstType::atGT: case AstType::atGTS: newp = new AstGtD (fl,lhsp,rhsp); break;
+51 -31
View File
@@ -62,8 +62,9 @@ public:
int m_pinNum; // Pin number currently parsing int m_pinNum; // Pin number currently parsing
string m_instModule; // Name of module referenced for instantiations string m_instModule; // Name of module referenced for instantiations
AstPin* m_instParamp; // Parameters for instantiations AstPin* m_instParamp; // Parameters for instantiations
AstNodeModule* m_modp; // Module bool m_tracingParse; // Tracing disable for parser
int m_modTypeImpNum; // Implicit type number, incremented each module
static int s_modTypeImpNum; // Implicit type number, incremented each module
// CONSTRUCTORS // CONSTRUCTORS
V3ParseGrammar() { V3ParseGrammar() {
@@ -76,10 +77,9 @@ public:
m_pinNum = -1; m_pinNum = -1;
m_instModule = ""; m_instModule = "";
m_instParamp = NULL; m_instParamp = NULL;
m_modp = NULL;
m_modTypeImpNum = 0;
m_varAttrp = NULL; m_varAttrp = NULL;
m_caseAttrp = NULL; m_caseAttrp = NULL;
m_tracingParse = true;
} }
static V3ParseGrammar* singletonp() { static V3ParseGrammar* singletonp() {
static V3ParseGrammar singleton; static V3ParseGrammar singleton;
@@ -88,6 +88,9 @@ public:
// METHODS // METHODS
void argWrapList(AstNodeFTaskRef* nodep); void argWrapList(AstNodeFTaskRef* nodep);
bool allTracingOn(FileLine* fl) {
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
}
AstNodeDType* createArray(AstNodeDType* basep, AstRange* rangep, bool isPacked); AstNodeDType* createArray(AstNodeDType* basep, AstRange* rangep, bool isPacked);
AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp); AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp);
AstNode* createSupplyExpr(FileLine* fileline, string name, int value); AstNode* createSupplyExpr(FileLine* fileline, string name, int value);
@@ -121,7 +124,6 @@ public:
AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->nodep()->castPackage(); AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->nodep()->castPackage();
if (!pkgp) { if (!pkgp) {
pkgp = PARSEP->rootp()->dollarUnitPkgAddp(); pkgp = PARSEP->rootp()->dollarUnitPkgAddp();
GRAMMARP->m_modp = pkgp; GRAMMARP->m_modTypeImpNum = 0;
SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global
} }
return pkgp; return pkgp;
@@ -167,6 +169,8 @@ public:
const AstBasicDTypeKwd LOGIC = AstBasicDTypeKwd::LOGIC; // Shorthand "LOGIC" const AstBasicDTypeKwd LOGIC = AstBasicDTypeKwd::LOGIC; // Shorthand "LOGIC"
const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT; const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
int V3ParseGrammar::s_modTypeImpNum = 0;
//====================================================================== //======================================================================
// Macro functions // Macro functions
@@ -686,7 +690,7 @@ timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
package_declaration: // ==IEEE: package_declaration package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE packageFront package_itemListE yENDPACKAGE endLabelE
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($2) $1->addStmtp($2);
SYMP->popScope($1); SYMP->popScope($1);
GRAMMARP->endLabel($<fl>4,$1,$4); } GRAMMARP->endLabel($<fl>4,$1,$4); }
@@ -696,8 +700,7 @@ packageFront<modulep>:
yPACKAGE idAny ';' yPACKAGE idAny ';'
{ $$ = new AstPackage($1,*$2); { $$ = new AstPackage($1,*$2);
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top" $$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
$$->modTrace(v3Global.opt.trace()); $$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$); PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); } SYMP->pushNew($$); }
; ;
@@ -770,7 +773,7 @@ module_declaration: // ==IEEE: module_declaration
// // IEEE: module_nonansi_header + module_ansi_header // // IEEE: module_nonansi_header + module_ansi_header
modFront importsAndParametersE portsStarE ';' modFront importsAndParametersE portsStarE ';'
module_itemListE yENDMODULE endLabelE module_itemListE yENDMODULE endLabelE
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5); if ($5) $1->addStmtp($5);
SYMP->popScope($1); SYMP->popScope($1);
@@ -780,6 +783,7 @@ module_declaration: // ==IEEE: module_declaration
{ $1->modTrace(false); // Stash for implicit wires, etc { $1->modTrace(false); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5); if ($5) $1->addStmtp($5);
GRAMMARP->m_tracingParse = true;
SYMP->popScope($1); SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); } GRAMMARP->endLabel($<fl>7,$1,$7); }
// //
@@ -792,8 +796,7 @@ modFront<modulep>:
// // any formal arguments, as the arguments must land in the new scope. // // any formal arguments, as the arguments must land in the new scope.
yMODULE lifetimeE idAny yMODULE lifetimeE idAny
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine()); { $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
$$->modTrace(v3Global.opt.trace()); $$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$); PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); } SYMP->pushNew($$); }
; ;
@@ -809,8 +812,7 @@ udpFront<modulep>:
{ $$ = new AstPrimitive($1,*$3); $$->inLibrary(true); { $$ = new AstPrimitive($1,*$3); $$->inLibrary(true);
$$->modTrace(false); $$->modTrace(false);
$$->addStmtp(new AstPragma($1,AstPragmaType::INLINE_MODULE)); $$->addStmtp(new AstPragma($1,AstPragmaType::INLINE_MODULE));
PARSEP->fileline()->tracingOn(false); GRAMMARP->m_tracingParse = false;
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$); PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); } SYMP->pushNew($$); }
; ;
@@ -845,8 +847,7 @@ paramPortDeclOrArgList<nodep>: // IEEE: list_of_param_assignments + { parameter_
paramPortDeclOrArg<nodep>: // IEEE: param_assignment + parameter_port_declaration paramPortDeclOrArg<nodep>: // IEEE: param_assignment + parameter_port_declaration
// // We combine the two as we can't tell which follows a comma // // We combine the two as we can't tell which follows a comma
param_assignment { $$ = $1; } parameter_port_declarationFrontE param_assignment { $$ = $2; }
| parameter_port_declarationFront param_assignment { $$ = $2; }
; ;
portsStarE<nodep>: // IEEE: .* + list_of_ports + list_of_port_declarations + empty portsStarE<nodep>: // IEEE: .* + list_of_ports + list_of_port_declarations + empty
@@ -1016,7 +1017,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
// // timeunits_delcarationE is instead in program_item // // timeunits_delcarationE is instead in program_item
pgmFront parameter_port_listE portsStarE ';' pgmFront parameter_port_listE portsStarE ';'
program_itemListE yENDPROGRAM endLabelE program_itemListE yENDPROGRAM endLabelE
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5); if ($5) $1->addStmtp($5);
SYMP->popScope($1); SYMP->popScope($1);
@@ -1028,8 +1029,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
pgmFront<modulep>: pgmFront<modulep>:
yPROGRAM lifetimeE idAny/*new_program*/ yPROGRAM lifetimeE idAny/*new_program*/
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine()); { $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
$$->modTrace(v3Global.opt.trace()); $$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$); PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); } SYMP->pushNew($$); }
; ;
@@ -1154,10 +1154,13 @@ parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); } //UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
; ;
parameter_port_declarationFront: // IEEE: parameter_port_declaration w/o assignment parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assignment
// // IEEE: parameter_declaration (minus assignment) // // IEEE: parameter_declaration (minus assignment)
parameter_declarationFront { } varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
// | varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
| implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
| data_type { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
//UNSUP data_type { VARDTYPE($1); } //UNSUP data_type { VARDTYPE($1); }
//UNSUP yTYPE { VARDTYPE($1); } //UNSUP yTYPE { VARDTYPE($1); }
; ;
@@ -1344,10 +1347,10 @@ data_typeBasic<dtypep>: // IEEE: part of data_type
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
data_typeBasic { $$ = $1; } data_typeBasic { $$ = $1; }
| struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->m_modTypeImpNum++), | struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->s_modTypeImpNum++),
GRAMMARP->m_modp,VFlagChildDType(),$1),$2,true); } SYMP,VFlagChildDType(),$1),$2,true); }
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++), | enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->s_modTypeImpNum++),
GRAMMARP->m_modp,VFlagChildDType(),$1); } SYMP,VFlagChildDType(),$1); }
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); } | ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
| yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); } | yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); }
//UNSUP yEVENT { UNSUP } //UNSUP yEVENT { UNSUP }
@@ -1597,8 +1600,9 @@ implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
type_declaration<nodep>: // ==IEEE: type_declaration type_declaration<nodep>: // ==IEEE: type_declaration
// // Use idAny, as we can redeclare a typedef on an existing typedef // // Use idAny, as we can redeclare a typedef on an existing typedef
yTYPEDEF data_type idAny variable_dimensionListE ';' { $$ = new AstTypedef($<fl>1, *$3, VFlagChildDType(), GRAMMARP->createArray($2,$4,false)); yTYPEDEF data_type idAny variable_dimensionListE dtypeAttrListE ';'
SYMP->reinsert($$); } /**/ { $$ = new AstTypedef($<fl>1, *$3, $5, VFlagChildDType(), GRAMMARP->createArray($2,$4,false));
SYMP->reinsert($$); }
//UNSUP yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; $1->v3error("Unsupported: SystemVerilog 2005 typedef in this context"); } //UNSUP //UNSUP yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; $1->v3error("Unsupported: SystemVerilog 2005 typedef in this context"); } //UNSUP
// // Combines into above "data_type id" rule // // Combines into above "data_type id" rule
// // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned // // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned
@@ -1609,6 +1613,20 @@ type_declaration<nodep>: // ==IEEE: type_declaration
//UNSUP yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($<fl>1, *$3); SYMP->reinsert($$); } //UNSUP yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($<fl>1, *$3); SYMP->reinsert($$); }
; ;
dtypeAttrListE<nodep>:
/* empty */ { $$ = NULL; }
| dtypeAttrList { $$ = $1; }
;
dtypeAttrList<nodep>:
dtypeAttr { $$ = $1; }
| dtypeAttrList dtypeAttr { $$ = $1->addNextNull($2); }
;
dtypeAttr<nodep>:
yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::DT_PUBLIC); }
;
//************************************************ //************************************************
// Module Items // Module Items
@@ -2020,9 +2038,11 @@ instnameList<nodep>:
| instnameList ',' instnameParen { $$ = $1->addNext($3); } | instnameList ',' instnameParen { $$ = $1->addNext($3); }
; ;
instnameParen<nodep>: instnameParen<cellp>:
id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2); } id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2);
| id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2); } $$->trace(GRAMMARP->allTracingOn($<fl>1)); }
| id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2);
$$->trace(GRAMMARP->allTracingOn($<fl>1)); }
//UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP //UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP
// // Adding above and switching to the Verilog-Perl syntax // // Adding above and switching to the Verilog-Perl syntax
// // causes a shift conflict due to use of idClassSel inside exprScope. // // causes a shift conflict due to use of idClassSel inside exprScope.
@@ -3786,7 +3806,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
// Propagate from current module tracing state // Propagate from current module tracing state
if (nodep->isGenVar()) nodep->trace(false); if (nodep->isGenVar()) nodep->trace(false);
else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false); else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false);
else nodep->trace(v3Global.opt.trace() && nodep->fileline()->tracingOn()); else nodep->trace(allTracingOn(nodep->fileline()));
// Remember the last variable created, so we can attach attributes to it in later parsing // Remember the last variable created, so we can attach attributes to it in later parsing
GRAMMARP->m_varAttrp = nodep; GRAMMARP->m_varAttrp = nodep;
+1 -1
View File
@@ -673,7 +673,7 @@ sub compile {
if ($param{make_pli}) { if ($param{make_pli}) {
$self->oprint("Compile vpi\n"); $self->oprint("Compile vpi\n");
my @cmd = ('g++', @{$param{pli_flags}}, "-DIS_VPI", "$self->{t_dir}/$self->{name}.cpp"); my @cmd = ('c++', @{$param{pli_flags}}, "-DIS_VPI", "$self->{t_dir}/$self->{name}.cpp");
$self->_run(logfile=>"$self->{obj_dir}/pli_compile.log", $self->_run(logfile=>"$self->{obj_dir}/pli_compile.log",
fails=>$param{fails}, fails=>$param{fails},
+2 -2
View File
@@ -54,10 +54,10 @@ module t (/*AUTOARG*/
if (cyc==0) begin if (cyc==0) begin
// Setup // Setup
crc <= 64'h5aef0c8d_d70a4497; crc <= 64'h5aef0c8d_d70a4497;
sum <= 64'h0; sum <= '0;
end end
else if (cyc<10) begin else if (cyc<10) begin
sum <= 64'h0; sum <= '0;
end end
else if (cyc<90) begin else if (cyc<90) begin
end end
+1 -1
View File
@@ -33,7 +33,7 @@ module t (/*AUTOARG*/
assert (0) else $info; assert (0) else $info;
assert (0) else $info("Info message"); assert (0) else $info("Info message");
assert (0) else $info("Info message, cyc=%d", cyc); assert (0) else $info("Info message, cyc=%d", cyc);
InWarningBlock: assert (0) else $warning("Warning...."); InWarningBlock: assert (0) else $warning("Warning.... 1.0=%f 2.0=%f", 1.0, 2.0);
InErrorBlock: assert (0) else $error("Error...."); InErrorBlock: assert (0) else $error("Error....");
assert (0) else $fatal(1,"Fatal...."); assert (0) else $fatal(1,"Fatal....");
`endif `endif
+5 -5
View File
@@ -8,17 +8,17 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Version 2.0. # Version 2.0.
compile ( compile (
verilator_flags2 => ["--stats --profile-cfuncs"], verilator_flags2 => ["--stats"],
); );
if ($Self->{vlt}) { if ($Self->{vlt}) {
file_grep ($Self->{stats}, qr/Optimizations, Tables created\s+(\d+)/i, 10); file_grep ($Self->{stats}, qr/Optimizations, Tables created\s+(\d+)/i, 10);
file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, 10); file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, 9);
} }
execute ( execute (
check_finished=>1, check_finished=>1,
); );
ok(1); ok(1);
1; 1;
+44
View File
@@ -0,0 +1,44 @@
#!/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.
$Self->{vlt} or $Self->skip("Verilator only test");
top_filename("t/t_case_huge.v");
compile (
verilator_flags2 => ["--stats --profile-cfuncs -CFLAGS '-pg' -LDFLAGS '-pg'"],
);
if ($Self->{vlt}) {
file_grep ($Self->{stats}, qr/Optimizations, Tables created\s+(\d+)/i, 10);
file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, 10);
}
unlink $_ foreach (glob "$Self->{obj_dir}/gmon.out.*");
$ENV{GMON_OUT_PREFIX} = "$Self->{obj_dir}/gmon.out";
execute (
check_finished=>1,
);
my $gmon_path;
$gmon_path = $_ foreach (glob "$Self->{obj_dir}/gmon.out.*");
$gmon_path or $Self->error("Profiler did not create a gmon.out");
(my $gmon_base = $gmon_path) =~ s!.*[/\\]!!;
$Self->_run(cmd=>["cd $Self->{obj_dir} && gprof $Self->{VM_PREFIX} $gmon_base > gprof.out"],
check_finished=>0);
$Self->_run(cmd=>["cd $Self->{obj_dir} && $ENV{VERILATOR_ROOT}/bin/verilator_profcfunc gprof.out > cfuncs.out"],
check_finished=>0);
file_grep ("$Self->{obj_dir}/cfuncs.out", qr/Overall summary by/);
ok(1);
1;
+23
View File
@@ -0,0 +1,23 @@
#!/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.
compile (
v_flags2 => ["--stats"],
);
execute (
check_finished=>1,
);
if ($Self->{vlt}) {
file_grep ($Self->{stats}, qr/Optimizations, Gate assign merged\s+(\d+)/i, 28);
};
ok(1);
1;
+100
View File
@@ -0,0 +1,100 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Jie Xu.
//
// change these two parameters to see the speed differences
`define DATA_WIDTH 8
`define REP_COUNT4 `DATA_WIDTH/4
`define REP_COUNT2 `DATA_WIDTH/2
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
reg [3:0] count4 = 0;
reg [1:0] count2 = 0;
reg [`DATA_WIDTH-1:0] a = {`REP_COUNT4{4'b0000}};
reg [`DATA_WIDTH-1:0] b = {`REP_COUNT4{4'b1111}};
reg [`DATA_WIDTH-1:0] c = {`REP_COUNT4{4'b1111}};
reg [`DATA_WIDTH-1:0] d = {`REP_COUNT4{4'b1111}};
reg [`DATA_WIDTH-1:0] res1;
reg [`DATA_WIDTH-1:0] res2;
reg [`DATA_WIDTH-1:0] res3;
reg [`DATA_WIDTH-1:0] res4;
drv1 t_drv1 [`DATA_WIDTH-1:0] (.colSelA(a), .datao(res1));
drv2 t_drv2 [`DATA_WIDTH-1:0] (.colSelA(a), .colSelB(b), .datao(res2));
drv3 t_drv3 [`DATA_WIDTH-1:0] (.colSelA(a), .colSelB(b), .colSelC(c), .datao(res3));
drv4 t_drv4 [`DATA_WIDTH-1:0] (.colSelA(a), .colSelB(b), .colSelC(c), .colSelD(d), .datao(res4));
always@(posedge clk)
begin
count2 <= count2 + 1;
count4 <= count4 + 1;
a <= {`REP_COUNT4{count4}};
b <= {`REP_COUNT4{count4}};
c <= {`REP_COUNT2{count2}};
d <= {`REP_COUNT2{count2}};
if (res1 != (a)) begin
$stop;
end
if (res2 != (a&b)) begin
$stop;
end
if (res3 != (a&b&c)) begin
$stop;
end
if (res4 != (a&b&c&d)) begin
$stop;
end
if (count4 > 10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module drv1
(input colSelA,
output datao
);
assign datao = colSelA;
endmodule
module drv2
(input colSelA,
input colSelB,
output datao
);
assign datao = colSelB & colSelA;
endmodule
module drv3
(input colSelA,
input colSelB,
input colSelC,
output datao
);
assign datao = colSelB & colSelA & colSelC;
endmodule
module drv4
(input colSelA,
input colSelB,
input colSelC,
input colSelD,
output datao
);
assign datao = colSelB & colSelA & colSelC & colSelD;
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2004 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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+71
View File
@@ -0,0 +1,71 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2004 by Jie Xu.
//
// The test was added together with the concat optimization.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc; initial cyc=1;
reg [31:0] in_a;
reg [31:0] in_b;
reg [31:0] in_c;
reg [31:0] in_d;
reg [31:0] in_e;
reg [15:0] in_f;
wire [31:0] in_g;
assign in_g = in_a << 4;
reg [31:0] out_x;
reg [31:0] out_y;
reg [31:0] out_z;
reg [31:0] out_o;
reg [31:0] out_p;
reg [31:0] out_q;
assign out_x = {in_a[31:16] & in_f, in_a[15:0] & in_f};
assign out_y = {in_a[31:18] & in_b[31:18], in_a[17:0] & in_b[17:0]};
assign out_z = {in_c[31:14] & in_d[31:14] & in_e[31:14], in_c[13:0] & in_d[13:0] & in_e[13:0]};
assign out_o = out_z | out_y;
assign out_p = {in_a[31:16] & in_f | in_e[31:16], in_a[15:0] & in_f | in_e[15:0]};
assign out_q = {{in_a[31:25] ^ in_g[31:25], in_a[24:16] ^ in_g[24:16]}, {in_a[15:5] ^ in_g[15:5], in_a[4:0] ^ in_g[4:0]}};
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
in_a <= cyc;
in_b <= cyc + 1;
in_c <= cyc + 3;
in_d <= cyc + 8;
in_e <= cyc;
in_f <= cyc[15:0];
if (out_x != (in_a & {2{in_f}}))
$stop;
if (out_y != (in_a&in_b))
$stop;
if (out_z != (in_e&in_d&in_c))
$stop;
if (out_o != (((in_a&in_b)|(in_c&in_e&in_d))))
$stop;
if (out_p != (in_a & {2{in_f}} | in_e))
$stop;
if (out_q != (in_a ^ in_g))
$stop;
if (cyc==100) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
+14
View File
@@ -27,6 +27,7 @@ module sub (input integer inst);
import "DPI-C" context function int dpic_line(); import "DPI-C" context function int dpic_line();
import "DPI-C" context function int dpic_save(int value); import "DPI-C" context function int dpic_save(int value);
import "DPI-C" context function int dpic_restore(); import "DPI-C" context function int dpic_restore();
import "DPI-C" context function int unsigned dpic_getcontext();
int result; int result;
@@ -49,4 +50,17 @@ module sub (input integer inst);
if (dpic_restore() != 23+inst) $stop; if (dpic_restore() != 23+inst) $stop;
endtask endtask
int unsigned cntxt1;
int unsigned cntxt2;
initial begin
cntxt1 = dpic_getcontext();
begin : caller_context
// call from a different scope - should still get the context of the function declaration
cntxt2 = dpic_getcontext();
end
// svContext should be the context of the function declaration, not the context of the function call
if (cntxt1 != cntxt2) $stop;
end
endmodule endmodule
+7
View File
@@ -42,6 +42,7 @@ extern "C" {
extern int dpic_line(); extern int dpic_line();
extern int dpic_save(int value); extern int dpic_save(int value);
extern int dpic_restore(); extern int dpic_restore();
extern unsigned dpic_getcontext();
} }
#endif #endif
@@ -126,3 +127,9 @@ int dpic_restore() {
return 0; return 0;
} }
} }
unsigned dpic_getcontext() {
svScope scope = svGetScope();
printf("%%Info: svGetScope returned scope (%p) with name %s\n", scope, svGetNameFromScope(scope));
return (unsigned) (uintptr_t) scope;
}
+26
View File
@@ -0,0 +1,26 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2006 by Wilson Snyder.
#include <verilated.h>
#include "Vt_enum_public.h"
#include "Vt_enum_public_p3.h"
#include "Vt_enum_public_p62.h"
int main (int argc, char *argv[]) {
Vt_enum_public *topp = new Vt_enum_public;
Verilated::debug(0);
// Make sure public tag worked
if (Vt_enum_public_p3::ZERO || Vt_enum_public_p3::ONE) {}
if (Vt_enum_public_p62::ZERO || Vt_enum_public_p62::ALLONE) {}
for (int i = 0; i < 10; i++) {
topp->eval();
}
}
+26
View File
@@ -0,0 +1,26 @@
#!/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.
if ($Self->{vlt}) {
compile (
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
make_top_shell => 0,
make_main => 0,
);
} else {
compile (
);
}
execute (
check_finished=>1,
);
ok(1);
1;
+33
View File
@@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
package p3;
typedef enum logic [2:0] {
ZERO = 3'b0,
ONE = 3'b1 } e3_t /*verilator public*/;
endpackage
package p62;
typedef enum logic [62:0] {
ZERO = '0,
ALLONE = '1 } e62_t /*verilator public*/;
endpackage
module t (/*AUTOARG*/);
enum integer {
EI_A,
EI_B,
EI_C
} m_state;
initial begin
m_state = EI_A;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+19
View File
@@ -0,0 +1,19 @@
#!/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.
compile (
v_flags2 => ["-f t/t_flag_define.vc"],
);
execute (
check_finished=>1,
);
ok(1);
1;
+61
View File
@@ -0,0 +1,61 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Wilson Snyder
`define STRINGIFY(x) `"x`"
module t;
initial begin
`ifdef D1A
if (`STRINGIFY(`D4B) !== "") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D2A
if (`STRINGIFY(`D2A) !== "VALA") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D3A
if (`STRINGIFY(`D4B) !== "") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D3B
if (`STRINGIFY(`D4B) !== "") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D4A
if (`STRINGIFY(`D4A) !== "VALA") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D4B
if (`STRINGIFY(`D4B) !== "") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D5A
if (`STRINGIFY(`D5A) !== "VALA") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
`ifdef D5A
if (`STRINGIFY(`D5B) !== "VALB") $stop;
`else
$write("%%Error: Missing define\n"); $stop;
`endif
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+7
View File
@@ -0,0 +1,7 @@
+define+D1A
+define+D2A=VALA
+define+D3A+D3B
+define+D4A=VALA+D4B
+define+D5A=VALA+D5B=VALB
// Quotes do NOT escape the plus
//+define+D5A="VALA+D5B"+D5C
+3 -3
View File
@@ -10,13 +10,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
$Self->{vlt} or $Self->skip("Verilator only test"); $Self->{vlt} or $Self->skip("Verilator only test");
$Self->_run (cmd=>["cd $Self->{obj_dir}" $Self->_run (cmd=>["cd $Self->{obj_dir}"
." && g++ -c ../../t/t_flag_ldflags_a.cpp" ." && c++ -c ../../t/t_flag_ldflags_a.cpp"
." && ar r t_flag_ldflags_a.a t_flag_ldflags_a.o" ." && ar r t_flag_ldflags_a.a t_flag_ldflags_a.o"
." && ranlib t_flag_ldflags_a.a "], ." && ranlib t_flag_ldflags_a.a "],
check_finished=>0); check_finished=>0);
$Self->_run (cmd=>["cd $Self->{obj_dir}" $Self->_run (cmd=>["cd $Self->{obj_dir}"
." && g++ -fPIC -c ../../t/t_flag_ldflags_so.cpp" ." && c++ -fPIC -c ../../t/t_flag_ldflags_so.cpp"
." && g++ -shared -o t_flag_ldflags_so.so -lc t_flag_ldflags_so.o"], ." && c++ -shared -o t_flag_ldflags_so.so -lc t_flag_ldflags_so.o"],
check_finished=>0); check_finished=>0);
compile ( compile (
+2
View File
@@ -5,6 +5,8 @@
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
`define is_near_real(a,b) ($abs((a)-(b)) < (((a)/(b))*0.0001))
module t (/*AUTOARG*/ module t (/*AUTOARG*/
// Inputs // Inputs
clk clk
+11
View File
@@ -26,6 +26,7 @@
reg [5:0] w6_u; reg [5:0] w6_u;
reg [15:0] w16a_u; reg [15:0] w16a_u;
reg [15:0] w16_u; reg [15:0] w16_u;
reg [31:0] w32_u;
real r; real r;
reg signed [4:0] bug754_a; reg signed [4:0] bug754_a;
@@ -162,6 +163,16 @@
w4_u = (w4_u >> w4_u) ^~ (w4_u >> w4_u); w4_u = (w4_u >> w4_u) ^~ (w4_u >> w4_u);
`checkh(w4_u, 4'b1111); `checkh(w4_u, 4'b1111);
// bug828
// verilator lint_off WIDTH
w32_u = 32'(signed'({4'b0001,5'b10000}) << 3);
`checkh(w32_u, 32'h0000_0180);
w32_u = 32'(signed'({4'b0011,5'b10000}) << 3);
`checkh(w32_u, 32'h0000_0380);
// verilator lint_on WIDTH
w32_u = 32'(signed'({4'b0011,5'b10000})) << 3; // Check no width warning
`checkh(w32_u, 32'h0000_0380);
if (fail) $stop; if (fail) $stop;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
+2
View File
@@ -25,6 +25,7 @@ module t (/*AUTOARG*/
initial begin initial begin
// Check constant propagation // Check constant propagation
// Note $abs is not defined in SystemVerilog (as of 2012)
check(`__LINE__, $ceil(-1.2), -1); check(`__LINE__, $ceil(-1.2), -1);
check(`__LINE__, $ceil(1.2), 2); check(`__LINE__, $ceil(1.2), 2);
check(`__LINE__, $exp(1.2), 3.3201169227365472380597566370852291584014892578125); check(`__LINE__, $exp(1.2), 3.3201169227365472380597566370852291584014892578125);
@@ -43,6 +44,7 @@ module t (/*AUTOARG*/
//check(`__LINE__, $pow(-2.3,1.2),0); // Bad value //check(`__LINE__, $pow(-2.3,1.2),0); // Bad value
check(`__LINE__, $sqrt(1.2), 1.095445115010332148841598609578795731067657470703125); check(`__LINE__, $sqrt(1.2), 1.095445115010332148841598609578795731067657470703125);
//check(`__LINE__, $sqrt(-1.2), 0); // Bad value //check(`__LINE__, $sqrt(-1.2), 0); // Bad value
check(`__LINE__, ((1.5)**(1.25)), 1.660023);
`ifndef VERILATOR `ifndef VERILATOR
check(`__LINE__, $acos (0.2), 1.369438406); // Arg1 is -1..1 check(`__LINE__, $acos (0.2), 1.369438406); // Arg1 is -1..1
check(`__LINE__, $acosh(1.2), 0.622362503); check(`__LINE__, $acosh(1.2), 0.622362503);
+2 -2
View File
@@ -46,8 +46,8 @@ module m1;
initial if (PACKED_PARAM != 8'h36) $stop; initial if (PACKED_PARAM != 8'h36) $stop;
endmodule endmodule
module m2; // bug 810
parameter PAR2 = 10; module m2 #(/*parameter*/ integer PAR2 = 10);
initial begin initial begin
$display("%x",PAR2); $display("%x",PAR2);
if (PAR2 !== 2) $stop; if (PAR2 !== 2) $stop;
+24
View File
@@ -0,0 +1,24 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2006 by Wilson Snyder.
#include <verilated.h>
#include "Vt_param_public.h"
#include "Vt_param_public_p.h"
int main (int argc, char *argv[]) {
Vt_param_public *topp = new Vt_param_public;
Verilated::debug(0);
// Make sure public tag worked
if (Vt_param_public_p::INPACK) {}
for (int i = 0; i < 10; i++) {
topp->eval();
}
}
+10 -2
View File
@@ -7,8 +7,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
compile ( if ($Self->{vlt}) {
); compile (
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
make_top_shell => 0,
make_main => 0,
);
} else {
compile (
);
}
execute ( execute (
check_finished=>1, check_finished=>1,
+5
View File
@@ -36,3 +36,8 @@ module b #(
initial if ($c32("TWO") != 2) $stop; initial if ($c32("TWO") != 2) $stop;
`endif `endif
endmodule endmodule
//bug804
package p;
localparam INPACK /*verilator public*/ = 6;
endpackage
+5 -1
View File
@@ -788,6 +788,10 @@ module t;
initial $write("GOT='%s' EXP='%s'\n", "foo `A(bar) baz", "foo `A(bar) baz"); initial $write("GOT='%s' EXP='%s'\n", "foo `A(bar) baz", "foo `A(bar) baz");
initial $write("Slashed=`%s'\n", "1//2.3");
endmodule endmodule
@@ -809,4 +813,4 @@ predef 1 1
predef 2 2 predef 2 2
`line 544 "t/t_preproc.v" 2 `line 548 "t/t_preproc.v" 2
+4
View File
@@ -520,6 +520,10 @@ module t;
`define A(name) boo name hiss `define A(name) boo name hiss
initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz"); initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz");
`undef A `undef STR `undef A `undef STR
//----
// bug845
`define SLASHED "1//2.3"
initial $write("Slashed=`%s'\n", `SLASHED);
endmodule endmodule
//====================================================================== //======================================================================
// IEEE mandated predefines // IEEE mandated predefines
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+91
View File
@@ -0,0 +1,91 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Wilson Snyder.
// bug823
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 [2:0] in = crc[2:0];
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [3:0] mask; // From test of Test.v
wire [3:0] out; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.out (out[3:0]),
.mask (mask[3:0]),
// Inputs
.clk (clk),
.in (in[2:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0, out & mask};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x out=%b mask=%b\n",$time, cyc, crc, out, mask);
`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'ha9d3a7a69d2bea75
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (/*AUTOARG*/
// Outputs
out, mask,
// Inputs
clk, in
);
input clk;
input [2:0] in;
output reg [3:0] out;
output reg [3:0] mask;
localparam [15:5] p = 11'h1ac;
always @(posedge clk) begin
// verilator lint_off WIDTH
out <= p[15 + in -: 5];
// verilator lint_on WIDTH
mask[3] <= ((15 + in - 5) < 12);
mask[2] <= ((15 + in - 5) < 13);
mask[1] <= ((15 + in - 5) < 14);
mask[0] <= ((15 + in - 5) < 15);
end
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+91
View File
@@ -0,0 +1,91 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Wilson Snyder.
// bug823
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 [6:0] in = crc[6:0];
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [3:0] mask; // From test of Test.v
wire [3:0] out; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.out (out[3:0]),
.mask (mask[3:0]),
// Inputs
.clk (clk),
.in (in[6:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0, out & mask};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x out=%b mask=%b\n",$time, cyc, crc, out, mask);
`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'h4e9d3a74e9d3f656
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (/*AUTOARG*/
// Outputs
out, mask,
// Inputs
clk, in
);
input clk;
input [6:0] in; // Note much wider than any index
output reg [3:0] out;
output reg [3:0] mask;
localparam [15:5] p = 11'h1ac;
always @(posedge clk) begin
// verilator lint_off WIDTH
out <= p[15 + in -: 5];
// verilator lint_on WIDTH
mask[3] <= ((15 + in - 5) < 12);
mask[2] <= ((15 + in - 5) < 13);
mask[1] <= ((15 + in - 5) < 14);
mask[0] <= ((15 + in - 5) < 15);
end
endmodule
+1 -1
View File
@@ -66,7 +66,7 @@ module t (/*AUTOARG*/
8'd04: begin if ((to^from)!==80'h6d000000000000000000) $stop; end 8'd04: begin if ((to^from)!==80'h6d000000000000000000) $stop; end
8'd05: begin if (((to^from)&~80'hf)!==80'h90000000000000000000) $stop; end // Exceed bounds, verilator may write index 0 8'd05: begin if (((to^from)&~80'hf)!==80'h90000000000000000000) $stop; end // Exceed bounds, verilator may write index 0
8'd06: begin if (((to^from)&~80'hf)!==80'h00000000000000000020) $stop; end // Exceed bounds, verilator may write index 0 8'd06: begin if (((to^from)&~80'hf)!==80'h00000000000000000020) $stop; end // Exceed bounds, verilator may write index 0
8'd07: begin if (((to^from)&~80'hf)!==80'h0c000000000000000000) $stop; end 8'd07: begin if (((to^from)&~80'hf)!==80'h4c000000000000000000) $stop; end
8'd08: begin if ((to^from)!==80'h0004d000000000000000) $stop; end 8'd08: begin if ((to^from)!==80'h0004d000000000000000) $stop; end
8'd09: begin if (((to^from)&~80'hf)!==80'h00000000000000000000) $stop; end 8'd09: begin if (((to^from)&~80'hf)!==80'h00000000000000000000) $stop; end
default: $stop; default: $stop;
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
v_flags2 => ["--lint-only"],
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
);
ok(1);
1;
+26
View File
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2013 by Wilson Snyder.
// Anonymous
struct packed {
logic [31:0] val1;
logic [31:0] val2;
} struct1;
struct packed {
logic [31:0] val3;
logic [31:0] val4;
} struct2;
module t (
output [63:0] s1,
output [63:0] s2
);
initial struct1 = 64'h123456789_abcdef0;
always_comb s1 = struct1;
initial struct2 = 64'h123456789_abcdef0;
always_comb s2 = struct2;
endmodule
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 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.
# Note: need to run at a higher optimization level to reproduce the issue
$Self->{benchmark} = 1;
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+35
View File
@@ -0,0 +1,35 @@
// DESCRIPTION: Verilator:
// Test an error where a shift amount was out of bounds and the compiler treats the
// value as undefined (Issue #803)
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Jeff Bush.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
struct packed {
logic flag;
logic [130:0] data;
} foo[1];
integer cyc=0;
// Test loop
always @ (posedge clk) begin
cyc <= cyc + 1;
foo[0].data <= 0;
foo[0].flag <= !foo[0].flag;
if (cyc==10) begin
if (foo[0].data != 0) begin
$display("bad data value %x", foo[0].data);
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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.
compile (
verilator_flags2 => ['--cc --trace --trace-structs'],
);
execute (
check_finished=>1,
);
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
ok(1);
1;
+26
View File
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Wilson Snyder.
module t (clk);
input clk;
integer cyc=0;
// Trace would overflow at 256KB which is 256 kb dump, 16 kb in a chunk
typedef struct packed {
logic [1024*1024:0] d;
} s1_t; // 128 b
s1_t biggie;
always @ (posedge clk) begin
cyc <= cyc + 1;
biggie [ cyc +: 32 ] <= 32'hfeedface;
if (cyc == 5) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+8
View File
@@ -17,6 +17,10 @@ module t (/*AUTOARG*/
integer c_trace_on; integer c_trace_on;
real r; real r;
// verilator tracing_off
sub sub ();
// verilator tracing_on
always @ (posedge clk) begin always @ (posedge clk) begin
if (cyc!=0) begin if (cyc!=0) begin
cyc <= cyc + 1; cyc <= cyc + 1;
@@ -34,3 +38,7 @@ module t (/*AUTOARG*/
end end
endmodule endmodule
module sub;
integer inside_sub = 0;
endmodule
+1
View File
@@ -21,6 +21,7 @@ if ($Self->{vlt}) {
file_grep ("$Self->{obj_dir}/V$Self->{name}__Trace__Slow.cpp", qr/c_trace_on\"/x); file_grep ("$Self->{obj_dir}/V$Self->{name}__Trace__Slow.cpp", qr/c_trace_on\"/x);
file_grep_not ("$Self->{obj_dir}/V$Self->{name}__Trace__Slow.cpp", qr/_trace_off\"/x); file_grep_not ("$Self->{obj_dir}/V$Self->{name}__Trace__Slow.cpp", qr/_trace_off\"/x);
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x); file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
file_grep_not ("$Self->{obj_dir}/simx.vcd", qr/inside_sub/x);
} }
ok(1); ok(1);
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
v_flags2 => ["--trace"],
);
execute (
check_finished=>1,
);
ok(1);
1;
+36
View File
@@ -0,0 +1,36 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Jonathon Donaldson.
package my_funcs;
function automatic int simple_func (input int value);
begin
simple_func = value;
end
endfunction
endpackage
package my_module_types;
import my_funcs::*;
localparam MY_PARAM = 3;
localparam MY_PARAM2 /*verilator public*/ = simple_func(12);
endpackage
module t
import my_module_types::*;
(
input i_clk,
input [MY_PARAM-1:0] i_d,
output logic [MY_PARAM-1:0] o_q
);
always_ff @(posedge i_clk)
o_q <= i_d;
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2013 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.
compile (
v_flags2 => ["--trace"],
);
execute (
check_finished=>1,
);
if ($Self->{vlt}) {
file_grep ("$Self->{obj_dir}/simx.vcd", "sub_t_i");
};
ok(1);
1;
+43
View File
@@ -0,0 +1,43 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Jie Xu.
module t
(
clk
);
input clk;
integer cyc; initial cyc = 0;
reg a;
reg b;
reg z;
sub_t sub_t_i (z, a, b);
always @ (posedge clk) begin
cyc <= cyc + 1;
a <= cyc[0];
b <= cyc[1];
if (cyc > 10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
primitive CINV (a, b);
output b;
input a;
assign b = ~a;
endprimitive
module sub_t (z, x, y);
input x, y;
output z;
assign z = x & y;
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+29
View File
@@ -0,0 +1,29 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2004 by Wilson Snyder.
//bug830
module sub();
endmodule
function integer cdiv(input integer x);
begin
cdiv = 10;
end
endfunction
module t (/*AUTOARG*/);
genvar j;
generate
for (j = 0; j < cdiv(10); j=j+1)
sub sub();
endgenerate
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+102
View File
@@ -0,0 +1,102 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Use this file as a template for submitting bugs, etc.
// This module takes a single clock input, and should either
// $write("*-* All Finished *-*\n");
// $finish;
// on success, or $stop.
//
// The code as shown applies a random vector to the Test
// module, then calculates a CRC on the Test module's outputs.
//
// **If you do not wish for your code to be released to the public
// please note it here, otherwise:**
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by ____YOUR_NAME_HERE____.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [255:0] sum;
// Take CRC data and apply to testblock inputs
wire [127:0] in = {~crc[63:0], crc[63:0]};
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [127:0] o1; // From test of Test.v
wire [127:0] o2; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.o1 (o1[127:0]),
.o2 (o2[127:0]),
// Inputs
.in (in[127:0]));
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x %x\n",$time, cyc, crc, o1, o2);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= {o1,o2} ^ {sum[254:0],sum[255]^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 256'h008a080aaa000000140550404115dc7b008a080aaae7c8cd897bc1ca49c9350a
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (/*AUTOARG*/
// Outputs
o1, o2,
// Inputs
in
);
input [127:0] in;
output logic [127:0] o1;
output logic [127:0] o2;
always_comb begin: b_test
logic [127:0] tmpp;
logic [127:0] tmp;
tmp = '0;
tmpp = '0;
tmp[63:0] = in[63:0];
tmpp[63:0] = in[63:0];
tmpp[63:0] = {tmp[0+:32], tmp[32+:32]};
tmp[63:0] = {tmp[0+:32], tmp[32+:32]};
o1 = tmp;
o2 = tmpp;
end
endmodule
+1 -1
View File
@@ -152,7 +152,7 @@ struct params {
unsigned int size; unsigned int size;
unsigned int direction; unsigned int direction;
unsigned int scalar; unsigned int scalar;
unsigned int type; int type;
} attributes, children; } attributes, children;
} values[] = { } values[] = {
{"onebit", {1, vpiNoDirection, 1, vpiReg}, {0, 0, 0, 0}}, {"onebit", {1, vpiNoDirection, 1, vpiReg}, {0, 0, 0, 0}},
+2 -2
View File
@@ -133,7 +133,7 @@ int _mon_check_memory() {
// iterate and store // iterate and store
iter_h = vpi_iterate(vpiMemoryWord, mem_h); iter_h = vpi_iterate(vpiMemoryWord, mem_h);
cnt = 0; cnt = 0;
while (lcl_h = vpi_scan(iter_h)) { while ((lcl_h = vpi_scan(iter_h))) {
value.value.integer = ++cnt; value.value.integer = ++cnt;
vpi_put_value(lcl_h, &value, NULL, vpiNoDelay); vpi_put_value(lcl_h, &value, NULL, vpiNoDelay);
// check size and range // check size and range
@@ -143,7 +143,7 @@ int _mon_check_memory() {
// iterate and accumulate // iterate and accumulate
iter_h = vpi_iterate(vpiMemoryWord, mem_h); iter_h = vpi_iterate(vpiMemoryWord, mem_h);
cnt = 0; cnt = 0;
while (lcl_h = vpi_scan(iter_h)) { while ((lcl_h = vpi_scan(iter_h))) {
++cnt; ++cnt;
vpi_get_value(lcl_h, &value); vpi_get_value(lcl_h, &value);
CHECK_RESULT(value.value.integer, cnt); CHECK_RESULT(value.value.integer, cnt);
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 B