mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 00:23:35 +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 ...]
|
||||
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
|
||||
|
||||
*** 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-<srcfile> <level> Enable debugging a source file at a level
|
||||
--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-treei <level> Enable dumping .tree files at a level
|
||||
-E Preprocess, but do not compile
|
||||
@@ -572,13 +572,16 @@ the comment "DefaultClock":
|
||||
|
||||
=item -DI<var>=I<value>
|
||||
|
||||
Defines the given preprocessor symbol. Same as +define; +define is fairly
|
||||
standard across Verilog tools while -D is an alias for GCC compatibility.
|
||||
Defines the given preprocessor symbol, without allowing. Similar to
|
||||
+define; +define is fairly standard across Verilog tools while -D is an
|
||||
alias for GCC compatibility.
|
||||
|
||||
=item --debug
|
||||
|
||||
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
|
||||
|
||||
@@ -590,9 +593,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
|
||||
=item --debugi-<srcfile> <level>
|
||||
|
||||
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
|
||||
specified level. Higher levels produce more detailed messages (plain
|
||||
C<--debug> is equivalent to C<--debugi 4>).
|
||||
to the specified debug level (1-10) or set the specified Verilator source
|
||||
file to the specified level (e.g. C<--debugi-V3Width 9>). Higher levels
|
||||
produce more detailed messages.
|
||||
|
||||
=item --default-language I<value>
|
||||
|
||||
@@ -613,10 +616,13 @@ used.
|
||||
If no language is specified, either by this flag or +I<lang>ext+ options,
|
||||
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
|
||||
standard across Verilog tools while -D is an alias for GCC compatibility.
|
||||
=item +define+I<var>=I<value>+I<var2>=I<value2>...
|
||||
|
||||
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
|
||||
|
||||
@@ -782,8 +788,10 @@ Disables optimization of the model.
|
||||
|
||||
=item -O3
|
||||
|
||||
Enables slow optimizations. This may reduce simulation runtimes at the
|
||||
cost of compile time. This currently sets --inline-mult -1.
|
||||
Enables slow optimizations for the code Verilator itself generates (as
|
||||
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>
|
||||
|
||||
@@ -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
|
||||
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)
|
||||
|
||||
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*/
|
||||
|
||||
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
|
||||
that the entire module is not traced.
|
||||
module, or cells below this module. Often this is placed just after a
|
||||
primitive's module statement, so that the entire module and cells below it
|
||||
are not traced.
|
||||
|
||||
=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
|
||||
|
||||
@@ -2968,8 +2986,8 @@ simulators.
|
||||
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.
|
||||
Instead of using absolute paths, relative paths (preferably without any
|
||||
directory specified whatever) should be used, and +include used on the
|
||||
command line to specify the top include source directory.
|
||||
directory specified whatever) should be used, and +incdir used on the
|
||||
command line to specify the top include source directories.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
+15
-1
@@ -118,6 +118,18 @@ sub profcfunc {
|
||||
$groups{type}{"Common code under $design"} += $pct;
|
||||
$groups{design}{$design} += $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 {
|
||||
$vfunc = sprintf("C++ %s", $func);
|
||||
$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;
|
||||
foreach (sort (keys %{$groups{$type}})) {
|
||||
$missing -= $groups{$type}{$_};
|
||||
@@ -150,8 +162,10 @@ sub profcfunc {
|
||||
print("Verilog code profile:\n");
|
||||
print(" These are split into three categories:\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(" 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(" % cumulative self \n");
|
||||
|
||||
+4
-2
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#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_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
|
||||
_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
|
||||
# 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.
|
||||
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
|
||||
_MY_CXX_CHECK_OPT(-Wno-sign-compare)
|
||||
_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-variable)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
|
||||
_MY_CXX_CHECK_OPT(-fbracket-depth=4096)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
# Checks for library functions.
|
||||
|
||||
@@ -74,6 +74,9 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
||||
Verilated::gotFinish(true);
|
||||
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
|
||||
Verilated::flushCall();
|
||||
|
||||
VL_PRINTF("Aborting...\n");
|
||||
Verilated::flushCall(); // Second flush in case VL_PRINTF does something needing a flush
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -43,14 +43,14 @@ VK_CPPFLAGS_ALWAYS += \
|
||||
-DVL_PRINTF=printf \
|
||||
-DVM_TRACE=$(VM_TRACE) \
|
||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
VK_CPPFLAGS_WALL += -Wall \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
-Werror
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL)
|
||||
CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
|
||||
|
||||
VPATH += ..
|
||||
VPATH += $(VERILATOR_ROOT)/include
|
||||
@@ -195,6 +195,7 @@ debug-make::
|
||||
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
|
||||
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
|
||||
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
|
||||
@echo CPPFLAGS: $(CPPFLAGS)
|
||||
@echo
|
||||
|
||||
######################################################################
|
||||
|
||||
@@ -261,6 +261,20 @@ void VerilatedVcd::printTime (vluint64_t 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 () {
|
||||
// We add output data to m_writep.
|
||||
// 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
|
||||
}
|
||||
|
||||
// Make sure write buffer is large enough (one character per bit), plus header
|
||||
bufferResize(bits+1024);
|
||||
|
||||
// Save declaration info
|
||||
VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
|
||||
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) {
|
||||
(*((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);
|
||||
m_writep += strlen(m_writep);
|
||||
*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) {
|
||||
(*((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);
|
||||
m_writep += strlen(m_writep);
|
||||
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||
@@ -703,5 +720,5 @@ main() {
|
||||
|
||||
//********************************************************************
|
||||
// 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:
|
||||
|
||||
@@ -77,7 +77,9 @@ private:
|
||||
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
||||
|
||||
char* m_wrBufp; ///< Output buffer
|
||||
char* m_wrFlushp; ///< Output buffer flush trigger location
|
||||
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
|
||||
|
||||
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
|
||||
@@ -87,13 +89,12 @@ private:
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
void bufferResize(vluint64_t minsize);
|
||||
void bufferFlush();
|
||||
void bufferCheck() {
|
||||
inline void bufferCheck() {
|
||||
// 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
|
||||
if (VL_UNLIKELY(m_writep > (m_wrBufp+(bufferSize()-bufferInsertSize())))) {
|
||||
if (VL_UNLIKELY(m_writep > m_wrFlushp)) {
|
||||
bufferFlush();
|
||||
}
|
||||
}
|
||||
@@ -135,17 +136,19 @@ protected:
|
||||
public:
|
||||
// CREATORS
|
||||
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_timeRes = m_timeUnit = 1e-9;
|
||||
m_timeLastDump = 0;
|
||||
m_sigs_oldvalp = NULL;
|
||||
m_evcd = false;
|
||||
m_scopeEscape = '.'; // Backward compatibility
|
||||
m_wroteBytes = 0;
|
||||
m_fd = 0;
|
||||
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();
|
||||
|
||||
|
||||
+11
-11
@@ -97,8 +97,8 @@ public:
|
||||
virtual const char* fullname() { return "<null>"; }
|
||||
virtual const char* defname() { return "<null>"; }
|
||||
virtual const vluint32_t type() { return 0; }
|
||||
virtual const vluint32_t size() { return 0; }
|
||||
virtual const VerilatedRange* rangep() { return 0; }
|
||||
virtual const vluint32_t size() const { return 0; }
|
||||
virtual const VerilatedRange* rangep() const { return NULL; }
|
||||
virtual vpiHandle dovpi_scan() { return 0; }
|
||||
};
|
||||
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
|
||||
class VerilatedVpioRange : public VerilatedVpio {
|
||||
const VerilatedRange* m_range;
|
||||
bool m_iteration;
|
||||
vlsint32_t m_iteration;
|
||||
public:
|
||||
VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
@@ -182,7 +182,7 @@ class VerilatedVpioVar : public VerilatedVpio {
|
||||
protected:
|
||||
void* m_varDatap; // varp()->datap() adjusted for array entries
|
||||
vlsint32_t m_index;
|
||||
const VerilatedRange& get_range() {
|
||||
const VerilatedRange& get_range() const {
|
||||
// Determine number of dimensions and return outermost
|
||||
return (m_varp->dims()>1) ? m_varp->array() : m_varp->range();
|
||||
}
|
||||
@@ -208,8 +208,8 @@ public:
|
||||
if (varp()->vldir() != vpiNoDirection) return vpiPort;
|
||||
return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
|
||||
}
|
||||
virtual const vluint32_t size() { return get_range().elements(); }
|
||||
virtual const VerilatedRange* rangep() { return &get_range(); }
|
||||
virtual const vluint32_t size() const { return get_range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &get_range(); }
|
||||
virtual const char* name() { return m_varp->name(); }
|
||||
virtual const char* fullname() {
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
@@ -237,8 +237,8 @@ public:
|
||||
virtual ~VerilatedVpioMemoryWord() {}
|
||||
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
|
||||
virtual const vluint32_t type() { return vpiMemoryWord; }
|
||||
virtual const vluint32_t size() { return varp()->range().elements(); }
|
||||
virtual const VerilatedRange* rangep() { return &(varp()->range()); }
|
||||
virtual const vluint32_t size() const { return varp()->range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
|
||||
virtual const char* fullname() {
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
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;
|
||||
switch (vop->varp()->vltype()) {
|
||||
// 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_UINT16: snprintf(outStr, outStrSz+1, "%hu", (unsigned int)*((SData*)(vop->varDatap()))); return;
|
||||
case VLVT_UINT32: snprintf(outStr, outStrSz+1, "%u", (unsigned int)*((IData*)(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 short)*((SData*)(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;
|
||||
default:
|
||||
strcpy(outStr, "-1");
|
||||
|
||||
+6
-3
@@ -61,10 +61,13 @@ private:
|
||||
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
|
||||
nodep->displayType(AstDisplayType::DT_WRITE);
|
||||
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
|
||||
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
|
||||
// cppcheck-suppress nullPointer
|
||||
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
||||
nodep->fmtp()->exprsp(timesp);
|
||||
AstNode* timenewp = new AstTime(nodep->fileline());
|
||||
if (AstNode* timesp = nodep->fmtp()->exprsp()) {
|
||||
timesp->unlinkFrBackWithNext();
|
||||
timenewp->addNext(timesp);
|
||||
}
|
||||
nodep->fmtp()->exprsp(timenewp);
|
||||
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
||||
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
}
|
||||
|
||||
+8
-11
@@ -884,24 +884,21 @@ void AstNode::cloneRelinkTree() {
|
||||
//======================================================================
|
||||
// Comparison
|
||||
|
||||
bool AstNode::sameTree(AstNode* node2p) {
|
||||
return sameTreeIter(node2p, true);
|
||||
}
|
||||
|
||||
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
|
||||
// Return true if the two trees are identical
|
||||
if (this==NULL && node2p==NULL) return true;
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->dtypep() != node2p->dtypep()
|
||||
|| !this->same(node2p)) {
|
||||
|| !this->same(node2p)
|
||||
|| (gateOnly && !this->isGateOptimizable())) {
|
||||
return false;
|
||||
}
|
||||
return (this->op1p()->sameTreeIter(node2p->op1p(),false)
|
||||
&& this->op2p()->sameTreeIter(node2p->op2p(),false)
|
||||
&& this->op3p()->sameTreeIter(node2p->op3p(),false)
|
||||
&& this->op4p()->sameTreeIter(node2p->op4p(),false)
|
||||
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false))
|
||||
return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
|
||||
&& this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
|
||||
&& this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
|
||||
&& this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
|
||||
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+55
-28
@@ -236,6 +236,8 @@ public:
|
||||
DIM_SIZE, // V3Width processes
|
||||
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
|
||||
//
|
||||
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
|
||||
//
|
||||
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
//
|
||||
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
@@ -255,6 +257,7 @@ public:
|
||||
"%E-AT",
|
||||
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||
"DT_PUBLIC",
|
||||
"MEMBER_BASE",
|
||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
@@ -932,7 +935,7 @@ class AstNode {
|
||||
AstNode* cloneTreeIterList();
|
||||
void checkTreeIter(AstNode* backp);
|
||||
void checkTreeIterList(AstNode* backp);
|
||||
bool sameTreeIter(AstNode* node2p, bool ignNext);
|
||||
bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
|
||||
void deleteTreeIter();
|
||||
void deleteNode();
|
||||
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
||||
@@ -1158,6 +1161,7 @@ public:
|
||||
// METHODS - Iterate on a tree
|
||||
AstNode* cloneTree(bool cloneNextLink);
|
||||
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 checkTree(); // User Interface version
|
||||
void checkIter() const;
|
||||
@@ -1216,8 +1220,9 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
||||
virtual ~Ast ##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
|
||||
public:
|
||||
AstNodeMath(FileLine* fl)
|
||||
: AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeMath)
|
||||
@@ -1232,8 +1237,9 @@ struct AstNodeMath : public AstNode {
|
||||
bool isOpaque() { return castCvtPackString()!=NULL; }
|
||||
};
|
||||
|
||||
struct AstNodeTermop : public AstNodeMath {
|
||||
class AstNodeTermop : public AstNodeMath {
|
||||
// Terminal operator -- a operator with no "inputs"
|
||||
public:
|
||||
AstNodeTermop(FileLine* fl)
|
||||
: AstNodeMath(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||
@@ -1243,8 +1249,9 @@ struct AstNodeTermop : public AstNodeMath {
|
||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||
};
|
||||
|
||||
struct AstNodeUniop : public AstNodeMath {
|
||||
class AstNodeUniop : public AstNodeMath {
|
||||
// Unary math
|
||||
public:
|
||||
AstNodeUniop(FileLine* fl, AstNode* lhsp)
|
||||
: AstNodeMath(fl) {
|
||||
dtypeFrom(lhsp);
|
||||
@@ -1263,8 +1270,9 @@ struct AstNodeUniop : public AstNodeMath {
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
struct AstNodeBiop : public AstNodeMath {
|
||||
class AstNodeBiop : public AstNodeMath {
|
||||
// Binary math
|
||||
public:
|
||||
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeMath(fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); }
|
||||
@@ -1286,8 +1294,9 @@ struct AstNodeBiop : public AstNodeMath {
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
struct AstNodeTriop : public AstNodeMath {
|
||||
class AstNodeTriop : public AstNodeMath {
|
||||
// Trinary math
|
||||
public:
|
||||
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNodeMath(fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
||||
@@ -1311,20 +1320,23 @@ struct AstNodeTriop : public AstNodeMath {
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
struct AstNodeBiCom : public AstNodeBiop {
|
||||
class AstNodeBiCom : public AstNodeBiop {
|
||||
// Binary math with commutative properties
|
||||
public:
|
||||
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeBiop(fl, lhs, rhs) {}
|
||||
ASTNODE_BASE_FUNCS(NodeBiCom)
|
||||
};
|
||||
|
||||
struct AstNodeBiComAsv : public AstNodeBiCom {
|
||||
class AstNodeBiComAsv : public AstNodeBiCom {
|
||||
// Binary math with commutative & associative properties
|
||||
public:
|
||||
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeBiCom(fl, lhs, rhs) {}
|
||||
ASTNODE_BASE_FUNCS(NodeBiComAsv)
|
||||
};
|
||||
struct AstNodeCond : public AstNodeTriop {
|
||||
class AstNodeCond : public AstNodeTriop {
|
||||
public:
|
||||
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeTriop(fl, condp, expr1p, expr2p) {
|
||||
if (expr1p) dtypeFrom(expr1p);
|
||||
@@ -1346,8 +1358,9 @@ struct AstNodeCond : public AstNodeTriop {
|
||||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
};
|
||||
|
||||
struct AstNodePreSel : public AstNode {
|
||||
class AstNodePreSel : public AstNode {
|
||||
// Something that becomes an AstSel
|
||||
public:
|
||||
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNode(fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
||||
@@ -1366,8 +1379,9 @@ struct AstNodePreSel : public AstNode {
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
struct AstNodeStmt : public AstNode {
|
||||
class AstNodeStmt : public AstNode {
|
||||
// Statement -- anything that's directly under a function
|
||||
public:
|
||||
AstNodeStmt(FileLine* fl)
|
||||
: AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeStmt)
|
||||
@@ -1376,7 +1390,8 @@ struct AstNodeStmt : public AstNode {
|
||||
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)
|
||||
: AstNodeStmt(fl) {
|
||||
setOp1p(rhsp); setOp2p(lhsp);
|
||||
@@ -1397,7 +1412,8 @@ struct AstNodeAssign : public AstNodeStmt {
|
||||
virtual string verilogKwd() const { return "="; }
|
||||
};
|
||||
|
||||
struct AstNodeFor : public AstNodeStmt {
|
||||
class AstNodeFor : public AstNodeStmt {
|
||||
public:
|
||||
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
|
||||
AstNode* incsp, AstNode* bodysp)
|
||||
: AstNodeStmt(fileline) {
|
||||
@@ -1414,7 +1430,7 @@ struct AstNodeFor : public AstNodeStmt {
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstNodeIf : public AstNodeStmt {
|
||||
class AstNodeIf : public AstNodeStmt {
|
||||
private:
|
||||
AstBranchPred m_branchPred; // Branch prediction as taken/untaken?
|
||||
public:
|
||||
@@ -1438,7 +1454,8 @@ public:
|
||||
AstBranchPred branchPred() const { return m_branchPred; }
|
||||
};
|
||||
|
||||
struct AstNodeCase : public AstNodeStmt {
|
||||
class AstNodeCase : public AstNodeStmt {
|
||||
public:
|
||||
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
|
||||
: AstNodeStmt(fl) {
|
||||
setOp1p(exprp); addNOp2p(casesp);
|
||||
@@ -1452,8 +1469,9 @@ struct AstNodeCase : public AstNodeStmt {
|
||||
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
||||
};
|
||||
|
||||
struct AstNodeSenItem : public AstNode {
|
||||
class AstNodeSenItem : public AstNode {
|
||||
// An AstSenItem or AstSenGate
|
||||
public:
|
||||
AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeSenItem)
|
||||
virtual bool isClocked() const = 0;
|
||||
@@ -1511,7 +1529,7 @@ public:
|
||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||
};
|
||||
|
||||
struct AstNodeText : public AstNode {
|
||||
class AstNodeText : public AstNode {
|
||||
private:
|
||||
string m_text;
|
||||
public:
|
||||
@@ -1528,11 +1546,11 @@ public:
|
||||
const string& text() const { return m_text; }
|
||||
};
|
||||
|
||||
struct AstNodeDType : public AstNode {
|
||||
private:
|
||||
class AstNodeDType : public AstNode {
|
||||
// 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.
|
||||
// Note the below members are included in AstTypeTable::Key lookups
|
||||
private:
|
||||
int m_width; // (also in AstTypeTable::Key) Bit width of operation
|
||||
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
|
||||
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
|
||||
@@ -1550,8 +1568,9 @@ public:
|
||||
virtual void dumpSmall(ostream& str);
|
||||
virtual bool hasDType() const { return true; }
|
||||
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* 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 widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
@@ -1581,7 +1600,7 @@ public:
|
||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||
};
|
||||
|
||||
struct AstNodeClassDType : public AstNodeDType {
|
||||
class AstNodeClassDType : public AstNodeDType {
|
||||
private:
|
||||
// TYPES
|
||||
typedef map<string,AstMemberDType*> MemberNameMap;
|
||||
@@ -1602,6 +1621,7 @@ public:
|
||||
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
|
||||
virtual AstNodeDType* skipRefp() 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 widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
// op1 = members
|
||||
@@ -1620,7 +1640,7 @@ public:
|
||||
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]"
|
||||
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||
// 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 AstNodeDType* skipRefp() 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 widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
|
||||
int msb() const;
|
||||
@@ -1666,8 +1687,9 @@ public:
|
||||
VNumRange declRange() const;
|
||||
};
|
||||
|
||||
struct AstNodeSel : public AstNodeBiop {
|
||||
class AstNodeSel : public AstNodeBiop {
|
||||
// Single bit range extraction, perhaps with non-constant selection or array selection
|
||||
public:
|
||||
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
||||
:AstNodeBiop(fl, fromp, bitp) {}
|
||||
ASTNODE_BASE_FUNCS(NodeSel)
|
||||
@@ -1679,8 +1701,9 @@ struct AstNodeSel : public AstNodeBiop {
|
||||
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()
|
||||
public:
|
||||
AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp->dtypep()) {
|
||||
dtypeSetLogicSized(lhsp->dtypep()->width(), lhsp->dtypep()->width(), AstNumeric::UNSIGNED);
|
||||
@@ -1692,7 +1715,7 @@ struct AstNodeStream : public AstNodeBiop {
|
||||
//######################################################################
|
||||
// Tasks/functions common handling
|
||||
|
||||
struct AstNodeFTask : public AstNode {
|
||||
class AstNodeFTask : public AstNode {
|
||||
private:
|
||||
string m_name; // Name of task
|
||||
string m_cname; // Name of task if DPI import
|
||||
@@ -1750,7 +1773,7 @@ public:
|
||||
bool pure() const { return m_pure; }
|
||||
};
|
||||
|
||||
struct AstNodeFTaskRef : public AstNode {
|
||||
class AstNodeFTaskRef : public AstNode {
|
||||
// A reference to a task (or function)
|
||||
private:
|
||||
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
||||
@@ -1796,7 +1819,7 @@ public:
|
||||
void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
|
||||
};
|
||||
|
||||
struct AstNodeModule : public AstNode {
|
||||
class AstNodeModule : public AstNode {
|
||||
// A module, package, program or interface declaration;
|
||||
// something that can live directly under the TOP,
|
||||
// excluding $unit package stuff
|
||||
@@ -1810,12 +1833,13 @@ private:
|
||||
bool m_internal:1; // Internally created
|
||||
int m_level; // 1=top module, 2=cell off top module, ...
|
||||
int m_varNum; // Incrementing variable number
|
||||
int m_typeNum; // Incrementing implicit type number
|
||||
public:
|
||||
AstNodeModule(FileLine* fl, const string& name)
|
||||
: AstNode (fl)
|
||||
,m_name(name), m_origName(name)
|
||||
,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)
|
||||
virtual void dump(ostream& str);
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
@@ -1835,6 +1859,7 @@ public:
|
||||
int level() const { return m_level; }
|
||||
bool isTop() const { return level()==1; }
|
||||
int varNumGetInc() { return ++m_varNum; }
|
||||
int typeNumGetInc() { return ++m_typeNum; }
|
||||
void modPublic(bool flag) { m_modPublic = flag; }
|
||||
bool modPublic() const { return m_modPublic; }
|
||||
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::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
|
||||
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()); }
|
||||
|
||||
|
||||
@@ -515,6 +515,24 @@ string AstScopeName::scopeSymName() const {
|
||||
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() {
|
||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||
@@ -801,6 +819,10 @@ void AstPin::dump(ostream& str) {
|
||||
else { str<<" ->UNLINKED"; }
|
||||
if (svImplicit()) str<<" [.SV]";
|
||||
}
|
||||
void AstTypedef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (attrPublic()) str<<" [PUBLIC]";
|
||||
}
|
||||
void AstRange::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (littleEndian()) str<<" [LITTLE]";
|
||||
|
||||
+439
-248
File diff suppressed because it is too large
Load Diff
@@ -238,6 +238,10 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
insureCleanAndNext (nodep->valuep());
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
// Control flow operators
|
||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||
|
||||
+142
-6
@@ -173,6 +173,16 @@ private:
|
||||
if (rnodep->width() != bnodep->width()) return false;
|
||||
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) {
|
||||
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
|
||||
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
|
||||
@@ -418,12 +428,12 @@ private:
|
||||
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
|
||||
// For now we just detect constants & simple vars, though it could be more generic
|
||||
if (node1p->castConst() && node2p->castConst()) {
|
||||
return node1p->sameTree(node2p);
|
||||
return node1p->sameGateTree(node2p);
|
||||
}
|
||||
else if (node1p->castVarRef() && node2p->castVarRef()) {
|
||||
// Avoid comparing widthMin's, which results in lost optimization attempts
|
||||
// If cleanup sameTree to be smarter, this can be restored.
|
||||
//return node1p->sameTree(node2p);
|
||||
// If cleanup sameGateTree to be smarter, this can be restored.
|
||||
//return node1p->sameGateTree(node2p);
|
||||
return node1p->same(node2p);
|
||||
} else {
|
||||
return false;
|
||||
@@ -439,7 +449,7 @@ private:
|
||||
AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
|
||||
if (!ifvarp || !elsevarp) return false;
|
||||
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;
|
||||
}
|
||||
bool operandIfIf(AstNodeIf* nodep) {
|
||||
@@ -450,6 +460,89 @@ private:
|
||||
if (afterComment(lowerIfp->elsesp())) return false;
|
||||
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.
|
||||
@@ -668,6 +761,45 @@ private:
|
||||
rrp->deleteTree();
|
||||
//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) {
|
||||
// -> EXTEND(nodep)
|
||||
// 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;
|
||||
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) 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* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
|
||||
// We need to make sure there's no self-references involved in either
|
||||
@@ -1539,7 +1671,7 @@ private:
|
||||
AstSenItem* litemp = senp->castSenItem();
|
||||
AstSenItem* ritemp = cmpp->castSenItem();
|
||||
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())) {
|
||||
// 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
|
||||
@@ -1910,6 +2042,7 @@ private:
|
||||
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 ("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
|
||||
// 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)");
|
||||
@@ -2064,6 +2197,9 @@ private:
|
||||
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
|
||||
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
|
||||
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
|
||||
TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
|
||||
TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
|
||||
|
||||
@@ -81,6 +81,7 @@ private:
|
||||
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
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
|
||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||
@@ -112,6 +113,12 @@ private:
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
@@ -158,6 +165,13 @@ private:
|
||||
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*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
@@ -168,6 +182,7 @@ private:
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||
if (mightElim(nodep)) {
|
||||
m_varEtcsp.push_back(nodep);
|
||||
}
|
||||
@@ -253,6 +268,7 @@ private:
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
||||
m_modp = NULL;
|
||||
m_elimUserVars = elimUserVars;
|
||||
m_elimDTypes = elimDTypes;
|
||||
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
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
bool paren = true; bool decind = false;
|
||||
@@ -226,7 +258,9 @@ public:
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// For use under AstCCalls for dpiImports. ScopeNames under displays are handled in AstDisplay
|
||||
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*) {
|
||||
@@ -661,6 +695,7 @@ public:
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
// NOPs
|
||||
virtual void visit(AstTypedef*, AstNUser*) {}
|
||||
virtual void visit(AstPragma*, AstNUser*) {}
|
||||
virtual void visit(AstCell*, 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(AstTraceInc*, 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
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
|
||||
@@ -783,6 +817,7 @@ class EmitCImp : EmitCStmts {
|
||||
|
||||
//---------------------------------------
|
||||
// VISITORS
|
||||
using EmitCStmts::visit; // Suppress hidden overloaded virtual function warnng
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
// TRACE_* and DPI handled elsewhere
|
||||
if (nodep->funcType().isTrace()) return;
|
||||
@@ -1842,6 +1877,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
}
|
||||
}
|
||||
|
||||
emitTypedefs(modp->stmtsp());
|
||||
|
||||
puts("\n// PORTS\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");
|
||||
@@ -2303,6 +2340,7 @@ class EmitCTrace : EmitCStmts {
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
using EmitCStmts::visit; // Suppress hidden overloaded virtual function warnng
|
||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||
// Top module only
|
||||
nodep->topModulep()->accept(*this);
|
||||
|
||||
+1
-2
@@ -685,7 +685,6 @@ public:
|
||||
class EmitVPrefixedVisitor : public EmitVBaseVisitor {
|
||||
// MEMBERS
|
||||
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
|
||||
virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); }
|
||||
virtual void puts(const string& str) { m_formatter.puts(str); }
|
||||
@@ -706,7 +705,7 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor {
|
||||
public:
|
||||
EmitVPrefixedVisitor(AstNode* nodep, ostream& os, const string& prefix, int flWidth,
|
||||
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(); }
|
||||
nodep->accept(*this);
|
||||
}
|
||||
|
||||
+5
-1
@@ -583,11 +583,15 @@ private:
|
||||
newSelBitBit(lhsp->lsbp()),
|
||||
VL_WORDSIZE)),
|
||||
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(),
|
||||
oldvalp,
|
||||
new AstShiftL (lhsp->fileline(),
|
||||
rhsp,
|
||||
lhsp->lsbp()->cloneTree(true),
|
||||
shiftp,
|
||||
VL_WORDSIZE));
|
||||
newp = new AstAssign (nodep->fileline(),
|
||||
new AstWordSel (nodep->fileline(),
|
||||
|
||||
+1
-1
@@ -567,7 +567,7 @@ const char* V3OutFormatter::indentStr(int num) {
|
||||
static char str[MAXSPACE+20];
|
||||
char* cp = str;
|
||||
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) {
|
||||
*cp++ = '\t';
|
||||
num -= 8;
|
||||
|
||||
+130
-1
@@ -303,6 +303,7 @@ private:
|
||||
V3Double0 m_statSigs; // Statistic tracking
|
||||
V3Double0 m_statRefs; // Statistic tracking
|
||||
V3Double0 m_statDedupLogic; // Statistic tracking
|
||||
V3Double0 m_statAssignMerged; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, const char* consumeReason) {
|
||||
@@ -352,6 +353,7 @@ private:
|
||||
void consumedMove();
|
||||
void replaceAssigns();
|
||||
void dedupe();
|
||||
void mergeAssigns();
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||
@@ -368,6 +370,7 @@ private:
|
||||
optimizeSignals(true);
|
||||
// Remove redundant logic
|
||||
if (v3Global.opt.oDedupe()) dedupe();
|
||||
if (v3Global.opt.oAssemble()) mergeAssigns();
|
||||
// Warn
|
||||
warnSignals();
|
||||
consumedMark();
|
||||
@@ -506,6 +509,7 @@ public:
|
||||
V3Stats::addStat("Optimizations, Gate sigs deleted", m_statSigs);
|
||||
V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs);
|
||||
V3Stats::addStat("Optimizations, Gate sigs deduped", m_statDedupLogic);
|
||||
V3Stats::addStat("Optimizations, Gate assign merged", m_statAssignMerged);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1009,7 +1013,6 @@ private:
|
||||
lvertexp->user(true);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1063,6 +1066,132 @@ void GateVisitor::dedupe() {
|
||||
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)
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ public:
|
||||
DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_start(start), m_accepting(accepting) {}
|
||||
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
|
||||
virtual DfaVertex* clone(DfaGraph* graphp) {
|
||||
return new DfaVertex(graphp, start(), accepting()); }
|
||||
virtual ~DfaVertex() {}
|
||||
|
||||
@@ -314,6 +314,7 @@ private:
|
||||
// Also clear I/O bits, as it is now local.
|
||||
string name = m_cellp->name() + "__DOT__" + nodep->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->valuep()->dumpTree(cout,"varchangei:"); }
|
||||
// Iterate won't hit AstIfaceRefDType directly as it is no longer underneath the module
|
||||
@@ -387,6 +388,10 @@ private:
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
nodep->scopeAttrp(new AstText(nodep->fileline(), (string)"__DOT__"+m_cellp->name()));
|
||||
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);
|
||||
}
|
||||
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_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Current task
|
||||
AstNodeDType* m_dtypep; // Current data type
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -104,6 +105,15 @@ private:
|
||||
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*) {
|
||||
// Expand ranges
|
||||
cleanFileline(nodep);
|
||||
@@ -176,7 +186,13 @@ private:
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
cleanFileline(nodep);
|
||||
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");
|
||||
m_varp->attrScClocked(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
@@ -265,7 +281,7 @@ private:
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
return;
|
||||
} 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));
|
||||
backp->addNextHere(defp);
|
||||
}
|
||||
@@ -327,6 +343,7 @@ public:
|
||||
m_varp = NULL;
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_dtypep = NULL;
|
||||
m_inAlways = false;
|
||||
m_inGenerate = false;
|
||||
m_needStart = false;
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ private:
|
||||
bool bitIsXZ(int bit) const {
|
||||
if (bit<0) return false;
|
||||
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 {
|
||||
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) {
|
||||
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
|
||||
string def = defline;
|
||||
string value;
|
||||
string::size_type pos;
|
||||
if ( ((pos=defline.find("+")) != string::npos)
|
||||
|| ((pos=defline.find("=")) != string::npos)) {
|
||||
value = def.substr(pos+1);
|
||||
def.erase(pos);
|
||||
// Optional + says to allow multiple defines on the line
|
||||
// + is not quotable, as other simulators do not allow that
|
||||
string left = defline;
|
||||
while (left != "") {
|
||||
string def = left;
|
||||
string::size_type 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) {
|
||||
@@ -668,7 +678,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
if (argv[i][0]=='+') {
|
||||
char *sw = argv[i];
|
||||
if ( !strncmp (sw, "+define+", 8)) {
|
||||
addDefine (string (sw+strlen("+define+")));
|
||||
addDefine (string (sw+strlen("+define+")), true);
|
||||
}
|
||||
else if ( !strncmp (sw, "+incdir+", 8)) {
|
||||
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 'c': m_oConst = flag; break;
|
||||
case 'd': m_oDedupe = flag; break;
|
||||
case 'm': m_oAssemble = flag; break;
|
||||
case 'e': m_oCase = flag; break;
|
||||
case 'f': m_oFlopGater = 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]);
|
||||
}
|
||||
else if ( !strncmp (sw, "-D", 2)) {
|
||||
addDefine (string (sw+strlen("-D")));
|
||||
addDefine (string (sw+strlen("-D")), false);
|
||||
}
|
||||
else if ( !strcmp (sw, "-debug") ) {
|
||||
setDebugMode(3);
|
||||
@@ -1319,6 +1330,7 @@ void V3Options::optimize(int level) {
|
||||
m_oSubstConst = flag;
|
||||
m_oTable = flag;
|
||||
m_oDedupe = flag;
|
||||
m_oAssemble = flag;
|
||||
// And set specific optimization levels
|
||||
if (level >= 3) {
|
||||
m_inlineMult = -1; // Maximum inlining
|
||||
|
||||
+3
-1
@@ -139,6 +139,7 @@ class V3Options {
|
||||
bool m_oCombine; // main switch: -Ob: common icode packing
|
||||
bool m_oConst; // main switch: -Oc: constant folding
|
||||
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_oFlopGater; // main switch: -Of: flop gater detection
|
||||
bool m_oGate; // main switch: -Og: gate wire elimination
|
||||
@@ -155,7 +156,7 @@ class V3Options {
|
||||
private:
|
||||
// METHODS
|
||||
void addArg(const string& flag);
|
||||
void addDefine(const string& defline);
|
||||
void addDefine(const string& defline, bool allowPlus);
|
||||
void addFuture(const string& flag);
|
||||
void addIncDirUser(const string& incdir); // User requested
|
||||
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
||||
@@ -282,6 +283,7 @@ class V3Options {
|
||||
bool oCombine() const { return m_oCombine; }
|
||||
bool oConst() const { return m_oConst; }
|
||||
bool oDedupe() const { return m_oDedupe; }
|
||||
bool oAssemble() const { return m_oAssemble; }
|
||||
bool oExpand() const { return m_oExpand; }
|
||||
bool oFlopGater() const { return m_oFlopGater; }
|
||||
bool oGate() const { return m_oGate; }
|
||||
|
||||
+2
-1
@@ -210,7 +210,8 @@ private:
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
if (nodep->dead()) {
|
||||
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
|
||||
m_todoModps.insert(make_pair(nodep->level(),nodep));
|
||||
visitModules();
|
||||
|
||||
@@ -169,6 +169,7 @@ class V3PreLex {
|
||||
int m_pslParenLevel;// PSL Parenthesis (){} counting, so we can find final ;
|
||||
bool m_pslMoreNeeded;// Next // comment is really psl
|
||||
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
|
||||
bool m_defQuote; // Definition value inside quote
|
||||
string m_defValue; // Definition value being built.
|
||||
int m_enterExit; // For VL_LINE, the enter/exit level
|
||||
|
||||
@@ -181,6 +182,7 @@ class V3PreLex {
|
||||
m_pedantic = false;
|
||||
m_formalLevel = 0;
|
||||
m_parenLevel = 0;
|
||||
m_defQuote = false;
|
||||
m_defCmtSlash = false;
|
||||
m_tokFilelinep = filelinep;
|
||||
m_enterExit = 0;
|
||||
|
||||
+4
-3
@@ -125,7 +125,7 @@ psl [p]sl
|
||||
<STRMODE>{backslash}{crnl} { linenoInc(); yymore(); }
|
||||
<STRMODE>{backslash}. { yymore(); }
|
||||
<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); }
|
||||
|
||||
/* 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>{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>{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>{tickquote} { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
|
||||
<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>{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>[^\/\*\n\r\\]+ |
|
||||
<DEFVAL>{quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); }
|
||||
<DEFVAL>[^\/\*\n\r\\\"]+ |
|
||||
<DEFVAL>[\\][^\n\r] |
|
||||
<DEFVAL>. { appendDefValue(yytext,yyleng); }
|
||||
|
||||
|
||||
+67
-2
@@ -40,6 +40,60 @@
|
||||
#include "V3Premit.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
|
||||
|
||||
@@ -49,6 +103,7 @@ private:
|
||||
// AstNodeMath::user() -> bool. True if iterated already
|
||||
// AstShiftL::user2() -> bool. True if converted to conditional
|
||||
// AstShiftR::user2() -> bool. True if converted to conditional
|
||||
// *::user4() -> See PremitAssignVisitor
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
|
||||
@@ -115,11 +170,13 @@ private:
|
||||
m_inWhilep->addPrecondsp(newp);
|
||||
} else if (m_inTracep) {
|
||||
m_inTracep->addPrecondsp(newp);
|
||||
} else {
|
||||
} else if (m_stmtp) {
|
||||
AstNRelinker linker;
|
||||
m_stmtp->unlinkFrBack(&linker);
|
||||
newp->addNext(m_stmtp);
|
||||
linker.relink(newp);
|
||||
} else {
|
||||
newp->v3fatalSrc("No statement insertion point.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +231,14 @@ private:
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
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);
|
||||
m_assignLhs = true;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
@@ -287,7 +352,7 @@ private:
|
||||
while (searchp && searchp->castComment()) searchp = searchp->nextp();
|
||||
if (searchp
|
||||
&& 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
|
||||
} else {
|
||||
UINFO(4,"Autoflush "<<nodep<<endl);
|
||||
|
||||
+7
-2
@@ -241,6 +241,7 @@ private:
|
||||
if (!nodep->user1p()) {
|
||||
AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
|
||||
UINFO(6," New scope "<<varscp<<endl);
|
||||
if (m_aboveCellp && !m_aboveCellp->isTrace()) varscp->trace(false);
|
||||
nodep->user1p(varscp);
|
||||
if (!m_scopep) nodep->v3fatalSrc("No scope for var");
|
||||
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.
|
||||
// So push to a list and post-correct
|
||||
m_varRefScopes.insert(make_pair(nodep, m_scopep));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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()
|
||||
string prefix = (string)("__DOT__")+m_scopep->name();
|
||||
@@ -270,6 +271,10 @@ private:
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
|
||||
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);
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
|
||||
@@ -233,7 +233,6 @@ private:
|
||||
SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering
|
||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||
bool m_inDly; // Inside ASSIGNDLY
|
||||
uint32_t m_stepNum; // Step number we need to ignore a edge in
|
||||
V3Double0 m_statSplits; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
|
||||
+1
-1
@@ -353,7 +353,7 @@ private:
|
||||
== var2p->dtypep()->arrayUnpackedElements())) {
|
||||
AstNode* init1p = var1p->valuep()->castInitArray();
|
||||
AstNode* init2p = var2p->valuep()->castInitArray();
|
||||
if (init1p->sameTree(init2p)) {
|
||||
if (init1p->sameGateTree(init2p)) {
|
||||
UINFO(8," Duplicate table var "<<vsc2p<<" == "<<vsc1p<<endl);
|
||||
vsc1p->unlinkFrBack()->deleteTree();
|
||||
return vsc2p;
|
||||
|
||||
+9
-6
@@ -43,7 +43,6 @@ private:
|
||||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstScope* m_scopetopp; // Current top scope
|
||||
AstCFunc* m_initFuncp; // Trace function being built
|
||||
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
|
||||
@@ -65,13 +64,17 @@ private:
|
||||
return level;
|
||||
}
|
||||
|
||||
const char* varIgnoreTrace(AstVar* nodep) {
|
||||
const char* vscIgnoreTrace(AstVarScope* nodep) {
|
||||
// Return true if this shouldn't be traced
|
||||
// See also similar rule in V3Coverage::varIgnoreToggle
|
||||
string prettyName = nodep->prettyName();
|
||||
if (!nodep->isTrace()) {
|
||||
AstVar* varp = nodep->varp();
|
||||
string prettyName = varp->prettyName();
|
||||
if (!varp->isTrace()) {
|
||||
return "Verilator trace_off";
|
||||
}
|
||||
else if (!nodep->isTrace()) {
|
||||
return "Verilator cell trace_off";
|
||||
}
|
||||
else if (!v3Global.opt.traceUnderscore()) {
|
||||
if (prettyName.size()>=1 && prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
@@ -164,8 +167,8 @@ private:
|
||||
|
||||
m_traVscp = nodep;
|
||||
m_traValuep = NULL;
|
||||
if (varIgnoreTrace(varp)) {
|
||||
addIgnore(varIgnoreTrace(varp));
|
||||
if (vscIgnoreTrace(nodep)) {
|
||||
addIgnore(vscIgnoreTrace(nodep));
|
||||
} else {
|
||||
++m_statSigs;
|
||||
if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true);
|
||||
|
||||
+5
-5
@@ -337,14 +337,14 @@ private:
|
||||
// Find range of dtype we are selecting from
|
||||
// Similar code in V3Const::warnSelect
|
||||
int maxmsb = nodep->fromp()->dtypep()->width()-1;
|
||||
int maxlsb = maxmsb - nodep->width() + 1;
|
||||
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(),
|
||||
new AstConst(nodep->fileline(), maxlsbnum),
|
||||
new AstConst(nodep->fileline(), maxmsbnum),
|
||||
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.
|
||||
condp = V3Const::constifyEdit(condp);
|
||||
if (condp->isOne()) {
|
||||
@@ -352,7 +352,7 @@ private:
|
||||
condp->deleteTree();
|
||||
}
|
||||
else if (!lvalue) {
|
||||
// SEL(...) -> COND(LTE(bit<=maxlsb), ARRAYSEL(...), {width{1'bx}})
|
||||
// SEL(...) -> COND(LTE(bit<=maxmsb), ARRAYSEL(...), {width{1'bx}})
|
||||
AstNRelinker replaceHandle;
|
||||
nodep->unlinkFrBack(&replaceHandle);
|
||||
V3Number xnum (nodep->fileline(), nodep->width());
|
||||
|
||||
+28
-12
@@ -164,15 +164,27 @@ private:
|
||||
bool gt = condp->castGt() || condp->castGtS();
|
||||
bool gte = condp->castGte() || condp->castGteS();
|
||||
if (!lt && !lte && !gt && !gte)
|
||||
return cantUnroll(nodep, "condition not <= or <");
|
||||
AstNodeBiop* condBip = condp->castNodeBiop();
|
||||
if (!condBip->rhsp()->castVarRef())
|
||||
return cantUnroll(nodep, "condition not <=, <, >= or >");
|
||||
AstNodeBiop* cmpInstrp = condp->castNodeBiop();
|
||||
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");
|
||||
if (condBip->rhsp()->castVarRef()->varp() != m_forVarp
|
||||
|| condBip->rhsp()->castVarRef()->varScopep() != m_forVscp)
|
||||
} else {
|
||||
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");
|
||||
UINFO(8, " Stop expr ok: "<<constStopp<<endl);
|
||||
//
|
||||
@@ -217,9 +229,9 @@ private:
|
||||
if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop");
|
||||
//
|
||||
// Finally, we can do it
|
||||
forUnroller(nodep, initp, precondsp, condp, incp, bodysp,
|
||||
forUnroller(nodep, initp, precondsp, incp, bodysp,
|
||||
constInitp->num(),
|
||||
condBip, constStopp->num(),
|
||||
cmpInstrp, constStopp->num(), cmpVarLhs,
|
||||
incInstrp, constIncp->num()); nodep = NULL;
|
||||
// Cleanup
|
||||
return true;
|
||||
@@ -227,10 +239,10 @@ private:
|
||||
|
||||
void forUnroller(AstNode* nodep,
|
||||
AstNode* initp,
|
||||
AstNode* precondsp, AstNode* condp,
|
||||
AstNode* precondsp,
|
||||
AstNode* incp, AstNode* bodysp,
|
||||
const V3Number& numInit,
|
||||
AstNodeBiop* cmpInstrp, const V3Number& numStop,
|
||||
AstNodeBiop* cmpInstrp, const V3Number& numStop, bool cmpVarLhs,
|
||||
AstNodeBiop* incInstrp, const V3Number& numInc) {
|
||||
UINFO(4, " Unroll for var="<<numInit<<"; var<"<<numStop<<"; var+="<<numInc<<endl);
|
||||
UINFO(6, " cmpI "<<cmpInstrp<<endl);
|
||||
@@ -270,7 +282,11 @@ private:
|
||||
UINFO(8," Looping "<<loopValue<<endl);
|
||||
// if loopValue<valStop
|
||||
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()) {
|
||||
break; // Done with the loop
|
||||
} 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
|
||||
// RHS is self-determined (IEEE)
|
||||
// Real if either side is real (as with AstAdd)
|
||||
iterate_shift_prelim(nodep, vup); // Iterate rhsp() as self-determined
|
||||
|
||||
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()) {
|
||||
spliceCvtD(nodep->lhsp());
|
||||
spliceCvtD(nodep->rhsp());
|
||||
replaceWithDVersion(nodep); nodep=NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
checkCvtUS(nodep->lhsp());
|
||||
iterateCheckSizedSelf(nodep,"RHS",nodep->rhsp(),SELF,BOTH);
|
||||
nodep->dtypeFrom(nodep->lhsp());
|
||||
}
|
||||
|
||||
if (vup->c()->final()) {
|
||||
AstNodeDType* expDTypep = vup->c()->dtypeOverridep(nodep->dtypep());
|
||||
nodep->dtypeFrom(expDTypep);
|
||||
@@ -902,7 +908,7 @@ private:
|
||||
} else if (!basicp->isSigned() && newp->isSigned()) {
|
||||
newp = new AstUnsigned(nodep->fileline(), newp);
|
||||
} else {
|
||||
newp = newp; // Can just remove cast
|
||||
//newp = newp; // Can just remove cast
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
@@ -925,7 +931,7 @@ private:
|
||||
: nodep->findBitDType(width, width, underDtp->numeric()));
|
||||
nodep->dtypep(newDtp);
|
||||
// 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()) {
|
||||
// CastSize not needed once sizes determined
|
||||
@@ -2297,7 +2303,7 @@ private:
|
||||
if (newp) {} // Ununused
|
||||
}
|
||||
void iterate_shift_prelim(AstNodeBiop* nodep, AstNUser* vup) {
|
||||
// Shifts, Pow
|
||||
// Shifts
|
||||
// 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.
|
||||
if (vup->c()->prelim()) {
|
||||
@@ -2885,6 +2891,7 @@ private:
|
||||
switch (nodep->type()) {
|
||||
case AstType::atADD: newp = new AstAddD (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::atNEQ: case AstType::atNEQCASE: newp = new AstNeqD (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
|
||||
string m_instModule; // Name of module referenced for instantiations
|
||||
AstPin* m_instParamp; // Parameters for instantiations
|
||||
AstNodeModule* m_modp; // Module
|
||||
int m_modTypeImpNum; // Implicit type number, incremented each module
|
||||
bool m_tracingParse; // Tracing disable for parser
|
||||
|
||||
static int s_modTypeImpNum; // Implicit type number, incremented each module
|
||||
|
||||
// CONSTRUCTORS
|
||||
V3ParseGrammar() {
|
||||
@@ -76,10 +77,9 @@ public:
|
||||
m_pinNum = -1;
|
||||
m_instModule = "";
|
||||
m_instParamp = NULL;
|
||||
m_modp = NULL;
|
||||
m_modTypeImpNum = 0;
|
||||
m_varAttrp = NULL;
|
||||
m_caseAttrp = NULL;
|
||||
m_tracingParse = true;
|
||||
}
|
||||
static V3ParseGrammar* singletonp() {
|
||||
static V3ParseGrammar singleton;
|
||||
@@ -88,6 +88,9 @@ public:
|
||||
|
||||
// METHODS
|
||||
void argWrapList(AstNodeFTaskRef* nodep);
|
||||
bool allTracingOn(FileLine* fl) {
|
||||
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
|
||||
}
|
||||
AstNodeDType* createArray(AstNodeDType* basep, AstRange* rangep, bool isPacked);
|
||||
AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp);
|
||||
AstNode* createSupplyExpr(FileLine* fileline, string name, int value);
|
||||
@@ -121,7 +124,6 @@ public:
|
||||
AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->nodep()->castPackage();
|
||||
if (!pkgp) {
|
||||
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
|
||||
}
|
||||
return pkgp;
|
||||
@@ -167,6 +169,8 @@ public:
|
||||
const AstBasicDTypeKwd LOGIC = AstBasicDTypeKwd::LOGIC; // Shorthand "LOGIC"
|
||||
const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
|
||||
|
||||
int V3ParseGrammar::s_modTypeImpNum = 0;
|
||||
|
||||
//======================================================================
|
||||
// Macro functions
|
||||
|
||||
@@ -686,7 +690,7 @@ timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
|
||||
|
||||
package_declaration: // ==IEEE: package_declaration
|
||||
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);
|
||||
SYMP->popScope($1);
|
||||
GRAMMARP->endLabel($<fl>4,$1,$4); }
|
||||
@@ -696,8 +700,7 @@ packageFront<modulep>:
|
||||
yPACKAGE idAny ';'
|
||||
{ $$ = new AstPackage($1,*$2);
|
||||
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
|
||||
$$->modTrace(v3Global.opt.trace());
|
||||
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
|
||||
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
|
||||
PARSEP->rootp()->addModulep($$);
|
||||
SYMP->pushNew($$); }
|
||||
;
|
||||
@@ -770,7 +773,7 @@ module_declaration: // ==IEEE: module_declaration
|
||||
// // IEEE: module_nonansi_header + module_ansi_header
|
||||
modFront importsAndParametersE portsStarE ';'
|
||||
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 ($5) $1->addStmtp($5);
|
||||
SYMP->popScope($1);
|
||||
@@ -780,6 +783,7 @@ module_declaration: // ==IEEE: module_declaration
|
||||
{ $1->modTrace(false); // Stash for implicit wires, etc
|
||||
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
|
||||
if ($5) $1->addStmtp($5);
|
||||
GRAMMARP->m_tracingParse = true;
|
||||
SYMP->popScope($1);
|
||||
GRAMMARP->endLabel($<fl>7,$1,$7); }
|
||||
//
|
||||
@@ -792,8 +796,7 @@ modFront<modulep>:
|
||||
// // any formal arguments, as the arguments must land in the new scope.
|
||||
yMODULE lifetimeE idAny
|
||||
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
|
||||
$$->modTrace(v3Global.opt.trace());
|
||||
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
|
||||
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
|
||||
PARSEP->rootp()->addModulep($$);
|
||||
SYMP->pushNew($$); }
|
||||
;
|
||||
@@ -809,8 +812,7 @@ udpFront<modulep>:
|
||||
{ $$ = new AstPrimitive($1,*$3); $$->inLibrary(true);
|
||||
$$->modTrace(false);
|
||||
$$->addStmtp(new AstPragma($1,AstPragmaType::INLINE_MODULE));
|
||||
PARSEP->fileline()->tracingOn(false);
|
||||
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
|
||||
GRAMMARP->m_tracingParse = false;
|
||||
PARSEP->rootp()->addModulep($$);
|
||||
SYMP->pushNew($$); }
|
||||
;
|
||||
@@ -845,8 +847,7 @@ paramPortDeclOrArgList<nodep>: // IEEE: list_of_param_assignments + { parameter_
|
||||
|
||||
paramPortDeclOrArg<nodep>: // IEEE: param_assignment + parameter_port_declaration
|
||||
// // We combine the two as we can't tell which follows a comma
|
||||
param_assignment { $$ = $1; }
|
||||
| parameter_port_declarationFront param_assignment { $$ = $2; }
|
||||
parameter_port_declarationFrontE param_assignment { $$ = $2; }
|
||||
;
|
||||
|
||||
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
|
||||
pgmFront parameter_port_listE portsStarE ';'
|
||||
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 ($5) $1->addStmtp($5);
|
||||
SYMP->popScope($1);
|
||||
@@ -1028,8 +1029,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
|
||||
pgmFront<modulep>:
|
||||
yPROGRAM lifetimeE idAny/*new_program*/
|
||||
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
|
||||
$$->modTrace(v3Global.opt.trace());
|
||||
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
|
||||
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
|
||||
PARSEP->rootp()->addModulep($$);
|
||||
SYMP->pushNew($$); }
|
||||
;
|
||||
@@ -1154,10 +1154,13 @@ parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
|
||||
//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)
|
||||
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 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_typeBasic { $$ = $1; }
|
||||
| struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
|
||||
GRAMMARP->m_modp,VFlagChildDType(),$1),$2,true); }
|
||||
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
|
||||
GRAMMARP->m_modp,VFlagChildDType(),$1); }
|
||||
| struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->s_modTypeImpNum++),
|
||||
SYMP,VFlagChildDType(),$1),$2,true); }
|
||||
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->s_modTypeImpNum++),
|
||||
SYMP,VFlagChildDType(),$1); }
|
||||
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
|
||||
| yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); }
|
||||
//UNSUP yEVENT { UNSUP }
|
||||
@@ -1597,8 +1600,9 @@ implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
|
||||
|
||||
type_declaration<nodep>: // ==IEEE: type_declaration
|
||||
// // 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));
|
||||
SYMP->reinsert($$); }
|
||||
yTYPEDEF data_type idAny variable_dimensionListE dtypeAttrListE ';'
|
||||
/**/ { $$ = 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
|
||||
// // 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
|
||||
@@ -1609,6 +1613,20 @@ type_declaration<nodep>: // ==IEEE: type_declaration
|
||||
//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
|
||||
|
||||
@@ -2020,9 +2038,11 @@ instnameList<nodep>:
|
||||
| instnameList ',' instnameParen { $$ = $1->addNext($3); }
|
||||
;
|
||||
|
||||
instnameParen<nodep>:
|
||||
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); }
|
||||
instnameParen<cellp>:
|
||||
id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, 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
|
||||
// // Adding above and switching to the Verilog-Perl syntax
|
||||
// // 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
|
||||
if (nodep->isGenVar()) 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
|
||||
GRAMMARP->m_varAttrp = nodep;
|
||||
|
||||
@@ -673,7 +673,7 @@ sub compile {
|
||||
|
||||
if ($param{make_pli}) {
|
||||
$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",
|
||||
fails=>$param{fails},
|
||||
|
||||
@@ -54,10 +54,10 @@ module t (/*AUTOARG*/
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ module t (/*AUTOARG*/
|
||||
assert (0) else $info;
|
||||
assert (0) else $info("Info message");
|
||||
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....");
|
||||
assert (0) else $fatal(1,"Fatal....");
|
||||
`endif
|
||||
|
||||
@@ -8,17 +8,17 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--stats --profile-cfuncs"],
|
||||
);
|
||||
verilator_flags2 => ["--stats"],
|
||||
);
|
||||
|
||||
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);
|
||||
file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, 9);
|
||||
}
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(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_save(int value);
|
||||
import "DPI-C" context function int dpic_restore();
|
||||
import "DPI-C" context function int unsigned dpic_getcontext();
|
||||
|
||||
int result;
|
||||
|
||||
@@ -49,4 +50,17 @@ module sub (input integer inst);
|
||||
if (dpic_restore() != 23+inst) $stop;
|
||||
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
|
||||
|
||||
@@ -42,6 +42,7 @@ extern "C" {
|
||||
extern int dpic_line();
|
||||
extern int dpic_save(int value);
|
||||
extern int dpic_restore();
|
||||
extern unsigned dpic_getcontext();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -126,3 +127,9 @@ int dpic_restore() {
|
||||
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->_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"
|
||||
." && ranlib t_flag_ldflags_a.a "],
|
||||
check_finished=>0);
|
||||
$Self->_run (cmd=>["cd $Self->{obj_dir}"
|
||||
." && g++ -fPIC -c ../../t/t_flag_ldflags_so.cpp"
|
||||
." && g++ -shared -o t_flag_ldflags_so.so -lc t_flag_ldflags_so.o"],
|
||||
." && c++ -fPIC -c ../../t/t_flag_ldflags_so.cpp"
|
||||
." && c++ -shared -o t_flag_ldflags_so.so -lc t_flag_ldflags_so.o"],
|
||||
check_finished=>0);
|
||||
|
||||
compile (
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
`define is_near_real(a,b) ($abs((a)-(b)) < (((a)/(b))*0.0001))
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
reg [5:0] w6_u;
|
||||
reg [15:0] w16a_u;
|
||||
reg [15:0] w16_u;
|
||||
reg [31:0] w32_u;
|
||||
real r;
|
||||
|
||||
reg signed [4:0] bug754_a;
|
||||
@@ -162,6 +163,16 @@
|
||||
w4_u = (w4_u >> w4_u) ^~ (w4_u >> w4_u);
|
||||
`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;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
||||
@@ -25,6 +25,7 @@ module t (/*AUTOARG*/
|
||||
|
||||
initial begin
|
||||
// Check constant propagation
|
||||
// Note $abs is not defined in SystemVerilog (as of 2012)
|
||||
check(`__LINE__, $ceil(-1.2), -1);
|
||||
check(`__LINE__, $ceil(1.2), 2);
|
||||
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__, $sqrt(1.2), 1.095445115010332148841598609578795731067657470703125);
|
||||
//check(`__LINE__, $sqrt(-1.2), 0); // Bad value
|
||||
check(`__LINE__, ((1.5)**(1.25)), 1.660023);
|
||||
`ifndef VERILATOR
|
||||
check(`__LINE__, $acos (0.2), 1.369438406); // Arg1 is -1..1
|
||||
check(`__LINE__, $acosh(1.2), 0.622362503);
|
||||
|
||||
@@ -46,8 +46,8 @@ module m1;
|
||||
initial if (PACKED_PARAM != 8'h36) $stop;
|
||||
endmodule
|
||||
|
||||
module m2;
|
||||
parameter PAR2 = 10;
|
||||
// bug 810
|
||||
module m2 #(/*parameter*/ integer PAR2 = 10);
|
||||
initial begin
|
||||
$display("%x",PAR2);
|
||||
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
|
||||
# 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 (
|
||||
check_finished=>1,
|
||||
|
||||
@@ -36,3 +36,8 @@ module b #(
|
||||
initial if ($c32("TWO") != 2) $stop;
|
||||
`endif
|
||||
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("Slashed=`%s'\n", "1//2.3");
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -809,4 +813,4 @@ predef 1 1
|
||||
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
|
||||
initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz");
|
||||
`undef A `undef STR
|
||||
//----
|
||||
// bug845
|
||||
`define SLASHED "1//2.3"
|
||||
initial $write("Slashed=`%s'\n", `SLASHED);
|
||||
endmodule
|
||||
//======================================================================
|
||||
// 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'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'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'd09: begin if (((to^from)&~80'hf)!==80'h00000000000000000000) $stop; end
|
||||
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;
|
||||
real r;
|
||||
|
||||
// verilator tracing_off
|
||||
sub sub ();
|
||||
// verilator tracing_on
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
@@ -34,3 +38,7 @@ module t (/*AUTOARG*/
|
||||
end
|
||||
|
||||
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_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_not ("$Self->{obj_dir}/simx.vcd", qr/inside_sub/x);
|
||||
}
|
||||
|
||||
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 direction;
|
||||
unsigned int scalar;
|
||||
unsigned int type;
|
||||
int type;
|
||||
} attributes, children;
|
||||
} values[] = {
|
||||
{"onebit", {1, vpiNoDirection, 1, vpiReg}, {0, 0, 0, 0}},
|
||||
|
||||
@@ -133,7 +133,7 @@ int _mon_check_memory() {
|
||||
// iterate and store
|
||||
iter_h = vpi_iterate(vpiMemoryWord, mem_h);
|
||||
cnt = 0;
|
||||
while (lcl_h = vpi_scan(iter_h)) {
|
||||
while ((lcl_h = vpi_scan(iter_h))) {
|
||||
value.value.integer = ++cnt;
|
||||
vpi_put_value(lcl_h, &value, NULL, vpiNoDelay);
|
||||
// check size and range
|
||||
@@ -143,7 +143,7 @@ int _mon_check_memory() {
|
||||
// iterate and accumulate
|
||||
iter_h = vpi_iterate(vpiMemoryWord, mem_h);
|
||||
cnt = 0;
|
||||
while (lcl_h = vpi_scan(iter_h)) {
|
||||
while ((lcl_h = vpi_scan(iter_h))) {
|
||||
++cnt;
|
||||
vpi_get_value(lcl_h, &value);
|
||||
CHECK_RESULT(value.value.integer, cnt);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 885 B |
Reference in New Issue
Block a user