Compare commits

...
33 Commits
Author SHA1 Message Date
Wilson Snyder b4a7e4697e Version bump 2016-07-30 10:10:35 -04:00
Wilson Snyder cd61b1d045 Usage check. 2016-07-30 10:05:55 -04:00
Wilson Snyder 24dc36ba4c Fix comparison of unpacked arrays, bug1071. 2016-07-23 16:58:30 -04:00
Wilson Snyder e8e4f1777d Internals: Add cloneType method. Unused - for next checkin. 2016-07-23 16:54:36 -04:00
Wilson Snyder ae38a26af3 Internals: Cleanup some slice code. No functional change. 2016-07-21 23:07:22 -04:00
Wilson Snyder 8ee94dd7aa Tests: Smaller verilated test. 2016-07-21 23:03:54 -04:00
Wilson Snyder e741a29d36 Commentary 2016-07-13 22:51:40 -04:00
Wilson Snyder be1d275151 Fix Ubuntu 16.04 test failures. 2016-07-12 21:43:16 -04:00
David Horton 31c9e26e2e Fix compiler warning in GCC 6.
Signed-off-by: Wilson Snyder <[email protected]>
2016-07-09 04:09:34 -04:00
Wilson Snyder 20ed1ada03 Spelling fixes. 2016-07-09 03:31:22 -04:00
Wilson Snyder 891214fa72 Fix enum values of 11-16 bits wide using .next/.prev, bug1062. 2016-06-15 22:46:34 -04:00
Wilson Snyder e819e285e2 Fix false warnings on non-power-2 enums using .next/.prev. 2016-06-15 20:13:52 -04:00
Wilson Snyder 171c175e54 devel release 2016-05-18 21:15:33 -04:00
Wilson Snyder 675cbce8cb Version bump 2016-05-18 21:10:56 -04:00
Wilson Snyder 4f1398f773 Add commandArgsAdd, msg1890. 2016-05-16 22:04:21 -04:00
Wilson Snyder ae89e399a3 Fix to string, msg1890. 2016-05-16 21:57:49 -04:00
Wilson Snyder 2c9716c64c Try 2. Fix core dump on Arch Linux/GCC 6.1.1, bug1058. 2016-05-16 21:40:49 -04:00
Wilson Snyder bc58245abf Fix core dump on Arch Linux/GCC 6.1.1, bug1058. 2016-05-14 17:56:04 -04:00
Johan Bjork 8c4aa8517e Fix --output-split of constructors, bug1035.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-12 07:19:02 -04:00
Johan Bjork c0b7a54bb9 Fix removal of empty packages, modules and cells, bug1034.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-11 21:44:55 -04:00
Wilson Snyder 6b32bb635d Change --l2-name default to remove 'v' naming. 2016-05-07 14:10:33 -04:00
Wilson Snyder 691de22ae3 Add --l2-name option for controlling 'v' naming, bug1050. 2016-05-07 14:01:02 -04:00
Wilson Snyder e64b2d3372 Internals: user#inc now has optional increment value. 2016-05-06 22:26:15 -04:00
Johan Bjork e190af9d87 Avoid extra clean ANDs after CCalls.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-06 21:18:48 -04:00
Johan Bjork 8d14463b18 Fix emitting public enumerations.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-05 22:48:53 -04:00
Wilson Snyder 04977ef721 Internals: Show clocker in debug dumps. Part of bug1009. 2016-05-05 22:40:19 -04:00
Wilson Snyder d84e6875c5 Test case 2016-04-06 19:18:59 -04:00
Wilson Snyder 80678ae7bc Fix clang 3.8.0 warnings. 2016-03-31 22:26:49 -04:00
Stefan Wallentowitz 482bdab0e0 Support command-line -G/+pvalue param overrides, bug1045.
Signed-off-by: Wilson Snyder <[email protected]>
2016-03-24 19:14:15 -04:00
Stefan Wallentowitz b2623b9841 Internals: Add success parameter to parseDouble. No functional change intended.
Signed-off-by: Wilson Snyder <[email protected]>
2016-03-23 07:48:32 -04:00
Wilson Snyder 9ae40d64f0 Support parameter type, bug376. 2016-03-14 21:51:31 -04:00
Wilson Snyder cef097b7b7 Internals: Refactoring prep for parameter type branch. No functional change intended. 2016-03-12 20:54:52 -05:00
Wilson Snyder b840334ad2 devel release 2016-03-01 19:14:04 -05:00
103 changed files with 1975 additions and 444 deletions
+33 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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; }
}
//======================================================================
+1
View File
@@ -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);
+1
View File
@@ -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
+5 -1
View File
@@ -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
}
+3
View File
@@ -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
View File
@@ -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); }
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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*) {
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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("}");
}
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+15
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+94
View File
@@ -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);
}
}
+36
View File
@@ -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
View File
@@ -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;
+8
View File
@@ -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
View File
@@ -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()
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
//
+1 -1
View File
@@ -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
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+58
View File
@@ -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
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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.*',
);
+6 -6
View File
@@ -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
+6 -6
View File
@@ -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
+1 -1
View File
@@ -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);
+13 -13
View File
@@ -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
+5 -5
View File
@@ -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
+5 -5
View File
@@ -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
+1 -1
View File
@@ -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.
+2 -2
View File
@@ -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 *-*
}),
);
+1 -1
View File
@@ -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 .*'
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+55
View File
@@ -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
+5 -5
View File
@@ -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;
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 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;
+23
View File
@@ -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
+20
View File
@@ -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;
+49
View File
@@ -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
+15
View File
@@ -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
+11 -11
View File
@@ -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 *-*}),
);
+1 -1
View File
@@ -16,7 +16,7 @@ compile (
execute (
check_finished=>1,
expect=>
'\] (%m|.*v\.ps): Clocked
'\] (%m|.*t\.ps): Clocked
',
);
+1 -1
View File
@@ -20,7 +20,7 @@ if ($Self->{vlt}) {
execute (
check_finished=>1,
expect=>
'\] (%m|.*v\.ps): Clocked
'\] (%m|.*t\.ps): Clocked
',
);
+1 -1
View File
@@ -16,7 +16,7 @@ compile (
execute (
check_finished=>1,
expect=>
'\] (%m|.*v\.ps): Clocked
'\] (%m|.*t\.ps): Clocked
',
);
+1 -1
View File
@@ -16,7 +16,7 @@ compile (
execute (
check_finished=>1,
expect=>
'\] (%m|.*v\.ps): Clocked
'\] (%m|.*t\.ps): Clocked
',
);
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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
.*',
);
+20
View File
@@ -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;
+38
View File
@@ -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
+3 -5
View File
@@ -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;
+3 -1
View File
@@ -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;
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
#execute (
# check_finished=>1,
# );
ok(1);
1;
+40
View File
@@ -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
+1 -3
View File
@@ -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);
+5
View File
@@ -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
-4
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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)
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+107
View File
@@ -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:
+1 -1
View File
@@ -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
.*',
);
+1 -1
View File
@@ -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
.*',
);
+1 -1
View File
@@ -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
.*',
);
+1 -1
View File
@@ -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
.*',
);
+22
View File
@@ -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;
+4 -4
View File
@@ -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 '
);
+1 -1
View File
@@ -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 ',
);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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