mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55f0d4ddd8 | ||
|
|
6d66fcaa57 | ||
|
|
26e79ca889 | ||
|
|
62eb247c1e | ||
|
|
c5fd583b2c | ||
|
|
117db3e11c | ||
|
|
3f82fd2f37 | ||
|
|
e9c46afcf7 | ||
|
|
3234fa15ef | ||
|
|
7ef84df852 | ||
|
|
4e2884b509 | ||
|
|
03100020ab | ||
|
|
8bfb5cc5e9 | ||
|
|
cf6d07aafa | ||
|
|
85c3179dbd | ||
|
|
bfbca34eb0 | ||
|
|
b73edc0564 | ||
|
|
6ba90e3a50 | ||
|
|
e8edbad18c | ||
|
|
c86fec5307 | ||
|
|
6e476255ca | ||
|
|
27af9b6b06 | ||
|
|
f8208fa961 | ||
|
|
87b9cb49ad | ||
|
|
b2da0772e6 | ||
|
|
4f73e0850e | ||
|
|
b6a39db627 | ||
|
|
3a83b06572 | ||
|
|
fe5bf01b25 | ||
|
|
5559ec903b | ||
|
|
18750028b2 | ||
|
|
6b88648c67 | ||
|
|
58ee803cb4 | ||
|
|
894ff73c7d | ||
|
|
8031f0ed7f | ||
|
|
3a56b5da47 |
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()); }
|
||||||
|
|
||||||
|
|||||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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)");
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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*) {
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Executable
+44
@@ -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;
|
||||||
Executable
+23
@@ -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;
|
||||||
@@ -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
|
||||||
|
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 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;
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+26
@@ -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;
|
||||||
@@ -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
|
||||||
|
|
||||||
Executable
+19
@@ -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;
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -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
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
verilator_make_gcc => 0,
|
||||||
|
make_top_shell => 0,
|
||||||
|
make_main => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -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
|
||||||
|
|
||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 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;
|
||||||
@@ -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
|
||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 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;
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 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;
|
||||||
@@ -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
|
||||||
Executable
+23
@@ -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;
|
||||||
@@ -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
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -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
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -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
|
||||||
@@ -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}},
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 885 B |
Reference in New Issue
Block a user