From 24fcae4f494b5432879dd02fd0b8b2f2adc6e262 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 25 May 2013 17:05:22 -0400 Subject: [PATCH] Internals: When broken link fatal, say which rule violated --- src/V3Ast.h | 15 +++++++----- src/V3AstNodes.cpp | 25 +++++++++++--------- src/V3AstNodes.h | 52 +++++++++++++++++++++--------------------- src/V3Broken.cpp | 4 ++-- test_regress/driver.pl | 2 +- 5 files changed, 52 insertions(+), 46 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index 7d58a3f61..7a0c4048f 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -38,6 +38,9 @@ class VFlagLogicPacked {}; class VFlagBitPacked {}; class VFlagChildDType {}; // Used by parser.y to select constructor that sets childDType +// For broken() function, return error string if have a match +#define BROKEN_RTN(test) do { if (VL_UNLIKELY(test)) return # test; } while(0) + //###################################################################### class AstType { @@ -1171,7 +1174,7 @@ public: virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc. - virtual bool broken() const { return false; } + virtual const char* broken() const { return NULL; } // INVOKERS virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0; @@ -1472,7 +1475,7 @@ public: } ASTNODE_BASE_FUNCS(NodeVarRef) virtual bool hasDType() const { return true; } - virtual bool broken() const; + virtual const char* broken() const; virtual int instrCount() const { return widthInstrs(); } virtual void cloneRelink(); virtual string name() const { return m_name; } // * = Var name @@ -1579,7 +1582,7 @@ public: numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); } ASTNODE_BASE_FUNCS(NodeClassDType) - virtual bool broken() const; + virtual const char* broken() const; virtual void dump(ostream& str); // For basicp() we reuse the size to indicate a "fake" basic type of same size virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); } @@ -1615,8 +1618,8 @@ public: ASTNODE_BASE_FUNCS(NodeArrayDType) virtual void dump(ostream& str); virtual void dumpSmall(ostream& str); - virtual bool broken() const { return !((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep())); } + virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); return NULL; } virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep()->castNodeDType(); }} @@ -1740,7 +1743,7 @@ public: addNOp2p(pinsp); } ASTNODE_BASE_FUNCS(NodeFTaskRef) - virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); } + virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) { m_taskp = m_taskp->clonep()->castNodeFTask(); }} diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index df1187036..36c0ed008 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -35,9 +35,10 @@ // Special methods // We need these here, because the classes they point to aren't defined when we declare the class -bool AstNodeVarRef::broken() const { - return ((m_varScopep && !m_varScopep->brokeExists()) - || (m_varp && !m_varp->brokeExists())); +const char* AstNodeVarRef::broken() const { + BROKEN_RTN(m_varScopep && !m_varScopep->brokeExists()); + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + return NULL; } void AstNodeVarRef::cloneRelink() { @@ -56,18 +57,18 @@ void AstNodeClassDType::repairMemberCache() { } } -bool AstNodeClassDType::broken() const { +const char* AstNodeClassDType::broken() const { set exists; for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { exists.insert(itemp); } for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) { - if (exists.find(it->second) == exists.end()) { + if (VL_UNLIKELY(exists.find(it->second) == exists.end())) { this->v3error("Internal: Structure member broken: "<first); - return true; + return "member broken"; } } - return false; + return NULL; } int AstBasicDType::widthAlignBytes() const { @@ -421,10 +422,12 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable return nodep; } -bool AstScope::broken() const { - return ((m_aboveScopep && !m_aboveScopep->brokeExists()) - || (m_aboveCellp && !m_aboveCellp->brokeExists()) - || !m_modp || !m_modp->brokeExists()); +const char* AstScope::broken() const { + BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists()); + BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists()); + BROKEN_RTN(!m_modp); + BROKEN_RTN(m_modp && !m_modp->brokeExists()); + return NULL; } void AstScope::cloneRelink() { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 3f794bd0a..e140ee05d 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -357,7 +357,7 @@ public: virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere return samep->castBasicDType()->m == m; } virtual string name() const { return m.m_keyword.ascii(); } - virtual bool broken() const { return dtypep()!=this; } + virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; } AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable void rangep(AstRange* nodep) { setNOp1p(nodep); } void setSignedState(VSignedState signst) { @@ -410,8 +410,8 @@ public: widthFromSub(subDTypep()); } ASTNODE_NODE_FUNCS(ConstDType, CONSTDTYPE) - virtual bool broken() const { return !((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep())); } + virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); return NULL; } virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep()->castNodeDType(); }} @@ -447,7 +447,7 @@ public: } ASTNODE_NODE_FUNCS(RefDType, REFDTYPE) // METHODS - virtual bool broken() const { return m_refDTypep && !m_refDTypep->brokeExists(); } + virtual const char* broken() const { BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep()->castNodeDType(); }} @@ -571,7 +571,7 @@ public: ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF) virtual void dump(ostream& str); virtual string name() const { return itemp()->name(); } - virtual bool broken() const { return !itemp(); } + virtual const char* broken() const { BROKEN_RTN(!itemp()); return NULL; } virtual int instrCount() const { return 0; } virtual void cloneRelink() { if (m_itemp->clonep()) m_itemp = m_itemp->clonep()->castEnumItem(); } virtual bool same(AstNode* samep) const { @@ -601,8 +601,8 @@ public: m_uniqueNum = uniqueNumInc(); } ASTNODE_NODE_FUNCS(EnumDType, ENUMDTYPE) - virtual bool broken() const { return !((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep())); } + virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); return NULL; } virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep()->castNodeDType(); }} @@ -1079,7 +1079,7 @@ public: ,m_name(name) ,m_aboveScopep(aboveScopep) ,m_aboveCellp(aboveCellp), m_modp(modp) {} ASTNODE_NODE_FUNCS(Scope, SCOPE) virtual void cloneRelink(); - virtual bool broken() const; + virtual const char* broken() const; virtual bool maybePointedTo() const { return true; } virtual string name() const { return m_name; } // * = Scope name virtual void name(const string& name) { m_name = name; } @@ -1133,8 +1133,8 @@ public: UASSERT(m_scopep->clonep(), "No clone cross link: "<clonep()->castScope(); }} - virtual bool broken() const { return ( (m_varp && !m_varp->brokeExists()) - || (m_scopep && !m_scopep->brokeExists())); } + virtual const char* broken() const { BROKEN_RTN(m_varp && !m_varp->brokeExists()); + BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); return NULL; } virtual bool maybePointedTo() const { return true; } virtual string name() const {return scopep()->name()+"->"+varp()->name();} // * = Var name virtual void dump(ostream& str); @@ -1234,7 +1234,7 @@ public: } ASTNODE_NODE_FUNCS(Pin, PIN) virtual void dump(ostream& str); - virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); } + virtual const char* broken() const { BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); return NULL; } virtual string name() const { return m_name; } // * = Pin name, ""=go by number virtual void name(const string& name) { m_name = name; } bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked @@ -1290,7 +1290,7 @@ public: AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name) : AstNode (fl), m_name(name), m_packagep(packagep) {} ASTNODE_NODE_FUNCS(PackageImport, PACKAGEIMPORT) - virtual bool broken() const { return (!m_packagep || !m_packagep->brokeExists()); } + virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep()->castPackage(); } virtual void dump(ostream& str); virtual string name() const { return m_name; } @@ -1315,7 +1315,7 @@ public: ASTNODE_NODE_FUNCS(Cell, CELL) // No cloneRelink, we presume cloneee's want the same module linkages virtual void dump(ostream& str); - virtual bool broken() const { return (m_modp && !m_modp->brokeExists()); } + virtual const char* broken() const { BROKEN_RTN(m_modp && !m_modp->brokeExists()); return NULL; } virtual bool maybePointedTo() const { return true; } // ACCESSORS virtual string name() const { return m_name; } // * = Cell name @@ -1440,7 +1440,7 @@ public: : AstNode(fl), m_packagep(packagep) {} ASTNODE_NODE_FUNCS(PackageRef, PACKAGEREF) // METHODS - virtual bool broken() const { return !m_packagep || !m_packagep->brokeExists(); } + virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) { m_packagep = m_packagep->clonep()->castPackage(); }} @@ -1799,10 +1799,10 @@ public: m_dataDeclp = NULL; } ASTNODE_NODE_FUNCS(CoverDecl, COVERDECL) - virtual bool broken() const { - if (m_dataDeclp && !m_dataDeclp->brokeExists()) return true; + virtual const char* broken() const { + BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); if (m_dataDeclp && m_dataDeclp->m_dataDeclp) v3fatalSrc("dataDeclp should point to real data, not be a list"); // Avoid O(n^2) accessing - return false; } + return NULL; } virtual void cloneRelink() { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep()->castCoverDecl(); } virtual void dump(ostream& str); virtual int instrCount() const { return 1+2*instrCountLd(); } @@ -1840,7 +1840,7 @@ public: m_declp = declp; } ASTNODE_NODE_FUNCS(CoverInc, COVERINC) - virtual bool broken() const { return !declp()->brokeExists(); } + virtual const char* broken() const { BROKEN_RTN(!declp()->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_declp->clonep()) m_declp = m_declp->clonep()->castCoverDecl(); } virtual void dump(ostream& str); virtual int instrCount() const { return 1+2*instrCountLd(); } @@ -1991,7 +1991,7 @@ public: } ASTNODE_NODE_FUNCS(Display, DISPLAY) virtual void dump(ostream& str); - virtual bool broken() const { return !fmtp(); } + virtual const char* broken() const { BROKEN_RTN(!fmtp()); return NULL; } virtual string verilogKwd() const { return (filep() ? (string)"$f"+(string)displayType().ascii() : (string)"$"+(string)displayType().ascii()); } virtual bool isGateOptimizable() const { return false; } @@ -2021,7 +2021,7 @@ struct AstSFormat : public AstNode { setOp3p(lhsp); } ASTNODE_NODE_FUNCS(SFormat, SFORMAT) - virtual bool broken() const { return !fmtp(); } + virtual const char* broken() const { BROKEN_RTN(!fmtp()); return NULL; } virtual string verilogKwd() const { return "$sformat"; } virtual string emitVerilog() { V3ERROR_NA; return ""; } virtual string emitC() { V3ERROR_NA; return ""; } @@ -2442,7 +2442,7 @@ public: m_labelp = labelp; } ASTNODE_NODE_FUNCS(JumpGo, JUMPGO) - virtual bool broken() const { return !labelp()->brokeExistsAbove(); } + virtual const char* broken() const { BROKEN_RTN(!labelp()->brokeExistsAbove()); return NULL; } virtual void cloneRelink() { if (m_labelp->clonep()) m_labelp = m_labelp->clonep()->castJumpLabel(); } virtual void dump(ostream& str); virtual int instrCount() const { return instrCountBranch(); } @@ -2719,7 +2719,7 @@ public: addNOp2p(valuep); } ASTNODE_NODE_FUNCS(TraceInc, TRACEINC) - virtual bool broken() const { return !declp()->brokeExists(); } + virtual const char* broken() const { BROKEN_RTN(!declp()->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_declp->clonep()) m_declp = m_declp->clonep()->castTraceDecl(); } virtual void dump(ostream& str); virtual int instrCount() const { return 10+2*instrCountLd(); } @@ -2756,7 +2756,7 @@ public: ASTNODE_NODE_FUNCS(Active, ACTIVE) virtual void dump(ostream& str=cout); virtual string name() const { return m_name; } - virtual bool broken() const { return (m_sensesp && !m_sensesp->brokeExists()); } + virtual const char* broken() const { BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists()); return NULL; } virtual void cloneRelink() { if (m_sensesp->clonep()) { m_sensesp = m_sensesp->clonep()->castSenTree(); @@ -4358,7 +4358,7 @@ public: } ASTNODE_NODE_FUNCS(CFunc, CFUNC) virtual string name() const { return m_name; } - virtual bool broken() const { return ( (m_scopep && !m_scopep->brokeExists())); } + virtual const char* broken() const { BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); return NULL; } virtual bool maybePointedTo() const { return true; } virtual void dump(ostream& str=cout); virtual V3Hash sameHash() const { return V3Hash(); } @@ -4446,7 +4446,7 @@ public: virtual void cloneRelink() { if (m_funcp && m_funcp->clonep()) { m_funcp = m_funcp->clonep()->castCFunc(); }} - virtual bool broken() const { return (m_funcp && !m_funcp->brokeExists()); } + virtual const char* broken() const { BROKEN_RTN(m_funcp && !m_funcp->brokeExists()); return NULL; } virtual int instrCount() const { return instrCountCall(); } virtual V3Hash sameHash() const { return V3Hash(funcp()); } virtual bool same(AstNode* samep) const { @@ -4578,7 +4578,7 @@ public: m_dollarUnitPkgp = NULL; } ASTNODE_NODE_FUNCS(Netlist, NETLIST) - virtual bool broken() const { return (m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); } + virtual const char* broken() const { BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); return NULL; } AstNodeModule* modulesp() const { return op1p()->castNodeModule();} // op1 = List of modules AstNodeModule* topModulep() const { return op1p()->castNodeModule(); } // * = Top module in hierarchy (first one added, for now) void addModulep(AstNodeModule* modulep) { addOp1p(modulep); } diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index ca11e7e93..ff728704b 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -202,8 +202,8 @@ class BrokenCheckVisitor : public AstNVisitor { private: virtual void visit(AstNode* nodep, AstNUser*) { BrokenTable::setUnder(nodep,true); - if (nodep->broken()) { - nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)"); + if (const char* whyp=nodep->broken()) { + nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<dtypep()) { if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); } diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 7ffc43e2a..3b9d3641e 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -878,7 +878,7 @@ sub _run { while (1) { my $buf = ''; my $got = sysread PARENTRD,$buf,10000; - last if $got==0; + last if defined $got && $got==0; print $buf if $param{tee}; print $logfh $buf if $logfh; }