Compare commits

..
20 Commits
Author SHA1 Message Date
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
91 changed files with 1542 additions and 338 deletions
+22 -1
View File
@@ -3,6 +3,27 @@ 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.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 +2732,5 @@ Version 2.0.
Local variables:
mode: outline
paragraph-separate: "[ \f\n]*$"
paragraph-separate: "[ \f\n]*$"
end:
+62 -4
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
@@ -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,6 +786,16 @@ 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
@@ -946,6 +999,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 +1398,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 +1661,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 +1905,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);
+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.884 2016-05-18])
# 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
+10 -1
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);
+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 \
+6 -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(); }
+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) {
+76 -2
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 {
@@ -1333,6 +1384,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 +1393,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 +1401,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 +1420,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; }
@@ -5098,6 +5157,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);
}
//--------------------
+6 -2
View File
@@ -2260,8 +2260,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
+86 -85
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,80 @@ 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 (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");
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");
}
splitSizeInc(1);
}
void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
@@ -1489,10 +1483,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 +2014,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");
+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()
+61 -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;
@@ -1142,7 +1201,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 +1250,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; }
+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
+33 -1
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()
@@ -2724,6 +2754,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;
@@ -3528,6 +3559,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
@@ -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 .*'
+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
+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;
+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
+8 -8
View File
@@ -13,14 +13,14 @@ compile (
execute (
expect=>quotemeta(
'ingen: {mod}.genblk1 top.v.genblk1
d3a: {mod}.d3nameda top.v.d3nameda
b2: {mod} top.v
b3n: {mod}.b3named: top.v.b3named
b3: {mod} top.v
b4: {mod} top.v
t1 {mod}.tsk top.v
t2 {mod}.tsk top.v
'ingen: {mod}.genblk1 top.t.genblk1
d3a: {mod}.d3nameda top.t.d3nameda
b2: {mod} top.t
b3n: {mod}.b3named: top.t.b3named
b3: {mod} top.t
b4: {mod} top.t
t1 {mod}.tsk top.t
t2 {mod}.tsk top.t
*-* All Finished *-*'),
);
+1 -1
View File
@@ -29,7 +29,7 @@ int main(int argc, char **argv, char **env) {
#define CYCTIME 10
// Cycle the interpreter
while (main_time < CYCTIME*top->v->CYCLES) {
while (main_time < CYCTIME*top->vgen->CYCLES) {
top->eval();
main_time += CYCTIME/2;
top->clk = !top->clk;