mirror of
https://github.com/verilator/verilator.git
synced 2026-10-04 17:13:40 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4a5aa2e94 | ||
|
|
bdd54eed1c | ||
|
|
c6a20a72f2 | ||
|
|
d7a54b3632 | ||
|
|
be6a3d0f10 | ||
|
|
e9125a3a22 | ||
|
|
c27a60658f | ||
|
|
8f2bc6e028 | ||
|
|
a6b78cbbee | ||
|
|
182a7076fd | ||
|
|
17a9b22dce | ||
|
|
f190d12802 | ||
|
|
b12dd526f9 | ||
|
|
473d555dc1 | ||
|
|
fa9208ccdd | ||
|
|
4aa088eb2f | ||
|
|
8f8147d646 | ||
|
|
e637dd2390 | ||
|
|
c90960fc88 | ||
|
|
da86a1c9f2 | ||
|
|
0adb789238 | ||
|
|
15082a178b | ||
|
|
4a0db26c36 | ||
|
|
ad3ea636d5 | ||
|
|
6a238b0514 |
@@ -3,6 +3,39 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
* Verilator 3.902 2017-04-02
|
||||
|
||||
** Add -FI option to force includes,msg2146. [Amir Gonnen]
|
||||
|
||||
** Add --relative-includes. [Rob Stoddard]
|
||||
|
||||
*** Add error on duplicate pattern assignments, bug1145. [Johan Bjork]
|
||||
|
||||
**** Fix error on improperly widthed default function, bug984. [Todd Strader]
|
||||
|
||||
**** Fix 2009 localparam syntax, msg2139. [Galen Seitz]
|
||||
|
||||
**** Fix ugly interface-to-non-interface errors, bug1112. [Johan Bjork]
|
||||
|
||||
**** Fix LDFLAGS and CFLAGS not preserving order, bug1130. [Olof Kindgren]
|
||||
|
||||
**** Fix internal error on initializing parameter array, bug1131. [Jie Xu]
|
||||
|
||||
**** Fix internal error on interface arrays, bug1135. [John Stevenson]
|
||||
|
||||
**** Fix calling sformatf to display, and elab $displays, bug1139. [Johan Bjork]
|
||||
|
||||
**** Fix realpath compile issue on MSVC++, bug1141. [Miodrag Milanovic]
|
||||
|
||||
**** Fix missing error on interface size mismatch, bug1143. [Johan Bjork]
|
||||
|
||||
**** Fix error on parameters with dotted references, bug1146. [Johan Bjork]
|
||||
|
||||
**** Fix wreal not handling continuous assign, bug1150. [J Briquet]
|
||||
|
||||
**** Fix nested structure parameter selects, bug1150. [J Briquet]
|
||||
|
||||
|
||||
* Verilator 3.900 2017-01-15
|
||||
|
||||
** Internal code changes for improved compatibility and performance.
|
||||
|
||||
@@ -132,6 +132,8 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
test_verilated/vgen*.pl \
|
||||
test_regress/t/t*/*.sv* \
|
||||
test_regress/t/t*/*.v* \
|
||||
test_regress/t/t*/*/*.sv* \
|
||||
test_regress/t/t*/*/*.v* \
|
||||
test_regress/t/*.cpp \
|
||||
test_regress/t/*.h \
|
||||
test_regress/t/*.dat \
|
||||
|
||||
+35
-4
@@ -280,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
|
||||
-FI <file> Force include of a file
|
||||
-G<name>=<value> Overwrite toplevel parameter
|
||||
--gdb Run Verilator under GDB interactively
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
@@ -323,6 +324,7 @@ descriptions in the next sections for more information.
|
||||
--private Debugging; see docs
|
||||
--public Debugging; see docs
|
||||
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||
--relative-includes Resolve includes relative to current file
|
||||
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
@@ -704,6 +706,14 @@ 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 -FI <file>
|
||||
|
||||
Force include of the specified C++ header file. All generated C++ files
|
||||
will insert a #include of the specified file before any other includes. The
|
||||
specified file might be used to contain define prototypes of custom
|
||||
VL_VPRINTF functions, and may need to include verilatedos.h as this file is
|
||||
included before any other standard includes.
|
||||
|
||||
=item -GI<name>=I<value>
|
||||
|
||||
Overwrites the given parameter of the toplevel module. The value is limited
|
||||
@@ -1014,6 +1024,12 @@ inlining. This will also turn off inlining as if all modules had a
|
||||
Overwrites the given parameter(s) of the toplevel module. See -G for a
|
||||
detailed description.
|
||||
|
||||
=item --relative-includes
|
||||
|
||||
When a file references an include file, resolve the filename relative to
|
||||
the path of the referencing file, instead of relative to the current
|
||||
directory.
|
||||
|
||||
=item --report-unoptflat
|
||||
|
||||
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
|
||||
@@ -2385,6 +2401,14 @@ reduce the size of the final executable when a task is used a very large
|
||||
number of times. For this flag to work, the task and tasks below it must
|
||||
be pure; they cannot reference any variables outside the task itself.
|
||||
|
||||
=item /*verilator public*/ (parameter)
|
||||
|
||||
Used after a parameter declaration to indicate the emitted C code should
|
||||
have the parameter values visible. Due to C++ language restrictions, this
|
||||
may only be used on 64-bit or narrower integral enumerations.
|
||||
|
||||
parameter [2:0] PARAM /*verilator public*/ = 2'b0;
|
||||
|
||||
=item /*verilator public*/ (typedef enum)
|
||||
|
||||
Used after an enum typedef declaration to indicate the emitted C code
|
||||
@@ -2518,6 +2542,14 @@ always @* to reduce missing activity items. Avoid putting $displays in
|
||||
combo blocks, as they may print multiple times when not desired, even on
|
||||
compliant simulators as event ordering is not specified.
|
||||
|
||||
=head2 Signal Naming
|
||||
|
||||
To avoid conflicts with C symbol naming, any character in a signal name
|
||||
that is not alphanumeric nor a single underscore will be replaced by __0hh
|
||||
where hh is the hex code of the character. To avoid conflicts with
|
||||
Verilator's internal symbols, any double underscore are replaced with
|
||||
___05F (5F is the hex code of an underscore.)
|
||||
|
||||
=head2 Bind
|
||||
|
||||
Verilator only supports "bind" to a target module name, not an instance
|
||||
@@ -2922,13 +2954,12 @@ Simply use a different register for the flop:
|
||||
always @* foo[0] = foo_flopped[0];
|
||||
always @* foo[1] = ...
|
||||
|
||||
This is good coding practice anyways.
|
||||
|
||||
It is also possible to disable this error when one of the assignments is
|
||||
inside a public task.
|
||||
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
This is not illegal in SystemVerilog, but a violation of good coding
|
||||
practice. Verilator reports this as an error, because ignoring this warning
|
||||
may make Verilator simulations differ from other simulators.
|
||||
|
||||
=item BLKSEQ
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.900 2017-01-15])
|
||||
AC_INIT([Verilator],[3.902 2017-04-02])
|
||||
# When releasing, also update header of Changes file
|
||||
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
|
||||
+3
-2
@@ -427,6 +427,7 @@ public:
|
||||
SUPPLY0,
|
||||
SUPPLY1,
|
||||
WIRE,
|
||||
WREAL,
|
||||
IMPLICITWIRE,
|
||||
TRIWIRE,
|
||||
TRI0,
|
||||
@@ -448,13 +449,13 @@ public:
|
||||
static const char* names[] = {
|
||||
"?","GPARAM","LPARAM","GENVAR",
|
||||
"VAR","INPUT","OUTPUT","INOUT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE",
|
||||
"SUPPLY0","SUPPLY1","WIRE","WREAL","IMPLICITWIRE",
|
||||
"TRIWIRE","TRI0","TRI1",
|
||||
"PORT",
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
|
||||
"IFACEREF"};
|
||||
return names[m_e]; }
|
||||
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE
|
||||
bool isSignal() const { return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|
||||
|| m_e==TRIWIRE
|
||||
|| m_e==TRI0 || m_e==TRI1
|
||||
|| m_e==SUPPLY0 || m_e==SUPPLY1
|
||||
|
||||
@@ -195,6 +195,8 @@ string AstVar::verilogKwd() const {
|
||||
return "tri";
|
||||
} else if (varType()==AstVarType::WIRE) {
|
||||
return "wire";
|
||||
} else if (varType()==AstVarType::WREAL) {
|
||||
return "wreal";
|
||||
} else {
|
||||
return dtypep()->name();
|
||||
}
|
||||
|
||||
+1
-6
@@ -270,12 +270,7 @@ void EmitCSyms::emitSymHdr() {
|
||||
puts("#define _"+symClassName()+"_H_\n");
|
||||
puts("\n");
|
||||
|
||||
if (optSystemPerl()) puts("#include \"systemperl.h\"\n");
|
||||
else if (optSystemC()) puts("#include \"systemc.h\"\n");
|
||||
|
||||
if (optSystemPerl() || optSystemC()) {
|
||||
puts("#include \"verilated_sc.h\"\n");
|
||||
}
|
||||
ofp()->putsIntTopInclude();
|
||||
if (v3Global.needHeavy()) {
|
||||
puts("#include \"verilated_heavy.h\"\n");
|
||||
} else {
|
||||
|
||||
+4
-4
@@ -168,16 +168,16 @@ public:
|
||||
|
||||
of.puts("# User CFLAGS (from -CFLAGS on Verilator command line)\n");
|
||||
of.puts("VM_USER_CFLAGS = \\\n");
|
||||
const V3StringSet& cFlags = v3Global.opt.cFlags();
|
||||
for (V3StringSet::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) {
|
||||
const V3StringList& cFlags = v3Global.opt.cFlags();
|
||||
for (V3StringList::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) {
|
||||
of.puts("\t"+*it+" \\\n");
|
||||
}
|
||||
of.puts("\n");
|
||||
|
||||
of.puts("# User LDLIBS (from -LDFLAGS on Verilator command line)\n");
|
||||
of.puts("VM_USER_LDLIBS = \\\n");
|
||||
const V3StringSet& ldLibs = v3Global.opt.ldLibs();
|
||||
for (V3StringSet::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) {
|
||||
const V3StringList& ldLibs = v3Global.opt.ldLibs();
|
||||
for (V3StringList::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) {
|
||||
of.puts("\t"+*it+" \\\n");
|
||||
}
|
||||
of.puts("\n");
|
||||
|
||||
+6
-1
@@ -269,7 +269,12 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
||||
#define UINFO(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
|
||||
#define UINFONL(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<stmsg; } }
|
||||
|
||||
#define UDEBUGONLY(stmts) {stmts}
|
||||
#ifdef VL_DEBUG
|
||||
# define UDEBUGONLY(stmts) {stmts}
|
||||
#else
|
||||
# define UDEBUGONLY(stmts) {if (0) {stmts}}
|
||||
#endif
|
||||
|
||||
#define UASSERT(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { v3fatalSrc(stmsg); }}
|
||||
// For use in V3Ast static functions only
|
||||
#define UASSERT_STATIC(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<":"<<(stmsg)<<endl; abort(); } }
|
||||
|
||||
@@ -841,3 +841,10 @@ V3OutFile::~V3OutFile() {
|
||||
if (m_fp) fclose(m_fp);
|
||||
m_fp = NULL;
|
||||
}
|
||||
|
||||
void V3OutFile::putsForceIncs() {
|
||||
const V3StringList& forceIncs = v3Global.opt.forceIncs();
|
||||
for (V3StringList::const_iterator it = forceIncs.begin(); it != forceIncs.end(); ++it) {
|
||||
puts("#include \""+*it+"\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -173,6 +173,7 @@ class V3OutFile : public V3OutFormatter {
|
||||
public:
|
||||
V3OutFile(const string& filename, V3OutFormatter::Language lang);
|
||||
virtual ~V3OutFile();
|
||||
void putsForceIncs();
|
||||
private:
|
||||
// CALLBACKS
|
||||
virtual void putcOutput(char chr) { fputc(chr, m_fp); }
|
||||
@@ -193,7 +194,9 @@ public:
|
||||
this->printf("%-19s\t%s;\n", classStar.c_str(), cellname.c_str());
|
||||
}
|
||||
virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); }
|
||||
virtual void putsIntTopInclude() { }
|
||||
virtual void putsIntTopInclude() {
|
||||
putsForceIncs();
|
||||
}
|
||||
// Print out public/privates
|
||||
void resetPrivate() { m_private = 0; }
|
||||
void putsPrivate(bool setPrivate) {
|
||||
@@ -213,6 +216,7 @@ public:
|
||||
virtual ~V3OutScFile() {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() {
|
||||
putsForceIncs();
|
||||
puts("#include \"systemc.h\"\n");
|
||||
puts("#include \"verilated_sc.h\"\n");
|
||||
}
|
||||
@@ -224,6 +228,7 @@ public:
|
||||
virtual ~V3OutSpFile() {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() {
|
||||
putsForceIncs();
|
||||
puts("#include \"systemperl.h\"\n");
|
||||
puts("#include \"verilated_sc.h\"\n");
|
||||
}
|
||||
|
||||
@@ -510,6 +510,7 @@ private:
|
||||
// delete it in later optimizations.
|
||||
AstVar* pinOldVarp = pinp->modVarp();
|
||||
AstVar* pinNewVarp = pinOldVarp->clonep();
|
||||
if (!pinNewVarp) pinOldVarp->v3fatalSrc("Cloning failed");
|
||||
|
||||
AstNode* connectRefp = pinp->exprp();
|
||||
if (!connectRefp->castConst() && !connectRefp->castVarRef()) {
|
||||
|
||||
+58
-26
@@ -143,7 +143,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit InstVisitor(AstNode* nodep) {
|
||||
explicit InstVisitor(AstNetlist* nodep) {
|
||||
m_modp=NULL;
|
||||
m_cellp=NULL;
|
||||
//
|
||||
@@ -162,6 +162,9 @@ private:
|
||||
int m_instNum; // Current instantiation number
|
||||
int m_instLsb; // Current instantiation number
|
||||
|
||||
typedef map<string,AstVar*> VarNameMap;
|
||||
VarNameMap m_modVarNameMap; // Per module, name of cloned variables
|
||||
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
@@ -169,6 +172,11 @@ private:
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) {
|
||||
m_modVarNameMap.clear();
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstCell* nodep) {
|
||||
if (nodep->rangep()) {
|
||||
m_cellRangep = nodep->rangep();
|
||||
@@ -232,21 +240,27 @@ private:
|
||||
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
|
||||
AstNode* prev = NULL;
|
||||
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
|
||||
AstVar* varNewp = nodep->cloneTree(false);
|
||||
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
|
||||
arrdtype->addNextHere(ifaceRefp);
|
||||
ifaceRefp->cellp(NULL);
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
if (!prev) {
|
||||
prev = varNewp;
|
||||
} else {
|
||||
prev->addNextHere(varNewp);
|
||||
|
||||
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
|
||||
if (it == m_modVarNameMap.end()) {
|
||||
AstVar* varNewp = nodep->cloneTree(false);
|
||||
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
|
||||
varNewp->name(varNewName);
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
if (!prev) {
|
||||
prev = varNewp;
|
||||
} else {
|
||||
prev->addNextHere(varNewp);
|
||||
}
|
||||
}
|
||||
}
|
||||
nodep->addNextHere(prev);
|
||||
if (debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; }
|
||||
if (prev) nodep->addNextHere(prev);
|
||||
if (prev && debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; }
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -303,7 +317,7 @@ private:
|
||||
}
|
||||
string index = AstNode::encodeNumber(constp->toSInt());
|
||||
AstVarRef* varrefp = arrselp->lhsp()->castVarRef();
|
||||
AstVarXRef* newp = new AstVarXRef(nodep->fileline(),varrefp->name () + "__BRA__" + index + "__KET__", "", true);
|
||||
AstVarXRef* newp = new AstVarXRef(nodep->fileline(), varrefp->name()+"__BRA__"+index+"__KET__", "", true);
|
||||
newp->dtypep(nodep->modVarp()->dtypep());
|
||||
newp->packagep(varrefp->packagep());
|
||||
arrselp->addNextHere(newp);
|
||||
@@ -319,24 +333,41 @@ private:
|
||||
// Clone the var referenced by the pin, and clone each var referenced by the varref
|
||||
// Clone pin varp:
|
||||
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) {
|
||||
AstVar* varNewp = pinVarp->cloneTree(false);
|
||||
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
|
||||
ifaceRefp->cellp(NULL);
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
if (!prevp) {
|
||||
prevp = varNewp;
|
||||
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
|
||||
AstVar* varNewp = NULL;
|
||||
|
||||
// Only clone the var once for each module
|
||||
if (!pinVarp->backp()) {
|
||||
if (it != m_modVarNameMap.end()) {
|
||||
varNewp = it->second;
|
||||
}
|
||||
} else {
|
||||
prevp->addNextHere(varNewp);
|
||||
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
|
||||
ifaceRefp->cellp(NULL);
|
||||
varNewp = pinVarp->cloneTree(false);
|
||||
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
|
||||
varNewp->name(varNewName);
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
if (!prevp) {
|
||||
prevp = varNewp;
|
||||
} else {
|
||||
prevp->addNextHere(varNewp);
|
||||
}
|
||||
}
|
||||
if (varNewp == NULL) {
|
||||
nodep->v3fatalSrc("Module dearray failed\n");
|
||||
}
|
||||
|
||||
// But clone the pin for each module instance
|
||||
// Now also clone the pin itself and update its varref
|
||||
AstPin* newp = nodep->cloneTree(false);
|
||||
newp->modVarp(varNewp);
|
||||
newp->name(newp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
// And replace exprp with a new varxref
|
||||
AstVarRef* varrefp = newp->exprp()->castVarRef();
|
||||
string newname = varrefp->name () + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||
string newname = varrefp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||
AstVarXRef* newVarXRefp = new AstVarXRef (nodep->fileline(), newname, "", true);
|
||||
newVarXRefp->varp(newp->modVarp());
|
||||
newVarXRefp->dtypep(newp->modVarp()->dtypep());
|
||||
@@ -348,11 +379,12 @@ private:
|
||||
prevPinp->addNextHere(newp);
|
||||
}
|
||||
}
|
||||
pinVarp->replaceWith(prevp);
|
||||
if (prevp) {
|
||||
pinVarp->replaceWith(prevp);
|
||||
pushDeletep(pinVarp);
|
||||
} // else pinVarp already unlinked when another instance did this step
|
||||
nodep->replaceWith(prevPinp);
|
||||
pushDeletep(pinVarp);
|
||||
pushDeletep(nodep);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +397,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit InstDeVisitor(AstNode* nodep) {
|
||||
explicit InstDeVisitor(AstNetlist* nodep) {
|
||||
m_cellRangep=NULL;
|
||||
m_instNum=0;
|
||||
m_instLsb=0;
|
||||
|
||||
+25
-20
@@ -1759,26 +1759,29 @@ private:
|
||||
// Upper AstDot visitor will handle it from here
|
||||
}
|
||||
else if (foundp->nodep()->castCell()
|
||||
&& allowVar && m_cellp
|
||||
&& foundp->nodep()->castCell()->modp()->castIface()) {
|
||||
// Interfaces can be referenced like a variable for interconnect
|
||||
&& allowVar && m_cellp) {
|
||||
AstCell* cellp = foundp->nodep()->castCell();
|
||||
VSymEnt* cellEntp = m_statep->getNodeSym(cellp); if (!cellEntp) nodep->v3fatalSrc("No interface sym entry");
|
||||
VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a module or generate begin
|
||||
string findName = nodep->name()+"__Viftop";
|
||||
VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName);
|
||||
AstVar* ifaceRefVarp = ifaceSymp ? ifaceSymp->nodep()->castVar() : NULL;
|
||||
if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "<<findName);
|
||||
//
|
||||
ok = true;
|
||||
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
|
||||
m_ds.m_dotText += nodep->name();
|
||||
m_ds.m_dotSymp = foundp;
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
|
||||
AstNode* newp = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
if (cellp->modp()->castIface()) {
|
||||
// Interfaces can be referenced like a variable for interconnect
|
||||
VSymEnt* cellEntp = m_statep->getNodeSym(cellp); if (!cellEntp) nodep->v3fatalSrc("No interface sym entry");
|
||||
VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a module or generate begin
|
||||
string findName = nodep->name()+"__Viftop";
|
||||
VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName);
|
||||
AstVar* ifaceRefVarp = ifaceSymp ? ifaceSymp->nodep()->castVar() : NULL;
|
||||
if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "<<findName);
|
||||
//
|
||||
ok = true;
|
||||
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
|
||||
m_ds.m_dotText += nodep->name();
|
||||
m_ds.m_dotSymp = foundp;
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
|
||||
AstNode* newp = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
} else if (cellp->modp()->castNotFoundModule()) {
|
||||
cellp->v3error("Cannot find file containing interface: " << AstNode::prettyName(cellp->modp()->name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (AstVar* varp = foundp->nodep()->castVar()) {
|
||||
AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(varp->subDTypep());
|
||||
@@ -1858,7 +1861,9 @@ private:
|
||||
}
|
||||
//
|
||||
if (!ok) {
|
||||
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="");
|
||||
//Cells/interfaces can't be implicit
|
||||
bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false;
|
||||
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell);
|
||||
bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name()));
|
||||
if (err) {
|
||||
if (foundp) {
|
||||
|
||||
+20
-9
@@ -183,14 +183,10 @@ void V3Options::addCppFile(const string& filename) {
|
||||
}
|
||||
}
|
||||
void V3Options::addCFlags(const string& filename) {
|
||||
if (m_cFlags.find(filename) == m_cFlags.end()) {
|
||||
m_cFlags.insert(filename);
|
||||
}
|
||||
m_cFlags.push_back(filename);
|
||||
}
|
||||
void V3Options::addLdLibs(const string& filename) {
|
||||
if (m_ldLibs.find(filename) == m_ldLibs.end()) {
|
||||
m_ldLibs.insert(filename);
|
||||
}
|
||||
m_ldLibs.push_back(filename);
|
||||
}
|
||||
void V3Options::addFuture(const string& flag) {
|
||||
if (m_futures.find(flag) == m_futures.end()) {
|
||||
@@ -229,6 +225,10 @@ void V3Options::addVFile(const string& filename) {
|
||||
// in a specific order and multiple of them.
|
||||
m_vFiles.push_back(filename);
|
||||
}
|
||||
void V3Options::addForceInc(const string& filename) {
|
||||
m_forceIncs.push_back(filename);
|
||||
}
|
||||
|
||||
void V3Options::addArg(const string& arg) {
|
||||
m_impp->m_allArgs.push_back(arg);
|
||||
}
|
||||
@@ -335,7 +335,7 @@ string V3Options::filePathCheckOneDir(const string& modname, const string& dirna
|
||||
return "";
|
||||
}
|
||||
|
||||
string V3Options::filePath (FileLine* fl, const string& modname,
|
||||
string V3Options::filePath (FileLine* fl, const string& modname, const string& lastpath,
|
||||
const string& errmsg) { // Error prefix or "" to suppress error
|
||||
// Find a filename to read the specified module name,
|
||||
// using the incdir and libext's.
|
||||
@@ -351,6 +351,11 @@ string V3Options::filePath (FileLine* fl, const string& modname,
|
||||
if (exists!="") return exists;
|
||||
}
|
||||
|
||||
if (m_relativeIncludes) {
|
||||
string exists = filePathCheckOneDir(modname, lastpath);
|
||||
if (exists!="") return V3Os::filenameRealPath(exists);
|
||||
}
|
||||
|
||||
// Warn and return not found
|
||||
if (errmsg != "") {
|
||||
fl->v3error(errmsg+modname);
|
||||
@@ -706,6 +711,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
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, "-relative-includes", flag/*ref*/) ) { m_relativeIncludes = 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; }
|
||||
else if ( onoff (sw, "-skip-identical", flag/*ref*/) ) { m_skipIdentical = flag; }
|
||||
@@ -795,11 +801,15 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
V3Error::errorLimit(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strcmp (sw, "-FI") && (i+1)<argc ) {
|
||||
shift;
|
||||
addForceInc(parseFileArg(optdir, string (argv[i])));
|
||||
}
|
||||
else if ( !strncmp (sw, "-G", strlen("-G"))) {
|
||||
addParameter (string (sw+strlen("-G")), false);
|
||||
addParameter(string (sw+strlen("-G")), false);
|
||||
}
|
||||
else if ( !strncmp (sw, "-I", 2)) {
|
||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
|
||||
addIncDirUser(parseFileArg(optdir, string (sw+strlen("-I"))));
|
||||
}
|
||||
else if ( !strcmp (sw, "-if-depth") && (i+1)<argc ) {
|
||||
shift;
|
||||
@@ -1218,6 +1228,7 @@ V3Options::V3Options() {
|
||||
m_preprocNoLine = false;
|
||||
m_public = false;
|
||||
m_reportUnoptflat = false;
|
||||
m_relativeIncludes = false;
|
||||
m_savable = false;
|
||||
m_skipIdentical = true;
|
||||
m_stats = false;
|
||||
|
||||
+10
-6
@@ -48,14 +48,15 @@ class V3Options {
|
||||
// MEMBERS (general options)
|
||||
V3OptionsImp* m_impp; // Slow hidden options
|
||||
|
||||
V3StringSet m_cppFiles; // argument: C++ files to link against
|
||||
V3StringSet m_cFlags; // argument: user CFLAGS
|
||||
V3StringSet m_ldLibs; // argument: user LDFLAGS
|
||||
V3StringSet m_cppFiles; // argument: C++ files to link against
|
||||
V3StringList m_cFlags; // argument: user CFLAGS
|
||||
V3StringList m_ldLibs; // argument: user LDFLAGS
|
||||
V3StringSet m_futures; // argument: -Wfuture- list
|
||||
V3StringSet m_libraryFiles; // argument: Verilog -v files
|
||||
V3StringSet m_clockers; // argument: Verilog -clk signals
|
||||
V3StringSet m_noClockers; // argument: Verilog -noclk signals
|
||||
V3StringList m_vFiles; // argument: Verilog files to read
|
||||
V3StringList m_forceIncs; // argument: -FI
|
||||
DebugSrcMap m_debugSrcs; // argument: --debugi-<srcfile>=<level>
|
||||
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
||||
map<string,string> m_parameters; // Parameters
|
||||
@@ -88,6 +89,7 @@ class V3Options {
|
||||
bool m_profileCFuncs;// main switch: --profile-cfuncs
|
||||
bool m_public; // main switch: --public
|
||||
bool m_reportUnoptflat; // main switch: --report-unoptflat
|
||||
bool m_relativeIncludes; // main switch: --relative-includes
|
||||
bool m_savable; // main switch: --savable
|
||||
bool m_systemC; // main switch: --sc: System C instead of simple C++
|
||||
bool m_skipIdentical;// main switch: --skip-identical
|
||||
@@ -199,6 +201,7 @@ class V3Options {
|
||||
void addClocker(const string& signame);
|
||||
void addNoClocker(const string& signame);
|
||||
void addVFile(const string& filename);
|
||||
void addForceInc(const string& filename);
|
||||
|
||||
// ACCESSORS (options)
|
||||
bool preprocOnly() const { return m_preprocOnly; }
|
||||
@@ -278,10 +281,11 @@ class V3Options {
|
||||
string xAssign() const { return m_xAssign; }
|
||||
|
||||
const V3StringSet& cppFiles() const { return m_cppFiles; }
|
||||
const V3StringSet& cFlags() const { return m_cFlags; }
|
||||
const V3StringSet& ldLibs() const { return m_ldLibs; }
|
||||
const V3StringList& cFlags() const { return m_cFlags; }
|
||||
const V3StringList& ldLibs() const { return m_ldLibs; }
|
||||
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
|
||||
const V3StringList& vFiles() const { return m_vFiles; }
|
||||
const V3StringList& forceIncs() const { return m_forceIncs; }
|
||||
const V3LangCode& defaultLanguage() const { return m_defaultLanguage; }
|
||||
|
||||
bool hasParameter(string name);
|
||||
@@ -341,7 +345,7 @@ class V3Options {
|
||||
|
||||
// METHODS (file utilities using these options)
|
||||
string fileExists (const string& filename);
|
||||
string filePath (FileLine* fl, const string& modname, const string& errmsg);
|
||||
string filePath(FileLine* fl, const string& modname, const string& lastpath, const string& errmsg);
|
||||
void filePathLookedMsg(FileLine* fl, const string& modname);
|
||||
V3LangCode fileLanguage(const string &filename);
|
||||
static bool fileStatDir (const string& filename);
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <iomanip>
|
||||
@@ -141,6 +143,23 @@ string V3Os::filenameSubstitute (const string& filename) {
|
||||
|
||||
}
|
||||
|
||||
string V3Os::filenameRealPath(const string& filename) {
|
||||
// Get rid of all the ../ behavior in the middle of the paths.
|
||||
// If there is a ../ that goes down from the 'root' of this path it is preserved.
|
||||
char retpath[PATH_MAX];
|
||||
if (
|
||||
#if defined( _MSC_VER ) || defined( __MINGW32__ )
|
||||
::_fullpath(retpath,filename.c_str(),PATH_MAX)
|
||||
#else
|
||||
realpath(filename.c_str(), retpath)
|
||||
#endif
|
||||
) {
|
||||
return string(retpath);
|
||||
} else {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
bool V3Os::filenameIsRel(const string& filename) {
|
||||
return (filename.length()>0 && filename[0] != '/');
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
|
||||
static string filenameDir (const string& filename); ///< Return directory part of filename
|
||||
static string filenameSubstitute (const string& filename); ///< Return filename with env vars removed
|
||||
static string filenameRealPath(const string& fn); ///< Return realpath of filename
|
||||
static bool filenameIsRel (const string& filename); ///< True if relative
|
||||
|
||||
// METHODS (directory utilities)
|
||||
|
||||
+2
-2
@@ -541,7 +541,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
AstVar* modvarp = pinp->modVarp();
|
||||
if (modvarp->isIfaceRef()) {
|
||||
AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType();
|
||||
if (!portIrefp) {
|
||||
if (!portIrefp && modvarp->subDTypep()->castUnpackArrayDType()) {
|
||||
portIrefp = modvarp->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
}
|
||||
|
||||
@@ -574,7 +574,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
UINFO(9," portIfaceRef "<<portIrefp<<endl);
|
||||
|
||||
if (!portIrefp) {
|
||||
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not an interface" << modvarp);
|
||||
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not an interface " << modvarp);
|
||||
} else if (!pinIrefp) {
|
||||
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not connected to interface/modport pin expression");
|
||||
} else {
|
||||
|
||||
+5
-4
@@ -33,6 +33,7 @@
|
||||
#include "V3PreProc.h"
|
||||
#include "V3File.h"
|
||||
#include "V3Parse.h"
|
||||
#include "V3Os.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -102,7 +103,7 @@ protected:
|
||||
|
||||
// Preprocess
|
||||
s_filterp = filterp;
|
||||
bool ok = preprocOpen(fl, s_filterp, modname, errmsg);
|
||||
bool ok = preprocOpen(fl, s_filterp, modname, "", errmsg);
|
||||
if (!ok) return false;
|
||||
|
||||
while (!s_preprocp->isEof()) {
|
||||
@@ -116,10 +117,10 @@ protected:
|
||||
if (modname[0]=='/' || modname[0]=='\\') {
|
||||
fl->v3warn(INCABSPATH,"Suggest `include with absolute path be made relative, and use +include: "<<modname);
|
||||
}
|
||||
preprocOpen(fl, s_filterp, modname, "Cannot find include file: ");
|
||||
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()), "Cannot find include file: ");
|
||||
}
|
||||
|
||||
bool preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname,
|
||||
bool preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname, const string& lastpath,
|
||||
const string& errmsg) { // Error message or "" to suppress
|
||||
// Returns true if successful
|
||||
// Allow user to put `defined names on the command line instead of filenames,
|
||||
@@ -127,7 +128,7 @@ protected:
|
||||
string ppmodname = s_preprocp->removeDefines (modname);
|
||||
|
||||
// Open include or master file
|
||||
string filename = v3Global.opt.filePath (fl, ppmodname, errmsg);
|
||||
string filename = v3Global.opt.filePath (fl, ppmodname, lastpath, errmsg);
|
||||
if (filename=="") return false; // Not found
|
||||
|
||||
UINFO(2," Reading "<<filename<<endl);
|
||||
|
||||
+75
-50
@@ -91,6 +91,11 @@ private:
|
||||
deque<V3Number*> m_numFreeps; ///< List of all numbers free and not in use
|
||||
deque<V3Number*> m_numAllps; ///< List of all numbers free and in use
|
||||
|
||||
// Cleanup
|
||||
// V3Numbers that represents strings are a bit special and the API for V3Number does not allow changing them.
|
||||
deque<V3Number*> m_stringNumbersp; // List of allocated string numbers
|
||||
|
||||
|
||||
// Note level 8&9 include debugging each simulation value
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
@@ -463,52 +468,53 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool handleAssignSel(AstNodeAssign* nodep, AstSel* selp, AstVarRef** outVarrefp, int depth) {
|
||||
void handleAssignSel(AstNodeAssign* nodep, AstSel* selp) {
|
||||
AstVarRef* varrefp = NULL;
|
||||
V3Number lsb = V3Number(nodep->fileline());
|
||||
nodep->rhsp()->iterateAndNext(*this); // Value to assign
|
||||
handleAssignSelRecurse(nodep, selp, varrefp/*ref*/, lsb/*ref*/, 0);
|
||||
if (!m_checkOnly && optimizable()) {
|
||||
if (!varrefp) nodep->v3fatalSrc("Indicated optimizable, but no variable found on RHS of select");
|
||||
AstNode* vscp = varOrScope(varrefp);
|
||||
V3Number outnum = V3Number(nodep->fileline());
|
||||
if (V3Number* vscpnump = fetchOutNumberNull(vscp)) {
|
||||
outnum = *vscpnump;
|
||||
} else if (V3Number* vscpnump = fetchNumberNull(vscp)) {
|
||||
outnum = *vscpnump;
|
||||
} else { // Assignment to unassigned variable, all bits are X or 0
|
||||
outnum = V3Number(nodep->fileline(), varrefp->varp()->widthMin());
|
||||
if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) {
|
||||
outnum.setAllBits0();
|
||||
} else {
|
||||
outnum.setAllBitsX();
|
||||
}
|
||||
}
|
||||
outnum.opSelInto(*fetchNumber(nodep->rhsp()),
|
||||
lsb,
|
||||
selp->widthConst());
|
||||
assignOutNumber(nodep, vscp, &outnum);
|
||||
}
|
||||
}
|
||||
void handleAssignSelRecurse (AstNodeAssign* nodep, AstSel* selp,
|
||||
AstVarRef*& outVarrefpRef, V3Number& lsbRef,
|
||||
int depth) {
|
||||
// Recurse down to find final variable being set (outVarrefp), with value to write on nodep->rhsp()
|
||||
checkNodeInfo(selp);
|
||||
AstVarRef* varrefp = selp->fromp()->castVarRef();
|
||||
if (!varrefp) {
|
||||
selp = selp->lhsp()->castSel();
|
||||
if (selp) {
|
||||
if (!handleAssignSel(nodep, selp, &varrefp, depth+1)) {
|
||||
clearOptimizable(nodep, "Select LHS isn't simple variable");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_checkOnly) {
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
selp->lsbp()->iterateAndNext(*this);
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
|
||||
selp->lsbp()->iterateAndNext(*this); // Bit index
|
||||
if (AstVarRef* varrefp = selp->fromp()->castVarRef()) {
|
||||
outVarrefpRef = varrefp;
|
||||
lsbRef = *fetchNumber(selp->lsbp());
|
||||
return; // And presumably still optimizable()
|
||||
} else if (AstSel* subselp = selp->lhsp()->castSel()) {
|
||||
V3Number sublsb = V3Number(nodep->fileline());
|
||||
handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb/*ref*/, depth+1);
|
||||
if (optimizable()) {
|
||||
if (varrefp) {
|
||||
AstNode* vscp = varOrScope(varrefp);
|
||||
V3Number outnum = V3Number(nodep->fileline());
|
||||
if (V3Number* vscpnump = fetchOutNumberNull(vscp)) {
|
||||
outnum = *vscpnump;
|
||||
} else if (V3Number* vscpnump = fetchNumberNull(vscp)) {
|
||||
outnum = *vscpnump;
|
||||
} else { // Assignment to unassigned variable, all bits are X or 0
|
||||
outnum = V3Number(nodep->fileline(), varrefp->varp()->widthMin());
|
||||
if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) {
|
||||
outnum.setAllBits0();
|
||||
} else {
|
||||
outnum.setAllBitsX();
|
||||
}
|
||||
}
|
||||
if (depth == 0) {
|
||||
outnum.opSelInto(*fetchNumber(nodep->rhsp()),
|
||||
*fetchNumber(selp->lsbp()),
|
||||
selp->widthConst());
|
||||
assignOutNumber(nodep, vscp, &outnum);
|
||||
}
|
||||
}
|
||||
lsbRef = sublsb;
|
||||
lsbRef.opAdd(sublsb, *fetchNumber(selp->lsbp()));
|
||||
}
|
||||
} else {
|
||||
clearOptimizable(nodep, "Select LHS isn't simple variable");
|
||||
}
|
||||
if (outVarrefp) *outVarrefp = varrefp;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep) {
|
||||
@@ -525,7 +531,7 @@ private:
|
||||
|
||||
if (AstSel* selp = nodep->lhsp()->castSel()) {
|
||||
if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; }
|
||||
handleAssignSel(nodep, selp, NULL, 0);
|
||||
handleAssignSel(nodep, selp);
|
||||
}
|
||||
else if (!nodep->lhsp()->castVarRef()) {
|
||||
clearOptimizable(nodep, "LHS isn't simple variable");
|
||||
@@ -726,6 +732,12 @@ private:
|
||||
if (!m_params) { badNodeType(nodep); return; }
|
||||
}
|
||||
|
||||
virtual void visit(AstScopeName *nodep) {
|
||||
if (jumpingOver(nodep)) return;
|
||||
if (!m_params) { badNodeType(nodep); return; }
|
||||
// Ignore
|
||||
}
|
||||
|
||||
virtual void visit(AstSFormatF *nodep) {
|
||||
if (jumpingOver(nodep)) return;
|
||||
if (!optimizable()) return; // Accelerate
|
||||
@@ -743,11 +755,11 @@ private:
|
||||
} else if (!inPct) { // Normal text
|
||||
result += *pos;
|
||||
} else { // Format character
|
||||
AstNode* argp = nextArgp;
|
||||
inPct = false;
|
||||
nextArgp = nextArgp->nextp();
|
||||
|
||||
if (V3Number::displayedFmtLegal(tolower(pos[0]))) {
|
||||
AstNode* argp = nextArgp;
|
||||
nextArgp = nextArgp->nextp();
|
||||
V3Number* nump = fetchNumberNull(argp);
|
||||
if (!nump) {
|
||||
clearOptimizable(nodep, "Argument for $display like statement is not constant");
|
||||
@@ -760,6 +772,10 @@ private:
|
||||
case '%':
|
||||
result += "%";
|
||||
break;
|
||||
case 'm':
|
||||
// This happens prior to AstScope so we don't know the scope name. Leave the %m in place.
|
||||
result += "%m";
|
||||
break;
|
||||
default:
|
||||
clearOptimizable(nodep, "Unknown $display-like format code.");
|
||||
break;
|
||||
@@ -767,7 +783,11 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
nodep->text(result);
|
||||
|
||||
V3Number* resultNump = new V3Number(V3Number::String(), nodep->fileline(), result);
|
||||
setNumber(nodep, resultNump);
|
||||
m_stringNumbersp.push_back(resultNump);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,19 +796,20 @@ private:
|
||||
if (!optimizable()) return; // Accelerate
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_params) {
|
||||
V3Number* textp = fetchNumber(nodep->fmtp());
|
||||
switch (nodep->displayType()) {
|
||||
case AstDisplayType::DT_DISPLAY: // FALLTHRU
|
||||
case AstDisplayType::DT_INFO:
|
||||
v3warn(USERINFO, nodep->fmtp()->text());
|
||||
v3warn(USERINFO, textp->toString());
|
||||
break;
|
||||
case AstDisplayType::DT_ERROR:
|
||||
v3warn(USERERROR, nodep->fmtp()->text());
|
||||
v3warn(USERERROR, textp->toString());
|
||||
break;
|
||||
case AstDisplayType::DT_WARNING:
|
||||
v3warn(USERWARN, nodep->fmtp()->text());
|
||||
v3warn(USERWARN, textp->toString());
|
||||
break;
|
||||
case AstDisplayType::DT_FATAL:
|
||||
v3warn(USERFATAL, nodep->fmtp()->text());
|
||||
v3warn(USERFATAL, textp->toString());
|
||||
break;
|
||||
case AstDisplayType::DT_WRITE: // FALLTHRU
|
||||
default:
|
||||
@@ -863,6 +884,10 @@ public:
|
||||
for (deque<V3Number*>::iterator it = m_numAllps.begin(); it != m_numAllps.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
for (deque<V3Number*>::iterator it = m_stringNumbersp.begin(); it != m_stringNumbersp.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
m_stringNumbersp.clear();
|
||||
m_numFreeps.clear();
|
||||
m_numAllps.clear();
|
||||
}
|
||||
|
||||
+43
-13
@@ -1184,7 +1184,14 @@ private:
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) {
|
||||
if (nodep->didWidth()) return;
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Unlinked varref");
|
||||
if (!nodep->varp()) {
|
||||
if (m_paramsOnly && nodep->castVarXRef()) {
|
||||
checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: "+nodep->prettyName()); VL_DANGLING(nodep);
|
||||
return;
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unlinked varref");
|
||||
}
|
||||
}
|
||||
if (!nodep->varp()->didWidth()) {
|
||||
// Var hasn't been widthed, so make it so.
|
||||
userIterate(nodep->varp(), NULL);
|
||||
@@ -1283,7 +1290,7 @@ private:
|
||||
AstNodeDType* vdtypep = m_vup->dtypep();
|
||||
if (!vdtypep) nodep->v3fatalSrc("InitArray type not assigned by AstPattern/Var visitor");
|
||||
nodep->dtypep(vdtypep);
|
||||
if (AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType()) {
|
||||
if (AstNodeArrayDType* arrayp = vdtypep->skipRefp()->castNodeArrayDType()) {
|
||||
userIterateChildren(nodep, WidthVP(arrayp->subDTypep(),BOTH).p());
|
||||
} else {
|
||||
nodep->v3fatalSrc("InitArray on non-array");
|
||||
@@ -1613,7 +1620,10 @@ private:
|
||||
} else if (!memp && patp) { patp->v3error("Assignment pattern contains too many elements");
|
||||
memp=NULL; patp=NULL; break;
|
||||
} else {
|
||||
patmap.insert(make_pair(memp, patp));
|
||||
pair<PatMap::iterator, bool> ret = patmap.insert(make_pair(memp, patp));
|
||||
if (!ret.second) {
|
||||
patp->v3error("Assignment pattern contains duplicate entry: " << patp->keyp()->castText()->text());
|
||||
}
|
||||
}
|
||||
// Next
|
||||
if (memp) memp = memp->nextp()->castMemberDType();
|
||||
@@ -2157,15 +2167,35 @@ private:
|
||||
// otherwise would need some mess to force both sides to proper size
|
||||
}
|
||||
}
|
||||
// TODO Simple dtype checking, should be a more general check
|
||||
bool hiArray = nodep->exprp()->dtypep()->skipRefp()->castUnpackArrayDType();
|
||||
bool loArray = nodep->modVarp()->dtypep()->skipRefp()->castUnpackArrayDType();
|
||||
if (loArray != hiArray && pinwidth != conwidth) {
|
||||
// Check if an interface is connected to a non-interface and vice versa
|
||||
AstNodeDType* modDTypep = nodep->modVarp()->dtypep();
|
||||
AstNodeDType* exprDTypep = nodep->exprp()->dtypep();
|
||||
if ((modDTypep->castIfaceRefDType() && !exprDTypep->castIfaceRefDType()) ||
|
||||
(exprDTypep->castIfaceRefDType() && !modDTypep->castIfaceRefDType())) {
|
||||
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
||||
<<" mismatch between port which is"<<(hiArray?"":" not")<<" an array,"
|
||||
<<" and expression which is"<<(loArray?"":" not")<<" an array.");
|
||||
UINFO(1," Related lo: "<<nodep->exprp()->dtypep()->skipRefp()<<endl);
|
||||
UINFO(1," Related hi: "<<nodep->modVarp()->dtypep()->skipRefp()<<endl);
|
||||
<<" mismatch between port which is"<<(modDTypep->castIfaceRefDType()?"":" not")<<" an interface,"
|
||||
<<" and expression which is"<<(exprDTypep->castIfaceRefDType()?"":" not")<<" an interface.");
|
||||
}
|
||||
|
||||
// TODO Simple dtype checking, should be a more general check
|
||||
AstNodeArrayDType* loArrayp = exprDTypep->skipRefp()->castUnpackArrayDType();
|
||||
AstNodeArrayDType* hiArrayp = modDTypep->skipRefp()->castUnpackArrayDType();
|
||||
if (loArrayp && hiArrayp && loArrayp->subDTypep()->skipRefp()->castIfaceRefDType()
|
||||
&& loArrayp->declRange().elements() != hiArrayp->declRange().elements()) {
|
||||
int loSize = loArrayp->declRange().elements();
|
||||
int hiSize = hiArrayp->declRange().elements();
|
||||
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
||||
<<" mismatch between port which is an interface array of size "<<loSize<<","
|
||||
<<" and expression which is an interface array of size "<<hiSize<<".");
|
||||
UINFO(1," Related lo: "<<modDTypep->skipRefp()<<endl);
|
||||
UINFO(1," Related hi: "<<exprDTypep->skipRefp()<<endl);
|
||||
} else if ((loArrayp && !hiArrayp && pinwidth != conwidth)
|
||||
|| (!loArrayp && hiArrayp && pinwidth != conwidth)) {
|
||||
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
|
||||
<<" mismatch between port which is"<<(loArrayp?"":" not")<<" an array,"
|
||||
<<" and expression which is"<<(hiArrayp?"":" not")<<" an array.");
|
||||
UINFO(1," Related lo: "<<modDTypep->skipRefp()<<endl);
|
||||
UINFO(1," Related hi: "<<exprDTypep->skipRefp()<<endl);
|
||||
}
|
||||
iterateCheckAssign(nodep,"pin connection",nodep->exprp(),FINAL,subDTypep);
|
||||
}
|
||||
@@ -2786,11 +2816,11 @@ private:
|
||||
if (extendRule == EXTEND_OFF) return;
|
||||
AstConst* constp = nodep->castConst();
|
||||
int expWidth = expDTypep->width();
|
||||
if (constp && !nodep->isSigned()) {
|
||||
if (constp && !constp->num().isNegative()) {
|
||||
// Save later constant propagation work, just right-size it.
|
||||
V3Number num (nodep->fileline(), expWidth);
|
||||
num.opAssign(constp->num());
|
||||
num.isSigned(expDTypep->isSigned());
|
||||
num.isSigned(false);
|
||||
AstNode* newp = new AstConst(nodep->fileline(), num);
|
||||
constp->replaceWith(newp);
|
||||
pushDeletep(constp); VL_DANGLING(constp); VL_DANGLING(nodep);
|
||||
|
||||
+14
-6
@@ -934,13 +934,13 @@ portDirNetE: // IEEE: part of port, optional net type and/or direction
|
||||
// // Per spec, if direction given default the nettype.
|
||||
// // The higher level rule may override this VARDTYPE with one later in the parse.
|
||||
| port_direction { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); }
|
||||
| port_direction { VARDECL(PORT); } net_type { VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARNET
|
||||
| net_type { } // net_type calls VARNET
|
||||
| port_direction { VARDECL(PORT); } net_type { VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARDECL
|
||||
| net_type { } // net_type calls VARDECL
|
||||
;
|
||||
|
||||
port_declNetE: // IEEE: part of port_declaration, optional net type
|
||||
/* empty */ { }
|
||||
| net_type { } // net_type calls VARNET
|
||||
| net_type { } // net_type calls VARDECL
|
||||
;
|
||||
|
||||
portSig<nodep>:
|
||||
@@ -1155,10 +1155,14 @@ parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
|
||||
|
||||
parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assignment
|
||||
// // IEEE: parameter_declaration (minus assignment)
|
||||
// // IEEE: local_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)); }
|
||||
| varLParamReset implicit_typeE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE(new AstParseTypeDType($2)); }
|
||||
| implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
|
||||
| data_type { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
|
||||
| yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($1)); }
|
||||
@@ -1205,6 +1209,8 @@ net_type: // ==IEEE: net_type
|
||||
//UNSUP yWAND { VARDECL(WAND); }
|
||||
| yWIRE { VARDECL(WIRE); }
|
||||
//UNSUP yWOR { VARDECL(WOR); }
|
||||
// // VAMS - somewhat hackish
|
||||
| yWREAL { VARDECL(WREAL); }
|
||||
;
|
||||
|
||||
varGParamReset:
|
||||
@@ -1287,8 +1293,6 @@ non_integer_type<bdtypep>: // ==IEEE: non_integer_type
|
||||
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
|
||||
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
|
||||
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
|
||||
// // VAMS - somewhat hackish
|
||||
| yWREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); VARDECL(WIRE); }
|
||||
;
|
||||
|
||||
signingE<signstate>: // IEEE: signing - plus empty
|
||||
@@ -2070,7 +2074,7 @@ instnameParen<cellp>:
|
||||
|
||||
instRangeE<rangep>:
|
||||
/* empty */ { $$ = NULL; }
|
||||
| '[' constExpr ']' { $$ = new AstRange($1,new AstConst($1,0),$2); }
|
||||
| '[' constExpr ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstSub($1, $2, new AstConst($1, 1))); }
|
||||
| '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
|
||||
;
|
||||
|
||||
@@ -3799,6 +3803,10 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
|
||||
return NULL;
|
||||
}
|
||||
AstVarType type = GRAMMARP->m_varIO;
|
||||
if (GRAMMARP->m_varDecl == AstVarType::WREAL) {
|
||||
// dtypep might not be null, might be implicit LOGIC before we knew better
|
||||
dtypep = new AstBasicDType(fileline,AstBasicDTypeKwd::DOUBLE);
|
||||
}
|
||||
if (!dtypep) { // Created implicitly
|
||||
dtypep = new AstBasicDType(fileline, LOGIC_IMPLICIT);
|
||||
} else { // May make new variables with same type, so clone
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
#include <verilated.h>
|
||||
#include "Vt_flag_fi.h"
|
||||
|
||||
//======================================================================
|
||||
|
||||
unsigned int main_time = 0;
|
||||
|
||||
double sc_time_stamp () {
|
||||
return main_time;
|
||||
}
|
||||
|
||||
VM_PREFIX* topp = NULL;
|
||||
bool gotit = false;
|
||||
|
||||
void myfunction() {
|
||||
gotit = true;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
topp = new VM_PREFIX;
|
||||
|
||||
Verilated::debug(0);
|
||||
|
||||
topp->eval();
|
||||
if (!gotit) {
|
||||
vl_fatal (__FILE__, __LINE__, "dut", "Never got call to myfunction");
|
||||
}
|
||||
|
||||
topp->final();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/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");
|
||||
|
||||
compile (
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ["-FI $Self->{t_dir}/t_flag_fi_h.h",
|
||||
"--exe $Self->{t_dir}/$Self->{name}.cpp"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,14 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2017 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.
|
||||
|
||||
module t ();
|
||||
initial begin
|
||||
$c("myfunction();");
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2017 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.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
extern void myfunction();
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--relative-includes",
|
||||
"--lint-only $Self->{t_dir}/t_flag_relinc_dir/chip/t_flag_relinc_sub.v"],
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_make_gcc => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,10 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2017 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.
|
||||
|
||||
module t;
|
||||
t_flag_relinc_sub sub ();
|
||||
endmodule
|
||||
@@ -0,0 +1,15 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2017 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.
|
||||
|
||||
`include "../include/t_flag_relinc.vh"
|
||||
|
||||
module t_flag_relinc_sub ();
|
||||
initial begin
|
||||
`all_finished;
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,8 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2017 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.
|
||||
|
||||
`define all_finished $write("*-* All Finished *-*\n")
|
||||
@@ -21,6 +21,13 @@ q{%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can
|
||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant WHILE: Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above 1024
|
||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_stop'
|
||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
||||
-Info: Printing in loop: 0
|
||||
-Info: Printing in loop: 1
|
||||
-Info: Printing in loop: 2
|
||||
%Warning-USERFATAL: Fatal Error
|
||||
%Warning-USERFATAL: Use ... verilator lint_off USERFATAL ... and lint_on around source to disable this message.
|
||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_fatal'
|
||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
||||
%Error: Exiting due to.*},
|
||||
);
|
||||
|
||||
|
||||
@@ -45,4 +45,12 @@ module t;
|
||||
$stop;
|
||||
endfunction
|
||||
|
||||
// Verify $fatal works with sformatf as argument
|
||||
localparam BFATAL = f_bad_fatal(3);
|
||||
function integer f_bad_fatal(input [31:0] a);
|
||||
for (integer i=0;i<3;i++) begin
|
||||
$display("Printing in loop: %s", $sformatf("%d", i));
|
||||
end
|
||||
$fatal(2, "%s", $sformatf("Fatal Error"));
|
||||
endfunction
|
||||
endmodule
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 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 => ["-Wno-WIDTH"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,28 @@
|
||||
// DESCRIPTION: Verilator: Test for warning (not error) on improperly width'ed
|
||||
// default function argument
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by Todd Strader.
|
||||
|
||||
function logic foo
|
||||
(
|
||||
// Intentionally provide a non-width'ed default value
|
||||
// This should warn, not error out
|
||||
input logic x = 0
|
||||
);
|
||||
return x;
|
||||
endfunction
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
logic foo_val;
|
||||
|
||||
initial begin
|
||||
foo_val = foo();
|
||||
if (foo_val != 1'b0) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/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 (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,26 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// The code here is used to trigger Verilator internal error
|
||||
// "InitArray on non-array"
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Jie Xu.
|
||||
|
||||
typedef logic [7:0] mask_t [7:0];
|
||||
|
||||
// parameter logic [7:0] IMP_MASK[7:0] = '{8'hE1, 8'h03, 8'h07, 8'h3F, 8'h33, 8'hC3, 8'hC3, 8'h37};
|
||||
|
||||
parameter mask_t IMP_MASK = '{8'hE1, 8'h03, 8'h07, 8'h3F, 8'h33, 8'hC3, 8'hC3, 8'h37};
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
mask_t a;
|
||||
//logic [7:0] a[7:0];
|
||||
|
||||
assign a = IMP_MASK;
|
||||
|
||||
endmodule
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 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 => ["--lint-only"],
|
||||
fails=>0,
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,120 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by John Stevenson.
|
||||
|
||||
package pkg;
|
||||
typedef logic [31:0] unique_id_t;
|
||||
typedef struct packed {
|
||||
unique_id_t foo;
|
||||
} inner_thing_t;
|
||||
typedef struct packed {
|
||||
inner_thing_t bar;
|
||||
inner_thing_t baz;
|
||||
} outer_thing_t;
|
||||
|
||||
endpackage
|
||||
|
||||
import pkg::*;
|
||||
|
||||
interface the_intf
|
||||
#(parameter M=5);
|
||||
outer_thing_t [M-1:0] things;
|
||||
logic valid;
|
||||
modport i (
|
||||
output things,
|
||||
output valid);
|
||||
modport t (
|
||||
input things,
|
||||
input valid);
|
||||
endinterface
|
||||
|
||||
module ThingMuxOH
|
||||
#(
|
||||
parameter NTHINGS = 1,
|
||||
parameter M = 5 )
|
||||
(
|
||||
input logic [NTHINGS-1:0] select_oh,
|
||||
the_intf.t things_in [NTHINGS-1:0],
|
||||
the_intf.i thing_out
|
||||
);
|
||||
endmodule
|
||||
|
||||
module Thinker
|
||||
#(
|
||||
parameter M = 5,
|
||||
parameter N = 2)
|
||||
(
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input unique_id_t uids[0:N-1],
|
||||
the_intf.t thing_inp,
|
||||
the_intf.i thing_out
|
||||
);
|
||||
|
||||
the_intf #(.M(M)) curr_things [N-1:0] ();
|
||||
the_intf #(.M(M)) prev_things [N-1:0] ();
|
||||
the_intf #(.M(M)) curr_thing ();
|
||||
the_intf #(.M(M)) prev_thing ();
|
||||
|
||||
logic [N-1:0] select_oh;
|
||||
|
||||
// 1st mux:
|
||||
ThingMuxOH #(
|
||||
.NTHINGS ( N ),
|
||||
.M ( M ))
|
||||
curr_thing_mux(
|
||||
.select_oh( select_oh ),
|
||||
.things_in( curr_things ),
|
||||
.thing_out( curr_thing ));
|
||||
|
||||
// 2nd mux, comment this out and no problem:
|
||||
ThingMuxOH #(
|
||||
.NTHINGS ( N ),
|
||||
.M ( M ))
|
||||
prev_thing_mux(
|
||||
.select_oh( select_oh ),
|
||||
.things_in( prev_things ),
|
||||
.thing_out( prev_thing ));
|
||||
|
||||
endmodule
|
||||
|
||||
module t
|
||||
(
|
||||
input logic clk,
|
||||
input logic reset
|
||||
);
|
||||
|
||||
localparam M = 5;
|
||||
localparam N = 2;
|
||||
|
||||
unique_id_t uids[0:N-1];
|
||||
|
||||
the_intf #(.M(M)) thing_inp();
|
||||
the_intf #(.M(M)) thing_out();
|
||||
|
||||
Thinker #(
|
||||
.M ( M ),
|
||||
.N ( N ))
|
||||
thinker(
|
||||
.clk ( clk ),
|
||||
.reset ( reset ),
|
||||
.uids ( uids ),
|
||||
.thing_inp( thing_inp ),
|
||||
.thing_out( thing_out ));
|
||||
|
||||
// Previously there was a problem in V3Inst if non-default parameters was used
|
||||
localparam K = 2;
|
||||
the_intf #(.M(K)) thing_inp2();
|
||||
the_intf #(.M(K)) thing_out2();
|
||||
|
||||
Thinker #(
|
||||
.M ( K ),
|
||||
.N ( N ))
|
||||
thinker2(
|
||||
.clk ( clk ),
|
||||
.reset ( reset ),
|
||||
.uids ( uids ),
|
||||
.thing_inp( thing_inp2 ),
|
||||
.thing_out( thing_out2 ));
|
||||
endmodule
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
fails=>1,
|
||||
expect=>
|
||||
q{%Error: t/t_interface_param_another_bad.v:\d+: Parameter-resolved constants must not use dotted references: dummy
|
||||
%Error: Exiting due to.*},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,17 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Johan Bjork.
|
||||
|
||||
module t ();
|
||||
simple_bus sb_intf();
|
||||
simple_bus #(.PARAMETER($bits(sb_intf.dummy))) simple();
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
interface simple_bus #(PARAMETER = 0);
|
||||
logic dummy;
|
||||
endinterface
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
fails=>1,
|
||||
expect=>
|
||||
q{%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 4, and expression which is an interface array of size 5.
|
||||
%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 6, and expression which is an interface array of size 5.
|
||||
%Error: Exiting due to.*},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,21 @@
|
||||
// DESCRIPTION: Verilator: Demonstrate deferred linking error messages
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Johan Bjork.
|
||||
|
||||
interface foo_intf;
|
||||
logic a;
|
||||
endinterface
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
localparam N = 4;
|
||||
foo_intf foo4 [N-1:0] ();
|
||||
foo_intf foo6 [5:0] ();
|
||||
|
||||
baz baz4_inst (.foo(foo4));
|
||||
baz baz6_inst (.foo(foo6));
|
||||
|
||||
endmodule
|
||||
|
||||
module baz(foo_intf foo[4:0] );
|
||||
endmodule
|
||||
@@ -17,7 +17,8 @@ compile (
|
||||
# However we no longer gate optimize this
|
||||
expect=>
|
||||
q{%Error: t/t_interface_typo_bad.v:\d+: Parent cell's interface is not found: foo_intf
|
||||
%Warning-IMPLICIT: t/t_interface_typo_bad.v:\d+: Signal definition not found, creating implicitly: the_foo
|
||||
%Error: t/t_interface_typo_bad.v:\d+: Cannot find file containing interface: fo_intf
|
||||
%Error: t/t_interface_typo_bad.v:\d+: Found definition of 'the_foo' as a CELL but expected a variable
|
||||
.*},
|
||||
);
|
||||
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,28 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
a, y
|
||||
);
|
||||
|
||||
input [1:0] a;
|
||||
output [3:0] y;
|
||||
|
||||
Test #(.C(2))
|
||||
test (.*);
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
#(C = 3,
|
||||
localparam O = 1 << C)
|
||||
(input [C-1:0] a,
|
||||
output reg [O-1:0] y);
|
||||
initial begin
|
||||
if (O != 4) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -49,6 +49,10 @@ module t;
|
||||
|
||||
pack2_t arr[2];
|
||||
|
||||
`ifdef T_STRUCT_INIT_BAD
|
||||
const b4_t b4_const_c = '{b1: 1'b1, b1: 1'b0, b0:1'b0, b2: 1'b1, b3: 1'b1};
|
||||
`endif
|
||||
|
||||
initial begin
|
||||
pack3_t tsu;
|
||||
tsu = 6'b110110;
|
||||
@@ -119,5 +123,5 @@ module t;
|
||||
if (in !== cmp) $stop;
|
||||
pat = 1'b0;
|
||||
endfunction
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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.
|
||||
|
||||
top_filename("t/t_struct_init.v");
|
||||
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+T_STRUCT_INIT_BAD'],
|
||||
fails => 1,
|
||||
expect=>
|
||||
'%Error: t/t_struct_init.v:\d+: Assignment pattern contains duplicate entry: b1
|
||||
%Error: Exiting due to.*'
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,54 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Matt Myers.
|
||||
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
package config_pkg;
|
||||
typedef struct packed {
|
||||
int UPPER0;
|
||||
struct packed {
|
||||
int USE_QUAD0;
|
||||
int USE_QUAD1;
|
||||
int USE_QUAD2;
|
||||
} mac;
|
||||
int UPPER2;
|
||||
} config_struct;
|
||||
|
||||
function automatic config_struct static_config(int selector);
|
||||
config_struct return_config;
|
||||
return_config = '0;
|
||||
return_config.UPPER0 = 10;
|
||||
return_config.UPPER2 = 20;
|
||||
return_config.mac.USE_QUAD0 = 4;
|
||||
return_config.mac.USE_QUAD2 = 6;
|
||||
case (selector)
|
||||
1: return_config.mac.USE_QUAD1 = 5;
|
||||
endcase
|
||||
return (return_config);
|
||||
endfunction
|
||||
endpackage : config_pkg
|
||||
|
||||
module t;
|
||||
import config_pkg::*;
|
||||
|
||||
localparam config_struct MY_CONFIG = static_config(1);
|
||||
|
||||
struct_submodule #(.MY_CONFIG(MY_CONFIG)) a_submodule_I ();
|
||||
endmodule : t
|
||||
|
||||
module struct_submodule
|
||||
import config_pkg::*;
|
||||
#(parameter config_struct MY_CONFIG = '0);
|
||||
|
||||
initial begin
|
||||
`checkd(MY_CONFIG.UPPER0, 10);
|
||||
`checkd(MY_CONFIG.mac.USE_QUAD0, 4);
|
||||
`checkd(MY_CONFIG.mac.USE_QUAD1, 5);
|
||||
`checkd(MY_CONFIG.mac.USE_QUAD2, 6);
|
||||
`checkd(MY_CONFIG.UPPER2, 20);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule : struct_submodule
|
||||
@@ -9,20 +9,75 @@ module t (/*autoarg*/
|
||||
// Outputs
|
||||
aout,
|
||||
// Inputs
|
||||
in
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
input [15:0] in;
|
||||
output aout;
|
||||
wreal aout;
|
||||
|
||||
integer cyc=0;
|
||||
|
||||
real vin;
|
||||
real gnd;
|
||||
wire out;
|
||||
within_range within_range (/*AUTOINST*/
|
||||
// Interfaces
|
||||
.vin (vin),
|
||||
.gnd (gnd),
|
||||
// Outputs
|
||||
.out (out));
|
||||
|
||||
parameter real lsb = 1;
|
||||
// verilator lint_off WIDTH
|
||||
assign aout = $itor(in) * lsb;
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
// verilator lint_on WIDTH
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d aout=%d (%f-%f=%f)\n",$time, cyc, out, vin, gnd, within_range.in_int);
|
||||
`endif
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
gnd = 0.0;
|
||||
vin = 0.2;
|
||||
end
|
||||
else if (cyc==2) begin
|
||||
if (out != 0) $stop;
|
||||
end
|
||||
else if (cyc==3) begin
|
||||
gnd = 0.0;
|
||||
vin = 0.6;
|
||||
end
|
||||
else if (cyc==4) begin
|
||||
if (out != 1) $stop;
|
||||
end
|
||||
else if (cyc==5) begin
|
||||
gnd = 0.6;
|
||||
vin = 0.8;
|
||||
end
|
||||
else if (cyc==6) begin
|
||||
if (out != 0) $stop;
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module within_range
|
||||
(input wreal vin,
|
||||
input wreal gnd,
|
||||
output out);
|
||||
|
||||
parameter real V_MIN = 0.5;
|
||||
parameter real V_MAX = 10;
|
||||
|
||||
wreal in_int = vin - gnd;
|
||||
wire out = (V_MIN <= in_int && in_int <= V_MAX);
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user