mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 00:23:35 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4a7e4697e | ||
|
|
cd61b1d045 | ||
|
|
24dc36ba4c | ||
|
|
e8e4f1777d | ||
|
|
ae38a26af3 | ||
|
|
8ee94dd7aa | ||
|
|
e741a29d36 | ||
|
|
be1d275151 | ||
|
|
31c9e26e2e | ||
|
|
20ed1ada03 | ||
|
|
891214fa72 | ||
|
|
e819e285e2 | ||
|
|
171c175e54 | ||
|
|
675cbce8cb | ||
|
|
4f1398f773 | ||
|
|
ae89e399a3 | ||
|
|
2c9716c64c | ||
|
|
bc58245abf | ||
|
|
8c4aa8517e | ||
|
|
c0b7a54bb9 | ||
|
|
6b32bb635d | ||
|
|
691de22ae3 | ||
|
|
e64b2d3372 | ||
|
|
e190af9d87 | ||
|
|
8d14463b18 | ||
|
|
04977ef721 | ||
|
|
d84e6875c5 | ||
|
|
80678ae7bc | ||
|
|
482bdab0e0 | ||
|
|
b2623b9841 | ||
|
|
9ae40d64f0 | ||
|
|
cef097b7b7 | ||
|
|
b840334ad2 |
@@ -3,6 +3,38 @@ 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.886 2016-07-30
|
||||
|
||||
**** Fix enum values of 11-16 bits wide using .next/.prev, bug1062. [Brian Flachs]
|
||||
|
||||
**** Fix false warnings on non-power-2 enums using .next/.prev.
|
||||
|
||||
**** Fix comparison of unpacked arrays, bug1071. [Andrew Bardsley]
|
||||
|
||||
**** Fix compiler warning in GCC 6. [David Horton]
|
||||
|
||||
|
||||
* Verilator 3.884 2016-05-18
|
||||
|
||||
** Support parameter type, bug376. [Alan Hunter, et al]
|
||||
|
||||
** Support command-line -G/+pvalue param overrides, bug1045. [Stefan Wallentowitz]
|
||||
|
||||
*** The default l2 scope name is now the same as the top-level module, bug1050.
|
||||
Use "--l2-name v" for the historical behavior.
|
||||
|
||||
*** Add --l2-name option for controlling "v" naming.
|
||||
|
||||
**** Fix --output-split of constructors, bug1035. [Johan Bjork]
|
||||
|
||||
**** Fix removal of empty packages, modules and cells, bug1034. [Johan Bjork]
|
||||
|
||||
**** Fix core dump on Arch Linux/GCC 6.1.1, bug1058. [Jannis Harder]
|
||||
|
||||
**** Fix $value$plusargs to string, msg1890. [Frederic Requin]
|
||||
|
||||
|
||||
* Verilator 3.882 2016-03-01
|
||||
|
||||
**** Internal Verilation-time performance enhancements, bug1021. [Johan Bjork]
|
||||
@@ -2711,5 +2743,5 @@ Version 2.0.
|
||||
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ \f\n]*$"
|
||||
paragraph-separate: "[ \f\n]*$"
|
||||
end:
|
||||
|
||||
+78
-15
@@ -54,7 +54,18 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
|
||||
# We sneak a look at the flags so we can do some pre-environment checks
|
||||
# All flags will hit verilator...
|
||||
foreach my $sw (@ARGV) {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
# Some special treatment for parameters to allow verilog literals for numbers
|
||||
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
|
||||
# If there is a single quote in the parameter put it double quotes ,
|
||||
# else just put it in double quotes
|
||||
if ($sw =~ m![\']!) {
|
||||
$sw = "\"$sw\"";
|
||||
} else {
|
||||
$sw = "'$sw'";
|
||||
}
|
||||
} else {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
}
|
||||
push @Opt_Verilator_Sw, $sw;
|
||||
}
|
||||
|
||||
@@ -269,6 +280,7 @@ descriptions in the next sections for more information.
|
||||
--exe Link to create executable
|
||||
-F <file> Parse options from a file, relatively
|
||||
-f <file> Parse options from a file
|
||||
-G<name>=<value> Overwrite toplevel parameter
|
||||
--gdb Run Verilator under GDB interactively
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
--help Display this help
|
||||
@@ -279,6 +291,7 @@ descriptions in the next sections for more information.
|
||||
--inline-mult <value> Tune module inlining
|
||||
-LDFLAGS <flags> Linker pre-object flags for makefile
|
||||
-LDLIBS <flags> Linker library flags for makefile
|
||||
--l2-name <value> Verilog scope name of the top module
|
||||
--language <lang> Default language standard to parse
|
||||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
--lint-only Lint, but do not make output
|
||||
@@ -308,6 +321,7 @@ descriptions in the next sections for more information.
|
||||
--profile-cfuncs Name functions for profiling
|
||||
--private Debugging; see docs
|
||||
--public Debugging; see docs
|
||||
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
@@ -479,7 +493,7 @@ RTL file to mark the signal directly.
|
||||
|
||||
=item --compiler I<compiler-name>
|
||||
|
||||
Enables tunings and work-arounds for the specified C++ compiler.
|
||||
Enables tunings and workarounds for the specified C++ compiler.
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -592,8 +606,8 @@ alias for GCC compatibility.
|
||||
=item --debug
|
||||
|
||||
Select the debug built image of Verilator (if available), and enable more
|
||||
internal assertions (equivelent to C<--debug-check>), debugging messages
|
||||
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
|
||||
internal assertions (equivalent to C<--debug-check>), debugging messages
|
||||
(equivalent to C<--debugi 4>), and intermediate form dump files (equivalent
|
||||
to C<--dump-treei 3>).
|
||||
|
||||
=item --debug-check
|
||||
@@ -688,6 +702,35 @@ The file may contain // comments which are ignored to the end of the line.
|
||||
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
||||
variable.
|
||||
|
||||
=item -GI<name>=I<value>
|
||||
|
||||
Overwrites the given parameter of the toplevel module. The value is limited
|
||||
to basic data literals:
|
||||
|
||||
=over 4
|
||||
|
||||
=item Verilog integer literals
|
||||
|
||||
The standard verilog integer literals are supported, so values like 32'h8,
|
||||
2'b00, 4 etc. are allowed. Care must be taken that the single quote (I') is
|
||||
properly escaped in an interactive shell, e.g., as -GWIDTH=8\'hx.
|
||||
|
||||
=item C integer literals
|
||||
|
||||
It is also possible to use C integer notation, including hexadecimal (0x..),
|
||||
octal (0..) or binary (0b..) notation.
|
||||
|
||||
=item Double literals
|
||||
|
||||
Double literals must contain a dot (.) and/or an exponent (e).
|
||||
|
||||
=item Strings
|
||||
|
||||
String must in double quotes ("). On the command line it is required to escape
|
||||
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
|
||||
|
||||
=back
|
||||
|
||||
=item --gdb
|
||||
|
||||
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
|
||||
@@ -743,9 +786,19 @@ called LDLIBS as that's the Makefile variable it controls. (In Make,
|
||||
LDFLAGS is before the first object, LDLIBS after. -L libraries need to be
|
||||
in the Make variable LDLIBS, not LDFLAGS.)
|
||||
|
||||
=item --l2-name I<value>
|
||||
|
||||
Instead of using the module name when showing Verilog scope, use the name
|
||||
provided. This allows simplifying some Verilator-embedded modeling
|
||||
methodologies. Default is an l2-name matching the top module. The default
|
||||
before 3.884 was "--l2-name v"
|
||||
|
||||
For example, the program "module t; initial $display("%m"); endmodule" will
|
||||
show by default "t". With "--l2-name v" it will print "v".
|
||||
|
||||
=item --language I<value>
|
||||
|
||||
A synonym for C<--default-langauge>, for compatibility with other tools and
|
||||
A synonym for C<--default-language>, for compatibility with other tools and
|
||||
earlier versions of Verilator.
|
||||
|
||||
=item +libext+I<ext>+I<ext>...
|
||||
@@ -873,9 +926,10 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
||||
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
||||
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
|
||||
33". The more sc_bv is used, the worse for performance. Use the
|
||||
"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv.
|
||||
"--pins-bv 65", and the value must be less than or equal to 65. Versions
|
||||
before Verilator 3.671 defaulted to "--pins-bv 33". The more sc_bv is
|
||||
used, the worse for performance. Use the "/*verilator sc_bv*/" attribute
|
||||
to select specific ports to be sc_bv.
|
||||
|
||||
=item --pins-sc-uint
|
||||
|
||||
@@ -946,6 +1000,11 @@ inlining. This will also turn off inlining as if all modules had a
|
||||
/*verilator public_module*/, unless the module specifically enabled it with
|
||||
/*verilator inline_module*/.
|
||||
|
||||
=item -pvalue+I<name>=I<value>
|
||||
|
||||
Overwrites the given parameter(s) of the toplevel module. See -G for a
|
||||
detailed description.
|
||||
|
||||
=item --report-unoptflat
|
||||
|
||||
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
|
||||
@@ -1340,7 +1399,7 @@ This is an example similar to the above, but using SystemC.
|
||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
||||
delete top;
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@@ -1603,7 +1662,7 @@ example:
|
||||
|
||||
double sc_time_stamp () { // Called by $time in Verilog
|
||||
return main_time; // converts to double, to match
|
||||
// what SystemC does
|
||||
// what SystemC does
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@@ -1847,7 +1906,7 @@ accesses the above would be:
|
||||
if (!vh1) { error... }
|
||||
const char* name = vpi_get_str(vpiName, vh1);
|
||||
printf("Module name: %s\n"); // Prints "readme"
|
||||
|
||||
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
vpi_get_value(vh1, &v);
|
||||
@@ -2431,7 +2490,7 @@ simulates as Synopsys's Design Compiler would; namely a block of the form:
|
||||
This will recompute y when there is even a potential for change in x or a
|
||||
change in z, that is when the flops computing x or z evaluate (which is
|
||||
what Design Compiler will synthesize.) A compliant simulator would only
|
||||
calculate y if x changes. Use verilog-mode's /*AS*/ or Verilog 2001's
|
||||
calculate y if x changes. Use Verilog-Mode's /*AS*/ or Verilog 2001's
|
||||
always @* to reduce missing activity items. Avoid putting $displays in
|
||||
combo blocks, as they may print multiple times when not desired, even on
|
||||
compliant simulators as event ordering is not specified.
|
||||
@@ -2514,7 +2573,7 @@ variables are initialized to a random value.
|
||||
Event driven simulators will generally trigger an edge on a transition from X
|
||||
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
||||
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
|
||||
code (particularly for reset) may rely on X->0 triggering an edge. Verilator
|
||||
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
||||
runs with and without this switch will find such problems.
|
||||
|
||||
@@ -2567,7 +2626,7 @@ clock_enable*/ attribute.
|
||||
=head2 Ranges must be big-bit-endian
|
||||
|
||||
Bit ranges must be numbered with the MSB being numbered greater or the same
|
||||
as the LSB. Little-bit-endian busses [0:15] are not supported as they
|
||||
as the LSB. Little-bit-endian buses [0:15] are not supported as they
|
||||
aren't easily made compatible with C++.
|
||||
|
||||
=head2 Gate Primitives
|
||||
@@ -2766,7 +2825,7 @@ when displaying all times, model wide.
|
||||
|
||||
=head1 ERRORS AND WARNINGS
|
||||
|
||||
Warnings may be disabled in two ways. First, when the warning is
|
||||
Warnings may be disabled in three ways. First, when the warning is
|
||||
printed it will include a warning code. Simply surround the offending
|
||||
line with a warn_off/warn_on pair:
|
||||
|
||||
@@ -2774,6 +2833,10 @@ line with a warn_off/warn_on pair:
|
||||
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
|
||||
// verilator lint_on UNSIGNED
|
||||
|
||||
Second, warnings may be disabled using a configuration file with a lint_off
|
||||
command. This is useful when a script is suppressing warnings and the
|
||||
Verilog source should not be changed.
|
||||
|
||||
Warnings may also be globally disabled by invoking Verilator with the
|
||||
C<-Wno-I<warning>> switch. This should be avoided, as it removes all
|
||||
checking across the designs, and prevents other users from compiling your
|
||||
|
||||
+2
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.882 2016-03-01])
|
||||
AC_INIT([Verilator],[3.886 2016-07-30])
|
||||
# When releasing, also update header of Changes file
|
||||
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
@@ -132,6 +132,7 @@ _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks)
|
||||
AC_SUBST(CFG_CXXFLAGS_SRC)
|
||||
|
||||
# Flags for compiling Verilator parser
|
||||
|
||||
+11
-2
@@ -961,7 +961,8 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
}
|
||||
|
||||
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const string& ofilenamep, void* memp, IData start, IData end) {
|
||||
const string& ofilenamep, void* memp, IData start, IData end) {
|
||||
if (fnwords) {}
|
||||
FILE* fp = fopen(ofilenamep.c_str(), "r");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
// We don't report the Verilog source filename as it slow to have to pass it down
|
||||
@@ -1076,6 +1077,14 @@ IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
else return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IN(int, const char* prefixp, char, string& ldr) {
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
if (match == "") return 0;
|
||||
ldr = string(dp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
@@ -1217,7 +1226,7 @@ VerilatedModule::VerilatedModule(const char* namep)
|
||||
}
|
||||
|
||||
VerilatedModule::~VerilatedModule() {
|
||||
if (m_namep) free((void*)m_namep); m_namep=NULL;
|
||||
if (m_namep) { free((void*)m_namep); m_namep=NULL; }
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
@@ -288,6 +288,7 @@ public:
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
static void commandArgsAdd(int argc, const char** argv);
|
||||
static CommandArgValues* getCommandArgs() {return &s_args;}
|
||||
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
|
||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||
|
||||
@@ -66,5 +66,6 @@ extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
||||
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
||||
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
||||
extern IData VL_VALUEPLUSARGS_IN(int rbits, const char* prefixp, char fmt, string& ldr);
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -92,7 +92,11 @@ public: // But only for verilated*.cpp
|
||||
|
||||
// METHODS - arguments
|
||||
static void commandArgs(int argc, const char** argv) {
|
||||
s_s.m_argVec.clear();
|
||||
s_s.m_argVec.clear(); // Always clear
|
||||
commandArgsAdd(argc, argv);
|
||||
}
|
||||
static void commandArgsAdd(int argc, const char** argv) {
|
||||
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
|
||||
@@ -99,6 +99,8 @@ CPPFLAGS += -MP # Only works on recent GCC versions
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
|
||||
#CPPFLAGS += -pedantic-errors
|
||||
else
|
||||
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
|
||||
endif
|
||||
CPPFLAGSWALL = $(CPPFLAGS)
|
||||
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
|
||||
@@ -235,6 +237,7 @@ RAW_OBJS = \
|
||||
V3Undriven.o \
|
||||
V3Unknown.o \
|
||||
V3Unroll.o \
|
||||
V3VarResets.o \
|
||||
V3Width.o \
|
||||
V3WidthSel.o \
|
||||
|
||||
|
||||
+8
-5
@@ -514,6 +514,7 @@ public:
|
||||
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
bool unknown() const { return m_e==CLOCKER_UNKNOWN; }
|
||||
AstVarAttrClocker invert() const {
|
||||
if (m_e==CLOCKER_YES) return CLOCKER_NO;
|
||||
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
|
||||
@@ -1118,7 +1119,7 @@ public:
|
||||
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
||||
int user1() const { return user1p()->castInt(); }
|
||||
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
||||
int user1Inc() { int v=user1(); user1(v+1); return v; }
|
||||
int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; }
|
||||
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
||||
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||
|
||||
@@ -1128,7 +1129,7 @@ public:
|
||||
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
||||
int user2() const { return user2p()->castInt(); }
|
||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
||||
int user2Inc() { int v=user2(); user2(v+1); return v; }
|
||||
int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; }
|
||||
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
|
||||
static void user2ClearTree() { AstUser2InUse::clear(); }
|
||||
|
||||
@@ -1138,7 +1139,7 @@ public:
|
||||
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
||||
int user3() const { return user3p()->castInt(); }
|
||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
||||
int user3Inc() { int v=user3(); user3(v+1); return v; }
|
||||
int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; }
|
||||
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
|
||||
static void user3ClearTree() { AstUser3InUse::clear(); }
|
||||
|
||||
@@ -1148,7 +1149,7 @@ public:
|
||||
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
||||
int user4() const { return user4p()->castInt(); }
|
||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
||||
int user4Inc() { int v=user4(); user4(v+1); return v; }
|
||||
int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; }
|
||||
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
|
||||
static void user4ClearTree() { AstUser4InUse::clear(); }
|
||||
|
||||
@@ -1158,7 +1159,7 @@ public:
|
||||
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
||||
int user5() const { return user5p()->castInt(); }
|
||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
||||
int user5Inc() { int v=user5(); user5(v+1); return v; }
|
||||
int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; }
|
||||
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
|
||||
static void user5ClearTree() { AstUser5InUse::clear(); }
|
||||
|
||||
@@ -1349,6 +1350,8 @@ public:
|
||||
: AstNodeMath(fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); }
|
||||
ASTNODE_BASE_FUNCS(NodeBiop)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||
// ACCESSORS
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||
|
||||
@@ -977,6 +977,7 @@ void AstVar::dump(ostream& str) {
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
if (isFuncReturn()) str<<" [FUNCRTN]";
|
||||
else if (isFuncLocal()) str<<" [FUNC]";
|
||||
if (!attrClocker().unknown()) str<<" ["<<attrClocker().ascii()<<"] ";
|
||||
str<<" "<<varType();
|
||||
}
|
||||
void AstSenTree::dump(ostream& str) {
|
||||
|
||||
+163
-7
@@ -158,6 +158,39 @@ public:
|
||||
//######################################################################
|
||||
//==== Data Types
|
||||
|
||||
class AstParamTypeDType : public AstNodeDType {
|
||||
// Parents: MODULE
|
||||
// A parameter type statement; much like a var or typedef
|
||||
private:
|
||||
AstVarType m_varType; // Type of variable (for localparam vs. param)
|
||||
string m_name; // Name of variable
|
||||
public:
|
||||
AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
|
||||
: AstNodeDType(fl), m_varType(type), m_name(name) {
|
||||
childDTypep(dtp); // Only for parser
|
||||
dtypep(NULL); // V3Width will resolve
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ParamTypeDType, PARAMTYPEDTYPE)
|
||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to
|
||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
|
||||
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
|
||||
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
|
||||
// METHODS
|
||||
virtual string name() const { return m_name; }
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual bool hasDType() const { return true; }
|
||||
void name(const string& flag) { m_name = flag; }
|
||||
AstVarType varType() const { return m_varType; } // * = Type of variable
|
||||
bool isParam() const { return true; }
|
||||
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
|
||||
};
|
||||
|
||||
class AstTypedef : public AstNode {
|
||||
private:
|
||||
string m_name;
|
||||
@@ -689,6 +722,24 @@ public:
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
|
||||
};
|
||||
|
||||
class AstParseTypeDType : public AstNodeDType {
|
||||
// Parents: VAR
|
||||
// During parsing, this indicates the type of a parameter is a "parameter type"
|
||||
// e.g. the data type is a container of any data type
|
||||
public:
|
||||
AstParseTypeDType(FileLine* fl)
|
||||
: AstNodeDType(fl) {}
|
||||
ASTNODE_NODE_FUNCS(ParseTypeDType, PARSETYPEDTYPE)
|
||||
AstNodeDType* dtypep() const { return NULL; }
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return NULL; }
|
||||
virtual AstNodeDType* skipRefp() const { return NULL; }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const { return 0; }
|
||||
virtual int widthTotalBytes() const { return 0; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstArraySel : public AstNodeSel {
|
||||
@@ -713,6 +764,7 @@ public:
|
||||
init(fromp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ArraySel, ARRAYSEL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstArraySel(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
V3ERROR_NA; /* How can from be a const? */ }
|
||||
virtual string emitVerilog() { return "%k(%l%f[%r])"; }
|
||||
@@ -742,6 +794,7 @@ public:
|
||||
dtypeSetUInt32(); // Always used on IData arrays so returns word entities
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(WordSel, WORDSEL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstWordSel(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k(%l%f[%r])"; }
|
||||
virtual string emitC() { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp
|
||||
@@ -1333,6 +1386,7 @@ private:
|
||||
int m_pinNum; // Pin number
|
||||
string m_name; // Pin name, or "" for number based interconnect
|
||||
AstVar* m_modVarp; // Input/output this pin connects to on submodule.
|
||||
AstParamTypeDType* m_modPTypep; // Param type this pin connects to on submodule.
|
||||
bool m_param; // Pin connects to parameter
|
||||
bool m_svImplicit; // Pin is SystemVerilog .name'ed
|
||||
public:
|
||||
@@ -1341,6 +1395,7 @@ public:
|
||||
,m_name(name), m_param(false), m_svImplicit(false) {
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
setNOp1p(exprp);
|
||||
}
|
||||
AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
|
||||
@@ -1348,11 +1403,15 @@ public:
|
||||
m_name = varname->name();
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
setNOp1p(exprp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Pin, PIN)
|
||||
virtual void dump(ostream& str);
|
||||
virtual const char* broken() const { BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); return NULL; }
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists());
|
||||
BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists());
|
||||
return NULL; }
|
||||
virtual string name() const { return m_name; } // * = Pin name, ""=go by number
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual string prettyOperatorName() const { return modVarp()
|
||||
@@ -1363,7 +1422,9 @@ public:
|
||||
void exprp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected
|
||||
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
|
||||
void modVarp(AstVar* varp) { m_modVarp=varp; }
|
||||
void modVarp(AstVar* nodep) { m_modVarp=nodep; }
|
||||
AstParamTypeDType* modPTypep() const { return m_modPTypep; } // [After Link] Pointer to variable
|
||||
void modPTypep(AstParamTypeDType* nodep) { m_modPTypep=nodep; }
|
||||
bool param() const { return m_param; }
|
||||
void param(bool flag) { m_param=flag; }
|
||||
bool svImplicit() const { return m_svImplicit; }
|
||||
@@ -2804,6 +2865,7 @@ public:
|
||||
dtypeSetUInt32(); // Always used on, and returns word entities
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ChangeXor, CHANGEXOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstChangeXor(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opChangeXor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f^ %r)"; }
|
||||
virtual string emitC() { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; }
|
||||
@@ -2922,20 +2984,37 @@ class AstInitArray : public AstNode {
|
||||
// Set a var to a large list of values
|
||||
// The values must be in sorted order, and not exceed the size of the var's array.
|
||||
// The first value on the initsp() list is for the lo() index of the array.
|
||||
// If default is specified, the vector may be sparse, and not provide each value.
|
||||
// Parents: ASTVAR::init()
|
||||
// Children: CONSTs...
|
||||
deque<uint32_t> m_indices; // Which array index each entry in the list is for (if defaultp)
|
||||
public:
|
||||
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* initsp)
|
||||
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* defaultp)
|
||||
: AstNode(fl) {
|
||||
dtypep(newDTypep);
|
||||
addNOp1p(initsp);
|
||||
addNOp1p(defaultp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(InitArray, INITARRAY)
|
||||
AstNode* initsp() const { return op1p()->castNode(); } // op1 = Initial value expressions
|
||||
void addInitsp(AstNode* newp) { addOp1p(newp); }
|
||||
AstNode* defaultp() const { return op1p()->castNode(); } // op1 = Default if sparse
|
||||
void defaultp(AstNode* newp) { setOp1p(newp); }
|
||||
AstNode* initsp() const { return op2p()->castNode(); } // op2 = Initial value expressions
|
||||
void addValuep(AstNode* newp) { addIndexValuep(m_indices.size(), newp); }
|
||||
void addIndexValuep(uint32_t index, AstNode* newp) {
|
||||
// Must insert in sorted order
|
||||
if (!m_indices.empty()) UASSERT(index > m_indices.back(), "InitArray adding index <= previous index");
|
||||
m_indices.push_back(index);
|
||||
addOp2p(newp); }
|
||||
void addFrontValuep(AstNode* newp) { // Add to front of list, e.g. index 0.
|
||||
// e.g. 0:100, 1:101 when addFront(200), get 0:200, 1:100, 2:101
|
||||
initsp()->addHereThisAsNext(newp);
|
||||
m_indices.push_back(m_indices.size());
|
||||
}
|
||||
int posIndex(int listPos) {
|
||||
UASSERT (listPos < (int)m_indices.size(), "InitArray past end of indices list");
|
||||
return m_indices[listPos]; }
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
virtual bool same(AstNode* samep) const { return m_indices==samep->castInitArray()->m_indices; }
|
||||
};
|
||||
|
||||
class AstPragma : public AstNode {
|
||||
@@ -3747,6 +3826,7 @@ public:
|
||||
AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogOr, LOGOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogOr(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogOr(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f|| %r)"; }
|
||||
virtual string emitC() { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3761,6 +3841,7 @@ public:
|
||||
AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogAnd, LOGAND)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogAnd(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogAnd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f&& %r)"; }
|
||||
virtual string emitC() { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3775,6 +3856,7 @@ public:
|
||||
AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogIf, LOGIF)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogIf(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogIf(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f-> %r)"; }
|
||||
virtual string emitC() { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3789,6 +3871,7 @@ public:
|
||||
AstLogIff(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogIff, LOGIFF)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogIff(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogIff(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<-> %r)"; }
|
||||
virtual string emitC() { return "VL_LOGIFF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3803,6 +3886,7 @@ public:
|
||||
AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Or, OR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstOr(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opOr(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f| %r)"; }
|
||||
virtual string emitC() { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3816,6 +3900,7 @@ public:
|
||||
AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(And, AND)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAnd(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAnd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f& %r)"; }
|
||||
virtual string emitC() { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3829,6 +3914,7 @@ public:
|
||||
AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Xor, XOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstXor(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f^ %r)"; }
|
||||
virtual string emitC() { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3842,6 +3928,7 @@ public:
|
||||
AstXnor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Xnor, XNOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstXnor(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXnor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f^ ~ %r)"; }
|
||||
virtual string emitC() { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3855,6 +3942,7 @@ public:
|
||||
AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Eq, EQ)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEq(this->fileline(), lhsp, rhsp); }
|
||||
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEq/AstEqD
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
@@ -3869,6 +3957,7 @@ public:
|
||||
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqD, EQD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3884,6 +3973,7 @@ public:
|
||||
AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqN, EQN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3899,6 +3989,7 @@ public:
|
||||
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Neq, NEQ)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeq(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3912,6 +4003,7 @@ public:
|
||||
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqD, NEQD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3927,6 +4019,7 @@ public:
|
||||
AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqN, NEQN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3942,6 +4035,7 @@ public:
|
||||
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Lt, LT)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLt(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLt(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3955,6 +4049,7 @@ public:
|
||||
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LtD, LTD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3970,6 +4065,7 @@ public:
|
||||
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LtS, LTS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3984,6 +4080,7 @@ public:
|
||||
AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LtN, LTN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3999,6 +4096,7 @@ public:
|
||||
AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Gt, GT)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGt(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGt(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4012,6 +4110,7 @@ public:
|
||||
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GtD, GTD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4027,6 +4126,7 @@ public:
|
||||
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GtS, GTS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4041,6 +4141,7 @@ public:
|
||||
AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GtN, GTN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4056,6 +4157,7 @@ public:
|
||||
AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Gte, GTE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGte(this->fileline(), lhsp, rhsp); }
|
||||
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstGte/AstGteS/AstGteD
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
@@ -4070,6 +4172,7 @@ public:
|
||||
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GteD, GTED)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4085,6 +4188,7 @@ public:
|
||||
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GteS, GTES)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4099,6 +4203,7 @@ public:
|
||||
AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GteN, GTEN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4114,6 +4219,7 @@ public:
|
||||
AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Lte, LTE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLte(this->fileline(), lhsp, rhsp); }
|
||||
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstLte/AstLteS/AstLteD
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
@@ -4128,6 +4234,7 @@ public:
|
||||
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LteD, LTED)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4143,6 +4250,7 @@ public:
|
||||
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LteS, LTES)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4157,6 +4265,7 @@ public:
|
||||
AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LteN, LTEN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4174,6 +4283,7 @@ public:
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftL, SHIFTL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftL(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftL(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<< %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4189,6 +4299,7 @@ public:
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftR, SHIFTR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftR(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftR(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>> %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4207,6 +4318,7 @@ public:
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftRS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMinV()); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>>> %r)"; }
|
||||
@@ -4222,6 +4334,7 @@ public:
|
||||
AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Add, ADD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAdd(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAdd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
|
||||
virtual string emitC() { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4235,6 +4348,7 @@ public:
|
||||
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(AddD, ADDD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAddD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4250,6 +4364,7 @@ public:
|
||||
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Sub, SUB)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstSub(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSub(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
|
||||
virtual string emitC() { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4263,6 +4378,7 @@ public:
|
||||
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(SubD, SUBD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstSubD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4278,6 +4394,7 @@ public:
|
||||
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Mul, MUL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMul(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMul(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4292,6 +4409,7 @@ public:
|
||||
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(MulD, MULD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMulD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4307,6 +4425,7 @@ public:
|
||||
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(MulS, MULS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMulS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4322,6 +4441,7 @@ public:
|
||||
AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Div, DIV)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDiv(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDiv(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4335,6 +4455,7 @@ public:
|
||||
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(DivD, DIVD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDivD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4350,6 +4471,7 @@ public:
|
||||
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(DivS, DIVS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDivS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4364,6 +4486,7 @@ public:
|
||||
AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(ModDiv, MODDIV)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstModDiv(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDiv(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f%% %r)"; }
|
||||
virtual string emitC() { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4377,6 +4500,7 @@ public:
|
||||
AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(ModDivS, MODDIVS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstModDivS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDivS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f%% %r)"; }
|
||||
virtual string emitC() { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4391,6 +4515,7 @@ public:
|
||||
AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Pow, POW)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPow(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPow(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4404,6 +4529,7 @@ public:
|
||||
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(PowD, POWD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "pow(%li,%ri)"; }
|
||||
@@ -4418,6 +4544,7 @@ public:
|
||||
AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(PowSU, POWSU)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowSU(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowSU(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; }
|
||||
@@ -4432,6 +4559,7 @@ public:
|
||||
AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(PowSS, POWSS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowSS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowSS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; }
|
||||
@@ -4446,6 +4574,7 @@ public:
|
||||
AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(PowUS, POWUS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowUS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowUS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; }
|
||||
@@ -4460,6 +4589,7 @@ public:
|
||||
AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqCase, EQCASE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqCase(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f=== %r)"; }
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4473,6 +4603,7 @@ public:
|
||||
AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqCase, NEQCASE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqCase(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!== %r)"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4487,6 +4618,7 @@ public:
|
||||
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqWild, EQWILD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f==? %r)"; }
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4500,6 +4632,7 @@ public:
|
||||
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqWild, NEQWILD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqWild(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!=? %r)"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4519,6 +4652,7 @@ public:
|
||||
}
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Concat, CONCAT)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstConcat(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{%l, %k%r}"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcat(lhs,rhs); }
|
||||
virtual string emitC() { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4534,6 +4668,7 @@ public:
|
||||
dtypeSetString();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ConcatN, CONCATN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstConcatN(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{%l, %k%r}"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcatN(lhs,rhs); }
|
||||
virtual string emitC() { return "VL_CONCATN_NNN(%li, %ri)"; }
|
||||
@@ -4560,6 +4695,7 @@ public:
|
||||
AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount)
|
||||
: AstNodeBiop(fl, lhsp, new AstConst(fl, repCount)) { init(); }
|
||||
ASTNODE_NODE_FUNCS(Replicate, REPLICATE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstReplicate(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opRepl(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%f{%r{%k%l}}"; }
|
||||
virtual string emitC() { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4578,6 +4714,7 @@ public:
|
||||
AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount)
|
||||
: AstNodeBiop(fl, lhsp, new AstConst(fl, repCount)) { init(); }
|
||||
ASTNODE_NODE_FUNCS(ReplicateN, REPLICATEN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstReplicateN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opReplN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%f{%r{%k%l}}"; }
|
||||
virtual string emitC() { return "VL_REPLICATEN_NN%rq(0,0,%rw, %li, %ri)"; }
|
||||
@@ -4592,6 +4729,7 @@ class AstStreamL : public AstNodeStream {
|
||||
public:
|
||||
AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeStream(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(StreamL, STREAML)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstStreamL(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{ << %r %k{%l} }"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opStreamL(lhs,rhs); }
|
||||
virtual string emitC() { return "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4605,6 +4743,7 @@ class AstStreamR : public AstNodeStream {
|
||||
public:
|
||||
AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeStream(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(StreamR, STREAMR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstStreamR(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{ >> %r %k{%l} }"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAssign(lhs); }
|
||||
virtual string emitC() { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; }
|
||||
@@ -4620,6 +4759,7 @@ public:
|
||||
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstBufIf1(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "bufif(%r,%l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
@@ -4632,6 +4772,7 @@ class AstFGetS : public AstNodeBiop {
|
||||
public:
|
||||
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FGetS, FGETS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstFGetS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$fgets(%l,%r)"; }
|
||||
virtual string emitC() { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; }
|
||||
@@ -5098,6 +5239,21 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class AstCReset : public AstNodeStmt {
|
||||
//Reset variable at startup
|
||||
public:
|
||||
AstCReset(FileLine* fl, AstNode* exprsp)
|
||||
: AstNodeStmt(fl) {
|
||||
addNOp1p(exprsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(CReset, CRESET)
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
AstVarRef* varrefp() const { return op1p()->castVarRef(); } // op1= varref to reset
|
||||
};
|
||||
|
||||
class AstCStmt : public AstNodeStmt {
|
||||
// Emit C statement
|
||||
public:
|
||||
|
||||
+58
-8
@@ -51,12 +51,54 @@ public:
|
||||
AstNodeModule* m_topModp; // Top module
|
||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||
AstCFunc* m_chgFuncp; // Change function we're building
|
||||
AstCFunc* m_tlChgFuncp; // Top level change function we're building
|
||||
int m_numStmts; // Number of statements added to m_chgFuncp
|
||||
int m_funcNum; // Number of change functions emitted
|
||||
|
||||
ChangedState() {
|
||||
m_topModp = NULL;
|
||||
m_chgFuncp = NULL;
|
||||
m_scopetopp = NULL;
|
||||
m_tlChgFuncp = NULL;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
}
|
||||
~ChangedState() {}
|
||||
|
||||
void maybeCreateChgFuncp() {
|
||||
// Don't create an extra function call if splitting is disabled
|
||||
if (!v3Global.opt.outputSplitCFuncs()) {
|
||||
m_chgFuncp = m_tlChgFuncp;
|
||||
return;
|
||||
}
|
||||
if (!m_chgFuncp || v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||
m_chgFuncp = new AstCFunc(m_scopetopp->fileline(), "_change_request_" + cvtToStr(++m_funcNum), m_scopetopp, "QData");
|
||||
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_chgFuncp->symProlog(true);
|
||||
m_chgFuncp->declPrivate(true);
|
||||
m_scopetopp->addActivep(m_chgFuncp);
|
||||
|
||||
// Add a top call to it
|
||||
AstCCall* callp = new AstCCall(m_scopetopp->fileline(), m_chgFuncp);
|
||||
callp->argTypes("vlSymsp");
|
||||
|
||||
if (!m_tlChgFuncp->stmtsp()) {
|
||||
m_tlChgFuncp->addStmtsp(new AstCReturn(m_scopetopp->fileline(), callp));
|
||||
} else {
|
||||
AstCReturn* returnp = m_tlChgFuncp->stmtsp()->castCReturn();
|
||||
if (!returnp) m_scopetopp->v3fatalSrc("Lost CReturn in top change function");
|
||||
// This is currently using AstLogOr which will shortcut the evaluation if
|
||||
// any function returns true. This is likely what we want and is similar to the logic already in use
|
||||
// inside V3EmitC, however, it also means that verbose logging may miss to print change detect variables.
|
||||
AstNode* newp = new AstCReturn(m_scopetopp->fileline(),
|
||||
new AstLogOr(m_scopetopp->fileline(), callp,
|
||||
returnp->lhsp()->unlinkFrBack()));
|
||||
returnp->replaceWith(newp);
|
||||
returnp->deleteTree(); VL_DANGLING(returnp);
|
||||
}
|
||||
m_numStmts = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -87,6 +129,8 @@ private:
|
||||
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl);
|
||||
return;
|
||||
}
|
||||
m_statep->maybeCreateChgFuncp();
|
||||
|
||||
AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(),
|
||||
m_varEqnp->cloneTree(true),
|
||||
m_newRvEqnp->cloneTree(true), false);
|
||||
@@ -95,6 +139,8 @@ private:
|
||||
m_newLvEqnp->cloneTree(true),
|
||||
m_varEqnp->cloneTree(true));
|
||||
m_statep->m_chgFuncp->addFinalsp(initp);
|
||||
EmitCBaseCounterVisitor visitor(initp);
|
||||
m_statep->m_numStmts += visitor.count();
|
||||
}
|
||||
|
||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
||||
@@ -200,6 +246,7 @@ private:
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
||||
UINFO(4," TS "<<nodep<<endl);
|
||||
// Clearing
|
||||
@@ -208,15 +255,18 @@ private:
|
||||
AstScope* scopep = nodep->scopep();
|
||||
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
||||
m_statep->m_scopetopp = scopep;
|
||||
// Create change detection function
|
||||
m_statep->m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
||||
m_statep->m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_statep->m_chgFuncp->symProlog(true);
|
||||
m_statep->m_chgFuncp->declPrivate(true);
|
||||
m_statep->m_scopetopp->addActivep(m_statep->m_chgFuncp);
|
||||
// We need at least one change detect so we know to emit the correct code
|
||||
|
||||
// Create a wrapper change detection function that calls each change detection function
|
||||
m_statep->m_tlChgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
||||
m_statep->m_tlChgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_statep->m_tlChgFuncp->symProlog(true);
|
||||
m_statep->m_tlChgFuncp->declPrivate(true);
|
||||
m_statep->m_scopetopp->addActivep(m_statep->m_tlChgFuncp);
|
||||
// Each change detection function needs at least one AstChangeDet
|
||||
// to ensure that V3EmitC outputs the necessary code.
|
||||
m_statep->maybeCreateChgFuncp();
|
||||
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
|
||||
//
|
||||
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
|
||||
@@ -242,6 +242,10 @@ private:
|
||||
// No cleaning, or would loose pointer to enum
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
// Control flow operators
|
||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||
@@ -269,6 +273,7 @@ private:
|
||||
virtual void visit(AstCCall* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
insureCleanAndNext (nodep->argsp());
|
||||
setClean (nodep, true);
|
||||
}
|
||||
|
||||
//--------------------
|
||||
|
||||
+21
-5
@@ -1464,9 +1464,21 @@ private:
|
||||
did=true;
|
||||
}
|
||||
else if (m_selp && valuep->castInitArray()) {
|
||||
int bit = m_selp->bitConst();
|
||||
AstNode* itemp = valuep->castInitArray()->initsp();
|
||||
for (int n=0; n<bit && itemp; ++n, itemp=itemp->nextp()) {}
|
||||
AstInitArray* initarp = valuep->castInitArray();
|
||||
uint32_t bit = m_selp->bitConst();
|
||||
int pos = 0;
|
||||
AstNode* itemp = initarp->initsp();
|
||||
for (; itemp; ++pos, itemp=itemp->nextp()) {
|
||||
uint32_t index = initarp->posIndex(pos);
|
||||
if (index == bit) break;
|
||||
if (index > bit) {
|
||||
if (initarp->defaultp()) {
|
||||
itemp = initarp->defaultp();
|
||||
} else {
|
||||
initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemp->castConst()) {
|
||||
const V3Number& num = itemp->castConst()->num();
|
||||
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
||||
@@ -2260,8 +2272,12 @@ private:
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
if (m_required) {
|
||||
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
||||
<<nodep->prettyTypeName()<<" to constant.");
|
||||
if (nodep->castNodeDType() || nodep->castRange()) {
|
||||
// Ignore dtypes for parameter type pins
|
||||
} else {
|
||||
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
||||
<<nodep->prettyTypeName()<<" to constant.");
|
||||
}
|
||||
} else {
|
||||
// Calculate the width of this operation
|
||||
if (m_params && !nodep->width()) {
|
||||
|
||||
+176
-31
@@ -25,7 +25,18 @@
|
||||
// dependencies easier to resolve.
|
||||
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
||||
// instead of needing as many visitors.
|
||||
//*************************************************************************
|
||||
//
|
||||
// The following nodes have package pointers and are cleaned up here:
|
||||
// AstRefDType, AstEnumItemRef, AstNodeVarRef, AstNodeFTask
|
||||
// These have packagep but will not exist at this stage
|
||||
// AstPackageImport, AstDot, AstPackageRef
|
||||
//
|
||||
// Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links
|
||||
// are no longer used, but their presence prevents us from removing empty
|
||||
// packages. As the links as no longer used after V3Scope, we remove them
|
||||
// here after scoping to allow more dead node
|
||||
// removal.
|
||||
// *************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
@@ -49,7 +60,7 @@ private:
|
||||
// VISITORS
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->modp()->user1(nodep->modp()->user1() - 1);
|
||||
nodep->modp()->user1Inc(-1);
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
||||
@@ -71,10 +82,10 @@ class DeadVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Entire Netlist:
|
||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user1() -> int. Count of number of references
|
||||
// AstVarScope::user1() -> int. Count of number of references
|
||||
// AstNodeDType::user1() -> int. Count of number of references
|
||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user1() -> int. Count of number of references
|
||||
// AstVarScope::user1() -> int. Count of number of references
|
||||
// AstNodeDType::user1() -> int. Count of number of references
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// TYPES
|
||||
@@ -82,11 +93,16 @@ private:
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstNode*> m_dtypesp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstScope*> m_scopesp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstCell*> m_cellsp; // List of all encountered to avoid another loop through tree
|
||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||
bool m_elimUserVars; // Allow removal of user's vars
|
||||
bool m_elimDTypes; // Allow removal of DTypes
|
||||
bool m_elimScopes; // Allow removal of Scopes
|
||||
bool m_elimCells; // Allow removal of Cells
|
||||
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||
|
||||
// METHODS
|
||||
@@ -97,19 +113,25 @@ private:
|
||||
}
|
||||
|
||||
void checkAll(AstNode* nodep) {
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc();
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
if (AstNode* subnodep = nodep->dtypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
}
|
||||
if (AstNode* subnodep = nodep->getChildDTypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
void checkDType(AstNodeDType* nodep) {
|
||||
if (!nodep->generic() // Don't remove generic types
|
||||
&& m_elimDTypes // dtypes stick around until post-widthing
|
||||
&& !nodep->castMemberDType() // Keep member names iff upper type exists
|
||||
) {
|
||||
m_varEtcsp.push_back(nodep);
|
||||
m_dtypesp.push_back(nodep);
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
@@ -119,11 +141,27 @@ private:
|
||||
checkAll(nodep);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
|
||||
|
||||
if (!nodep->isTop() && !nodep->varsp() && !nodep->blocksp() && !nodep->finalClksp()) {
|
||||
m_scopesp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
m_cellsp.push_back(nodep);
|
||||
nodep->modp()->user1Inc();
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
@@ -135,14 +173,16 @@ private:
|
||||
nodep->varp()->user1Inc();
|
||||
}
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
||||
@@ -150,7 +190,8 @@ private:
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
||||
@@ -162,11 +203,27 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstModport* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_elimCells) {
|
||||
if (!nodep->varsp()) {
|
||||
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_elimCells && !nodep->attrPublic()) {
|
||||
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
checkAll(nodep);
|
||||
// Don't let packages with only public variables disappear
|
||||
// Normal modules may disappear, e.g. if they are parameterized then removed
|
||||
@@ -175,7 +232,8 @@ private:
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (mightElim(nodep->varp())) {
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
if (mightElimVar(nodep->varp())) {
|
||||
m_vscsp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
@@ -183,11 +241,10 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||
if (mightElim(nodep)) {
|
||||
m_varEtcsp.push_back(nodep);
|
||||
if (mightElimVar(nodep)) {
|
||||
m_varsp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
// See if simple assignments to variables may be eliminated because that variable is never used.
|
||||
// Similar code in V3Life
|
||||
@@ -199,7 +256,7 @@ private:
|
||||
if (varrefp && !m_sideEffect
|
||||
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||
checkAll(varrefp); // Must track reference to dtype()
|
||||
checkAll(varrefp); // Must track reference to dtype()
|
||||
} else { // Track like any other statement
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
}
|
||||
@@ -235,13 +292,45 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool mightElim(AstVar* nodep) {
|
||||
bool mightElimVar(AstVar* nodep) {
|
||||
return (!nodep->isSigPublic() // Can't elim publics!
|
||||
&& !nodep->isIO()
|
||||
&& (nodep->isTemp()
|
||||
|| (nodep->isParam() && !nodep->isTrace())
|
||||
|| m_elimUserVars)); // Post-Trace can kill most anything
|
||||
}
|
||||
|
||||
void deadCheckScope() {
|
||||
for (bool retry=true; retry; ) {
|
||||
retry = false;
|
||||
for (vector<AstScope*>::iterator it = m_scopesp.begin(); it != m_scopesp.end();++it) {
|
||||
AstScope* scp = *it;
|
||||
if (!scp)
|
||||
continue;
|
||||
if (scp->user1() == 0) {
|
||||
UINFO(4, " Dead AstScope " << scp << endl);
|
||||
scp->aboveScopep()->user1Inc(-1);
|
||||
if (scp->dtypep()) {
|
||||
scp->dtypep()->user1Inc(-1);
|
||||
}
|
||||
scp->unlinkFrBack()->deleteTree(); VL_DANGLING(scp);
|
||||
*it = NULL;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deadCheckCells() {
|
||||
for (vector<AstCell*>::iterator it = m_cellsp.begin(); it!=m_cellsp.end(); ++it) {
|
||||
AstCell* cellp = *it;
|
||||
if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) {
|
||||
cellp->modp()->user1Inc(-1);
|
||||
cellp->unlinkFrBack()->deleteTree(); VL_DANGLING(cellp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deadCheckVar() {
|
||||
// Delete any unused varscopes
|
||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||
@@ -251,34 +340,76 @@ private:
|
||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
AstNodeAssign* assp = it->second;
|
||||
UINFO(4," Dead assign "<<assp<<endl);
|
||||
UINFO(4," Dead assign "<<assp<<endl);
|
||||
assp->dtypep()->user1Inc(-1);
|
||||
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
|
||||
}
|
||||
if (vscp->scopep()) vscp->scopep()->user1Inc(-1);
|
||||
vscp->dtypep()->user1Inc(-1);
|
||||
vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp);
|
||||
}
|
||||
}
|
||||
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
|
||||
for (bool retry=true; retry; ) {
|
||||
retry = false;
|
||||
for (vector<AstVar *>::iterator it = m_varsp.begin(); it != m_varsp.end();++it) {
|
||||
AstVar* varp = *it;
|
||||
if (!varp)
|
||||
continue;
|
||||
if (varp->user1() == 0) {
|
||||
UINFO(4, " Dead " << varp << endl);
|
||||
if (varp->dtypep()) {
|
||||
varp->dtypep()->user1Inc(-1);
|
||||
}
|
||||
varp->unlinkFrBack()->deleteTree(); VL_DANGLING(varp);
|
||||
*it = NULL;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (vector<AstNode*>::iterator it = m_dtypesp.begin(); it != m_dtypesp.end();++it) {
|
||||
if ((*it)->user1() == 0) {
|
||||
UINFO(4," Dead "<<(*it)<<endl);
|
||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
||||
AstNodeClassDType *classp;
|
||||
// It's possible that there if a reference to each individual member, but
|
||||
// not to the dtype itself. Check and don't remove the parent dtype if
|
||||
// members are still alive.
|
||||
if ((classp = (*it)->castNodeClassDType())) {
|
||||
bool cont = true;
|
||||
for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = memberp->nextp()->castMemberDType()) {
|
||||
if (memberp->user1() != 0) {
|
||||
cont = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cont)
|
||||
continue;
|
||||
}
|
||||
(*it)->unlinkFrBack()->deleteTree(); VL_DANGLING(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes, bool elimCells) {
|
||||
m_modp = NULL;
|
||||
m_elimCells = elimCells;
|
||||
m_elimUserVars = elimUserVars;
|
||||
m_elimDTypes = elimDTypes;
|
||||
m_elimScopes = elimScopes;
|
||||
m_sideEffect = false;
|
||||
// Prepare to remove some datatypes
|
||||
nodep->typeTablep()->clearCache();
|
||||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
|
||||
deadCheckVar();
|
||||
// We only elimate scopes when in a flattened structure
|
||||
// Otherwise we have no easy way to know if a scope is used
|
||||
if (elimScopes) deadCheckScope();
|
||||
if (elimCells) deadCheckCells();
|
||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||
deadCheckMod();
|
||||
|
||||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
}
|
||||
@@ -290,16 +421,30 @@ public:
|
||||
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, false);
|
||||
DeadVisitor visitor (nodep, false, false, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true);
|
||||
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
DeadVisitor visitor (nodep, false, true, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true, true, false);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true);
|
||||
DeadVisitor visitor (nodep, true, true, false, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true, true, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@ public:
|
||||
static void deadifyModules(AstNetlist* nodep);
|
||||
// Modules, Data types
|
||||
static void deadifyDTypes(AstNetlist* nodep);
|
||||
static void deadifyDTypesScoped(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void deadifyAll(AstNetlist* nodep);
|
||||
static void deadifyAllScoped(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+93
-84
@@ -120,7 +120,7 @@ public:
|
||||
puts(itemp->name());
|
||||
puts(" = ");
|
||||
itemp->valuep()->iterateAndNext(*this);
|
||||
if (nodep->nextp()) puts(",");
|
||||
if (itemp->nextp()->castEnumItem()) puts(",");
|
||||
puts("\n");
|
||||
}
|
||||
puts("};\n");
|
||||
@@ -912,12 +912,17 @@ class EmitCImp : EmitCStmts {
|
||||
m_blkChangeDetVec.push_back(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstCReset* nodep, AstNUser*) {
|
||||
AstVar* varp = nodep->varrefp()->varp();
|
||||
emitVarReset(varp);
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
// ACCESSORS
|
||||
|
||||
// METHODS
|
||||
// Low level
|
||||
void emitVarResets(AstNodeModule* modp);
|
||||
void emitVarReset(AstVar* modp);
|
||||
void emitCellCtors(AstNodeModule* modp);
|
||||
void emitSensitives();
|
||||
// Medium level
|
||||
@@ -1382,91 +1387,88 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
//######################################################################
|
||||
// Internal EmitC
|
||||
|
||||
void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
||||
puts("// Reset internal values\n");
|
||||
if (modp->isTop()) {
|
||||
if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n");
|
||||
puts("\n");
|
||||
void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
|
||||
} else if (varp->isParam()) {
|
||||
if (!varp->valuep()) varp->v3fatalSrc("No init for a param?");
|
||||
// If a simple CONST value we initialize it using an enum
|
||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||
//puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n");
|
||||
}
|
||||
|
||||
puts("// Reset structure values\n");
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
if (varp->isIO() && modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.
|
||||
else if (AstInitArray* initarp = varp->valuep()->castInitArray()) {
|
||||
if (AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||
if (initarp->defaultp()) {
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi=0;");
|
||||
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++__Vi) {\n");
|
||||
emitSetVarConstant(varp->name()+"[__Vi]", initarp->defaultp()->castConst());
|
||||
puts("}}\n");
|
||||
}
|
||||
else if (varp->isParam()) {
|
||||
if (!varp->valuep()) nodep->v3fatalSrc("No init for a param?");
|
||||
// If a simple CONST value we initialize it using an enum
|
||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||
//puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n");
|
||||
}
|
||||
else if (AstInitArray* initarp = varp->valuep()->castInitArray()) {
|
||||
AstConst* constsp = initarp->initsp()->castConst();
|
||||
if (AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||
for (int i=0; i<arrayp->elementsConst(); i++) {
|
||||
if (!constsp) initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||
emitSetVarConstant(varp->name()+"["+cvtToStr(i)+"]", constsp);
|
||||
constsp = constsp->nextp()->castConst();
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
}
|
||||
}
|
||||
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// Constructor deals with it
|
||||
}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
if (zeroit) puts("VL_ZERO_RESET_W(");
|
||||
else puts("VL_RAND_RESET_W(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(",");
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(");\n");
|
||||
} else {
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
// first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash
|
||||
// with any initial block settings.
|
||||
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||
puts(" = 0;\n");
|
||||
} else if (v3Global.opt.xInitialEdge()
|
||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||
puts(" = 1;\n");
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
puts("(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
int pos = 0;
|
||||
for (AstNode* itemp = initarp->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
||||
int index = initarp->posIndex(pos);
|
||||
if (!initarp->defaultp() && index!=pos) initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||
emitSetVarConstant(varp->name()+"["+cvtToStr(index)+"]", itemp->castConst());
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
}
|
||||
}
|
||||
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// Constructor deals with it
|
||||
}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
if (zeroit) puts("VL_ZERO_RESET_W(");
|
||||
else puts("VL_RAND_RESET_W(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(",");
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(");\n");
|
||||
} else {
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
// first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash
|
||||
// with any initial block settings.
|
||||
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||
puts(" = 0;\n");
|
||||
} else if (v3Global.opt.xInitialEdge()
|
||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||
puts(" = 1;\n");
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
puts("(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
}
|
||||
splitSizeInc(1);
|
||||
}
|
||||
|
||||
void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
|
||||
@@ -1489,10 +1491,16 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) {
|
||||
}
|
||||
emitVarCtors();
|
||||
puts(" {\n");
|
||||
|
||||
emitCellCtors(modp);
|
||||
emitSensitives();
|
||||
emitVarResets(modp);
|
||||
|
||||
puts("// Reset internal values\n");
|
||||
if (modp->isTop()) {
|
||||
if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n");
|
||||
puts("\n");
|
||||
}
|
||||
puts("// Reset structure values\n");
|
||||
puts("_ctor_var_reset();\n");
|
||||
emitTextSection(AstType::atSCCTOR);
|
||||
if (optSystemPerl()) puts("SP_AUTO_CTOR;\n");
|
||||
puts("}\n");
|
||||
@@ -2014,6 +2022,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
puts("static void traceChg ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
ofp()->putsPrivate(false); // public:
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
puts("\n");
|
||||
|
||||
+7
-3
@@ -448,9 +448,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep, AstNUser*) {
|
||||
putfs(nodep,"`{");
|
||||
for (AstNode* subp = nodep->initsp(); subp; subp=subp->nextp()) {
|
||||
subp->accept(*this);
|
||||
if (subp->nextp()) putbs(",");
|
||||
int pos = 0;
|
||||
for (AstNode* itemp = nodep->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
||||
int index = nodep->posIndex(pos);
|
||||
puts(cvtToStr(index));
|
||||
puts(":");
|
||||
itemp->accept(*this);
|
||||
if (itemp->nextp()) putbs(",");
|
||||
}
|
||||
puts("}");
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ private:
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar*, AstNUser*) {}
|
||||
virtual void visit(AstTypedef*, AstNUser*) {}
|
||||
virtual void visit(AstParamTypeDType*, AstNUser*) {}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodeHashIterate(nodep);
|
||||
}
|
||||
|
||||
+90
-12
@@ -77,6 +77,7 @@
|
||||
#include "V3SymTable.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3ParseImp.h"
|
||||
|
||||
//######################################################################
|
||||
// LinkDot state, as a visitor of each AstNode
|
||||
@@ -194,6 +195,7 @@ public:
|
||||
else if (nodep->castFunc()) return "function";
|
||||
else if (nodep->castBegin()) return "block";
|
||||
else if (nodep->castIface()) return "interface";
|
||||
else if (nodep->castParamTypeDType()) return "parameter type";
|
||||
else return nodep->prettyTypeName();
|
||||
}
|
||||
|
||||
@@ -585,6 +587,42 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
// METHODS
|
||||
int debug() { return LinkDotState::debug(); }
|
||||
|
||||
virtual AstConst* parseParamLiteral(FileLine* fl, string literal) {
|
||||
bool success = false;
|
||||
if (literal[0] == '"') {
|
||||
// This is a string
|
||||
string v = literal.substr(1, literal.find('"', 1) - 1);
|
||||
V3Number n(V3Number::VerilogStringLiteral(), fl, v);
|
||||
return new AstConst(fl,n);
|
||||
} else if ((literal.find(".") != string::npos)
|
||||
|| (literal.find("e") != string::npos)) {
|
||||
// This may be a real
|
||||
double v = V3ParseImp::parseDouble(literal.c_str(), literal.length(), &success);
|
||||
if (success) {
|
||||
return new AstConst(fl, AstConst::RealDouble(), v);
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
// This is either an integer or an error
|
||||
// We first try to convert it as C literal. If strtol returns
|
||||
// 0 this is either an error or 0 was parsed. But in any case
|
||||
// we will try to parse it as a verilog literal, hence having
|
||||
// the false negative for 0 is okay. If anything remains in
|
||||
// the string after the number, this is invalid C and we try
|
||||
// the Verilog literal parser.
|
||||
char* endp;
|
||||
int v = strtol(literal.c_str(), &endp, 0);
|
||||
if ((v != 0) && (endp[0] == 0)) { // C literal
|
||||
V3Number n(fl, 32, v);
|
||||
return new AstConst(fl, n);
|
||||
} else { // Try a Verilog literal (fatals if not)
|
||||
V3Number n(fl, literal.c_str());
|
||||
return new AstConst(fl, n);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||
// Process $unit or other packages
|
||||
@@ -872,6 +910,24 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
}
|
||||
}
|
||||
if (ins) {
|
||||
if (m_statep->forPrimary() && nodep->isGParam()
|
||||
&& (m_statep->rootEntp()->nodep() == m_modSymp->parentp()->nodep())) {
|
||||
// This is the toplevel module. Check for command line overwrites of parameters
|
||||
// We first search if the parameter is overwritten and then replace it with a
|
||||
// new value. It will keep the same FileLine information.
|
||||
if (v3Global.opt.hasParameter(nodep->name())) {
|
||||
AstVar* newp = new AstVar(nodep->fileline(), AstVarType(AstVarType::GPARAM),
|
||||
nodep->name(), nodep);
|
||||
string svalue = v3Global.opt.parameter(nodep->name());
|
||||
if (AstNode* valuep = parseParamLiteral(nodep->fileline(), svalue)) {
|
||||
newp->valuep(valuep);
|
||||
UINFO(9," replace parameter "<<nodep<<endl);
|
||||
UINFO(9," with "<<newp<<endl);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
nodep = newp;
|
||||
}
|
||||
}
|
||||
}
|
||||
VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
if (m_statep->forPrimary() && nodep->isGParam()) {
|
||||
m_paramNum++;
|
||||
@@ -893,6 +949,11 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
nodep->iterateChildren(*this);
|
||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module??\n");
|
||||
nodep->iterateChildren(*this);
|
||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
// For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist
|
||||
if (m_statep->forScopeCreation()) nodep->v3fatalSrc("No CFuncs expected in tree yet");
|
||||
@@ -1440,6 +1501,15 @@ private:
|
||||
m_modp->addStmtp(varp);
|
||||
return varp;
|
||||
}
|
||||
void markAndCheckPinDup(AstNode* nodep, AstNode* refp, const char* whatp) {
|
||||
if (refp->user5p() && refp->user5p()->castNode()!=nodep) {
|
||||
nodep->v3error("Duplicate "<<whatp<<" connection: "<<nodep->prettyName()<<endl
|
||||
<<refp->user5p()->castNode()->warnMore()
|
||||
<<"... Location of original "<<whatp<<" connection");
|
||||
} else {
|
||||
refp->user5p(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNetlist* nodep, AstNUser* vup) {
|
||||
@@ -1513,27 +1583,30 @@ private:
|
||||
if (!nodep->modVarp()) {
|
||||
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?\n");
|
||||
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
||||
AstVar* refp = foundp ? foundp->nodep()->castVar() : NULL;
|
||||
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
||||
if (!refp) {
|
||||
if (!foundp) {
|
||||
if (nodep->name() == "__paramNumber1" && m_cellp->modp()->castPrimitive()) {
|
||||
// Primitive parameter is really a delay we can just ignore
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName());
|
||||
} else if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) {
|
||||
nodep->v3error(ucfirst(whatp)<<" is not an in/out/inout/param/interface: "<<nodep->prettyName());
|
||||
} else {
|
||||
nodep->modVarp(refp);
|
||||
if (refp->user5p() && refp->user5p()->castNode()!=nodep) {
|
||||
nodep->v3error("Duplicate "<<whatp<<" connection: "<<nodep->prettyName()<<endl
|
||||
<<refp->user5p()->castNode()->warnMore()
|
||||
<<"... Location of original "<<whatp<<" connection");
|
||||
}
|
||||
else if (AstVar* refp = foundp->nodep()->castVar()) {
|
||||
if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) {
|
||||
nodep->v3error(ucfirst(whatp)<<" is not an in/out/inout/param/interface: "<<nodep->prettyName());
|
||||
} else {
|
||||
refp->user5p(nodep);
|
||||
nodep->modVarp(refp);
|
||||
markAndCheckPinDup(nodep, refp, whatp);
|
||||
}
|
||||
}
|
||||
else if (AstParamTypeDType* refp = foundp->nodep()->castParamTypeDType()) {
|
||||
nodep->modPTypep(refp);
|
||||
markAndCheckPinDup(nodep, refp, whatp);
|
||||
}
|
||||
else {
|
||||
nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
// Early return() above when deleted
|
||||
}
|
||||
@@ -2091,7 +2164,12 @@ private:
|
||||
if (AstTypedef* defp = foundp ? foundp->nodep()->castTypedef() : NULL) {
|
||||
nodep->refDTypep(defp->subDTypep());
|
||||
nodep->packagep(foundp->packagep());
|
||||
} else {
|
||||
}
|
||||
else if (AstParamTypeDType* defp = foundp ? foundp->nodep()->castParamTypeDType() : NULL) {
|
||||
nodep->refDTypep(defp);
|
||||
nodep->packagep(foundp->packagep());
|
||||
}
|
||||
else {
|
||||
nodep->v3error("Can't find typedef: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* netlistp) {
|
||||
|
||||
// Add instance
|
||||
AstCell* cellp = new AstCell(newmodp->fileline(),
|
||||
(v3Global.opt.l2Name() ? "v" : oldmodp->name()),
|
||||
((v3Global.opt.l2Name()!="") ? v3Global.opt.l2Name() : oldmodp->name()),
|
||||
oldmodp->name(),
|
||||
NULL, NULL, NULL);
|
||||
cellp->modp(oldmodp);
|
||||
|
||||
@@ -140,6 +140,21 @@ private:
|
||||
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
cleanFileline(nodep);
|
||||
if (nodep->subDTypep()->castParseTypeDType()) {
|
||||
// It's a parameter type. Use a different node type for this.
|
||||
AstNodeDType* dtypep = nodep->valuep()->castNodeDType();
|
||||
if (!dtypep) {
|
||||
nodep->v3error("Parameter type's initial value isn't a type: "<<nodep->prettyName());
|
||||
nodep->unlinkFrBack();
|
||||
} else {
|
||||
dtypep->unlinkFrBack();
|
||||
AstNode* newp = new AstParamTypeDType(nodep->fileline(), nodep->varType(), nodep->name(),
|
||||
VFlagChildDType(), dtypep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We used modTrace before leveling, and we may now
|
||||
// want to turn it off now that we know the levelizations
|
||||
if (v3Global.opt.traceDepth()
|
||||
|
||||
+62
-2
@@ -130,6 +130,52 @@ void V3Options::addDefine(const string& defline, bool allowPlus) {
|
||||
V3PreShell::defineCmdLine(def,value);
|
||||
}
|
||||
}
|
||||
void V3Options::addParameter(const string& paramline, bool allowPlus) {
|
||||
// Split +define+foo=value into the appropriate parts and parse
|
||||
// Optional + says to allow multiple defines on the line
|
||||
// + is not quotable, as other simulators do not allow that
|
||||
string left = paramline;
|
||||
while (left != "") {
|
||||
string param = left;
|
||||
string::size_type pos;
|
||||
if (allowPlus && ((pos=left.find("+")) != string::npos)) {
|
||||
left = left.substr(pos+1);
|
||||
param.erase(pos);
|
||||
} else {
|
||||
left = "";
|
||||
}
|
||||
string value;
|
||||
if ((pos=param.find("=")) != string::npos) {
|
||||
value = param.substr(pos+1);
|
||||
param.erase(pos);
|
||||
}
|
||||
UINFO(4,"Add parameter"<<param<<"="<<value<<endl);
|
||||
(void)m_parameters.erase(param);
|
||||
m_parameters[param] = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool V3Options::hasParameter(string name) {
|
||||
return m_parameters.find(name) != m_parameters.end();
|
||||
}
|
||||
|
||||
string V3Options::parameter(string name) {
|
||||
string value = m_parameters.find(name)->second;
|
||||
m_parameters.erase(m_parameters.find(name));
|
||||
return value;
|
||||
}
|
||||
|
||||
void V3Options::checkParameters() {
|
||||
if (!m_parameters.empty()) {
|
||||
stringstream msg;
|
||||
msg << "Parameters from the command line were not found in the design:";
|
||||
for (map<string,string>::iterator it = m_parameters.begin();
|
||||
it != m_parameters.end(); ++it) {
|
||||
msg << " " << it->first;
|
||||
}
|
||||
v3fatal(msg.str()<<endl);
|
||||
}
|
||||
}
|
||||
|
||||
void V3Options::addCppFile(const string& filename) {
|
||||
if (m_cppFiles.find(filename) == m_cppFiles.end()) {
|
||||
@@ -647,7 +693,6 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( onoff (sw, "-exe", flag/*ref*/) ) { m_exe = flag; }
|
||||
else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; }
|
||||
else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)){ m_inhibitSim = flag; }
|
||||
else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; }
|
||||
else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; }
|
||||
else if ( !strcmp (sw, "-no-pins64") ) { m_pinsBv = 33; }
|
||||
else if ( onoff (sw, "-order-clock-delay", flag/*ref*/) ) { m_orderClockDly = flag; }
|
||||
@@ -658,6 +703,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( !strcmp (sw, "-private") ) { m_public = false; }
|
||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
|
||||
else if ( onoff (sw, "-public", flag/*ref*/) ) { m_public = flag; }
|
||||
else if ( !strncmp(sw, "-pvalue+", strlen("-pvalue+"))) { addParameter(string(sw+strlen("-pvalue+")), false); }
|
||||
else if ( onoff (sw, "-report-unoptflat", flag/*ref*/) ) { m_reportUnoptflat = flag; }
|
||||
else if ( onoff (sw, "-savable", flag/*ref*/) ) { m_savable = flag; }
|
||||
else if ( !strcmp (sw, "-sc") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = false; }
|
||||
@@ -748,6 +794,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
V3Error::errorLimit(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strncmp (sw, "-G", strlen("-G"))) {
|
||||
addParameter (string (sw+strlen("-G")), false);
|
||||
}
|
||||
else if ( !strncmp (sw, "-I", 2)) {
|
||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
|
||||
}
|
||||
@@ -763,6 +812,16 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
addLdLibs(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-l2-name") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_l2Name = argv[i];
|
||||
}
|
||||
else if ( !strcmp (sw, "-l2name")) { // Historical and undocumented
|
||||
m_l2Name = "v";
|
||||
}
|
||||
else if ( !strcmp (sw, "-no-l2name")) { // Historical and undocumented
|
||||
m_l2Name = "";
|
||||
}
|
||||
else if ( (!strcmp (sw, "-language") && (i+1)<argc)
|
||||
|| (!strcmp (sw, "-default-language") && (i+1)<argc)) {
|
||||
shift;
|
||||
@@ -927,6 +986,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
}
|
||||
else if ( !strcmp (sw, "-pins-bv") && (i+1)<argc ) {
|
||||
shift; m_pinsBv = atoi(argv[i]);
|
||||
if (m_pinsBv > 65) fl->v3fatal("--pins-bv maximum is 65: "<<argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-pipe-filter") && (i+1)<argc ) {
|
||||
shift; m_pipeFilter = argv[i];
|
||||
@@ -1142,7 +1202,6 @@ V3Options::V3Options() {
|
||||
m_exe = false;
|
||||
m_ignc = false;
|
||||
m_inhibitSim = false;
|
||||
m_l2Name = true;
|
||||
m_lintOnly = false;
|
||||
m_makeDepend = true;
|
||||
m_makePhony = false;
|
||||
@@ -1192,6 +1251,7 @@ V3Options::V3Options() {
|
||||
m_makeDir = "obj_dir";
|
||||
m_bin = "";
|
||||
m_flags = "";
|
||||
m_l2Name = "";
|
||||
m_unusedRegexp = "*unused*";
|
||||
m_xAssign = "fast";
|
||||
|
||||
|
||||
+9
-2
@@ -58,6 +58,8 @@ class V3Options {
|
||||
V3StringList m_vFiles; // argument: Verilog files to read
|
||||
DebugSrcMap m_debugSrcs; // argument: --debugi-<srcfile>=<level>
|
||||
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
||||
map<string,string> m_parameters; // Parameters
|
||||
|
||||
|
||||
bool m_preprocOnly; // main switch: -E
|
||||
bool m_makeDepend; // main switch: -MMD
|
||||
@@ -76,7 +78,6 @@ class V3Options {
|
||||
bool m_exe; // main switch: --exe
|
||||
bool m_ignc; // main switch: --ignc
|
||||
bool m_inhibitSim; // main switch: --inhibit-sim
|
||||
bool m_l2Name; // main switch: --l2name
|
||||
bool m_lintOnly; // main switch: --lint-only
|
||||
bool m_orderClockDly;// main switch: --order-clock-delay
|
||||
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
|
||||
@@ -122,6 +123,7 @@ class V3Options {
|
||||
string m_bin; // main switch: --bin {binary}
|
||||
string m_exeName; // main switch: -o {name}
|
||||
string m_flags; // main switch: -f {name}
|
||||
string m_l2Name; // main switch: --l2name; "" for top-module's name
|
||||
string m_makeDir; // main switch: -Mdir
|
||||
string m_modPrefix; // main switch: --mod-prefix
|
||||
string m_pipeFilter; // main switch: --pipe-filter
|
||||
@@ -162,6 +164,7 @@ class V3Options {
|
||||
void addFuture(const string& flag);
|
||||
void addIncDirUser(const string& incdir); // User requested
|
||||
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
||||
void addParameter(const string& paramline, bool allowPlus);
|
||||
void addLangExt(const string& langext, const V3LangCode& lc);
|
||||
void addLibExtV(const string& libext);
|
||||
void optimize(int level);
|
||||
@@ -237,7 +240,6 @@ class V3Options {
|
||||
bool pinsUint8() const { return m_pinsUint8; }
|
||||
bool profileCFuncs() const { return m_profileCFuncs; }
|
||||
bool allPublic() const { return m_public; }
|
||||
bool l2Name() const { return m_l2Name; }
|
||||
bool lintOnly() const { return m_lintOnly; }
|
||||
bool ignc() const { return m_ignc; }
|
||||
bool inhibitSim() const { return m_inhibitSim; }
|
||||
@@ -264,6 +266,7 @@ class V3Options {
|
||||
int compLimitParens() const { return m_compLimitParens; }
|
||||
|
||||
string exeName() const { return m_exeName!="" ? m_exeName : prefix(); }
|
||||
string l2Name() const { return m_l2Name; }
|
||||
string makeDir() const { return m_makeDir; }
|
||||
string modPrefix() const { return m_modPrefix; }
|
||||
string pipeFilter() const { return m_pipeFilter; }
|
||||
@@ -279,6 +282,10 @@ class V3Options {
|
||||
const V3StringList& vFiles() const { return m_vFiles; }
|
||||
const V3LangCode& defaultLanguage() const { return m_defaultLanguage; }
|
||||
|
||||
bool hasParameter(string name);
|
||||
string parameter(string name);
|
||||
void checkParameters();
|
||||
|
||||
bool isFuture(const string& flag) const;
|
||||
bool isLibraryFile(const string& filename) const;
|
||||
bool isClocker(const string& signame) const;
|
||||
|
||||
+102
-54
@@ -84,10 +84,10 @@ private:
|
||||
typedef deque<pair<AstIfaceRefDType*,AstIfaceRefDType*> > IfaceRefRefs; // Note may have duplicate entries
|
||||
|
||||
// STATE
|
||||
typedef map<AstVar*,AstVar*> VarCloneMap;
|
||||
typedef map<AstNode*,AstNode*> CloneMap;
|
||||
struct ModInfo {
|
||||
AstNodeModule* m_modp; // Module with specified name
|
||||
VarCloneMap m_cloneMap; // Map of old-varp -> new cloned varp
|
||||
CloneMap m_cloneMap; // Map of old-varp -> new cloned varp
|
||||
explicit ModInfo(AstNodeModule* modp) { m_modp=modp; }
|
||||
};
|
||||
typedef map<string,ModInfo> ModNameMap;
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
string paramSmallName(AstNodeModule* modp, AstVar* varp) {
|
||||
string paramSmallName(AstNodeModule* modp, AstNode* varp) {
|
||||
if (varp->user4()<=1) {
|
||||
makeSmallNames(modp);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ private:
|
||||
return st;
|
||||
}
|
||||
string paramValueNumber(AstNode* nodep) {
|
||||
// Given a compilcated object create a number to use for param module assignment
|
||||
// Given a complicated object create a number to use for param module assignment
|
||||
// Ideally would be relatively stable if design changes (not use pointer value),
|
||||
// and must return same value given same input node
|
||||
// Return must presently be numeric so doesn't collide with 'small' alphanumeric parameter names
|
||||
@@ -166,14 +166,42 @@ private:
|
||||
return (string)"z"+cvtToStr(num);
|
||||
}
|
||||
}
|
||||
void relinkPins(VarCloneMap* clonemapp, AstPin* startpinp) {
|
||||
void collectPins(CloneMap* clonemapp, AstNodeModule* modp) {
|
||||
// Grab all I/O so we can remap our pins later
|
||||
for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* varp = stmtp->castVar()) {
|
||||
if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) {
|
||||
// Cloning saved a pointer to the new node for us, so just follow that link.
|
||||
AstVar* oldvarp = varp->clonep()->castVar();
|
||||
//UINFO(8,"Clone list 0x"<<hex<<(uint32_t)oldvarp<<" -> 0x"<<(uint32_t)varp<<endl);
|
||||
clonemapp->insert(make_pair(oldvarp, varp));
|
||||
}
|
||||
}
|
||||
else if (AstParamTypeDType* ptp = stmtp->castParamTypeDType()) {
|
||||
if (ptp->isGParam()) {
|
||||
AstParamTypeDType* oldptp = ptp->clonep()->castParamTypeDType();
|
||||
clonemapp->insert(make_pair(oldptp, ptp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void relinkPins(CloneMap* clonemapp, AstPin* startpinp) {
|
||||
for (AstPin* pinp = startpinp; pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (!pinp->modVarp()) pinp->v3fatalSrc("Not linked?\n");
|
||||
// Find it in the clone structure
|
||||
//UINFO(8,"Clone find 0x"<<hex<<(uint32_t)pinp->modVarp()<<endl);
|
||||
VarCloneMap::iterator cloneiter = clonemapp->find(pinp->modVarp());
|
||||
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
|
||||
pinp->modVarp(cloneiter->second);
|
||||
if (pinp->modVarp()) {
|
||||
// Find it in the clone structure
|
||||
//UINFO(8,"Clone find 0x"<<hex<<(uint32_t)pinp->modVarp()<<endl);
|
||||
CloneMap::iterator cloneiter = clonemapp->find(pinp->modVarp());
|
||||
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
|
||||
pinp->modVarp(cloneiter->second->castVar());
|
||||
}
|
||||
else if (pinp->modPTypep()) {
|
||||
CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep());
|
||||
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
|
||||
pinp->modPTypep(cloneiter->second->castParamTypeDType());
|
||||
}
|
||||
else {
|
||||
pinp->v3fatalSrc("Not linked?\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
void visitCell(AstCell* nodep);
|
||||
@@ -458,31 +486,50 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
if (debug()>8) nodep->paramsp()->dumpTreeAndNext(cout,"-cellparams:\t");
|
||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (!pinp->exprp()) continue; // No-connect
|
||||
AstVar* modvarp = pinp->modVarp();
|
||||
if (!modvarp) {
|
||||
pinp->v3error("Parameter not found in sub-module: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
} else if (!modvarp->isGParam()) {
|
||||
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
} else {
|
||||
AstConst* constp = pinp->exprp()->castConst();
|
||||
AstConst* origconstp = modvarp->valuep()->castConst();
|
||||
if (!constp) {
|
||||
//if (debug()) pinp->dumpTree(cout,"error:");
|
||||
pinp->v3error("Can't convert defparam value to constant: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
pinp->exprp()->replaceWith(new AstConst(pinp->fileline(), V3Number(pinp->fileline(), modvarp->width(), 0)));
|
||||
} else if (origconstp && constp->sameTree(origconstp)) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else if (constp->num().isDouble()
|
||||
|| constp->num().isString()
|
||||
|| constp->num().isFourState()) {
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+paramValueNumber(constp);
|
||||
any_overrides = true;
|
||||
if (AstVar* modvarp = pinp->modVarp()) {
|
||||
if (!modvarp->isGParam()) {
|
||||
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+constp->num().ascii(false);
|
||||
any_overrides = true;
|
||||
AstConst* exprp = pinp->exprp()->castConst();
|
||||
AstConst* origp = modvarp->valuep()->castConst();
|
||||
if (!exprp) {
|
||||
//if (debug()) pinp->dumpTree(cout,"error:");
|
||||
pinp->v3error("Can't convert defparam value to constant: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
pinp->exprp()->replaceWith(new AstConst(pinp->fileline(), V3Number(pinp->fileline(), modvarp->width(), 0)));
|
||||
} else if (origp && exprp->sameTree(origp)) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else if (exprp->num().isDouble()
|
||||
|| exprp->num().isString()
|
||||
|| exprp->num().isFourState()) {
|
||||
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
|
||||
any_overrides = true;
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),modvarp)+exprp->num().ascii(false);
|
||||
any_overrides = true;
|
||||
}
|
||||
}
|
||||
} else if (AstParamTypeDType* modvarp = pinp->modPTypep()) {
|
||||
AstNodeDType* exprp = pinp->exprp()->castNodeDType();
|
||||
AstNodeDType* origp = modvarp->subDTypep();
|
||||
if (!exprp) {
|
||||
pinp->v3error("Parameter type pin value isn't a type: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||
} else if (!origp) {
|
||||
pinp->v3error("Parameter type variable isn't a type: Param "<<modvarp->prettyName());
|
||||
} else {
|
||||
UINFO(9,"Parameter type assignment expr="<<exprp<<" to "<<origp<<endl);
|
||||
if (origp && exprp->sameTree(origp)) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
|
||||
any_overrides = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pinp->v3error("Parameter not found in sub-module: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
IfaceRefRefs ifaceRefRefs;
|
||||
@@ -573,22 +620,12 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
|
||||
m_modNameMap.insert(make_pair(modp->name(), ModInfo(modp)));
|
||||
iter = m_modNameMap.find(newname);
|
||||
VarCloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
CloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
UINFO(4," De-parameterize to new: "<<modp<<endl);
|
||||
|
||||
// Grab all I/O so we can remap our pins later
|
||||
// Note we allow multiple users of a parameterized model, thus we need to stash this info.
|
||||
for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* varp = stmtp->castVar()) {
|
||||
if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) {
|
||||
// Cloning saved a pointer to the new node for us, so just follow that link.
|
||||
AstVar* oldvarp = varp->clonep()->castVar();
|
||||
//UINFO(8,"Clone list 0x"<<hex<<(uint32_t)oldvarp<<" -> 0x"<<(uint32_t)varp<<endl);
|
||||
clonemapp->insert(make_pair(oldvarp, varp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectPins(clonemapp, modp);
|
||||
// Relink parameter vars to the new module
|
||||
relinkPins(clonemapp, nodep->paramsp());
|
||||
|
||||
@@ -608,15 +645,26 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
// Assign parameters to the constants specified
|
||||
// DOES clone() so must be finished with module clonep() before here
|
||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
AstVar* modvarp = pinp->modVarp();
|
||||
if (modvarp && pinp->exprp()) {
|
||||
AstConst* constp = pinp->exprp()->castConst();
|
||||
// Remove any existing parameter
|
||||
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
|
||||
// Set this parameter to value requested by cell
|
||||
modvarp->valuep(constp->cloneTree(false));
|
||||
if (pinp->exprp()) {
|
||||
if (AstVar* modvarp = pinp->modVarp()) {
|
||||
AstConst* constp = pinp->exprp()->castConst();
|
||||
// Remove any existing parameter
|
||||
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
|
||||
// Set this parameter to value requested by cell
|
||||
modvarp->valuep(constp->cloneTree(false));
|
||||
}
|
||||
else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
|
||||
AstNodeDType* dtypep = pinp->exprp()->castNodeDType();
|
||||
if (!dtypep) pinp->v3fatalSrc("unlinked param dtype");
|
||||
if (modptp->childDTypep()) pushDeletep(modptp->childDTypep()->unlinkFrBack());
|
||||
// Set this parameter to value requested by cell
|
||||
modptp->childDTypep(dtypep->cloneTree(false));
|
||||
// Later V3LinkDot will convert the ParamDType to a Typedef
|
||||
// Not done here as may be localparams, etc, that also need conversion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
UINFO(4," De-parameterize to old: "<<modp<<endl);
|
||||
}
|
||||
@@ -626,7 +674,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
nodep->modName(newname);
|
||||
|
||||
// We need to relink the pins to the new module
|
||||
VarCloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
CloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
relinkPins(clonemapp, nodep->pinsp());
|
||||
UINFO(8," Done with "<<modp<<endl);
|
||||
} // if any_overrides
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ public:
|
||||
void verilatorCmtLintSave();
|
||||
void verilatorCmtLintRestore();
|
||||
void verilatorCmtBad(const char* text);
|
||||
double parseDouble(const char* text, size_t length);
|
||||
static double parseDouble(const char* text, size_t length, bool* successp = NULL);
|
||||
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
|
||||
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
|
||||
int lastVerilogState() const { return m_lastVerilogState; }
|
||||
|
||||
+89
-40
@@ -139,37 +139,34 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
UINFO(4, "Cloning "<<nodep->user2()<<" times: "<<nodep<<endl);
|
||||
|
||||
AstNode* lhsp = NULL;
|
||||
AstNode* rhsp = NULL;
|
||||
for (int i = 0; i < nodep->user2(); ++i) {
|
||||
// Clone the node and iterate over the clone
|
||||
m_vecIdx = -1;
|
||||
AstNodeUniop* clonep = nodep->cloneTree(false)->castNodeUniop();
|
||||
clonep->iterateChildren(*this);
|
||||
if (!lhsp) lhsp = clonep;
|
||||
else rhsp = clonep;
|
||||
if (lhsp && rhsp) {
|
||||
else {
|
||||
switch (nodep->type()) {
|
||||
case AstType::atREDOR:
|
||||
lhsp = new AstOr(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstOr(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
case AstType::atREDAND:
|
||||
lhsp = new AstAnd(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstAnd(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
case AstType::atREDXOR:
|
||||
lhsp = new AstXor(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstXor(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
case AstType::atREDXNOR:
|
||||
lhsp = new AstXnor(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstXnor(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
default:
|
||||
nodep->v3fatalSrc("Unsupported: Unary operation on multiple packed dimensions");
|
||||
break;
|
||||
}
|
||||
rhsp = NULL;
|
||||
}
|
||||
}
|
||||
nodep->addNextHere(lhsp);
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
nodep->replaceWith(lhsp);
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstRedOr* nodep, AstNUser*) {
|
||||
cloneUniop(nodep);
|
||||
@@ -421,17 +418,19 @@ class SliceVisitor : public AstNVisitor {
|
||||
if (AstInitArray* initp = nodep->rhsp()->castInitArray()) {
|
||||
//if (debug()>=9) nodep->dumpTree(cout, "-InitArrayIn: ");
|
||||
AstNode* newp = NULL;
|
||||
int index = 0;
|
||||
while (AstNode* subp=initp->initsp()) {
|
||||
for (int pos = 0; AstNode* itemp=initp->initsp(); ++pos) {
|
||||
int index = initp->posIndex(pos);
|
||||
AstNode* lhsp = new AstArraySel(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
index++);
|
||||
newp = AstNode::addNext(newp, nodep->cloneType(lhsp, subp->unlinkFrBack()));
|
||||
index);
|
||||
newp = AstNode::addNext(newp, nodep->cloneType(lhsp, itemp->unlinkFrBack()));
|
||||
// Deleted from list of items without correcting posIndex, but that's ok as about
|
||||
// to delete the entire InitArray
|
||||
}
|
||||
//if (debug()>=9) newp->dumpTreeAndNext(cout, "-InitArrayOut: ");
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
return; // WIll iterate in a moment
|
||||
return; // Will iterate in a moment
|
||||
}
|
||||
// Hasn't been searched for implicit slices yet
|
||||
findImplicit(nodep);
|
||||
@@ -439,44 +438,94 @@ class SliceVisitor : public AstNVisitor {
|
||||
}
|
||||
|
||||
void expandUniOp(AstNodeUniop* nodep) {
|
||||
nodep->user1(true);
|
||||
unsigned dim = 0;
|
||||
if (AstArraySel* selp = nodep->lhsp()->castArraySel()) {
|
||||
// We have explicit dimensions, either packed or unpacked
|
||||
dim = explicitDimensions(selp);
|
||||
}
|
||||
if (dim == 0 && !nodep->lhsp()->castVarRef()) {
|
||||
// No ArraySel nor VarRef, not something we can expand
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
||||
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
|
||||
if ((int)(dim - varDim.second) < 0) {
|
||||
// Unpacked dimensions are referenced first, make sure we have them all
|
||||
nodep->v3error("Unary operator used across unpacked dimensions");
|
||||
if (!nodep->user1()) {
|
||||
nodep->user1(true);
|
||||
unsigned dim = 0;
|
||||
if (AstArraySel* selp = nodep->lhsp()->castArraySel()) {
|
||||
// We have explicit dimensions, either packed or unpacked
|
||||
dim = explicitDimensions(selp);
|
||||
}
|
||||
if (dim == 0 && !nodep->lhsp()->castVarRef()) {
|
||||
// No ArraySel nor VarRef, not something we can expand
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
||||
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
|
||||
if ((int)(dim - varDim.second) < 0) {
|
||||
// Unpacked dimensions are referenced first, make sure we have them all
|
||||
nodep->v3error("Unary operator used across unpacked dimensions");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedOr* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
virtual void visit(AstRedAnd* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
virtual void visit(AstRedXnor* nodep, AstNUser*) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
|
||||
void expandBiOp(AstNodeBiop* nodep) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
nodep->user1(true);
|
||||
// If it's a unpacked array, blow it up into comparing each element
|
||||
AstNodeDType* fromDtp = nodep->lhsp()->dtypep()->skipRefp();
|
||||
UINFO(9, " Bi-Eq/Neq expansion "<<nodep<<endl);
|
||||
if (AstUnpackArrayDType* adtypep = fromDtp->castUnpackArrayDType()) {
|
||||
AstNodeBiop* logp = NULL;
|
||||
for (int index = adtypep->rangep()->lsbConst();
|
||||
index <= adtypep->rangep()->msbConst(); ++index) {
|
||||
// EQ(a,b) -> LOGAND(EQ(ARRAYSEL(a,0), ARRAYSEL(b,0)), ...[1])
|
||||
AstNodeBiop* clonep = nodep->cloneType
|
||||
(new AstArraySel(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
index),
|
||||
new AstArraySel(nodep->fileline(),
|
||||
nodep->rhsp()->cloneTree(false),
|
||||
index))->castNodeBiop();
|
||||
if (!logp) logp = clonep;
|
||||
else {
|
||||
switch (nodep->type()) {
|
||||
case AstType::atEQ: // FALLTHRU
|
||||
case AstType::atEQCASE:
|
||||
logp = new AstLogAnd(nodep->fileline(), logp, clonep);
|
||||
break;
|
||||
case AstType::atNEQ: // FALLTHRU
|
||||
case AstType::atNEQCASE:
|
||||
logp = new AstLogOr(nodep->fileline(), logp, clonep);
|
||||
break;
|
||||
default:
|
||||
nodep->v3fatalSrc("Unknown node type processing array slice");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!logp) nodep->v3fatalSrc("Unpacked array with empty indices range");
|
||||
nodep->replaceWith(logp);
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
nodep = logp;
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEq* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
virtual void visit(AstNeq* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
virtual void visit(AstEqCase* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
virtual void visit(AstNeqCase* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
|
||||
+2
-2
@@ -328,7 +328,7 @@ private:
|
||||
setp = new AstConst (outnump->fileline(), *outnump);
|
||||
}
|
||||
// Note InitArray requires us to have the values in inValue order
|
||||
m_tableVarps[outnum]->varp()->valuep()->castInitArray()->addInitsp(setp);
|
||||
m_tableVarps[outnum]->varp()->valuep()->castInitArray()->addValuep(setp);
|
||||
outnum++;
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ private:
|
||||
if (inValue != inValueNextInitArray++)
|
||||
nodep->v3fatalSrc("InitArray requires us to have the values in inValue order");
|
||||
AstNode* setp = new AstConst (nodep->fileline(), outputChgMask);
|
||||
chgVscp->varp()->valuep()->castInitArray()->addInitsp(setp);
|
||||
chgVscp->varp()->valuep()->castInitArray()->addValuep(setp);
|
||||
}
|
||||
} // each value
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Generate AstCReset nodes.
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2016 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.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
// V3VarReset's Transformations:
|
||||
// Iterates over all modules and creates a _ctor_var_reset AstCFunc
|
||||
// For each variable that needs reset, add a AstCReset node.
|
||||
// This transformation honors outputSplitCFuncs.
|
||||
//*************************************************************************
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3VarResets.h"
|
||||
|
||||
class V3VarReset {
|
||||
private:
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_tlFuncp; // Top level function being built
|
||||
AstCFunc* m_funcp; // Current function
|
||||
int m_numStmts; // Number of statements output
|
||||
int m_funcNum; // Function number being built
|
||||
|
||||
void initializeVar(AstVar* nodep) {
|
||||
if (v3Global.opt.outputSplitCFuncs()
|
||||
&& v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||
m_funcp = NULL;
|
||||
}
|
||||
if (!m_funcp) {
|
||||
m_funcp = new AstCFunc(m_modp->fileline(), "_ctor_var_reset_" + cvtToStr(++m_funcNum), NULL, "void");
|
||||
m_funcp->isStatic(false);
|
||||
m_funcp->declPrivate(true);
|
||||
m_funcp->slow(true);
|
||||
m_modp->addStmtp(m_funcp);
|
||||
|
||||
// Add a top call to it
|
||||
AstCCall* callp = new AstCCall(m_modp->fileline(), m_funcp);
|
||||
|
||||
m_tlFuncp->addStmtsp(callp);
|
||||
m_numStmts = 0;
|
||||
}
|
||||
m_funcp->addStmtsp(new AstCReset(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true)));
|
||||
m_numStmts += 1;
|
||||
}
|
||||
|
||||
public:
|
||||
V3VarReset(AstNodeModule* nodep) {
|
||||
m_modp = nodep;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
m_tlFuncp = new AstCFunc(nodep->fileline(), "_ctor_var_reset", NULL, "void");
|
||||
m_tlFuncp->declPrivate(true);
|
||||
m_tlFuncp->isStatic(false);
|
||||
m_tlFuncp->slow(true);
|
||||
m_funcp = m_tlFuncp;
|
||||
m_modp->addStmtp(m_tlFuncp);
|
||||
for (AstNode* np = m_modp->stmtsp(); np; np = np->nextp()) {
|
||||
AstVar* varp = np->castVar();
|
||||
if (varp) initializeVar(varp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
void V3VarResets::emitResets() {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) {
|
||||
// Process each module in turn
|
||||
V3VarReset v(nodep);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Emit C++ code for module tree
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2016 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.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3VARRESETS_H_
|
||||
#define _V3VARRESETS_H_ 1
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3VarResets {
|
||||
public:
|
||||
static void emitResets();
|
||||
};
|
||||
|
||||
|
||||
#endif // Guard
|
||||
+62
-22
@@ -151,6 +151,26 @@ ostream& operator<<(ostream& str, const WidthVP* vup) {
|
||||
|
||||
//######################################################################
|
||||
|
||||
class WidthClearVisitor {
|
||||
// Rather than a AstNVisitor, can just quickly touch every node
|
||||
void clearWidthRecurse(AstNode* nodep) {
|
||||
nodep->didWidth(false);
|
||||
if (nodep->op1p()) clearWidthRecurse(nodep->op1p());
|
||||
if (nodep->op2p()) clearWidthRecurse(nodep->op2p());
|
||||
if (nodep->op3p()) clearWidthRecurse(nodep->op3p());
|
||||
if (nodep->op4p()) clearWidthRecurse(nodep->op4p());
|
||||
if (nodep->nextp()) clearWidthRecurse(nodep->nextp());
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit WidthClearVisitor(AstNetlist* nodep) {
|
||||
clearWidthRecurse(nodep);
|
||||
}
|
||||
virtual ~WidthClearVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class WidthVisitor : public AstNVisitor {
|
||||
private:
|
||||
// TYPES
|
||||
@@ -913,6 +933,9 @@ private:
|
||||
// calculation would return identical values. Therefore we can directly replace the width
|
||||
nodep->widthForce(nodep->rangep()->elementsConst(), nodep->rangep()->elementsConst());
|
||||
}
|
||||
else if (nodep->isRanged()) {
|
||||
nodep->widthForce(nodep->nrange().elements(), nodep->nrange().elements());
|
||||
}
|
||||
else if (nodep->implicit()) {
|
||||
// Parameters may notice implicitness and change to different dtype
|
||||
nodep->widthForce(1,1);
|
||||
@@ -951,6 +974,13 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep()));
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||
if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep));
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep()));
|
||||
nodep->widthFromSub(nodep->subDTypep());
|
||||
}
|
||||
virtual void visit(AstCastParse* nodep, AstNUser* vup) {
|
||||
// nodep->dtp could be data type, or a primary_constant
|
||||
// Don't iterate lhsp, will deal with that once convert the type
|
||||
@@ -1157,7 +1187,7 @@ private:
|
||||
// Note genvar's are also entered as integers
|
||||
nodep->dtypeFrom(nodep->varp());
|
||||
if (nodep->backp()->castNodeAssign() && nodep->lvalue()) { // On LHS
|
||||
if (!nodep->widthMin()) v3fatalSrc("LHS var should be size complete");
|
||||
if (!nodep->widthMin()) nodep->v3fatalSrc("LHS var should be size complete");
|
||||
}
|
||||
//if (debug()>=9) nodep->dumpTree(cout," VRout ");
|
||||
if (nodep->lvalue() && nodep->varp()->isConst()
|
||||
@@ -1463,6 +1493,7 @@ private:
|
||||
nodep->v3error("Unsupported: Arguments passed to enum.next method");
|
||||
}
|
||||
// Need a runtime lookup table. Yuk.
|
||||
// Most enums unless overridden are 32 bits, so we size array based on max enum value used.
|
||||
// Ideally we would have a fast algorithm when a number is
|
||||
// of small width and complete and so can use an array, and
|
||||
// a map for when the value is many bits and sparse.
|
||||
@@ -1473,15 +1504,20 @@ private:
|
||||
if (!vconstp) nodep->v3fatalSrc("Enum item without constified value");
|
||||
if (vconstp->toUQuad() >= msbdim) msbdim = vconstp->toUQuad();
|
||||
}
|
||||
if (adtypep->itemsp()->width() > 64 || msbdim >= 1024) {
|
||||
if (adtypep->itemsp()->width() > 64 || msbdim >= (1<<16)) {
|
||||
nodep->v3error("Unsupported; enum next/prev method on enum with > 10 bits");
|
||||
return;
|
||||
}
|
||||
}
|
||||
AstVar* varp = enumVarp(adtypep, attrType, msbdim);
|
||||
int selwidth = V3Number::log2b(msbdim)+1; // Width to address a bit
|
||||
AstVar* varp = enumVarp(adtypep, attrType, (VL_ULL(1)<<selwidth)-1);
|
||||
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
|
||||
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, nodep->fromp()->unlinkFrBack());
|
||||
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp,
|
||||
// Select in case widths are off due to msblen!=width
|
||||
new AstSel(nodep->fileline(),
|
||||
nodep->fromp()->unlinkFrBack(),
|
||||
0, selwidth));
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->v3error("Unknown built-in enum method '"<<nodep->fromp()->prettyTypeName()<<"'");
|
||||
@@ -1667,11 +1703,13 @@ private:
|
||||
}
|
||||
if (arrayp->castUnpackArrayDType()) {
|
||||
if (!newp) {
|
||||
newp = new AstInitArray(nodep->fileline(), arrayp, valuep);
|
||||
AstInitArray* newap = new AstInitArray(nodep->fileline(), arrayp, NULL);
|
||||
newap->addValuep(valuep);
|
||||
newp = newap;
|
||||
} else {
|
||||
// We iterate hi()..lo() as that is what packed needs,
|
||||
// but INITARRAY needs lo() first
|
||||
newp->castInitArray()->initsp()->addHereThisAsNext(valuep);
|
||||
newp->castInitArray()->addFrontValuep(valuep);
|
||||
}
|
||||
} else { // Packed. Convert to concat for now.
|
||||
if (!newp) newp = valuep;
|
||||
@@ -2724,6 +2762,7 @@ private:
|
||||
if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
|
||||
if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
|
||||
if (expWidthMin==0) expWidthMin = expWidth;
|
||||
if (nodep->dtypep()->width() == expWidth) return false;
|
||||
if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true;
|
||||
if (!nodep->dtypep()->widthSized() && nodep->widthMin() > expWidthMin) return true;
|
||||
return false;
|
||||
@@ -3372,9 +3411,9 @@ private:
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
|
||||
// Element 0 is a non-index and has speced values
|
||||
initp->addInitsp(dimensionValue(nodep, attrType, 0));
|
||||
initp->addValuep(dimensionValue(nodep, attrType, 0));
|
||||
for (unsigned i=1; i<msbdim+1; ++i) {
|
||||
initp->addInitsp(dimensionValue(nodep, attrType, i));
|
||||
initp->addValuep(dimensionValue(nodep, attrType, i));
|
||||
}
|
||||
varp->iterate(*this); // May have already done $unit so must do this var
|
||||
m_tableMap.insert(make_pair(make_pair(nodep,attrType), varp));
|
||||
@@ -3382,7 +3421,7 @@ private:
|
||||
}
|
||||
AstVar* enumVarp(AstEnumDType* nodep, AstAttrType attrType, uint32_t msbdim) {
|
||||
// Return a variable table which has specified dimension properties for this variable
|
||||
TableMap::iterator pos = m_tableMap.find(make_pair(nodep,attrType));
|
||||
TableMap::iterator pos = m_tableMap.find(make_pair(nodep, attrType));
|
||||
if (pos != m_tableMap.end()) {
|
||||
return pos->second;
|
||||
}
|
||||
@@ -3391,7 +3430,7 @@ private:
|
||||
if (attrType == AstAttrType::ENUM_NAME) {
|
||||
basep = nodep->findStringDType();
|
||||
} else {
|
||||
basep = nodep->findSigned32DType();
|
||||
basep = nodep->dtypep();
|
||||
}
|
||||
AstNodeArrayDType* vardtypep = new AstUnpackArrayDType(nodep->fileline(),
|
||||
basep,
|
||||
@@ -3407,6 +3446,16 @@ private:
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
|
||||
|
||||
// Default for all unspecified values
|
||||
if (attrType == AstAttrType::ENUM_NAME) {
|
||||
initp->defaultp(new AstConst(nodep->fileline(), AstConst::String(), ""));
|
||||
} else if (attrType == AstAttrType::ENUM_NEXT
|
||||
|| attrType == AstAttrType::ENUM_PREV) {
|
||||
initp->defaultp(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), nodep->width(), 0)));
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
|
||||
// Find valid values and populate
|
||||
if (!nodep->itemsp()) nodep->v3fatalSrc("enum without items");
|
||||
vector<AstNode*> values;
|
||||
@@ -3436,20 +3485,10 @@ private:
|
||||
itemp = nextp;
|
||||
}
|
||||
}
|
||||
// Fill in all unspecified values and add to table
|
||||
// Add all specified values to table
|
||||
for (unsigned i=0; i<(msbdim+1); ++i) {
|
||||
AstNode* valp = values[i];
|
||||
if (!valp) {
|
||||
if (attrType == AstAttrType::ENUM_NAME) {
|
||||
valp = new AstConst(nodep->fileline(), AstConst::String(), "");
|
||||
} else if (attrType == AstAttrType::ENUM_NEXT
|
||||
|| attrType == AstAttrType::ENUM_PREV) {
|
||||
valp = new AstConst(nodep->fileline(), V3Number(nodep->fileline(), nodep->width(), 0));
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
}
|
||||
initp->addInitsp(valp);
|
||||
if (valp) initp->addIndexValuep(i, valp);
|
||||
}
|
||||
varp->iterate(*this); // May have already done $unit so must do this var
|
||||
m_tableMap.insert(make_pair(make_pair(nodep,attrType), varp));
|
||||
@@ -3528,6 +3567,7 @@ int V3Width::debug() {
|
||||
void V3Width::width(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
// We should do it in bottom-up module order, but it works in any order.
|
||||
WidthClearVisitor cvisitor (nodep);
|
||||
WidthVisitor visitor (false, false);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
WidthRemoveVisitor rvisitor;
|
||||
|
||||
@@ -128,9 +128,17 @@ private:
|
||||
visitIterateNodeDType(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
visitIterateNodeDType(nodep);
|
||||
nodep->clearCache();
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
visitIterateNodeDType(nodep);
|
||||
// Move to type table as all dtype pointers must resolve there
|
||||
nodep->unlinkFrBack(); // Make non-child
|
||||
v3Global.rootp()->typeTablep()->addTypesp(nodep);
|
||||
}
|
||||
void visitIterateNodeDType(AstNodeDType* nodep) {
|
||||
// Rather than use dtypeChg which may make new nodes, we simply edit in place,
|
||||
// as we don't need to preserve any widthMin's, and every dtype with the same width
|
||||
|
||||
+11
-4
@@ -39,6 +39,7 @@
|
||||
#include "V3Const.h"
|
||||
#include "V3Coverage.h"
|
||||
#include "V3CoverageJoin.h"
|
||||
#include "V3VarResets.h"
|
||||
#include "V3Dead.h"
|
||||
#include "V3Delayed.h"
|
||||
#include "V3Depth.h"
|
||||
@@ -160,6 +161,8 @@ void process () {
|
||||
// Cross-link dotted hierarchical references
|
||||
V3LinkDot::linkDotPrimary(v3Global.rootp());
|
||||
v3Global.checkTree(); // Force a check, as link is most likely place for problems
|
||||
// Check if all parameters have been found
|
||||
v3Global.opt.checkParameters();
|
||||
// Correct state we couldn't know at parse time, repair SEL's
|
||||
V3LinkResolve::linkResolve(v3Global.rootp());
|
||||
// Set Lvalue's in variable refs
|
||||
@@ -282,7 +285,7 @@ void process () {
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Cleanup
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
V3Dead::deadifyDTypesScoped(v3Global.rootp());
|
||||
v3Global.checkTree();
|
||||
|
||||
// Convert case statements to if() blocks. Must be after V3Unknown
|
||||
@@ -317,7 +320,7 @@ void process () {
|
||||
|
||||
// Cleanup
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
V3Dead::deadifyDTypesScoped(v3Global.rootp());
|
||||
v3Global.checkTree();
|
||||
|
||||
// Detect clock enables and mode into sensitives, and split always based on clocks
|
||||
@@ -357,7 +360,7 @@ void process () {
|
||||
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAllScoped(v3Global.rootp());
|
||||
|
||||
// Clock domain crossing analysis
|
||||
if (v3Global.opt.cdc()) {
|
||||
@@ -402,7 +405,7 @@ void process () {
|
||||
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAllScoped(v3Global.rootp());
|
||||
|
||||
// Detect change loop
|
||||
V3Changed::changedAll(v3Global.rootp());
|
||||
@@ -495,6 +498,10 @@ void process () {
|
||||
}
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
if (!v3Global.opt.lintOnly()
|
||||
&& !v3Global.opt.xmlOnly()) {
|
||||
V3VarResets::emitResets();
|
||||
}
|
||||
|
||||
// Output the text
|
||||
if (!v3Global.opt.lintOnly()
|
||||
|
||||
@@ -19,6 +19,7 @@ my $Opt_Prefix = $ARGV[0] or die "%Error: No prefix specified,";
|
||||
|
||||
foreach my $line (<STDIN>) {
|
||||
# Fix flex 2.6.0 warning
|
||||
$line =~ s/ > YY_CURRENT_BUFFER_LVALUE->yy_buf_size/ > (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size/;
|
||||
$line =~ s/ number_to_move == YY_MORE_ADJ / (int)number_to_move == (int)YY_MORE_ADJ /;
|
||||
# Fix flex 2.5.4 namespace omission
|
||||
$line =~ s/^class istream;/\#include <iostream>\nusing namespace std;\n/;
|
||||
|
||||
+7
-3
@@ -459,6 +459,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"struct" { FL; return ySTRUCT; }
|
||||
"timeprecision" { FL; return yTIMEPRECISION; }
|
||||
"timeunit" { FL; return yTIMEUNIT; }
|
||||
"type" { FL; return yTYPE; }
|
||||
"typedef" { FL; return yTYPEDEF; }
|
||||
"union" { FL; return yUNION; }
|
||||
"unique" { FL; return yUNIQUE; }
|
||||
@@ -508,7 +509,6 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"tagged" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"this" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"throughout" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"type" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"virtual" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"wait_order" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"wildcard" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
@@ -975,9 +975,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
%%
|
||||
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
|
||||
|
||||
double V3ParseImp::parseDouble(const char* textp, size_t length) {
|
||||
double V3ParseImp::parseDouble(const char* textp, size_t length, bool* successp) {
|
||||
char* strgp = new char[length+1];
|
||||
char* dp=strgp;
|
||||
if (successp) *successp = true;
|
||||
for (const char* sp=textp; sp<(textp+length); ++sp) {
|
||||
if (*sp != '_') *dp++ = *sp;
|
||||
}
|
||||
@@ -985,7 +986,10 @@ double V3ParseImp::parseDouble(const char* textp, size_t length) {
|
||||
char* endp = strgp;
|
||||
double d = strtod(strgp, &endp);
|
||||
size_t parsed_len = endp-strgp;
|
||||
if (parsed_len != strlen(strgp)) { yyerrorf("Syntax error parsing real: %s",strgp); }
|
||||
if (parsed_len != strlen(strgp)) {
|
||||
if (successp) *successp = false;
|
||||
else yyerrorf("Syntax error parsing real: %s",strgp);
|
||||
}
|
||||
delete[] strgp;
|
||||
return d;
|
||||
}
|
||||
|
||||
+55
-12
@@ -421,6 +421,7 @@ class AstSenTree;
|
||||
%token<fl> yTRI0 "tri0"
|
||||
%token<fl> yTRI1 "tri1"
|
||||
%token<fl> yTRUE "true"
|
||||
%token<fl> yTYPE "type"
|
||||
%token<fl> yTYPEDEF "typedef"
|
||||
%token<fl> yUNION "union"
|
||||
%token<fl> yUNIQUE "unique"
|
||||
@@ -805,7 +806,7 @@ udpFront<modulep>:
|
||||
|
||||
parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
|
||||
/* empty */ { $$ = NULL; }
|
||||
| '#' '(' cellpinList ')' { $$ = $3; }
|
||||
| '#' '(' cellparamList ')' { $$ = $3; }
|
||||
// // Parentheses are optional around a single parameter
|
||||
| '#' yaINTNUM { $$ = new AstPin($1,1,"",new AstConst($1,*$2)); }
|
||||
| '#' yaFLOATNUM { $$ = new AstPin($1,1,"",new AstConst($1,AstConst::Unsized32(),(int)(($2<0)?($2-0.5):($2+0.5)))); }
|
||||
@@ -1123,6 +1124,7 @@ genvar_identifierDecl<varp>: // IEEE: genvar_identifier (for declaration)
|
||||
|
||||
local_parameter_declaration<nodep>: // IEEE: local_parameter_declaration
|
||||
// // See notes in parameter_declaration
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
local_parameter_declarationFront list_of_param_assignments { $$ = $2; }
|
||||
;
|
||||
|
||||
@@ -1131,30 +1133,33 @@ parameter_declaration<nodep>: // IEEE: parameter_declaration
|
||||
// // Instead of list_of_type_assignments
|
||||
// // we use list_of_param_assignments because for port handling
|
||||
// // it already must accept types, so simpler to have code only one place
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
parameter_declarationFront list_of_param_assignments { $$ = $2; }
|
||||
;
|
||||
|
||||
local_parameter_declarationFront: // IEEE: local_parameter_declaration w/o assignment
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
varLParamReset implicit_typeE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
//UNSUP varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE(new AstParseTypeDType($2)); }
|
||||
;
|
||||
|
||||
parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); }
|
||||
;
|
||||
|
||||
parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assignment
|
||||
// // IEEE: parameter_declaration (minus assignment)
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($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); }
|
||||
| yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($1)); }
|
||||
;
|
||||
|
||||
net_declaration<nodep>: // IEEE: net_declaration - excluding implict
|
||||
@@ -1988,9 +1993,9 @@ packed_dimension<rangep>: // ==IEEE: packed_dimension
|
||||
param_assignment<varp>: // ==IEEE: param_assignment
|
||||
// // IEEE: constant_param_expression
|
||||
// // constant_param_expression: '$' is in expr
|
||||
id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' expr
|
||||
// // note exptOrDataType being a data_type is only for yPARAMETER yTYPE
|
||||
id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' exprOrDataType
|
||||
/**/ { $$ = VARDONEA($<fl>1,*$1, $2, $3); $$->valuep($5); }
|
||||
//UNSUP: exprOrDataType instead of expr
|
||||
;
|
||||
|
||||
list_of_param_assignments<varp>: // ==IEEE: list_of_param_assignments
|
||||
@@ -2067,16 +2072,25 @@ instRangeE<rangep>:
|
||||
| '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
|
||||
;
|
||||
|
||||
cellparamList<pinp>:
|
||||
{VARRESET_LIST(UNKNOWN);} cellparamItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
|
||||
;
|
||||
|
||||
cellpinList<pinp>:
|
||||
{VARRESET_LIST(UNKNOWN);} cellpinItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
|
||||
;
|
||||
|
||||
cellpinItList<pinp>: // IEEE: list_of_port_connections + list_of_parameter_assignmente
|
||||
cellparamItList<pinp>: // IEEE: list_of_parameter_assignmente
|
||||
cellparamItemE { $$ = $1; }
|
||||
| cellparamItList ',' cellparamItemE { $$ = $1->addNextNull($3)->castPin(); }
|
||||
;
|
||||
|
||||
cellpinItList<pinp>: // IEEE: list_of_port_connections
|
||||
cellpinItemE { $$ = $1; }
|
||||
| cellpinItList ',' cellpinItemE { $$ = $1->addNextNull($3)->castPin(); }
|
||||
;
|
||||
|
||||
cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment + empty
|
||||
cellparamItemE<pinp>: // IEEE: named_parameter_assignment + empty
|
||||
// Note empty can match either () or (,); V3LinkCells cleans up ()
|
||||
/* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(),PINNUMINC(),"",NULL); }
|
||||
| yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); }
|
||||
@@ -2088,9 +2102,26 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
|
||||
//UNSUP '.' idAny '(' expr ':' expr ')' { }
|
||||
//UNSUP '.' idAny '(' expr ':' expr ':' expr ')' { }
|
||||
// // For parameters
|
||||
//UNSUP '.' idAny '(' data_type ')' { PINDONE($1,$2,$4); GRAMMARP->pinNumInc(); }
|
||||
| '.' idAny '(' data_type ')' { $$ = new AstPin($1,PINNUMINC(),*$2,$4); }
|
||||
// // For parameters
|
||||
//UNSUP data_type { PINDONE($1->fileline(),"",$1); GRAMMARP->pinNumInc(); }
|
||||
| data_type { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//
|
||||
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//UNSUP expr ':' expr { }
|
||||
//UNSUP expr ':' expr ':' expr { }
|
||||
;
|
||||
|
||||
cellpinItemE<pinp>: // IEEE: named_port_connection + empty
|
||||
// Note empty can match either () or (,); V3LinkCells cleans up ()
|
||||
/* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(),PINNUMINC(),"",NULL); }
|
||||
| yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); }
|
||||
| '.' idSVKwd { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
|
||||
| '.' idAny { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
|
||||
| '.' idAny '(' ')' { $$ = new AstPin($1,PINNUMINC(),*$2,NULL); }
|
||||
// // mintypmax is expanded here, as it might be a UDP or gate primitive
|
||||
| '.' idAny '(' expr ')' { $$ = new AstPin($1,PINNUMINC(),*$2,$4); }
|
||||
//UNSUP '.' idAny '(' expr ':' expr ')' { }
|
||||
//UNSUP '.' idAny '(' expr ':' expr ':' expr ')' { }
|
||||
//
|
||||
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//UNSUP expr ':' expr { }
|
||||
@@ -2674,6 +2705,12 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
||||
;
|
||||
|
||||
exprOrDataType<nodep>: // expr | data_type: combined to prevent conflicts
|
||||
expr { $$ = $1; }
|
||||
// // data_type includes id that overlaps expr, so special flavor
|
||||
| data_type { $$ = $1; }
|
||||
;
|
||||
|
||||
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
|
||||
argsDottedList { $$ = $1; }
|
||||
| argsExprListE { if ($1->castArg() && $1->castArg()->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()'
|
||||
@@ -3765,6 +3802,12 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
|
||||
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) {
|
||||
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1));
|
||||
}
|
||||
if (dtypep->castParseTypeDType()) {
|
||||
// Parser needs to know what is a type
|
||||
AstNode* newp = new AstTypedefFwd(fileline, name);
|
||||
nodep->addNext(newp);
|
||||
SYMP->reinsert(newp);
|
||||
}
|
||||
// Don't set dtypep in the ranging;
|
||||
// We need to autosize parameters and integers separately
|
||||
//
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// please note it here, otherwise:**
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by ____YOUR_NAME_HERE____.
|
||||
// without warranty, 2016 by ____YOUR_NAME_HERE____.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
||||
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,58 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Andrew Bardsley.
|
||||
|
||||
// bug1071
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [3:0] array_1 [2:0];
|
||||
reg [3:0] array_2 [2:0];
|
||||
reg [3:0] array_3 [3:1];
|
||||
|
||||
reg [3:0] elem;
|
||||
|
||||
reg array_1_ne_array_2;
|
||||
reg array_1_eq_array_2;
|
||||
reg array_1_ne_array_3;
|
||||
reg array_1_eq_array_3;
|
||||
|
||||
initial begin
|
||||
array_1[0] = 4'b1000;
|
||||
array_1[1] = 4'b1000;
|
||||
array_1[2] = 4'b1000;
|
||||
|
||||
array_2[0] = 4'b1000;
|
||||
array_2[1] = 4'b1000;
|
||||
array_2[2] = 4'b1000;
|
||||
|
||||
array_3[1] = 4'b1000;
|
||||
array_3[2] = 4'b0100;
|
||||
array_3[3] = 4'b0100;
|
||||
|
||||
// Comparisons only compare elements 0
|
||||
array_1_ne_array_2 = array_1 != array_2; // 0
|
||||
array_1_eq_array_2 = array_1 == array_2; // 0
|
||||
array_1_ne_array_3 = array_1 != array_3; // 1
|
||||
array_1_eq_array_3 = array_1 == array_3; // 1
|
||||
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("array_1_ne_array2==%0d\n", array_1_ne_array_2);
|
||||
$write("array_1_ne_array3==%0d\n", array_1_ne_array_3);
|
||||
`endif
|
||||
|
||||
if (array_1_ne_array_2 !== 0) $stop;
|
||||
if (array_1_eq_array_2 !== 1) $stop;
|
||||
if (array_1_ne_array_3 !== 1) $stop;
|
||||
if (array_1_eq_array_3 !== 0) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -19,7 +19,7 @@ execute (
|
||||
check_finished=>0,
|
||||
fails=> $Self->{vlt},
|
||||
expect=>
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.v: synthesis full_case'
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.t: synthesis full_case'
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -19,7 +19,7 @@ execute (
|
||||
check_finished=>0,
|
||||
fails => $Self->{v3},
|
||||
expect=>
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.v: synthesis parallel_case'
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.t: synthesis parallel_case'
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -12,11 +12,11 @@ compile (
|
||||
verilator_make_gcc => 0,
|
||||
fails => 1,
|
||||
expect=>
|
||||
'%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst2_bad_n
|
||||
'%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst2_bad_n
|
||||
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
|
||||
%Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6a_bad_n
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6b_bad_n
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst6a_bad_n
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst6b_bad_n
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
input toggle;
|
||||
always @ (posedge clk) begin
|
||||
%000002 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.a*",2)
|
||||
// CHECK_COVER(-1,"top.t.a*",2)
|
||||
// t.a1 and t.a2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -100,11 +100,11 @@
|
||||
|
||||
always @ (posedge clk) begin
|
||||
%000000 if (0) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",0)
|
||||
// CHECK_COVER(-1,"top.t.b*",0)
|
||||
// Make sure that we don't optimize away zero buckets
|
||||
end
|
||||
%000002 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",2)
|
||||
// CHECK_COVER(-1,"top.t.b*",2)
|
||||
// t.b1 and t.b2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -133,10 +133,10 @@
|
||||
input external;
|
||||
begin
|
||||
%000001 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
end
|
||||
%000001 if (external) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
$write("[%0t] Got external pulse\n", $time);
|
||||
end
|
||||
end
|
||||
@@ -161,7 +161,7 @@
|
||||
// verilator coverage_on
|
||||
always @ (posedge clk) begin
|
||||
%000001 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.o1",1)
|
||||
// CHECK_COVER(-1,"top.t.o1",1)
|
||||
// because under coverage_module_off
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,7 +76,7 @@ module alpha (/*AUTOARG*/
|
||||
input toggle;
|
||||
always @ (posedge clk) begin
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.a*",2)
|
||||
// CHECK_COVER(-1,"top.t.a*",2)
|
||||
// t.a1 and t.a2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -99,11 +99,11 @@ module beta (/*AUTOARG*/
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (0) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",0)
|
||||
// CHECK_COVER(-1,"top.t.b*",0)
|
||||
// Make sure that we don't optimize away zero buckets
|
||||
end
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",2)
|
||||
// CHECK_COVER(-1,"top.t.b*",2)
|
||||
// t.b1 and t.b2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -132,10 +132,10 @@ module tsk (/*AUTOARG*/
|
||||
input external;
|
||||
begin
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
end
|
||||
if (external) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
$write("[%0t] Got external pulse\n", $time);
|
||||
end
|
||||
end
|
||||
@@ -160,7 +160,7 @@ module off (/*AUTOARG*/
|
||||
// verilator coverage_on
|
||||
always @ (posedge clk) begin
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.o1",1)
|
||||
// CHECK_COVER(-1,"top.t.o1",1)
|
||||
// because under coverage_module_off
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ execute (
|
||||
# Allow old Perl format dump, or new binary dump
|
||||
# Check that the hierarchy doesn't include __PVT__
|
||||
# Otherwise our coverage reports would look really ugly
|
||||
file_grep ($Self->{coverage_filename}, qr/(top\.v\.sub.*.cyc_eq_5)/)
|
||||
file_grep ($Self->{coverage_filename}, qr/(top\.t\.sub.*.cyc_eq_5)/)
|
||||
if $Self->{vlt};
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -95,25 +95,25 @@ module alpha (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
input toggle;
|
||||
// CHECK_COVER(-1,"top.v.a*",4)
|
||||
// CHECK_COVER(-1,"top.t.a*",4)
|
||||
// 2 edges * (t.a1 and t.a2)
|
||||
|
||||
input [7:0] cyc_copy;
|
||||
// CHECK_COVER(-1,"top.v.a*","cyc_copy[0]",22)
|
||||
// CHECK_COVER(-2,"top.v.a*","cyc_copy[1]",10)
|
||||
// CHECK_COVER(-3,"top.v.a*","cyc_copy[2]",4)
|
||||
// CHECK_COVER(-4,"top.v.a*","cyc_copy[3]",2)
|
||||
// CHECK_COVER(-5,"top.v.a*","cyc_copy[4]",0)
|
||||
// CHECK_COVER(-6,"top.v.a*","cyc_copy[5]",0)
|
||||
// CHECK_COVER(-7,"top.v.a*","cyc_copy[6]",0)
|
||||
// CHECK_COVER(-8,"top.v.a*","cyc_copy[7]",0)
|
||||
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
|
||||
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
|
||||
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
|
||||
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
|
||||
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
|
||||
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
|
||||
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
|
||||
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
|
||||
|
||||
reg toggle_internal;
|
||||
// CHECK_COVER(-1,"top.v.a*",4)
|
||||
// CHECK_COVER(-1,"top.t.a*",4)
|
||||
// 2 edges * (t.a1 and t.a2)
|
||||
|
||||
output reg toggle_up;
|
||||
// CHECK_COVER(-1,"top.v.a*",4)
|
||||
// CHECK_COVER(-1,"top.t.a*",4)
|
||||
// 2 edges * (t.a1 and t.a2)
|
||||
|
||||
always @ (posedge clk) begin
|
||||
@@ -130,7 +130,7 @@ module beta (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
input toggle_up;
|
||||
// CHECK_COVER(-1,"top.v.b1","toggle_up",2)
|
||||
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
|
||||
|
||||
/* verilator public_module */
|
||||
|
||||
@@ -150,6 +150,6 @@ module off (/*AUTOARG*/
|
||||
|
||||
// verilator coverage_on
|
||||
input toggle;
|
||||
// CHECK_COVER(-1,"top.v.o1","toggle",2)
|
||||
// CHECK_COVER(-1,"top.t.o1","toggle",2)
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -13,11 +13,11 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>dequote(
|
||||
q{[0] In top.v: Hi
|
||||
[0] In top.v.sub (sub)
|
||||
[0] In top.v.sub.subblock (sub)
|
||||
[0] In top.v.sub2 (sub2)
|
||||
[0] In top.v.sub2.subblock2 (sub2)
|
||||
q{[0] In top.t: Hi
|
||||
[0] In top.t.sub (sub)
|
||||
[0] In top.t.sub.subblock (sub)
|
||||
[0] In top.t.sub2 (sub2)
|
||||
[0] In top.t.sub2.subblock2 (sub2)
|
||||
[0] Back \ Quote "
|
||||
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
|
||||
@@ -16,11 +16,11 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>dequote(
|
||||
q{[0] In top.v: Hi
|
||||
[0] In top.v.sub (sub)
|
||||
[0] In top.v.sub.subblock (sub)
|
||||
[0] In top.v.sub2 (sub2)
|
||||
[0] In top.v.sub2.subblock2 (sub2)
|
||||
q{[0] In top.t: Hi
|
||||
[0] In top.t.sub (sub)
|
||||
[0] In top.t.sub.subblock (sub)
|
||||
[0] In top.t.sub2 (sub2)
|
||||
[0] In top.t.sub2.subblock2 (sub2)
|
||||
[0] Back \ Quote "
|
||||
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
|
||||
@@ -90,7 +90,7 @@ checkResult (bool p,
|
||||
int main ()
|
||||
{
|
||||
Vt_dpi_accessors *dut = new Vt_dpi_accessors ("dut");
|
||||
svSetScope (svGetScopeFromName ("dut.v"));
|
||||
svSetScope (svGetScopeFromName ("dut.t"));
|
||||
|
||||
// evaluate the model with no signal changes to get the initial blocks
|
||||
// executed.
|
||||
|
||||
@@ -22,8 +22,8 @@ dpii_display_call: constant
|
||||
dpii_display_call: constant_value
|
||||
one10=0000000a
|
||||
dpii_display_call: one10=0000000a
|
||||
Mod=top.v 16= 10 10=0000000a
|
||||
dpii_display_call: Mod=top.v 16= 10 10=0000000a
|
||||
Mod=top.t 16= 10 10=0000000a
|
||||
dpii_display_call: Mod=top.t 16= 10 10=0000000a
|
||||
*-* All Finished *-*
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_dpi_dup_bad.v:\d+: Duplicate declaration of DPI function with different formal arguments: v.oth_f_int2
|
||||
'%Error: t/t_dpi_dup_bad.v:\d+: Duplicate declaration of DPI function with different formal arguments: t.oth_f_int2
|
||||
%Error: t/t_dpi_dup_bad.v:\d+: ... New prototype: pure int dpii_fa_bit \(int, int\)
|
||||
%Error: t/t_dpi_dup_bad.v:\d+: ... Original prototype: int dpii_fa_bit \(int\)
|
||||
%Error: Exiting due to .*'
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,55 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
typedef enum {
|
||||
E01 = 'h1,
|
||||
ELARGE = 'hf00d
|
||||
} my_t;
|
||||
|
||||
integer cyc=0;
|
||||
my_t e;
|
||||
|
||||
string all;
|
||||
|
||||
// Check runtime
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
e <= E01;
|
||||
end
|
||||
else if (cyc==1) begin
|
||||
`checks(e.name, "E01");
|
||||
`checkh(e.next, ELARGE);
|
||||
e <= ELARGE;
|
||||
end
|
||||
else if (cyc==3) begin
|
||||
`checks(e.name, "ELARGE");
|
||||
`checkh(e.next, E01);
|
||||
`checkh(e.prev, E01);
|
||||
e <= E01;
|
||||
end
|
||||
else if (cyc==20) begin
|
||||
e <= 'h11; // Unknown
|
||||
end
|
||||
else if (cyc==20) begin
|
||||
`checks(e.name, ""); // Unknown
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -12,11 +12,11 @@ module t (/*AUTOARG*/
|
||||
);
|
||||
input clk;
|
||||
|
||||
typedef enum {
|
||||
E01 = 1,
|
||||
E03 = 3,
|
||||
E04 = 4
|
||||
} my_t;
|
||||
typedef enum [3:0] {
|
||||
E01 = 1,
|
||||
E03 = 3,
|
||||
E04 = 4
|
||||
} my_t;
|
||||
|
||||
integer cyc=0;
|
||||
my_t e;
|
||||
|
||||
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 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 (
|
||||
verilator_flags2 => ["--mod-prefix modPrefix --top-module t --l2-name l2Name"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,23 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
sub sub ();
|
||||
endmodule
|
||||
|
||||
module sub;
|
||||
string scope;
|
||||
initial begin
|
||||
scope = $sformatf("%m");
|
||||
$write("[%0t] In %s\n", $time, scope);
|
||||
`ifdef VERILATOR
|
||||
if (scope != "top.l2Name.sub") $stop;
|
||||
`else
|
||||
if (scope != "top.t.sub") $stop;
|
||||
`endif
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 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 (
|
||||
# It is not possible to put them into the options file
|
||||
v_flags2 => ['-Gstring1="\"New String\"" -pvalue+string2="\"New String\"" -f t/t_flag_parameter.vc'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,49 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder
|
||||
|
||||
`define check(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: Wrong parameter value", `__FILE__,`__LINE__); $stop; end while(0);
|
||||
|
||||
module t;
|
||||
parameter string1 = "Original String";
|
||||
parameter string2 = "Original String";
|
||||
|
||||
parameter real11 = 0.1;
|
||||
parameter real12 = 0.1;
|
||||
parameter real21 = 0.1;
|
||||
parameter real22 = 0.1;
|
||||
parameter real31 = 0.1;
|
||||
parameter real32 = 0.1;
|
||||
|
||||
parameter int11 = 1;
|
||||
parameter int12 = 1;
|
||||
parameter int21 = 1;
|
||||
parameter int22 = 1;
|
||||
parameter int31 = 1;
|
||||
parameter int32 = 1;
|
||||
parameter int41 = 1;
|
||||
parameter int42 = 1;
|
||||
|
||||
initial begin
|
||||
`check(string1,"New String");
|
||||
`check(string2,"New String");
|
||||
`check(real11,0.2);
|
||||
`check(real12,0.2);
|
||||
`check(real21,400);
|
||||
`check(real22,400);
|
||||
`check(real31,20);
|
||||
`check(real32,20);
|
||||
`check(int11,16);
|
||||
`check(int12,16);
|
||||
`check(int21,16);
|
||||
`check(int22,16);
|
||||
`check(int31,123);
|
||||
`check(int32,123);
|
||||
`check(int41,32'hdeadbeef);
|
||||
`check(int42,32'hdeadbeef);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,15 @@
|
||||
-Greal11=0.2
|
||||
-pvalue+real12=0.2
|
||||
-Greal21=4e2
|
||||
-pvalue+real22=4e2
|
||||
-Greal31=0.2e2
|
||||
-pvalue+real32=0.2e2
|
||||
-Gint11=0x10
|
||||
-pvalue+int12=0x10
|
||||
-Gint21=020
|
||||
-pvalue+int22=020
|
||||
-Gint31=123
|
||||
-pvalue+int32=123
|
||||
-Gint41=32'hdead_beef
|
||||
-pvalue+int42=32'hdead_beef
|
||||
|
||||
@@ -13,17 +13,17 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>quotemeta(
|
||||
q{created tag with scope = top.v.b.gen[0].tag
|
||||
created tag with scope = top.v.b.gen[1].tag
|
||||
created tag with scope = top.v.tag
|
||||
mod a has scope = top.v
|
||||
mod a has tag = top.v.tag
|
||||
mod b has scope = top.v.b
|
||||
mod b has tag = top.v.tag
|
||||
mod c has scope = top.v.b.gen[0].c
|
||||
mod c has tag = top.v.b.gen[0].tag
|
||||
mod c has scope = top.v.b.gen[1].c
|
||||
mod c has tag = top.v.b.gen[1].tag
|
||||
q{created tag with scope = top.t.b.gen[0].tag
|
||||
created tag with scope = top.t.b.gen[1].tag
|
||||
created tag with scope = top.t.tag
|
||||
mod a has scope = top.t
|
||||
mod a has tag = top.t.tag
|
||||
mod b has scope = top.t.b
|
||||
mod b has tag = top.t.tag
|
||||
mod c has scope = top.t.b.gen[0].c
|
||||
mod c has tag = top.t.b.gen[0].tag
|
||||
mod c has scope = top.t.b.gen[1].c
|
||||
mod c has tag = top.t.b.gen[1].tag
|
||||
*-* All Finished *-*}),
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ if ($Self->{vlt}) {
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
expect=>
|
||||
'%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: Signal has multiple driving blocks: v.mem
|
||||
'%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: Signal has multiple driving blocks: t.mem
|
||||
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of first driving block
|
||||
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of other driving block
|
||||
%Warning-MULTIDRIVEN: Use ".*" and lint_on around source to disable this message.
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
expect=>
|
||||
'%Error: Circular logic when ordering code .*
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: ALWAYS
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: v.ready
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: t.ready
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: ACTIVE
|
||||
.*',
|
||||
);
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug477");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,38 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
sub #(.IDX(0), .CHK(10)) i0;
|
||||
sub #(.IDX(2), .CHK(12)) i2;
|
||||
sub #(.IDX(7), .CHK(17)) i7;
|
||||
always @ (posedge clk) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub ();
|
||||
function integer get_element;
|
||||
input integer index;
|
||||
input integer array_arg[7:0];
|
||||
get_element = array_arg[index];
|
||||
endfunction
|
||||
|
||||
parameter integer IDX = 5;
|
||||
parameter integer CHK = 5;
|
||||
localparam integer array[0:7] = '{10, 11, 12, 13, 14, 15, 16, 17};
|
||||
localparam element1 = array[IDX];
|
||||
localparam elementf = get_element(IDX, array);
|
||||
initial begin
|
||||
`checkh (element1, CHK);
|
||||
`checkh (elementf, CHK);
|
||||
end
|
||||
endmodule
|
||||
@@ -7,14 +7,12 @@ 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.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug376");
|
||||
|
||||
compile (
|
||||
);
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
@@ -55,10 +55,12 @@ module mod_typ #(
|
||||
parameter type TYP = byte
|
||||
)(
|
||||
input logic clk,
|
||||
output TYP cnt = 0,
|
||||
output TYP cnt,
|
||||
output int siz
|
||||
);
|
||||
|
||||
initial cnt = 0;
|
||||
|
||||
always @ (posedge clk)
|
||||
cnt <= cnt + 1;
|
||||
|
||||
|
||||
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,40 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Iztok Jeras.
|
||||
|
||||
package tt_pkg;
|
||||
typedef enum logic [1:0] {L0, L1, L2, L3} test_t;
|
||||
endpackage
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
ob
|
||||
);
|
||||
|
||||
output [1:0] ob;
|
||||
|
||||
import tt_pkg::*;
|
||||
|
||||
test_t a;
|
||||
test_t b;
|
||||
|
||||
assign a = L0;
|
||||
assign ob = b;
|
||||
|
||||
tt_buf #(.T_t(test_t))
|
||||
u_test
|
||||
(.i(a), .o(b));
|
||||
|
||||
endmodule
|
||||
|
||||
module tt_buf
|
||||
#(
|
||||
parameter type T_t = logic [0:0]
|
||||
)
|
||||
(
|
||||
input T_t i,
|
||||
output T_t o
|
||||
);
|
||||
assign o = i;
|
||||
endmodule
|
||||
@@ -17,9 +17,7 @@ compile (
|
||||
stdout_filename => $stdout_filename,
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t_pipe_exit_bad.pf: Intentional bad exit status...
|
||||
%Error: File not found: t/t_pipe_filter.v
|
||||
%Error: Exiting due to.*',
|
||||
'%Error: t_pipe_exit_bad.pf: Intentional bad exit status....*',
|
||||
);
|
||||
ok(1);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ module t;
|
||||
|
||||
integer p_i;
|
||||
reg [7*8:1] p_str;
|
||||
string sv_str;
|
||||
|
||||
initial begin
|
||||
if ($test$plusargs("PLUS")!==1) $stop;
|
||||
@@ -32,6 +33,10 @@ module t;
|
||||
$display("str='%s'",p_str);
|
||||
if (p_str !== "T=1234") $stop;
|
||||
|
||||
if ($value$plusargs("IN%s", sv_str)!==1) $stop;
|
||||
$display("str='%s'",sv_str);
|
||||
if (sv_str != "T=1234") $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -49,11 +49,7 @@ module t;
|
||||
|
||||
$swrite(str2, "mod=%m");
|
||||
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
|
||||
`ifdef verilator
|
||||
if (str2 !== "mod=top.v") $stop;
|
||||
`else
|
||||
if (str2 !== "mod=top.t") $stop;
|
||||
`endif
|
||||
|
||||
$swrite(str2, "lib=%l");
|
||||
`ifdef TEST_VERBOSE $display("chkl %0s",str2); `endif
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -5,7 +5,7 @@ $timescale 1ns $end
|
||||
|
||||
$scope module top $end
|
||||
$var wire 1 $ clk $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 $ clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$upscope $end
|
||||
|
||||
@@ -8,7 +8,7 @@ $timescale 1ns $end
|
||||
$scope module $unit $end
|
||||
$var wire 1 # global_bit $end
|
||||
$upscope $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 9 clk $end
|
||||
$var wire 32 $ cyc [31:0] $end
|
||||
$var real 64 3 v_arr_real(0) $end
|
||||
|
||||
@@ -8,7 +8,7 @@ $timescale 1ns $end
|
||||
$scope module $unit $end
|
||||
$var wire 1 # global_bit $end
|
||||
$upscope $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 9 clk $end
|
||||
$var wire 32 $ cyc [31:0] $end
|
||||
$var real 64 3 v_arr_real(0) $end
|
||||
|
||||
@@ -8,7 +8,7 @@ $timescale 1ns $end
|
||||
$scope module $unit $end
|
||||
$var wire 1 # global_bit $end
|
||||
$upscope $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 D clk $end
|
||||
$var wire 32 $ cyc [31:0] $end
|
||||
$var real 64 > v_arr_real(0) $end
|
||||
|
||||
@@ -6,7 +6,7 @@ $timescale 1ns $end
|
||||
$scope module top $end
|
||||
$var wire 1 6 CLK $end
|
||||
$var wire 1 7 RESET $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 6 CLK $end
|
||||
$var wire 1 # RESET $end
|
||||
$var wire 32 $ val [31:0] $end
|
||||
|
||||
@@ -33,7 +33,7 @@ int main(int argc, char **argv, char **env) {
|
||||
top->CLK = (main_time/dt_2)%2;
|
||||
top->eval();
|
||||
|
||||
top->v->glbl->setGSR(main_time < 7);
|
||||
top->t->glbl->setGSR(main_time < 7);
|
||||
|
||||
tfp->dump((unsigned int)(main_time));
|
||||
++main_time;
|
||||
|
||||
@@ -33,7 +33,7 @@ int main(int argc, char **argv, char **env) {
|
||||
top->CLK = (main_time/dt_2)%2;
|
||||
top->eval();
|
||||
|
||||
top->v->glbl->GSR = (main_time < 7);
|
||||
top->t->glbl->GSR = (main_time < 7);
|
||||
|
||||
tfp->dump((unsigned int)(main_time));
|
||||
++main_time;
|
||||
|
||||
@@ -16,9 +16,9 @@ bool check() {
|
||||
bool verbose = false;
|
||||
#endif
|
||||
|
||||
int Y = (tb->OE1 & !tb->OE2) ? tb->A1
|
||||
: (!tb->OE1 & tb->OE2) ? tb->A2
|
||||
: (tb->OE1 & tb->OE2) ? (tb->A1 | tb->A2)
|
||||
int Y = ((tb->OE1) & (!tb->OE2)) ? tb->A1
|
||||
: ((!tb->OE1) & (tb->OE2)) ? tb->A2
|
||||
: ((tb->OE1) & (tb->OE2)) ? (tb->A1 | tb->A2)
|
||||
: 3; // pullup
|
||||
|
||||
int W = (((tb->OE2) ? (tb->A2 & 0x1) : 0) << tb->A1)
|
||||
|
||||
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,107 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2009 by Wilson Snyder.
|
||||
|
||||
typedef reg [2:0] threeansi_t;
|
||||
|
||||
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];
|
||||
|
||||
localparam type three_t = reg [2:0];
|
||||
|
||||
three_t outna;
|
||||
three_t outa;
|
||||
|
||||
TestNonAnsi #( .p_t (reg [2:0]) )
|
||||
test (// Outputs
|
||||
.out (outna),
|
||||
/*AUTOINST*/
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[2:0]));
|
||||
|
||||
TestAnsi #( .p_t (reg [2:0]))
|
||||
testa (// Outputs
|
||||
.out (outa),
|
||||
/*AUTOINST*/
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[2:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {57'h0, outna, 1'b0, outa};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
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'h018decfea0a8828a
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module TestNonAnsi (/*AUTOARG*/
|
||||
// Outputs
|
||||
out,
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
parameter type p_t = shortint;
|
||||
|
||||
input clk;
|
||||
input p_t in;
|
||||
output p_t out;
|
||||
|
||||
always @(posedge clk) begin
|
||||
out <= ~in;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module TestAnsi
|
||||
#( parameter type p_t = shortint )
|
||||
(
|
||||
input clk,
|
||||
input p_t in,
|
||||
output p_t out
|
||||
);
|
||||
always @(posedge clk) begin
|
||||
out <= ~in;
|
||||
end
|
||||
endmodule
|
||||
|
||||
// Local Variables:
|
||||
// verilog-typedef-regexp: "_t$"
|
||||
// End:
|
||||
@@ -19,7 +19,7 @@ compile (
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.t: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ compile (
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.t: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ compile (
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.t: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ compile (
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.t: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/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_unopt_array.v");
|
||||
compile (
|
||||
v_flags2 => ["--trace --output-split 1 --output-split-cfuncs 1 -Wno-UNOPTFLAT"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -12,13 +12,13 @@ top_filename("t/t_unopt_combo.v");
|
||||
compile (
|
||||
fails=>$Self->{vlt},
|
||||
expect=>
|
||||
'%Warning-UNOPTFLAT: t/t_unopt_combo.v:\d+: Signal unoptimizable: Feedback to clock or circular logic: v.c
|
||||
'%Warning-UNOPTFLAT: t/t_unopt_combo.v:\d+: Signal unoptimizable: Feedback to clock or circular logic: t.c
|
||||
%Warning-UNOPTFLAT: Use "/\* verilator lint_off UNOPTFLAT \*/" and lint_on around source to disable this message.
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: v.c
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: t.c
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: ALWAYS
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: v.b
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: t.b
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: ALWAYS
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: v.c
|
||||
%Warning-UNOPTFLAT: Example path: t/t_unopt_combo.v:\d+: t.c
|
||||
%Error: Exiting due to '
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
fails => 1,
|
||||
expect=>
|
||||
'.*%Warning-UNOPTFLAT: Widest candidate vars to split:
|
||||
%Warning-UNOPTFLAT: t/t_unoptflat_simple_2.v:\d+: v.x, width 3, fanout \d+
|
||||
%Warning-UNOPTFLAT: t/t_unoptflat_simple_2.v:\d+: t.x, width 3, fanout \d+
|
||||
.*%Error: Exiting due to ',
|
||||
);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ $timescale 1ns $end
|
||||
$var wire 1 ' clk $end
|
||||
$var wire 1 ) double__underscore $end
|
||||
$var wire 1 ( escaped_normal $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 * 9num $end
|
||||
$var wire 32 & a0.cyc [31:0] $end
|
||||
$var wire 1 + bra[ket]slash/dash-colon:9backslash\done $end
|
||||
|
||||
@@ -6,7 +6,7 @@ $timescale 1ns $end
|
||||
$scope module top $end
|
||||
$var wire 1 # clk $end
|
||||
$var wire 1 $ reset_l $end
|
||||
$scope module v $end
|
||||
$scope module t $end
|
||||
$var wire 1 # clk $end
|
||||
$var wire 1 % inmod $end
|
||||
$var wire 32 & rawmod [31:0] $end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user