Merge branch 'master' into split_var0

This commit is contained in:
Yutetsu TAKATSUKASA 2020-01-19 07:04:10 +09:00 committed by GitHub
commit 34a6499218
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 335 additions and 192 deletions

10
Changes
View File

@ -5,11 +5,15 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.027 devel
** Support attributes (public, isolate_assignments, etc.) in configuration files.
** Support attributes (public, isolate_assignments, etc.) in configuration files.
** Add -match to lint_off to waive warnings. [Philipp Wagner]
** Add -match to lint_off to waive warnings. [Philipp Wagner]
*** Support $readmem/$writemem with assoc arrarys. Closes #2100. [agrobman]
*** Support $readmem/$writemem with assoc arrarys. Closes #2100. [agrobman]
**** Support left justified $display. Closes #2101. [Pieter Kapsenberg]
**** Add parameter values in XML. #2110. [Pieter Kapsenberg]
**** Add error on misused define. [Topa Tota]

View File

@ -16,6 +16,7 @@ ifndef::env-github[]
:link_verilator_contributing: https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc
:link_verilator_install: https://verilator.org/install
endif::[]
:link_verilator_commercial_support: https://verilator.org/verilator_commercial_support
== Welcome to Verilator
@ -38,12 +39,18 @@ endif::[]
+++ <br/> +++ &bullet; Out-of-the-box support from Arm, and RISC-V vendor IP
<.^|image:https://www.veripool.org/img/verilator_usage_400x200-min.png[,400,200]
>.^|image:https://www.veripool.org/img/chips_alliance_logo_225x75-min.png[CHIPS Alliance,link=https://chipsalliance.org]
image:https://www.veripool.org/img/osi_logo_125x125-min.png[,125,125]
>.^|image:https://www.veripool.org/img/verilator_community_400x125-min.png[,400,125]
^.^| *Community Driven & Openly Licensed*
+++ <br/> +++ &bullet; Guided by the https://chipsalliance.org/[CHIPS Alliance] and https://www.linuxfoundation.org/[Linux Foundation]
+++ <br/> +++ &bullet; Open, and free as in both speech and beer
+++ <br/> +++ &bullet; More simulation for your verification budget
^.^| *Commercial Support Available*
+++ <br/> +++ &bullet; Commercial support contracts
+++ <br/> +++ &bullet; Design support contracts
+++ <br/> +++ &bullet; Enhancement contracts
<.^|image:https://www.veripool.org/img/verilator_support_400x125-min.png[,400,125]
|===
== What Verilator Does
@ -109,7 +116,7 @@ or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)]
* https://verilator.org/issues[Verilator Issues]
== Community Supported
== Support
Verilator is a community project, guided by the
https://chipsalliance.org/[CHIPS Alliance] under the
@ -120,6 +127,10 @@ We appreciate and welcome your contributions in whatever form; please see
https://verilator.org/verilator_doc.html#CONTRIBUTORS[Contributors and
Sponsors].
Verilator also supports and encourages commercial support models and
organizations; please see {link_verilator_commercial_support}[Verilator
Commercial Support].
== Related Projects
* http://gtkwave.sourceforge.net/[GTKwave] - Waveform viewer for Verilator

View File

@ -11,7 +11,7 @@ contributions flow more efficiently.
https://verilator.org/issues[Verilator Issues].
* If you're unable to find an open issue addressing the problem,
https://verilator.org/issues/new[open a new issue].
https://verilator.org/issues/new[open a new Verilator issue].
** Be sure to include a **code sample** or an **executable test case**
demonstrating the bug and expected behavior that is not occurring.

View File

@ -24,12 +24,14 @@ Lukasz Dalek
Maarten De Braekeleer
Matthew Ballance
Mike Popoloski
Peter Monsson
Patrick Stewart
Peter Monsson
Philipp Wagner
Pieter Kapsenberg
Richard Myers
Sebastien Van Cauwenberghe
Stefan Wallentowitz
Tobias Rosenkranz
Todd Strader
Wilson Snyder
Yutetsu TAKATSUKASA

View File

@ -618,7 +618,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false;
bool widthSet = false;
int width = 0;
bool left = false;
size_t width = 0;
for (const char* pos = formatp; *pos; ++pos) {
if (!inPct && pos[0]=='%') {
pctp = pos;
@ -643,6 +644,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
widthSet = true;
width = width*10 + (fmt - '0');
break;
case '-':
left = true;
inPct = true; // Get more digits
break;
case '.':
inPct = true; // Get more digits
break;
@ -662,8 +667,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case '@': { // Verilog/C++ string
va_arg(ap, int); // # bits is ignored
const std::string* cstrp = va_arg(ap, const std::string*);
if (width > cstrp->size()) output += std::string(width - cstrp->size(), ' ');
output += *cstrp;
std::string padding;
if (width > cstrp->size()) padding.append(width - cstrp->size(), ' ');
output += left ? (*cstrp + padding) : (padding + *cstrp);
break;
}
case 'e':
@ -721,8 +727,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
field += (charval==0)?' ':charval;
}
if (width > field.size()) output += std::string(width - field.size(), ' ');
output += field;
std::string padding;
if (width > field.size()) padding.append(width - field.size(), ' ');
output += left ? (field + padding) : (padding + field);
break;
}
case 'd': { // Signed decimal
@ -743,14 +750,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
digits = append.length();
}
int needmore = width-digits;
std::string padding;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero
padding.append(needmore, '0'); // Pre-pad zero
} else {
output.append(needmore, ' '); // Pre-pad spaces
padding.append(needmore, ' '); // Pre-pad spaces
}
}
output += append;
output += left ? (append + padding) : (padding + append);
break;
}
case '#': { // Unsigned decimal
@ -764,14 +772,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
digits = append.length();
}
int needmore = width-digits;
std::string padding;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero
padding.append(needmore, '0'); // Pre-pad zero
} else {
output.append(needmore, ' '); // Pre-pad spaces
padding.append(needmore, ' '); // Pre-pad spaces
}
}
output += append;
output += left ? (append + padding) : (padding + append);
break;
}
case 't': { // Time
@ -786,8 +795,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER");
}
int needmore = width-digits;
if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces
output += tmp;
std::string padding;
if (needmore>0) padding.append(needmore, ' '); // Pad with spaces
output += left ? (tmp + padding) : (padding + tmp);
break;
}
case 'b':
@ -1740,9 +1750,7 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
}
VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end)
: m_hex(hex)
, m_bits(bits)
, m_filename(filename)
: m_bits(bits)
, m_addr(0) {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(filename.c_str(), 0, "",

View File

@ -65,9 +65,7 @@ public:
};
class VlWriteMem {
bool m_hex; // Hex format
int m_bits; // Bit width of values
const std::string& m_filename; // Filename
FILE* m_fp; // File handle for filename
QData m_addr; // Next address to write
public:

View File

@ -160,9 +160,13 @@
# define VL_DANGLING(var) do { (var) = NULL; } while(0)
#endif
///< Perform an e.g. delete, then set variable to NULL to indicate must not use later
///< Perform an e.g. delete, then set variable to NULL to indicate must not use later.
///< Unlike VL_DO_CLEAR the setting of the variable is only for debug reasons.
#define VL_DO_DANGLING(stmt, var) do { do { stmt; } while(0); VL_DANGLING(var); } while(0)
///< Perform an e.g. delete, then set variable to NULL as a requirement
#define VL_DO_CLEAR(stmt, stmt2) do { do { stmt; } while(0); do { stmt2; } while(0); } while(0)
//=========================================================================
// C++-2011

View File

@ -1724,12 +1724,15 @@ public:
class AstNodeStmt : public AstNode {
// Statement -- anything that's directly under a function
bool m_statement; // Really a statement (e.g. not a function with return)
public:
explicit AstNodeStmt(FileLine* fl)
: AstNode(fl) {}
explicit AstNodeStmt(FileLine* fl, bool statement = true)
: AstNode(fl)
, m_statement(statement) {}
ASTNODE_BASE_FUNCS(NodeStmt)
// METHODS
virtual bool isStatement() const { return true; } // Really a statement
bool isStatement() const { return m_statement; } // Really a statement
void statement(bool flag) { m_statement = flag; }
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
};
@ -2171,13 +2174,13 @@ private:
string m_inlinedDots; // Dotted hierarchy flattened out
AstPackage* m_packagep; // Package hierarchy
public:
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
: AstNodeStmt(fl)
AstNodeFTaskRef(FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp)
: AstNodeStmt(fl, statement)
, m_taskp(NULL), m_packagep(NULL) {
setOp1p(namep); addNOp2p(pinsp);
}
AstNodeFTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
: AstNodeStmt(fl)
AstNodeFTaskRef(FileLine* fl, bool statement, const string& name, AstNode* pinsp)
: AstNodeStmt(fl, statement)
, m_taskp(NULL), m_name(name), m_packagep(NULL) {
addNOp2p(pinsp);
}

View File

@ -999,6 +999,12 @@ void AstJumpGo::dump(std::ostream& str) const {
if (labelp()) { labelp()->dump(str); }
else { str<<"%Error:UNLINKED"; }
}
void AstMemberSel::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " -> ";
if (varp()) { varp()->dump(str); }
else { str << "%Error:UNLINKED"; }
}
void AstModportFTaskRef::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isExport()) str<<" EXPORT";

View File

@ -1366,39 +1366,40 @@ public:
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
};
class AstCMethodCall : public AstNodeStmt {
class AstCMethodHard : public AstNodeStmt {
// A reference to a "C" hardocded member task (or function)
// PARENTS: stmt/math
// Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal.
private:
string m_name; // Name of method
bool m_pure; // Pure optimizable
bool m_statement; // Is a statement (AstNodeMath-like) versus AstNodeStmt-like
public:
AstCMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
AstNode* pinsp)
: AstNodeStmt(fl), m_name(name), m_pure(false), m_statement(false) {
: AstNodeStmt(fl, false)
, m_name(name)
, m_pure(false) {
setOp1p(fromp);
dtypep(NULL); // V3Width will resolve
addNOp2p(pinsp);
}
AstCMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
: AstNodeStmt(fl), m_name(name), m_statement(false) {
AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
: AstNodeStmt(fl, false)
, m_name(name) {
setOp1p(fromp);
addNOp2p(pinsp);
}
ASTNODE_NODE_FUNCS(CMethodCall)
ASTNODE_NODE_FUNCS(CMethodHard)
virtual string name() const { return m_name; } // * = Var name
virtual bool hasDType() const { return true; }
virtual void name(const string& name) { m_name = name; }
virtual V3Hash sameHash() const { return V3Hash(m_name); }
virtual bool same(const AstNode* samep) const {
const AstCMethodCall* asamep = static_cast<const AstCMethodCall*>(samep);
const AstCMethodHard* asamep = static_cast<const AstCMethodHard*>(samep);
return (m_name == asamep->m_name); }
virtual bool isStatement() const { return m_statement; }
virtual bool isPure() const { return m_pure; }
void pure(bool flag) { m_pure = flag; }
void makeStatement() { m_statement = true; dtypeSetVoid(); }
void makeStatement() { statement(true); dtypeSetVoid(); }
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
void fromp(AstNode* nodep) { setOp1p(nodep); }
AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list
@ -2064,6 +2065,7 @@ public:
virtual void cloneRelink() { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); } }
virtual const char* broken() const {
BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; }
virtual void dump(std::ostream& str) const;
virtual string name() const { return m_name; }
virtual V3Hash sameHash() const { return V3Hash(m_name); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
@ -2430,22 +2432,22 @@ class AstTaskRef : public AstNodeFTaskRef {
// A reference to a task
public:
AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
: AstNodeFTaskRef(fl, namep, pinsp) {}
: AstNodeFTaskRef(fl, true, namep, pinsp) {
statement(true);
}
AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
: AstNodeFTaskRef(fl, name, pinsp) {}
: AstNodeFTaskRef(fl, true, name, pinsp) {}
ASTNODE_NODE_FUNCS(TaskRef)
virtual bool isStatement() const { return true; } // A statement, unlike FuncRef
};
class AstFuncRef : public AstNodeFTaskRef {
// A reference to a function
public:
AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
: AstNodeFTaskRef(fl, namep, pinsp) {}
: AstNodeFTaskRef(fl, false, namep, pinsp) {}
AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp)
: AstNodeFTaskRef(fl, name, pinsp) {}
: AstNodeFTaskRef(fl, false, name, pinsp) {}
ASTNODE_NODE_FUNCS(FuncRef)
virtual bool isStatement() const { return false; } // Not a statement, unlike TaskRef
virtual bool hasDType() const { return true; }
};

View File

@ -761,7 +761,7 @@ public:
}
}
virtual ~CdcVisitor() {
if (m_ofp) { delete m_ofp; m_ofp = NULL; }
if (m_ofp) VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
};

View File

@ -282,7 +282,7 @@ private:
insureCleanAndNext(nodep->argsp());
setClean(nodep, true);
}
virtual void visit(AstCMethodCall* nodep) {
virtual void visit(AstCMethodHard* nodep) {
iterateChildren(nodep);
insureCleanAndNext(nodep->pinsp());
setClean(nodep, true);

View File

@ -2072,7 +2072,7 @@ private:
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) {
} else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch;
} else if (inPct) {
inPct = false;

View File

@ -54,8 +54,8 @@ private:
: m_comment(comment), m_varRefp(vp), m_chgRefp(cp) {}
~ToggleEnt() {}
void cleanup() {
m_varRefp->deleteTree(); m_varRefp = NULL;
m_chgRefp->deleteTree(); m_chgRefp = NULL;
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL);
VL_DO_CLEAR(m_chgRefp->deleteTree(), m_chgRefp = NULL);
}
};

View File

@ -299,7 +299,7 @@ private:
return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO()
&& ((nodep->isTemp() && !nodep->isTrace())
|| (nodep->isParam() && !nodep->isTrace())
|| (nodep->isParam() && !nodep->isTrace() && !v3Global.opt.xmlOnly())
|| m_elimUserVars)); // Post-Trace can kill most anything
}

View File

@ -192,7 +192,7 @@ public:
} else if (nodep->isWide()
&& VN_IS(nodep->lhsp(), VarRef)
&& !VN_IS(nodep->rhsp(), CMath)
&& !VN_IS(nodep->rhsp(), CMethodCall)
&& !VN_IS(nodep->rhsp(), CMethodHard)
&& !VN_IS(nodep->rhsp(), VarRef)
&& !VN_IS(nodep->rhsp(), AssocSel)
&& !VN_IS(nodep->rhsp(), ArraySel)) {
@ -257,7 +257,7 @@ public:
puts(");\n");
}
}
virtual void visit(AstCMethodCall* nodep) {
virtual void visit(AstCMethodHard* nodep) {
iterate(nodep->fromp());
puts(".");
puts(nodep->nameProtect());
@ -1797,7 +1797,8 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
case '.': // FALLTHRU
case '-':
// Digits, like %5d, etc.
vfmt += pos[0];
inPct = true; // Get more digits
@ -2812,7 +2813,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
void EmitCImp::maybeSplit(AstNodeModule* modp) {
if (splitNeeded()) {
// Close old file
delete m_ofp; m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
// Open a new file
m_ofp = newOutCFile(modp, !m_fast, true/*source*/, splitFilenumInc());
emitImp(modp);
@ -2833,7 +2834,7 @@ void EmitCImp::main(AstNodeModule* modp, bool slow, bool fast) {
if (m_fast) {
m_ofp = newOutCFile(modp, !m_fast, false/*source*/);
emitInt(modp);
delete m_ofp; m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
m_ofp = newOutCFile(modp, !m_fast, true/*source*/);
@ -2864,7 +2865,7 @@ void EmitCImp::main(AstNodeModule* modp, bool slow, bool fast) {
}
}
}
delete m_ofp; m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
//######################################################################
@ -3191,7 +3192,7 @@ class EmitCTrace : EmitCStmts {
if (splitNeeded()) {
// Close old file
delete m_ofp; m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
// Open a new file
newOutCFile(splitFilenumInc());
}
@ -3272,7 +3273,7 @@ public:
iterate(v3Global.rootp());
delete m_ofp; m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
};

View File

@ -480,8 +480,7 @@ void EmitCSyms::closeSplit() {
if (!m_ofp || m_ofp == m_ofpBase) return;
puts("}\n");
delete m_ofp;
m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
void EmitCSyms::checkSplit(bool usesVfinal) {

View File

@ -140,6 +140,8 @@ class EmitXmlFileVisitor : public AstNVisitor {
if (nodep->isSigPublic()) puts(" public=\"true\"");
if (nodep->isSigUserRdPublic()) puts(" public_flat_rd=\"true\"");
if (nodep->isSigUserRWPublic()) puts(" public_flat_rw=\"true\"");
if (nodep->isGParam()) puts(" param=\"true\"");
else if (nodep->isParam()) puts(" localparam=\"true\"");
if (nodep->attrScBv()) puts(" sc_bv=\"true\"");
if (nodep->attrScClocked()) puts(" sc_clock=\"true\"");
if (nodep->attrSFormat()) puts(" sformat=\"true\"");

View File

@ -594,7 +594,7 @@ protected:
// Just dispatch to the implementation
VInFilter::VInFilter(const string& command) { m_impp = new VInFilterImp(command); }
VInFilter::~VInFilter() { if (m_impp) delete m_impp; m_impp = NULL; }
VInFilter::~VInFilter() { if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = NULL); }
bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) {
if (!m_impp) v3fatalSrc("readWholefile on invalid filter");

View File

@ -150,9 +150,7 @@ public:
V3GraphEdge* deletep = NULL;
for (V3GraphEdge* edgep = vxp->outBeginp();
edgep; edgep = edgep->outNextp()) {
if (deletep) {
deletep->unlinkDelete(); deletep = NULL;
}
if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = NULL);
// It should be safe to modify the graph, despite using
// the GraphPathChecker, as none of the modifications will
// change what can be reached from what, nor should they

View File

@ -595,7 +595,7 @@ public:
add_complement_edges();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
m_tempNewerReject->unlinkDelete(graphp()); m_tempNewerReject = NULL;
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
}
~DfaGraphComplement() {}

View File

@ -453,11 +453,11 @@ public:
{
m_lifep = new LifeBlock(NULL, m_statep);
iterate(nodep);
if (m_lifep) { delete m_lifep; m_lifep = NULL; }
if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = NULL);
}
}
virtual ~LifeVisitor() {
if (m_lifep) { delete m_lifep; m_lifep = NULL; }
if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = NULL);
}
VL_UNCOPYABLE(LifeVisitor);
};

View File

@ -49,12 +49,12 @@ private:
// NODE STATE
// Entire netlist:
// AstCaseItem::user2() // bool Moved default caseitems
AstUser2InUse m_inuser2;
AstUser2InUse m_inuser2;
// STATE
// Below state needs to be preserved between each module call.
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Function or task we're inside
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Function or task we're inside
AstNodeCoverOrAssert* m_assertp; // Current assertion
int m_senitemCvtNum; // Temporary signal counter
@ -270,7 +270,7 @@ private:
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) {
} else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch;
} else if (inPct) {
inPct = false;

View File

@ -497,10 +497,10 @@ bool V3Number::displayedFmtLegal(char format) {
}
}
string V3Number::displayPad(size_t fmtsize, char pad, const string& in) {
string prefix;
if (in.length() < fmtsize) prefix = string(fmtsize - in.length(), pad);
return prefix + in;
string V3Number::displayPad(size_t fmtsize, char pad, bool left, const string& in) {
string padding;
if (in.length() < fmtsize) padding = string(fmtsize - in.length(), pad);
return left ? (in + padding) : (padding + in);
}
string V3Number::displayed(AstNode* nodep, const string& vformat) const {
@ -512,6 +512,11 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
UASSERT(pos != vformat.end() && pos[0]=='%',
"$display-like function with non format argument "<<*this);
++pos;
bool left = false;
if (pos[0] == '-') {
left = true;
++pos;
}
string fmtsize;
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) {
fmtsize += pos[0];
@ -574,7 +579,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
}
}
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', str);
str = displayPad(fmtsizen, ' ', left, str);
return str;
}
case '~': // Signed decimal
@ -604,7 +609,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
// fmtsize might have changed since we parsed the %fmtsize
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, (zeropad ? '0' : ' '), str);
str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str);
return str;
}
case 'e':
@ -651,7 +656,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
}
case '@': { // Packed string
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', toString());
str = displayPad(fmtsizen, ' ', left, toString());
return str;
}
default:

View File

@ -175,7 +175,7 @@ private:
for (int i=0; i<words(); i++) m_value[i] = m_valueX[i] = 0;
}
void setNames(AstNode* nodep);
static string displayPad(size_t fmtsize, char pad, const string& in);
static string displayPad(size_t fmtsize, char pad, bool left, const string& in);
string displayed(FileLine* fl, const string& vformat) const;
string displayed(const string& vformat) const {
return displayed(m_fileline, vformat);

View File

@ -1553,7 +1553,7 @@ V3Options::V3Options() {
}
V3Options::~V3Options() {
delete m_impp; m_impp = NULL;
VL_DO_CLEAR(delete m_impp, m_impp = NULL);
}
void V3Options::setDebugMode(int level) {

View File

@ -57,11 +57,11 @@ extern void yyerrorf(const char* format, ...);
V3ParseImp::~V3ParseImp() {
for (std::deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) {
delete (*it);
VL_DO_DANGLING(delete *it, *it);
}
m_stringps.clear();
for (std::deque<V3Number*>::iterator it = m_numberps.begin(); it != m_numberps.end(); ++it) {
delete (*it);
VL_DO_DANGLING(delete *it, *it);
}
m_numberps.clear();
lexDestroy();
@ -297,7 +297,7 @@ V3Parse::V3Parse(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* symp) {
m_impp = new V3ParseImp(rootp, filterp, symp);
}
V3Parse::~V3Parse() {
delete m_impp; m_impp = NULL;
VL_DO_CLEAR(delete m_impp, m_impp = NULL);
}
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary,
const string& errmsg) {

View File

@ -82,5 +82,5 @@ void V3ParseImp::lexNew() {
}
void V3ParseImp::lexDestroy() {
if (m_lexerp) { delete m_lexerp; m_lexerp = NULL; }
if (m_lexerp) VL_DO_CLEAR(delete m_lexerp, m_lexerp = NULL);
}

View File

@ -1411,7 +1411,7 @@ private:
// Remove and free the connecting edge. Must do this before
// propagating CP's below.
m_sb.removeElem(mergeCanp);
mergeEdgep->unlinkDelete(); mergeEdgep=NULL;
VL_DO_CLEAR(mergeEdgep->unlinkDelete(), mergeEdgep=NULL);
}
// This also updates cost and stepCost on recipientp
@ -1467,7 +1467,7 @@ private:
partMergeEdgesFrom(m_mtasksp, recipientp, donorp, &m_sb);
// Delete the donorp mtask from the graph
donorp->unlinkDelete(m_mtasksp); donorp = NULL;
VL_DO_CLEAR(donorp->unlinkDelete(m_mtasksp), donorp = NULL);
m_mergesSinceRescore++;

View File

@ -189,7 +189,7 @@ class V3PreLex {
}
~V3PreLex() {
while (!m_streampStack.empty()) { delete m_streampStack.top(); m_streampStack.pop(); }
yy_delete_buffer(m_bufferState); m_bufferState = NULL;
VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = NULL);
}
// Called by V3PreLex.l from lexer

View File

@ -285,7 +285,7 @@ public:
m_lexp->debug(debug()>=5 ? debug() : 0); // See also V3PreProc::debug() method
}
~V3PreProcImp() {
if (m_lexp) { delete m_lexp; m_lexp = NULL; }
if (m_lexp) VL_DO_CLEAR(delete m_lexp, m_lexp = NULL);
}
};

View File

@ -164,12 +164,12 @@ public:
void deleteUnusedAssign() {
// If there are unused assignments in this var, kill them
if (!m_whole.m_use && !m_wordUse && m_whole.m_assignp) {
deleteAssign(m_whole.m_assignp); m_whole.m_assignp = NULL;
VL_DO_CLEAR(deleteAssign(m_whole.m_assignp), m_whole.m_assignp = NULL);
}
for (unsigned i=0; i<m_words.size(); i++) {
if (!m_whole.m_use && !m_words[i].m_use
&& m_words[i].m_assignp && !m_words[i].m_complex) {
deleteAssign(m_words[i].m_assignp); m_words[i].m_assignp = NULL;
VL_DO_CLEAR(deleteAssign(m_words[i].m_assignp), m_words[i].m_assignp = NULL);
}
}
}

View File

@ -129,15 +129,14 @@ public:
return iter->second;
}
bool ftaskNoInline(AstNodeFTask* nodep) {
return (getFTaskVertex(nodep)->noInline());
return getFTaskVertex(nodep)->noInline();
}
AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) {
return (getFTaskVertex(nodep)->cFuncp());
return getFTaskVertex(nodep)->cFuncp();
}
void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) {
getFTaskVertex(nodep)->cFuncp(cfuncp);
}
void checkPurity(AstNodeFTask* nodep) {
checkPurity(nodep, getFTaskVertex(nodep));
}
@ -196,7 +195,7 @@ private:
// of multiple statements. Perhaps someday make all wassigns into always's?
UINFO(5," IM_WireRep "<<m_assignwp<<endl);
m_assignwp->convertToAlways();
pushDeletep(m_assignwp); m_assignwp = NULL;
VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = NULL);
}
// We make multiple edges if a task is called multiple times from another task.
UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked task");
@ -471,7 +470,8 @@ private:
{
AstBegin* tempp = new AstBegin(beginp->fileline(), "[EditWrapper]", beginp);
TaskRelinkVisitor visit (tempp);
tempp->stmtsp()->unlinkFrBackWithNext(); VL_DO_DANGLING(tempp->deleteTree(), tempp);
tempp->stmtsp()->unlinkFrBackWithNext();
VL_DO_DANGLING(tempp->deleteTree(), tempp);
}
//
if (debug()>=9) { beginp->dumpTreeAndNext(cout, "-iotask: "); }
@ -489,8 +489,8 @@ private:
string("Function: ")+refp->name(), true);
AstCCall* ccallp = new AstCCall(refp->fileline(), cfuncp, NULL);
beginp->addNext(ccallp);
// Convert complicated outputs to temp signals
// Convert complicated outputs to temp signals
V3TaskConnects tconnects = V3Task::taskConnects(refp, refp->taskp()->stmtsp());
for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
AstVar* portp = it->first;
@ -521,7 +521,7 @@ private:
// Correct lvalue; we didn't know when we linked
// This is slightly scary; are we sure no decisions were made
// before here based on this not being a lvalue?
// Doesn't seem so; V3Unknown uses it earlier, but works ok.
// Seems correct assumption; V3Unknown uses it earlier, but works ok.
V3LinkLValue::linkLValueSet(pinp);
// Even if it's referencing a varref, we still make a temporary
@ -1074,7 +1074,8 @@ private:
{
AstBegin* tempp = new AstBegin(cfuncp->fileline(), "[EditWrapper]", cfuncp);
TaskRelinkVisitor visit (tempp);
tempp->stmtsp()->unlinkFrBackWithNext(); VL_DO_DANGLING(tempp->deleteTree(), tempp);
tempp->stmtsp()->unlinkFrBackWithNext();
VL_DO_DANGLING(tempp->deleteTree(), tempp);
}
// Delete rest of cloned task and return new func
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@ -1411,7 +1412,8 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
UINFO(9,"Default pin for "<<portp<<endl);
AstArg* newp = new AstArg(nodep->fileline(), portp->name(), newvaluep);
if (tconnects[i].second) { // Have a "NULL" pin already defined for it
tconnects[i].second->unlinkFrBack()->deleteTree(); tconnects[i].second = NULL;
VL_DO_CLEAR(tconnects[i].second->unlinkFrBack()->deleteTree(),
tconnects[i].second = NULL);
}
tconnects[i].second = newp;
reorganize = true;

View File

@ -227,7 +227,7 @@ private:
iterate(varp->dtypeSkipRefp());
}
// Cleanup
if (m_traValuep) { m_traValuep->deleteTree(); m_traValuep = NULL; }
if (m_traValuep) VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
}
m_traVscp = NULL;
m_traValuep = NULL;
@ -272,7 +272,7 @@ private:
i - nodep->lsb());
iterate(subtypep);
m_traValuep->deleteTree(); m_traValuep = NULL;
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
}
m_traShowname = oldShowname;
m_traValuep = oldValuep;
@ -298,7 +298,7 @@ private:
(i - nodep->lsb())*subtypep->width(),
subtypep->width());
iterate(subtypep);
m_traValuep->deleteTree(); m_traValuep = NULL;
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
}
m_traShowname = oldShowname;
m_traValuep = oldValuep;
@ -329,7 +329,7 @@ private:
m_traValuep->cloneTree(true),
itemp->lsb(), subtypep->width());
iterate(subtypep);
m_traValuep->deleteTree(); m_traValuep = NULL;
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
} else { // Else union, replicate fields
iterate(subtypep);
}

View File

@ -1155,7 +1155,9 @@ class TristateVisitor : public TristateBaseVisitor {
AstVar* outModVarp = static_cast<AstVar*>(nodep->modVarp()->user4p());
if (!outModVarp) {
// At top, no need for __out as might be input only. Otherwise resolvable.
UASSERT_OBJ(m_modp->isTop(), nodep, "Unlinked");
if (!m_modp->isTop()) {
nodep->v3error("Unsupported: tristate in top-level IO: " << nodep->prettyNameQ());
}
} else {
AstNode* outexprp = nodep->exprp()->cloneTree(false); // Note has lvalue() set
outpinp = new AstPin(nodep->fileline(),

View File

@ -86,7 +86,8 @@ private:
// Wire assigns must become always statements to deal with insertion
// of multiple statements. Perhaps someday make all wassigns into always's?
UINFO(5," IM_WireRep "<<m_assignwp<<endl);
m_assignwp->convertToAlways(); pushDeletep(m_assignwp); m_assignwp = NULL;
m_assignwp->convertToAlways();
VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = NULL);
}
bool needDly = (m_assigndlyp != NULL);
if (m_assigndlyp) {
@ -95,7 +96,8 @@ private:
AstNode* newp = new AstAssign(m_assigndlyp->fileline(),
m_assigndlyp->lhsp()->unlinkFrBackWithNext(),
m_assigndlyp->rhsp()->unlinkFrBackWithNext());
m_assigndlyp->replaceWith(newp); pushDeletep(m_assigndlyp); m_assigndlyp = NULL;
m_assigndlyp->replaceWith(newp);
VL_DO_CLEAR(pushDeletep(m_assigndlyp), m_assigndlyp = NULL);
}
AstNode* prep = nodep;

View File

@ -184,7 +184,7 @@ private:
SimulateVisitor simvis;
AstNode* clonep = nodep->cloneTree(true);
simvis.mainCheckTree(clonep);
pushDeletep(clonep); clonep = NULL;
VL_DO_CLEAR(pushDeletep(clonep), clonep = NULL);
return simvis.optimizable();
}
@ -202,7 +202,7 @@ private:
clonep = tempp->stmtsp()->unlinkFrBackWithNext();
tempp->deleteTree();
tempp = NULL;
pushDeletep(m_varValuep); m_varValuep = NULL;
VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = NULL);
}
SimulateVisitor simvis;
simvis.mainParamEmulate(clonep);
@ -329,7 +329,7 @@ private:
string nname = m_beginName + "__BRA__" + index + "__KET__";
oneloopp = new AstBegin(oneloopp->fileline(), nname, oneloopp, true);
}
pushDeletep(m_varValuep); m_varValuep = NULL;
VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = NULL);
if (newbodysp) newbodysp->addNext(oneloopp);
else newbodysp = oneloopp;

View File

@ -1081,7 +1081,7 @@ private:
if (VN_IS(nodep->fromp()->dtypep(), QueueDType)) {
switch (nodep->attrType()) {
case AstAttrType::DIM_SIZE: {
AstNode* newp = new AstCMethodCall(
AstNode* newp = new AstCMethodHard(
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", NULL);
newp->dtypeSetSigned32();
newp->didWidth(true);
@ -1097,7 +1097,7 @@ private:
}
case AstAttrType::DIM_RIGHT:
case AstAttrType::DIM_HIGH: {
AstNode* sizep = new AstCMethodCall(
AstNode* sizep = new AstCMethodHard(
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", NULL);
sizep->dtypeSetSigned32();
sizep->didWidth(true);
@ -1788,7 +1788,7 @@ private:
return false;
}
virtual void visit(AstCMethodCall* nodep) {
virtual void visit(AstCMethodHard* nodep) {
// Never created before V3Width, so no need to redo it
UASSERT_OBJ(nodep->dtypep(), nodep, "CMETHODCALLs should have already been sized");
}
@ -1936,11 +1936,11 @@ private:
}
}
void methodCallAssoc(AstMethodCall* nodep, AstAssocArrayDType* adtypep) {
AstCMethodCall* newp = NULL;
AstCMethodHard* newp = NULL;
if (nodep->name() == "num" // function int num()
|| nodep->name() == "size") {
methodOkArguments(nodep, 0, 0);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"size", NULL); // So don't need num()
newp->dtypeSetSigned32();
@ -1952,7 +1952,7 @@ private:
|| nodep->name() == "prev") {
methodOkArguments(nodep, 1, 1);
AstNode* index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
nodep->name(), // first/last/next/prev
index_exprp->unlinkFrBack());
@ -1963,7 +1963,7 @@ private:
// IEEE really should have made this a "bit" return
methodOkArguments(nodep, 1, 1);
AstNode* index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"exists", index_exprp->unlinkFrBack());
newp->dtypeSetSigned32();
@ -1974,14 +1974,14 @@ private:
methodOkArguments(nodep, 0, 1);
methodCallLValue(nodep, nodep->fromp(), true);
if (!nodep->pinsp()) {
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"clear", NULL);
newp->protect(false);
newp->makeStatement();
} else {
AstNode* index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"erase",
index_exprp->unlinkFrBack());
@ -2013,11 +2013,11 @@ private:
}
}
void methodCallQueue(AstMethodCall* nodep, AstQueueDType* adtypep) {
AstCMethodCall* newp = NULL;
AstCMethodHard* newp = NULL;
if (nodep->name() == "at") { // Created internally for []
methodOkArguments(nodep, 1, 1);
methodCallLValue(nodep, nodep->fromp(), true);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"at", NULL);
newp->dtypeFrom(adtypep->subDTypep());
@ -2026,7 +2026,7 @@ private:
} else if (nodep->name() == "num" // function int num()
|| nodep->name() == "size") {
methodOkArguments(nodep, 0, 0);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"size", NULL);
newp->dtypeSetSigned32();
@ -2036,7 +2036,7 @@ private:
methodOkArguments(nodep, 0, 1);
methodCallLValue(nodep, nodep->fromp(), true);
if (!nodep->pinsp()) {
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"clear", NULL);
newp->protect(false);
@ -2044,7 +2044,7 @@ private:
} else {
AstNode* index_exprp = methodCallQueueIndexExpr(nodep);
if (index_exprp->isZero()) { // delete(0) is a pop_front
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"pop_front", NULL);
newp->dtypeFrom(adtypep->subDTypep());
@ -2053,7 +2053,7 @@ private:
newp->makeStatement();
} else {
nodep->v3error("Unsupported: Queue .delete(index) method, as is O(n) complexity and slow.");
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack());
newp->protect(false);
@ -2067,14 +2067,14 @@ private:
AstArg* argp = VN_CAST(nodep->pinsp()->nextp(), Arg);
iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH);
if (index_exprp->isZero()) { // insert(0, ...) is a push_front
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"push_front", argp->exprp()->unlinkFrBack());
newp->protect(false);
newp->makeStatement();
} else {
nodep->v3error("Unsupported: Queue .insert method, as is O(n) complexity and slow.");
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
nodep->name(),
index_exprp->unlinkFrBack());
@ -2086,7 +2086,7 @@ private:
|| nodep->name() == "pop_back") {
methodOkArguments(nodep, 0, 0);
methodCallLValue(nodep, nodep->fromp(), true);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
nodep->name(), NULL);
newp->dtypeFrom(adtypep->subDTypep());
@ -2101,7 +2101,7 @@ private:
methodCallLValue(nodep, nodep->fromp(), true);
AstArg* argp = VN_CAST(nodep->pinsp(), Arg);
iterateCheckTyped(nodep, "push value", argp->exprp(), adtypep->subDTypep(), BOTH);
newp = new AstCMethodCall(nodep->fileline(),
newp = new AstCMethodHard(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
nodep->name(), argp->exprp()->unlinkFrBack());
newp->protect(false);
@ -2706,7 +2706,7 @@ private:
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) {
} else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch;
} else if (tolower(inPct)) {
inPct = false;
@ -2737,7 +2737,7 @@ private:
newFormat += "%@";
AstNRelinker handle;
argp->unlinkFrBack(&handle);
AstCMethodCall* newp = new AstCMethodCall(
AstCMethodHard* newp = new AstCMethodHard(
nodep->fileline(), argp, "to_string", NULL);
newp->dtypeSetString();
newp->pure(true);

View File

@ -262,7 +262,7 @@ private:
else if (AstQueueDType* adtypep = VN_CAST(ddtypep, QueueDType)) {
// SELBIT(array, index) -> CMETHODCALL(queue, "at", index)
AstNode* subp = rhsp;
AstCMethodCall* newp = new AstCMethodCall(nodep->fileline(),
AstCMethodHard* newp = new AstCMethodHard(nodep->fileline(),
fromp, "at", subp);
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference
if (debug()>=9) newp->dumpTree(cout, "--SELBTq: ");

View File

@ -113,7 +113,7 @@ AstNetlist* V3Global::makeNetlist() {
void V3Global::checkTree() { rootp()->checkTree(); }
void V3Global::clear() {
if (m_rootp) { m_rootp->deleteTree(); m_rootp = NULL; }
if (m_rootp) VL_DO_CLEAR(m_rootp->deleteTree(), m_rootp = NULL);
}
void V3Global::readFiles() {

View File

@ -110,7 +110,7 @@ public:
VlcTests() {}
~VlcTests() {
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
delete *it; *it=NULL;
VL_DO_CLEAR(delete *it, *it=NULL);
}
}

View File

@ -123,7 +123,7 @@ public:
}
void setVarDecl(AstVarType type) { m_varDecl = type; }
void setDType(AstNodeDType* dtypep) {
if (m_varDTypep) { m_varDTypep->deleteTree(); m_varDTypep=NULL; } // It was cloned, so this is safe.
if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep=NULL); // It was cloned, so this is safe.
m_varDTypep = dtypep;
}
AstPackage* unitPackage(FileLine* fl) {
@ -2364,7 +2364,10 @@ etcInst<nodep>: // IEEE: module_instantiation + gate_instantiation + udp_insta
instDecl<nodep>:
id parameter_value_assignmentE {INSTPREP($<fl>1,*$1,$2);} instnameList ';'
{ $$ = $4; GRAMMARP->m_impliedDecl=false;
if (GRAMMARP->m_instParamp) { GRAMMARP->m_instParamp->deleteTree(); GRAMMARP->m_instParamp = NULL; } }
if (GRAMMARP->m_instParamp) {
VL_DO_CLEAR(GRAMMARP->m_instParamp->deleteTree(),
GRAMMARP->m_instParamp = NULL);
} }
// // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers
| id/*interface*/ '.' id/*modport*/
{ VARRESET_NONLIST(AstVarType::IFACEREF);
@ -5356,13 +5359,17 @@ classExtendsE<nodep>: // IEEE: part of class_declaration
classExtendsList<nodep>: // IEEE: part of class_declaration
classExtendsOne { $$ = $1; }
| classExtendsList ',' classExtendsOne { $$ = AstNode::addNextNull($1, $3); }
| classExtendsList ',' classExtendsOne
{ $$ = $3; BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 8.13)"
", and unsupported for interface classes."); }
;
classExtendsOne<nodep>: // IEEE: part of class_declaration
class_typeWithoutId { $$ = NULL; BBUNSUP($1, "Unsupported: extends"); }
class_typeWithoutId
{ $$ = NULL; BBUNSUP($1, "Unsupported: extends"); }
// // IEEE: Might not be legal to have more than one set of parameters in an extends
| class_typeWithoutId '(' list_of_argumentsE ')' { $$ = NULL; BBUNSUP($1, "Unsupported: extends"); }
| class_typeWithoutId '(' list_of_argumentsE ')'
{ $$ = NULL; BBUNSUP($1, "Unsupported: extends"); }
;
classImplementsE<nodep>: // IEEE: part of class_declaration

View File

@ -51,5 +51,19 @@ extra argument: 0000000000000000
[0] Embedded <#013> return
[0] Embedded
multiline
'23 23 23'
'23 23 23 '
'23 23 23'
'23 23 23 '
' 24'
'24 '
' 0'
'0 '
' sv-str'
'sv-str '
' meep'
'meep '
' beep'
'beep '
log10(2) = 2
*-* All Finished *-*

View File

@ -13,7 +13,10 @@ module t;
reg [31:0] str; initial str = "\000\277\021\n";
reg [47:0] str2; initial str2 = "\000what!";
reg [79:0] str3; initial str3 = "\000hmmm!1234";
int n; initial n = 23;
reg [7:0] m; initial m = 24;
string svs = "sv-str";
reg [31:0] regstr = "meep";
sub sub ();
sub2 sub2 ();
@ -144,6 +147,22 @@ multiline", $time);
if (str !== 32'h00_bf_11_0a) $stop;
`endif
// Padding
$write("'%0d %2d %8d'\n", 23, 23, 23);
$write("'%-0d %-2d %-8d'\n", 23, 23, 23);
$write("'%0d %2d %8d'\n", n, n, n);
$write("'%-0d %-2d %-8d'\n", n, n, n);
$write("'%8d'\n", m);
$write("'%-8d'\n", m);
$write("'%8t'\n", $time);
$write("'%-8t'\n", $time);
$write("'%8s'\n", svs);
$write("'%-8s'\n", svs);
$write("'%8s'\n", regstr);
$write("'%-8s'\n", regstr);
$write("'%8s'\n", "beep");
$write("'%-8s'\n", "beep");
// $itord conversion bug, note a %d instead of proper float
$display("log10(2) = %d", $log10(100));

View File

@ -34,7 +34,10 @@ sub check {
for my $author (sort keys %Authors) {
print "Check: $author\n" if $Self->{verbose};
if (!$Contributors{$author}) {
error("Certify your contribution by appending '$author' to CONTRIBUTORS");
error("Certify your contribution by appending '$author' to docs/CONTRIBUTORS.\n"
." If '$author' is not your real name, please fix 'name=' in ~/.gitconfig\n"
." Also check your https://github.com account's Settings->Profile->Name\n"
." matches your ~/.gitconfig 'name='.\n");
}
}
}

View File

@ -0,0 +1,5 @@
%Error: t/t_tri_compass_bad.v:15: Unsupported: tristate in top-level IO: '__pinNumber1'
: ... In instance t
sub sub(i, o);
^
%Error: Exiting due to

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.
scenarios(vlt => 1);
compile(
expect_filename => $Self->{golden_filename},
fails => 1,
);
ok(1);
1;

View File

@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2020 by Wilson Snyder.
module t(/*AUTOARG*/
// Outputs
o,
// Inputs
i
);
input i;
output o;
sub sub(i, o);
endmodule
module sub(input i, output o);
assign o = (i===1'bz) ? 1'b0 : i;
endmodule

View File

@ -12,7 +12,7 @@
</module_files>
<cells>
<cell fl="d6" name="t" submodname="t" hier="t">
<cell fl="d18" name="cell1" submodname="mod1" hier="t.cell1"/>
<cell fl="d19" name="cell1" submodname="mod1__W4" hier="t.cell1"/>
<cell fl="d24" name="cell2" submodname="mod2" hier="t.cell2"/>
</cell>
</cells>
@ -22,57 +22,64 @@
<var fl="d13" name="d" dtype_id="2" dir="input" vartype="logic" origName="d"/>
<var fl="d14" name="q" dtype_id="2" dir="output" vartype="logic" origName="q"/>
<var fl="d16" name="between" dtype_id="2" vartype="logic" origName="between"/>
<instance fl="d18" name="cell1" defName="mod1" origName="cell1">
<port fl="d18" name="q" direction="out" portIndex="1">
<varref fl="d18" name="between" dtype_id="2"/>
<instance fl="d19" name="cell1" defName="mod1__W4" origName="cell1">
<port fl="d19" name="q" direction="out" portIndex="1">
<varref fl="d19" name="between" dtype_id="2"/>
</port>
<port fl="d21" name="clk" direction="in" portIndex="2">
<varref fl="d21" name="clk" dtype_id="1"/>
<port fl="d20" name="clk" direction="in" portIndex="2">
<varref fl="d20" name="clk" dtype_id="1"/>
</port>
<port fl="d22" name="d" direction="in" portIndex="3">
<varref fl="d22" name="d" dtype_id="2"/>
<port fl="d21" name="d" direction="in" portIndex="3">
<varref fl="d21" name="d" dtype_id="2"/>
</port>
</instance>
<instance fl="d24" name="cell2" defName="mod2" origName="cell2">
<port fl="d24" name="d" direction="in" portIndex="1">
<varref fl="d24" name="between" dtype_id="2"/>
</port>
<port fl="d27" name="q" direction="out" portIndex="2">
<varref fl="d27" name="q" dtype_id="2"/>
<port fl="d25" name="q" direction="out" portIndex="2">
<varref fl="d25" name="q" dtype_id="2"/>
</port>
<port fl="d29" name="clk" direction="in" portIndex="3">
<varref fl="d29" name="clk" dtype_id="1"/>
<port fl="d26" name="clk" direction="in" portIndex="3">
<varref fl="d26" name="clk" dtype_id="1"/>
</port>
</instance>
</module>
<module fl="d33" name="mod1" origName="mod1">
<var fl="d35" name="clk" dtype_id="1" dir="input" vartype="logic" origName="clk"/>
<var fl="d36" name="d" dtype_id="2" dir="input" vartype="logic" origName="d"/>
<var fl="d37" name="q" dtype_id="2" dir="output" vartype="logic" origName="q"/>
<always fl="d39">
<sentree fl="d39">
<senitem fl="d39" edgeType="POS">
<varref fl="d39" name="clk" dtype_id="1"/>
<module fl="d30" name="mod1__W4" origName="mod1">
<var fl="d31" name="WIDTH" dtype_id="3" vartype="logic" origName="WIDTH" param="true">
<const fl="d18" name="32&apos;sh4" dtype_id="3"/>
</var>
<var fl="d33" name="clk" dtype_id="1" dir="input" vartype="logic" origName="clk"/>
<var fl="d34" name="d" dtype_id="2" dir="input" vartype="logic" origName="d"/>
<var fl="d35" name="q" dtype_id="2" dir="output" vartype="logic" origName="q"/>
<var fl="d38" name="IGNORED" dtype_id="3" vartype="logic" origName="IGNORED" localparam="true">
<const fl="d38" name="32&apos;sh1" dtype_id="3"/>
</var>
<always fl="d40">
<sentree fl="d40">
<senitem fl="d40" edgeType="POS">
<varref fl="d40" name="clk" dtype_id="1"/>
</senitem>
</sentree>
<assigndly fl="d40" dtype_id="2">
<varref fl="d40" name="d" dtype_id="2"/>
<varref fl="d40" name="q" dtype_id="2"/>
<assigndly fl="d41" dtype_id="2">
<varref fl="d41" name="d" dtype_id="2"/>
<varref fl="d41" name="q" dtype_id="2"/>
</assigndly>
</always>
</module>
<module fl="d44" name="mod2" origName="mod2">
<var fl="d46" name="clk" dtype_id="1" dir="input" vartype="logic" origName="clk"/>
<var fl="d47" name="d" dtype_id="2" dir="input" vartype="logic" origName="d"/>
<var fl="d48" name="q" dtype_id="2" dir="output" vartype="logic" origName="q"/>
<contassign fl="d51" dtype_id="2">
<varref fl="d51" name="d" dtype_id="2"/>
<varref fl="d51" name="q" dtype_id="2"/>
<module fl="d45" name="mod2" origName="mod2">
<var fl="d47" name="clk" dtype_id="1" dir="input" vartype="logic" origName="clk"/>
<var fl="d48" name="d" dtype_id="2" dir="input" vartype="logic" origName="d"/>
<var fl="d49" name="q" dtype_id="2" dir="output" vartype="logic" origName="q"/>
<contassign fl="d52" dtype_id="2">
<varref fl="d52" name="d" dtype_id="2"/>
<varref fl="d52" name="q" dtype_id="2"/>
</contassign>
</module>
<typetable fl="a0">
<basicdtype fl="d46" id="1" name="logic"/>
<basicdtype fl="d47" id="1" name="logic"/>
<basicdtype fl="d13" id="2" name="logic" left="3" right="0"/>
<basicdtype fl="d18" id="3" name="logic" left="31" right="0"/>
</typetable>
</netlist>
</verilator_xml>

View File

@ -13,29 +13,30 @@ module t (/*AUTOARG*/
input [3:0] d;
output wire [3:0] q;
logic [3:0] between;
logic [3:0] between;
mod1 cell1 (.q(between),
/*AUTOINST*/
// Inputs
.clk (clk),
.d (d[3:0]));
mod1 #(.WIDTH(4))
cell1 (.q(between),
.clk (clk),
.d (d[3:0]));
mod2 cell2 (.d(between),
/*AUTOINST*/
// Outputs
.q (q[3:0]),
// Inputs
.clk (clk));
mod2
cell2 (.d(between),
.q (q[3:0]),
.clk (clk));
endmodule
module mod1
(
input clk,
input [3:0] d,
output logic [3:0] q
#(parameter WIDTH = 32)
(
input clk,
input [WIDTH-1:0] d,
output logic [WIDTH-1:0] q
);
localparam IGNORED = 1;
always @(posedge clk)
q <= d;