From 597d28b505ec16f571685347a0050b279ad5781f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 1 Feb 2018 21:32:58 -0500 Subject: [PATCH] Fix internals to make null-pointer-check clean. Also add more const's. No functional change intended, but likely something will break. --- Changes | 4 + configure.ac | 1 - src/V3Active.cpp | 4 +- src/V3ActiveTop.cpp | 4 +- src/V3Assert.cpp | 14 +- src/V3Ast.cpp | 10 +- src/V3Ast.h | 69 +++-- src/V3AstNodes.cpp | 69 ++--- src/V3AstNodes.h | 120 ++++----- src/V3Broken.cpp | 10 +- src/V3CCtors.cpp | 10 +- src/V3Case.cpp | 32 +-- src/V3Cast.cpp | 8 +- src/V3Cdc.cpp | 8 +- src/V3Changed.cpp | 2 +- src/V3Clean.cpp | 8 +- src/V3ClkGater.cpp | 6 +- src/V3Clock.cpp | 6 +- src/V3Combine.cpp | 10 +- src/V3Const.cpp | 598 +++++++++++++++++++++-------------------- src/V3Coverage.cpp | 18 +- src/V3CoverageJoin.cpp | 2 +- src/V3Dead.cpp | 14 +- src/V3Delayed.cpp | 42 +-- src/V3Depth.cpp | 2 +- src/V3DepthBlock.cpp | 2 +- src/V3Descope.cpp | 4 +- src/V3EmitC.cpp | 178 ++++++------ src/V3EmitCBase.h | 6 +- src/V3EmitCSyms.cpp | 10 +- src/V3EmitMk.cpp | 2 +- src/V3EmitV.cpp | 28 +- src/V3EmitXml.cpp | 4 +- src/V3Expand.cpp | 58 ++-- src/V3Gate.cpp | 78 +++--- src/V3GenClk.cpp | 2 +- src/V3Hashed.cpp | 4 +- src/V3Inline.cpp | 34 +-- src/V3Inst.cpp | 66 ++--- src/V3Life.cpp | 6 +- src/V3LifePost.cpp | 4 +- src/V3LinkCells.cpp | 26 +- src/V3LinkDot.cpp | 188 ++++++------- src/V3LinkJump.cpp | 22 +- src/V3LinkLValue.cpp | 2 +- src/V3LinkLevel.cpp | 10 +- src/V3LinkParse.cpp | 18 +- src/V3LinkResolve.cpp | 47 ++-- src/V3Localize.cpp | 6 +- src/V3Order.cpp | 26 +- src/V3Param.cpp | 126 ++++----- src/V3Premit.cpp | 28 +- src/V3Scope.cpp | 6 +- src/V3Simulate.h | 36 +-- src/V3Slice.cpp | 36 +-- src/V3Split.cpp | 2 +- src/V3Stats.cpp | 4 +- src/V3Subst.cpp | 14 +- src/V3SymTable.h | 6 +- src/V3Table.cpp | 10 +- src/V3Task.cpp | 60 ++--- src/V3Trace.cpp | 12 +- src/V3TraceDecl.cpp | 6 +- src/V3Tristate.cpp | 36 +-- src/V3Undriven.cpp | 6 +- src/V3Unknown.cpp | 36 +-- src/V3Unroll.cpp | 22 +- src/V3Width.cpp | 286 ++++++++++---------- src/V3WidthCommit.h | 2 +- src/V3WidthSel.cpp | 56 ++-- src/astgen | 40 ++- src/verilog.l | 10 +- src/verilog.y | 52 ++-- 73 files changed, 1421 insertions(+), 1373 deletions(-) mode change 100755 => 100644 src/astgen diff --git a/Changes b/Changes index 13dc1c06c..cf9ec6f38 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,10 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.000 devel +** This is a major release. Any patches may require major rework to apply. + +** Fix internals to make null-pointer-check clean. + **** Fix internals to avoid 'using namespace std'. diff --git a/configure.ac b/configure.ac index bdab2c727..e6e079c44 100644 --- a/configure.ac +++ b/configure.ac @@ -199,7 +199,6 @@ AC_SUBST(CFG_CXXFLAGS_WEXTRA) # Flags for compiling Verilator internals including parser always _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-faligned-new) -_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow) diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 5966a2b69..a6687fe43 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -312,8 +312,8 @@ private: // Move always to appropriate ACTIVE based on its sense list if (oldsensesp && oldsensesp->sensesp() - && oldsensesp->sensesp()->castSenItem() - && oldsensesp->sensesp()->castSenItem()->isNever()) { + && VN_IS(oldsensesp->sensesp(), SenItem) + && VN_CAST(oldsensesp->sensesp(), SenItem)->isNever()) { // Never executing. Kill it. if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated."); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index 63b8d6cc9..e4e923418 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -83,8 +83,8 @@ private: AstSenTree* sensesp = nodep->sensesp(); if (!sensesp) nodep->v3fatalSrc("NULL"); if (sensesp->sensesp() - && sensesp->sensesp()->castSenItem() - && sensesp->sensesp()->castSenItem()->isNever()) { + && VN_IS(sensesp->sensesp(), SenItem) + && VN_CAST(sensesp->sensesp(), SenItem)->isNever()) { // Never executing. Kill it. if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated."); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 1092515d5..44fbec8f0 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -105,12 +105,12 @@ private: // AstNode* bodysp = NULL; bool selfDestruct = false; - if (AstPslCover* snodep = nodep->castPslCover()) { + if (AstPslCover* snodep = VN_CAST(nodep, PslCover)) { if (!v3Global.opt.coverageUser()) { selfDestruct = true; } else { // V3Coverage assigned us a bucket to increment. - AstCoverInc* covincp = snodep->coverincp()->castCoverInc(); + AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc); if (!covincp) snodep->v3fatalSrc("Missing AstCoverInc under assertion"); covincp->unlinkFrBack(); if (message!="") covincp->declp()->comment(message); @@ -122,7 +122,7 @@ private: if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp); AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL); bodysp = ifp; - if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY); + if (VN_IS(nodep, VAssert)) ifp->branchPred(AstBranchPred::BP_UNLIKELY); // AstNode* newp = new AstAlways (nodep->fileline(), VAlwaysKwd::ALWAYS, @@ -146,7 +146,7 @@ private: AstNode* passsp = nodep->passsp(); if (passsp) passsp->unlinkFrBackWithNext(); AstNode* failsp = nodep->failsp(); if (failsp) failsp->unlinkFrBackWithNext(); // - if (nodep->castVAssert()) { + if (VN_IS(nodep, VAssert)) { if (passsp) passsp = newIfAssertOn(passsp); if (failsp) failsp = newIfAssertOn(failsp); } else { @@ -155,7 +155,7 @@ private: AstIf* ifp = new AstIf (nodep->fileline(), propp, passsp, failsp); AstNode* newp = ifp; - if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY); + if (VN_IS(nodep, VAssert)) ifp->branchPred(AstBranchPred::BP_UNLIKELY); // // Install it nodep->replaceWith(newp); @@ -227,7 +227,7 @@ private: nodep->iterateChildren(*this); if (!nodep->user1SetOnce()) { bool has_default=false; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (itemp->isDefault()) has_default=true; } if (nodep->fullPragma() || nodep->priorityPragma()) { @@ -246,7 +246,7 @@ private: // Not parallel, but harmlessly so. } else { AstNode* propp = NULL; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { AstNode* onep; if (nodep->casex() || nodep->casez() || nodep->caseInside()) { diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 2013fec2b..4e79c8873 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -828,7 +828,7 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) { // To solve this, this function returns the pointer to the replacement node, // which in many cases is just the same node that was passed in. AstNode* nodep = this; // Note "this" may point to bogus point later in this function - if (nodep->castNetlist()) { + if (VN_IS(nodep, Netlist)) { // Calling on top level; we know the netlist won't get replaced nodep->accept(v); } else if (!nodep->backp()) { @@ -875,7 +875,7 @@ void AstNode::cloneRelinkTree() { //====================================================================== // Comparison -bool AstNode::gateTreeIter() { +bool AstNode::gateTreeIter() const { // private: Return true if the two trees are identical if (!isGateOptimizable()) return false; if (m_op1p && !m_op1p->gateTreeIter()) return false; @@ -885,7 +885,7 @@ bool AstNode::gateTreeIter() { return true; } -bool AstNode::sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly) { +bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext, bool gateOnly) const { // private: Return true if the two trees are identical if (!node1p && !node2p) return true; if (!node1p || !node2p) return false; @@ -927,7 +927,7 @@ void AstNode::checkTreeIter(AstNode* backp) { if (backp != this->backp()) { this->v3fatalSrc("Back node inconsistent"); } - if (castNodeTermop() || castNodeVarRef()) { + if (VN_IS(this, NodeTermop) || VN_IS(this, NodeVarRef)) { // Termops have a short-circuited iterateChildren, so check usage if (op1p()||op2p()||op3p()||op4p()) this->v3fatalSrc("Terminal operation with non-terminals"); @@ -1055,7 +1055,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) { checkTree(); // Broken isn't part of check tree because it can munge iterp's // set by other steps if it is called in the middle of other operations - if (AstNetlist* netp=this->castNetlist()) V3Broken::brokenAll(netp); + if (AstNetlist* netp=VN_CAST(this, Netlist)) V3Broken::brokenAll(netp); } // Next dump can indicate start from here editCountSetLast(); diff --git a/src/V3Ast.h b/src/V3Ast.h index c98a7587d..b4ee6f7b0 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -44,6 +44,15 @@ class VFlagChildDType {}; // Used by parser.y to select constructor that sets c //###################################################################### +// (V)erilator (N)ode (is)): True if AstNode is of a a given AstType +#define VN_IS(nodep,nodetypename) (AstNode::privateIs ## nodetypename(nodep)) + +// (V)erilator (N)ode (cast): Cast to given type if can; effectively dynamic_cast(nodep)(nodetypename) +#define VN_CAST(nodep,nodetypename) (AstNode::privateCast ## nodetypename(nodep)) +#define VN_CAST_CONST(nodep,nodetypename) (AstNode::privateConstCast ## nodetypename(nodep) ) + +//###################################################################### + class AstType { public: #include "V3Ast__gen_types.h" // From ./astgen @@ -1048,8 +1057,8 @@ private: AstNode* cloneTreeIterList(); void checkTreeIter(AstNode* backp); void checkTreeIterList(AstNode* backp); - bool gateTreeIter(); - bool sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly); + bool gateTreeIter() const; + bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext, bool gateOnly) const; void deleteTreeIter(); void deleteNode(); public: @@ -1240,11 +1249,11 @@ public: // ACCESSORS for specific types // Alas these can't be virtual or they break when passed a NULL - bool isZero(); - bool isOne(); - bool isNeqZero(); - bool isAllOnes(); - bool isAllOnesV(); // Verilog width rules apply + bool isZero() const; + bool isOne() const; + bool isNeqZero() const; + bool isAllOnes() const; + bool isAllOnesV() const; // Verilog width rules apply // METHODS - data type changes especially for initial creation void dtypep(AstNodeDType* nodep) { if (m_dtypep != nodep) { m_dtypep = nodep; editCountInc(); } } @@ -1303,8 +1312,8 @@ public: // METHODS - Iterate on a tree AstNode* cloneTree(bool cloneNextLink); bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable? - bool sameTree(AstNode* node2p); // Does tree of this == node2p? - bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable + bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p? + bool sameGateTree(const AstNode* node2p) const; // Does tree of this == node2p?, not allowing non-isGateOptimizable void deleteTree(); // Always deletes the next link void checkTree(); // User Interface version void checkIter() const; @@ -1376,7 +1385,7 @@ public: virtual bool cleanOut() = 0; // True if output has extra upper bits zero // Someday we will generically support data types on every math node // Until then isOpaque indicates we shouldn't constant optimize this node type - bool isOpaque() { return castCvtPackString()!=NULL; } + bool isOpaque() { return VN_IS(this, CvtPackString); } }; class AstNodeTermop : public AstNodeMath { @@ -1516,7 +1525,7 @@ public: AstNode* fromp() const { return lhsp(); } AstNode* rhsp() const { return op2p(); } AstNode* thsp() const { return op3p(); } - AstAttrOf* attrp() const { return op4p()->castAttrOf(); } + AstAttrOf* attrp() const { return VN_CAST(op4p(), AttrOf); } void lhsp(AstNode* nodep) { return setOp1p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); } void thsp(AstNode* nodep) { return setOp3p(nodep); } @@ -1611,7 +1620,7 @@ public: ASTNODE_BASE_FUNCS(NodeCase) virtual int instrCount() const { return instrCountBranch(); } AstNode* exprp() const { return op1p(); } // op1 = case condition - AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions + AstCaseItem* itemsp() const { return VN_CAST(op2p(), CaseItem); } // op2 = list of case expressions AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's void addItemsp(AstNode* nodep) { addOp2p(nodep); } void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } @@ -1774,8 +1783,9 @@ public: virtual void dump(std::ostream& str); // For basicp() we reuse the size to indicate a "fake" basic type of same size virtual AstBasicDType* basicp() const { - return (isFourstate() ? findLogicDType(width(),width(),numeric())->castBasicDType() - : findBitDType(width(),width(),numeric())->castBasicDType()); } + return (isFourstate() + ? VN_CAST(findLogicDType(width(),width(),numeric()), BasicDType) + : VN_CAST(findBitDType(width(),width(),numeric()), BasicDType)); } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } @@ -1785,7 +1795,7 @@ public: virtual bool similarDType(AstNodeDType* samep) const { return this==samep; // We don't compare members, require exact equivalence } - AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list + AstMemberDType* membersp() const { return VN_CAST(op1p(), MemberDType); } // op1 = AstMember list void addMembersp(AstNode* nodep) { addNOp1p(nodep); } bool packed() const { return m_packed; } bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs @@ -1836,13 +1846,13 @@ public: } virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - AstRange* rangep() const { return op2p()->castRange(); } // op2 = Array(s) of variable + AstRange* rangep() const { return VN_CAST(op2p(), Range); } // op2 = Array(s) of variable void rangep(AstRange* nodep); // METHODS virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type @@ -1927,7 +1937,7 @@ public: AstNode* stmtsp() const { return op3p(); } // op3 = List of statements void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } // op4 = scope name - AstScopeName* scopeNamep() const { return op4p()->castScopeName(); } + AstScopeName* scopeNamep() const { return VN_CAST(op4p(), ScopeName); } // MORE ACCESSORS void dpiOpenParentInc() { ++m_dpiOpenParent; } void dpiOpenParentClear() { m_dpiOpenParent=0; } @@ -1996,7 +2006,7 @@ public: AstNode* pinsp() const { return op2p(); } void addPinsp(AstNode* nodep) { addOp2p(nodep); } // op3 = scope tracking - AstScopeName* scopeNamep() const { return op3p()->castScopeName(); } + AstScopeName* scopeNamep() const { return VN_CAST(op3p(), ScopeName); } void scopeNamep(AstNode* nodep) { setNOp3p(nodep); } }; @@ -2029,7 +2039,7 @@ public: virtual bool maybePointedTo() const { return true; } virtual string name() const { return m_name; } AstNode* stmtsp() const { return op2p(); } // op2 = List of statements - AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks + AstActive* activesp() const { return VN_CAST(op3p(), Active); } // op3 = List of i/sblocks // METHODS void addInlinesp(AstNode* nodep) { addOp1p(nodep); } void addStmtp(AstNode* nodep) { addOp2p(nodep); } @@ -2071,7 +2081,8 @@ public: #include "V3Ast__gen_impl.h" // From ./astgen // Things like: -// inline AstAlways* AstNode::castAlways() { return dynamic_cast(this);} +// inline AstAlways* AstNode::castAlways() { return dynamic_cast(this);} +// inline bool AstNode::privateIsaAlways(const AstNode* nodep) { return nodep && nodep->type() == AstType::atAlways; } //###################################################################### // Inline ACCESSORS @@ -2080,17 +2091,17 @@ inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); } -inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); } +inline bool AstNode::isDouble() const { return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); } inline bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); } inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); } -inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); } -inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); } -inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); } -inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); } -inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); } -inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, false); } -inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, true); } +inline bool AstNode::isZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqZero()); } +inline bool AstNode::isNeqZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isNeqZero()); } +inline bool AstNode::isOne() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqOne()); } +inline bool AstNode::isAllOnes() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->isEqAllOnes()); } +inline bool AstNode::isAllOnesV() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->isEqAllOnesV()); } +inline bool AstNode::sameTree(const AstNode* node2p) const { return sameTreeIter(this, node2p, true, false); } +inline bool AstNode::sameGateTree(const AstNode* node2p) const { return sameTreeIter(this, node2p, true, true); } inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 246db14cb..942505d71 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -44,7 +44,7 @@ const char* AstIfaceRefDType::broken() const { } AstIface* AstIfaceRefDType::ifaceViaCellp() const { - return ((m_cellp && m_cellp->modp()) ? m_cellp->modp()->castIface() : m_ifacep); + return ((m_cellp && m_cellp->modp()) ? VN_CAST(m_cellp->modp(), Iface) : m_ifacep); } const char* AstNodeVarRef::broken() const { @@ -58,12 +58,13 @@ void AstNodeVarRef::cloneRelink() { } int AstNodeSel::bitConst() const { - AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0); + AstConst* constp=VN_CAST(bitp(), Const); + return (constp ? constp->toSInt() : 0); } void AstNodeClassDType::repairMemberCache() { clearCache(); - for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { + for (AstMemberDType* itemp = membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<prettyName()); } else m_members.insert(make_pair(itemp->name(), itemp)); } @@ -71,7 +72,7 @@ void AstNodeClassDType::repairMemberCache() { const char* AstNodeClassDType::broken() const { vl_unordered_set exists; - for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { + for (AstMemberDType* itemp = membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { exists.insert(itemp); } for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) { @@ -243,7 +244,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const { arg += " (& "+name()+")"; for (AstNodeDType* dtp=dtypep(); dtp; ) { dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstUnpackArrayDType* adtypep = dtp->castUnpackArrayDType()) { + if (AstUnpackArrayDType* adtypep = VN_CAST(dtp, UnpackArrayDType)) { arg += "["+cvtToStr(adtypep->declRange().elements())+"]"; dtp = adtypep->subDTypep(); } else break; @@ -315,7 +316,7 @@ string AstVar::vlPropInit() const { bool first = true; for (AstNodeDType* dtp=dtypep(); dtp; ) { dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstNodeArrayDType* adtypep = dtp->castNodeArrayDType()) { + if (AstNodeArrayDType* adtypep = VN_CAST(dtp, NodeArrayDType)) { if (first) { out += ", VerilatedVarProps::Unpacked()"; first = false; @@ -422,15 +423,15 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) { // See if this is a SC assignment; if so return that type // Historically sc variables are identified by a variable // attribute. TODO it would better be a data type attribute. - if (AstVar* anodep = nodep->castVar()) { + if (AstVar* anodep = VN_CAST(nodep, Var)) { if (anodep->isSc()) return anodep; else return NULL; } - else if (nodep->castVarRef()) { - if (nodep->castVarRef()->varp()->isSc()) return nodep->castVarRef()->varp(); + else if (VN_IS(nodep, VarRef)) { + if (VN_CAST(nodep, VarRef)->varp()->isSc()) return VN_CAST(nodep, VarRef)->varp(); else return NULL; } - else if (nodep->castArraySel()) { + else if (VN_IS(nodep, ArraySel)) { if (nodep->op1p()) if (AstVar* p = scVarRecurse(nodep->op1p())) return p; if (nodep->op2p()) if (AstVar* p = scVarRecurse(nodep->op2p())) return p; if (nodep->op3p()) if (AstVar* p = scVarRecurse(nodep->op3p())) return p; @@ -457,14 +458,14 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) { UDEBUGONLY(UASSERT(dynamic_cast(this),"this should not be NULL");); for (AstNodeDType* dtypep=this; dtypep; ) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { + if (AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { if ((dim++)==dimension) { return dtypep; } dtypep = adtypep->subDTypep(); continue; } - else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { + else if (AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { // AstBasicDType - nothing below, return null if (adtypep->isRanged()) { if ((dim++) == dimension) { @@ -473,7 +474,7 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) { } return NULL; } - else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) { + else if (AstNodeClassDType* adtypep = VN_CAST(dtypep, NodeClassDType)) { if (adtypep->packed()) { if ((dim++) == dimension) { return adtypep; @@ -492,7 +493,7 @@ uint32_t AstNodeDType::arrayUnpackedElements() { UDEBUGONLY(UASSERT(dynamic_cast(this),"this should not be NULL");); for (AstNodeDType* dtypep=this; dtypep; ) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) { + if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { entries *= adtypep->elementsConst(); dtypep = adtypep->subDTypep(); } @@ -511,13 +512,13 @@ std::pair AstNodeDType::dimensions(bool includeBasic) { UDEBUGONLY(UASSERT(dynamic_cast(this),"this should not be NULL");); for (AstNodeDType* dtypep=this; dtypep; ) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { - if (adtypep->castPackArrayDType()) packed++; + if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { + if (VN_IS(adtypep, PackArrayDType)) packed++; else unpacked++; dtypep = adtypep->subDTypep(); continue; } - else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { + else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { if (includeBasic && adtypep->isRanged()) packed++; } break; @@ -537,15 +538,15 @@ int AstNodeDType::widthPow2() const { AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences? // Else AstArraySel etc; search for the base while (nodep) { - if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; } - else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; } + if (VN_IS(nodep, ArraySel)) { nodep=VN_CAST(nodep, ArraySel)->fromp(); continue; } + else if (VN_IS(nodep, Sel)) { nodep=VN_CAST(nodep, Sel)->fromp(); continue; } // AstNodeSelPre stashes the associated variable under an ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified - else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; } - else if (nodep->castNodePreSel()) { - if (nodep->castNodePreSel()->attrp()) { - nodep=nodep->castNodePreSel()->attrp(); + else if (VN_IS(nodep, AttrOf)) { nodep=VN_CAST(nodep, AttrOf)->fromp(); continue; } + else if (VN_IS(nodep, NodePreSel)) { + if (VN_CAST(nodep, NodePreSel)->attrp()) { + nodep=VN_CAST(nodep, NodePreSel)->attrp(); } else { - nodep=nodep->castNodePreSel()->lhsp(); + nodep=VN_CAST(nodep, NodePreSel)->lhsp(); } continue; } @@ -579,7 +580,7 @@ string AstScope::nameDotless() const { string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const { string out; - for (AstText* textp=scopeTextp; textp; textp=textp->nextp()->castText()) { + for (AstText* textp=scopeTextp; textp; textp=VN_CAST(textp->nextp(), Text)) { out += textp->text(); } // TOP will be replaced by top->name() @@ -591,7 +592,7 @@ string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const { string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const { string out; - for (AstText* textp=scopeTextp; textp; textp=textp->nextp()->castText()) { + for (AstText* textp=scopeTextp; textp; textp=VN_CAST(textp->nextp(), Text)) { out += textp->text(); } if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,""); @@ -609,28 +610,28 @@ string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const { bool AstSenTree::hasClocked() const { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isClocked()) return true; } return false; } bool AstSenTree::hasSettle() const { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isSettle()) return true; } return false; } bool AstSenTree::hasInitial() const { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isInitial()) return true; } return false; } bool AstSenTree::hasCombo() const { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isCombo()) return true; } return false; @@ -651,7 +652,7 @@ void AstTypeTable::clearCache() { m_detailedMap.clear(); // Clear generic()'s so dead detection will work for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) { - if (AstBasicDType* bdtypep = nodep->castBasicDType()) { + if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) { bdtypep->generic(false); } } @@ -661,7 +662,7 @@ void AstTypeTable::repairCache() { // After we mass-change widthMin in V3WidthCommit, we need to correct the table. clearCache(); for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) { - if (AstBasicDType* bdtypep = nodep->castBasicDType()) { + if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) { (void)findInsertSameDType(bdtypep); } } @@ -812,7 +813,7 @@ void AstNode::dump(std::ostream& str) { if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep(); } if (name()!="") { - if (castConst()) str<<" "<AstNodeDType::dumpSmall(str); - if (castPackArrayDType()) str<<"p"; else str<<"u"; + if (VN_IS(this, PackArrayDType)) str<<"p"; else str<<"u"; str<castConst(); return (constp?constp->toSInt():0); } - int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->toSInt():0); } + int msbConst() const { AstConst* constp=VN_CAST(msbp(), Const); return (constp?constp->toSInt():0); } + int lsbConst() const { AstConst* constp=VN_CAST(lsbp(), Const); return (constp?constp->toSInt():0); } int elementsConst() const { return (msbConst()>lsbConst()) ? msbConst()-lsbConst()+1 : lsbConst()-msbConst()+1; } - int leftConst() const { AstConst* constp=leftp()->castConst(); return (constp?constp->toSInt():0); } - int rightConst() const { AstConst* constp=rightp()->castConst(); return (constp?constp->toSInt():0); } + int leftConst() const { AstConst* constp=VN_CAST(leftp(), Const); return (constp?constp->toSInt():0); } + int rightConst() const { AstConst* constp=VN_CAST(rightp(), Const); return (constp?constp->toSInt():0); } int leftToRightInc() const { return littleEndian()?1:-1; } bool littleEndian() const { return m_littleEndian; } void littleEndian(bool flag) { m_littleEndian=flag; } @@ -168,7 +168,7 @@ public: virtual string emitC() { V3ERROR_NA; return ""; } virtual bool cleanOut() { return true; } AstNode* exprp() const { return op1p(); } // op1 = Pin expression - AstRange* rangep() const { return op2p()->castRange(); } // op2 = Range of pin + AstRange* rangep() const { return VN_CAST(op2p(), Range); } // op2 = Range of pin }; //###################################################################### @@ -188,7 +188,7 @@ public: } ASTNODE_NODE_FUNCS(ParamTypeDType) AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Type assigning to void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type @@ -196,7 +196,7 @@ public: virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } virtual bool similarDType(AstNodeDType* samep) const { - AstParamTypeDType* sp = samep->castParamTypeDType(); + const AstParamTypeDType* sp = static_cast(samep); return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp())); } virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); } @@ -227,7 +227,7 @@ public: ASTNODE_NODE_FUNCS(Typedef) virtual void dump(std::ostream& str); AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Type assigning to void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } @@ -279,7 +279,7 @@ public: return type()==samep->type() && same(samep); } virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } void* containerp() const { return m_containerp; } @@ -373,7 +373,7 @@ public: virtual void dumpSmall(std::ostream& str); virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } @@ -466,7 +466,7 @@ public: return type()==samep->type() && same(samep); } virtual string name() const { return m.m_keyword.ascii(); } virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; } - AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable + AstRange* rangep() const { return VN_CAST(op1p(), Range); } // op1 = Range of variable void rangep(AstRange* nodep) { setNOp1p(nodep); } void setSignedState(VSignedState signst) { // Note NOSIGN does NOT change the state; this is required by the parser @@ -498,7 +498,7 @@ public: bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; } VNumRange declRange() const { return isRanged() ? VNumRange(msb(), lsb(), littleEndian()) : VNumRange(); } void cvtRangeConst() { // Convert to smaller represenation - if (rangep() && rangep()->msbp()->castConst() && rangep()->lsbp()->castConst()) { + if (rangep() && VN_IS(rangep()->msbp(), Const) && VN_IS(rangep()->lsbp(), Const)) { m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(), rangep()->littleEndian()); rangep()->unlinkFrBackWithNext()->deleteTree(); @@ -534,7 +534,7 @@ public: return skipRefp()->similarDType(samep->skipRefp()); } virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } // node's type() included elsewhere AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } // op1 = Range of variable void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } @@ -698,7 +698,7 @@ public: virtual bool hasDType() const { return true; } virtual bool maybePointedTo() const { return true; } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } @@ -734,7 +734,7 @@ public: virtual bool maybePointedTo() const { return true; } virtual bool hasDType() const { return true; } void name(const string& flag) { m_name = flag; } - AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range for name appending + AstRange* rangep() const { return VN_CAST(op1p(), Range); } // op1 = Range for name appending void rangep(AstNode* nodep) { addOp1p(nodep); } AstNode* valuep() const { return op2p(); } // op2 = Value void valuep(AstNode* nodep) { addOp2p(nodep); } @@ -754,7 +754,7 @@ public: virtual string name() const { return itemp()->name(); } 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 void cloneRelink() { if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); } virtual bool same(const AstNode* samep) const { const AstEnumItemRef* sp = static_cast(samep); return itemp() == sp->itemp(); } @@ -794,13 +794,13 @@ public: virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Data type + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Data type void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } // op1 = Range of variable void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - AstEnumItem* itemsp() const { return op2p()->castEnumItem(); } // op2 = AstEnumItem's + AstEnumItem* itemsp() const { return VN_CAST(op2p(), EnumItem); } // op2 = AstEnumItem's void addValuesp(AstNode* nodep) { addOp2p(nodep); } // METHODS virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type @@ -837,9 +837,9 @@ class AstArraySel : public AstNodeSel { // Children: varref|arraysel, math private: void init(AstNode* fromp) { - if (fromp && fromp->dtypep()->skipRefp()->castNodeArrayDType()) { + if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) { // Strip off array to find what array references - dtypeFrom(fromp->dtypep()->skipRefp()->castNodeArrayDType()->subDTypep()); + dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); } } public: @@ -945,9 +945,9 @@ public: AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp) :AstNodeTriop(fl, fromp, lsbp, widthp) { m_declElWidth = 1; - if (widthp->castConst()) { - dtypeSetLogicSized(widthp->castConst()->toUInt(), - widthp->castConst()->toUInt(), + if (VN_IS(widthp, Const)) { + dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(), + VN_CAST(widthp, Const)->toUInt(), AstNumeric::UNSIGNED); } } @@ -973,13 +973,13 @@ public: virtual bool sizeMattersThs() {return false;} virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode*) const { return true; } - virtual int instrCount() const { return widthInstrs()*(lsbp()->castConst()?3:10); } + virtual int instrCount() const { return widthInstrs()*(VN_CAST(lsbp(), Const)?3:10); } AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) AstNode* lsbp() const { return op2p(); } // op2 = Msb selection expression AstNode* widthp() const { return op3p(); } // op3 = Width - int widthConst() const { return widthp()->castConst()->toSInt(); } - int lsbConst() const { return lsbp()->castConst()->toSInt(); } - int msbConst() const { return lsbConst()+widthConst()-1; } + int widthConst() const { return VN_CAST(widthp(), Const)->toSInt(); } + int lsbConst() const { return VN_CAST(lsbp(), Const)->toSInt(); } + int msbConst() const { return lsbConst()+widthConst()-1; } VNumRange& declRange() { return m_declRange; } void declRange(const VNumRange& flag) { m_declRange = flag; } int declElWidth() const { return m_declElWidth; } @@ -1189,7 +1189,7 @@ public: string vlPropInit() const; // Return VerilatorVarProps initializer void combineType(AstVarType type); AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType) AstNode* valuep() const { return op3p(); } // op3 = Initial value that never changes (static const) @@ -1396,7 +1396,7 @@ public: ASTNODE_NODE_FUNCS(TopScope) AstNode* stmtsp() const { return op1p(); } void addStmtsp(AstNode* nodep) { addOp1p(nodep); } - AstScope* scopep() const { return op2p()->castScope(); } // op1 = AstVarScope's + AstScope* scopep() const { return VN_CAST(op2p(), Scope); } // op1 = AstVarScope's }; class AstVarScope : public AstNode { @@ -1753,9 +1753,9 @@ public: void origName(const string& name) { m_origName = name; } string modName() const { return m_modName; } // * = Instance name void modName(const string& name) { m_modName = name; } - AstPin* pinsp() const { return op1p()->castPin(); } // op1 = List of cell ports - AstPin* paramsp() const { return op2p()->castPin(); } // op2 = List of parameter #(##) values - AstRange* rangep() const { return op3p()->castRange(); } // op3 = Range of arrayed instants (NULL=not ranged) + AstPin* pinsp() const { return VN_CAST(op1p(), Pin); } // op1 = List of cell ports + AstPin* paramsp() const { return VN_CAST(op2p(), Pin); } // op2 = List of parameter #(##) values + AstRange* rangep() const { return VN_CAST(op3p(), Range); } // op3 = Range of arrayed instants (NULL=not ranged) AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated void addPinsp(AstPin* nodep) { addOp1p(nodep); } void addParamsp(AstPin* nodep) { addOp2p(nodep); } @@ -1846,7 +1846,7 @@ public: AstBind(FileLine* fl, const string& name, AstNode* cellsp) : AstNode(fl) , m_name(name) { - if (!cellsp->castCell()) cellsp->v3fatalSrc("Only cells allowed to be bound"); + if (!VN_IS(cellsp, Cell)) cellsp->v3fatalSrc("Only cells allowed to be bound"); addNOp1p(cellsp); } ASTNODE_NODE_FUNCS(Bind) @@ -2061,7 +2061,7 @@ public: AstEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge void edgeType(AstEdgeType type) { m_edgeType=type; editCountInc(); }// * = Posedge/negedge AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized - AstNodeVarRef* varrefp() const { return op1p()->castNodeVarRef(); } // op1 = Signal sensitized + AstNodeVarRef* varrefp() const { return VN_CAST(op1p(), NodeVarRef); } // op1 = Signal sensitized // virtual bool isClocked() const { return edgeType().clockedStmt(); } virtual bool isCombo() const { return edgeType()==AstEdgeType::ET_COMBO; } @@ -2083,7 +2083,7 @@ public: } ASTNODE_NODE_FUNCS(SenGate) virtual string emitVerilog() { return "(%l) %f&& (%r)"; } - AstSenItem* sensesp() const { return op1p()->castSenItem(); } + AstSenItem* sensesp() const { return VN_CAST(op1p(), SenItem); } AstNode* rhsp() const { return op2p(); } void sensesp(AstSenItem* nodep) { addOp1p(nodep); } void rhsp(AstNode* nodep) { setOp2p(nodep); } @@ -2110,7 +2110,7 @@ public: virtual void dump(std::ostream& str); virtual bool maybePointedTo() const { return true; } bool isMulti() const { return m_multi; } - AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list void addSensesp(AstNodeSenItem* nodep) { addOp1p(nodep); } void multi(bool flag) { m_multi = true; } // METHODS @@ -2130,7 +2130,7 @@ public: ASTNODE_NODE_FUNCS(Always) // virtual void dump(std::ostream& str); - AstSenTree* sensesp() const { return op1p()->castSenTree(); } // op1 = Sensitivity list + AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate void addStmtp(AstNode* nodep) { addOp2p(nodep); } VAlwaysKwd keyword() const { return m_keyword; } @@ -2150,7 +2150,7 @@ public: virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { return true; } // - AstSenTree* sensesp() const { return op1p()->castSenTree(); } // op1 = Sensitivity list + AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate void addStmtp(AstNode* nodep) { addOp2p(nodep); } // Special accessors @@ -2404,7 +2404,7 @@ public: virtual bool isPredictOptimizable() const { return true; } virtual bool isOutputter() const { return false; } // Though the AstCoverInc under this is an outputter // but isPure() true - AstCoverInc* incp() const { return op1p()->castCoverInc(); } + AstCoverInc* incp() const { return VN_CAST(op1p(), CoverInc); } void incp(AstCoverInc* nodep) { setOp1p(nodep); } AstNode* origp() const { return op2p(); } AstNode* changep() const { return op3p(); } @@ -2514,7 +2514,7 @@ public: AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display void text(const string& text) { m_text=text; } - AstScopeName* scopeNamep() const { return op2p()->castScopeName(); } + AstScopeName* scopeNamep() const { return VN_CAST(op2p(), ScopeName); } void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive return (name().find("%m") != string::npos || name().find("%M") != string::npos); } @@ -2560,7 +2560,7 @@ public: void displayType(AstDisplayType type) { m_displayType = type; } bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return op1p()->castSFormatF(); } + AstSFormatF* fmtp() const { return VN_CAST(op1p(), SFormatF); } AstNode* filep() const { return op3p(); } void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); } }; @@ -2589,7 +2589,7 @@ public: virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { return true; } void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return op1p()->castSFormatF(); } + AstSFormatF* fmtp() const { return VN_CAST(op1p(), SFormatF); } AstNode* lhsp() const { return op3p(); } void lhsp(AstNode* nodep) { setOp3p(nodep); } }; @@ -3047,7 +3047,7 @@ public: addNOp2p(stablesp); addNOp3p(bodysp); } ASTNODE_NODE_FUNCS(UntilStable) - AstVarRef* stablesp() const { return op2p()->castVarRef(); } // op2= list of variables that must become stable + AstVarRef* stablesp() const { return VN_CAST(op2p(), VarRef); } // op2= list of variables that must become stable AstNode* bodysp() const { return op3p(); } // op3= body of loop void addStablesp(AstVarRef* newp) { addOp2p(newp); } void addBodysp(AstNode* newp) { addOp3p(newp); } @@ -3371,7 +3371,7 @@ public: AstSenTree* sensesp() const { return m_sensesp; } // op1 = Sensitivity tree, if a clocked block in early stages void sensesStorep(AstSenTree* nodep) { addOp1p(nodep); } - AstSenTree* sensesStorep() const { return op1p()->castSenTree(); } + AstSenTree* sensesStorep() const { return VN_CAST(op1p(), SenTree); } // op2 = Combo logic AstNode* stmtsp() const { return op2p(); } void addStmtsp(AstNode* nodep) { addOp2p(nodep); } @@ -3416,10 +3416,10 @@ public: virtual string emitVerilog() { return ""; } virtual string emitC() { V3ERROR_NA; return ""; } virtual bool cleanOut() { return true; } - AstText* scopeAttrp() const { return op1p()->castText(); } - void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } - AstText* scopeEntrp() const { return op2p()->castText(); } - void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } + AstText* scopeAttrp() const { return VN_CAST(op1p(), Text); } + void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } + AstText* scopeEntrp() const { return VN_CAST(op2p(), Text); } + void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } string scopeSymName() const { return scopeNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children string scopeDpiName() const { return scopeNameFormatter(scopeEntrp()); } // Name for DPI import scope string scopePrettySymName() const { return scopePrettyNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children @@ -3435,7 +3435,7 @@ public: addNOp1p(bodysp); } ASTNODE_NODE_FUNCS(UdpTable) - AstUdpTableLine* bodysp() const { return op1p()->castUdpTableLine(); } // op1 = List of UdpTableLines + AstUdpTableLine* bodysp() const { return VN_CAST(op1p(), UdpTableLine); } // op1 = List of UdpTableLines }; class AstUdpTableLine : public AstNode { @@ -3839,7 +3839,7 @@ public: virtual bool sizeMattersLhs() {return false;} AstNode* lhsp() const { return op1p(); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op2p()->castNodeDType(); } + AstNodeDType* childDTypep() const { return VN_CAST(op2p(), NodeDType); } }; class AstCastParse : public AstNode { @@ -4904,7 +4904,7 @@ class AstReplicate : public AstNodeBiop { private: void init() { if (lhsp()) { - if (AstConst* constp=rhsp()->castConst()) { + if (const AstConst* constp = VN_CAST(rhsp(), Const)) { dtypeSetLogicSized(lhsp()->width()*constp->toUInt(), lhsp()->width()*constp->toUInt(), AstNumeric::UNSIGNED); } } @@ -5020,7 +5020,7 @@ public: virtual bool cleanOut() {V3ERROR_NA; return "";} virtual int instrCount() const { return widthInstrs(); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Type assigning to void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } AstNode* itemsp() const { return op2p(); } // op2 = AstPatReplicate, AstPatMember, etc @@ -5084,7 +5084,7 @@ public: addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(Clocking) - AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list AstNode* bodysp() const { return op2p(); } // op2 = Body }; @@ -5104,7 +5104,7 @@ public: } ASTNODE_NODE_FUNCS(PslClocked) virtual bool hasDType() const { return true; } // Used under PslCover, which expects a bool child - AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list AstNode* disablep() const { return op2p(); } // op2 = disable AstNode* propp() const { return op3p(); } // op3 = property }; @@ -5128,7 +5128,7 @@ public: virtual bool same(const AstNode* samep) const { return samep->name() == name(); } virtual void name(const string& name) { m_name = name; } AstNode* propp() const { return op1p(); } // op1 = property - AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain + AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain AstNode* coverincp() const { return op3p(); } // op3 = coverage node void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node @@ -5477,7 +5477,7 @@ public: virtual bool isPredictOptimizable() const { return false; } virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { return true; } - AstVarRef* varrefp() const { return op1p()->castVarRef(); } // op1= varref to reset + AstVarRef* varrefp() const { return VN_CAST(op1p(), VarRef); } // op1= varref to reset }; class AstCStmt : public AstNodeStmt { @@ -5519,7 +5519,7 @@ public: for (int i=0; icastNodeDType();} // op1 = List of dtypes + AstNodeDType* typesp() const { return VN_CAST(op1p(), NodeDType);} // op1 = List of dtypes void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); } AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd); AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, @@ -5555,10 +5555,10 @@ public: BROKEN_RTN(m_evalp && !m_evalp->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) + AstNodeModule* modulesp() const { return VN_CAST(op1p(), NodeModule); } // op1 = List of modules + AstNodeModule* topModulep() const { return VN_CAST(op1p(), NodeModule); } // * = Top module in hierarchy (first one added, for now) void addModulep(AstNodeModule* modulep) { addOp1p(modulep); } - AstCFile* filesp() const { return op2p()->castCFile();} // op2 = List of files + AstCFile* filesp() const { return VN_CAST(op2p(), CFile);} // op2 = List of files void addFilesp(AstCFile* filep) { addOp2p(filep); } AstNode* miscsp() const { return op3p();} // op3 = List of dtypes etc void addMiscsp(AstNode* nodep) { addOp3p(nodep); } diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 5b93bd165..eb98d1a55 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -212,7 +212,7 @@ public: class BrokenCheckVisitor : public AstNVisitor { private: - void checkWidthMin(AstNode* nodep) { + void checkWidthMin(const AstNode* nodep) { if (nodep->width() != nodep->widthMin() && v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH) { nodep->v3fatalSrc("Width != WidthMin"); @@ -225,7 +225,7 @@ private: } if (nodep->dtypep()) { if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); } - else if (!nodep->dtypep()->castNodeDType()) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); } + else if (!VN_IS(nodep->dtypep(), NodeDType)) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); } } if (v3Global.assertDTypesResolved()) { if (nodep->hasDType()) { @@ -234,7 +234,7 @@ private: if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<prettyTypeName()); } if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed"); - if (AstNodeDType* dnodep = nodep->castNodeDType()) checkWidthMin(dnodep); + if (const AstNodeDType* dnodep = VN_CAST(nodep, NodeDType)) checkWidthMin(dnodep); } checkWidthMin(nodep); nodep->iterateChildrenConst(*this); @@ -244,8 +244,8 @@ private: processAndIterate(nodep); if (v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue() - && nodep->lhsp()->castNodeVarRef() - && !nodep->lhsp()->castNodeVarRef()->lvalue()) { + && VN_IS(nodep->lhsp(), NodeVarRef) + && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()) { nodep->v3fatalSrc("Assignment LHS is not an lvalue"); } } diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 5f9f6fc67..d248644a6 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -112,9 +112,9 @@ void V3CCtors::evalAsserts() { funcp->ifdef("VL_DEBUG"); modp->addStmtp(funcp); for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { - if (AstVar* varp = np->castVar()) { + if (AstVar* varp = VN_CAST(np, Var)) { if (varp->isPrimaryIn() && !varp->isSc()) { - if (AstBasicDType* basicp = varp->dtypeSkipRefp()->castBasicDType()) { + if (AstBasicDType* basicp = VN_CAST(varp->dtypeSkipRefp(), BasicDType)) { int storedWidth = basicp->widthAlignBytes() * 8; int lastWordWidth = varp->width() % storedWidth; if (lastWordWidth != 0) { @@ -143,12 +143,12 @@ void V3CCtors::evalAsserts() { void V3CCtors::cctorsAll() { UINFO(2,__FUNCTION__<<": "<modulesp(); modp; modp=modp->nextp()->castNodeModule()) { + for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=VN_CAST(modp->nextp(), NodeModule)) { // Process each module in turn { V3CCtorsVisitor var_reset (modp, "_ctor_var_reset"); for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { - if (AstVar* varp = np->castVar()) { + if (AstVar* varp = VN_CAST(np, Var)) { if (!varp->isIfaceParent() && !varp->isIfaceRef()) { var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true))); } @@ -160,7 +160,7 @@ void V3CCtors::cctorsAll() { (modp, "_configure_coverage", EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first", "if (0 && vlSymsp && first) {} // Prevent unused\n"); for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { - if (AstCoverDecl* coverp = np->castCoverDecl()) { + if (AstCoverDecl* coverp = VN_CAST(np, CoverDecl)) { AstNode* backp = coverp->backp(); coverp->unlinkFrBack(); configure_coverage.add(coverp); diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 977651be8..bc59131bd 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -66,12 +66,12 @@ private: } virtual void visit(AstNodeCase* nodep) { - if (nodep->castCase() && nodep->castCase()->casex()) { + if (VN_IS(nodep, Case) && VN_CAST(nodep, Case)->casex()) { nodep->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)"); } // Detect multiple defaults bool hitDefault = false; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (itemp->isDefault()) { if (hitDefault) { nodep->v3error("Multiple default statements in case statement."); @@ -84,7 +84,7 @@ private: { m_caseExprp = nodep; nodep->exprp()->accept(*this); - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { itemp->condsp()->iterateAndNext(*this); } m_caseExprp = NULL; @@ -93,12 +93,12 @@ private: virtual void visit(AstConst* nodep) { // See also neverItem if (m_caseExprp && nodep->num().isFourState()) { - if (m_caseExprp->castGenCase()) { + if (VN_IS(m_caseExprp, GenCase)) { nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')"); - } else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) { + } else if (VN_IS(m_caseExprp, Case) && VN_CAST(m_caseExprp, Case)->casex()) { // Don't sweat it, we already complained about casex in general - } else if (m_caseExprp->castCase() && (m_caseExprp->castCase()->casez() - || m_caseExprp->castCase()->caseInside())) { + } else if (VN_IS(m_caseExprp, Case) && (VN_CAST(m_caseExprp, Case)->casez() + || VN_CAST(m_caseExprp, Case)->caseInside())) { if (nodep->num().isUnknown()) { nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)"); } @@ -151,11 +151,11 @@ private: bool opaque = false; m_caseItems = 0; m_caseNoOverlapsAllCovered = true; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { if (icondp->width() > width) width = icondp->width(); if (icondp->isDouble()) opaque = true; - if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant + if (!VN_IS(icondp, Const)) width = CASE_BARF; // Can't parse; not a constant m_caseItems++; } } @@ -170,10 +170,10 @@ private: // Now pick up the values for each assignment // We can cheat and use uint32_t's because we only support narrow case's bool bitched = false; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { //if (debug()>=9) icondp->dumpTree(cout," caseitem: "); - AstConst* iconstp = icondp->castConst(); + AstConst* iconstp = VN_CAST(icondp, Const); if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this"); if (neverItem(nodep, iconstp)) { // X in casez can't ever be executed @@ -215,7 +215,7 @@ private: // Convert valueItem from AstCaseItem* to the expression // Not done earlier, as we may now have a NULL because it's just a ";" NOP branch for (uint32_t i=0; i<(1UL<castCaseItem()->bodysp(); + m_valueItem[i] = VN_CAST(m_valueItem[i], CaseItem)->bodysp(); } return true; // All is fine } @@ -310,7 +310,7 @@ private: // the appropriate IF AND terms. if (debug()>=9) nodep->dumpTree(cout," _comp_IN: "); bool hadDefault = false; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->condsp()) { // Default clause. Just make true, we'll optimize it away later itemp->condsp(new AstConst(itemp->fileline(), AstConst::LogicTrue())); @@ -324,14 +324,14 @@ private: icondp->unlinkFrBack(); AstNode* condp = NULL; // Default is to use and1p/and2p - AstConst* iconstp = icondp->castConst(); + AstConst* iconstp = VN_CAST(icondp, Const); if (iconstp && neverItem(nodep, iconstp)) { // X in casez can't ever be executed icondp->deleteTree(); VL_DANGLING(icondp); VL_DANGLING(iconstp); // For simplicity, make expression that is not equal, and let later // optimizations remove it condp = new AstConst(itemp->fileline(), AstConst::LogicFalse()); - } else if (AstInsideRange* irangep = icondp->castInsideRange()) { + } else if (AstInsideRange* irangep = VN_CAST(icondp, InsideRange)) { // Similar logic in V3Width::visit(AstInside) AstNode* ap = AstGte::newTyped(itemp->fileline(), cexprp->cloneTree(false), @@ -387,7 +387,7 @@ private: AstNode* grouprootp = NULL; AstIf* groupnextp = NULL; AstIf* itemnextp = NULL; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { AstNode* istmtsp = itemp->bodysp(); // Maybe null -- no action. if (istmtsp) istmtsp->unlinkFrBackWithNext(); // Expressioned clause diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index cf67d57d7..a37a73c79 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -101,7 +101,7 @@ private: // Otherwise a (uint64)(a>b) would return wrong value, as // less than has undeterministic signedness. if (nodep->isQuad() && !nodep->lhsp()->isQuad() - && !nodep->lhsp()->castCCast()) { + && !VN_IS(nodep->lhsp(), CCast)) { insertCast(nodep->lhsp(), VL_WORDSIZE); } } @@ -147,9 +147,9 @@ private: } virtual void visit(AstVarRef* nodep) { if (!nodep->lvalue() - && !nodep->backp()->castCCast() - && nodep->backp()->castNodeMath() - && !nodep->backp()->castArraySel() + && !VN_IS(nodep->backp(), CCast) + && VN_IS(nodep->backp(), NodeMath) + && !VN_IS(nodep->backp(), ArraySel) && nodep->backp()->width() && castSize(nodep) != castSize(nodep->varp())) { // Cast vars to IData first, else below has upper bits wrongly set diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index c81ecfa88..ca00eb871 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -448,7 +448,7 @@ private: // See also OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) AstNode* nodep = vertexp->nodep(); string front = pad(filelineWidth(),nodep->fileline()->ascii()+":")+" "+prefix+" +- "; - if (nodep->castVarScope()) { + if (VN_IS(nodep, VarScope)) { *m_ofp<prettyName()<castSenTree(); + senoutp = VN_CAST(V3Const::constifyExpensiveEdit(senoutp), SenTree); } if (traceDests) { vertexp->dstDomainSet(true); // Note it's set - domainp may be null, so can't use that @@ -700,11 +700,11 @@ private: nodep->iterateChildren(*this); } virtual void visit(AstSel* nodep) { - if (!nodep->lsbp()->castConst()) setNodeHazard(nodep); + if (!VN_IS(nodep->lsbp(), Const)) setNodeHazard(nodep); nodep->iterateChildren(*this); } virtual void visit(AstNodeSel* nodep) { - if (!nodep->bitp()->castConst()) setNodeHazard(nodep); + if (!VN_IS(nodep->bitp(), Const)) setNodeHazard(nodep); nodep->iterateChildren(*this); } diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 0b5f22fac..f69b27575 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -85,7 +85,7 @@ public: if (!m_tlChgFuncp->stmtsp()) { m_tlChgFuncp->addStmtsp(new AstCReturn(m_scopetopp->fileline(), callp)); } else { - AstCReturn* returnp = m_tlChgFuncp->stmtsp()->castCReturn(); + AstCReturn* returnp = VN_CAST(m_tlChgFuncp->stmtsp(), CReturn); if (!returnp) m_scopetopp->v3fatalSrc("Lost CReturn in top change function"); // This is currently using AstLogOr which will shortcut the evaluation if // any function returns true. This is likely what we want and is similar to the logic already in use diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 1b958d472..0b652ac73 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -78,7 +78,7 @@ private: if (old_dtypep->width() != width) { // Since any given dtype's cppWidth() is the same, we can just // remember one convertion for each, and reuse it - if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNodeDType()) { + if (AstNodeDType* new_dtypep = VN_CAST(old_dtypep->user3p(), NodeDType)) { nodep->dtypep(new_dtypep); } else { nodep->dtypeChgWidth(width, nodep->widthMin()); @@ -90,8 +90,8 @@ private: } void computeCppWidth (AstNode* nodep) { if (!nodep->user2() && nodep->hasDType()) { - if (nodep->castVar() || nodep->castNodeDType() // Don't want to change variable widths! - || nodep->dtypep()->skipRefp()->castUnpackArrayDType()) { // Or arrays + if (VN_IS(nodep, Var) || VN_IS(nodep, NodeDType) // Don't want to change variable widths! + || VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) { // Or arrays } else { setCppWidth(nodep); } @@ -230,7 +230,7 @@ private: computeCppWidth(nodep); setClean (nodep, false); // We always clean, as we don't trust those pesky users. - if (!nodep->backp()->castAnd()) { + if (!VN_IS(nodep->backp(), And)) { insertClean(nodep); } insureCleanAndNext (nodep->bodysp()); diff --git a/src/V3ClkGater.cpp b/src/V3ClkGater.cpp index cc0f1362b..23a7ede9e 100644 --- a/src/V3ClkGater.cpp +++ b/src/V3ClkGater.cpp @@ -672,7 +672,7 @@ class GaterVisitor : public GaterBaseVisitor { AstSenTree* sensesp = nodep->sensesp()->cloneTree(true); #else // Make a SenGate - AstSenItem* oldsenitemsp = nodep->sensesp()->sensesp()->castSenItem(); + AstSenItem* oldsenitemsp = VN_CAST(nodep->sensesp()->sensesp(), SenItem); if (!oldsenitemsp) nodep->v3fatalSrc("SenTree doesn't have any SenItem under it"); AstSenTree* sensesp = new AstSenTree(nodep->fileline(), @@ -857,7 +857,7 @@ class GaterVisitor : public GaterBaseVisitor { AstVarScope* lastvscp = m_stmtVscp; bool lastpli = m_stmtInPli; m_directlyUnderAlw = under; - if (nodep->castNodeStmt()) { // Restored below + if (VN_IS(nodep, NodeStmt)) { // Restored below UINFO(9," Stmt: "<iterateChildren(*this); } m_directlyUnderAlw = lastdua; - if (nodep->castNodeStmt()) { // Reset what set above; else propagate up to above statement + if (VN_IS(nodep, NodeStmt)) { // Reset what set above; else propagate up to above statement m_stmtVscp = lastvscp; m_stmtInPli = lastpli; } diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index e0e3528e3..6b59a4b27 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -154,11 +154,11 @@ private: AstNode* createSenseEquation(AstNodeSenItem* nodesp) { // Nodep may be a list of elements; we need to walk it AstNode* senEqnp = NULL; - for (AstNodeSenItem* senp = nodesp; senp; senp=senp->nextp()->castNodeSenItem()) { + for (AstNodeSenItem* senp = nodesp; senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { AstNode* senOnep = NULL; - if (AstSenItem* itemp = senp->castSenItem()) { + if (AstSenItem* itemp = VN_CAST(senp, SenItem)) { senOnep = createSenItemEquation(itemp); - } else if (AstSenGate* itemp = senp->castSenGate()) { + } else if (AstSenGate* itemp = VN_CAST(senp, SenGate)) { senOnep = createSenGateEquation(itemp); } else { senp->v3fatalSrc("Strange node under sentree"); diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index ef3715f3c..79cd7311c 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -221,7 +221,7 @@ private: void walkEmptyFuncs() { for (V3Hashed::iterator it = m_hashed.begin(); it != m_hashed.end(); ++it) { AstNode* node1p = it->second; - AstCFunc* oldfuncp = node1p->castCFunc(); + AstCFunc* oldfuncp = VN_CAST(node1p, CFunc); if (oldfuncp && oldfuncp->emptyBody() && !oldfuncp->dontCombine()) { @@ -238,7 +238,7 @@ private: for (V3Hashed::iterator it = m_hashed.begin(); it != m_hashed.end(); ++it) { V3Hash hashval = it->first; AstNode* node1p = it->second; - if (!node1p->castCFunc()) continue; + if (!VN_IS(node1p, CFunc)) continue; if (hashval.isIllegal()) node1p->v3fatalSrc("Illegal (unhashed) nodes"); for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) { AstNode* node2p = eqit->second; @@ -247,9 +247,9 @@ private: if (node1p->user3p() || node2p->user3p()) continue; // Already merged if (node1p->sameTree(node2p)) { // walk of tree has same comparison // Replace AstCCall's that point here - replaceFuncWFunc(node2p->castCFunc(), node1p->castCFunc()); + replaceFuncWFunc(VN_CAST(node2p, CFunc), VN_CAST(node1p, CFunc)); // Replacement may promote a slow routine to fast path - if (!node2p->castCFunc()->slow()) node1p->castCFunc()->slow(false); + if (!VN_CAST(node2p, CFunc)->slow()) VN_CAST(node1p, CFunc)->slow(false); } } } @@ -265,7 +265,7 @@ private: pushDeletep(oldfuncp); VL_DANGLING(oldfuncp); } void replaceOnlyCallFunc(AstCCall* nodep) { - if (AstCFunc* oldfuncp = nodep->backp()->castCFunc()) { + if (AstCFunc* oldfuncp = VN_CAST(nodep->backp(), CFunc)) { //oldfuncp->dumpTree(cout,"MAYDEL: "); if (nodep->nextp()==NULL && oldfuncp->initsp()==NULL diff --git a/src/V3Const.cpp b/src/V3Const.cpp index b70b979aa..5224ca99f 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -121,33 +121,33 @@ private: } bool operandConst (AstNode* nodep) { - return (nodep->castConst()); + return VN_IS(nodep, Const); } - bool operandAsvConst (AstNode* nodep) { + bool operandAsvConst(const AstNode* nodep) { // BIASV(CONST, BIASV(CONST,...)) -> BIASV( BIASV_CONSTED(a,b), ...) - AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv(); + const AstNodeBiComAsv* bnodep = VN_CAST_CONST(nodep, NodeBiComAsv); if (!bnodep) return false; - if (!bnodep->lhsp()->castConst()) return false; - AstNodeBiComAsv* rnodep = bnodep->rhsp()->castNodeBiComAsv(); + if (!VN_IS(bnodep->lhsp(), Const)) return false; + const AstNodeBiComAsv* rnodep = VN_CAST_CONST(bnodep->rhsp(), NodeBiComAsv); if (!rnodep) return false; if (rnodep->type() != bnodep->type()) return false; if (rnodep->width() != bnodep->width()) return false; if (rnodep->lhsp()->width() != bnodep->lhsp()->width()) return false; - if (!rnodep->lhsp()->castConst()) return false; + if (!VN_IS(rnodep->lhsp(), Const)) return false; return true; } - bool operandAsvSame (AstNode* nodep) { + bool operandAsvSame(const AstNode* nodep) { // BIASV(SAMEa, BIASV(SAMEb,...)) -> BIASV( BIASV(SAMEa,SAMEb), ...) - AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv(); + const AstNodeBiComAsv* bnodep = VN_CAST_CONST(nodep, NodeBiComAsv); if (!bnodep) return false; - AstNodeBiComAsv* rnodep = bnodep->rhsp()->castNodeBiComAsv(); + const AstNodeBiComAsv* rnodep = VN_CAST_CONST(bnodep->rhsp(), NodeBiComAsv); if (!rnodep) return false; if (rnodep->type() != bnodep->type()) return false; if (rnodep->width() != bnodep->width()) return false; return operandsSame(bnodep->lhsp(), rnodep->lhsp()); } - bool operandAsvLUp (AstNode* nodep) { - // BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r)) + bool operandAsvLUp(const AstNode* nodep) { + // BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r)) ? // // Example of how this is useful: // BIASV(BIASV(CONSTa,b...),BIASV(CONSTc,d...)) // hits operandAsvUp @@ -157,40 +157,40 @@ private: // BIASV(CONST_a_c,BIASV(c...,d...))) // // Idea for the future: All BiComAsvs could be lists, sorted by if they're constant - AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv(); + const AstNodeBiComAsv* bnodep = VN_CAST_CONST(nodep, NodeBiComAsv); if (!bnodep) return false; - AstNodeBiComAsv* lnodep = bnodep->lhsp()->castNodeBiComAsv(); + const AstNodeBiComAsv* lnodep = VN_CAST_CONST(bnodep->lhsp(), NodeBiComAsv); if (!lnodep) return false; if (lnodep->type() != bnodep->type()) return false; if (lnodep->width() != bnodep->width()) return false; - return lnodep->lhsp()->castConst(); + return VN_IS(lnodep->lhsp(), Const); } - bool operandAsvRUp (AstNode* nodep) { - // BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr)) - AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv(); + bool operandAsvRUp(const AstNode* nodep) { + // BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr)) ? + const AstNodeBiComAsv* bnodep = VN_CAST_CONST(nodep, NodeBiComAsv); if (!bnodep) return false; - AstNodeBiComAsv* rnodep = bnodep->rhsp()->castNodeBiComAsv(); + const AstNodeBiComAsv* rnodep = VN_CAST_CONST(bnodep->rhsp(), NodeBiComAsv); if (!rnodep) return false; if (rnodep->type() != bnodep->type()) return false; if (rnodep->width() != bnodep->width()) return false; - return rnodep->lhsp()->castConst(); + return VN_IS(rnodep->lhsp(), Const); } - static bool operandSubAdd(AstNode* nodep) { + static bool operandSubAdd(const AstNode* nodep) { // SUB( ADD(CONSTx,y), CONSTz) -> ADD(SUB(CONSTx,CONSTz), y) - AstNodeBiop* np = nodep->castNodeBiop(); - AstNodeBiop* lp = np->lhsp()->castNodeBiop(); + const AstNodeBiop* np = VN_CAST_CONST(nodep, NodeBiop); + const AstNodeBiop* lp = VN_CAST_CONST(np->lhsp(), NodeBiop); return (lp - && lp->lhsp()->castConst() - && np->rhsp()->castConst() + && VN_IS(lp->lhsp(), Const) + && VN_IS(np->rhsp(), Const) && lp->width()==np->width()); } - static bool operandAndOrSame(AstNode* nodep) { + static bool operandAndOrSame(const AstNode* nodep) { // OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y)) // OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL) - AstNodeBiop* np = nodep->castNodeBiop(); - AstNodeBiop* lp = np->lhsp()->castNodeBiop(); - AstNodeBiop* rp = np->rhsp()->castNodeBiop(); + const AstNodeBiop* np = VN_CAST_CONST(nodep, NodeBiop); + const AstNodeBiop* lp = VN_CAST_CONST(np->lhsp(), NodeBiop); + const AstNodeBiop* rp = VN_CAST_CONST(np->rhsp(), NodeBiop); return (lp && rp && lp->width()==rp->width() && lp->type()==rp->type() @@ -204,13 +204,13 @@ private: // if (rst) ... else if (enable)... -> OR(rst,AND(!rst,enable)) AstNode* ap; AstNodeBiop* andp; - if (nodep->lhsp()->castAnd()) { andp=nodep->lhsp()->castAnd(); ap=nodep->rhsp(); } - else if (nodep->rhsp()->castAnd()) { andp=nodep->rhsp()->castAnd(); ap=nodep->lhsp(); } + if (VN_IS(nodep->lhsp(), And)) { andp=VN_CAST(nodep->lhsp(), And); ap=nodep->rhsp(); } + else if (VN_IS(nodep->rhsp(), And)) { andp=VN_CAST(nodep->rhsp(), And); ap=nodep->lhsp(); } else return false; AstNodeUniop* notp; AstNode* cp; - if (andp->lhsp()->castNot()) { notp=andp->lhsp()->castNot(); cp=andp->rhsp(); } - else if (andp->rhsp()->castNot()) { notp=andp->rhsp()->castNot(); cp=andp->lhsp(); } + if (VN_IS(andp->lhsp(), Not)) { notp=VN_CAST(andp->lhsp(), Not); cp=andp->rhsp(); } + else if (VN_IS(andp->rhsp(), Not)) { notp=VN_CAST(andp->rhsp(), Not); cp=andp->lhsp(); } else return false; AstNode* bp = notp->lhsp(); if (!operandsSame(ap, bp)) return false; @@ -222,11 +222,11 @@ private: else nodep->rhsp(cp); return true; } - static bool operandShiftSame(AstNode* nodep) { - AstNodeBiop* np = nodep->castNodeBiop(); + static bool operandShiftSame(const AstNode* nodep) { + const AstNodeBiop* np = VN_CAST_CONST(nodep, NodeBiop); { - AstShiftL* lp = np->lhsp()->castShiftL(); - AstShiftL* rp = np->rhsp()->castShiftL(); + const AstShiftL* lp = VN_CAST_CONST(np->lhsp(), ShiftL); + const AstShiftL* rp = VN_CAST_CONST(np->rhsp(), ShiftL); if (lp && rp) { return (lp->width() == rp->width() && lp->lhsp()->width() == rp->lhsp()->width() @@ -234,8 +234,8 @@ private: } } { - AstShiftR* lp = np->lhsp()->castShiftR(); - AstShiftR* rp = np->rhsp()->castShiftR(); + const AstShiftR* lp = VN_CAST_CONST(np->lhsp(), ShiftR); + const AstShiftR* rp = VN_CAST_CONST(np->rhsp(), ShiftR); if (lp && rp) { return (lp->width() == rp->width() && lp->lhsp()->width() == rp->lhsp()->width() @@ -244,67 +244,67 @@ private: } return false; } - bool operandHugeShiftL(AstNodeBiop* nodep) { - return (nodep->rhsp()->castConst() - && !nodep->rhsp()->castConst()->num().isFourState() - && nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()) + bool operandHugeShiftL(const AstNodeBiop* nodep) { + return (VN_IS(nodep->rhsp(), Const) + && !VN_CAST_CONST(nodep->rhsp(), Const)->num().isFourState() + && VN_CAST_CONST(nodep->rhsp(), Const)->toUInt() >= (uint32_t)(nodep->width()) && isTPure(nodep->lhsp())); } - bool operandHugeShiftR(AstNodeBiop* nodep) { - return (nodep->rhsp()->castConst() - && !nodep->rhsp()->castConst()->num().isFourState() - && nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()) + bool operandHugeShiftR(const AstNodeBiop* nodep) { + return (VN_IS(nodep->rhsp(), Const) + && !VN_CAST_CONST(nodep->rhsp(), Const)->num().isFourState() + && VN_CAST_CONST(nodep->rhsp(), Const)->toUInt() >= (uint32_t)(nodep->lhsp()->width()) && isTPure(nodep->lhsp())); } - bool operandIsTwo(AstNode* nodep) { - return (nodep->castConst() - && !nodep->castConst()->num().isFourState() + bool operandIsTwo(const AstNode* nodep) { + return (VN_IS(nodep, Const) + && !VN_CAST_CONST(nodep, Const)->num().isFourState() && nodep->width() <= VL_QUADSIZE - && nodep->castConst()->toUQuad()==2); + && VN_CAST_CONST(nodep, Const)->toUQuad()==2); } - bool operandIsTwostate(AstNode* nodep) { - return (nodep->castConst() - && !nodep->castConst()->num().isFourState()); + bool operandIsTwostate(const AstNode* nodep) { + return (VN_IS(nodep, Const) + && !VN_CAST_CONST(nodep, Const)->num().isFourState()); } - bool operandIsPowTwo(AstNode* nodep) { + bool operandIsPowTwo(const AstNode* nodep) { if (!operandIsTwostate(nodep)) return false; - return (1==nodep->castConst()->num().countOnes()); + return (1==VN_CAST_CONST(nodep, Const)->num().countOnes()); } - bool operandShiftOp(AstNodeBiop* nodep) { - if (!nodep->rhsp()->castConst()) return false; - AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop(); - if (!lhsp || !(lhsp->castAnd()||lhsp->castOr()||lhsp->castXor())) return false; + bool operandShiftOp(const AstNodeBiop* nodep) { + if (!VN_IS(nodep->rhsp(), Const)) return false; + const AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); + if (!lhsp || !(VN_IS(lhsp, And) || VN_IS(lhsp, Or) || VN_IS(lhsp, Xor))) return false; if (nodep->width()!=lhsp->width()) return false; if (nodep->width()!=lhsp->lhsp()->width()) return false; if (nodep->width()!=lhsp->rhsp()->width()) return false; return true; } - bool operandShiftShift(AstNodeBiop* nodep) { + bool operandShiftShift(const AstNodeBiop* nodep) { // We could add a AND though. - AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop(); - if (!lhsp || !(lhsp->castShiftL()||lhsp->castShiftR())) return false; + const AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); + if (!lhsp || !(VN_IS(lhsp, ShiftL) || VN_IS(lhsp, ShiftR))) return false; // We can only get rid of a<>c or a<rhsp()->castConst() && lhsp->rhsp()->castConst())) return false; - if (nodep->rhsp()->castConst()->num().isFourState() - || lhsp->rhsp()->castConst()->num().isFourState()) return false; + if (!(VN_IS(nodep->rhsp(), Const) && VN_IS(lhsp->rhsp(), Const))) return false; + if (VN_CAST_CONST(nodep->rhsp(), Const)->num().isFourState() + || VN_CAST_CONST(lhsp->rhsp(), Const)->num().isFourState()) return false; if (nodep->width()!=lhsp->width()) return false; if (nodep->width()!=lhsp->lhsp()->width()) return false; return true; } - bool operandWordOOB(AstWordSel* nodep) { + bool operandWordOOB(const AstWordSel* nodep) { // V3Expand may make a arraysel that exceeds the bounds of the array // It was an expression, then got constified. In reality, the WordSel // must be wrapped in a Cond, that will be false. - return (nodep->rhsp()->castConst() - && nodep->fromp()->castNodeVarRef() - && !nodep->fromp()->castNodeVarRef()->lvalue() - && ((int)(nodep->rhsp()->castConst()->toUInt()) - >= nodep->fromp()->castNodeVarRef()->varp()->widthWords())); + return (VN_IS(nodep->rhsp(), Const) + && VN_IS(nodep->fromp(), NodeVarRef) + && !VN_CAST_CONST(nodep->fromp(), NodeVarRef)->lvalue() + && ((int)(VN_CAST_CONST(nodep->rhsp(), Const)->toUInt()) + >= VN_CAST(nodep->fromp(), NodeVarRef)->varp()->widthWords())); } - bool operandSelFull(AstSel* nodep) { - return (nodep->lsbp()->castConst() - && nodep->widthp()->castConst() + bool operandSelFull(const AstSel* nodep) { + return (VN_IS(nodep->lsbp(), Const) + && VN_IS(nodep->widthp(), Const) && nodep->lsbConst()==0 && (int)nodep->widthConst()==nodep->fromp()->width()); } @@ -312,11 +312,11 @@ private: // A pattern created by []'s after offsets have been removed // SEL(EXTEND(any,width,...),(width-1),0) -> ... // Since select's return unsigned, this is always an extend - AstExtend* extendp = nodep->fromp()->castExtend(); + AstExtend* extendp = VN_CAST(nodep->fromp(), Extend); if (!(m_doV && extendp - && nodep->lsbp()->castConst() - && nodep->widthp()->castConst() + && VN_IS(nodep->lsbp(), Const) + && VN_IS(nodep->widthp(), Const) && nodep->lsbConst()==0 && (int)nodep->widthConst()==extendp->lhsp()->width() )) return false; @@ -326,11 +326,11 @@ private: bool operandSelBiLower(AstSel* nodep) { // SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b)) // Add or any operation which doesn't care if we discard top bits - AstNodeBiop* bip = nodep->fromp()->castNodeBiop(); + AstNodeBiop* bip = VN_CAST(nodep->fromp(), NodeBiop); if (!(m_doV && bip - && nodep->lsbp()->castConst() - && nodep->widthp()->castConst() + && VN_IS(nodep->lsbp(), Const) + && VN_IS(nodep->widthp(), Const) && nodep->lsbConst()==0 )) return false; if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:"); @@ -346,16 +346,16 @@ private: // AND({a}, SHIFTR({b}, {c})) is often shorthand in C for Verilog {b}[{c} :+ {a}] // becomes thought other optimizations // SEL(SHIFTR({a},{b}),{lsb},{width}) -> SEL({a},{lsb+b},{width}) - AstShiftR* shiftp = nodep->fromp()->castShiftR(); + AstShiftR* shiftp = VN_CAST(nodep->fromp(), ShiftR); if (!(m_doV && shiftp - && shiftp->rhsp()->castConst() - && nodep->lsbp()->castConst() - && nodep->widthp()->castConst() + && VN_IS(shiftp->rhsp(), Const) + && VN_IS(nodep->lsbp(), Const) + && VN_IS(nodep->widthp(), Const) )) return false; AstNode* ap = shiftp->lhsp(); - AstConst* bp = shiftp->rhsp()->castConst(); - AstConst* lp = nodep->lsbp()->castConst(); + AstConst* bp = VN_CAST(shiftp->rhsp(), Const); + AstConst* lp = VN_CAST(nodep->lsbp(), Const); if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() || lp->isWide() || lp->num().isFourState() || lp->num().isNegative()) return false; int newLsb = lp->toSInt() + bp->toSInt(); @@ -375,11 +375,11 @@ private: // EQ(const{width32}, EXTEND(xx{width3})) -> EQ(const{3}, xx{3}) // The constant must have zero bits (+ 1 if signed) or compare // would be incorrect. See also operandBiExtendConst - AstExtend* extendp = nodep->rhsp()->castExtend(); + AstExtend* extendp = VN_CAST(nodep->rhsp(), Extend); if (!extendp) return false; AstNode* smallerp = extendp->lhsp(); int subsize = smallerp->width(); - AstConst* constp = nodep->lhsp()->castConst(); + AstConst* constp = VN_CAST(nodep->lhsp(), Const); if (!constp) return false; if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false; // @@ -396,15 +396,15 @@ private: if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:"); return true; } - bool operandBiExtendConstOver(AstNodeBiop* nodep) { + bool operandBiExtendConstOver(const AstNodeBiop* nodep) { // EQ(const{width32}, EXTEND(xx{width3})) -> constant // When the constant has non-zero bits above the extend it's a constant. // Avoids compiler warning - AstExtend* extendp = nodep->rhsp()->castExtend(); + const AstExtend* extendp = VN_CAST_CONST(nodep->rhsp(), Extend); if (!extendp) return false; AstNode* smallerp = extendp->lhsp(); int subsize = smallerp->width(); - AstConst* constp = nodep->lhsp()->castConst(); + const AstConst* constp = VN_CAST_CONST(nodep->lhsp(), Const); if (!constp) return false; if (constp->num().isBitsZero(constp->width()-1, subsize)) return false; return true; @@ -413,7 +413,7 @@ private: AstNode* afterComment(AstNode* nodep) { // Ignore comments, such as to determine if a AstIf is empty. // nodep may be null, if so return null. - while (nodep && nodep->castComment()) { nodep = nodep->nextp(); } + while (nodep && VN_IS(nodep, Comment)) { nodep = nodep->nextp(); } return nodep; } @@ -422,7 +422,7 @@ private: // side effects can do this optimization // Eventually we'll recurse through tree when unknown, memoizing results so far, // but for now can disable en-mass until V3Purify takes effect. - return m_doShort || nodep->castVarRef() || nodep->castConst(); + return m_doShort || VN_IS(nodep, VarRef) || VN_IS(nodep, Const); } // Extraction checks @@ -436,12 +436,12 @@ private: // Similar code in V3Unknown::AstSel bool doit = true; if (m_warn - && nodep->lsbp()->castConst() - && nodep->widthp()->castConst() + && VN_IS(nodep->lsbp(), Const) + && VN_IS(nodep->widthp(), Const) && doit) { int maxDeclBit = nodep->declRange().hiMaxSelect()*nodep->declElWidth() + (nodep->declElWidth()-1); - if (nodep->lsbp()->castConst()->num().isFourState() - || nodep->widthp()->castConst()->num().isFourState()) { + if (VN_CAST(nodep->lsbp(), Const)->num().isFourState() + || VN_CAST(nodep->widthp(), Const)->num().isFourState()) { nodep->v3error("Selection index is constantly unknown or tristated: " "lsb="<lsbp()->name()<<" width="<widthp()->name()); // Replacing nodep will make a mess above, so we replace the offender @@ -468,10 +468,10 @@ private: static bool operandsSame(AstNode* node1p, AstNode* node2p) { // For now we just detect constants & simple vars, though it could be more generic - if (node1p->castConst() && node2p->castConst()) { + if (VN_IS(node1p, Const) && VN_IS(node2p, Const)) { return node1p->sameGateTree(node2p); } - else if (node1p->castVarRef() && node2p->castVarRef()) { + else if (VN_IS(node1p, VarRef) && VN_IS(node2p, VarRef)) { // Avoid comparing widthMin's, which results in lost optimization attempts // If cleanup sameGateTree to be smarter, this can be restored. //return node1p->sameGateTree(node2p); @@ -480,9 +480,9 @@ private: return false; } } - bool ifSameAssign(AstNodeIf* nodep) { - AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign(); - AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign(); + bool ifSameAssign(const AstNodeIf* nodep) { + const AstNodeAssign* ifp = VN_CAST_CONST(nodep->ifsp(), NodeAssign); + const AstNodeAssign* elsep = VN_CAST_CONST(nodep->elsesp(), NodeAssign); if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement if (!elsep || elsep->nextp()) return false; if (ifp->type() != elsep->type()) return false; // Can't mix an assigndly and an assign @@ -491,30 +491,30 @@ private: if (!elsep->rhsp()->gateTree()) return false; return true; } - bool operandIfIf(AstNodeIf* nodep) { + bool operandIfIf(const AstNodeIf* nodep) { if (nodep->elsesp()) return false; - AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf(); + const AstNodeIf* lowerIfp = VN_CAST_CONST(nodep->ifsp(), NodeIf); if (!lowerIfp || lowerIfp->nextp()) return false; if (nodep->type() != lowerIfp->type()) return false; if (afterComment(lowerIfp->elsesp())) return false; return true; } - bool ifConcatMergeableBiop(AstNode* nodep) { - return (nodep->castAnd() - || nodep->castOr() - || nodep->castXor() - || nodep->castXnor()); + bool ifConcatMergeableBiop(const AstNode* nodep) { + return (VN_IS(nodep, And) + || VN_IS(nodep, Or) + || VN_IS(nodep, Xor) + || VN_IS(nodep, Xnor)); } - bool ifAdjacentSel(AstSel* lhsp, AstSel* rhsp) { + bool ifAdjacentSel(const AstSel* lhsp, const AstSel* rhsp) { if (!v3Global.opt.oAssemble()) return false; // opt disabled if (!lhsp || !rhsp) return false; - AstNode* lfromp = lhsp->fromp(); - AstNode* rfromp = rhsp->fromp(); + const AstNode* lfromp = lhsp->fromp(); + const AstNode* rfromp = rhsp->fromp(); if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false; - AstConst* lstart = lhsp->lsbp()->castConst(); - AstConst* rstart = rhsp->lsbp()->castConst(); - AstConst* lwidth = lhsp->widthp()->castConst(); - AstConst* rwidth = rhsp->widthp()->castConst(); + const AstConst* lstart = VN_CAST_CONST(lhsp->lsbp(), Const); + const AstConst* rstart = VN_CAST_CONST(rhsp->lsbp(), Const); + const AstConst* lwidth = VN_CAST_CONST(lhsp->widthp(), Const); + const AstConst* rwidth = VN_CAST_CONST(rhsp->widthp(), Const); if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated int rend = (rstart->toSInt() + rwidth->toSInt()); if (rend == lstart->toSInt()) return true; @@ -525,30 +525,30 @@ private: if (!v3Global.opt.oAssemble()) return false; // opt disabled // two same varref if (operandsSame(lhsp, rhsp)) return true; - AstSel* lselp = lhsp->castSel(); - AstSel* rselp = rhsp->castSel(); + AstSel* lselp = VN_CAST(lhsp, Sel); + AstSel* rselp = VN_CAST(rhsp, Sel); // a[i:0] a if (lselp && !rselp && rhsp->sameGateTree(lselp->fromp())) rselp = new AstSel(rhsp->fileline(), rhsp->cloneTree(false), 0, rhsp->width()); // a[i:j] {a[j-1:k], b} - if (lselp && !rselp && rhsp->castConcat()) - return ifMergeAdjacent(lhsp, rhsp->castConcat()->lhsp()); + if (lselp && !rselp && VN_IS(rhsp, Concat)) + return ifMergeAdjacent(lhsp, VN_CAST(rhsp, Concat)->lhsp()); // a a[msb:j] if (rselp && !lselp && lhsp->sameGateTree(rselp->fromp())) lselp = new AstSel(lhsp->fileline(), lhsp->cloneTree(false), 0, lhsp->width()); // {b, a[j:k]} a[k-1:i] - if (rselp && !lselp && lhsp->castConcat()) - return ifMergeAdjacent(lhsp->castConcat()->rhsp(), rhsp); + if (rselp && !lselp && VN_IS(lhsp, Concat)) + return ifMergeAdjacent(VN_CAST(lhsp, Concat)->rhsp(), rhsp); if (!lselp || !rselp) return false; // a[a:b] a[b-1:c] are adjacent AstNode* lfromp = lselp->fromp(); AstNode* rfromp = rselp->fromp(); if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false; - AstConst* lstart = lselp->lsbp()->castConst(); - AstConst* rstart = rselp->lsbp()->castConst(); - AstConst* lwidth = lselp->widthp()->castConst(); - AstConst* rwidth = rselp->widthp()->castConst(); + AstConst* lstart = VN_CAST(lselp->lsbp(), Const); + AstConst* rstart = VN_CAST(rselp->lsbp(), Const); + AstConst* lwidth = VN_CAST(lselp->widthp(), Const); + AstConst* rwidth = VN_CAST(rselp->widthp(), Const); if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated int rend = (rstart->toSInt() + rwidth->toSInt()); // a[i:j] a[j-1:k] @@ -557,14 +557,14 @@ private: if (rend == rfromp->width() && lstart->toSInt() == 0) return true; return false; } - bool concatMergeable(AstNode* lhsp, AstNode* rhsp) { + bool concatMergeable(const AstNode* lhsp, const AstNode* rhsp) { // determine if {a OP b, c OP d} => {a, c} OP {b, d} is advantagous if (!v3Global.opt.oAssemble()) return false; // opt disabled if (lhsp->type() != rhsp->type()) return false; if (!ifConcatMergeableBiop(lhsp)) return false; - AstNodeBiop* lp = lhsp->castNodeBiop(); - AstNodeBiop* rp = rhsp->castNodeBiop(); + const AstNodeBiop* lp = VN_CAST_CONST(lhsp, NodeBiop); + const AstNodeBiop* rp = VN_CAST_CONST(rhsp, NodeBiop); if (!lp || !rp) return false; // {a[]&b[], a[]&b[]} bool lad = ifMergeAdjacent(lp->lhsp(), rp->lhsp()); @@ -590,7 +590,7 @@ private: void replaceNum (AstNode* oldp, const V3Number& num) { // Replace oldp node with a constant set to specified value UASSERT (oldp, "Null old\n"); - if (oldp->castConst() && !oldp->castConst()->num().isFourState()) { + if (VN_IS(oldp, Const) && !VN_CAST(oldp, Const)->num().isFourState()) { oldp->v3fatalSrc("Already constant??"); } AstNode* newp = new AstConst(oldp->fileline(), num); @@ -606,7 +606,7 @@ private: } void replaceNumSigned(AstNodeBiop* nodep, uint32_t val) { // We allow both sides to be constant, as one may have come from parameter propagation, etc. - if (m_warn && !(nodep->lhsp()->castConst() && nodep->rhsp()->castConst())) { + if (m_warn && !(VN_IS(nodep->lhsp(), Const) && VN_IS(nodep->rhsp(), Const))) { nodep->v3warn(UNSIGNED,"Comparison is constant due to unsigned arithmetic"); } replaceNum(nodep, val); VL_DANGLING(nodep); @@ -641,21 +641,21 @@ private: } void replaceConst(AstNodeUniop* nodep) { V3Number num (nodep->fileline(), nodep->width()); - nodep->numberOperate(num, nodep->lhsp()->castConst()->num()); + nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num()); UINFO(4,"UNICONST -> "<fileline(), nodep->width()); - nodep->numberOperate(num, nodep->lhsp()->castConst()->num(), nodep->rhsp()->castConst()->num()); + nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(), VN_CAST(nodep->rhsp(), Const)->num()); UINFO(4,"BICONST -> "<fileline(), nodep->width()); - nodep->numberOperate(num, nodep->lhsp()->castConst()->num(), - nodep->rhsp()->castConst()->num(), - nodep->thsp()->castConst()->num()); + nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(), + VN_CAST(nodep->rhsp(), Const)->num(), + VN_CAST(nodep->thsp(), Const)->num()); UINFO(4,"TRICONST -> "< BIASV( BIASV(SAMEa,SAMEb), c) //nodep->dumpTree(cout, " repAsvConst_old: "); AstNode* ap = nodep->lhsp(); - AstNodeBiop* rp = nodep->rhsp()->castNodeBiop(); + AstNodeBiop* rp = VN_CAST(nodep->rhsp(), NodeBiop); AstNode* bp = rp->lhsp(); AstNode* cp = rp->rhsp(); ap->unlinkFrBack(); @@ -724,12 +724,12 @@ private: nodep->rhsp(cp); rp->lhsp(ap); rp->rhsp(bp); - if (rp->lhsp()->castConst() && rp->rhsp()->castConst()) replaceConst(rp); + if (VN_IS(rp->lhsp(), Const) && VN_IS(rp->rhsp(), Const)) replaceConst(rp); //nodep->dumpTree(cout, " repAsvConst_new: "); } void replaceAsvLUp (AstNodeBiop* nodep) { // BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r)) - AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* lp = VN_CAST(nodep->lhsp()->unlinkFrBack(), NodeBiop); AstNode* llp = lp->lhsp()->unlinkFrBack(); AstNode* lrp = lp->rhsp()->unlinkFrBack(); AstNode* rp = nodep->rhsp()->unlinkFrBack(); @@ -742,7 +742,7 @@ private: void replaceAsvRUp (AstNodeBiop* nodep) { // BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr)) AstNode* lp = nodep->lhsp()->unlinkFrBack(); - AstNodeBiop* rp = nodep->rhsp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* rp = VN_CAST(nodep->rhsp()->unlinkFrBack(), NodeBiop); AstNode* rlp = rp->lhsp()->unlinkFrBack(); AstNode* rrp = rp->rhsp()->unlinkFrBack(); nodep->lhsp(rlp); @@ -756,10 +756,10 @@ private: // OR (AND (CONSTll,lr), AND(CONSTrl, rr=lr)) -> AND (OR(ll,rl), rr) // nodep ^lp ^llp ^lrp ^rp ^rlp ^rrp // (Or/And may also be reversed) - AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* lp = VN_CAST(nodep->lhsp()->unlinkFrBack(), NodeBiop); AstNode* llp = lp->lhsp()->unlinkFrBack(); AstNode* lrp = lp->rhsp()->unlinkFrBack(); - AstNodeBiop* rp = nodep->rhsp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* rp = VN_CAST(nodep->rhsp()->unlinkFrBack(), NodeBiop); AstNode* rlp = rp->lhsp()->unlinkFrBack(); AstNode* rrp = rp->rhsp()->unlinkFrBack(); nodep->replaceWith(lp); @@ -785,10 +785,10 @@ private: void replaceShiftSame (AstNodeBiop* nodep) { // Or(Shift(ll,CONSTlr),Shift(rl,CONSTrr==lr)) -> Shift(Or(ll,rl),CONSTlr) // (Or/And may also be reversed) - AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* lp = VN_CAST(nodep->lhsp()->unlinkFrBack(), NodeBiop); AstNode* llp = lp->lhsp()->unlinkFrBack(); AstNode* lrp = lp->rhsp()->unlinkFrBack(); - AstNodeBiop* rp = nodep->rhsp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* rp = VN_CAST(nodep->rhsp()->unlinkFrBack(), NodeBiop); AstNode* rlp = rp->lhsp()->unlinkFrBack(); AstNode* rrp = rp->rhsp()->unlinkFrBack(); nodep->replaceWith(lp); @@ -802,8 +802,8 @@ private: } void replaceConcatSel(AstConcat* nodep) { // {a[1], a[0]} -> a[1:0] - AstSel* lselp = nodep->lhsp()->unlinkFrBack()->castSel(); - AstSel* rselp = nodep->rhsp()->unlinkFrBack()->castSel(); + AstSel* lselp = VN_CAST(nodep->lhsp()->unlinkFrBack(), Sel); + AstSel* rselp = VN_CAST(nodep->rhsp()->unlinkFrBack(), Sel); int lstart = lselp->lsbConst(); int lwidth = lselp->widthConst(); int rstart = rselp->lsbConst(); @@ -819,8 +819,8 @@ private: nodep->deleteTree(); VL_DANGLING(nodep); } void replaceConcatMerge(AstConcat* nodep) { - AstNodeBiop* lp = nodep->lhsp()->castNodeBiop(); - AstNodeBiop* rp = nodep->rhsp()->castNodeBiop(); + AstNodeBiop* lp = VN_CAST(nodep->lhsp(), NodeBiop); + AstNodeBiop* rp = VN_CAST(nodep->rhsp(), NodeBiop); AstNode* llp = lp->lhsp()->cloneTree(false); AstNode* lrp = lp->rhsp()->cloneTree(false); AstNode* rlp = rp->lhsp()->cloneTree(false); @@ -843,7 +843,7 @@ private: // -> EXTEND(nodep) // like a AstExtend{$rhsp}, but we need to set the width correctly from base node arg0p->unlinkFrBack(); - AstNode* newp = (nodep->castExtendS() + AstNode* newp = (VN_IS(nodep, ExtendS) ? static_cast(new AstExtendS(nodep->fileline(), arg0p)) : static_cast(new AstExtend (nodep->fileline(), arg0p))); newp->dtypeFrom(nodep); @@ -861,7 +861,7 @@ private: } void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<lhsp()->castConst()->num().mostSetBitP1()-1; // 2^n->n+1 + int amount = VN_CAST(nodep->lhsp(), Const)->num().mostSetBitP1()-1; // 2^n->n+1 AstNode* opp = nodep->rhsp()->unlinkFrBack(); AstShiftL* newp = new AstShiftL(nodep->fileline(), opp, new AstConst(nodep->fileline(), amount)); @@ -870,7 +870,7 @@ private: } void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<rhsp()->castConst()->num().mostSetBitP1()-1; // 2^n->n+1 + int amount = VN_CAST(nodep->rhsp(), Const)->num().mostSetBitP1()-1; // 2^n->n+1 AstNode* opp = nodep->lhsp()->unlinkFrBack(); AstShiftR* newp = new AstShiftR(nodep->fileline(), opp, new AstConst(nodep->fileline(), amount)); @@ -881,7 +881,7 @@ private: UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<unlinkFrBack(&handle); - AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop(); lhsp->unlinkFrBack(); + AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); lhsp->unlinkFrBack(); AstNode* shiftp = nodep->rhsp()->unlinkFrBack(); AstNode* ap = lhsp->lhsp()->unlinkFrBack(); AstNode* bp = lhsp->rhsp()->unlinkFrBack(); @@ -897,14 +897,14 @@ private: void replaceShiftShift (AstNodeBiop* nodep) { UINFO(4,"SHIFT(SHIFT(a,s1),s2)->SHIFT(a,ADD(s1,s2)) "<=9) nodep->dumpTree(cout, " repShiftShift_old: "); - AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop(); lhsp->unlinkFrBack(); + AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); lhsp->unlinkFrBack(); AstNode* ap = lhsp->lhsp()->unlinkFrBack(); AstNode* shift1p = lhsp->rhsp()->unlinkFrBack(); AstNode* shift2p = nodep->rhsp()->unlinkFrBack(); // Shift1p and shift2p may have different sizes, both are self-determined so sum with infinite width if (nodep->type()==lhsp->type()) { - int shift1 = shift1p->castConst()->toUInt(); - int shift2 = shift2p->castConst()->toUInt(); + int shift1 = VN_CAST(shift1p, Const)->toUInt(); + int shift2 = VN_CAST(shift2p, Const)->toUInt(); int newshift = shift1+shift2; shift1p->deleteTree(); VL_DANGLING(shift1p); shift2p->deleteTree(); VL_DANGLING(shift2p); @@ -913,8 +913,8 @@ private: nodep->accept(*this); // Further reduce, either node may have more reductions. } else { // We know shift amounts are constant, but might be a mixed left/right shift - int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1; - int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2; + int shift1 = VN_CAST(shift1p, Const)->toUInt(); if (VN_IS(lhsp, ShiftR)) shift1=-shift1; + int shift2 = VN_CAST(shift2p, Const)->toUInt(); if (VN_IS(nodep, ShiftR)) shift2=-shift2; int newshift = shift1+shift2; shift1p->deleteTree(); VL_DANGLING(shift1p); shift2p->deleteTree(); VL_DANGLING(shift2p); @@ -957,15 +957,15 @@ private: // ASSIGN(SEL(a),aq), ASSIGN(SEL(a+1),bq) -> ASSIGN(SEL(a:b),CONCAT(aq,bq) // ie. assign var[2]=a, assign var[3]=b -> assign var[3:2]={b,a} if (!m_modp) return false; // Skip if we're not const'ing an entire module (IE doing only one assign, etc) - AstSel* sel1p = nodep->lhsp()->castSel(); if (!sel1p) return false; - AstNodeAssign* nextp = nodep->nextp()->castNodeAssign(); if (!nextp) return false; + AstSel* sel1p = VN_CAST(nodep->lhsp(), Sel); if (!sel1p) return false; + AstNodeAssign* nextp = VN_CAST(nodep->nextp(), NodeAssign); if (!nextp) return false; if (nodep->type() != nextp->type()) return false; - AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false; - AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false; - AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false; + AstSel* sel2p = VN_CAST(nextp->lhsp(), Sel); if (!sel2p) return false; + AstVarRef* varref1p = VN_CAST(sel1p->fromp(), VarRef); if (!varref1p) return false; + AstVarRef* varref2p = VN_CAST(sel2p->fromp(), VarRef); if (!varref2p) return false; if (!varref1p->sameGateTree(varref2p)) return false; - AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false; - AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false; + AstConst* con1p = VN_CAST(sel1p->lsbp(), Const); if (!con1p) return false; + AstConst* con2p = VN_CAST(sel2p->lsbp(), Const); if (!con2p) return false; // We need to make sure there's no self-references involved in either // assignment. For speed, we only look 3 deep, then give up. if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false; @@ -1004,7 +1004,7 @@ private: if (!nodep) return true; if (level>2) return false; if (nodep->isPure()) return false; // For example a $fgetc can't be reordered - if (nodep->castNodeVarRef() && nodep->castNodeVarRef()->varp()==varp) return false; + if (VN_IS(nodep, NodeVarRef) && VN_CAST(nodep, NodeVarRef)->varp()==varp) return false; return (varNotReferenced (nodep->nextp(),varp,level+1) && varNotReferenced(nodep->op1p(),varp,level+1) && varNotReferenced(nodep->op2p(),varp,level+1) @@ -1013,12 +1013,12 @@ private: } bool replaceNodeAssign(AstNodeAssign* nodep) { - if (nodep->lhsp()->castVarRef() - && nodep->rhsp()->castVarRef() - && nodep->lhsp()->castVarRef()->sameNoLvalue(nodep->rhsp()->castVarRef()) - && !nodep->castAssignDly()) { + if (VN_IS(nodep->lhsp(), VarRef) + && VN_IS(nodep->rhsp(), VarRef) + && VN_CAST(nodep->lhsp(), VarRef)->sameNoLvalue(VN_CAST(nodep->rhsp(), VarRef)) + && !VN_IS(nodep, AssignDly)) { // X = X. Quite pointless, though X <= X may override another earlier assignment - if (nodep->castAssignW()) { + if (VN_IS(nodep, AssignW)) { nodep->v3error("Wire inputs its own output, creating circular logic (wire x=x)"); return false; // Don't delete the assign, or V3Gate will freak out } else { @@ -1026,9 +1026,9 @@ private: return true; } } - else if (m_doV && nodep->lhsp()->castConcat()) { + else if (m_doV && VN_IS(nodep->lhsp(), Concat)) { bool need_temp = false; - if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS? + if (m_warn && !VN_IS(nodep, AssignDly)) { // Is same var on LHS and RHS? // Note only do this (need user4) when m_warn, which is // done as unique visitor AstUser4InUse m_inuser4; @@ -1051,9 +1051,9 @@ private: } if (debug()>=9) nodep->dumpTree(cout," Ass_old: "); // Unlink the stuff - AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack(); - AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack(); - AstNode* conp = nodep->lhsp()->castConcat()->unlinkFrBack(); + AstNode* lc1p = VN_CAST(nodep->lhsp(), Concat)->lhsp()->unlinkFrBack(); + AstNode* lc2p = VN_CAST(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack(); + AstNode* conp = VN_CAST(nodep->lhsp(), Concat)->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* rhs2p = rhsp->cloneTree(false); // Calc widths @@ -1069,8 +1069,8 @@ private: //*** Not cloneTree; just one node. AstNode* newp = NULL; if (!need_temp) { - AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign(); - AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign(); + AstNodeAssign* asn1ap = VN_CAST(nodep->cloneType(lc1p, sel1p), NodeAssign); + AstNodeAssign* asn2ap = VN_CAST(nodep->cloneType(lc2p, sel2p), NodeAssign); asn1ap->dtypeFrom(sel1p); asn2ap->dtypeFrom(sel2p); newp = AstNode::addNext(newp, asn1ap); @@ -1087,18 +1087,18 @@ private: VFlagLogicPacked(), msb2-lsb2+1); m_modp->addStmtp(temp1p); m_modp->addStmtp(temp2p); - AstNodeAssign* asn1ap=nodep->cloneType - (new AstVarRef(sel1p->fileline(), temp1p, true), - sel1p)->castNodeAssign(); - AstNodeAssign* asn2ap=nodep->cloneType - (new AstVarRef(sel2p->fileline(), temp2p, true), - sel2p)->castNodeAssign(); - AstNodeAssign* asn1bp=nodep->cloneType - (lc1p, new AstVarRef(sel1p->fileline(), temp1p, false)) - ->castNodeAssign(); - AstNodeAssign* asn2bp=nodep->cloneType - (lc2p, new AstVarRef(sel2p->fileline(), temp2p, false)) - ->castNodeAssign(); + AstNodeAssign* asn1ap = VN_CAST(nodep->cloneType + (new AstVarRef(sel1p->fileline(), temp1p, true), + sel1p), NodeAssign); + AstNodeAssign* asn2ap = VN_CAST(nodep->cloneType + (new AstVarRef(sel2p->fileline(), temp2p, true), + sel2p), NodeAssign); + AstNodeAssign* asn1bp = VN_CAST(nodep->cloneType + (lc1p, new AstVarRef(sel1p->fileline(), temp1p, false)), + NodeAssign); + AstNodeAssign* asn2bp = VN_CAST(nodep->cloneType + (lc2p, new AstVarRef(sel2p->fileline(), temp2p, false)), + NodeAssign); asn1ap->dtypeFrom(temp1p); asn1bp->dtypeFrom(temp1p); asn2ap->dtypeFrom(temp2p); @@ -1117,13 +1117,13 @@ private: // Further reduce, either node may have more reductions. return true; } - else if (m_doV && nodep->rhsp()->castStreamR()) { + else if (m_doV && VN_IS(nodep->rhsp(), StreamR)) { // The right-streaming operator on rhs of assignment does not // change the order of bits. Eliminate stream but keep its lhsp // Unlink the stuff - AstNode* srcp = nodep->rhsp()->castStreamR()->lhsp()->unlinkFrBack(); - AstNode* sizep = nodep->rhsp()->castStreamR()->rhsp()->unlinkFrBack(); - AstNode* streamp = nodep->rhsp()->castStreamR()->unlinkFrBack(); + AstNode* srcp = VN_CAST(nodep->rhsp(), StreamR)->lhsp()->unlinkFrBack(); + AstNode* sizep = VN_CAST(nodep->rhsp(), StreamR)->rhsp()->unlinkFrBack(); + AstNode* streamp = VN_CAST(nodep->rhsp(), StreamR)->unlinkFrBack(); nodep->rhsp(srcp); // Cleanup sizep->deleteTree(); VL_DANGLING(sizep); @@ -1131,16 +1131,16 @@ private: // Further reduce, any of the nodes may have more reductions. return true; } - else if (m_doV && nodep->lhsp()->castStreamL()) { + else if (m_doV && VN_IS(nodep->lhsp(), StreamL)) { // Push the stream operator to the rhs of the assignment statement - int dWidth = nodep->lhsp()->castStreamL()->lhsp()->width(); + int dWidth = VN_CAST(nodep->lhsp(), StreamL)->lhsp()->width(); int sWidth = nodep->rhsp()->width(); // Unlink the stuff - AstNode* dstp = nodep->lhsp()->castStreamL()->lhsp()->unlinkFrBack(); - AstNode* streamp = nodep->lhsp()->castStreamL()->unlinkFrBack(); + AstNode* dstp = VN_CAST(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack(); + AstNode* streamp = VN_CAST(nodep->lhsp(), StreamL)->unlinkFrBack(); AstNode* srcp = nodep->rhsp()->unlinkFrBack(); // Connect the rhs to the stream operator and update its width - streamp->castStreamL()->lhsp(srcp); + VN_CAST(streamp, StreamL)->lhsp(srcp); streamp->dtypeSetLogicSized((srcp->width()), (srcp->widthMin()), AstNumeric::UNSIGNED); @@ -1153,16 +1153,16 @@ private: nodep->rhsp(streamp); return true; } - else if (m_doV && nodep->lhsp()->castStreamR()) { + else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) { // The right stream operator on lhs of assignment statement does // not reorder bits. However, if the rhs is wider than the lhs, // then we select bits from the left-most, not the right-most. - int dWidth = nodep->lhsp()->castStreamR()->lhsp()->width(); + int dWidth = VN_CAST(nodep->lhsp(), StreamR)->lhsp()->width(); int sWidth = nodep->rhsp()->width(); // Unlink the stuff - AstNode* dstp = nodep->lhsp()->castStreamR()->lhsp()->unlinkFrBack(); - AstNode* sizep = nodep->lhsp()->castStreamR()->rhsp()->unlinkFrBack(); - AstNode* streamp = nodep->lhsp()->castStreamR()->unlinkFrBack(); + AstNode* dstp = VN_CAST(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack(); + AstNode* sizep = VN_CAST(nodep->lhsp(), StreamR)->rhsp()->unlinkFrBack(); + AstNode* streamp = VN_CAST(nodep->lhsp(), StreamR)->unlinkFrBack(); AstNode* srcp = nodep->rhsp()->unlinkFrBack(); if (sWidth > dWidth) { srcp = new AstSel(streamp->fileline(), srcp, sWidth-dWidth, dWidth); @@ -1182,21 +1182,21 @@ private: } // Boolean replacements - bool operandBoolShift(AstNode* nodep) { + bool operandBoolShift(const AstNode* nodep) { // boolean test of AND(const,SHIFTR(x,const)) -> test of AND(SHIFTL(x,const), x) - if (!nodep->castAnd()) return false; - if (!nodep->castAnd()->lhsp()->castConst()) return false; - if (!nodep->castAnd()->rhsp()->castShiftR()) return false; - AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR(); - if (!shiftp->rhsp()->castConst()) return false; - if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->toUInt()) return false; + if (!VN_IS(nodep, And)) return false; + if (!VN_IS(VN_CAST_CONST(nodep, And)->lhsp(), Const)) return false; + if (!VN_IS(VN_CAST_CONST(nodep, And)->rhsp(), ShiftR)) return false; + const AstShiftR* shiftp = VN_CAST(VN_CAST_CONST(nodep, And)->rhsp(), ShiftR); + if (!VN_IS(shiftp->rhsp(), Const)) return false; + if ((uint32_t)(nodep->width()) <= VN_CAST_CONST(shiftp->rhsp(), Const)->toUInt()) return false; return true; } void replaceBoolShift(AstNode* nodep) { if (debug()>=9) nodep->dumpTree(cout," bshft_old: "); - AstConst* andConstp = nodep->castAnd()->lhsp()->castConst(); - AstNode* fromp = nodep->castAnd()->rhsp()->castShiftR()->lhsp()->unlinkFrBack(); - AstConst* shiftConstp = nodep->castAnd()->rhsp()->castShiftR()->rhsp()->castConst(); + AstConst* andConstp = VN_CAST(VN_CAST(nodep, And)->lhsp(), Const); + AstNode* fromp = VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->lhsp()->unlinkFrBack(); + AstConst* shiftConstp = VN_CAST(VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->rhsp(), Const); V3Number val (andConstp->fileline(), andConstp->width()); val.opShiftL(andConstp->num(), shiftConstp->num()); AstAnd* newp = new AstAnd(nodep->fileline(), @@ -1269,8 +1269,8 @@ private: int operandConcatMove(AstConcat* nodep) { // CONCAT under concat (See moveConcat) // Return value: true indicates to do it; 2 means move to LHS - AstConcat* abConcp = nodep->lhsp()->castConcat(); - AstConcat* bcConcp = nodep->rhsp()->castConcat(); + AstConcat* abConcp = VN_CAST(nodep->lhsp(), Concat); + AstConcat* bcConcp = VN_CAST(nodep->rhsp(), Concat); if (!abConcp && !bcConcp) return 0; if (bcConcp) { AstNode* ap = nodep->lhsp(); @@ -1294,7 +1294,7 @@ private: UINFO(4,"Move concat: "<1) { AstNode* ap = nodep->lhsp()->unlinkFrBack(); - AstConcat* bcConcp = nodep->rhsp()->castConcat(); bcConcp->unlinkFrBack(); + AstConcat* bcConcp = VN_CAST(nodep->rhsp(), Concat); bcConcp->unlinkFrBack(); AstNode* bp = bcConcp->lhsp()->unlinkFrBack(); AstNode* cp = bcConcp->rhsp()->unlinkFrBack(); AstConcat* abConcp = new AstConcat(bcConcp->fileline(), @@ -1306,7 +1306,7 @@ private: if (operandConcatMove(abConcp)) moveConcat(abConcp); bcConcp->deleteTree(); VL_DANGLING(bcConcp); } else { - AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack(); + AstConcat* abConcp = VN_CAST(nodep->lhsp(), Concat); abConcp->unlinkFrBack(); AstNode* ap = abConcp->lhsp()->unlinkFrBack(); AstNode* bp = abConcp->rhsp()->unlinkFrBack(); AstNode* cp = nodep->rhsp()->unlinkFrBack(); @@ -1335,7 +1335,7 @@ private: void replaceSelSel(AstSel* nodep) { // SEL(SEL({x},a,b),c,d) => SEL({x},a+c,d) - AstSel* belowp = nodep->fromp()->castSel(); + AstSel* belowp = VN_CAST(nodep->fromp(), Sel); AstNode* fromp = belowp->fromp()->unlinkFrBack(); AstNode* widthp = nodep->widthp()->unlinkFrBack(); AstNode* lsb1p = nodep->lsbp()->unlinkFrBack(); @@ -1343,9 +1343,10 @@ private: // Eliminate lower range UINFO(4,"Elim Lower range: "<castConst() && lsb2p->castConst()) { + if (VN_IS(lsb1p, Const) && VN_IS(lsb2p, Const)) { newlsbp = new AstConst(lsb1p->fileline(), - lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt()); + VN_CAST(lsb1p, Const)->toUInt() + + VN_CAST(lsb2p, Const)->toUInt()); lsb1p->deleteTree(); VL_DANGLING(lsb1p); lsb2p->deleteTree(); VL_DANGLING(lsb2p); } else { @@ -1354,7 +1355,7 @@ private: newlsbp = new AstAdd(lsb1p->fileline(), lsb2p, new AstExtend(lsb1p->fileline(), lsb1p)); newlsbp->dtypeFrom(lsb2p); // Unsigned - newlsbp->castAdd()->rhsp()->dtypeFrom(lsb2p); + VN_CAST(newlsbp, Add)->rhsp()->dtypeFrom(lsb2p); } AstSel* newp = new AstSel(nodep->fileline(), fromp, @@ -1366,7 +1367,7 @@ private: void replaceSelConcat(AstSel* nodep) { // SEL(CONCAT(a,b),c,d) => SEL(a or b, . .) - AstConcat* conp = nodep->fromp()->castConcat(); + AstConcat* conp = VN_CAST(nodep->fromp(), Concat); AstNode* conLhsp = conp->lhsp(); AstNode* conRhsp = conp->rhsp(); if ((int)nodep->lsbConst() >= conRhsp->width()) { @@ -1405,10 +1406,10 @@ private: } bool operandSelReplicate(AstSel* nodep) { // SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long as SEL's width <= b's width - AstReplicate* repp = nodep->fromp()->castReplicate(); + AstReplicate* repp = VN_CAST(nodep->fromp(), Replicate); AstNode* fromp = repp->lhsp(); - AstConst* lsbp = nodep->lsbp()->castConst(); if (!lsbp) return false; - AstNode* widthp = nodep->widthp(); if (!widthp->castConst()) return false; + AstConst* lsbp = VN_CAST(nodep->lsbp(), Const); if (!lsbp) return false; + AstNode* widthp = nodep->widthp(); if (!VN_IS(widthp, Const)) return false; if (!fromp->width()) nodep->v3fatalSrc("Not widthed"); if ((lsbp->toUInt() / fromp->width()) != ((lsbp->toUInt()+nodep->width()-1) / fromp->width())) return false; @@ -1425,10 +1426,10 @@ private: } bool operandRepRep(AstReplicate* nodep) { // REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2)) - AstReplicate* rep2p = nodep->lhsp()->castReplicate(); + AstReplicate* rep2p = VN_CAST(nodep->lhsp(), Replicate); AstNode* from2p = rep2p->lhsp(); - AstConst* cnt1p = nodep->rhsp()->castConst(); if (!cnt1p) return false; - AstConst* cnt2p = rep2p->rhsp()->castConst(); if (!cnt2p) return false; + AstConst* cnt1p = VN_CAST(nodep->rhsp(), Const); if (!cnt1p) return false; + AstConst* cnt2p = VN_CAST(rep2p->rhsp(), Const); if (!cnt2p) return false; // from2p->unlinkFrBack(); cnt1p->unlinkFrBack(); @@ -1446,14 +1447,14 @@ private: // CONCAT(REP(fromp,cnt1),REP(fromp,cnt2)) -> REPLICATE(fromp,cnt1+cnt2) AstNode* from1p = nodep->lhsp(); uint32_t cnt1 = 1; AstNode* from2p = nodep->rhsp(); uint32_t cnt2 = 1; - if (from1p->castReplicate()) { - AstConst* cnt1p = from1p->castReplicate()->rhsp()->castConst(); if (!cnt1p) return false; - from1p = from1p->castReplicate()->lhsp(); + if (VN_IS(from1p, Replicate)) { + AstConst* cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->rhsp(), Const); if (!cnt1p) return false; + from1p = VN_CAST(from1p, Replicate)->lhsp(); cnt1 = cnt1p->toUInt(); } - if (from2p->castReplicate()) { - AstConst* cnt2p = from2p->castReplicate()->rhsp()->castConst(); if (!cnt2p) return false; - from2p = from2p->castReplicate()->lhsp(); + if (VN_IS(from2p, Replicate)) { + AstConst* cnt2p = VN_CAST(VN_CAST(from2p, Replicate)->rhsp(), Const); if (!cnt2p) return false; + from2p = VN_CAST(from2p, Replicate)->lhsp(); cnt2 = cnt2p->toUInt(); } if (!operandsSame(from1p,from2p)) return false; @@ -1466,7 +1467,7 @@ private: } void replaceSelIntoBiop(AstSel* nodep) { // SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit)) - AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop(); + AstNodeBiop* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), NodeBiop); if (!fromp) nodep->v3fatalSrc("Called on non biop"); AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); AstNode* widthp = nodep->widthp()->unlinkFrBack(); @@ -1483,7 +1484,7 @@ private: } void replaceSelIntoUniop(AstSel* nodep) { // SEL(NOT(a),1,bit) => NOT(SEL(a,bit)) - AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop(); + AstNodeUniop* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), NodeUniop); if (!fromp) nodep->v3fatalSrc("Called on non biop"); AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); AstNode* widthp = nodep->widthp()->unlinkFrBack(); @@ -1505,23 +1506,23 @@ private: virtual void visit(AstArraySel* nodep) { nodep->bitp()->iterateAndNext(*this); - if (nodep->bitp()->castConst() - && nodep->fromp()->castVarRef() + if (VN_IS(nodep->bitp(), Const) + && VN_IS(nodep->fromp(), VarRef) // Need to make sure it's an array object so don't mis-allow a constant (bug509.) - && nodep->fromp()->castVarRef()->varp() - && nodep->fromp()->castVarRef()->varp()->valuep()->castInitArray()) { + && VN_CAST(nodep->fromp(), VarRef)->varp() + && VN_IS(VN_CAST(nodep->fromp(), VarRef)->varp()->valuep(), InitArray)) { m_selp = nodep; // Ask visit(AstVarRef) to replace varref with const } nodep->fromp()->iterateAndNext(*this); - if (nodep->fromp()->castConst()) { // It did. + if (VN_IS(nodep->fromp(), Const)) { // It did. if (!m_selp) { nodep->v3error("Illegal assignment of constant to unpacked array"); } else { AstNode* fromp = nodep->fromp()->unlinkFrBack(); nodep->replaceWith(fromp); - if (fromp->dtypep()->skipRefp()->castNodeArrayDType()) { + if (VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) { // Strip off array to find what array references - fromp->dtypeFrom(fromp->dtypep()->skipRefp()->castNodeArrayDType()->subDTypep()); + fromp->dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); } } } @@ -1545,13 +1546,13 @@ private: && !nodep->varp()->isSigPublic()) || nodep->varp()->isParam())) { if (operandConst(valuep)) { - const V3Number& num = valuep->castConst()->num(); + const V3Number& num = VN_CAST(valuep, Const)->num(); //UINFO(2,"constVisit "<<(void*)valuep<<" "<castInitArray()) { - AstInitArray* initarp = valuep->castInitArray(); + else if (m_selp && VN_IS(valuep, InitArray)) { + AstInitArray* initarp = VN_CAST(valuep, InitArray); uint32_t bit = m_selp->bitConst(); int pos = 0; AstNode* itemp = initarp->initsp(); @@ -1566,14 +1567,14 @@ private: } } } - if (itemp->castConst()) { - const V3Number& num = itemp->castConst()->num(); + if (VN_IS(itemp, Const)) { + const V3Number& num = VN_CAST(itemp, Const)->num(); //UINFO(2,"constVisit "<<(void*)valuep<<" "<castInitArray() && nodep->backp()->castPin()) { + else if (m_params && VN_IS(valuep, InitArray) && VN_IS(nodep->backp(), Pin)) { // Allow parameters to pass arrays // Earlier recursion of InitArray made sure each array value is constant // This exception is fairly fragile, i.e. doesn't support arrays of arrays or other stuff @@ -1594,7 +1595,7 @@ private: if (nodep->itemp()->valuep()) { //if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: "); nodep->itemp()->valuep()->iterateAndNext(*this); - if (AstConst* valuep = nodep->itemp()->valuep()->castConst()) { + if (AstConst* valuep = VN_CAST(nodep->itemp()->valuep(), Const)) { const V3Number& num = valuep->num(); replaceNum(nodep, num); VL_DANGLING(nodep); did=true; @@ -1616,8 +1617,8 @@ private: virtual void visit(AstSenItem* nodep) { nodep->iterateChildren(*this); if (m_doNConst - && (nodep->sensp()->castConst() - || nodep->sensp()->castEnumItemRef() + && (VN_IS(nodep->sensp(), Const) + || VN_IS(nodep->sensp(), EnumItemRef) || (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) { // Constants in sensitivity lists may be removed (we'll simplify later) if (nodep->isClocked()) { // A constant can never get a pos/negexge @@ -1631,24 +1632,24 @@ private: nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo())); nodep->deleteTree(); VL_DANGLING(nodep); } - } else if (m_doNConst && nodep->sensp()->castNot()) { + } else if (m_doNConst && VN_IS(nodep->sensp(), Not)) { // V3Gate may propagate NOTs into clocks... Just deal with it AstNode* sensp = nodep->sensp(); AstNode* lastSensp = sensp; bool invert = false; - while (lastSensp->castNot()) { - lastSensp = lastSensp->castNot()->lhsp(); + while (VN_IS(lastSensp, Not)) { + lastSensp = VN_CAST(lastSensp, Not)->lhsp(); invert = !invert; } UINFO(8,"senItem(NOT...) "<edgeType( nodep->edgeType().invert() ); - AstNodeVarRef* senvarp = lastSensp->unlinkFrBack()->castNodeVarRef(); + AstNodeVarRef* senvarp = VN_CAST(lastSensp->unlinkFrBack(), NodeVarRef); if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable"); sensp->replaceWith(senvarp); sensp->deleteTree(); VL_DANGLING(sensp); } else if (!m_doNConst // Deal with later when doNConst missing - && (nodep->sensp()->castEnumItemRef() - || nodep->sensp()->castConst())) { + && (VN_IS(nodep->sensp(), EnumItemRef) + || VN_IS(nodep->sensp(), Const))) { } else if (nodep->isIllegal()) { // Deal with later } else { if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable"); @@ -1656,7 +1657,7 @@ private: } virtual void visit(AstSenGate* nodep) { nodep->iterateChildren(*this); - if (AstConst* constp = nodep->rhsp()->castConst()) { + if (AstConst* constp = VN_CAST(nodep->rhsp(), Const)) { if (constp->isZero()) { UINFO(4,"SENGATE(...,0)->NEVER"<type() < rhsp->type()) return true; if (lhsp->type() > rhsp->type()) return false; - const AstSenItem* litemp = lhsp->castSenItem(); - const AstSenItem* ritemp = rhsp->castSenItem(); + const AstSenItem* litemp = VN_CAST_CONST(lhsp, SenItem); + const AstSenItem* ritemp = VN_CAST_CONST(rhsp, SenItem); if (litemp && ritemp) { // Looks visually better if we keep sorted by name if (!litemp->varrefp() && ritemp->varrefp()) return true; @@ -1719,20 +1720,20 @@ private: { AstUser4InUse m_inuse4; // Mark x in SENITEM(x) - for (AstNodeSenItem* senp = nodep->sensesp()->castNodeSenItem(); - senp; senp=senp->nextp()->castNodeSenItem()) { - if (AstSenItem* itemp = senp->castSenItem()) { + for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); + senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { + if (AstSenItem* itemp = VN_CAST(senp, SenItem)) { if (itemp->varrefp() && itemp->varrefp()->varScopep()) { itemp->varrefp()->varScopep()->user4(1); } } } // Find x in SENTREE(SENITEM(x)) - for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem(); + for (AstNodeSenItem* nextp, * senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; senp=nextp) { - nextp=senp->nextp()->castNodeSenItem(); - if (AstSenGate* gatep = senp->castSenGate()) { - if (AstSenItem* itemp = gatep->sensesp()->castSenItem()) { + nextp=VN_CAST(senp->nextp(), NodeSenItem); + if (AstSenGate* gatep = VN_CAST(senp, SenGate)) { + if (AstSenItem* itemp = VN_CAST(gatep->sensesp(), SenItem)) { if (itemp->varrefp() && itemp->varrefp()->varScopep()) { if (itemp->varrefp()->varScopep()->user4()) { // Found, push this item up to the top @@ -1749,16 +1750,16 @@ private: // Sort the sensitivity names so "posedge a or b" and "posedge b or a" end up together. // Also, remove duplicate assignments, and fold POS&NEGs into ANYEDGEs // Make things a little faster; check first if we need a sort - for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem(); + for (AstNodeSenItem* nextp, * senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; senp=nextp) { - nextp=senp->nextp()->castNodeSenItem(); + nextp=VN_CAST(senp->nextp(), NodeSenItem); // cppcheck-suppress unassignedVariable // cppcheck bug SenItemCmp cmp; if (nextp && !cmp(senp, nextp)) { // Something's out of order, sort it senp = NULL; - std::vector vec; - for (AstNodeSenItem* senp = nodep->sensesp()->castNodeSenItem(); senp; senp=senp->nextp()->castNodeSenItem()) { + std::vector vec; + for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { vec.push_back(senp); } stable_sort(vec.begin(), vec.end(), SenItemCmp()); @@ -1773,12 +1774,12 @@ private: } // Pass2, remove dup edges - for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem(); + for (AstNodeSenItem* nextp, * senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; senp=nextp) { - nextp=senp->nextp()->castNodeSenItem(); + nextp=VN_CAST(senp->nextp(), NodeSenItem); AstNodeSenItem* cmpp = nextp; - AstSenItem* litemp = senp->castSenItem(); - AstSenItem* ritemp = cmpp->castSenItem(); + AstSenItem* litemp = VN_CAST(senp, SenItem); + AstSenItem* ritemp = VN_CAST(cmpp, SenItem); if (litemp && ritemp) { if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameGateTree(ritemp->varrefp())) || (!litemp->varrefp() && !ritemp->varrefp())) { @@ -1820,10 +1821,10 @@ private: virtual void visit(AstAssignW* nodep) { nodep->iterateChildren(*this); if (m_doNConst && replaceNodeAssign(nodep)) return; - AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy + AstNodeVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); // Not VarXRef, as different refs may set different values to each hierarchy if (m_wremove && !m_params && m_doNConst && m_modp && operandConst(nodep->rhsp()) - && !nodep->rhsp()->castConst()->num().isFourState() + && !VN_CAST(nodep->rhsp(), Const)->num().isFourState() && varrefp // Don't do messes with BITREFs/ARRAYREFs && !varrefp->varp()->valuep() // Not already constified && !varrefp->varScopep()) { // Not scoped (or each scope may have different initial value) @@ -1847,7 +1848,7 @@ private: virtual void visit(AstNodeIf* nodep) { nodep->iterateChildren(*this); if (m_doNConst) { - if (AstConst* constp = nodep->condp()->castConst()) { + if (const AstConst* constp = VN_CAST(nodep->condp(), Const)) { AstNode* keepp = NULL; if (constp->isZero()) { UINFO(4,"IF(0,{any},{x}) => {x}: "<condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible nodep->addIfsp(elsesp); } - else if (((nodep->condp()->castNot() && nodep->condp()->width()==1) - || (nodep->condp()->castLogNot())) + else if (((VN_IS(nodep->condp(), Not) && nodep->condp()->width()==1) + || VN_IS(nodep->condp(), LogNot)) && nodep->ifsp() && nodep->elsesp()) { UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<condp()->castNot()->lhsp()->unlinkFrBackWithNext(); + AstNode* condp = VN_CAST(nodep->condp(), Not)->lhsp()->unlinkFrBackWithNext(); AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext(); AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext(); AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp); @@ -1893,8 +1894,8 @@ private: } else if (ifSameAssign(nodep)) { UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<ifsp()->castNodeAssign(); - AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign(); + AstNodeAssign* ifp = VN_CAST(nodep->ifsp(), NodeAssign); + AstNodeAssign* elsep = VN_CAST(nodep->elsesp(), NodeAssign); ifp->unlinkFrBack(); AstNode* condp = nodep->condp()->unlinkFrBack(); AstNode* truep = ifp->rhsp()->unlinkFrBack(); @@ -1907,7 +1908,7 @@ private: else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting && operandIfIf(nodep)) { UINFO(9,"IF({a}) IF({b}) => IF({a} && {b})"<ifsp()->castNodeIf(); + AstNodeIf* lowerIfp = VN_CAST(nodep->ifsp(), NodeIf); AstNode* condp = nodep->condp()->unlinkFrBack(); AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext(); AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext(); @@ -1931,7 +1932,7 @@ private: // DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2)) if (!m_modp) return false; // Don't optimize under single statement if (!nodep->backp()) return false; - AstDisplay* prevp = nodep->backp()->castDisplay(); + AstDisplay* prevp = VN_CAST(nodep->backp(), Display); if (!prevp) return false; if (!((prevp->displayType() == nodep->displayType()) || (prevp->displayType() == AstDisplayType::DT_WRITE @@ -1974,7 +1975,7 @@ private: nodep->iterateChildren(*this); bool anyconst = false; for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) { - if (argp->castConst()) { anyconst=true; break; } + if (VN_IS(argp, Const)) { anyconst=true; break; } } if (m_doNConst && anyconst) { //UINFO(9," Display in "<text()<nextp(); - if (argp && argp->castConst()) { // Convert it - string out = argp->castConst()->num().displayed(nodep->fileline(), fmt); + if (argp && VN_IS(argp, Const)) { // Convert it + string out = VN_CAST(argp, Const)->num().displayed(nodep->fileline(), fmt); UINFO(9," DispConst: "< "<width()==$rhsp->width()}", "replaceNumLimited(nodep,0)"); TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)"); // Two level bubble pushing - TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==$lhsp->castNot()->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x + TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==VN_CAST($lhsp,,Not)->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->op1p())"); // LOGNOT(LOGNOT(x))->x TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}"); @@ -2361,7 +2363,7 @@ private: TREEOPV("AstRedAnd{$lhsp.castConcat}", "AstAnd{AstRedAnd{$lhsp->castConcat()->lhsp()}, AstRedAnd{$lhsp->castConcat()->rhsp()}}"); // &{a,b} => {&a}&{&b} TREEOPV("AstRedOr {$lhsp.castConcat}", "AstOr {AstRedOr {$lhsp->castConcat()->lhsp()}, AstRedOr {$lhsp->castConcat()->rhsp()}}"); // |{a,b} => {|a}|{|b} TREEOPV("AstRedXor{$lhsp.castConcat}", "AstXor{AstRedXor{$lhsp->castConcat()->lhsp()}, AstRedXor{$lhsp->castConcat()->rhsp()}}"); // ^{a,b} => {^a}^{^b} - TREEOPV("AstRedAnd{$lhsp.castExtend, $lhsp->width() > $lhsp->castExtend()->lhsp()->width()}", "replaceZero(nodep)"); // &{0,...} => 0 Prevents compiler limited range error + TREEOPV("AstRedAnd{$lhsp.castExtend, $lhsp->width() > VN_CAST($lhsp,,Extend)->lhsp()->width()}", "replaceZero(nodep)"); // &{0,...} => 0 Prevents compiler limited range error TREEOPV("AstRedOr {$lhsp.castExtend}", "AstRedOr {$lhsp->castExtend()->lhsp()}"); TREEOPV("AstRedXor{$lhsp.castExtend}", "AstRedXor{$lhsp->castExtend()->lhsp()}"); TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)"); @@ -2375,7 +2377,7 @@ private: TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)"); TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())"); // CONCAT(a[1],a[0]) -> a[1:0] - TREEOPV("AstConcat{$lhsp.castSel, $rhsp.castSel, ifAdjacentSel($lhsp->castSel(),,$rhsp->castSel())}", "replaceConcatSel(nodep)"); + TREEOPV("AstConcat{$lhsp.castSel, $rhsp.castSel, ifAdjacentSel(VN_CAST($lhsp,,Sel),,VN_CAST($rhsp,,Sel))}", "replaceConcatSel(nodep)"); TREEOPV("AstConcat{ifConcatMergeableBiop($lhsp), concatMergeable($lhsp,,$rhsp)}", "replaceConcatMerge(nodep)"); // Common two-level operations that can be simplified TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); @@ -2386,8 +2388,8 @@ private: TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); // "AstXnor{operandShiftSame(nodep)}", // Cannot ShiftSame as the shifted-in zeros might create a one // Note can't simplify a extend{extends}, extends{extend}, as the sign bits end up in the wrong places - TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, nodep->lhsp()->castExtend()->lhsp())"); - TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())"); + TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, VN_CAST(nodep->lhsp(), Extend)->lhsp())"); + TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, VN_CAST(nodep->lhsp(), ExtendS)->lhsp())"); TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs TREEOPV("AstReplicateN{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs TREEOPV("AstReplicate{$lhsp.castReplicate, operandRepRep(nodep)}", "DONE"); // {2{3{lhs}}}->{6{lhs}} @@ -2423,7 +2425,7 @@ private: TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}"); // Strings - TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())"); + TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, VN_CAST(nodep->lhsp(), Const)->num().toString())"); // Possible futures: @@ -2438,7 +2440,7 @@ private: virtual void visit(AstNode* nodep) { // Default: Just iterate if (m_required) { - if (nodep->castNodeDType() || nodep->castRange()) { + if (VN_IS(nodep, NodeDType) || VN_IS(nodep, Range)) { // Ignore dtypes for parameter type pins } else { nodep->v3error("Expecting expression to be constant, but can't convert a " @@ -2513,7 +2515,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) { // Make sure we've sized everything first nodep = V3Width::widthParamsEdit(nodep); ConstVisitor visitor(ConstVisitor::PROC_PARAMS); - if (AstVar* varp=nodep->castVar()) { + if (AstVar* varp=VN_CAST(nodep, Var)) { // If a var wants to be constified, it's really a param, and // we want the value to be constant. We aren't passed just the // init value because we need widthing above to handle the var's type. @@ -2543,7 +2545,7 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) { // Make sure we've sized everything first nodep = V3Width::widthGenerateParamsEdit(nodep); ConstVisitor visitor(ConstVisitor::PROC_GENERATE); - if (AstVar* varp=nodep->castVar()) { + if (AstVar* varp=VN_CAST(nodep, Var)) { // If a var wants to be constified, it's really a param, and // we want the value to be constant. We aren't passed just the // init value because we need widthing above to handle the var's type. diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 3ee6bf5af..7235253f6 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -200,7 +200,7 @@ private: void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant - if (AstBasicDType* bdtypep = dtypep->castBasicDType()) { + if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) { if (bdtypep->isRanged()) { for (int index_docs=bdtypep->lsb(); index_docsmsb()+1; index_docs++) { int index_code = index_docs - bdtypep->lsb(); @@ -218,7 +218,7 @@ private: varp, chgVarp); } } - else if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) { + else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) { int index_code = index_docs - adtypep->lsb(); ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]", @@ -230,7 +230,7 @@ private: newent.cleanup(); } } - else if (AstPackArrayDType* adtypep = dtypep->castPackArrayDType()) { + else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) { for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) { AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp(); int index_code = index_docs - adtypep->lsb(); @@ -245,9 +245,9 @@ private: newent.cleanup(); } } - else if (AstStructDType* adtypep = dtypep->castStructDType()) { + else if (AstStructDType* adtypep = VN_CAST(dtypep, StructDType)) { // For now it's packed, so similar to array - for (AstMemberDType* itemp = adtypep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { + for (AstMemberDType* itemp = adtypep->membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); int index_code = itemp->lsb(); ToggleEnt newent (above.m_comment+string(".")+itemp->name(), @@ -261,7 +261,7 @@ private: newent.cleanup(); } } - else if (AstUnionDType* adtypep = dtypep->castUnionDType()) { + else if (AstUnionDType* adtypep = VN_CAST(dtypep, UnionDType)) { // Arbitrarially handle only the first member of the union if (AstMemberDType* itemp = adtypep->membersp()) { AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); @@ -284,9 +284,9 @@ private: UINFO(4," IF: "<elsesp()->castIf() - && !nodep->elsesp()->castIf()->nextp()); - if (elsif) nodep->elsesp()->castIf()->user1(true); + bool elsif = (VN_IS(nodep->elsesp(), If) + && !VN_CAST(nodep->elsesp(), If)->nextp()); + if (elsif) VN_CAST(nodep->elsesp(), If)->user1(true); // nodep->ifsp()->iterateAndNext(*this); if (m_checkBlock && !m_inModOff diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index 44ea3270f..ee1bbe2e8 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -82,7 +82,7 @@ private: AstNode* duporigp = hashed.iteratorNodep(dupit); // Note hashed will point to the original variable (what's duplicated), not the covertoggle, // but we need to get back to the covertoggle which is immediately above, so: - AstCoverToggle* removep = duporigp->backp()->castCoverToggle(); + AstCoverToggle* removep = VN_CAST(duporigp->backp(), CoverToggle); if (!removep) nodep->v3fatalSrc("CoverageJoin duplicate of wrong type"); UINFO(8," Orig "<> "<incp()->declp()<> "<incp()->declp()<generic() // Don't remove generic types && m_elimDTypes // dtypes stick around until post-widthing - && !nodep->castMemberDType() // Keep member names iff upper type exists + && !VN_IS(nodep, MemberDType) // Keep member names iff upper type exists ) { m_dtypesp.push_back(nodep); } @@ -229,7 +229,7 @@ private: checkAll(nodep); // Don't let packages with only public variables disappear // Normal modules may disappear, e.g. if they are parameterized then removed - if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc(); + if (nodep->attrPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc(); } virtual void visit(AstVarScope* nodep) { nodep->iterateChildren(*this); @@ -242,7 +242,7 @@ private: virtual void visit(AstVar* nodep) { nodep->iterateChildren(*this); checkAll(nodep); - if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc(); + if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc(); if (mightElimVar(nodep)) { m_varsp.push_back(nodep); } @@ -254,7 +254,7 @@ private: nodep->rhsp()->iterateAndNext(*this); checkAll(nodep); // Has to be direct assignment without any EXTRACTing. - AstVarRef* varrefp = nodep->lhsp()->castVarRef(); + AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); if (varrefp && !m_sideEffect && varrefp->varScopep()) { // For simplicity, we only remove post-scoping m_assignMap.insert(make_pair(varrefp->varScopep(), nodep)); @@ -281,7 +281,7 @@ private: retry=false; AstNodeModule* nextmodp; for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) { - nextmodp = modp->nextp()->castNodeModule(); + nextmodp = VN_CAST(modp->nextp(), NodeModule); if (modp->dead() || (modp->level()>2 && modp->user1()==0 && !modp->internal())) { // > 2 because L1 is the wrapper, L2 is the top user module UINFO(4," Dead module "<castNodeClassDType())) { + if ((classp = VN_CAST((*it), NodeClassDType))) { bool cont = true; - for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = memberp->nextp()->castMemberDType()) { + for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = VN_CAST(memberp->nextp(), MemberDType)) { if (memberp->user1() != 0) { cont = false; break; diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 6c3982a1c..3812ff355 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -188,25 +188,25 @@ private: AstNode* newlhsp = NULL; // NULL = unlink old assign AstSel* bitselp = NULL; AstArraySel* arrayselp = NULL; - if (lhsp->castSel()) { - bitselp = lhsp->castSel(); - arrayselp = bitselp->fromp()->castArraySel(); + if (VN_IS(lhsp, Sel)) { + bitselp = VN_CAST(lhsp, Sel); + arrayselp = VN_CAST(bitselp->fromp(), ArraySel); } else { - arrayselp = lhsp->castArraySel(); + arrayselp = VN_CAST(lhsp, ArraySel); } if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?"); - if (arrayselp->dtypep()->skipRefp()->castUnpackArrayDType()) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); + if (VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType)) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); UINFO(4,"AssignDlyArray: "< dimvalp; // Assignment value for each dimension of assignment AstNode* dimselp=arrayselp; - for (; dimselp->castArraySel(); dimselp=dimselp->castArraySel()->fromp()) { - AstNode* valp = dimselp->castArraySel()->bitp()->unlinkFrBack(); + for (; VN_IS(dimselp, ArraySel); dimselp=VN_CAST(dimselp, ArraySel)->fromp()) { + AstNode* valp = VN_CAST(dimselp, ArraySel)->bitp()->unlinkFrBack(); dimvalp.push_front(valp); } - AstVarRef* varrefp = dimselp->castVarRef(); + AstVarRef* varrefp = VN_CAST(dimselp, VarRef); if (!varrefp) nodep->v3fatalSrc("No var underneath arraysels"); if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); varrefp->unlinkFrBack(); @@ -216,7 +216,7 @@ private: std::deque dimreadps; // Read value for each dimension of assignment for (unsigned dimension=0; dimensioncastConst()) { // bit = const, can just use it + if (VN_IS(dimp, Const)) { // bit = const, can just use it dimreadps.push_front(dimp); } else { string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension) @@ -235,7 +235,7 @@ private: AstNode* bitreadp=NULL; // Code to read Vdlyvlsb if (bitselp) { AstNode* lsbvaluep = bitselp->lsbp()->unlinkFrBack(); - if (bitselp->fromp()->castConst()) {// vlsb = constant, can just push constant into where we use it + if (VN_IS(bitselp->fromp(), Const)) { // vlsb = constant, can just push constant into where we use it bitreadp = lsbvaluep; } else { string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); @@ -250,7 +250,7 @@ private: // //=== Value: __Vdlyvval__ AstNode* valreadp; // Code to read Vdlyvval - if (nodep->rhsp()->castConst()) { // vval = constant, can just push constant into where we use it + if (VN_IS(nodep->rhsp(), Const)) { // vval = constant, can just push constant into where we use it valreadp = nodep->rhsp()->unlinkFrBack(); } else { string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); @@ -268,7 +268,7 @@ private: // then we told this nodep->user3 we can use its Vdlyvset rather than making a new one. // This is good for code like: // for (i=0; i<5; i++) vector[i] <= something; - setvscp = nodep->user3p()->castVarScope(); + setvscp = VN_CAST(nodep->user3p(), VarScope); ++m_statSharedSet; } else { // Create new one string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); @@ -303,9 +303,9 @@ private: // Build "IF (changeit) ... UINFO(9," For "<varScopep()->user4p()->castAlwaysPost(); + AstAlwaysPost* finalp = VN_CAST(varrefp->varScopep()->user4p(), AlwaysPost); if (finalp) { - AstActive* oldactivep = finalp->user2p()->castActive(); + AstActive* oldactivep = VN_CAST(finalp->user2p(), Active); checkActivePost(varrefp, oldactivep); if (setinitp) oldactivep->addStmtsp(setinitp); } else { // first time we've dealt with this memory @@ -321,7 +321,7 @@ private: if (finalp->user3p() == setvscp) { // Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*, // we can share the IF statement too - postLogicp = finalp->user4p()->castIf(); + postLogicp = VN_CAST(finalp->user4p(), If); if (!postLogicp) nodep->v3fatalSrc("Delayed assignment misoptimized; prev var found w/o associated IF"); } else { postLogicp = new AstIf (nodep->fileline(), @@ -363,11 +363,11 @@ private: } virtual void visit(AstAssignDly* nodep) { m_inDly = true; - m_nextDlyp = nodep->nextp()->castAssignDly(); // Next assignment in same block, maybe NULL. + m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe NULL. if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task"); - if (nodep->lhsp()->castArraySel() - || (nodep->lhsp()->castSel() - && nodep->lhsp()->castSel()->fromp()->castArraySel())) { + if (VN_IS(nodep->lhsp(), ArraySel) + || (VN_IS(nodep->lhsp(), Sel) + && VN_IS(VN_CAST(nodep->lhsp(), Sel)->fromp(), ArraySel))) { AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* newlhsp = createDlyArray(nodep, lhsp); if (m_inLoop) nodep->v3warn(BLKLOOPINIT,"Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs)"); @@ -394,9 +394,9 @@ private: if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active"); AstVarScope* oldvscp = nodep->varScopep(); if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); - AstVarScope* dlyvscp = oldvscp->user1p()->castVarScope(); + AstVarScope* dlyvscp = VN_CAST(oldvscp->user1p(), VarScope); if (dlyvscp) { // Multiple use of delayed variable - AstActive* oldactivep = dlyvscp->user2p()->castActive(); + AstActive* oldactivep = VN_CAST(dlyvscp->user2p(), Active); checkActivePost(nodep, oldactivep); } if (!dlyvscp) { // First use of this delayed variable diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index a0ae345f0..e9cddfcd7 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -122,7 +122,7 @@ private: if (m_stmtp && (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it && (m_maxdepth-m_depth) > v3Global.opt.compLimitParens() - && !nodep->backp()->castNodeStmt() // Not much point if we're about to use it + && !VN_IS(nodep->backp(), NodeStmt) // Not much point if we're about to use it ) { m_maxdepth = m_depth; createDeepTemp(nodep); diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 90a7a962a..8fe6e821c 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -98,7 +98,7 @@ private: void visitStmt(AstNodeStmt* nodep) { m_depth++; if (m_depth > v3Global.opt.compLimitBlocks() - && !nodep->castCCall()) { // Already done + && !VN_IS(nodep, CCall)) { // Already done UINFO(4, "DeepBlocks "<backp(); // Only for debug if (debug()>=9) backp->dumpTree(cout,"- pre : "); diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 2eb8bed62..f1915b297 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -68,7 +68,7 @@ private: // True iff there's exactly one instance of this module in the design. int instances = 0; for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (stmtp->castScope()) { + if (VN_IS(stmtp, Scope)) { if (++instances > 1) { return false; } } } @@ -187,7 +187,7 @@ private: funcp->declPrivate(true); AstNode* argsp = NULL; for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn()) { AstNode* newp = new AstVarRef(portp->fileline(), portp, portp->isOutput()); if (argsp) argsp = argsp->addNextNull(newp); diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 2b98e1d8f..c1267aae7 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -44,9 +44,11 @@ class EmitCStmts : public EmitCBaseVisitor { private: + typedef std::vector VarVec; + bool m_suppressSemi; AstVarRef* m_wideTempRefp; // Variable that _WW macros should be setting - std::vector m_ctorVarsVec; // All variables in constructor order + VarVec m_ctorVarsVec; // All variables in constructor order int m_splitSize; // # of cfunc nodes placed into output file int m_splitFilenum; // File number being created, 0 = primary @@ -74,7 +76,7 @@ public: void displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const string& vfmt, char fmtLetter); - void emitVarDecl(AstVar* nodep, const string& prefixIfImp); + void emitVarDecl(const AstVar* nodep, const string& prefixIfImp); typedef enum {EVL_CLASS_IO, EVL_CLASS_SIG, EVL_CLASS_TEMP, EVL_CLASS_PAR, EVL_CLASS_ALL, EVL_FUNC_ALL} EisWhich; void emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp); @@ -93,10 +95,10 @@ public: } void emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, AstNode* rhsp, AstNode* thsp); - void emitDeclArrayBrackets(AstVar* nodep) { + void emitDeclArrayBrackets(const AstVar* nodep) { // This isn't very robust and may need cleanup for other data types - for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { + for (const AstUnpackArrayDType* arrayp=VN_CAST_CONST(nodep->dtypeSkipRefp(), UnpackArrayDType); arrayp; + arrayp = VN_CAST_CONST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { puts("["+cvtToStr(arrayp->elementsConst())+"]"); } } @@ -104,7 +106,7 @@ public: void emitTypedefs(AstNode* firstp) { bool first = true; for (AstNode* loopp=firstp; loopp; loopp = loopp->nextp()) { - if (AstTypedef* nodep = loopp->castTypedef()) { + if (const AstTypedef* nodep = VN_CAST(loopp, Typedef)) { if (nodep->attrPublic()) { if (first) { first = false; @@ -113,16 +115,16 @@ public: } else { puts("\n"); } - if (AstEnumDType* adtypep = nodep->dtypep()->skipRefToEnump()->castEnumDType()) { + if (const AstEnumDType* adtypep = VN_CAST(nodep->dtypep()->skipRefToEnump(), EnumDType)) { if (adtypep->width()>64) { putsDecoration("// enum "+nodep->name()+" // Ignored: Too wide for C++\n"); } else { puts("enum "+nodep->name()+" {\n"); - for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp=itemp->nextp()->castEnumItem()) { + for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), EnumItem)) { puts(itemp->name()); puts(" = "); itemp->valuep()->iterateAndNext(*this); - if (itemp->nextp()->castEnumItem()) puts(","); + if (VN_IS(itemp->nextp(), EnumItem)) puts(","); puts("\n"); } puts("};\n"); @@ -136,7 +138,7 @@ public: // VISITORS virtual void visit(AstNodeAssign* nodep) { bool paren = true; bool decind = false; - if (AstSel* selp=nodep->lhsp()->castSel()) { + if (AstSel* selp=VN_CAST(nodep->lhsp(), Sel)) { if (selp->widthMin()==1) { putbs("VL_ASSIGNBIT_"); emitIQW(selp->fromp()); @@ -173,12 +175,12 @@ public: puts(cvtToStr(nodep->widthMin())+","); nodep->lhsp()->iterateAndNext(*this); puts(", "); } else if (nodep->isWide() - && nodep->lhsp()->castVarRef() - && !nodep->rhsp()->castCMath() - && !nodep->rhsp()->castVarRef() - && !nodep->rhsp()->castArraySel()) { + && VN_IS(nodep->lhsp(), VarRef) + && !VN_IS(nodep->rhsp(), CMath) + && !VN_IS(nodep->rhsp(), VarRef) + && !VN_IS(nodep->rhsp(), ArraySel)) { // Wide functions assign into the array directly, don't need separate assign statement - m_wideTempRefp = nodep->lhsp()->castVarRef(); + m_wideTempRefp = VN_CAST(nodep->lhsp(), VarRef); paren = false; } else if (nodep->isWide()) { putbs("VL_ASSIGN_W("); @@ -189,7 +191,7 @@ public: nodep->lhsp()->iterateAndNext(*this); puts(" "); ofp()->blockInc(); decind = true; - if (!nodep->rhsp()->castConst()) ofp()->putBreak(); + if (!VN_IS(nodep->rhsp(), Const)) ofp()->putBreak(); puts("= "); } nodep->rhsp()->iterateAndNext(*this); @@ -210,7 +212,7 @@ public: subnodep->accept(*this); comma = true; } - if (nodep->backp()->castNodeMath() || nodep->backp()->castCReturn()) { + if (VN_IS(nodep->backp(), NodeMath) || VN_IS(nodep->backp(), CReturn)) { // We should have a separate CCall for math and statement usage, but... puts(")"); } else { @@ -332,9 +334,9 @@ public: putbs(","); uint32_t array_lsb = 0; { - AstVarRef* varrefp = nodep->memp()->castVarRef(); + const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); if (!varrefp) { nodep->v3error("Readmem loading non-variable"); } - else if (AstUnpackArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castUnpackArrayDType()) { + else if (const AstUnpackArrayDType* adtypep = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements())); array_lsb = adtypep->lsb(); } @@ -496,7 +498,7 @@ public: } virtual void visit(AstRedXor* nodep) { if (nodep->lhsp()->isWide()) { - visit(nodep->castNodeUniop()); + visit(VN_CAST(nodep, NodeUniop)); } else { putbs("VL_REDXOR_"); puts(cvtToStr(nodep->lhsp()->dtypep()->widthPow2())); @@ -509,31 +511,31 @@ public: if (nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3error("Unsupported: Signed multiply of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } - visit(nodep->castNodeBiop()); + visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPow* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } - visit(nodep->castNodeBiop()); + visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowSS* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } - visit(nodep->castNodeBiop()); + visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowSU* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } - visit(nodep->castNodeBiop()); + visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowUS* nodep) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3error("Unsupported: Power of "<width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } - visit(nodep->castNodeBiop()); + visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstCCast* nodep) { // Extending a value of the same word width is just a NOP. @@ -562,7 +564,7 @@ public: } virtual void visit(AstReplicate* nodep) { if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) { - if (((int)nodep->rhsp()->castConst()->toUInt() + if (((int)VN_CAST(nodep->rhsp(), Const)->toUInt() * nodep->lhsp()->widthMin()) != nodep->widthMin()) nodep->v3fatalSrc("Replicate non-constant or width miscomputed"); puts("VL_REPLICATE_"); @@ -581,8 +583,8 @@ public: virtual void visit(AstStreamL* nodep) { // Attempt to use a "fast" stream function for slice size = power of 2 if (!nodep->isWide()) { - uint32_t isPow2 = nodep->rhsp()->castConst()->num().countOnes() == 1; - uint32_t sliceSize = nodep->rhsp()->castConst()->toUInt(); + uint32_t isPow2 = VN_CAST(nodep->rhsp(), Const)->num().countOnes() == 1; + uint32_t sliceSize = VN_CAST(nodep->rhsp(), Const)->toUInt(); if (isPow2 && sliceSize <= (nodep->isQuad() ? sizeof(uint64_t) : sizeof(uint32_t))) { puts("VL_STREAML_FAST_"); emitIQW(nodep); @@ -593,7 +595,7 @@ public: puts(","+cvtToStr(nodep->rhsp()->widthMin())); puts(","); nodep->lhsp()->iterateAndNext(*this); puts(", "); - uint32_t rd_log2 = V3Number::log2b(nodep->rhsp()->castConst()->toUInt()); + uint32_t rd_log2 = V3Number::log2b(VN_CAST(nodep->rhsp(), Const)->toUInt()); puts(cvtToStr(rd_log2)+")"); return; } @@ -606,7 +608,7 @@ public: puts(nodep->varp()->name()); } void emitCvtPackStr(AstNode* nodep) { - if (AstConst* constp = nodep->castConst()) { + if (const AstConst* constp = VN_CAST(nodep, Const)) { putbs("std::string("); putsQuoted(constp->num().toString()); puts(")"); @@ -656,7 +658,7 @@ public: puts(","); if (!assigntop) { puts(assignString); - } else if (assigntop->castVarRef()) { + } else if (VN_IS(assigntop, VarRef)) { puts(assigntop->hiername()); puts(assigntop->varp()->name()); } else { @@ -677,7 +679,7 @@ public: puts(","); if (!assigntop) { puts(assignString); - } else if (assigntop->castVarRef()) { + } else if (VN_IS(assigntop, VarRef)) { puts(assigntop->hiername()); puts(assigntop->varp()->name()); } else { @@ -790,8 +792,8 @@ class EmitCImp : EmitCStmts { AstNode* lhsp = changep->lhsp(); AstNode* rhsp = changep->rhsp(); static int addDoubleOr = 10; // Determined experimentally as best - if (!lhsp->castVarRef() && !lhsp->castArraySel()) changep->v3fatalSrc("Not ref?"); - if (!rhsp->castVarRef() && !rhsp->castArraySel()) changep->v3fatalSrc("Not ref?"); + if (!VN_IS(lhsp, VarRef) && !VN_IS(lhsp, ArraySel)) changep->v3fatalSrc("Not ref?"); + if (!VN_IS(rhsp, VarRef) && !VN_IS(rhsp, ArraySel)) changep->v3fatalSrc("Not ref?"); for (int word=0; wordlhsp()->widthWords(); word++) { if (!gotOne) { gotOne = true; @@ -887,7 +889,7 @@ class EmitCImp : EmitCStmts { if (nodep->initsp()) putsDecoration("// Variables\n"); for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { - if (AstVar* varp=subnodep->castVar()) { + if (AstVar* varp=VN_CAST(subnodep, Var)) { if (varp->isFuncReturn()) emitVarDecl(varp, ""); } } @@ -937,8 +939,8 @@ class EmitCImp : EmitCStmts { bool gotOneIgnore = false; doubleOrDetect(nodep, gotOneIgnore); string varname; - if (nodep->lhsp()->castVarRef()) { - varname = ": "+nodep->lhsp()->castVarRef()->varp()->prettyName(); + if (VN_IS(nodep->lhsp(), VarRef)) { + varname = ": "+VN_CAST(nodep->lhsp(), VarRef)->varp()->prettyName(); } puts(")) VL_DBG_MSGF(\" CHANGE: "+nodep->fileline()->ascii() +varname+"\\n\"); );\n"); @@ -996,7 +998,7 @@ public: //###################################################################### // Internal EmitCStmts -void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { +void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { AstBasicDType* basicp = nodep->basicp(); if (!basicp) nodep->v3fatalSrc("Unimplemented: Outputting this data type"); if (nodep->isIO()) { if (nodep->isSc()) { @@ -1077,9 +1079,9 @@ void EmitCStmts::emitVarCtors() { puts("\n"); puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer bool first = true; - for (std::vector::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) { - AstVar* varp = *it; - bool isArray = !varp->dtypeSkipRefp()->castBasicDType(); + for (VarVec::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) { + const AstVar* varp = *it; + bool isArray = !VN_CAST(varp->dtypeSkipRefp(), BasicDType); if (isArray) { puts("// Skipping array: "); puts(varp->name()); @@ -1230,17 +1232,17 @@ struct EmitDispState { void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { if (emitDispState.m_format == "" - && nodep->castDisplay()) { // not fscanf etc, as they need to return value + && VN_IS(nodep, Display)) { // not fscanf etc, as they need to return value // NOP } else { // Format bool isStmt = false; - if (AstFScanF* dispp = nodep->castFScanF()) { + if (const AstFScanF* dispp = VN_CAST(nodep, FScanF)) { isStmt = false; puts("VL_FSCANF_IX("); dispp->filep()->iterate(*this); puts(","); - } else if (AstSScanF* dispp = nodep->castSScanF()) { + } else if (const AstSScanF* dispp = VN_CAST(nodep, SScanF)) { isStmt = false; checkMaxWords(dispp->fromp()); puts("VL_SSCANF_I"); emitIQW(dispp->fromp()); puts("X("); @@ -1248,7 +1250,7 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { puts(","); dispp->fromp()->iterate(*this); puts(","); - } else if (AstDisplay* dispp = nodep->castDisplay()) { + } else if (const AstDisplay* dispp = VN_CAST(nodep, Display)) { isStmt = true; if (dispp->filep()) { puts("VL_FWRITEF("); @@ -1257,14 +1259,14 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { } else { puts("VL_WRITEF("); } - } else if (AstSFormat* dispp = nodep->castSFormat()) { + } else if (const AstSFormat* dispp = VN_CAST(nodep, SFormat)) { isStmt = true; puts("VL_SFORMAT_X("); puts(cvtToStr(dispp->lhsp()->widthMin())); putbs(","); dispp->lhsp()->iterate(*this); putbs(","); - } else if (AstSFormatF* dispp = nodep->castSFormatF()) { + } else if (const AstSFormatF* dispp = VN_CAST(nodep, SFormatF)) { isStmt = false; if (dispp) {} puts("VL_SFORMATF_NX("); @@ -1424,21 +1426,21 @@ void EmitCImp::emitVarReset(AstVar* varp) { // If an ARRAYINIT we initialize it using an initial block similar to a signal //puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n"); } - else if (AstInitArray* initarp = varp->valuep()->castInitArray()) { - if (AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType()) { + else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) { + if (AstUnpackArrayDType* arrayp = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType)) { if (initarp->defaultp()) { // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block puts("{ int __Vi=0;"); puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst())); puts("; ++__Vi) {\n"); - emitSetVarConstant(varp->name()+"[__Vi]", initarp->defaultp()->castConst()); + emitSetVarConstant(varp->name()+"[__Vi]", VN_CAST(initarp->defaultp(), Const)); puts("}}\n"); } int pos = 0; for (AstNode* itemp = initarp->initsp(); itemp; ++pos, itemp=itemp->nextp()) { int index = initarp->posIndex(pos); if (!initarp->defaultp() && index!=pos) initarp->v3fatalSrc("Not enough values in array initalizement"); - emitSetVarConstant(varp->name()+"["+cvtToStr(index)+"]", itemp->castConst()); + emitSetVarConstant(varp->name()+"["+cvtToStr(index)+"]", VN_CAST(itemp, Const)); } } else { varp->v3fatalSrc("InitArray under non-arrayed var"); @@ -1450,8 +1452,9 @@ void EmitCImp::emitVarReset(AstVar* varp) { else { int vects = 0; // This isn't very robust and may need cleanup for other data types - for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { + for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType); + arrayp; + arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); @@ -1588,7 +1591,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { // OK if this hash includes some things we won't dump, since just looking for loading the wrong model VHashSha1 hash; for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstVar* varp = nodep->castVar()) { + if (const AstVar* varp = VN_CAST(nodep, Var)) { hash.insert(varp->name()); hash.insert(varp->dtypep()->width()); } @@ -1604,7 +1607,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { // Save all members if (v3Global.opt.inhibitSim()) puts("os"+op+"__Vm_inhibitSim;\n"); for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstVar* varp = nodep->castVar()) { + if (const AstVar* varp = VN_CAST(nodep, Var)) { if (varp->isIO() && modp->isTop() && optSystemC()) { // System C top I/O doesn't need loading, as the lower level subinst code does it. } @@ -1613,8 +1616,9 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { else { int vects = 0; // This isn't very robust and may need cleanup for other data types - for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { + for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType); + arrayp; + arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); @@ -1658,7 +1662,7 @@ void EmitCImp::emitStaticDecl(AstNodeModule* modp) { void EmitCImp::emitTextSection(AstType type) { int last_line = -999; for (AstNode* nodep = m_modp->stmtsp(); nodep != NULL; nodep = nodep->nextp()) { - if (AstNodeText* textp = nodep->castNodeText()) { + if (const AstNodeText* textp = VN_CAST(nodep, NodeText)) { if (nodep->type() == type) { if (last_line != nodep->fileline()->lineno()) { if (last_line < 0) { @@ -1687,7 +1691,7 @@ void EmitCImp::emitCellCtors(AstNodeModule* modp) { puts(EmitCBaseVisitor::symTopAssign()+"\n"); } for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstCell* cellp=nodep->castCell()) { + if (AstCell* cellp=VN_CAST(nodep, Cell)) { puts("VL_CELL ("+cellp->name()+", "+modClassName(cellp->modp())+");\n"); } } @@ -1700,12 +1704,13 @@ void EmitCImp::emitSensitives() { putsDecoration("// Sensitivities on all clocks and combo inputs\n"); puts("SC_METHOD(eval);\n"); for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstVar* varp = nodep->castVar()) { + if (const AstVar* varp = VN_CAST(nodep, Var)) { if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) { int vects = 0; // This isn't very robust and may need cleanup for other data types - for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { + for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType); + arrayp; + arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); @@ -1799,7 +1804,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref // Largest->smallest reduces the number of pad variables. // But for now, Smallest->largest makes it more likely a small offset will allow access to the signal. // TODO: Move this sort to an earlier visitor stage. - typedef std::multimap VarSortMap; + typedef std::multimap VarSortMap; VarSortMap varAnonMap; VarSortMap varNonanonMap; int anonMembers = 0; @@ -1807,13 +1812,13 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref for (int isstatic=1; isstatic>=0; isstatic--) { if (prefixIfImp!="" && !isstatic) continue; for (AstNode* nodep=firstp; nodep; nodep = nodep->nextp()) { - if (AstVar* varp = nodep->castVar()) { + if (const AstVar* varp = VN_CAST(nodep, Var)) { bool doit = true; switch (which) { case EVL_CLASS_IO: doit = varp->isIO(); break; case EVL_CLASS_SIG: doit = (varp->isSignal() && !varp->isIO()); break; case EVL_CLASS_TEMP: doit = (varp->isTemp() && !varp->isIO()); break; - case EVL_CLASS_PAR: doit = (varp->isParam() && !varp->valuep()->castConst()); break; + case EVL_CLASS_PAR: doit = (varp->isParam() && !VN_IS(varp->valuep(), Const)); break; case EVL_CLASS_ALL: doit = true; break; case EVL_FUNC_ALL: doit = true; break; default: v3fatalSrc("Bad Case"); @@ -1823,7 +1828,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref int sigbytes = varp->dtypeSkipRefp()->widthAlignBytes(); int sortbytes = 9; if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0; - else if (varp->dtypeSkipRefp()->castUnpackArrayDType()) sortbytes=8; + else if (VN_IS(varp->dtypeSkipRefp(), UnpackArrayDType)) sortbytes=8; else if (varp->basicp() && varp->basicp()->isOpaque()) sortbytes=7; else if (varp->isScBv() || varp->isScBigUint()) sortbytes=6; else if (sigbytes==8) sortbytes=5; @@ -1873,7 +1878,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref for (int l1=0; l1second; + const AstVar* varp = it->second; emitVarDecl(varp, prefixIfImp); ++it; } @@ -1885,13 +1890,13 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref } // Leftovers, just in case off by one error somewhere above for (; it != varAnonMap.end(); ++it) { - AstVar* varp = it->second; + const AstVar* varp = it->second; emitVarDecl(varp, prefixIfImp); } } // Output nonanons for (VarSortMap::iterator it = varNonanonMap.begin(); it != varNonanonMap.end(); ++it) { - AstVar* varp = it->second; + const AstVar* varp = it->second; emitVarDecl(varp, prefixIfImp); } } @@ -1903,10 +1908,11 @@ struct CmpName { }; void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) { - std::vector funcsp; + typedef std::vector FuncVec; + FuncVec funcsp; for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstCFunc* funcp = nodep->castCFunc()) { + if (const AstCFunc* funcp = VN_CAST(nodep, CFunc)) { if (!funcp->skipDecl()) { funcsp.push_back(funcp); } @@ -1915,8 +1921,8 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) { stable_sort(funcsp.begin(), funcsp.end(), CmpName()); - for (std::vector::iterator it = funcsp.begin(); it != funcsp.end(); ++it) { - AstCFunc* funcp = *it; + for (FuncVec::iterator it = funcsp.begin(); it != funcsp.end(); ++it) { + const AstCFunc* funcp = *it; if (!funcp->dpiImport()) { // DPI is prototyped in __Dpi.h ofp()->putsPrivate(funcp->declPrivate()); if (funcp->ifdef()!="") puts("#ifdef "+funcp->ifdef()+"\n"); @@ -1961,7 +1967,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) { puts("class "+symClassName()+";\n"); vl_unordered_set didClassName; for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstCell* cellp=nodep->castCell()) { + if (AstCell* cellp=VN_CAST(nodep, Cell)) { string className = modClassName(cellp->modp()); if (didClassName.find(className)==didClassName.end()) { puts("class "+className+";\n"); @@ -1987,7 +1993,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) { { // Instantiated cells bool did = false; for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstCell* cellp=nodep->castCell()) { + if (AstCell* cellp=VN_CAST(nodep, Cell)) { if (!did) { did = true; putsDecoration("// CELLS\n"); @@ -2031,17 +2037,17 @@ void EmitCImp::emitInt(AstNodeModule* modp) { ofp()->putsPrivate(false); // public: emitVarList(modp->stmtsp(), EVL_CLASS_PAR, ""); // Only those that are non-CONST for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstVar* varp = nodep->castVar()) { + if (const AstVar* varp = VN_CAST(nodep, Var)) { if (varp->isParam() && (varp->isUsedParam() || varp->isSigPublic())) { if (!varp->valuep()) nodep->v3fatalSrc("No init for a param?"); // These should be static const values, however microsloth VC++ doesn't // support them. They also cause problems with GDB under GCC2.95. if (varp->isWide()) { // Unsupported for output putsDecoration("// enum WData "+varp->name()+" //wide"); - } else if (!varp->valuep()->castConst()) { // Unsupported for output + } else if (!VN_IS(varp->valuep(), Const)) { // Unsupported for output //putsDecoration("// enum ..... "+varp->name()+" //not simple value, see variable above instead"); - } else if (varp->dtypep()->castBasicDType() - && varp->dtypep()->castBasicDType()->isOpaque()) { // Can't put out e.g. doubles + } else if (VN_IS(varp->dtypep(), BasicDType) + && VN_CAST(varp->dtypep(), BasicDType)->isOpaque()) { // Can't put out e.g. doubles } else { puts("enum "); puts(varp->isQuad()?"_QData":"_IData"); @@ -2226,7 +2232,7 @@ void EmitCImp::main(AstNodeModule* modp, bool slow, bool fast) { emitImp (modp); for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { - if (AstCFunc* funcp = nodep->castCFunc()) { + if (AstCFunc* funcp = VN_CAST(nodep, CFunc)) { if (splitNeeded()) { // Close old file delete m_ofp; m_ofp=NULL; @@ -2329,21 +2335,21 @@ class EmitCTrace : EmitCStmts { } bool emitTraceIsScBv(AstTraceInc* nodep) { - AstVarRef* varrefp = nodep->valuep()->castVarRef(); + const AstVarRef* varrefp = VN_CAST(nodep->valuep(), VarRef); if (!varrefp) return false; AstVar* varp = varrefp->varp(); return varp->isSc() && varp->isScBv(); } bool emitTraceIsScBigUint(AstTraceInc* nodep) { - AstVarRef* varrefp = nodep->valuep()->castVarRef(); + const AstVarRef* varrefp = VN_CAST(nodep->valuep(), VarRef); if (!varrefp) return false; AstVar* varp = varrefp->varp(); return varp->isSc() && varp->isScBigUint(); } bool emitTraceIsScUint(AstTraceInc* nodep) { - AstVarRef* varrefp = nodep->valuep()->castVarRef(); + const AstVarRef* varrefp = VN_CAST(nodep->valuep(), VarRef); if (!varrefp) return false; AstVar* varp = varrefp->varp(); return varp->isSc() && varp->isScUint(); @@ -2404,8 +2410,8 @@ class EmitCTrace : EmitCStmts { puts(");\n"); } void emitTraceValue(AstTraceInc* nodep, int arrayindex) { - if (nodep->valuep()->castVarRef()) { - AstVarRef* varrefp = nodep->valuep()->castVarRef(); + if (VN_IS(nodep->valuep(), VarRef)) { + AstVarRef* varrefp = VN_CAST(nodep->valuep(), VarRef); AstVar* varp = varrefp->varp(); puts("("); if (emitTraceIsScBigUint(nodep)) puts("(vluint32_t*)"); @@ -2534,7 +2540,7 @@ public: void V3EmitC::emitc() { UINFO(2,__FUNCTION__<<": "<modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) { + for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) { if (v3Global.opt.outputSplit()) { { EmitCImp imp; imp.main(nodep, false, true); } { EmitCImp imp; imp.main(nodep, true, false); } diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 2133544b0..ce6e6ddd1 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -66,12 +66,12 @@ public: v3Global.rootp()->addFilesp(cfilep); return cfilep; } - string cFuncArgs(AstCFunc* nodep) { + string cFuncArgs(const AstCFunc* nodep) { // Return argument list for given C function string args = nodep->argTypes(); // Might be a user function with argument list. - for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + for (const AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) { + if (const AstVar* portp = VN_CAST_CONST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn()) { if (args != "") args+= ", "; if (nodep->dpiImport() || nodep->dpiExportWrapper()) diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 7a6b4b4ce..5ca387100 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -278,7 +278,7 @@ void EmitCSyms::emitSymHdr() { // for puts("\n// INCLUDE MODULE CLASSES\n"); - for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) { + for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) { puts("#include \""+modClassName(nodep)+".h\"\n"); } @@ -369,7 +369,7 @@ void EmitCSyms::emitSymImp() { // Includes puts("#include \""+symClassName()+".h\"\n"); - for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) { + for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) { puts("#include \""+modClassName(nodep)+".h\"\n"); } @@ -481,10 +481,10 @@ void EmitCSyms::emitSymImp() { } for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { + if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { bounds += " ,"; bounds += cvtToStr(adtypep->msb()); bounds += ","; bounds += cvtToStr(adtypep->lsb()); - if (dtypep->castPackArrayDType()) pdim++; else udim++; + if (VN_IS(dtypep, PackArrayDType)) pdim++; else udim++; dtypep = adtypep->subDTypep(); } else break; // AstBasicDType - nothing below, 1 @@ -628,7 +628,7 @@ void EmitCSyms::emitDpiImp() { puts("return "+topClassName()+"::"+nodep->name()+"("); string args; for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (const AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn()) { if (args != "") args+= ", "; args += portp->name(); diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 4dd964304..677a0664d 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -102,7 +102,7 @@ public: else if (support==2 && slow) { } else { - for (AstCFile* nodep = v3Global.rootp()->filesp(); nodep; nodep=nodep->nextp()->castCFile()) { + for (AstCFile* nodep = v3Global.rootp()->filesp(); nodep; nodep=VN_CAST(nodep->nextp(), CFile)) { if (nodep->source() && nodep->slow()==(slow!=0) && nodep->support()==(support!=0)) { putMakeClassEntry(of, nodep->name()); } diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 7026f805d..35a09da0a 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -170,7 +170,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstNodeCase* nodep) { putfs(nodep,""); - if (AstCase* casep = nodep->castCase()) { + if (const AstCase* casep = VN_CAST(nodep, Case)) { if (casep->priorityPragma()) puts("priority "); if (casep->uniquePragma()) puts("unique "); if (casep->unique0Pragma()) puts("unique0 "); @@ -179,7 +179,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts(" ("); nodep->exprp()->iterateAndNext(*this); puts(")\n"); - if (AstCase* casep = nodep->castCase()) { + if (const AstCase* casep = VN_CAST(nodep, Case)) { if (casep->fullPragma() || casep->parallelPragma()) { puts(" // synopsys"); if (casep->fullPragma()) puts(" full_case"); @@ -316,7 +316,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstNodeIf* nodep) { putfs(nodep,""); - if (AstIf* ifp = nodep->castIf()) { + if (const AstIf* ifp = VN_CAST(nodep, If)) { if (ifp->priorityPragma()) puts("priority "); if (ifp->uniquePragma()) puts("unique "); if (ifp->unique0Pragma()) puts("unique0 "); @@ -462,10 +462,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstRange* nodep) { puts("["); - if (nodep->msbp()->castConst() && nodep->lsbp()->castConst()) { + if (VN_IS(nodep->msbp(), Const) && VN_IS(nodep->lsbp(), Const)) { // Looks nicer if we print [1:0] rather than [32'sh1:32sh0] - puts(cvtToStr(nodep->leftp()->castConst()->toSInt())); puts(":"); - puts(cvtToStr(nodep->rightp()->castConst()->toSInt())); puts("]"); + puts(cvtToStr(VN_CAST(nodep->leftp(), Const)->toSInt())); puts(":"); + puts(cvtToStr(VN_CAST(nodep->rightp(), Const)->toSInt())); puts("]"); } else { nodep->leftp()->iterateAndNext(*this); puts(":"); nodep->rightp()->iterateAndNext(*this); puts("]"); @@ -473,19 +473,19 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstSel* nodep) { nodep->fromp()->iterateAndNext(*this); puts("["); - if (nodep->lsbp()->castConst()) { + if (VN_IS(nodep->lsbp(), Const)) { if (nodep->widthp()->isOne()) { - if (nodep->lsbp()->castConst()) { - puts(cvtToStr(nodep->lsbp()->castConst()->toSInt())); + if (VN_IS(nodep->lsbp(), Const)) { + puts(cvtToStr(VN_CAST(nodep->lsbp(), Const)->toSInt())); } else { nodep->lsbp()->iterateAndNext(*this); } } else { - puts(cvtToStr(nodep->lsbp()->castConst()->toSInt() - +nodep->widthp()->castConst()->toSInt() - -1)); + puts(cvtToStr(VN_CAST(nodep->lsbp(), Const)->toSInt() + + VN_CAST(nodep->widthp(), Const)->toSInt() + - 1)); puts(":"); - puts(cvtToStr(nodep->lsbp()->castConst()->toSInt())); + puts(cvtToStr(VN_CAST(nodep->lsbp(), Const)->toSInt())); } } else { nodep->lsbp()->iterateAndNext(*this); putfs(nodep,"+:"); @@ -725,7 +725,7 @@ void V3EmitV::emitv() { EmitVFileVisitor visitor (v3Global.rootp(), &of); } else { // Process each module in turn - for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) { + for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=VN_CAST(modp->nextp(), NodeModule)) { V3OutVFile of (v3Global.opt.makeDir() +"/"+EmitCBaseVisitor::modClassName(modp)+"__Vout.v"); of.putsHeader(); diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index 750dab54c..54e43ed58 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -76,10 +76,10 @@ class EmitXmlFileVisitor : public AstNVisitor { void outputTag(AstNode* nodep, string tag) { if (tag=="") tag = VString::downcase(nodep->typeName()); puts("<"+tag+" "+nodep->fileline()->xml()); - if (nodep->castNodeDType()) { puts(" id="); outputId(nodep); } + if (VN_IS(nodep, NodeDType)) { puts(" id="); outputId(nodep); } if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); } if (nodep->tag()!="") { puts(" tag="); putsQuoted(nodep->tag()); } - if (AstNodeDType* dtp = nodep->castNodeDType()) { + if (AstNodeDType* dtp = VN_CAST(nodep, NodeDType)) { if (dtp->subDTypep()) { puts(" sub_dtype_id="); outputId(dtp->subDTypep()->skipRefp()); } } else { if (nodep->dtypep()) { puts(" dtype_id="); outputId(nodep->dtypep()->skipRefp()); } diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 91659350e..0f5b4a0ec 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -107,7 +107,7 @@ private: void fixCloneLvalue (AstNode* nodep) { // In AstSel transforms, we call clone() on VarRefs that were lvalues, // but are now being used on the RHS of the assignment - if (nodep->castVarRef()) nodep->castVarRef()->lvalue(false); + if (VN_IS(nodep, VarRef)) VN_CAST(nodep, VarRef)->lvalue(false); // Iterate if (nodep->op1p()) fixCloneLvalue(nodep->op1p()); if (nodep->op2p()) fixCloneLvalue(nodep->op2p()); @@ -178,9 +178,9 @@ private: AstNode* newSelBitWord(AstNode* lsbp, int wordAdder) { // Return equation to get the VL_BITWORD of a constant or non-constant - if (lsbp->castConst()) { + if (VN_IS(lsbp, Const)) { return new AstConst (lsbp->fileline(), - wordAdder + VL_BITWORD_I(lsbp->castConst()->toUInt())); + wordAdder + VL_BITWORD_I(VN_CAST(lsbp, Const)->toUInt())); } else { AstNode* shiftp = new AstShiftR (lsbp->fileline(), lsbp->cloneTree(true), @@ -201,17 +201,17 @@ private: // If there's a CONDBOUND safety to keep arrays in bounds, // we're going to AND it to a value that always fits inside a // word, so we don't need it. - //if (nodep->castCondBound() && nodep->castCondBound()->lhsp()->castLte()) { - // nodep = nodep->castCondBound()->rhsp(); + //if (VN_IS(nodep, CondBound) && VN_IS(VN_CAST(nodep, CondBound)->lhsp(), Lte)) { + // nodep = VN_CAST(nodep, CondBound)->rhsp(); //} return nodep; } AstNode* newSelBitBit(AstNode* lsbp) { // Return equation to get the VL_BITBIT of a constant or non-constant - if (lsbp->castConst()) { + if (VN_IS(lsbp, Const)) { return new AstConst (lsbp->fileline(), - VL_BITBIT_I(lsbp->castConst()->toUInt())); + VL_BITBIT_I(VN_CAST(lsbp, Const)->toUInt())); } else { return new AstAnd (lsbp->fileline(), new AstConst(lsbp->fileline(), VL_WORDSIZE-1), @@ -243,7 +243,7 @@ private: } bool expandWide (AstNodeAssign* nodep, AstArraySel* rhsp) { UINFO(8," Wordize ASSIGN(ARRAYSEL) "<dtypep()->skipRefp()->castUnpackArrayDType()) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); + if (VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); for (int w=0; wwidthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone (rhsp, w)); } @@ -352,7 +352,7 @@ private: nodep->iterateChildren(*this); // Remember, Sel's may have non-integer rhs, so need to optimize for that! if (nodep->widthMin()!=(int)nodep->widthConst()) nodep->v3fatalSrc("Width mismatch"); - if (nodep->backp()->castNodeAssign() && nodep==nodep->backp()->castNodeAssign()->lhsp()) { + if (VN_IS(nodep->backp(), NodeAssign) && nodep==VN_CAST(nodep->backp(), NodeAssign)->lhsp()) { // Sel is an LHS assignment select } else if (nodep->isWide()) { // See under ASSIGN(WIDE) @@ -460,7 +460,7 @@ private: bool expandWide (AstNodeAssign* nodep, AstSel* rhsp) { if (nodep->widthMin()!=(int)rhsp->widthConst()) nodep->v3fatalSrc("Width mismatch"); - if (rhsp->lsbp()->castConst() && VL_BITBIT_I(rhsp->lsbConst())==0) { + if (VN_IS(rhsp->lsbp(), Const) && VL_BITBIT_I(rhsp->lsbConst())==0) { int lsb = rhsp->lsbConst(); UINFO(8," Wordize ASSIGN(SEL,align) "<widthWords(); w++) { @@ -513,7 +513,7 @@ private: // Yuk. bool destwide = lhsp->fromp()->isWide(); bool ones = nodep->rhsp()->isAllOnesV(); - if (lhsp->lsbp()->castConst()) { + if (VN_IS(lhsp->lsbp(), Const)) { // The code should work without this constant test, but it won't // constify as nicely as we'd like. AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); @@ -702,7 +702,7 @@ private: newp = new AstNegate (nodep->fileline(), lhsp); } else { UINFO(8," REPLICATE "<rhsp()->castConst(); + const AstConst* constp = VN_CAST(nodep->rhsp(), Const); if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!"); uint32_t times = constp->toUInt(); if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCCast(nodep->fileline(), lhsp, nodep); @@ -727,7 +727,7 @@ private: UINFO(8," Wordize ASSIGN(REPLICATE) "<lhsp(); int lhswidth = lhsp->widthMin(); - AstConst* constp = rhsp->rhsp()->castConst(); + const AstConst* constp = VN_CAST(rhsp->rhsp(), Const); if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!"); uint32_t times = constp->toUInt(); for (int w=0; wwidthWords(); w++) { @@ -777,7 +777,7 @@ private: newAstWordSelClone (nodep->rhsp(), w)); newp = (newp==NULL) ? eqp : (new AstOr (nodep->fileline(), newp, eqp)); } - if (nodep->castNeq()) { + if (VN_IS(nodep, Neq)) { newp = new AstNeq (nodep->fileline(), new AstConst (nodep->fileline(), 0), newp); } else { @@ -873,36 +873,36 @@ private: m_stmtp = nodep; nodep->iterateChildren(*this); bool did = false; - if (nodep->isWide() && ((nodep->lhsp()->castVarRef() - || nodep->lhsp()->castArraySel())) + if (nodep->isWide() && ((VN_IS(nodep->lhsp(), VarRef) + || VN_IS(nodep->lhsp(), ArraySel))) && !AstVar::scVarRecurse(nodep->lhsp()) // Need special function for SC && !AstVar::scVarRecurse(nodep->rhsp())) { - if (AstConst* rhsp = nodep->rhsp()->castConst()) { + if (AstConst* rhsp = VN_CAST(nodep->rhsp(), Const)) { did = expandWide(nodep,rhsp); - } else if (AstVarRef* rhsp = nodep->rhsp()->castVarRef()) { + } else if (AstVarRef* rhsp = VN_CAST(nodep->rhsp(), VarRef)) { did = expandWide(nodep,rhsp); - } else if (AstSel* rhsp = nodep->rhsp()->castSel()) { + } else if (AstSel* rhsp = VN_CAST(nodep->rhsp(), Sel)) { did = expandWide(nodep,rhsp); - } else if (AstArraySel* rhsp = nodep->rhsp()->castArraySel()) { + } else if (AstArraySel* rhsp = VN_CAST(nodep->rhsp(), ArraySel)) { did = expandWide(nodep,rhsp); - } else if (AstConcat* rhsp = nodep->rhsp()->castConcat()) { + } else if (AstConcat* rhsp = VN_CAST(nodep->rhsp(), Concat)) { did = expandWide(nodep,rhsp); - } else if (AstReplicate* rhsp = nodep->rhsp()->castReplicate()) { + } else if (AstReplicate* rhsp = VN_CAST(nodep->rhsp(), Replicate)) { did = expandWide(nodep,rhsp); - } else if (AstAnd* rhsp = nodep->rhsp()->castAnd()) { + } else if (AstAnd* rhsp = VN_CAST(nodep->rhsp(), And)) { did = expandWide(nodep,rhsp); - } else if (AstOr* rhsp = nodep->rhsp()->castOr()) { + } else if (AstOr* rhsp = VN_CAST(nodep->rhsp(), Or)) { did = expandWide(nodep,rhsp); - } else if (AstNot* rhsp = nodep->rhsp()->castNot()) { + } else if (AstNot* rhsp = VN_CAST(nodep->rhsp(), Not)) { did = expandWide(nodep,rhsp); - } else if (AstXor* rhsp = nodep->rhsp()->castXor()) { + } else if (AstXor* rhsp = VN_CAST(nodep->rhsp(), Xor)) { did = expandWide(nodep,rhsp); - } else if (AstXnor* rhsp = nodep->rhsp()->castXnor()) { + } else if (AstXnor* rhsp = VN_CAST(nodep->rhsp(), Xnor)) { did = expandWide(nodep,rhsp); - } else if (AstNodeCond* rhsp = nodep->rhsp()->castNodeCond()) { + } else if (AstNodeCond* rhsp = VN_CAST(nodep->rhsp(), NodeCond)) { did = expandWide(nodep,rhsp); } - } else if (AstSel* lhsp = nodep->lhsp()->castSel()) { + } else if (AstSel* lhsp = VN_CAST(nodep->lhsp(), Sel)) { did = expandLhs(nodep,lhsp); } // Cleanup common code diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 25b57ee0e..859c0ff8a 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -234,19 +234,19 @@ private: } virtual void visit(AstNodeAssign* nodep) { m_substTreep = nodep->rhsp(); - if (!nodep->lhsp()->castNodeVarRef()) + if (!VN_IS(nodep->lhsp(), NodeVarRef)) clearSimple("ASSIGN(non-VARREF)"); else nodep->iterateChildren(*this); // We don't push logic other then assignments/NOTs into SenItems // This avoids a mess in computing what exactly a POSEDGE is // V3Const cleans up any NOTs by flipping the edges for us if (m_buffersOnly - && !(nodep->rhsp()->castVarRef() + && !(VN_IS(nodep->rhsp(), VarRef) // Avoid making non-clocked logic into clocked, // as it slows down the verilator_sim_benchmark - || (nodep->rhsp()->castNot() - && nodep->rhsp()->castNot()->lhsp()->castVarRef() - && nodep->rhsp()->castNot()->lhsp()->castVarRef()->varp()->isUsedClock()) + || (VN_IS(nodep->rhsp(), Not) + && VN_IS(VN_CAST(nodep->rhsp(), Not)->lhsp(), VarRef) + && VN_CAST(VN_CAST(nodep->rhsp(), Not)->lhsp(), VarRef)->varp()->isUsedClock()) )) { clearSimple("Not a buffer (goes to a clock)"); } @@ -342,7 +342,7 @@ private: m_logicVertexp->clearReducible("Block Unreducible"); // Sequential logic is dedupable } if (consumeReason) m_logicVertexp->setConsumed(consumeReason); - if (nodep->castSenItem()) m_logicVertexp->setConsumed("senItem"); + if (VN_IS(nodep, SenItem)) m_logicVertexp->setConsumed("senItem"); nodep->iterateChildren(*this); m_logicVertexp = NULL; } @@ -508,7 +508,7 @@ private: m_inSlow = lastslow; } virtual void visit(AstConcat* nodep) { - if (nodep->backp()->castNodeAssign() && nodep->backp()->castNodeAssign()->lhsp()==nodep) { + if (VN_IS(nodep->backp(), NodeAssign) && VN_CAST(nodep->backp(), NodeAssign)->lhsp()==nodep) { nodep->v3fatalSrc("Concat on LHS of assignment; V3Const should have deleted it"); } nodep->iterateChildren(*this); @@ -702,31 +702,31 @@ void GateVisitor::replaceAssigns() { // Take the Comments/assigns that were moved to the VarScope and change them to a // simple value assignment AstVarScope* vscp = vvertexp->varScp(); - if (vscp->valuep() && !vscp->valuep()->castNodeMath()) { + if (vscp->valuep() && !VN_IS(vscp->valuep(), NodeMath)) { //if (debug()>9) vscp->dumpTree(cout, "-vscPre: "); - while (AstNode* delp=vscp->valuep()->castComment()) { + while (AstNode* delp=VN_CAST(vscp->valuep(), Comment)) { delp->unlinkFrBack()->deleteTree(); VL_DANGLING(delp); } - if (AstInitial* delp=vscp->valuep()->castInitial()) { + if (AstInitial* delp=VN_CAST(vscp->valuep(), Initial)) { AstNode* bodyp=delp->bodysp(); bodyp->unlinkFrBackWithNext(); delp->replaceWith(bodyp); delp->deleteTree(); VL_DANGLING(delp); } - if (AstAlways* delp=vscp->valuep()->castAlways()) { + if (AstAlways* delp=VN_CAST(vscp->valuep(), Always)) { AstNode* bodyp=delp->bodysp(); bodyp->unlinkFrBackWithNext(); delp->replaceWith(bodyp); delp->deleteTree(); VL_DANGLING(delp); } - if (AstNodeAssign* delp=vscp->valuep()->castNodeAssign()) { + if (AstNodeAssign* delp=VN_CAST(vscp->valuep(), NodeAssign)) { AstNode* rhsp=delp->rhsp(); rhsp->unlinkFrBack(); delp->replaceWith(rhsp); delp->deleteTree(); VL_DANGLING(delp); } //if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<valuep()->castNodeMath() + if (!VN_IS(vscp->valuep(), NodeMath) || vscp->valuep()->nextp()) { vscp->dumpTree(std::cerr, "vscStrange: "); vscp->v3fatalSrc("Value of varscope not mathematical"); @@ -829,8 +829,8 @@ private: m_didReplace = true; if (nodep->lvalue()) nodep->v3fatalSrc("Can't replace lvalue assignments with const var"); AstNode* substp = m_replaceTreep->cloneTree(false); - if (nodep->castNodeVarRef() - && substp->castNodeVarRef() + if (VN_IS(nodep, NodeVarRef) + && VN_IS(substp, NodeVarRef) && nodep->same(substp)) { // Prevent a infinite loop... substp->v3fatalSrc("Replacing node with itself; perhaps circular logic?"); @@ -840,9 +840,9 @@ private: // IE what we're replacing with. // However a VARREF should point to the original as it's otherwise confusing // to throw warnings that point to a PIN rather than where the pin us used. - if (substp->castVarRef()) substp->fileline(nodep->fileline()); + if (VN_IS(substp, VarRef)) substp->fileline(nodep->fileline()); // Make the substp an rvalue like nodep. This facilitate the hashing in dedupe. - if (AstNodeVarRef* varrefp = substp->castNodeVarRef()) varrefp->lvalue(false); + if (AstNodeVarRef* varrefp = VN_CAST(substp, NodeVarRef)) varrefp->lvalue(false); nodep->replaceWith(substp); nodep->deleteTree(); VL_DANGLING(nodep); } @@ -929,7 +929,7 @@ public: // So dupit is either a different, duplicate rhsp, or the end of the hash. if (dupit != m_hashed.end()) { m_hashed.erase(inserted); - return m_hashed.iteratorNodep(dupit)->user2p()->castNodeAssign(); + return VN_CAST(m_hashed.iteratorNodep(dupit)->user2p(), NodeAssign); } return NULL; } @@ -1017,7 +1017,7 @@ public: if (m_dedupable && m_assignp) { AstNode* lhsp = m_assignp->lhsp(); // Possible todo, handle more complex lhs expressions - if (AstNodeVarRef* lhsVarRefp = lhsp->castNodeVarRef()) { + if (AstNodeVarRef* lhsVarRefp = VN_CAST(lhsp, NodeVarRef)) { if (lhsVarRefp->varScopep() != consumerVarScopep) consumerVarScopep->v3fatalSrc("Consumer doesn't match lhs of assign"); if (AstNodeAssign* dup = m_hash.hashAndFindDupe(m_assignp,activep,m_ifCondp)) { return (AstNodeVarRef*) dup->lhsp(); @@ -1157,13 +1157,13 @@ private: // assemble two Sel into one if possible AstSel* merge(AstSel* pre, AstSel* cur) { - AstVarRef* preVarRefp = pre->fromp()->castVarRef(); - AstVarRef* curVarRefp = cur->fromp()->castVarRef(); + AstVarRef* preVarRefp = VN_CAST(pre->fromp(), VarRef); + AstVarRef* curVarRefp = VN_CAST(cur->fromp(), VarRef); if (!preVarRefp || !curVarRefp || !curVarRefp->same(preVarRefp)) return NULL; // not the same var - AstConst* pstart = pre->lsbp()->castConst(); - AstConst* pwidth = pre->widthp()->castConst(); - AstConst* cstart = cur->lsbp()->castConst(); - AstConst* cwidth = cur->widthp()->castConst(); + const AstConst* pstart = VN_CAST(pre->lsbp(), Const); + const AstConst* pwidth = VN_CAST(pre->widthp(), Const); + const AstConst* cstart = VN_CAST(cur->lsbp(), Const); + const AstConst* cwidth = VN_CAST(cur->widthp(), Const); if (!pstart || !pwidth || !cstart || !cwidth) return NULL; // too complicated if (cur->lsbConst()+cur->widthConst() == pre->lsbConst()) return new AstSel(curVarRefp->fileline(), curVarRefp->cloneTree(false), cur->lsbConst(), pre->widthConst()+cur->widthConst()); @@ -1175,10 +1175,10 @@ private: V3GraphEdge* oldedgep = edgep; edgep = edgep->inNextp(); // for recursive since the edge could be deleted if (GateLogicVertex* lvertexp = dynamic_cast(oldedgep->fromp())) { - if (AstNodeAssign* assignp = lvertexp->nodep()->castNodeAssign()) { - //if (lvertexp->outSize1() && assignp->lhsp()->castSel()) { - if (assignp->lhsp()->castSel() && lvertexp->outSize1()) { - UINFO(9, "assing to the nodep["<lhsp()->castSel()->lsbConst()<<"]"<nodep(), NodeAssign)) { + //if (lvertexp->outSize1() && VN_IS(assignp->lhsp(), Sel)) { + if (VN_IS(assignp->lhsp(), Sel) && lvertexp->outSize1()) { + UINFO(9, "assing to the nodep["<lhsp(), Sel)->lsbConst()<<"]"<activep(); if (!m_logicvp) m_logicvp = lvertexp; @@ -1192,8 +1192,8 @@ private: continue; } - AstSel* preselp = m_assignp->lhsp()->castSel(); - AstSel* curselp = assignp->lhsp()->castSel(); + AstSel* preselp = VN_CAST(m_assignp->lhsp(), Sel); + AstSel* curselp = VN_CAST(assignp->lhsp(), Sel); if (!preselp || !curselp) continue; if (AstSel* newselp = merge(preselp, curselp)) { @@ -1370,10 +1370,10 @@ private: virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) { GateClkDecompState* currState = (GateClkDecompState*) vu.c(); int clk_offset = currState->m_offset; - if (AstAssignW* assignp = lvertexp->nodep()->castAssignW()) { + if (const AstAssignW* assignp = VN_CAST(lvertexp->nodep(), AssignW)) { UINFO(9,"CLK DECOMP Logic (off = "<rhsp()->castSel()) { - if (rselp->lsbp()->castConst() && rselp->widthp()->castConst()) { + if (AstSel* rselp = VN_CAST(assignp->rhsp(), Sel)) { + if (VN_IS(rselp->lsbp(), Const) && VN_IS(rselp->widthp(), Const)) { if (clk_offset < rselp->lsbConst() || clk_offset > rselp->msbConst()) { UINFO(9,"CLK DECOMP Sel [ "<msbConst()<<" : "<lsbConst()<<" ] dropped clock ("<rhsp()->castConcat()) { + } else if (AstConcat* catp = VN_CAST(assignp->rhsp(), Concat)) { UINFO(9,"CLK DECOMP Concat searching - "<lhsp()<m_last_vsp, concat_offset)) { @@ -1390,13 +1390,13 @@ private: } clk_offset += concat_offset; } - if (AstSel* lselp = assignp->lhsp()->castSel()) { - if (lselp->lsbp()->castConst() && lselp->widthp()->castConst()) { + if (const AstSel* lselp = VN_CAST(assignp->lhsp(), Sel)) { + if (VN_IS(lselp->lsbp(), Const) && VN_IS(lselp->widthp(), Const)) { clk_offset += lselp->lsbConst(); } else { return VNUser(0); } - } else if (AstVarRef* vrp = assignp->lhsp()->castVarRef()) { + } else if (const AstVarRef* vrp = VN_CAST(assignp->lhsp(), VarRef)) { if (vrp->dtypep()->width() == 1 && m_seen_clk_vectors) { if (clk_offset != 0) { UINFO(9,"Should only make it here with clk_offset = 0"<valuep()->castNodeAssign()) { + if (AstNodeAssign* assp = VN_CAST(nodep->valuep(), NodeAssign)) { UINFO(5," Removeassign "<rhsp(); valuep->unlinkFrBack(); diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index a88339cd6..599bfe65f 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -65,7 +65,7 @@ private: // METHODS AstVarScope* genInpClk(AstVarScope* vscp) { if (vscp->user2p()) { - return vscp->user2p()->castVarScope(); + return VN_CAST(vscp->user2p(), VarScope); } else { AstVar* varp = vscp->varp(); string newvarname = "__VinpClk__"+vscp->scopep()->nameDotless()+"__"+varp->name(); diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index bcd9746dc..7a2093d2e 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -62,8 +62,8 @@ private: // METHODS void nodeHashIterate(AstNode* nodep) { if (!nodep->user4()) { - if (nodep->backp()->castCFunc() - && !(nodep->castNodeStmt() || nodep->castCFunc())) { + if (VN_IS(nodep->backp(), CFunc) + && !(VN_IS(nodep, NodeStmt) || VN_IS(nodep, CFunc))) { nodep->v3fatalSrc("Node "<prettyTypeName()<<" in statement position but not marked stmt (node under function)"); } V3Hash oldHash = m_lowerHash; diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 3debeffad..301a26c63 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -109,7 +109,7 @@ private: m_allMods.push_back(nodep); m_modp->user2(CIL_MAYBE); m_modp->user4(0); // statement count - if (m_modp->castIface()) { + if (VN_IS(m_modp, Iface)) { // Inlining an interface means we no longer have a cell handle to resolve to. // If inlining moves post-scope this can perhaps be relaxed. cantInline("modIface",true); @@ -200,7 +200,7 @@ private: || v3Global.opt.inlineMult() < 1 || refs*statements < v3Global.opt.inlineMult()))); // Packages aren't really "under" anything so they confuse this algorithm - if (modp->castPackage()) doit = false; + if (VN_IS(modp, Package)) doit = false; UINFO(4, " Inline="<user1(doit); @@ -313,8 +313,8 @@ private: if (nodep->user2p()) { // Make an assignment, so we'll trace it properly // user2p is either a const or a var. - AstConst* exprconstp = nodep->user2p()->castConst(); - AstVarRef* exprvarrefp = nodep->user2p()->castVarRef(); + AstConst* exprconstp = VN_CAST(nodep->user2p(), Const); + AstVarRef* exprvarrefp = VN_CAST(nodep->user2p(), VarRef); UINFO(8,"connectto: "<user2p()<v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up"); @@ -350,16 +350,16 @@ private: } } // Iterate won't hit AstIfaceRefDType directly as it is no longer underneath the module - if (AstIfaceRefDType* ifacerefp = nodep->dtypep()->castIfaceRefDType()) { + if (AstIfaceRefDType* ifacerefp = VN_CAST(nodep->dtypep(), IfaceRefDType)) { m_renamedInterfaces.insert(nodep->name()); // Each inlined cell that contain an interface variable need to copy the IfaceRefDType and point it to // the newly cloned interface cell. - AstIfaceRefDType* newdp = ifacerefp->cloneTree(false)->castIfaceRefDType(); + AstIfaceRefDType* newdp = VN_CAST(ifacerefp->cloneTree(false), IfaceRefDType); nodep->dtypep(newdp); ifacerefp->addNextHere(newdp); // Relink to point to newly cloned cell if (newdp->cellp()) { - if (AstCell* newcellp = newdp->cellp()->user4p()->castCell()) { + if (AstCell* newcellp = VN_CAST(newdp->cellp()->user4p(), Cell)) { newdp->cellp(newcellp); newdp->cellName(newcellp->name()); // Tag the old ifacerefp to ensure it leaves no stale reference to the inlined cell. @@ -390,9 +390,9 @@ private: virtual void visit(AstVarRef* nodep) { if (nodep->varp()->user2p() // It's being converted to an alias. && !nodep->varp()->user3() - && !nodep->backp()->castAssignAlias()) { // Don't constant propagate aliases (we just made) - AstConst* exprconstp = nodep->varp()->user2p()->castConst(); - AstVarRef* exprvarrefp = nodep->varp()->user2p()->castVarRef(); + && !VN_IS(nodep->backp(), AssignAlias)) { // Don't constant propagate aliases (we just made) + AstConst* exprconstp = VN_CAST(nodep->varp()->user2p(), Const); + AstVarRef* exprvarrefp = VN_CAST(nodep->varp()->user2p(), VarRef); if (exprconstp) { nodep->replaceWith(exprconstp->cloneTree(true)); nodep->deleteTree(); VL_DANGLING(nodep); @@ -535,7 +535,7 @@ private: // Better off before, as if module has multiple instantiations // we'll save work, and we can't call pinReconnectSimple in // this loop as it clone()s itself. - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (!pinp->exprp()) continue; V3Inst::pinReconnectSimple(pinp, nodep, m_modp, false); } @@ -554,7 +554,7 @@ private: nodep->name(), nodep->modp()->origName()); m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells // Create assignments to the pins - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (!pinp->exprp()) continue; UINFO(6," Pin change from "<modVarp()<v3fatalSrc("Cloning failed"); AstNode* connectRefp = pinp->exprp(); - if (!connectRefp->castConst() && !connectRefp->castVarRef()) { + if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) { pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up"); } - if (pinNewVarp->isOutOnly() && connectRefp->castConst()) { + if (pinNewVarp->isOutOnly() && VN_IS(connectRefp, Const)) { pinp->v3error("Output port is connected to a constant pin, electrical short"); } // Propagate any attributes across the interconnect pinNewVarp->propagateAttrFrom(pinOldVarp); - if (connectRefp->castVarRef()) { - connectRefp->castVarRef()->varp()->propagateAttrFrom(pinOldVarp); + if (VN_IS(connectRefp, VarRef)) { + VN_CAST(connectRefp, VarRef)->varp()->propagateAttrFrom(pinOldVarp); } // One to one interconnect won't make a temporary variable. @@ -641,7 +641,7 @@ void V3Inline::inlineAll(AstNetlist* nodep) { // idea to avoid dumping the hugely exploded tree. AstNodeModule* nextmodp; for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) { - nextmodp = modp->nextp()->castNodeModule(); + nextmodp = VN_CAST(modp->nextp(), NodeModule); if (modp->user1()) { // Was inlined modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp); } diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 364bc5070..5b591b4e4 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -81,7 +81,7 @@ private: UINFO(4," PIN "<exprp()) return; // No-connect if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: "); - if (nodep->modVarp()->isOutOnly() && nodep->exprp()->castConst()) + if (nodep->modVarp()->isOutOnly() && VN_IS(nodep->exprp(), Const)) nodep->v3error("Output port is connected to a constant pin, electrical short"); // Use user1p on the PIN to indicate we created an assign for this pin if (!nodep->user1SetOnce()) { @@ -107,12 +107,12 @@ private: m_modp->addStmtp(assp); if (debug()>=9) assp->dumpTree(cout," _new: "); } else if (nodep->modVarp()->isIfaceRef() - || (nodep->modVarp()->subDTypep()->castUnpackArrayDType() - && nodep->modVarp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType())) { + || (VN_IS(nodep->modVarp()->subDTypep(), UnpackArrayDType) + && VN_IS(VN_CAST(nodep->modVarp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType))) { // Create an AstAssignVarScope for Vars to Cells so we can link with their scope later AstNode* lhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false); - AstVarRef* refp = exprp->castVarRef(); - AstVarXRef* xrefp = exprp->castVarXRef(); + const AstVarRef* refp = VN_CAST(exprp, VarRef); + const AstVarXRef* xrefp = VN_CAST(exprp, VarXRef); if (!refp && !xrefp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef or VarXRef"); AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, exprp); m_modp->addStmtp(assp); @@ -169,7 +169,7 @@ private: // VISITORS virtual void visit(AstVar* nodep) { - if (nodep->dtypep()->castIfaceRefDType()) { + if (VN_IS(nodep->dtypep(), IfaceRefDType)) { UINFO(8," dm-1-VAR "<dtypep()->castUnpackArrayDType() - && nodep->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType()) { + if (VN_IS(nodep->dtypep(), UnpackArrayDType) + && VN_IS(VN_CAST(nodep->dtypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) { UINFO(8," dv-vec-VAR "<dtypep()->castUnpackArrayDType(); + AstUnpackArrayDType* arrdtype = VN_CAST(nodep->dtypep(), UnpackArrayDType); AstNode* prevp = NULL; for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) { string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__"; UINFO(8,"VAR name insert "<subDTypep()->castIfaceRefDType()->cloneTree(false); + AstIfaceRefDType* ifaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType)->cloneTree(false); arrdtype->addNextHere(ifaceRefp); ifaceRefp->cellp(NULL); @@ -271,10 +271,10 @@ private: if (nodep->rangep()) { m_cellRangep = nodep->rangep(); - AstVar* ifaceVarp = nodep->nextp()->castVar(); + AstVar* ifaceVarp = VN_CAST(nodep->nextp(), Var); bool isIface = ifaceVarp - && ifaceVarp->dtypep()->castUnpackArrayDType() - && ifaceVarp->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType(); + && VN_IS(ifaceVarp->dtypep(), UnpackArrayDType) + && VN_IS(VN_CAST(ifaceVarp->dtypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); // Make all of the required clones for (int i = 0; i < m_cellRangep->elementsConst(); i++) { @@ -295,11 +295,11 @@ private: // If this AstCell is actually an interface instantiation, also clone the IfaceRef // within the same parent module as the cell if (isIface) { - AstUnpackArrayDType* arrdtype = ifaceVarp->dtypep()->castUnpackArrayDType(); - AstIfaceRefDType* origIfaceRefp = arrdtype->subDTypep()->castIfaceRefDType(); + AstUnpackArrayDType* arrdtype = VN_CAST(ifaceVarp->dtypep(), UnpackArrayDType); + AstIfaceRefDType* origIfaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType); origIfaceRefp->cellp(NULL); AstVar* varNewp = ifaceVarp->cloneTree(false); - AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false); + AstIfaceRefDType* ifaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType)->cloneTree(false); arrdtype->addNextHere(ifaceRefp); ifaceRefp->cellp(newp); ifaceRefp->cellName(newp->name()); @@ -356,9 +356,9 @@ private: } AstNode* exprp = nodep->exprp()->unlinkFrBack(); bool inputPin = nodep->modVarp()->isInput(); - if (!inputPin && !exprp->castVarRef() - && !exprp->castConcat() // V3Const will collapse the SEL with the one we're about to make - && !exprp->castSel()) { // V3Const will collapse the SEL with the one we're about to make + if (!inputPin && !VN_IS(exprp, VarRef) + && !VN_IS(exprp, Concat) // V3Const will collapse the SEL with the one we're about to make + && !VN_IS(exprp, Sel)) { // V3Const will collapse the SEL with the one we're about to make nodep->v3error("Unsupported: Per-bit array instantiations with output connections to non-wires."); // Note spec allows more complicated matches such as slices and such } @@ -369,19 +369,19 @@ private: } else { nodep->v3fatalSrc("Width mismatch; V3Width should have errored out."); } - } else if (AstArraySel* arrselp = nodep->exprp()->castArraySel()) { - if (AstUnpackArrayDType* arrp = arrselp->lhsp()->dtypep()->castUnpackArrayDType()) { - if (!arrp->subDTypep()->castIfaceRefDType()) + } else if (AstArraySel* arrselp = VN_CAST(nodep->exprp(), ArraySel)) { + if (AstUnpackArrayDType* arrp = VN_CAST(arrselp->lhsp()->dtypep(), UnpackArrayDType)) { + if (!VN_IS(arrp->subDTypep(), IfaceRefDType)) return; V3Const::constifyParamsEdit(arrselp->rhsp()); - AstConst* constp = arrselp->rhsp()->castConst(); + const AstConst* constp = VN_CAST(arrselp->rhsp(), Const); if (!constp) { nodep->v3error("Unsupported: Non-constant index when passing interface to module"); return; } string index = AstNode::encodeNumber(constp->toSInt()); - AstVarRef* varrefp = arrselp->lhsp()->castVarRef(); + AstVarRef* varrefp = VN_CAST(arrselp->lhsp(), VarRef); AstVarXRef* newp = new AstVarXRef(nodep->fileline(), varrefp->name()+"__BRA__"+index+"__KET__", "", true); newp->dtypep(nodep->modVarp()->dtypep()); newp->packagep(varrefp->packagep()); @@ -390,8 +390,8 @@ private: } } else { AstVar* pinVarp = nodep->modVarp(); - AstUnpackArrayDType* pinArrp = pinVarp->dtypep()->castUnpackArrayDType(); - if (!pinArrp || !pinArrp->subDTypep()->castIfaceRefDType()) + AstUnpackArrayDType* pinArrp = VN_CAST(pinVarp->dtypep(), UnpackArrayDType); + if (!pinArrp || !VN_IS(pinArrp->subDTypep(), IfaceRefDType)) return; AstNode* prevp = NULL; AstNode* prevPinp = NULL; @@ -405,7 +405,7 @@ private: if (!pinVarp->backp()) { varNewp = m_deModVars.find(varNewName); } else { - AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType(); + AstIfaceRefDType* ifaceRefp = VN_CAST(pinArrp->subDTypep(), IfaceRefDType); ifaceRefp->cellp(NULL); varNewp = pinVarp->cloneTree(false); varNewp->name(varNewName); @@ -429,7 +429,7 @@ private: newp->modVarp(varNewp); newp->name(newp->name() + "__BRA__" + cvtToStr(i) + "__KET__"); // And replace exprp with a new varxref - AstVarRef* varrefp = newp->exprp()->castVarRef(); + const AstVarRef* varrefp = VN_CAST(newp->exprp(), VarRef); string newname = varrefp->name() + "__BRA__" + cvtToStr(i) + "__KET__"; AstVarXRef* newVarXRefp = new AstVarXRef (nodep->fileline(), newname, "", true); newVarXRefp->varp(newp->modVarp()); @@ -504,12 +504,12 @@ public: // Note this module calles cloneTree() via new AstVar AstVar* pinVarp = pinp->modVarp(); - AstVarRef* connectRefp = pinp->exprp()->castVarRef(); - AstVarXRef* connectXRefp = pinp->exprp()->castVarXRef(); - AstBasicDType* pinBasicp = pinVarp->dtypep()->castBasicDType(); // Maybe NULL + AstVarRef* connectRefp = VN_CAST(pinp->exprp(), VarRef); + AstVarXRef* connectXRefp = VN_CAST(pinp->exprp(), VarXRef); + AstBasicDType* pinBasicp = VN_CAST(pinVarp->dtypep(), BasicDType); // Maybe NULL AstBasicDType* connBasicp = NULL; AstAssignW* assignp = NULL; - if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->castBasicDType(); + if (connectRefp) connBasicp = VN_CAST(connectRefp->varp()->dtypep(), BasicDType); // if (!alwaysCvt && connectRefp @@ -532,7 +532,7 @@ public: && !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types && connBasicp->width() == pinVarp->width()) { // Done. One to one interconnect won't need a temporary variable. - } else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) { + } else if (!alwaysCvt && !forTristate && VN_IS(pinp->exprp(), Const)) { // Done. Constant. } else { // Make a new temp wire diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 488c30c8f..c5bfc9587 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -104,7 +104,7 @@ public: m_assignp = assp; m_constp = NULL; m_everSet = true; - if (assp->rhsp()->castConst()) m_constp = assp->rhsp()->castConst(); + if (VN_IS(assp->rhsp(), Const)) m_constp = VN_CAST(assp->rhsp(), Const); } inline void complexAssign() { // A[x]=... or some complicated assignment m_assignp = NULL; @@ -329,8 +329,8 @@ private: V3Const::constifyEdit(nodep->rhsp()); // rhsp may change } // Has to be direct assignment without any EXTRACTing. - if (nodep->lhsp()->castVarRef() && !m_sideEffect && !m_noopt) { - AstVarScope* vscp = nodep->lhsp()->castVarRef()->varScopep(); + if (VN_IS(nodep->lhsp(), VarRef) && !m_sideEffect && !m_noopt) { + AstVarScope* vscp = VN_CAST(nodep->lhsp(), VarRef)->varScopep(); if (!vscp) nodep->v3fatalSrc("Scope lost on variable"); m_lifep->simpleAssign(vscp, nodep); } else { diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index 34042a103..253d01ddc 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -148,8 +148,8 @@ private: } } virtual void visit(AstAssignPost* nodep) { - if (AstVarRef* lhsp = nodep->lhsp()->castVarRef()) { - if (AstVarRef* rhsp = nodep->rhsp()->castVarRef()) { + if (AstVarRef* lhsp = VN_CAST(nodep->lhsp(), VarRef)) { + if (AstVarRef* rhsp = VN_CAST(nodep->rhsp(), VarRef)) { // Scrunch these: // __Vdly__q = __PVT__clk_clocks; // ... {no reads or writes of __PVT__q after the first write to __Vdly__q} diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 1d61ddbe2..3d54ef133 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -131,7 +131,7 @@ private: AstNodeModule* findModuleSym(const string& modName) { VSymEnt* foundp = m_mods.rootp()->findIdFallback(modName); if (!foundp) return NULL; - else return foundp->nodep()->castNodeModule(); + else return VN_CAST(foundp->nodep(), NodeModule); } AstNodeModule* resolveModule(AstNode* nodep, const string& modName) { @@ -203,7 +203,7 @@ private: <<"' does not match "<typeName()<<" name: "<prettyName()); } } - if (nodep->castIface() || nodep->castPackage()) nodep->inLibrary(true); // Interfaces can't be at top, unless asked + if (VN_IS(nodep, Iface) || VN_IS(nodep, Package)) nodep->inLibrary(true); // Interfaces can't be at top, unless asked bool topMatch = (v3Global.opt.topModule()==nodep->prettyName()); if (topMatch) { m_topVertexp = vertex(nodep); @@ -231,11 +231,11 @@ private: // but we might support modules-under-modules someday. AstNodeModule* modp = resolveModule(nodep, nodep->ifaceName()); if (modp) { - if (modp->castIface()) { + if (VN_IS(modp, Iface)) { // Track module depths, so can sort list from parent down to children new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false); - if (!nodep->cellp()) nodep->ifacep(modp->castIface()); - } else if (modp->castNotFoundModule()) { // Will error out later + if (!nodep->cellp()) nodep->ifacep(VN_CAST(modp, Iface)); + } else if (VN_IS(modp, NotFoundModule)) { // Will error out later } else { nodep->v3error("Non-interface used as an interface: "<prettyName()); } @@ -298,7 +298,7 @@ private: // This lets us link the XREFs between the (uncloned) children so // they don't point to the same module which would // break parameter resolution. - AstNodeModule* otherModp = cellmodp->user2p()->castNodeModule(); + AstNodeModule* otherModp = VN_CAST(cellmodp->user2p(), NodeModule); if (!otherModp) { otherModp = cellmodp->cloneTree(false); otherModp->name(otherModp->name()+"__Vrcm"); @@ -342,7 +342,7 @@ private: // Convert .* to list of pins bool pinStar = false; for (AstPin* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) { - nextp = pinp->nextp()->castPin(); + nextp = VN_CAST(pinp->nextp(), Pin); if (pinp->dotStar()) { if (pinStar) pinp->v3error("Duplicate .* in a cell"); pinStar = true; @@ -351,10 +351,10 @@ private: } } // Convert unnamed pins to pin number based assignments - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (pinp->name()=="") pinp->name("__pinNumber"+cvtToStr(pinp->pinNum())); } - for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { pinp->param(true); if (pinp->name()=="") pinp->name("__paramNumber"+cvtToStr(pinp->pinNum())); } @@ -362,7 +362,7 @@ private: nodep->modName(nodep->modp()->name()); // Note what pins exist vl_unordered_set ports; // Symbol table of all connected port names - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells"); if (!pinp->exprp()) { if (pinp->name().substr(0, 11) == "__pinNumber") { @@ -378,7 +378,7 @@ private: // We search ports, rather than in/out declarations as they aren't resolved yet, // and it's easier to do it now than in V3LinkDot when we'd need to repeat steps. for (AstNode* portnodep = nodep->modp()->stmtsp(); portnodep; portnodep=portnodep->nextp()) { - if (AstPort* portp = portnodep->castPort()) { + if (const AstPort* portp = VN_CAST(portnodep, Port)) { if (ports.find(portp->name()) == ports.end() && ports.find("__pinNumber"+cvtToStr(portp->pinNum())) == ports.end()) { if (pinStar) { @@ -398,7 +398,7 @@ private: } } } - if (nodep->modp()->castIface()) { + if (VN_IS(nodep->modp(), Iface)) { // Cell really is the parent's instantiation of an interface, not a normal module // Make sure we have a variable to refer to this cell, so can . // in the same way that a child does. Rename though to avoid conflict with cell. @@ -443,7 +443,7 @@ private: void readModNames() { // Look at all modules, and store pointers to all module names for (AstNodeModule* nextp,* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nextp) { - nextp = nodep->nextp()->castNodeModule(); + nextp = VN_CAST(nodep->nextp(), NodeModule); AstNodeModule* foundp = findModuleSym(nodep->name()); if (foundp && foundp != nodep) { if (!(foundp->fileline()->warnIsOff(V3ErrorCode::MODDUP) || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP))) { diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 8414f4a85..206da560c 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -190,13 +190,13 @@ public: // METHODS static string nodeTextType(AstNode* nodep) { - if (nodep->castVar()) return "variable"; - else if (nodep->castCell()) return "cell"; - else if (nodep->castTask()) return "task"; - else if (nodep->castFunc()) return "function"; - else if (nodep->castBegin()) return "block"; - else if (nodep->castIface()) return "interface"; - else if (nodep->castParamTypeDType()) return "parameter type"; + if (VN_IS(nodep, Var)) return "variable"; + else if (VN_IS(nodep, Cell)) return "cell"; + else if (VN_IS(nodep, Task)) return "task"; + else if (VN_IS(nodep, Func)) return "function"; + else if (VN_IS(nodep, Begin)) return "block"; + else if (VN_IS(nodep, Iface)) return "interface"; + else if (VN_IS(nodep, ParamTypeDType)) return "parameter type"; else return nodep->prettyTypeName(); } @@ -217,8 +217,8 @@ public: // Good. } else if (foundp->imported()) { // From package // We don't throw VARHIDDEN as if the import is later the symbol table's import wouldn't warn - } else if (nodep->castBegin() && fnodep->castBegin() - && nodep->castBegin()->generate()) { + } else if (VN_IS(nodep, Begin) && VN_IS(fnodep, Begin) + && VN_CAST(nodep, Begin)->generate()) { // Begin: ... blocks often replicate under genif/genfor, so simply suppress duplicate checks // See t_gen_forif.v for an example. } else { @@ -370,10 +370,10 @@ public: } // Iface for a raw or arrayed iface static AstIfaceRefDType* ifaceRefFromArray(AstNodeDType* nodep) { - AstIfaceRefDType* ifacerefp = nodep->castIfaceRefDType(); + AstIfaceRefDType* ifacerefp = VN_CAST(nodep, IfaceRefDType); if (!ifacerefp) { - if (AstUnpackArrayDType* arrp = nodep->castUnpackArrayDType()) { - ifacerefp = arrp->subDTypep()->castIfaceRefDType(); + if (AstUnpackArrayDType* arrp = VN_CAST(nodep, UnpackArrayDType)) { + ifacerefp = VN_CAST(arrp->subDTypep(), IfaceRefDType); } } return ifacerefp; @@ -381,7 +381,7 @@ public: void computeIfaceVarSyms() { for (IfaceVarSyms::iterator it = m_ifaceVarSyms.begin(); it != m_ifaceVarSyms.end(); ++it) { VSymEnt* varSymp = *it; - AstVar* varp = varSymp ? varSymp->nodep()->castVar() : NULL; + AstVar* varp = varSymp ? VN_CAST(varSymp->nodep(), Var) : NULL; UINFO(9, " insAllIface se"<<(void*)varSymp<<" "<subDTypep()); if (!ifacerefp) varp->v3fatalSrc("Non-ifacerefs on list!"); @@ -403,7 +403,7 @@ public: VSymEnt* foundp = ifaceSymp->findIdFallback(ifacerefp->modportName()); bool ok = false; if (foundp) { - if (AstModport* modportp = foundp->nodep()->castModport()) { + if (AstModport* modportp = VN_CAST(foundp->nodep(), Modport)) { UINFO(4,"Link Modport: "<modportp(modportp); ifOrPortSymp = foundp; @@ -424,8 +424,8 @@ public: // Track and later insert scope aliases; an interface referenced by a child cell connecting to that interface // Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell UINFO(9," insertScopeAlias se"<<(void*)lhsp<<" se"<<(void*)rhsp<nodep()->castCell() - && !rhsp->nodep()->castCell()->modp()->castIface()) { + if (VN_IS(rhsp->nodep(), Cell) + && !VN_IS(VN_CAST(rhsp->nodep(), Cell)->modp(), Iface)) { rhsp->nodep()->v3fatalSrc("Got a non-IFACE alias RHS"); } m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp)); @@ -447,7 +447,7 @@ public: // srcp should be an interface reference pointing to the interface we want to import lhsp->importFromIface(symsp(), srcp); // Allow access to objects not permissible to be listed in a modport - if (srcp->nodep()->castModport()) { + if (VN_IS(srcp->nodep(), Modport)) { lhsp->importFromIface(symsp(), srcp->parentp(), true); } } @@ -499,8 +499,8 @@ public: // then look up (inst name or modname) if (firstId) { // Check this module - subcellnames - AstCell* cellp = lookupSymp ? lookupSymp->nodep()->castCell() : NULL; // Replicated below - AstCellInline* inlinep = lookupSymp ? lookupSymp->nodep()->castCellInline() : NULL; // Replicated below + AstCell* cellp = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) : NULL; // Replicated below + AstCellInline* inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) : NULL; // Replicated below if (VSymEnt* findSymp = findWithAltFallback(lookupSymp, ident, altIdent)) { lookupSymp = findSymp; } @@ -512,8 +512,8 @@ public: bool crossedCell = false; // Crossed a cell boundary while (lookupSymp) { lookupSymp = lookupSymp->parentp(); - cellp = lookupSymp ? lookupSymp->nodep()->castCell() : NULL; // Replicated above - inlinep = lookupSymp ? lookupSymp->nodep()->castCellInline() : NULL; // Replicated above + cellp = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) : NULL; // Replicated above + inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) : NULL; // Replicated above if (lookupSymp) { UINFO(9,"\t\tUp to "<nodep()->castVar()) { + if (crossedCell && VN_IS(lookupSymp->nodep(), Var)) { UINFO(9,"\t\tNot found but matches var name in parent "<modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) { - // if (nodep->castPackage()) {}} + //for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) { + // if (VN_IS(nodep, Package)) {}} m_statep->insertDUnit(nodep); @@ -676,7 +676,7 @@ class LinkDotFindVisitor : public AstNVisitor { UINFO(8," "<forPrearray() && nodep->castPackage()); + bool standalonePkg = !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package)); bool doit = (m_modSymp || standalonePkg); string oldscope = m_scope; VSymEnt* oldModSymp = m_modSymp; @@ -691,7 +691,7 @@ class LinkDotFindVisitor : public AstNVisitor { UINFO(4," Link Module: "<dead()) nodep->v3fatalSrc("Module in cell tree mislabeled as dead?"); VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); - m_packagep = nodep->castPackage(); + m_packagep = VN_CAST(nodep, Package); if (standalonePkg) { if (m_packagep->isDollarUnit()) { m_curSymp = m_modSymp = m_statep->dunitEntp(); @@ -713,7 +713,7 @@ class LinkDotFindVisitor : public AstNVisitor { nodep->user2(false); nodep->user4(true); // Interfaces need another pass when signals are resolved - if (AstIface* ifacep = nodep->castIface()) { + if (AstIface* ifacep = VN_CAST(nodep, Iface)) { m_statep->insertIfaceModSym(ifacep, m_curSymp); } } else { //!doit @@ -829,7 +829,7 @@ class LinkDotFindVisitor : public AstNVisitor { // places such as tasks, where "task ...; begin ... end" // are common. for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (stmtp->castVar()) { + if (VN_IS(stmtp, Var)) { ++m_modBeginNum; nodep->name("unnamedblk"+cvtToStr(m_modBeginNum)); break; @@ -865,8 +865,8 @@ class LinkDotFindVisitor : public AstNVisitor { // This should probably be done in the Parser instead, as then we could // just attact normal signal attributes to it. if (nodep->fvarp() - && !nodep->fvarp()->castVar()) { - AstNodeDType* dtypep = nodep->fvarp()->castNodeDType(); + && !VN_IS(nodep->fvarp(), Var)) { + AstNodeDType* dtypep = VN_CAST(nodep->fvarp(), NodeDType); // If unspecified, function returns one bit; however when we support NEW() it could // also return the class reference. if (dtypep) dtypep->unlinkFrBack(); @@ -894,7 +894,7 @@ class LinkDotFindVisitor : public AstNVisitor { // Find under either a task or the module's vars VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) foundp = m_modSymp; // Conflicts with modname? - AstVar* findvarp = foundp ? foundp->nodep()->castVar() : NULL; + AstVar* findvarp = foundp ? VN_CAST(foundp->nodep(), Var) : NULL; bool ins=false; if (!foundp) { ins=true; @@ -910,7 +910,7 @@ class LinkDotFindVisitor : public AstNVisitor { || (findvarp->isSignal() && nodep->isIO())) { findvarp->combineType(nodep); nodep->fileline()->modifyStateInherit(nodep->fileline()); - AstBasicDType* bdtypep = findvarp->childDTypep()->castBasicDType(); + AstBasicDType* bdtypep = VN_CAST(findvarp->childDTypep(), BasicDType); if (bdtypep && bdtypep->implicit()) { // Then have "input foo" and "real foo" so the dtype comes from the other side. AstNodeDType* newdtypep = nodep->subDTypep(); @@ -991,7 +991,7 @@ class LinkDotFindVisitor : public AstNVisitor { // Find under either a task or the module's vars VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) foundp = m_modSymp; // Conflicts with modname? - AstEnumItem* findvarp = foundp ? foundp->nodep()->castEnumItem() : NULL; + AstEnumItem* findvarp = foundp ? VN_CAST(foundp->nodep(), EnumItem) : NULL; bool ins=false; if (!foundp) { ins=true; @@ -1091,10 +1091,10 @@ private: void pinImplicitExprRecurse(AstNode* nodep) { // Under a pin, Check interconnect expression for a pin reference or a concat. // Create implicit variable as needed - if (nodep->castDot()) { // Not creating a simple implied type, + if (VN_IS(nodep, Dot)) { // Not creating a simple implied type, // and implying something else would just confuse later errors } - else if (nodep->castVarRef() || nodep->castParseRef()) { + else if (VN_IS(nodep, VarRef) || VN_IS(nodep, ParseRef)) { // To prevent user errors, we should only do single bit // implicit vars, however some netlists (MIPS) expect single // bit implicit wires to get created with range 0:0 etc. @@ -1140,7 +1140,7 @@ private: nodep->iterateChildren(*this); nodep->v3warn(DEFPARAM,"Suggest replace defparam with Verilog 2001 #(."<prettyName()<<"(...etc...))"); VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path()); - AstCell* cellp = foundp ? foundp->nodep()->castCell() : NULL; + AstCell* cellp = foundp ? VN_CAST(foundp->nodep(), Cell) : NULL; if (!cellp) { nodep->v3error("In defparam, cell "<path()<<" never declared"); } else { @@ -1162,7 +1162,7 @@ private: // Need to set pin numbers after varnames are created // But before we do the final resolution based on names VSymEnt* foundp = m_statep->getNodeSym(m_modp)->findIdFlat(nodep->name()); - AstVar* refp = foundp ? foundp->nodep()->castVar() : NULL; + AstVar* refp = foundp ? VN_CAST(foundp->nodep(), Var) : NULL; if (!refp) { nodep->v3error("Input/output/inout declaration not found for port: "<prettyName()); } else if (!refp->isIO() && !refp->isIfaceRef()) { @@ -1187,10 +1187,10 @@ private: // tran gates need implicit creation // As VarRefs don't exist in forPrimary, sanity check if (m_statep->forPrimary()) nodep->v3fatalSrc("Assign aliases unexpected pre-dot"); - if (AstVarRef* forrefp = nodep->lhsp()->castVarRef()) { + if (AstVarRef* forrefp = VN_CAST(nodep->lhsp(), VarRef)) { pinImplicitExprRecurse(forrefp); } - if (AstVarRef* forrefp = nodep->rhsp()->castVarRef()) { + if (AstVarRef* forrefp = VN_CAST(nodep->rhsp(), VarRef)) { pinImplicitExprRecurse(forrefp); } nodep->iterateChildren(*this); @@ -1282,8 +1282,8 @@ class LinkDotScopeVisitor : public AstNVisitor { // Track aliases created by V3Inline; if we get a VARXREF(aliased_from) // we'll need to replace it with a VARXREF(aliased_to) if (debug()>=9) nodep->dumpTree(cout,"-\t\t\t\talias: "); - AstVarScope* fromVscp = nodep->lhsp()->castVarRef()->varScopep(); - AstVarScope* toVscp = nodep->rhsp()->castVarRef()->varScopep(); + AstVarScope* fromVscp = VN_CAST(nodep->lhsp(), VarRef)->varScopep(); + AstVarScope* toVscp = VN_CAST(nodep->rhsp(), VarRef)->varScopep(); if (!fromVscp || !toVscp) nodep->v3fatalSrc("Bad alias scopes"); fromVscp->user2p(toVscp); nodep->iterateChildren(*this); @@ -1293,8 +1293,8 @@ class LinkDotScopeVisitor : public AstNVisitor { if (debug()>=9) nodep->dumpTree(cout,"-\t\t\t\tavs: "); VSymEnt* rhsSymp; { - AstVarRef* refp = nodep->rhsp()->castVarRef(); - AstVarXRef* xrefp = nodep->rhsp()->castVarXRef(); + AstVarRef* refp = VN_CAST(nodep->rhsp(), VarRef); + AstVarXRef* xrefp = VN_CAST(nodep->rhsp(), VarXRef); if (!refp && !xrefp) nodep->v3fatalSrc("Unsupported: Non Var(X)Ref attached to interface pin"); string inl = (xrefp && xrefp->inlinedDots().size()) ? (xrefp->inlinedDots() + "__DOT__") : ""; VSymEnt* symp = NULL; @@ -1314,8 +1314,8 @@ class LinkDotScopeVisitor : public AstNVisitor { } VSymEnt* lhsSymp; { - AstVarXRef* xrefp = nodep->lhsp()->castVarXRef(); - AstVarRef* refp = nodep->lhsp()->castVarRef(); + const AstVarXRef* xrefp = VN_CAST(nodep->lhsp(), VarXRef); + const AstVarRef* refp = VN_CAST(nodep->lhsp(), VarRef); if (!refp && !xrefp) nodep->v3fatalSrc("Unsupported: Non Var(X)Ref attached to interface pin"); string scopename = refp ? refp->varp()->name() : xrefp->dotted()+"."+xrefp->name(); @@ -1385,7 +1385,7 @@ class LinkDotIfaceVisitor : public AstNVisitor { VSymEnt* symp = m_curSymp->findIdFallback(nodep->name()); if (!symp) { nodep->v3error("Modport item not found: "<prettyName()); - } else if (AstNodeFTask* ftaskp = symp->nodep()->castNodeFTask()) { + } else if (AstNodeFTask* ftaskp = VN_CAST(symp->nodep(), NodeFTask)) { // Make symbol under modport that points at the _interface_'s var, not the modport. nodep->ftaskp(ftaskp); VSymEnt* subSymp = m_statep->insertSym(m_curSymp, nodep->name(), ftaskp, NULL/*package*/); @@ -1405,12 +1405,12 @@ class LinkDotIfaceVisitor : public AstNVisitor { VSymEnt* symp = m_curSymp->findIdFallback(nodep->name()); if (!symp) { nodep->v3error("Modport item not found: "<prettyName()); - } else if (AstVar* varp = symp->nodep()->castVar()) { + } else if (AstVar* varp = VN_CAST(symp->nodep(), Var)) { // Make symbol under modport that points at the _interface_'s var via the modport. // (Need modport still to test input/output markings) nodep->varp(varp); m_statep->insertSym(m_curSymp, nodep->name(), nodep, NULL/*package*/); - } else if (AstVarScope* vscp = symp->nodep()->castVarScope()) { + } else if (AstVarScope* vscp = VN_CAST(symp->nodep(), VarScope)) { // Make symbol under modport that points at the _interface_'s var, not the modport. nodep->varp(vscp->varp()); m_statep->insertSym(m_curSymp, nodep->name(), vscp, NULL/*package*/); @@ -1531,10 +1531,10 @@ private: // Return a variable if possible, auto converting a modport to variable if (!symp) { return NULL; - } else if (symp->nodep()->castVar()) { - return symp->nodep()->castVar(); - } else if (symp->nodep()->castModportVarRef()) { - AstModportVarRef* snodep = symp->nodep()->castModportVarRef(); + } else if (VN_IS(symp->nodep(), Var)) { + return VN_CAST(symp->nodep(), Var); + } else if (VN_IS(symp->nodep(), ModportVarRef)) { + AstModportVarRef* snodep = VN_CAST(symp->nodep(), ModportVarRef); AstVar* varp = snodep->varp(); if (lvalue && snodep->isInput()) { nodep->v3error("Attempt to drive input-only modport: "<prettyName()); @@ -1545,8 +1545,8 @@ private: } } void taskFuncSwapCheck(AstNodeFTaskRef* nodep) { - if (nodep->taskp() && nodep->taskp()->castTask() - && nodep->castFuncRef()) nodep->v3error("Illegal call of a task as a function: "<prettyName()); + if (nodep->taskp() && VN_IS(nodep->taskp(), Task) + && VN_IS(nodep, FuncRef)) nodep->v3error("Illegal call of a task as a function: "<prettyName()); } inline void checkNoDot(AstNode* nodep) { if (VL_UNLIKELY(m_ds.m_dotPos != DP_NONE)) { @@ -1620,7 +1620,7 @@ private: nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out } else { - if (nodep->modp()->castNotFoundModule()) { + if (VN_IS(nodep->modp(), NotFoundModule)) { // Prevent warnings about missing pin connects if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree(); if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree(); @@ -1649,14 +1649,14 @@ private: VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name()); const char* whatp = nodep->param() ? "parameter pin" : "pin"; if (!foundp) { - if (nodep->name() == "__paramNumber1" && m_cellp->modp()->castPrimitive()) { + if (nodep->name() == "__paramNumber1" && VN_IS(m_cellp->modp(), Primitive)) { // Primitive parameter is really a delay we can just ignore nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); return; } nodep->v3error(ucfirst(whatp)<<" not found: "<prettyName()); } - else if (AstVar* refp = foundp->nodep()->castVar()) { + else if (AstVar* refp = VN_CAST(foundp->nodep(), Var)) { if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) { nodep->v3error(ucfirst(whatp)<<" is not an in/out/inout/param/interface: "<prettyName()); } else { @@ -1664,7 +1664,7 @@ private: markAndCheckPinDup(nodep, refp, whatp); } } - else if (AstParamTypeDType* refp = foundp->nodep()->castParamTypeDType()) { + else if (AstParamTypeDType* refp = VN_CAST(foundp->nodep(), ParamTypeDType)) { nodep->modPTypep(refp); markAndCheckPinDup(nodep, refp, whatp); } @@ -1692,7 +1692,7 @@ private: m_ds.m_dotPos = DP_SCOPE; // m_ds.m_dotText communicates the cell prefix between stages - if (nodep->lhsp()->castPackageRef()) { + if (VN_IS(nodep->lhsp(), PackageRef)) { //if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in dotted reference"); m_ds.m_dotErr=true; } m_ds.m_dotPos = DP_PACKAGE; } else { @@ -1700,7 +1700,7 @@ private: nodep->lhsp()->iterateAndNext(*this); //if (debug()>=9) nodep->dumpTree("-dot-lho: "); } - if (m_ds.m_unresolved && (nodep->lhsp()->castCellRef() || nodep->lhsp()->castCellArrayRef())) { + if (m_ds.m_unresolved && (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) { m_ds.m_unlinkedScope = nodep->lhsp(); } if (!m_ds.m_dotErr) { // Once something wrong, give up @@ -1766,8 +1766,8 @@ private: expectWhat = "scope/variable"; allowScope = true; allowVar = true; - if (!m_ds.m_dotp->lhsp()->castPackageRef()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); - packagep = m_ds.m_dotp->lhsp()->castPackageRef()->packagep(); + if (!VN_IS(m_ds.m_dotp->lhsp(), PackageRef)) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); + packagep = VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(); if (!packagep) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); m_ds.m_dotSymp = m_statep->getNodeSym(packagep); m_ds.m_dotPos = DP_SCOPE; @@ -1799,9 +1799,9 @@ private: // What fell out? bool ok = false; if (!foundp) { - } else if (foundp->nodep()->castCell() - || foundp->nodep()->castBegin() - || foundp->nodep()->castModule()) { // if top + } else if (VN_IS(foundp->nodep(), Cell) + || VN_IS(foundp->nodep(), Begin) + || VN_IS(foundp->nodep(), Module)) { // if top if (allowScope) { ok = true; if (m_ds.m_dotText!="") m_ds.m_dotText += "."; @@ -1810,16 +1810,16 @@ private: m_ds.m_dotPos = DP_SCOPE; // Upper AstDot visitor will handle it from here } - else if (foundp->nodep()->castCell() + else if (VN_IS(foundp->nodep(), Cell) && allowVar && m_cellp) { - AstCell* cellp = foundp->nodep()->castCell(); - if (cellp->modp()->castIface()) { + AstCell* cellp = VN_CAST(foundp->nodep(), Cell); + if (VN_IS(cellp->modp(), Iface)) { // 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; + AstVar* ifaceRefVarp = ifaceSymp ? VN_CAST(ifaceSymp->nodep(), Var) : NULL; if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "< iface varref "<nodep()<fileline(), ifaceRefVarp, false); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); - } else if (cellp->modp()->castNotFoundModule()) { + } else if (VN_IS(cellp->modp(), NotFoundModule)) { cellp->v3error("Cannot find file containing interface: " << AstNode::prettyName(cellp->modp()->name())); } } @@ -1857,7 +1857,7 @@ private: refp->varp(varp); m_ds.m_dotText = ""; if (m_ds.m_unresolved && m_ds.m_unlinkedScope) { - newp = new AstUnlinkedRef(nodep->fileline(), refp->castVarXRef(), + newp = new AstUnlinkedRef(nodep->fileline(), VN_CAST(refp, VarXRef), refp->name(), m_ds.m_unlinkedScope->unlinkFrBack()); m_ds.m_unlinkedScope = NULL; m_ds.m_unresolved = false; @@ -1875,23 +1875,23 @@ private: ok = true; } } - else if (AstModport* modportp = foundp->nodep()->castModport()) { + else if (AstModport* modportp = VN_CAST(foundp->nodep(), Modport)) { // A scope reference into an interface's modport (not necessarily at a pin connection) UINFO(9,"cell-ref-to-modport "<nodep()<nodep()->castCell() - || !m_ds.m_dotSymp->nodep()->castCell()->modp() - || !m_ds.m_dotSymp->nodep()->castCell()->modp()->castIface()) { + || !VN_IS(m_ds.m_dotSymp->nodep(), Cell) + || !VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp() + || !VN_IS(VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp(), Iface)) { nodep->v3error("Modport not referenced as ."<prettyName()); - } else if (!m_ds.m_dotSymp->nodep()->castCell()->modp() - || !m_ds.m_dotSymp->nodep()->castCell()->modp()->castIface()) { + } else if (!VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp() + || !VN_IS(VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp(), Iface)) { nodep->v3error("Modport not referenced from underneath an interface: "<prettyName()); } else { - AstCell* cellp = m_ds.m_dotSymp->nodep()->castCell(); + AstCell* cellp = VN_CAST(m_ds.m_dotSymp->nodep(), Cell); if (!cellp) nodep->v3fatalSrc("Modport not referenced from a cell"); - AstIface* ifacep = cellp->modp()->castIface(); + AstIface* ifacep = VN_CAST(cellp->modp(), Iface); //string cellName = m_ds.m_dotText; // Use cellp->name if (m_ds.m_dotText!="") m_ds.m_dotText += "."; m_ds.m_dotText += nodep->name(); @@ -1903,7 +1903,7 @@ private: nodep->replaceWith(refp); pushDeletep(nodep); VL_DANGLING(nodep); } } - else if (AstEnumItem* valuep = foundp->nodep()->castEnumItem()) { + else if (AstEnumItem* valuep = VN_CAST(foundp->nodep(), EnumItem)) { if (allowVar) { AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep()); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); @@ -1914,7 +1914,7 @@ private: // if (!ok) { // Cells/interfaces can't be implicit - bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false; + bool isCell = foundp ? VN_IS(foundp->nodep(), Cell) : false; bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell); bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name())); if (err) { @@ -2000,7 +2000,7 @@ private: // V3Inst may have expanded arrays of interfaces to AstVarXRef's even though they are in the same module // detect this and convert to normal VarRefs if (!m_statep->forPrearray() && !m_statep->forScopeCreation()) { - if (nodep->dtypep()->castIfaceRefDType()) { + if (VN_IS(nodep->dtypep(), IfaceRefDType)) { AstVarRef* newrefp = new AstVarRef(nodep->fileline(), nodep->varp(), nodep->lvalue()); nodep->replaceWith(newrefp); nodep->deleteTree(); VL_DANGLING(nodep); @@ -2009,14 +2009,14 @@ private: } else { string baddot; VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); - AstVarScope* vscp = foundp ? foundp->nodep()->castVarScope() : NULL; + AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL; if (!vscp) { nodep->v3error("Can't find varpin scope of '"<dotted()+"."+nodep->prettyName()); okSymp->cellErrorScopes(nodep); } else { while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal UINFO(7," Resolved pre-alias "<user2p()->castVarScope(); + vscp = VN_CAST(vscp->user2p(), VarScope); } // Convert the VarXRef to a VarRef, so we don't need later optimizations to deal with VarXRef. nodep->varp(vscp->varp()); @@ -2054,9 +2054,9 @@ private: if (nodep->user3SetOnce()) return; UINFO(8," "<lhsp()->castPackageRef()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); - if (!m_ds.m_dotp->lhsp()->castPackageRef()->packagep()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); - nodep->packagep(m_ds.m_dotp->lhsp()->castPackageRef()->packagep()); + if (!VN_IS(m_ds.m_dotp->lhsp(), PackageRef)) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); + if (!VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); + nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = NULL; } else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) { @@ -2113,7 +2113,7 @@ private: VSymEnt* foundp = NULL; AstNodeFTask* taskp = NULL; foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); - taskp = foundp ? foundp->nodep()->castNodeFTask() : NULL; // Maybe NULL + taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; // Maybe NULL if (taskp) { nodep->taskp(taskp); nodep->packagep(foundp->packagep()); @@ -2215,9 +2215,9 @@ private: // Resolve its reference if (nodep->user3SetOnce()) return; if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { - if (!m_ds.m_dotp->lhsp()->castPackageRef()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); - if (!m_ds.m_dotp->lhsp()->castPackageRef()->packagep()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); - nodep->packagep(m_ds.m_dotp->lhsp()->castPackageRef()->packagep()); + if (!VN_IS(m_ds.m_dotp->lhsp(), PackageRef)) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); + if (!VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep()) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); + nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = NULL; } else { @@ -2230,11 +2230,11 @@ private: } else { foundp = m_curSymp->findIdFallback(nodep->name()); } - if (AstTypedef* defp = foundp ? foundp->nodep()->castTypedef() : NULL) { + if (AstTypedef* defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : NULL) { nodep->refDTypep(defp->subDTypep()); nodep->packagep(foundp->packagep()); } - else if (AstParamTypeDType* defp = foundp ? foundp->nodep()->castParamTypeDType() : NULL) { + else if (AstParamTypeDType* defp = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) : NULL) { nodep->refDTypep(defp); nodep->packagep(foundp->packagep()); } @@ -2249,7 +2249,7 @@ private: nodep->iterateChildren(*this); checkNoDot(nodep); VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); - AstNodeFTask* taskp = foundp ? foundp->nodep()->castNodeFTask() : NULL; + AstNodeFTask* taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; if (!taskp) { nodep->v3error("Can't find definition of exported task/function: "<prettyName()); } else if (taskp->dpiExport()) { nodep->v3error("Function was already DPI Exported, duplicate not allowed: "<prettyName()); diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 495cf1788..6dde64548 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -63,16 +63,16 @@ private: AstJumpLabel* findAddLabel(AstNode* nodep, bool endOfIter) { // Put label under given node, and if WHILE optionally at end of iteration UINFO(4,"Create label for "<castJumpLabel()) return nodep->castJumpLabel(); // Done + if (VN_IS(nodep, JumpLabel)) return VN_CAST(nodep, JumpLabel); // Done AstNode* underp = NULL; bool under_and_next = true; - if (nodep->castBegin()) underp = nodep->castBegin()->stmtsp(); - else if (nodep->castNodeFTask()) underp = nodep->castNodeFTask()->stmtsp(); - else if (nodep->castWhile()) { + if (VN_IS(nodep, Begin)) underp = VN_CAST(nodep, Begin)->stmtsp(); + else if (VN_IS(nodep, NodeFTask)) underp = VN_CAST(nodep, NodeFTask)->stmtsp(); + else if (VN_IS(nodep, While)) { if (endOfIter) { // Note we jump to end of bodysp; a FOR loop has its increment under incsp() which we don't skip - underp = nodep->castWhile()->bodysp(); + underp = VN_CAST(nodep, While)->bodysp(); } else { underp = nodep; under_and_next=false; // IE we skip the entire while } @@ -84,14 +84,14 @@ private: // Skip over variables as we'll just move them in a momement // Also this would otherwise prevent us from using a label twice // see t_func_return test. - while (underp && underp->castVar()) underp = underp->nextp(); + while (underp && VN_IS(underp, Var)) underp = underp->nextp(); if (underp) UINFO(5," Underpoint is "<v3fatalSrc("Break/disable/continue not under expected statement"); return NULL; - } else if (underp->castJumpLabel()) { - return underp->castJumpLabel(); + } else if (VN_IS(underp, JumpLabel)) { + return VN_CAST(underp, JumpLabel); } else { // Move underp stuff to be under a new label AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), NULL); @@ -104,7 +104,7 @@ private: // Keep any AstVars under the function not under the new JumpLabel for (AstNode* nextp, *varp=underp; varp; varp = nextp) { nextp = varp->nextp(); - if (varp->castVar()) { + if (VN_IS(varp, Var)) { labelp->addPrev(varp->unlinkFrBack()); } } @@ -177,7 +177,7 @@ private: } virtual void visit(AstReturn* nodep) { nodep->iterateChildren(*this); - AstFunc* funcp = m_ftaskp->castFunc(); + AstFunc* funcp = VN_CAST(m_ftaskp, Func); if (!m_ftaskp) { nodep->v3error("Return isn't underneath a task or function"); } else if (funcp && !nodep->lhsp()) { nodep->v3error("Return underneath a function should have return value"); } else if (!funcp && nodep->lhsp()) { nodep->v3error("Return underneath a task shouldn't have return value"); } @@ -185,7 +185,7 @@ private: if (funcp && nodep->lhsp()) { // Set output variable to return value nodep->addPrev(new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), funcp->fvarp()->castVar(), true), + new AstVarRef(nodep->fileline(), VN_CAST(funcp->fvarp(), Var), true), nodep->lhsp()->unlinkFrBackWithNext())); } // Jump to the end of the function call diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 88839ac7e..74fe776ff 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -242,7 +242,7 @@ private: // We'll deal with mismatching pins later if (!taskp) return; for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (const AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { if (portp->isInput()) { pinp->iterate(*this); diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 4de07fb3b..5396593ce 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -56,7 +56,7 @@ void V3LinkLevel::modSortByLevel() { ModVec vec; AstNodeModule* topp = NULL; - for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) { + for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) { if (nodep->level()<=2) { if (topp) { nodep->v3warn(E_MULTITOP, "Unsupported: Multiple top level modules: " @@ -108,7 +108,7 @@ void V3LinkLevel::wrapTop(AstNetlist* netlistp) { void V3LinkLevel::wrapTopCell(AstNetlist* netlistp) { AstNodeModule* newmodp = netlistp->modulesp(); if (!newmodp || !newmodp->isTop()) netlistp->v3fatalSrc("No TOP module found to process"); - AstNodeModule* oldmodp = newmodp->nextp()->castNodeModule(); + AstNodeModule* oldmodp = VN_CAST(newmodp->nextp(), NodeModule); if (!oldmodp) netlistp->v3fatalSrc("No module found to process"); // Add instance @@ -121,7 +121,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* netlistp) { // Add pins for (AstNode* subnodep=oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { - if (AstVar* oldvarp=subnodep->castVar()) { + if (AstVar* oldvarp=VN_CAST(subnodep, Var)) { UINFO(8,"VARWRAP "<isIO()) { AstVar* varp = oldvarp->cloneTree(false); @@ -154,8 +154,8 @@ void V3LinkLevel::wrapTopPackages(AstNetlist* netlistp) { // This way all later SCOPE based optimizations can ignore packages AstNodeModule* newmodp = netlistp->modulesp(); if (!newmodp || !newmodp->isTop()) netlistp->v3fatalSrc("No TOP module found to process"); - for (AstNodeModule* modp = netlistp->modulesp(); modp; modp=modp->nextp()->castNodeModule()) { - if (modp->castPackage()) { + for (AstNodeModule* modp = netlistp->modulesp(); modp; modp=VN_CAST(modp->nextp(), NodeModule)) { + if (VN_IS(modp, Package)) { AstCell* cellp = new AstCell(modp->fileline(), // Could add __03a__03a="::" to prevent conflict // with module names/"v" diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index d942a791e..e39983223 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -119,8 +119,8 @@ private: cleanFileline(nodep); nodep->iterateChildren(*this); if (nodep->rangep()) { - if (!nodep->rangep()->msbp()->castConst() - || !nodep->rangep()->lsbp()->castConst()) nodep->v3error("Enum ranges must be integral, per spec"); + if (!VN_IS(nodep->rangep()->msbp(), Const) + || !VN_IS(nodep->rangep()->lsbp(), Const)) nodep->v3error("Enum ranges must be integral, per spec"); int msb = nodep->rangep()->msbConst(); int lsb = nodep->rangep()->lsbConst(); int increment = (msb > lsb) ? -1 : 1; @@ -142,9 +142,9 @@ private: virtual void visit(AstVar* nodep) { cleanFileline(nodep); - if (nodep->subDTypep()->castParseTypeDType()) { + if (VN_IS(nodep->subDTypep(), ParseTypeDType)) { // It's a parameter type. Use a different node type for this. - AstNodeDType* dtypep = nodep->valuep()->castNodeDType(); + AstNodeDType* dtypep = VN_CAST(nodep->valuep(), NodeDType); if (!dtypep) { nodep->v3error("Parameter type's initial value isn't a type: "<prettyName()); nodep->unlinkFrBack(); @@ -204,7 +204,7 @@ private: cleanFileline(nodep); nodep->iterateChildren(*this); if (nodep->attrType() == AstAttrType::DT_PUBLIC) { - AstTypedef* typep = nodep->backp()->castTypedef(); + AstTypedef* typep = VN_CAST(nodep->backp(), Typedef); if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef"); typep->attrPublic(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); @@ -296,13 +296,13 @@ private: // AstVar, AstTypedef, AstNodeFTask are common containers AstNode* backp = nodep->backp(); for (; backp; backp=backp->backp()) { - if (backp->castVar()) break; - else if (backp->castTypedef()) break; - else if (backp->castNodeFTask()) break; + if (VN_IS(backp, Var)) break; + else if (VN_IS(backp, Typedef)) break; + else if (VN_IS(backp, NodeFTask)) break; } if (!backp) nodep->v3fatalSrc("Implicit enum/struct type created under unexpected node type"); AstNodeDType* dtypep = nodep->childDTypep(); dtypep->unlinkFrBack(); - if (backp->castTypedef()) { // A typedef doesn't need us to make yet another level of typedefing + if (VN_IS(backp, Typedef)) { // A typedef doesn't need us to make yet another level of typedefing // For typedefs just remove the AstRefDType level of abstraction nodep->replaceWith(dtypep); nodep->deleteTree(); VL_DANGLING(nodep); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 9f9257380..d64e1b479 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -136,8 +136,8 @@ private: // and any width errors will look a bit odd, but it works. AstNode* sensp = nodep->sensp(); if (sensp - && !sensp->castNodeVarRef() - && !sensp->castConst()) { + && !VN_IS(sensp, NodeVarRef) + && !VN_IS(sensp, Const)) { // Make a new temp wire string newvarname = "__Vsenitemexpr"+cvtToStr(++m_senitemCvtNum); AstVar* newvarp = new AstVar (sensp->fileline(), AstVarType::MODULETEMP, newvarname, @@ -145,11 +145,11 @@ private: // We can't just add under the module, because we may be inside a generate, begin, etc. // We know a SenItem should be under a SenTree/Always etc, we we'll just hunt upwards AstNode* addwherep = nodep; // Add to this element's next - while (addwherep->castSenItem() - || addwherep->castSenTree()) { + while (VN_IS(addwherep, SenItem) + || VN_IS(addwherep, SenTree)) { addwherep = addwherep->backp(); } - if (!addwherep->castAlways()) { // Assertion perhaps? + if (!VN_IS(addwherep, Always)) { // Assertion perhaps? sensp->v3error("Unsupported: Non-single-bit pos/negedge clock statement under some complicated block"); addwherep = m_modp; } @@ -166,26 +166,26 @@ private: bool did=1; while (did) { did=0; - if (AstNodeSel* selp = nodep->sensp()->castNodeSel()) { + if (AstNodeSel* selp = VN_CAST(nodep->sensp(), NodeSel)) { AstNode* fromp = selp->fromp()->unlinkFrBack(); selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp); did=1; } // NodeSel doesn't include AstSel.... - if (AstSel* selp = nodep->sensp()->castSel()) { + if (AstSel* selp = VN_CAST(nodep->sensp(), Sel)) { AstNode* fromp = selp->fromp()->unlinkFrBack(); selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp); did=1; } - if (AstNodePreSel* selp = nodep->sensp()->castNodePreSel()) { + if (AstNodePreSel* selp = VN_CAST(nodep->sensp(), NodePreSel)) { AstNode* fromp = selp->lhsp()->unlinkFrBack(); selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp); did=1; } } } - if (!nodep->sensp()->castNodeVarRef() - && !nodep->sensp()->castEnumItemRef() // V3Const will cleanup + if (!VN_IS(nodep->sensp(), NodeVarRef) + && !VN_IS(nodep->sensp(), EnumItemRef) // V3Const will cleanup && !nodep->isIllegal()) { if (debug()) nodep->dumpTree(cout,"-tree: "); nodep->v3error("Unsupported: Complex statement in sensitivity list"); @@ -203,16 +203,16 @@ private: // So we replicate it in another node // Note that V3Param knows not to replace AstVarRef's under AstAttrOf's AstNode* basefromp = AstArraySel::baseFromp(nodep); - if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { // Maybe varxref - so need to clone + if (AstNodeVarRef* varrefp = VN_CAST(basefromp, NodeVarRef)) { // Maybe varxref - so need to clone nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE, varrefp->cloneTree(false))); - } else if (AstUnlinkedRef* uvxrp = basefromp->castUnlinkedRef()) { // Maybe unlinked - so need to clone + } else if (AstUnlinkedRef* uvxrp = VN_CAST(basefromp, UnlinkedRef)) { // Maybe unlinked - so need to clone nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE, uvxrp->cloneTree(false))); - } else if (AstMemberSel* fromp = basefromp->castMemberSel()) { + } else if (AstMemberSel* fromp = VN_CAST(basefromp, MemberSel)) { nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::MEMBER_BASE, fromp->cloneTree(false))); - } else if (AstEnumItemRef* fromp = basefromp->castEnumItemRef()) { + } else if (AstEnumItemRef* fromp = VN_CAST(basefromp, EnumItemRef)) { nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::ENUM_BASE, fromp->cloneTree(false))); } else { @@ -307,7 +307,7 @@ private: skipCount--; continue; } - AstConst *constp = argp->castConst(); + AstConst *constp = VN_CAST(argp, Const); bool isFromString = (constp) ? constp->num().isFromString() : false; if (isFromString) { int numchars = argp->dtypep()->width()/8; @@ -357,15 +357,15 @@ private: virtual void visit(AstFOpen* nodep) { nodep->iterateChildren(*this); - expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); + expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } virtual void visit(AstFClose* nodep) { nodep->iterateChildren(*this); - expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); + expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } virtual void visit(AstFEof* nodep) { nodep->iterateChildren(*this); - expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); + expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } virtual void visit(AstFScanF* nodep) { nodep->iterateChildren(*this); @@ -380,9 +380,9 @@ private: // Cleanup old-school displays without format arguments if (!nodep->hasFormat()) { if (nodep->text()!="") nodep->v3fatalSrc("Non-format $sformatf should have \"\" format"); - if (nodep->exprsp()->castConst() - && nodep->exprsp()->castConst()->num().isFromString()) { - AstConst* fmtp = nodep->exprsp()->unlinkFrBack()->castConst(); + if (VN_IS(nodep->exprsp(), Const) + && VN_CAST(nodep->exprsp(), Const)->num().isFromString()) { + AstConst* fmtp = VN_CAST(nodep->exprsp()->unlinkFrBack(), Const); nodep->text(fmtp->num().toString()); pushDeletep(fmtp); VL_DANGLING(fmtp); } @@ -390,7 +390,8 @@ private: } string newFormat = expectFormat(nodep, nodep->text(), nodep->exprsp(), false); nodep->text(newFormat); - if ((nodep->backp()->castDisplay() && nodep->backp()->castDisplay()->displayType().needScopeTracking()) + if ((VN_IS(nodep->backp(), Display) + && VN_CAST(nodep->backp(), Display)->displayType().needScopeTracking()) || nodep->formatScopeTracking()) { nodep->scopeNamep(new AstScopeName(nodep->fileline())); } @@ -408,7 +409,7 @@ private: // Massive hack, just tie off all outputs so our analysis can proceed AstVar* varoutp = NULL; for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* varp = stmtp->castVar()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isInput()) { } else if (varp->isOutput()) { if (varoutp) { varp->v3error("Multiple outputs not allowed in udp modules"); } diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index f2253b165..5ad426281 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -141,7 +141,7 @@ private: // We don't need to test for tracing; it would be in the tracefunc if it was needed UINFO(4," ModVar->BlkVar "<user1p()->castCFunc(); + AstCFunc* newfuncp = VN_CAST(nodep->user1p(), CFunc); nodep->unlinkFrBack(); newfuncp->addInitsp(nodep); // Done @@ -175,8 +175,8 @@ private: // This could be more complicated; allow always-set under both branches of a IF. // If so, check for ArrayRef's and such, as they aren't acceptable. for (; nodep; nodep=nodep->nextp()) { - if (nodep->castNodeAssign()) { - if (AstVarRef* varrefp = nodep->castNodeAssign()->lhsp()->castVarRef()) { + if (VN_IS(nodep, NodeAssign)) { + if (AstVarRef* varrefp = VN_CAST(VN_CAST(nodep, NodeAssign)->lhsp(), VarRef)) { if (!varrefp->lvalue()) varrefp->v3fatalSrc("LHS assignment not lvalue"); if (!varrefp->varp()->user4p()) { UINFO(4," FuncAsn "<rhsp()->castVarRef()) { + if (AstVarRef* varrefp = VN_CAST(nodep->rhsp(), VarRef)) { this->visit(varrefp); m_rightClkWidth = varrefp->width(); if (varrefp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) { @@ -298,7 +298,7 @@ private: return; // skip the marking } - AstVarRef* lhsp = nodep->lhsp()->castVarRef(); + const AstVarRef* lhsp = VN_CAST(nodep->lhsp(), VarRef); if (lhsp && (lhsp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_UNKNOWN)) { lhsp->varp()->attrClocker(AstVarAttrClocker::CLOCKER_YES); // mark as clocker m_newClkMarked = true; // enable a further run since new clocker is marked @@ -343,8 +343,8 @@ private: virtual void visit(AstReplicate* nodep) { if (m_inAss) { nodep->iterateChildren(*this); - if (nodep->rhsp()->castConst()) { - m_childClkWidth = m_childClkWidth * nodep->rhsp()->castConst()->toUInt(); + if (VN_IS(nodep->rhsp(), Const)) { + m_childClkWidth = m_childClkWidth * VN_CAST(nodep->rhsp(), Const)->toUInt(); } else { m_childClkWidth = nodep->width(); // can not check in this case. } @@ -389,7 +389,7 @@ private: return level; } virtual void visit(AstNodeAssign* nodep) { - if (AstVarRef* varrefp = nodep->lhsp()->castVarRef() ) + if (const AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef) ) if (varrefp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) { m_clkAss = true; UINFO(6, "node was marked as clocker "<(edgep->top()); } // - if ((fromLVtxp && fromLVtxp->nodep()->castInitial()) - || (toLVtxp && toLVtxp->nodep()->castInitial())) { + if ((fromLVtxp && VN_IS(fromLVtxp->nodep(), Initial)) + || (toLVtxp && VN_IS(toLVtxp->nodep(), Initial))) { // IEEE does not specify ordering between initial blocks, so we can do whatever we want // We especially do not want to evaluate multiple times, so do not mark the edge circular } @@ -1079,7 +1079,7 @@ void OrderVisitor::processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec processInputsInIterate(vvertexp, todoVec); } if (OrderLogicVertex* vvertexp = dynamic_cast(toVertexp)) { - if (vvertexp->nodep()->castNodeAssign()) { + if (VN_IS(vvertexp->nodep(), NodeAssign)) { processInputsInIterate(vvertexp, todoVec); } } @@ -1340,8 +1340,8 @@ bool OrderVisitor::domainsExclusive(const AstSenTree* fromp, // always @(negedge A) // // ... unless you know more about A and B, which sounds hard. - const AstSenItem* fromSenListp = fromp->sensesp()->castSenItem(); - const AstSenItem* toSenListp = top->sensesp()->castSenItem(); + const AstSenItem* fromSenListp = VN_CAST(fromp->sensesp(), SenItem); + const AstSenItem* toSenListp = VN_CAST(top->sensesp(), SenItem); // If clk gating is ever reenabled, we may need to update this to handle // AstSenGate also. if (!fromSenListp) fromp->v3fatalSrc("sensitivity list item is not an AstSenItem"); @@ -1516,11 +1516,11 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d <<" s="<<(void*)(scopep)<<" "<domainp(); AstNode* nodep = lvertexp->nodep(); - AstNodeModule* modp = scopep->user1p()->castNodeModule(); UASSERT(modp,"NULL"); // Stashed by visitor func - if (nodep->castUntilStable()) { + AstNodeModule* modp = VN_CAST(scopep->user1p(), NodeModule); UASSERT(modp,"NULL"); // Stashed by visitor func + if (VN_IS(nodep, UntilStable)) { nodep->v3fatalSrc("Not implemented"); } - else if (nodep->castSenTree()) { + else if (VN_IS(nodep, SenTree)) { // Just ignore sensitivities, we'll deal with them when we move statements that need them } else { // Normal logic diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 6308953af..b4a9a364e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -123,14 +123,14 @@ private: std::vector usedLetter; usedLetter.resize(256); // Pass 1, assign first letter to each gparam's name for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* varp = stmtp->castVar()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isGParam()||varp->isIfaceRef()) { char ch = varp->name()[0]; ch = toupper(ch); if (ch<'A' || ch>'Z') ch='Z'; varp->user4(usedLetter[static_cast(ch)]*256 + ch); usedLetter[static_cast(ch)]++; } - } else if (AstParamTypeDType* typep = stmtp->castParamTypeDType()) { + } else if (AstParamTypeDType* typep = VN_CAST(stmtp, ParamTypeDType)) { char ch = 'T'; typep->user4(usedLetter[static_cast(ch)]*256 + ch); usedLetter[static_cast(ch)]++; @@ -175,7 +175,7 @@ private: void collectPins(CloneMap* clonemapp, AstNodeModule* modp) { // Grab all I/O so we can remap our pins later for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { - if (AstVar* varp = stmtp->castVar()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) { // Cloning saved a pointer to the new node for us, so just follow that link. AstVar* oldvarp = varp->clonep(); @@ -183,7 +183,7 @@ private: clonemapp->insert(make_pair(oldvarp, varp)); } } - else if (AstParamTypeDType* ptp = stmtp->castParamTypeDType()) { + else if (AstParamTypeDType* ptp = VN_CAST(stmtp, ParamTypeDType)) { if (ptp->isGParam()) { AstParamTypeDType* oldptp = ptp->clonep(); clonemapp->insert(make_pair(oldptp, ptp)); @@ -192,18 +192,18 @@ private: } } void relinkPins(CloneMap* clonemapp, AstPin* startpinp) { - for (AstPin* pinp = startpinp; pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = startpinp; pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (pinp->modVarp()) { // Find it in the clone structure //UINFO(8,"Clone find 0x"<modVarp()<find(pinp->modVarp()); UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list"); - pinp->modVarp(cloneiter->second->castVar()); + pinp->modVarp(VN_CAST(cloneiter->second, Var)); } else if (pinp->modPTypep()) { CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep()); UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list"); - pinp->modPTypep(cloneiter->second->castParamTypeDType()); + pinp->modPTypep(VN_CAST(cloneiter->second, ParamTypeDType)); } else { pinp->v3fatalSrc("Not linked?"); @@ -229,8 +229,8 @@ private: for (int nonIf=0; nonIf<2; ++nonIf) { for (CellList::iterator it=m_cellps.begin(); it!=m_cellps.end(); ++it) { AstCell* nodep = *it; - if ((nonIf==0 && nodep->modp()->castIface()) - || (nonIf==1 && !nodep->modp()->castIface())) { + if ((nonIf==0 && VN_IS(nodep->modp(), Iface)) + || (nonIf==1 && !VN_IS(nodep->modp(), Iface))) { visitCell(nodep); } } @@ -253,7 +253,7 @@ private: UINFO(4," MOD-recursive-dead. "<dead(true); // So Dead checks won't count references to it } else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top - || nodep->castPackage()) { // Likewise haven't done wrapTopPackages yet + || VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet // Add request to END of modules left to process m_todoModps.insert(make_pair(nodep->level(), nodep)); visitModules(); @@ -275,7 +275,7 @@ private: if (nodep->isParam()) { if (!nodep->valuep()) { nodep->v3fatalSrc("Parameter without initial value"); } V3Const::constifyParamsEdit(nodep); // The variable, not just the var->init() - if (!nodep->valuep()->castConst()) { // Complex init, like an array + if (!VN_IS(nodep->valuep(), Const)) { // Complex init, like an array // Make a new INITIAL to set the value. // This allows the normal array/struct handling code to properly initialize the parameter nodep->addNext(new AstInitial(nodep->fileline(), @@ -293,11 +293,11 @@ private: bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) { for (; candp; candp = candp->nextp()) { if (nodep->name() == candp->name()) { - if (AstVar* varp = candp->castVar()) { + if (AstVar* varp = VN_CAST(candp, Var)) { UINFO(9,"Found interface parameter: "<varp(varp); return true; - } else if (AstPin* pinp = candp->castPin()) { + } else if (AstPin* pinp = VN_CAST(candp, Pin)) { UINFO(9,"Found interface parameter: "<exprp()) pinp->v3fatalSrc("Interface parameter pin missing expression"); nodep->replaceWith(pinp->exprp()->cloneTree(false)); VL_DANGLING(nodep); @@ -313,15 +313,15 @@ private: if (!dotted.empty() && nodep->varp() && nodep->varp()->isParam()) { AstNode* backp = nodep; while ((backp = backp->backp())) { - if (backp->castNodeModule()) { + if (VN_IS(backp, NodeModule)) { UINFO(9,"Hit module boundary, done looking for interface"<castVar() - && backp->castVar()->isIfaceRef() - && backp->castVar()->childDTypep() - && backp->castVar()->childDTypep()->castIfaceRefDType()) { - AstIfaceRefDType* ifacerefp = backp->castVar()->childDTypep()->castIfaceRefDType(); + if (VN_IS(backp, Var) + && VN_CAST(backp, Var)->isIfaceRef() + && VN_CAST(backp, Var)->childDTypep() + && VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType)) { + AstIfaceRefDType* ifacerefp = VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType); // Interfaces passed in on the port map have ifaces if (AstIface* ifacep = ifacerefp->ifacep()) { if (dotted == backp->name()) { @@ -347,8 +347,8 @@ private: } virtual void visit(AstUnlinkedRef* nodep) { - AstVarXRef* varxrefp = nodep->op1p()->castVarXRef(); - AstNodeFTaskRef* taskrefp = nodep->op1p()->castNodeFTaskRef(); + AstVarXRef* varxrefp = VN_CAST(nodep->op1p(), VarXRef); + AstNodeFTaskRef* taskrefp = VN_CAST(nodep->op1p(), NodeFTaskRef); if (varxrefp) { m_unlinkedTxt = varxrefp->dotted(); } else if (taskrefp) { @@ -369,7 +369,7 @@ private: } virtual void visit(AstCellArrayRef* nodep) { V3Const::constifyParamsEdit(nodep->selp()); - if (AstConst* constp = nodep->selp()->castConst()) { + if (const AstConst* constp = VN_CAST(nodep->selp(), Const)) { string index = AstNode::encodeNumber(constp->toSInt()); string replacestr = nodep->name() + "__BRA__??__KET__"; size_t pos = m_unlinkedTxt.find(replacestr); @@ -408,7 +408,7 @@ private: V3Width::widthGenerateParamsEdit(nodep); // Param typed widthing will // NOT recurse the body. V3Const::constifyGenerateParamsEdit(nodep->condp()); // condp may change - if (AstConst* constp = nodep->condp()->castConst()) { + if (const AstConst* constp = VN_CAST(nodep->condp(), Const)) { AstNode* keepp = (constp->isZero() ? nodep->elsesp() : nodep->ifsp()); @@ -431,7 +431,7 @@ private: //! move to more generic constant expressions, such code will be needed here. virtual void visit(AstBegin* nodep) { if (nodep->genforp()) { - AstGenFor* forp = nodep->genforp()->castGenFor(); + AstGenFor* forp = VN_CAST(nodep->genforp(), GenFor); if (!forp) nodep->v3fatalSrc("Non-GENFOR under generate-for BEGIN"); // We should have a GENFOR under here. We will be replacing the begin, // so process here rather than at the generate to avoid iteration problems @@ -468,9 +468,9 @@ private: V3Width::widthParamsEdit(nodep); // Param typed widthing will NOT recurse the body, // don't trigger errors yet. V3Const::constifyParamsEdit(nodep->exprp()); // exprp may change - AstConst* exprp = nodep->exprp()->castConst(); + AstConst* exprp = VN_CAST(nodep->exprp(), Const); // Constify - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { for (AstNode* ep = itemp->condsp(); ep; ) { AstNode* nextp = ep->nextp(); //May edit list ep->iterateAndNext(*this); @@ -479,10 +479,10 @@ private: } } // Item match - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->isDefault()) { for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) { - if (AstConst* ccondp = ep->castConst()) { + if (const AstConst* ccondp = VN_CAST(ep, Const)) { V3Number match (nodep->fileline(), 1); match.opEq(ccondp->num(), exprp->num()); if (!keepp && match.isNeqZero()) { @@ -495,7 +495,7 @@ private: } } // Else default match - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (itemp->isDefault()) { if (!keepp) keepp=itemp->bodysp(); } @@ -550,20 +550,20 @@ void ParamVisitor::visitCell(AstCell* nodep) { if (nodep->recursive()) any_overrides = true; // Must always clone __Vrcm (recursive modules) longname += "_"; if (debug()>8) nodep->paramsp()->dumpTreeAndNext(cout,"-cellparams:\t"); - for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (!pinp->exprp()) continue; // No-connect if (AstVar* modvarp = pinp->modVarp()) { if (!modvarp->isGParam()) { pinp->v3error("Attempted parameter setting of non-parameter: Param "<prettyName()<<" of "<prettyName()); - } else if (pinp->exprp()->castInitArray() - && modvarp->subDTypep()->castUnpackArrayDType()) { + } else if (VN_IS(pinp->exprp(), InitArray) + && VN_IS(modvarp->subDTypep(), UnpackArrayDType)) { // Array assigned to array AstNode* exprp = pinp->exprp(); longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); any_overrides = true; } else { - AstConst* exprp = pinp->exprp()->castConst(); - AstConst* origp = modvarp->valuep()->castConst(); + AstConst* exprp = VN_CAST(pinp->exprp(), Const); + AstConst* origp = VN_CAST(modvarp->valuep(), Const); if (!exprp) { //if (debug()) pinp->dumpTree(cout,"error:"); pinp->v3error("Can't convert defparam value to constant: Param "<name()<<" of "<prettyName()); @@ -583,7 +583,7 @@ void ParamVisitor::visitCell(AstCell* nodep) { } } } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { - AstNodeDType* exprp = pinp->exprp()->castNodeDType(); + AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); AstNodeDType* origp = modvarp->subDTypep(); if (!exprp) { pinp->v3error("Parameter type pin value isn't a type: Param "<prettyName()<<" of "<prettyName()); @@ -605,39 +605,39 @@ void ParamVisitor::visitCell(AstCell* nodep) { } } IfaceRefRefs ifaceRefRefs; - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { AstVar* modvarp = pinp->modVarp(); if (modvarp->isIfaceRef()) { - AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType(); - if (!portIrefp && modvarp->subDTypep()->castUnpackArrayDType()) { - portIrefp = modvarp->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType(); + AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType); + if (!portIrefp && VN_IS(modvarp->subDTypep(), UnpackArrayDType)) { + portIrefp = VN_CAST(VN_CAST(modvarp->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); } AstIfaceRefDType* pinIrefp = NULL; AstNode* exprp = pinp->exprp(); if (exprp - && exprp->castVarRef() - && exprp->castVarRef()->varp() - && exprp->castVarRef()->varp()->subDTypep() - && exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType()) - pinIrefp = exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType(); + && VN_IS(exprp, VarRef) + && VN_CAST(exprp, VarRef)->varp() + && VN_CAST(exprp, VarRef)->varp()->subDTypep() + && VN_IS(VN_CAST(exprp, VarRef)->varp()->subDTypep(), IfaceRefDType)) + pinIrefp = VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), IfaceRefDType); else if (exprp && exprp->op1p() - && exprp->op1p()->castVarRef() - && exprp->op1p()->castVarRef()->varp() - && exprp->op1p()->castVarRef()->varp()->subDTypep() - && exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType() - && exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep() - && exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType()) - pinIrefp = exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType(); + && VN_IS(exprp->op1p(), VarRef) + && VN_CAST(exprp->op1p(), VarRef)->varp() + && VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep() + && VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType) + && VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep() + && VN_CAST(VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) + pinIrefp = VN_CAST(VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); else if (exprp - && exprp->castVarRef() - && exprp->castVarRef()->varp() - && exprp->castVarRef()->varp()->subDTypep() - && exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType() - && exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep() - && exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType()) - pinIrefp = exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType(); + && VN_IS(exprp, VarRef) + && VN_CAST(exprp, VarRef)->varp() + && VN_CAST(exprp, VarRef)->varp()->subDTypep() + && VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType) + && VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep() + && VN_CAST(VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) + pinIrefp = VN_CAST(VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); UINFO(9," portIfaceRef "<nextp()->castNodeModule() - && insertp->nextp()->castNodeModule()->level() < cellmodp->level()) { - insertp = insertp->nextp()->castNodeModule(); + while (VN_IS(insertp->nextp(), NodeModule) + && VN_CAST(insertp->nextp(), NodeModule)->level() < cellmodp->level()) { + insertp = VN_CAST(insertp->nextp(), NodeModule); } insertp->addNextHere(cellmodp); @@ -730,7 +730,7 @@ void ParamVisitor::visitCell(AstCell* nodep) { // Assign parameters to the constants specified // DOES clone() so must be finished with module clonep() before here - for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { if (pinp->exprp()) { if (AstVar* modvarp = pinp->modVarp()) { AstNode* newp = pinp->exprp(); // Const or InitArray @@ -740,7 +740,7 @@ void ParamVisitor::visitCell(AstCell* nodep) { modvarp->valuep(newp->cloneTree(false)); } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { - AstNodeDType* dtypep = pinp->exprp()->castNodeDType(); + AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); if (!dtypep) pinp->v3fatalSrc("unlinked param dtype"); if (modptp->childDTypep()) pushDeletep(modptp->childDTypep()->unlinkFrBack()); // Set this parameter to value requested by cell diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 0fa2a154a..aaea9b51c 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -123,9 +123,9 @@ private: } bool assignNoTemp(AstNodeAssign* nodep) { - return (nodep->lhsp()->castVarRef() + return (VN_IS(nodep->lhsp(), VarRef) && !AstVar::scVarRecurse(nodep->lhsp()) - && nodep->rhsp()->castConst()); + && VN_IS(nodep->rhsp(), Const)); } void checkNode(AstNode* nodep) { // Consider adding a temp for this expression. @@ -141,14 +141,14 @@ private: if (nodep->isWide()) { if (m_assignLhs) { } else if (nodep->firstAbovep() - && nodep->firstAbovep()->castNodeAssign() - && assignNoTemp(nodep->firstAbovep()->castNodeAssign())) { + && VN_IS(nodep->firstAbovep(), NodeAssign) + && assignNoTemp(VN_CAST(nodep->firstAbovep(), NodeAssign))) { // Not much point if it's just a direct assignment to a constant - } else if (nodep->backp()->castSel() - && nodep->backp()->castSel()->widthp() == nodep) { + } else if (VN_IS(nodep->backp(), Sel) + && VN_CAST(nodep->backp(), Sel)->widthp() == nodep) { // AstSel::width must remain a constant } else if (nodep->firstAbovep() - && nodep->firstAbovep()->castArraySel()) { + && VN_IS(nodep->firstAbovep(), ArraySel)) { // ArraySel's are pointer refs, ignore } else { UINFO(4,"Cre Temp: "< 32/64 bits in C++ will wrap-around and generate non-0s if (!nodep->user2SetOnce()) { UINFO(4," ShiftFix "<rhsp()->castConst(); + const AstConst* shiftp = VN_CAST(nodep->rhsp(), Const); if (shiftp && shiftp->num().mostSetBitP1() > 32) { shiftp->v3error("Unsupported: Shifting of by over 32-bit number isn't supported." <<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n"); @@ -359,8 +359,8 @@ private: virtual void visit(AstNodeCond* nodep) { nodep->iterateChildren(*this); if (nodep->expr1p()->isWide() - && !nodep->condp()->castConst() - && !nodep->condp()->castVarRef()) { + && !VN_IS(nodep->condp(), Const) + && !VN_IS(nodep->condp(), VarRef)) { // We're going to need the expression several times in the expanded code, // so might as well make it a common expression createDeepTemp(nodep->condp(), false); @@ -375,10 +375,10 @@ private: m_stmtp = NULL; if (v3Global.opt.autoflush()) { AstNode* searchp = nodep->nextp(); - while (searchp && searchp->castComment()) searchp = searchp->nextp(); + while (searchp && VN_IS(searchp, Comment)) searchp = searchp->nextp(); if (searchp - && searchp->castDisplay() - && nodep->filep()->sameGateTree(searchp->castDisplay()->filep())) { + && VN_IS(searchp, Display) + && nodep->filep()->sameGateTree(VN_CAST(searchp, Display)->filep())) { // There's another display next; we can just wait to flush } else { UINFO(4,"Autoflush "<exprsp(); expp; expp = expp->nextp()) { if (expp->dtypep()->basicp()->isString() - && !expp->castVarRef()) { + && !VN_IS(expp, VarRef)) { createDeepTemp(expp, true); } } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 1715af7be..1b0b28c5d 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -110,11 +110,11 @@ private: m_scopep = new AstScope((m_aboveCellp?(AstNode*)m_aboveCellp:(AstNode*)nodep)->fileline(), nodep, scopename, m_aboveScopep, m_aboveCellp); - if (nodep->castPackage()) m_packageScopes.insert(make_pair(nodep->castPackage(), m_scopep)); + if (VN_IS(nodep, Package)) m_packageScopes.insert(make_pair(VN_CAST(nodep, Package), m_scopep)); // Now for each child cell, iterate the module this cell points to for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp=cellnextp->nextp()) { - if (AstCell* cellp = cellnextp->castCell()) { + if (AstCell* cellp = VN_CAST(cellnextp, Cell)) { AstScope* oldScopep = m_scopep; AstCell* oldAbCellp = m_aboveCellp; AstScope* oldAbScopep = m_aboveScopep; @@ -381,7 +381,7 @@ private: if (nodep->packagep()) { // Point to the clone if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked"); - AstNodeFTask* newp = nodep->taskp()->user2p()->castNodeFTask(); + AstNodeFTask* newp = VN_CAST(nodep->taskp()->user2p(), NodeFTask); if (!newp) nodep->v3fatalSrc("No clone for package function"); nodep->taskp(newp); UINFO(9," New pkg-taskref "<castRefDType()) { + if (AstRefDType* refdtypep = VN_CAST(dtypep, RefDType)) { dtypep = refdtypep->skipRefp(); } - if (AstStructDType* stp = dtypep->castStructDType()) { + if (AstStructDType* stp = VN_CAST(dtypep, StructDType)) { if (stp->packed()) { std::ostringstream out; out<<"'{"; - for (AstMemberDType* itemp = stp->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { + for (AstMemberDType* itemp = stp->membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { int width = itemp->width(); int lsb = itemp->lsb(); int msb = lsb + width - 1; @@ -143,7 +143,7 @@ private: out<<"}"; return out.str(); } - } else if (AstPackArrayDType * arrayp = dtypep->castPackArrayDType()) { + } else if (AstPackArrayDType * arrayp = VN_CAST(dtypep, PackArrayDType)) { if (AstNodeDType * childTypep = arrayp->subDTypep()) { std::ostringstream out; out<<"["; @@ -314,7 +314,7 @@ private: } void assignOutNumber(AstNodeAssign* nodep, AstNode* vscp, const V3Number* nump) { // Don't do setNumber, as value isn't yet visible to following statements - if (nodep->castAssignDly()) { + if (VN_IS(nodep, AssignDly)) { // Don't do setNumber, as value isn't yet visible to following statements newOutNumber(vscp)->opAssign(*nump); } else { @@ -341,9 +341,9 @@ private: // We can't have non-delayed assignments with same value on LHS and RHS // as we don't figure out variable ordering. // Delayed is OK though, as we'll decode the next state separately. - if (!nodep->varp()->dtypeSkipRefp()->castBasicDType() - && !nodep->varp()->dtypeSkipRefp()->castPackArrayDType() - && !nodep->varp()->dtypeSkipRefp()->castStructDType()) + if (!VN_IS(nodep->varp()->dtypeSkipRefp(), BasicDType) + && !VN_IS(nodep->varp()->dtypeSkipRefp(), PackArrayDType) + && !VN_IS(nodep->varp()->dtypeSkipRefp(), StructDType)) clearOptimizable(nodep,"Array references/not basic"); if (nodep->lvalue()) { if (m_inDlyAssign) { @@ -576,11 +576,11 @@ private: // Recurse down to find final variable being set (outVarrefp), with value to write on nodep->rhsp() checkNodeInfo(selp); selp->lsbp()->iterateAndNext(*this); // Bit index - if (AstVarRef* varrefp = selp->fromp()->castVarRef()) { + if (AstVarRef* varrefp = VN_CAST(selp->fromp(), VarRef)) { outVarrefpRef = varrefp; lsbRef = *fetchNumber(selp->lsbp()); return; // And presumably still optimizable() - } else if (AstSel* subselp = selp->lhsp()->castSel()) { + } else if (AstSel* subselp = VN_CAST(selp->lhsp(), Sel)) { V3Number sublsb = V3Number(nodep->fileline()); handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb/*ref*/, depth+1); if (optimizable()) { @@ -595,7 +595,7 @@ private: virtual void visit(AstNodeAssign* nodep) { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate - if (nodep->castAssignDly()) { + if (VN_IS(nodep, AssignDly)) { if (m_anyAssignComb) clearOptimizable(nodep, "Mix of dly/non-dly assigns"); m_anyAssignDly = true; m_inDlyAssign = true; @@ -604,11 +604,11 @@ private: m_anyAssignComb = true; } - if (AstSel* selp = nodep->lhsp()->castSel()) { + if (AstSel* selp = VN_CAST(nodep->lhsp(), Sel)) { if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; } handleAssignSel(nodep, selp); } - else if (!nodep->lhsp()->castVarRef()) { + else if (!VN_IS(nodep->lhsp(), VarRef)) { clearOptimizable(nodep, "LHS isn't simple variable"); } else if (m_checkOnly) { @@ -617,7 +617,7 @@ private: else if (optimizable()) { nodep->rhsp()->iterateAndNext(*this); if (optimizable()) { - AstNode* vscp = varOrScope(nodep->lhsp()->castVarRef()); + AstNode* vscp = varOrScope(VN_CAST(nodep->lhsp(), VarRef)); assignOutNumber(nodep, vscp, fetchNumber(nodep->rhsp())); } } @@ -636,7 +636,7 @@ private: } else if (optimizable()) { nodep->exprp()->iterateAndNext(*this); bool hit = false; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->isDefault()) { for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) { if (hit) break; @@ -653,7 +653,7 @@ private: } } // Else default match - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { if (hit) break; if (!hit && itemp->isDefault()) { itemp->bodysp()->iterateAndNext(*this); @@ -764,9 +764,9 @@ private: if (!optimizable()) return; // Accelerate UINFO(5," FUNCREF "<taskp()->castNodeFTask(); if (!funcp) nodep->v3fatalSrc("Not linked"); + AstNodeFTask* funcp = VN_CAST(nodep->taskp(), NodeFTask); if (!funcp) nodep->v3fatalSrc("Not linked"); if (m_params) { V3Width::widthParamsEdit(funcp); } VL_DANGLING(funcp); // Make sure we've sized the function - funcp = nodep->taskp()->castNodeFTask(); if (!funcp) nodep->v3fatalSrc("Not linked"); + funcp = VN_CAST(nodep->taskp(), NodeFTask); if (!funcp) nodep->v3fatalSrc("Not linked"); // Apply function call values to function V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); // Must do this in two steps, eval all params, then apply them diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index f070a2e87..357e77341 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -72,7 +72,7 @@ class SliceVisitor : public AstNVisitor { AstNode* cloneAndSel(AstNode* nodep, int elements, int offset) { // Insert an ArraySel, except for a few special cases - AstUnpackArrayDType* arrayp = nodep->dtypep()->skipRefp()->castUnpackArrayDType(); + AstUnpackArrayDType* arrayp = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType); if (!arrayp) { // V3Width should have complained, but... if (!m_assignError) nodep->v3error(nodep->prettyTypeName()<<" is not an unpacked array, but is in an unpacked array context"); m_assignError = true; @@ -85,7 +85,7 @@ class SliceVisitor : public AstNVisitor { elements = 1; offset = 0; } AstNode* newp; - if (AstInitArray* initp = nodep->castInitArray()) { + if (AstInitArray* initp = VN_CAST(nodep, InitArray)) { UINFO(9," cloneInitArray("<initsp(); int leOffset = !arrayp->rangep()->littleEndian() ? arrayp->rangep()->elementsConst()-1-offset : offset; @@ -98,21 +98,21 @@ class SliceVisitor : public AstNVisitor { } newp = itemp->cloneTree(false); } - else if (AstNodeCond* snodep = nodep->castNodeCond()) { + else if (AstNodeCond* snodep = VN_CAST(nodep, NodeCond)) { UINFO(9," cloneCond("<cloneType(snodep->condp()->cloneTree(false), cloneAndSel(snodep->expr1p(), elements, offset), cloneAndSel(snodep->expr2p(), elements, offset)); } - else if (AstSliceSel* snodep = nodep->castSliceSel()) { + else if (AstSliceSel* snodep = VN_CAST(nodep, SliceSel)) { UINFO(9," cloneSliceSel("<declRange().lo() + (!snodep->declRange().littleEndian() ? snodep->declRange().elements()-1-offset : offset)); newp = new AstArraySel(nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset); } - else if (nodep->castArraySel() - || nodep->castNodeVarRef() - || nodep->castNodeSel()) { + else if (VN_IS(nodep, ArraySel) + || VN_IS(nodep, NodeVarRef) + || VN_IS(nodep, NodeSel)) { UINFO(9," cloneSel("<rangep()->littleEndian() ? arrayp->rangep()->elementsConst()-1-offset : offset; newp = new AstArraySel(nodep->fileline(), nodep->cloneTree(false), leOffset); @@ -128,12 +128,12 @@ class SliceVisitor : public AstNVisitor { virtual void visit(AstNodeAssign* nodep) { // Called recursively on newly created assignments if (!nodep->user1() - && !nodep->castAssignAlias()) { + && !VN_IS(nodep, AssignAlias)) { nodep->user1(true); m_assignError = false; if (debug()>=9) { cout<dumpTree(cout," Deslice-In: "); } AstNodeDType* dtp = nodep->lhsp()->dtypep()->skipRefp(); - if (AstUnpackArrayDType* arrayp = dtp->castUnpackArrayDType()) { + if (AstUnpackArrayDType* arrayp = VN_CAST(dtp, UnpackArrayDType)) { // Left and right could have different msb/lsbs/endianness, but #elements is common // and all variables are realigned to start at zero // Assign of a little endian'ed slice to a big endian one must reverse the elements @@ -170,17 +170,19 @@ class SliceVisitor : public AstNVisitor { // If it's an unpacked array, blow it up into comparing each element AstNodeDType* fromDtp = nodep->lhsp()->dtypep()->skipRefp(); UINFO(9, " Bi-Eq/Neq expansion "<castUnpackArrayDType()) { + if (AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { AstNodeBiop* logp = NULL; for (int index = 0; index < adtypep->rangep()->elementsConst(); ++index) { // EQ(a,b) -> LOGAND(EQ(ARRAYSEL(a,0), ARRAYSEL(b,0)), ...[1]) - AstNodeBiop* clonep = nodep->cloneType - (new AstArraySel(nodep->fileline(), - nodep->lhsp()->cloneTree(false), - index), - new AstArraySel(nodep->fileline(), - nodep->rhsp()->cloneTree(false), - index))->castNodeBiop(); + AstNodeBiop* clonep + = VN_CAST(nodep->cloneType + (new AstArraySel(nodep->fileline(), + nodep->lhsp()->cloneTree(false), + index), + new AstArraySel(nodep->fileline(), + nodep->rhsp()->cloneTree(false), + index)), + NodeBiop); if (!logp) logp = clonep; else { switch (nodep->type()) { diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 98d0de79e..a5bf32d6d 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -365,7 +365,7 @@ private: void reorderBlock(AstNode* nodep) { // Reorder statements in the completed graph - AstAlways* splitAlwaysp = nodep->backp()->castAlways(); + AstAlways* splitAlwaysp = VN_CAST(nodep->backp(), Always); // Map the rank numbers into nodes they associate with typedef std::multimap RankNodeMap; diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 0c26c7b7f..19cfcd356 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -101,7 +101,7 @@ private: nodep->iterateChildrenConst(*this); if (m_counting && nodep->dtypep()) { if (nodep->isUsedClock()) ++m_statVarClock; - if (nodep->dtypeSkipRefp()->castUnpackArrayDType()) ++m_statVarArray; + if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) ++m_statVarArray; else m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes(); if (int(m_statVarWidths.size()) <= nodep->width()) { m_statVarWidths.resize(nodep->width()+5); @@ -123,7 +123,7 @@ private: allNodes(nodep); nodep->iterateChildrenConst(*this); if (m_counting) { - if (nodep->varp()->dtypeSkipRefp()->castBasicDType()) { + if (VN_IS(nodep->varp()->dtypeSkipRefp(), BasicDType)) { m_statVarScpBytes += nodep->varp()->dtypeSkipRefp()->widthTotalBytes(); } } diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index df2fa37e5..f0ae9cb7a 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -268,7 +268,7 @@ private: m_assignStep++; nodep->rhsp()->iterateAndNext(*this); bool hit=false; - if (AstVarRef* varrefp = nodep->lhsp()->castVarRef()) { + if (AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef)) { if (isSubstVar(varrefp->varp())) { SubstVarEntry* entryp = getEntryp(varrefp); hit = true; @@ -281,11 +281,11 @@ private: } } } - else if (AstWordSel* wordp = nodep->lhsp()->castWordSel()) { - if (AstVarRef* varrefp = wordp->lhsp()->castVarRef()) { - if (wordp->rhsp()->castConst() + else if (AstWordSel* wordp = VN_CAST(nodep->lhsp(), WordSel)) { + if (AstVarRef* varrefp = VN_CAST(wordp->lhsp(), VarRef)) { + if (VN_IS(wordp->rhsp(), Const) && isSubstVar(varrefp->varp())) { - int word = wordp->rhsp()->castConst()->toUInt(); + int word = VN_CAST(wordp->rhsp(), Const)->toUInt(); SubstVarEntry* entryp = getEntryp(varrefp); hit = true; if (m_ops > SUBST_MAX_OPS_SUBST) { @@ -315,8 +315,8 @@ private: } virtual void visit(AstWordSel* nodep) { nodep->rhsp()->accept(*this); - AstVarRef* varrefp = nodep->lhsp()->castVarRef(); - AstConst* constp = nodep->rhsp()->castConst(); + AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); + AstConst* constp = VN_CAST(nodep->rhsp(), Const); if (varrefp && isSubstVar(varrefp->varp()) && !varrefp->lvalue() && constp) { diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 670a7df5b..b93212afb 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -210,7 +210,7 @@ public: for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) { const string& name = it->first; VSymEnt* subSrcp = it->second; - AstVar* varp = subSrcp->nodep()->castVar(); + const AstVar* varp = VN_CAST(subSrcp->nodep(), Var); if (!onlyUnmodportable || (varp && varp->varType() == AstVarType::GPARAM)) { VSymEnt* subSymp = new VSymEnt(graphp, subSrcp); reinsert(name, subSymp); @@ -224,8 +224,8 @@ public: string scopes; for (IdNameMap::iterator it = m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) { AstNode* nodep = it->second->nodep(); - if (nodep->castCell() - || (nodep->castModule() && nodep->castModule()->isTop())) { + if (VN_IS(nodep, Cell) + || (VN_IS(nodep, Module) && VN_CAST(nodep, Module)->isTop())) { if (scopes != "") scopes += ", "; scopes += AstNode::prettyName(it->first); } diff --git a/src/V3Table.cpp b/src/V3Table.cpp index e9b99aec5..b51e5b845 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -217,7 +217,7 @@ private: createOutputAssigns(nodep, stmtsp, indexVscp, chgVscp); // Link it in. - if (AstAlways* nodeap = nodep->castAlways()) { + if (AstAlways* nodeap = VN_CAST(nodep, Always)) { // Keep sensitivity list, but delete all else nodeap->bodysp()->unlinkFrBackWithNext()->deleteTree(); nodeap->addStmtp(stmtsp); @@ -328,7 +328,7 @@ private: setp = new AstConst (outnump->fileline(), *outnump); } // Note InitArray requires us to have the values in inValue order - m_tableVarps[outnum]->varp()->valuep()->castInitArray()->addValuep(setp); + VN_CAST(m_tableVarps[outnum]->varp()->valuep(), InitArray)->addValuep(setp); outnum++; } @@ -336,7 +336,7 @@ private: if (inValue != inValueNextInitArray++) nodep->v3fatalSrc("InitArray requires us to have the values in inValue order"); AstNode* setp = new AstConst (nodep->fileline(), outputChgMask); - chgVscp->varp()->valuep()->castInitArray()->addValuep(setp); + VN_CAST(chgVscp->varp()->valuep(), InitArray)->addValuep(setp); } } // each value } @@ -351,8 +351,8 @@ private: if (var1p->width() == var2p->width() && (var1p->dtypep()->arrayUnpackedElements() == var2p->dtypep()->arrayUnpackedElements())) { - AstNode* init1p = var1p->valuep()->castInitArray(); - AstNode* init2p = var2p->valuep()->castInitArray(); + const AstNode* init1p = VN_CAST(var1p->valuep(), InitArray); + const AstNode* init2p = VN_CAST(var2p->valuep(), InitArray); if (init1p->sameGateTree(init2p)) { UINFO(8," Duplicate table var "<varscope mappings, for later cleanup for (AstNode* stmtp = nodep->varsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVarScope* vscp = stmtp->castVarScope()) { + if (AstVarScope* vscp = VN_CAST(stmtp, VarScope)) { if (vscp->varp()->isFuncLocal()) { UINFO(9," funcvsc "<varp()), vscp)); @@ -175,7 +175,7 @@ private: } // Likewise, all FTask->scope mappings for (AstNode* stmtp = nodep->blocksp(); stmtp; stmtp=stmtp->nextp()) { - if (AstNodeFTask* taskp = stmtp->castNodeFTask()) { + if (AstNodeFTask* taskp = VN_CAST(stmtp, NodeFTask)) { taskp->user3p(nodep); } } @@ -263,7 +263,7 @@ private: // Similar code in V3Inline if (nodep->varp()->user2p()) { // It's being converted to a alias. UINFO(9, " relinkVar "<<(void*)nodep->varp()->user2p()<<" "<varp()->user2p()->castVarScope(); + AstVarScope* newvscp = VN_CAST(nodep->varp()->user2p(), VarScope); if (!newvscp) nodep->v3fatalSrc("not linked"); nodep->varScopep(newvscp); nodep->varp(nodep->varScopep()->varp()); @@ -382,14 +382,14 @@ private: pinp->unlinkFrBack(); // Relinked to assignment below argp->unlinkFrBack()->deleteTree(); // Args no longer needed // - if ((portp->isInout()||portp->isOutput()) && pinp->castConst()) { + if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) { pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName()); } else if (portp->isInout()) { // Correct lvalue; see comments below V3LinkLValue::linkLValueSet(pinp); - if (AstVarRef* varrefp = pinp->castVarRef()) { + if (AstVarRef* varrefp = VN_CAST(pinp, VarRef)) { // Connect to this exact variable AstVarScope* localVscp = varrefp->varScopep(); if (!localVscp) varrefp->v3fatalSrc("Null var scope"); portp->user2p(localVscp); @@ -439,7 +439,7 @@ private: AstNode* nextstmtp; for (AstNode* stmtp = beginp; stmtp; stmtp=nextstmtp) { nextstmtp = stmtp->nextp(); - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { // Any I/O variables that fell out of above loop were already linked if (!portp->user2p()) { // Move it to a new localized variable @@ -487,14 +487,14 @@ private: } else { UINFO(9, " Port "<isInout()||portp->isOutput()) && pinp->castConst()) { + if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) { pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName()); } else if (portp->isInout()) { // Correct lvalue; see comments below V3LinkLValue::linkLValueSet(pinp); - if (pinp->castVarRef()) { + if (VN_IS(pinp, VarRef)) { // Connect to this exact variable } else { pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable"); @@ -541,7 +541,7 @@ private: for (AstNode* pinp = refp->pinsp(); pinp; pinp=nextpinp) { nextpinp = pinp->nextp(); // Move pin to the CCall, removing all Arg's - AstNode* exprp = pinp->castArg()->exprp(); + AstNode* exprp = VN_CAST(pinp, Arg)->exprp(); exprp->unlinkFrBack(); ccallp->addArgsp(exprp); } @@ -564,7 +564,7 @@ private: dpiproto += " "+nodep->cname()+" ("; string args; for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (const AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn() && portp!=rtnvarp) { if (args != "") { args+= ", "; dpiproto+= ", "; } args += portp->name(); // Leftover so ,'s look nice @@ -716,7 +716,7 @@ private: args += "("+v3Global.opt.prefix()+"__Syms*)(__Vscopep->symsp())"; // Upcast w/o overhead AstNode* argnodesp = NULL; for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn() && portp != rtnvarp) { // No createDpiTemp; we make a real internal variable instead // SAME CODE BELOW @@ -757,7 +757,7 @@ private: // Convert output/inout arguments back to internal type for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && portp->isOutput() && !portp->isFuncReturn()) { dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt","")); } @@ -817,7 +817,7 @@ private: void makePortList(AstNodeFTask* nodep, AstVar* rtnvarp, AstCFunc* dpip) { // Copy nodep's list of function I/O to the new dpip c function for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { // Move it to new function AstVar* newPortp = portp->cloneTree(false); @@ -838,8 +838,8 @@ private: // Convert input/inout arguments to DPI types string args; for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { - AstVarScope* portvscp = portp->user2p()->castVarScope(); // Remembered when we created it earlier + if (AstVar* portp = VN_CAST(stmtp, Var)) { + AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier if (portp->isIO() && !portp->isFuncReturn() && portvscp != rtnvscp && portp->name() != "__Vscopep" // Passed to dpiContext, not callee && portp->name() != "__Vfilenamep" @@ -901,10 +901,10 @@ private: // Convert output/inout arguments back to internal type for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn()) && !portp->isDpiOpenArray()) { - AstVarScope* portvscp = portp->user2p()->castVarScope(); // Remembered when we created it earlier + AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true)); } } @@ -918,7 +918,7 @@ private: AstNode::user2ClearTree(); AstVar* rtnvarp = NULL; if (nodep->isFunction()) { - AstVar* portp = nodep->fvarp()->castVar(); + AstVar* portp = VN_CAST(nodep->fvarp(), Var); if (!portp) nodep->v3fatalSrc("function without function output variable"); if (!portp->isFuncReturn()) nodep->v3error("Not marked as function return var"); if (portp->isWide()) nodep->v3error("Unsupported: Public functions with return > 64 bits wide. (Make it a output instead.)"); @@ -1021,7 +1021,7 @@ private: // Create list of arguments and move to function for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp=nextp) { nextp = stmtp->nextp(); - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { // Move it to new function portp->unlinkFrBack(); @@ -1096,7 +1096,7 @@ private: } else if (m_insMode == IM_WHILE_PRECOND) { UINFO(5," IM_While_Precond "<castWhile(); + AstWhile* whilep = VN_CAST(m_insStmtp, While); if (!whilep) nodep->v3fatalSrc("Insert should be under WHILE"); whilep->addPrecondsp(newp); } @@ -1131,13 +1131,13 @@ private: UINFO(4," FTask REF "<=9) { nodep->dumpTree(cout,"-inlfunc:"); } if (!m_scopep) nodep->v3fatalSrc("func ref not under scope"); - string namePrefix = ((nodep->castFuncRef()?"__Vfunc_":"__Vtask_") + string namePrefix = ((VN_IS(nodep, FuncRef) ? "__Vfunc_":"__Vtask_") +nodep->taskp()->shortName()+"__"+cvtToStr(m_modNCalls++)); // Create output variable AstVarScope* outvscp = NULL; if (nodep->taskp()->isFunction()) { // Not that it's a FUNCREF, but that we're calling a function (perhaps as a task) - outvscp = createVarScope (nodep->taskp()->fvarp()->castVar(), + outvscp = createVarScope (VN_CAST(nodep->taskp()->fvarp(), Var), namePrefix+"__Vfuncout"); } // Create cloned statements @@ -1149,7 +1149,7 @@ private: beginp = createInlinedFTask(nodep, namePrefix, outvscp); } // Replace the ref - if (nodep->castFuncRef()) { + if (VN_IS(nodep, FuncRef)) { if (!nodep->taskp()->isFunction()) nodep->v3fatalSrc("func reference to non-function"); AstVarRef* outrefp = new AstVarRef (nodep->fileline(), outvscp, false); nodep->replaceWith(outrefp); @@ -1197,7 +1197,7 @@ private: // Any variables inside the function still have varscopes pointing to them. // We're going to delete the vars, so delete the varscopes. if (nodep->isFunction()) { - if (AstVar* portp = nodep->fvarp()->castVar()) { + if (AstVar* portp = VN_CAST(nodep->fvarp(), Var)) { AstVarScope* vscp = m_statep->findVarScope(m_scopep, portp); UINFO(9," funcremovevsc "<unlinkFrBack()); VL_DANGLING(vscp); @@ -1205,7 +1205,7 @@ private: } for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp=nextp) { nextp = stmtp->nextp(); - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { AstVarScope* vscp = m_statep->findVarScope(m_scopep, portp); UINFO(9," funcremovevsc "<unlinkFrBack()); VL_DANGLING(vscp); @@ -1282,7 +1282,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) int tpinnum = 0; AstVar* sformatp = NULL; for (AstNode* stmtp = taskStmtsp; stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { tconnects.push_back(make_pair(portp, (AstArg*)NULL)); nameToIndex.insert(make_pair(portp->name(), tpinnum)); // For name based connections @@ -1301,7 +1301,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) bool reorganize = false; for (AstNode* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) { nextp = pinp->nextp(); - AstArg* argp = pinp->castArg(); if (!argp) pinp->v3fatalSrc("Non-arg under ftask reference"); + AstArg* argp = VN_CAST(pinp, Arg); if (!argp) pinp->v3fatalSrc("Non-arg under ftask reference"); if (argp->name() != "") { // By name NameToIndex::iterator it = nameToIndex.find(argp->name()); @@ -1346,12 +1346,12 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) nodep->v3error("Missing argument on non-defaulted argument '"<prettyName() <<"' in function call to "<taskp()->prettyTypeName()); newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0); - } else if (!portp->valuep()->castConst()) { + } else if (!VN_IS(portp->valuep(), Const)) { // The default value for this port might be a constant // expression that hasn't been folded yet. Try folding it // now; we don't have much to lose if it fails. newvaluep = V3Const::constifyParamsEdit(portp->valuep()); - if (!newvaluep->castConst()) { + if (!VN_IS(newvaluep, Const)) { // Problem otherwise is we might have a varref, task call, or something else that only // makes sense in the domain of the function, not the callee. nodep->v3error("Unsupported: Non-constant default value in missing argument '"<prettyName() diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 84200bf93..7d8d9c06e 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -223,7 +223,7 @@ private: if (nodep->valuep() && !vvertexp->duplicatep()) { V3Hashed::iterator dupit = hashed.findDuplicate(nodep->valuep()); if (dupit != hashed.end()) { - AstTraceInc* dupincp = hashed.iteratorNodep(dupit)->backp()->castTraceInc(); + AstTraceInc* dupincp = VN_CAST(hashed.iteratorNodep(dupit)->backp(), TraceInc); if (!dupincp) nodep->v3fatalSrc("Trace duplicate of wrong type"); TraceTraceVertex* dupvertexp = dynamic_cast(dupincp->user1u().toGraphVertex()); UINFO(8," Orig "<fileline(), funcp); callp->argTypes("vlSymsp, vcdp, code"); - if (callfromp->castCFunc()) { - callfromp->castCFunc()->addStmtsp(callp); - } else if (callfromp->castIf()) { - callfromp->castIf()->addIfsp(callp); + if (VN_IS(callfromp, CFunc)) { + VN_CAST(callfromp, CFunc)->addStmtsp(callp); + } else if (VN_IS(callfromp, If)) { + VN_CAST(callfromp, If)->addIfsp(callp); } else { callfromp->v3fatalSrc("Unknown caller node type"); // Where to add it?? } @@ -602,7 +602,7 @@ private: // If so, all funcs might share the same activity code TraceActivityVertex* activityVtxp = getActivityVertexp(nodep, nodep->funcp()->slow()); for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { - if (AstCCall* ccallp = nextp->castCCall()) { + if (AstCCall* ccallp = VN_CAST(nextp, CCall)) { ccallp->user2(true); // Processed UINFO(8," SubCCALL "<funcp()); diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 97cc47ffe..98201b0b3 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -198,7 +198,7 @@ private: if (m_traVscp) { if ((int)nodep->arrayUnpackedElements() > v3Global.opt.traceMaxArray()) { addIgnore("Wide memory > --trace-max-array ents"); - } else if (nodep->subDTypep()->skipRefp()->castBasicDType() // Nothing lower than this array + } else if (VN_IS(nodep->subDTypep()->skipRefp(), BasicDType) // Nothing lower than this array && m_traVscp->dtypep()->skipRefp() == nodep) { // Nothing above this array // Simple 1-D array, use exising V3EmitC runtime loop rather than unrolling // This will put "(index)" at end of signal name for us @@ -258,13 +258,13 @@ private: if (!nodep->packed()) { addIgnore("Unsupported: Unpacked struct/union"); } else { - for (AstMemberDType* itemp = nodep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { + for (AstMemberDType* itemp = nodep->membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); string oldShowname = m_traShowname; AstNode* oldValuep = m_traValuep; { m_traShowname += string(" ")+itemp->prettyName(); - if (nodep->castStructDType()) { + if (VN_IS(nodep, StructDType)) { m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), itemp->lsb(), subtypep->width()); subtypep->accept(*this); diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 305db626d..9d4102d84 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -101,7 +101,7 @@ public: virtual ~TristateVertex() {} // ACCESSORS AstNode* nodep() const { return m_nodep; } - AstVar* varp() const { return nodep()->castVar(); } + AstVar* varp() const { return VN_CAST(nodep(), Var); } virtual string name() const { return ((isTristate() ? "tri\\n" :feedsTri() ? "feed\\n" : "-\\n") @@ -180,7 +180,7 @@ private: // A variable is tristated. Find all of the LHS VARREFs that drive this signal now need tristate drivers for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep=edgep->inNextp()) { TristateVertex* vvertexp = dynamic_cast(edgep->fromp()); - if (AstVarRef* refp = vvertexp->nodep()->castVarRef()) { + if (const AstVarRef* refp = VN_CAST(vvertexp->nodep(), VarRef)) { if (refp->lvalue() // Doesn't hurt to not check if already set, but by doing so when we // print out the debug messages, we'll see this node at level 0 instead. @@ -269,7 +269,7 @@ public: for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { TristateVertex* vvertexp = static_cast(itp); if (vvertexp->isTristate()) { - if (AstVar* nodep = vvertexp->nodep()->castVar()) { + if (AstVar* nodep = VN_CAST(vvertexp->nodep(), Var)) { v.push_back(nodep); } } @@ -393,7 +393,7 @@ class TristateVisitor : public TristateBaseVisitor { else m_modp->addStmtp(newp); invarp->user1p(newp); // find envar given invarp } - return invarp->user1p()->castVar(); + return VN_CAST(invarp->user1p(), Var); } AstVar* getCreateOutVarp(AstVar* invarp) { @@ -408,7 +408,7 @@ class TristateVisitor : public TristateBaseVisitor { else m_modp->addStmtp(newp); invarp->user4p(newp); // find outvar given invarp } - return invarp->user4p()->castVar(); + return VN_CAST(invarp->user4p(), Var); } AstVar* getCreateUnconnVarp(AstNode* fromp, AstNodeDType* dtypep) { @@ -467,10 +467,10 @@ class TristateVisitor : public TristateBaseVisitor { nodep->v3error("Unsupported LHS tristate construct: "<prettyTypeName()); } // Ignore Var's because they end up adjacent to statements - if ((nodep->op1p() && nodep->op1p()->user1p() && !nodep->op1p()->castVar()) - || (nodep->op2p() && nodep->op2p()->user1p() && !nodep->op1p()->castVar()) - || (nodep->op3p() && nodep->op3p()->user1p() && !nodep->op1p()->castVar()) - || (nodep->op4p() && nodep->op4p()->user1p() && !nodep->op1p()->castVar())) { + if ((nodep->op1p() && nodep->op1p()->user1p() && !VN_IS(nodep->op1p(), Var)) + || (nodep->op2p() && nodep->op2p()->user1p() && !VN_IS(nodep->op1p(), Var)) + || (nodep->op3p() && nodep->op3p()->user1p() && !VN_IS(nodep->op1p(), Var)) + || (nodep->op4p() && nodep->op4p()->user1p() && !VN_IS(nodep->op1p(), Var))) { nodep->v3error("Unsupported tristate construct: "<prettyTypeName()); } } @@ -546,7 +546,7 @@ class TristateVisitor : public TristateBaseVisitor { outvarp->user3p(invarp->user3p()); // AstPull* propagation if (invarp->user3p()) UINFO(9, "propagate pull to "<user1p()) { - envarp = invarp->user1p()->castVar(); // From CASEEQ, foo === 1'bz + envarp = VN_CAST(invarp->user1p(), Var); // From CASEEQ, foo === 1'bz } AstNode* orp = NULL; @@ -936,13 +936,13 @@ class TristateVisitor : public TristateBaseVisitor { // away later when we determine the signal has no tristate nodep->iterateChildren(*this); UINFO(9,dbgState()<lhsp()->castConst(); // Constification always moves const to LHS - AstVarRef* varrefp = nodep->rhsp()->castVarRef(); // Input variable + const AstConst* constp = VN_CAST(nodep->lhsp(), Const); // Constification always moves const to LHS + AstVarRef* varrefp = VN_CAST(nodep->rhsp(), VarRef); // Input variable if (constp && constp->user1p() && varrefp) { // 3'b1z0 -> ((3'b101 == in__en) && (3'b100 == in)) varrefp->unlinkFrBack(); FileLine* fl = nodep->fileline(); - V3Number oneIfEn = constp->user1p()->castConst()->num(); // visit(AstConst) already split into en/ones + V3Number oneIfEn = VN_CAST(constp->user1p(), Const)->num(); // visit(AstConst) already split into en/ones V3Number oneIfEnOne = constp->num(); AstVar* envarp = getCreateEnVarp(varrefp->varp()); AstNode* newp = new AstLogAnd (fl, new AstEq (fl, new AstConst(fl, oneIfEn), @@ -962,7 +962,7 @@ class TristateVisitor : public TristateBaseVisitor { } } void visitEqNeqWild(AstNodeBiop* nodep) { - if (!nodep->rhsp()->castConst()) { + if (!VN_IS(nodep->rhsp(), Const)) { nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec. // rhs we want to keep X/Z intact, so otherwise ignore } @@ -985,7 +985,7 @@ class TristateVisitor : public TristateBaseVisitor { virtual void visit(AstPull* nodep) { UINFO(9,dbgState()<lhsp()->castVarRef()) { + if (AstVarRef* lhsp = VN_CAST(nodep->lhsp(), VarRef)) { lhsp->lvalue(true); m_logicp = nodep; m_tgraph.setTristate(nodep); @@ -1001,7 +1001,7 @@ class TristateVisitor : public TristateBaseVisitor { // current limitation of this implementation is that a pullup/down // gets applied to all bits of a bus and a bus cannot have drivers // in opposite directions on indvidual pins. - if (AstVarRef* lhsp = nodep->lhsp()->castVarRef()) { + if (AstVarRef* lhsp = VN_CAST(nodep->lhsp(), VarRef)) { lhsp->lvalue(true); m_tgraph.didProcess(nodep); m_tgraph.didProcess(lhsp->varp()); @@ -1159,12 +1159,12 @@ class TristateVisitor : public TristateBaseVisitor { exprrefp = NULL; // Primary input only } else { // pinReconnect should have converted this - exprrefp = outpinp->exprp()->castVarRef(); + exprrefp = VN_CAST(outpinp->exprp(), VarRef); if (!exprrefp) nodep->v3error("Unsupported tristate port expression: "<exprp()->prettyTypeName()); } } else { // pinReconnect should have converted this - exprrefp = outAssignp->rhsp()->castVarRef(); // This should be the same var as the output pin + exprrefp = VN_CAST(outAssignp->rhsp(), VarRef); // This should be the same var as the output pin if (!exprrefp) nodep->v3error("Unsupported tristate port expression: "<exprp()->prettyTypeName()); } if (exprrefp) { diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index adeabcc08..ae7102a9e 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -266,7 +266,7 @@ private: AstVar* varp = nodep->varp(); if (!varp->isParam() && !varp->isGenVar() && !varp->isUsedLoopIdx() && !m_inBBox // We may have falsely considered a SysIgnore as a driver - && !nodep->castVarXRef() // Xrefs might point at two different instances + && !VN_IS(nodep, VarXRef) // Xrefs might point at two different instances && !varp->fileline()->warnIsOff(V3ErrorCode::ALWCOMBORDER)) { // Warn only once per variable nodep->v3warn(ALWCOMBORDER, "Always_comb variable driven after use: "<prettyName()); varp->fileline()->modifyWarnOff(V3ErrorCode::ALWCOMBORDER, true); // Complain just once for any usage @@ -303,8 +303,8 @@ private: nodep->iterateChildren(*this); } virtual void visit(AstSel* nodep) { - AstNodeVarRef* varrefp = nodep->fromp()->castNodeVarRef(); - AstConst* constp = nodep->lsbp()->castConst(); + AstNodeVarRef* varrefp = VN_CAST(nodep->fromp(), NodeVarRef); + AstConst* constp = VN_CAST(nodep->lsbp(), Const); if (varrefp && constp && !constp->num().isFourState()) { for (int usr=1; usr<(m_alwaysp?3:2); ++usr) { UndrivenVarEntry* entryp = getEntryp (varrefp->varp(), usr); diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 5dec11be3..2b6173050 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -104,8 +104,8 @@ private: AstNode* prep = nodep; // Scan back to put the condlvalue above all selects (IE top of the lvalue) - while (prep->backp()->castNodeSel() - || prep->backp()->castSel()) { + while (VN_IS(prep->backp(), NodeSel) + || VN_IS(prep->backp(), Sel)) { prep=prep->backp(); } FileLine* fl = nodep->fileline(); @@ -113,7 +113,7 @@ private: // Already exists; rather than IF(a,... IF(b... optimize to IF(a&&b, // Saves us teaching V3Const how to optimize, and it won't be needed again. - if (AstIf* ifp = prep->user2p()->castIf()) { + if (AstIf* ifp = VN_CAST(prep->user2p(), If)) { if (needDly) prep->v3fatalSrc("Should have already converted to non-delay"); AstNRelinker replaceHandle; AstNode* earliercondp = ifp->condp()->unlinkFrBack(&replaceHandle); @@ -179,7 +179,7 @@ private: UINFO(4," N/EQCASE->EQ "<lhsp()); // lhsp may change V3Const::constifyEdit(nodep->rhsp()); // rhsp may change - if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) { + if (VN_IS(nodep->lhsp(), Const) && VN_IS(nodep->rhsp(), Const)) { // Both sides are constant, node can be constant V3Const::constifyEdit(nodep); VL_DANGLING(nodep); return; @@ -188,14 +188,14 @@ private: AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* newp; // If we got ==1'bx it can never be true (but 1'bx==1'bx can be!) - if (((lhsp->castConst() && lhsp->castConst()->num().isFourState()) - || (rhsp->castConst() && rhsp->castConst()->num().isFourState()))) { - V3Number num (nodep->fileline(), 1, (nodep->castEqCase()?0:1)); + if (((VN_IS(lhsp, Const) && VN_CAST(lhsp, Const)->num().isFourState()) + || (VN_IS(rhsp, Const) && VN_CAST(rhsp, Const)->num().isFourState()))) { + V3Number num (nodep->fileline(), 1, (VN_IS(nodep, EqCase) ? 0:1)); newp = new AstConst (nodep->fileline(), num); lhsp->deleteTree(); VL_DANGLING(lhsp); rhsp->deleteTree(); VL_DANGLING(rhsp); } else { - if (nodep->castEqCase()) + if (VN_IS(nodep, EqCase)) newp = new AstEq (nodep->fileline(), lhsp, rhsp); else newp = new AstNeq (nodep->fileline(), lhsp, rhsp); } @@ -209,7 +209,7 @@ private: UINFO(4," N/EQWILD->EQ "<lhsp()); // lhsp may change V3Const::constifyEdit(nodep->rhsp()); // rhsp may change - if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) { + if (VN_IS(nodep->lhsp(), Const) && VN_IS(nodep->rhsp(), Const)) { // Both sides are constant, node can be constant V3Const::constifyEdit(nodep); VL_DANGLING(nodep); return; @@ -217,20 +217,20 @@ private: AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* newp; - if (!rhsp->castConst()) { + if (!VN_IS(rhsp, Const)) { nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec. // Replace with anything that won't cause more errors newp = new AstEq (nodep->fileline(), lhsp, rhsp); } else { // X or Z's become mask, ala case statements. V3Number nummask (rhsp->fileline(), rhsp->width()); - nummask.opBitsNonX(rhsp->castConst()->num()); + nummask.opBitsNonX(VN_CAST(rhsp, Const)->num()); V3Number numval (rhsp->fileline(), rhsp->width()); - numval.opBitsOne (rhsp->castConst()->num()); + numval.opBitsOne (VN_CAST(rhsp, Const)->num()); AstNode* and1p = new AstAnd(nodep->fileline(), lhsp, new AstConst(nodep->fileline(), nummask)); AstNode* and2p = new AstConst(nodep->fileline(), numval); - if (nodep->castEqWild()) + if (VN_IS(nodep, EqWild)) newp = new AstEq (nodep->fileline(), and1p, and2p); else newp = new AstNeq (nodep->fileline(), and1p, and2p); rhsp->deleteTree(); VL_DANGLING(rhsp); @@ -333,7 +333,7 @@ private: // Guard against reading/writing past end of bit vector array AstNode* basefromp = AstArraySel::baseFromp(nodep); bool lvalue = false; - if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { + if (const AstNodeVarRef* varrefp = VN_CAST(basefromp, NodeVarRef)) { lvalue = varrefp->lvalue(); } // Find range of dtype we are selecting from @@ -385,9 +385,9 @@ private: // Guard against reading/writing past end of arrays AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); bool lvalue = false; - if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { + if (const AstNodeVarRef* varrefp = VN_CAST(basefromp, NodeVarRef)) { lvalue = varrefp->lvalue(); - } else if (basefromp->castConst()) { + } else if (VN_IS(basefromp, Const)) { // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp } else { nodep->v3fatalSrc("No VarRef or Const under ArraySel"); @@ -396,7 +396,7 @@ private: int declElements = -1; AstNodeDType* dtypep = nodep->fromp()->dtypep()->skipRefp(); if (!dtypep) nodep->v3fatalSrc("Select of non-selectable type"); - if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { + if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { declElements = adtypep->elementsConst(); } else { nodep->v3error("Select from non-array "<prettyTypeName()); @@ -415,7 +415,7 @@ private: condp->deleteTree(); } else if (!lvalue - && !nodep->backp()->castArraySel()) { // Too complicated and slow if mid-multidimension + && !VN_IS(nodep->backp(), ArraySel)) { // Too complicated and slow if mid-multidimension // ARRAYSEL(...) -> COND(LT(bitunlinkFrBack(&replaceHandle); diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index dcfd17781..948004052 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -110,22 +110,22 @@ private: if (incp) UINFO(6, " Inc "<castAssign(); + AstAssign* initAssp = VN_CAST(initp, Assign); if (!initAssp) return cantUnroll(nodep, "no initial assignment"); if (initp->nextp() && initp->nextp()!=nodep) nodep->v3fatalSrc("initial assignment shouldn't be a list"); - if (!initAssp->lhsp()->castVarRef()) return cantUnroll(nodep, "no initial assignment to simple variable"); + if (!VN_IS(initAssp->lhsp(), VarRef)) return cantUnroll(nodep, "no initial assignment to simple variable"); // // Condition check if (condp->nextp()) nodep->v3fatalSrc("conditional shouldn't be a list"); // // Assignment of next value check - AstAssign* incAssp = incp->castAssign(); + AstAssign* incAssp = VN_CAST(incp, Assign); if (!incAssp) return cantUnroll(nodep, "no increment assignment"); if (incAssp->nextp()) nodep->v3fatalSrc("increment shouldn't be a list"); - m_forVarp = initAssp->lhsp()->castVarRef()->varp(); - m_forVscp = initAssp->lhsp()->castVarRef()->varScopep(); - if (nodep->castGenFor() && !m_forVarp->isGenVar()) { + m_forVarp = VN_CAST(initAssp->lhsp(), VarRef)->varp(); + m_forVscp = VN_CAST(initAssp->lhsp(), VarRef)->varScopep(); + if (VN_IS(nodep, GenFor) && !m_forVarp->isGenVar()) { nodep->v3error("Non-genvar used in generate for: "<prettyName()<rhsp()); // rhsp may change @@ -134,7 +134,7 @@ private: // however, for repeat loops, the loop variable is auto-generated // and the initp statements will reference a variable outside of the initp scope // alas, failing to simulate. - AstConst* constInitp = initAssp->rhsp()->castConst(); + AstConst* constInitp = VN_CAST(initAssp->rhsp(), Const); if (!constInitp) return cantUnroll(nodep, "non-constant initializer"); // @@ -156,7 +156,7 @@ private: if (!m_generate) { - AstAssign *incpAssign = incp->castAssign(); + AstAssign *incpAssign = VN_CAST(incp, Assign); if (!canSimulate(incpAssign->rhsp())) return cantUnroll(incp, "Unable to simulate increment"); if (!canSimulate(condp)) return cantUnroll(condp, "Unable to simulate condition"); @@ -251,7 +251,7 @@ private: outLoopsr++; // Run inc - AstAssign* incpass = incp->castAssign(); + AstAssign* incpass = VN_CAST(incp, Assign); V3Number newLoopValue = V3Number(initp->fileline()); if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) { return false; @@ -287,7 +287,7 @@ private: bodysp->unlinkFrBackWithNext(); stmtsp = AstNode::addNextNull(stmtsp, bodysp); // Maybe null if no body } - if (incp && !nodep->castGenFor()) { // Generates don't need to increment loop index + if (incp && !VN_IS(nodep, GenFor)) { // Generates don't need to increment loop index incp->unlinkFrBackWithNext(); stmtsp = AstNode::addNextNull(stmtsp, incp); // Maybe null if no body } @@ -338,7 +338,7 @@ private: } // loopValue += valInc - AstAssign *incpass = incp->castAssign(); + AstAssign *incpass = VN_CAST(incp, Assign); V3Number newLoopValue = V3Number(nodep->fileline()); if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) { nodep->v3error("Loop unrolling failed"); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6d766d33d..5320aa9d3 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -24,7 +24,7 @@ // widthUnsized() = # bits for unsized constant, or 0 if it's sized // widthMin() = Alternative acceptable width for linting, or width() if sized // Determine this subop's width, can be either: -// Fixed width X +// Fixed width X // Unsized, min width X ('d5 is unsized, min 3 bits.) // Pass up: // width() = # bits this expression generates @@ -38,8 +38,8 @@ // If subop larger, add a EXTRACT // If subop smaller, add a EXTEND // Pass size to sub-expressions if required (+/-* etc) -// FINAL = true. -// Subexpressions lint and extend as needed +// FINAL = true. +// Subexpressions lint and extend as needed // //************************************************************************* // Signedness depends on: @@ -53,7 +53,7 @@ // Else, if any operand unsigned, output unsigned // // Real number rules: -// Real numbers are real (duh) +// Real numbers are real (duh) // Reals convert to integers by rounding // Reals init to 0.0 // Logicals convert compared to zero @@ -393,14 +393,14 @@ private: AstNumeric::UNSIGNED); // Cleanup zero width Verilog2001 {x,{0{foo}}} now, // otherwise having width(0) will cause later assertions to fire - if (AstReplicate* repp=nodep->lhsp()->castReplicate()) { + if (AstReplicate* repp=VN_CAST(nodep->lhsp(), Replicate)) { if (repp->width()==0) { // Keep rhs nodep->replaceWith(nodep->rhsp()->unlinkFrBack()); pushDeletep(nodep); VL_DANGLING(nodep); return; } } - if (AstReplicate* repp=nodep->rhsp()->castReplicate()) { + if (AstReplicate* repp=VN_CAST(nodep->rhsp(), Replicate)) { if (repp->width()==0) { // Keep lhs nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); pushDeletep(nodep); VL_DANGLING(nodep); @@ -446,10 +446,10 @@ private: iterateCheckSizedSelf(nodep,"LHS",nodep->lhsp(),SELF,BOTH); iterateCheckSizedSelf(nodep,"RHS",nodep->rhsp(),SELF,BOTH); V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change - AstConst* constp = nodep->rhsp()->castConst(); + const AstConst* constp = VN_CAST(nodep->rhsp(), Const); if (!constp) { nodep->v3error("Replication value isn't a constant."); return; } uint32_t times = constp->toUInt(); - if (times==0 && !nodep->backp()->castConcat()) { // Concat Visitor will clean it up. + if (times==0 && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up. nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2012 11.4.12.1)"); times=1; } if (nodep->lhsp()->isString()) { @@ -477,10 +477,10 @@ private: iterateCheckString(nodep,"LHS",nodep->lhsp(),BOTH); iterateCheckSizedSelf(nodep,"RHS",nodep->rhsp(),SELF,BOTH); V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change - AstConst* constp = nodep->rhsp()->castConst(); + const AstConst* constp = VN_CAST(nodep->rhsp(), Const); if (!constp) { nodep->v3error("Replication value isn't a constant."); return; } uint32_t times = constp->toUInt(); - if (times==0 && !nodep->backp()->castConcat()) { // Concat Visitor will clean it up. + if (times==0 && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up. nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2012 11.4.12.1)"); } nodep->dtypeSetString(); @@ -497,8 +497,8 @@ private: iterateCheckSizedSelf(nodep,"LHS",nodep->lhsp(),SELF,BOTH); iterateCheckSizedSelf(nodep,"RHS",nodep->rhsp(),SELF,BOTH); V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change - AstConst* constp = nodep->rhsp()->castConst(); - AstBasicDType* basicp = nodep->rhsp()->castBasicDType(); + const AstConst* constp = VN_CAST(nodep->rhsp(), Const); + AstBasicDType* basicp = VN_CAST(nodep->rhsp(), BasicDType); if (!constp && !basicp) { nodep->v3error("Slice size isn't a constant or basic data type."); return; } if (basicp) { // Convert data type to a constant size AstConst* newp = new AstConst(basicp->fileline(), basicp->width()); @@ -544,8 +544,8 @@ private: int width = nodep->elementsConst(); if (width > (1<<28)) nodep->v3error("Width of bit range is huge; vector of over 1billion bits: 0x"<littleEndian() && !nodep->backp()->castUnpackArrayDType() - && !nodep->backp()->castCell()) { // For cells we warn in V3Inst + if (nodep->littleEndian() && !VN_IS(nodep->backp(), UnpackArrayDType) + && !VN_IS(nodep->backp(), Cell)) { // For cells we warn in V3Inst nodep->v3warn(LITENDIAN,"Little bit endian vector: MSB < LSB of bit range: "<lsbConst()<<":"<msbConst()); } } @@ -564,14 +564,14 @@ private: iterateCheckSizedSelf(nodep,"Select Width",nodep->widthp(),SELF,BOTH); iterateCheckSizedSelf(nodep,"Select LHS",nodep->lhsp(),SELF,BOTH); V3Const::constifyParamsEdit(nodep->widthp()); // widthp may change - AstConst* widthConstp = nodep->widthp()->castConst(); + AstConst* widthConstp = VN_CAST(nodep->widthp(), Const); if (!widthConstp) { nodep->v3error("Width of bit extract isn't a constant"); nodep->dtypeSetLogicBool(); return; } int width = nodep->widthConst(); if (!nodep->dtypep()) nodep->v3fatalSrc("dtype wasn't set") // by V3WidthSel - if (nodep->lsbp()->castConst() + if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) { nodep->v3error("Unsupported: MSB < LSB of bit extract: " <msbConst()<<"<"<lsbConst()); @@ -617,7 +617,7 @@ private: UINFO(1," Related node: "<lsbp()->castConst() && nodep->msbConst() > frommsb) { + if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() > frommsb) { // See also warning in V3Const // We need to check here, because the widthCheckSized may silently // add another SEL which will lose the out-of-range check @@ -660,7 +660,7 @@ private: int frommsb; int fromlsb; AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp(); - if (AstUnpackArrayDType* adtypep = fromDtp->castUnpackArrayDType()) { + if (const AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { frommsb = adtypep->msb(); fromlsb = adtypep->lsb(); if (fromlsb>frommsb) {int t=frommsb; frommsb=fromlsb; fromlsb=t; } @@ -692,10 +692,11 @@ private: if (!m_doGenerate) { // Must check bounds before adding a select that truncates the bound // Note we've already subtracted off LSB - if (nodep->bitp()->castConst() && (nodep->bitp()->castConst()->toSInt() > (frommsb-fromlsb) - || nodep->bitp()->castConst()->toSInt() < 0)) { + if (VN_IS(nodep->bitp(), Const) + && (VN_CAST(nodep->bitp(), Const)->toSInt() > (frommsb-fromlsb) + || VN_CAST(nodep->bitp(), Const)->toSInt() < 0)) { nodep->v3warn(SELRANGE,"Selection index out of range: " - <<(nodep->bitp()->castConst()->toSInt()+fromlsb) + <<(VN_CAST(nodep->bitp(), Const)->toSInt()+fromlsb) <<" outside "<fromp()->dtypep()->skipRefp(); - AstUnpackArrayDType* adtypep = fromDtp->castUnpackArrayDType(); + AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType); if (!adtypep) { UINFO(1," Related dtype: "<v3fatalSrc("Packed array reference exceeds dimension of array"); @@ -923,8 +924,8 @@ private: if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression"); std::pair dim = nodep->fromp()->dtypep()->skipRefp()->dimensions(true); uint32_t msbdim = dim.first+dim.second; - if (!nodep->dimp() || nodep->dimp()->castConst() || msbdim<1) { - int dim = !nodep->dimp() ? 1 : nodep->dimp()->castConst()->toSInt(); + if (!nodep->dimp() || VN_IS(nodep->dimp(), Const) || msbdim<1) { + int dim = !nodep->dimp() ? 1 : VN_CAST(nodep->dimp(), Const)->toSInt(); AstConst* newp = dimensionValue(nodep->fromp()->dtypep(), nodep->attrType(), dim); nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); } @@ -962,7 +963,7 @@ private: // Cleanup array size userIterateAndNext(nodep->rangep(), WidthVP(SELF,BOTH).p()); nodep->dtypep(nodep); // The array itself, not subDtype - if (nodep->castUnpackArrayDType()) { + if (VN_IS(nodep, UnpackArrayDType)) { // Historically array elements have width of the ref type not the full array nodep->widthFromSub(nodep->subDTypep()); } else { @@ -1042,7 +1043,7 @@ private: // nodep->dtp could be data type, or a primary_constant // Don't iterate lhsp, will deal with that once convert the type V3Const::constifyParamsEdit(nodep->dtp()); // itemp may change - if (AstConst* constp = nodep->dtp()->castConst()) { + if (AstConst* constp = VN_CAST(nodep->dtp(), Const)) { constp->unlinkFrBack(); AstNode* newp = new AstCastSize(nodep->fileline(), nodep->lhsp()->unlinkFrBack(), constp); nodep->replaceWith(newp); @@ -1095,19 +1096,19 @@ private: virtual void visit(AstCastSize* nodep) { // IEEE: Signedness of result is same as self-determined signedness // However, the result is same as BITSEL, so we do not sign extend the LHS - if (!nodep->rhsp()->castConst()) nodep->v3fatalSrc("Unsupported: Non-const cast of size"); + if (!VN_IS(nodep->rhsp(), Const)) nodep->v3fatalSrc("Unsupported: Non-const cast of size"); //if (debug()) nodep->dumpTree(cout," CastSizePre: "); if (m_vup->prelim()) { - int width = nodep->rhsp()->castConst()->toSInt(); + int width = VN_CAST(nodep->rhsp(), Const)->toSInt(); if (width < 1) { nodep->v3error("Size-changing cast to zero or negative size"); width=1; } userIterateAndNext(nodep->lhsp(), WidthVP(SELF,PRELIM).p()); - AstBasicDType* underDtp = nodep->lhsp()->dtypep()->castBasicDType(); + AstBasicDType* underDtp = VN_CAST(nodep->lhsp()->dtypep(), BasicDType); if (!underDtp) { underDtp = nodep->lhsp()->dtypep()->basicp(); } if (!underDtp) { nodep->v3error("Unsupported: Size-changing cast on non-basic data type"); - underDtp = nodep->findLogicBoolDType()->castBasicDType(); + underDtp = VN_CAST(nodep->findLogicBoolDType(), BasicDType); } // A cast propagates its size to the lower expression and is included in the maximum // width, so 23'(1'b1 + 1'b1) uses 23-bit math, but 1'(2'h2 * 2'h1) uses two-bit math. @@ -1161,21 +1162,21 @@ private: if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep)); nodep->dtypep(iterateEditDTypep(nodep, nodep->dtypep())); if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype determined for var"); - if (nodep->dtypeSkipRefp()->castUnsizedArrayDType()) { + if (VN_IS(nodep->dtypeSkipRefp(), UnsizedArrayDType)) { if (!(m_ftaskp && m_ftaskp->dpiImport())) { nodep->v3error("Unsized/open arrays ('[]') are only supported in DPI imports"); } } - else if (nodep->isIO() && !(nodep->dtypeSkipRefp()->castBasicDType() - || nodep->dtypeSkipRefp()->castNodeArrayDType() - || nodep->dtypeSkipRefp()->castNodeClassDType())) { + else if (nodep->isIO() && !(VN_IS(nodep->dtypeSkipRefp(), BasicDType) + || VN_IS(nodep->dtypeSkipRefp(), NodeArrayDType) + || VN_IS(nodep->dtypeSkipRefp(), NodeClassDType))) { nodep->v3error("Unsupported: Inputs and outputs must be simple data types"); } - if (nodep->dtypep()->skipRefToConstp()->castConstDType()) { + if (VN_IS(nodep->dtypep()->skipRefToConstp(), ConstDType)) { nodep->isConst(true); } // Parameters if implicit untyped inherit from what they are assigned to - AstBasicDType* bdtypep = nodep->dtypep()->castBasicDType(); + AstBasicDType* bdtypep = VN_CAST(nodep->dtypep(), BasicDType); bool didchk = false; bool implicitParam = nodep->isParam() && bdtypep && bdtypep->implicit(); if (implicitParam) { @@ -1241,7 +1242,7 @@ private: virtual void visit(AstNodeVarRef* nodep) { if (nodep->didWidth()) return; if (!nodep->varp()) { - if (m_paramsOnly && nodep->castVarXRef()) { + if (m_paramsOnly && VN_IS(nodep, VarXRef)) { checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: "+nodep->prettyName()); VL_DANGLING(nodep); return; } else { @@ -1255,7 +1256,7 @@ private: //if (debug()>=9) { nodep->dumpTree(cout," VRin "); nodep->varp()->dumpTree(cout," forvar "); } // Note genvar's are also entered as integers nodep->dtypeFrom(nodep->varp()); - if (nodep->backp()->castNodeAssign() && nodep->lvalue()) { // On LHS + if (VN_IS(nodep->backp(), NodeAssign) && nodep->lvalue()) { // On LHS if (!nodep->widthMin()) nodep->v3fatalSrc("LHS var should be size complete"); } //if (debug()>=9) nodep->dumpTree(cout," VRout "); @@ -1280,12 +1281,12 @@ private: // Assign missing values V3Number num (nodep->fileline(), nodep->width(), 0); V3Number one (nodep->fileline(), nodep->width(), 1); - std::map inits; - for (AstEnumItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castEnumItem()) { + std::map inits; + for (AstEnumItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), EnumItem)) { if (itemp->valuep()) { if (debug()>=9) { UINFO(0,"EnumInit "<valuep()->dumpTree(cout,"-EnumInit: "); } V3Const::constifyParamsEdit(itemp->valuep()); // itemp may change - if (!itemp->valuep()->castConst()) { + if (!VN_IS(itemp->valuep(), Const)) { itemp->valuep()->v3error("Enum value isn't a constant"); itemp->valuep()->unlinkFrBack()->deleteTree(); continue; @@ -1302,7 +1303,7 @@ private: } itemp->valuep(new AstConst(itemp->fileline(), num)); } - num.opAssign(itemp->valuep()->castConst()->num()); + num.opAssign(VN_CAST(itemp->valuep(), Const)->num()); // Look for duplicates if (inits.find(num) != inits.end()) { // IEEE says illegal itemp->v3error("Overlapping enumeration value: "<prettyName()<valuep()->castConst()->num()); + num.opAdd(one, VN_CAST(itemp->valuep(), Const)->num()); } } virtual void visit(AstEnumItem* nodep) { @@ -1333,7 +1334,7 @@ private: AstNode* enump = nodep->itemp(); if (!enump) nodep->v3fatalSrc("EnumItemRef not linked"); for (; enump; enump=enump->backp()) { - if (enump->castEnumDType()) break; + if (VN_IS(enump, EnumDType)) break; } if (!enump) nodep->v3fatalSrc("EnumItemRef can't deref back to an Enum"); userIterate(enump, m_vup); VL_DANGLING(enump); // parent's connection to enump may be relinked @@ -1346,7 +1347,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->skipRefp()->castNodeArrayDType()) { + if (AstNodeArrayDType* arrayp = VN_CAST(vdtypep->skipRefp(), NodeArrayDType)) { userIterateChildren(nodep, WidthVP(arrayp->subDTypep(),BOTH).p()); } else { nodep->v3fatalSrc("InitArray on non-array"); @@ -1379,7 +1380,7 @@ private: for (AstNode* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) { nextip = itemp->nextp(); // Will be unlinking AstNode* inewp; - if (AstInsideRange* irangep = itemp->castInsideRange()) { + if (AstInsideRange* irangep = VN_CAST(itemp, InsideRange)) { // Similar logic in V3Case inewp = new AstAnd(itemp->fileline(), new AstGte(itemp->fileline(), @@ -1431,13 +1432,13 @@ private: nodep->isFourstate(false); // MSB is first, so go backwards AstMemberDType* itemp; - for (itemp = nodep->membersp(); itemp && itemp->nextp(); itemp=itemp->nextp()->castMemberDType()) ; + for (itemp = nodep->membersp(); itemp && itemp->nextp(); itemp=VN_CAST(itemp->nextp(), MemberDType)) ; for (AstMemberDType* backip; itemp; itemp=backip) { if (nodep->isFourstate()) nodep->isFourstate(true); - backip = itemp->backp()->castMemberDType(); + backip = VN_CAST(itemp->backp(), MemberDType); itemp->lsb(lsb); - if (nodep->castUnionDType()) { - width = std::max(width, itemp->width()); + if (VN_IS(nodep, UnionDType)) { + width = std::max(width, itemp->width()); } else { lsb += itemp->width(); width += itemp->width(); @@ -1463,14 +1464,14 @@ private: AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); UINFO(9," from dt "<castNodeClassDType()) { + if (AstNodeClassDType* adtypep = VN_CAST(fromDtp, NodeClassDType)) { // No need to width-resolve the class, as it was done when we did the child memberp = adtypep->findMember(nodep->name()); if (!memberp) { nodep->v3error("Member '"<prettyName()<<"' not found in structure"); } } - else if (fromDtp->castEnumDType()) { + else if (VN_IS(fromDtp, EnumDType)) { // Method call on enum without following parenthesis, e.g. "ENUM.next" // Convert this into a method call, and let that visitor figure out what to do next AstNode* newp = new AstMethodSel(nodep->fileline(), nodep->fromp()->unlinkFrBack(), nodep->name(), NULL); @@ -1511,7 +1512,7 @@ private: if (debug()>=9) nodep->dumpTree("-mts-in: "); // Should check types the method requires, but at present we don't do much userIterate(nodep->fromp(), WidthVP(SELF,BOTH).p()); - for (AstArg* argp = nodep->pinsp()->castArg(); argp; argp = argp->nextp()->castArg()) { + for (AstArg* argp = VN_CAST(nodep->pinsp(), Arg); argp; argp = VN_CAST(argp->nextp(), Arg)) { if (argp->exprp()) userIterate(argp->exprp(), WidthVP(SELF,BOTH).p()); } // Find the fromp dtype - should be a class @@ -1519,7 +1520,7 @@ private: AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : NULL; UINFO(9," from dt "<castEnumDType()) { + if (AstEnumDType* adtypep = VN_CAST(fromDtp, EnumDType)) { // Method call on enum without following parenthesis, e.g. "ENUM.next" // Convert this into a method call, and let that visitor figure out what to do next if (adtypep) {} @@ -1536,12 +1537,12 @@ private: } else if (nodep->name() == "first") { AstEnumItem* itemp = adtypep->itemsp(); if (!itemp) newp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0); // Spec doesn't say what to do - else newp = itemp->valuep()->cloneTree(false)->castConst(); // A const + else newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const } else if (nodep->name() == "last") { AstEnumItem* itemp = adtypep->itemsp(); - while (itemp && itemp->nextp()) itemp = itemp->nextp()->castEnumItem(); + while (itemp && itemp->nextp()) itemp = VN_CAST(itemp->nextp(), EnumItem); if (!itemp) newp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0); // Spec doesn't say what to do - else newp = itemp->valuep()->cloneTree(false)->castConst(); // A const + else newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const } if (!newp) nodep->v3fatalSrc("Enum method (perhaps enum item) not const"); newp->fileline(nodep->fileline()); // Use method's filename/line number to be clearer; may have warning disables @@ -1559,8 +1560,8 @@ private: if (nodep->pinsp() && nodep->name() == "name") { nodep->v3error("Arguments passed to enum.name method, but it does not take arguments"); - } else if (nodep->pinsp() && !(nodep->pinsp()->castArg()->exprp()->castConst() - && nodep->pinsp()->castArg()->exprp()->castConst()->toUInt()==1 + } else if (nodep->pinsp() && !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const) + && VN_CAST(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)->toUInt()==1 && !nodep->pinsp()->nextp())) { nodep->v3error("Unsupported: Arguments passed to enum.next method"); } @@ -1571,8 +1572,8 @@ private: // a map for when the value is many bits and sparse. uint64_t msbdim = 0; { - for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp = itemp->nextp()->castEnumItem()) { - AstConst* vconstp = itemp->valuep()->castConst(); + for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) { + const AstConst* vconstp = VN_CAST(itemp->valuep(), Const); if (!vconstp) nodep->v3fatalSrc("Enum item without constified value"); if (vconstp->toUQuad() >= msbdim) msbdim = vconstp->toUQuad(); } @@ -1595,7 +1596,7 @@ private: nodep->v3error("Unknown built-in enum method '"<fromp()->prettyTypeName()<<"'"); } } - else if (AstUnpackArrayDType* arrayType = fromDtp->castUnpackArrayDType()) { + else if (AstUnpackArrayDType* arrayType = VN_CAST(fromDtp, UnpackArrayDType)) { enum { UNKNOWN = 0, ARRAY_OR, @@ -1666,7 +1667,7 @@ private: UINFO(9," adtypep "<dtypep(vdtypep); // Determine replication count, and replicate initial value as widths need to be individually determined - for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; patp = VN_CAST(patp->nextp(), PatMember)) { int times = visitPatMemberRep(patp); for (int i=1; icloneTree(false); @@ -1675,7 +1676,7 @@ private: } } // Convert any PatMember with multiple items to multiple PatMembers - for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->lhssp()->nextp()) { // Can't just addNext, as would add to end of all members. So detach, add next and reattach AstNRelinker relinkHandle; @@ -1689,17 +1690,17 @@ private: } } AstPatMember* defaultp = NULL; - for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->isDefault()) { if (defaultp) nodep->v3error("Multiple '{ default: } clauses"); defaultp = patp; patp->unlinkFrBack(); } } - while (AstConstDType* classp = vdtypep->castConstDType()) { + while (const AstConstDType* classp = VN_CAST(vdtypep, ConstDType)) { vdtypep = classp->subDTypep()->skipRefp(); } - if (AstNodeClassDType* classp = vdtypep->castNodeClassDType()) { + if (AstNodeClassDType* classp = VN_CAST(vdtypep, NodeClassDType)) { // Due to "default" and tagged patterns, we need to determine // which member each AstPatMember corresponds to before we can // determine the dtypep for that PatMember's value, and then @@ -1708,11 +1709,11 @@ private: PatMap patmap; { AstMemberDType* memp = classp->membersp(); - AstPatMember* patp = nodep->itemsp()->castPatMember(); + AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); for (; memp || patp; ) { if (patp) { if (patp->keyp()) { - if (AstText* textp = patp->keyp()->castText()) { + if (AstText* textp = VN_CAST(patp->keyp(), Text)) { memp = classp->findMember(textp->text()); if (!memp) { patp->keyp()->v3error("Assignment pattern key '"<text()<<"' not found as member"); @@ -1731,16 +1732,16 @@ private: } else { std::pair ret = patmap.insert(make_pair(memp, patp)); if (!ret.second) { - patp->v3error("Assignment pattern contains duplicate entry: " << patp->keyp()->castText()->text()); + patp->v3error("Assignment pattern contains duplicate entry: " << VN_CAST(patp->keyp(), Text)->text()); } } // Next - if (memp) memp = memp->nextp()->castMemberDType(); - if (patp) patp = patp->nextp()->castPatMember(); + if (memp) memp = VN_CAST(memp->nextp(), MemberDType); + if (patp) patp = VN_CAST(patp->nextp(), PatMember); } } AstNode* newp = NULL; - for (AstMemberDType* memp = classp->membersp(); memp; memp=memp->nextp()->castMemberDType()) { + for (AstMemberDType* memp = classp->membersp(); memp; memp=VN_CAST(memp->nextp(), MemberDType)) { PatMap::iterator it = patmap.find(memp); AstPatMember* newpatp = NULL; AstPatMember* patp = NULL; @@ -1750,7 +1751,7 @@ private: patp = newpatp; } else { - if (!classp->castUnionDType()) { + if (!VN_IS(classp, UnionDType)) { patp->v3error("Assignment pattern missed initializing elements: "<prettyTypeName()); } } @@ -1765,9 +1766,9 @@ private: // Convert to concat for now AstNode* valuep = patp->lhssp()->unlinkFrBack(); - if (valuep->castConst()) { + if (VN_IS(valuep, Const)) { // Forming a AstConcat will cause problems with unsized (uncommitted sized) constants - if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) { + if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) { pushDeletep(valuep); VL_DANGLING(valuep); valuep = newp; } @@ -1787,8 +1788,8 @@ private: else nodep->v3error("Assignment pattern with no members"); pushDeletep(nodep); VL_DANGLING(nodep); // Deletes defaultp also, if present } - else if (vdtypep->castNodeArrayDType()) { - AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType(); + else if (VN_IS(vdtypep, NodeArrayDType)) { + AstNodeArrayDType* arrayp = VN_CAST(vdtypep, NodeArrayDType); VNumRange range = arrayp->declRange(); PatVecMap patmap = patVectorMap(nodep, range); UINFO(9,"ent "<dtypep(),BOTH).p()); // See visit(AstPatMember* // Convert to InitArray or constify immediately AstNode* valuep = patp->lhssp()->unlinkFrBack(); - if (valuep->castConst()) { + if (VN_IS(valuep, Const)) { // Forming a AstConcat will cause problems with unsized (uncommitted sized) constants - if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) { + if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) { pushDeletep(valuep); VL_DANGLING(valuep); valuep = newp; } } - if (arrayp->castUnpackArrayDType()) { + if (VN_IS(arrayp, UnpackArrayDType)) { if (!newp) { AstInitArray* newap = new AstInitArray(nodep->fileline(), arrayp, NULL); newap->addValuep(valuep); @@ -1834,7 +1835,7 @@ private: } else { // We iterate hi()..lo() as that is what packed needs, // but INITARRAY needs lo() first - newp->castInitArray()->addFrontValuep(valuep); + VN_CAST(newp, InitArray)->addFrontValuep(valuep); } } else { // Packed. Convert to concat for now. if (!newp) newp = valuep; @@ -1855,9 +1856,9 @@ private: //if (debug()>=9) newp->dumpTree("-apat-out: "); pushDeletep(nodep); VL_DANGLING(nodep); // Deletes defaultp also, if present } - else if (vdtypep->castBasicDType() - && vdtypep->castBasicDType()->isRanged()) { - AstBasicDType* bdtypep = vdtypep->castBasicDType(); + else if (VN_IS(vdtypep, BasicDType) + && VN_CAST(vdtypep, BasicDType)->isRanged()) { + AstBasicDType* bdtypep = VN_CAST(vdtypep, BasicDType); VNumRange range = bdtypep->declRange(); PatVecMap patmap = patVectorMap(nodep, range); UINFO(9,"ent "<dtypep(),BOTH).p()); // Convert to InitArray or constify immediately AstNode* valuep = patp->lhssp()->unlinkFrBack(); - if (valuep->castConst()) { + if (VN_IS(valuep, Const)) { // Forming a AstConcat will cause problems with unsized (uncommitted sized) constants - if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) { + if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) { pushDeletep(valuep); VL_DANGLING(valuep); valuep = newp; } @@ -1932,7 +1933,7 @@ private: if (nodep->repp()) { // else repp()==NULL shorthand for rep count 1 iterateCheckSizedSelf(nodep,"LHS",nodep->repp(),SELF,BOTH); V3Const::constifyParamsEdit(nodep->repp()); // repp may change - AstConst* constp = nodep->repp()->castConst(); + const AstConst* constp = VN_CAST(nodep->repp(), Const); if (!constp) { nodep->v3error("Replication value isn't a constant."); times=0; } else times = constp->toUInt(); if (times==0) { nodep->v3error("Pattern replication value of 0 is not legal."); times=1; } @@ -1962,8 +1963,8 @@ private: assertAtStatement(nodep); userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT,PRELIM).p()); for (AstCaseItem* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) { - nextip = itemp->nextp()->castCaseItem(); // Prelim may cause the node to get replaced - if (!nodep->castGenCase()) userIterateAndNext(itemp->bodysp(), NULL); + nextip = VN_CAST(itemp->nextp(), CaseItem); // Prelim may cause the node to get replaced + if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->bodysp(), NULL); for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) { nextcp = condp->nextp(); // Prelim may cause the node to get replaced userIterate(condp, WidthVP(CONTEXT,PRELIM).p()); VL_DANGLING(condp); @@ -1972,7 +1973,7 @@ private: // Take width as maximum across all items, if any is real whole thing is real AstNodeDType* subDTypep = nodep->exprp()->dtypep(); - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { for (AstNode* condp = itemp->condsp(); condp; condp=condp->nextp()) { if (condp->dtypep() != subDTypep) { if (condp->dtypep()->isDouble()) { @@ -1988,7 +1989,7 @@ private: } // Apply width iterateCheck(nodep,"Case expression",nodep->exprp(),CONTEXT,FINAL,subDTypep,EXTEND_LHS); - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) { nextcp = condp->nextp(); // Final may cause the node to get replaced iterateCheck(nodep,"Case Item",condp,CONTEXT,FINAL,subDTypep,EXTEND_LHS); @@ -1999,7 +2000,7 @@ private: assertAtStatement(nodep); userIterateAndNext(nodep->initsp(), NULL); iterateCheckBool(nodep,"For Test Condition",nodep->condp(),BOTH); // it's like an if() condition. - if (!nodep->castGenFor()) userIterateAndNext(nodep->bodysp(), NULL); + if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), NULL); userIterateAndNext(nodep->incsp(), NULL); } @@ -2018,7 +2019,7 @@ private: virtual void visit(AstNodeIf* nodep) { assertAtStatement(nodep); //if (debug()) nodep->dumpTree(cout," IfPre: "); - if (!nodep->castGenIf()) { // for m_paramsOnly + if (!VN_IS(nodep, GenIf)) { // for m_paramsOnly userIterateAndNext(nodep->ifsp(), NULL); userIterateAndNext(nodep->elsesp(), NULL); } @@ -2195,7 +2196,7 @@ private: assertAtStatement(nodep); userIterateAndNext(nodep->filenamep(), WidthVP(SELF,BOTH).p()); userIterateAndNext(nodep->memp(), WidthVP(SELF,BOTH).p()); - if (!nodep->memp()->dtypep()->skipRefp()->castUnpackArrayDType()) { + if (!VN_IS(nodep->memp()->dtypep()->skipRefp(), UnpackArrayDType)) { nodep->memp()->v3error("Unsupported: $readmem into other than unpacked array"); } userIterateAndNext(nodep->lsbp(), WidthVP(SELF,BOTH).p()); @@ -2281,17 +2282,17 @@ private: // 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())) { + if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(exprDTypep, IfaceRefDType)) || + (VN_IS(exprDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) { nodep->v3error("Illegal "<prettyOperatorName()<<"," - <<" mismatch between port which is"<<(modDTypep->castIfaceRefDType()?"":" not")<<" an interface," - <<" and expression which is"<<(exprDTypep->castIfaceRefDType()?"":" not")<<" an interface."); + <<" mismatch between port which is"<<(VN_CAST(modDTypep, IfaceRefDType)?"":" not")<<" an interface," + <<" and expression which is"<<(VN_CAST(exprDTypep, IfaceRefDType)?"":" not")<<" an interface."); } // TODO Simple dtype checking, should be a more general check - AstNodeArrayDType* exprArrayp = exprDTypep->skipRefp()->castUnpackArrayDType(); - AstNodeArrayDType* modArrayp = modDTypep->skipRefp()->castUnpackArrayDType(); - if (exprArrayp && modArrayp && exprArrayp->subDTypep()->skipRefp()->castIfaceRefDType() + AstNodeArrayDType* exprArrayp = VN_CAST(exprDTypep->skipRefp(), UnpackArrayDType); + AstNodeArrayDType* modArrayp = VN_CAST(modDTypep->skipRefp(), UnpackArrayDType); + if (exprArrayp && modArrayp && VN_IS(exprArrayp->subDTypep()->skipRefp(), IfaceRefDType) && exprArrayp->declRange().elements() != modArrayp->declRange().elements()) { int exprSize = exprArrayp->declRange().elements(); int modSize = modArrayp->declRange().elements(); @@ -2315,7 +2316,7 @@ private: } virtual void visit(AstCell* nodep) { if (!m_paramsOnly) { - if (nodep->modp()->castNotFoundModule()) { + if (VN_IS(nodep->modp(), NotFoundModule)) { // We've resolved parameters and hit a module that we couldn't resolve. It's // finally time to report it. // Note only here in V3Width as this is first visitor after V3Dead. @@ -2371,7 +2372,7 @@ private: m_ftaskp = nodep; userIterateChildren(nodep, NULL); if (nodep->fvarp()) { - m_funcp = nodep->castFunc(); + m_funcp = VN_CAST(nodep, Func); if (!m_funcp) nodep->v3fatalSrc("FTask with function variable, but isn't a function"); nodep->dtypeFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep() } @@ -2404,7 +2405,7 @@ private: } virtual void visit(AstFuncRef* nodep) { - visit(nodep->castNodeFTaskRef()); + visit(VN_CAST(nodep, NodeFTaskRef)); nodep->dtypeFrom(nodep->taskp()); //if (debug()) nodep->dumpTree(cout," FuncOut: "); } @@ -2428,17 +2429,17 @@ private: // Prelim may cause the node to get replaced; we've lost our // pointer, so need to iterate separately later if (portp->attrSFormat() - && (!pinp->castSFormatF() || pinp->nextp())) { // Not already done + && (!VN_IS(pinp, SFormatF) || pinp->nextp())) { // Not already done UINFO(4," sformat via metacomment: "<unlinkFrBackWithNext(&handle); // Format + additional args, if any AstNode* argsp = NULL; - while (AstArg* nextargp = argp->nextp()->castArg()) { + while (AstArg* nextargp = VN_CAST(argp->nextp(), Arg)) { argsp = AstNode::addNext(argsp, nextargp->exprp()->unlinkFrBackWithNext()); // Expression goes to SFormatF nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper } string format; - if (pinp->castConst()) format = pinp->castConst()->num().toString(); + if (VN_IS(pinp, Const)) format = VN_CAST(pinp, Const)->num().toString(); else pinp->v3error("Format to $display-like function must have constant format string"); pushDeletep(argp); VL_DANGLING(argp); AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp); @@ -2450,9 +2451,10 @@ private: goto reloop; // so exit early; next loop will correct it } else if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING - && !pinp->castCvtPackString() - && !pinp->castSFormatF() // Already generates a string - && !(pinp->castVarRef() && pinp->castVarRef()->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) { + && !VN_IS(pinp, CvtPackString) + && !VN_IS(pinp, SFormatF) // Already generates a string + && !(VN_IS(pinp, VarRef) + && VN_CAST(pinp, VarRef)->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) { UINFO(4," Add CvtPackString: "<unlinkFrBack(&handle); // No next, that's the next pin @@ -2807,17 +2809,17 @@ private: AstNodeDType* subDTypep = expDTypep; nodep->dtypeFrom(expDTypep); // ShiftRS converts to ShiftR, but not vice-versa - if (nodep->castShiftRS()) { + if (VN_IS(nodep, ShiftRS)) { if (AstNodeBiop* newp=replaceWithUOrSVersion(nodep, nodep->isSigned())) { VL_DANGLING(nodep); nodep = newp; // Process new node instead } } bool warnOn = true; // No warning if "X = 1'b1<lhsp()->isOne() && nodep->backp()->castNodeAssign()) warnOn = false; + if (nodep->lhsp()->isOne() && VN_IS(nodep->backp(), NodeAssign)) warnOn = false; iterateCheck(nodep,"LHS",nodep->lhsp(),CONTEXT,FINAL,subDTypep,EXTEND_EXP,warnOn); if (nodep->rhsp()->width()>32) { - AstConst* shiftp = nodep->rhsp()->castConst(); + AstConst* shiftp = VN_CAST(nodep->rhsp(), Const); if (shiftp && shiftp->num().mostSetBitP1() <= 32) { // If (number)<<96'h1, then make it into (number)<<32'h1 V3Number num (shiftp->fileline(), 32, 0); num.opAssign(shiftp->num()); @@ -2911,10 +2913,10 @@ private: } // Some warning suppressions bool lhsWarn=true; bool rhsWarn = true; - if (nodep->castAdd() || nodep->castSub()) { + if (VN_IS(nodep, Add) || VN_IS(nodep, Sub)) { if (subDTypep->widthMin() == (nodep->lhsp()->widthMin()+1)) lhsWarn=false; // Warn if user wants extra bit from carry if (subDTypep->widthMin() == (nodep->rhsp()->widthMin()+1)) rhsWarn=false; // Warn if user wants extra bit from carry - } else if (nodep->castMul() || nodep->castMulS()) { + } else if (VN_IS(nodep, Mul) || VN_IS(nodep, MulS)) { if (subDTypep->widthMin() >= (nodep->lhsp()->widthMin())) lhsWarn=false; if (subDTypep->widthMin() >= (nodep->rhsp()->widthMin())) rhsWarn=false; } @@ -2972,7 +2974,7 @@ private: // for example $unsigned(a)+$signed(b), the SIGNED(B) will be unsigned dtype out UINFO(4," widthExtend_(r="<castConst(); + AstConst* constp = VN_CAST(nodep, Const); int expWidth = expDTypep->width(); if (constp && !constp->num().isNegative()) { // Save later constant propagation work, just right-size it. @@ -3026,7 +3028,7 @@ private: int expWidth = 1; int expSigned = false; UINFO(4," widthReduce_old: "<castConst(); + AstConst* constp = VN_CAST(nodep, Const); if (constp) { V3Number num (nodep->fileline(), expWidth); num.opRedOr(constp->num()); @@ -3048,7 +3050,7 @@ private: bool fixAutoExtend (AstNode*& nodepr, int expWidth) { // For SystemVerilog '0,'1,'x,'z, autoextend and don't warn - if (AstConst* constp = nodepr->castConst()) { + if (AstConst* constp = VN_CAST(nodepr, Const)) { if (constp->num().autoExtend() && !constp->num().sized() && constp->width()==1) { // Make it the proper size. Careful of proper extension of 0's/1's V3Number num (constp->fileline(), expWidth); @@ -3123,8 +3125,8 @@ private: //if (debug()) nodep->dumpTree(cout,"-checkass: "); if (stage != FINAL) nodep->v3fatalSrc("Bad width call"); // We iterate and size the RHS based on the result of RHS evaluation - bool lhsStream = (nodep->castNodeAssign() - && nodep->castNodeAssign()->lhsp()->castNodeStream()); + bool lhsStream = (VN_IS(nodep, NodeAssign) + && VN_IS(VN_CAST(nodep, NodeAssign)->lhsp(), NodeStream)); rhsp = iterateCheck(nodep,side,rhsp,ASSIGN,FINAL,lhsDTypep,lhsStream?EXTEND_OFF:EXTEND_LHS); //if (debug()) nodep->dumpTree(cout,"-checkout: "); if (rhsp) {} // cppcheck @@ -3257,15 +3259,15 @@ private: underp=NULL; // Changes underp return; } - if (underp->castConst() && underp->castConst()->num().isFromString() + if (VN_IS(underp, Const) && VN_CAST(underp, Const)->num().isFromString() && expWidth > underp->width() && (((expWidth - underp->width()) % 8) == 0)) { // At least it's character sized // reg [31:0] == "foo" we'll consider probably fine. // Maybe this should be a special warning? Not for now. warnOn = false; } - if ((nodep->castAdd() && underp->width()==1 && underp->isOne()) - || (nodep->castSub() && underp->width()==1 && underp->isOne() && 0==strcmp(side,"RHS"))) { + if ((VN_IS(nodep, Add) && underp->width()==1 && underp->isOne()) + || (VN_IS(nodep, Sub) && underp->width()==1 && underp->isOne() && 0==strcmp(side,"RHS"))) { // "foo + 1'b1", or "foo - 1'b1" are very common, people assume they extend correctly warnOn = false; } @@ -3284,9 +3286,9 @@ private: // If we're in an NodeAssign, don't truncate the RHS if the LHS is // a NodeStream. The streaming operator changes the rules regarding // which bits to truncate. - AstNodeAssign* assignp = nodep->castNodeAssign(); - AstPin* pinp = nodep->castPin(); - if (assignp && assignp->lhsp()->castNodeStream()) { + AstNodeAssign* assignp = VN_CAST(nodep, NodeAssign); + AstPin* pinp = VN_CAST(nodep, Pin); + if (assignp && VN_IS(assignp->lhsp(), NodeStream)) { } else if (pinp && !pinp->modVarp()->isInput()) { // V3Inst::pinReconnectSimple must deal UINFO(5,"pinInSizeMismatch: "<castNodeArrayDType()) { + if (AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { declRange = adtypep->declRange(); if (isubDTypep()->skipRefp(); continue; - } else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) { + } else if (AstNodeClassDType* adtypep = VN_CAST(dtypep, NodeClassDType)) { declRange = adtypep->declRange(); if (adtypep) {} // UNUSED break; // Sub elements don't look like arrays and can't iterate into - } else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { + } else if (AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { if (adtypep->isRanged()) declRange = adtypep->declRange(); break; } @@ -3538,14 +3540,14 @@ private: int bits = 1; while (dtypep) { //UINFO(9, " bits at "<castNodeArrayDType()) { + if (AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { bits *= adtypep->declRange().elements(); dtypep = adtypep->subDTypep()->skipRefp(); continue; - } else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) { + } else if (AstNodeClassDType* adtypep = VN_CAST(dtypep, NodeClassDType)) { bits *= adtypep->width(); break; - } else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { + } else if (AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { bits *= adtypep->width(); break; } @@ -3660,10 +3662,10 @@ private: { AstEnumItem* firstp = nodep->itemsp(); AstEnumItem* prevp = firstp; // Prev must start with last item - while (prevp->nextp()) prevp = prevp->nextp()->castEnumItem(); + while (prevp->nextp()) prevp = VN_CAST(prevp->nextp(), EnumItem); for (AstEnumItem* itemp = firstp; itemp;) { - AstEnumItem* nextp = itemp->nextp()->castEnumItem(); - AstConst* vconstp = itemp->valuep()->castConst(); + AstEnumItem* nextp = VN_CAST(itemp->nextp(), EnumItem); + const AstConst* vconstp = VN_CAST(itemp->valuep(), Const); if (!vconstp) nodep->v3fatalSrc("Enum item without constified value"); uint32_t i = vconstp->toUInt(); if (attrType == AstAttrType::ENUM_NAME) { @@ -3692,10 +3694,10 @@ private: PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) { PatVecMap patmap; int element = range.left(); - for (AstPatMember* patp = nodep->itemsp()->castPatMember(); - patp; patp = patp->nextp()->castPatMember()) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); + patp; patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->keyp()) { - if (AstConst* constp = patp->keyp()->castConst()) { + if (const AstConst* constp = VN_CAST(patp->keyp(), Const)) { element = constp->toSInt(); } else { patp->keyp()->v3error("Assignment pattern key not supported/understood: "<keyp()->prettyTypeName()); @@ -3740,7 +3742,7 @@ private: bool markHasOpenArray(AstNodeFTask* nodep) { bool hasOpen = false; for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { - if (AstVar* portp = stmtp->castVar()) { + if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isDpiOpenArray() || hasOpenArrayIterateDType(portp->dtypep())) { portp->isDpiOpenArray(true); hasOpen = true; @@ -3751,7 +3753,7 @@ private: } bool hasOpenArrayIterateDType(AstNodeDType* nodep) { // Return true iff this datatype or child has an openarray - if (nodep->castUnsizedArrayDType()) return true; + if (VN_IS(nodep, UnsizedArrayDType)) return true; if (nodep->subDTypep()) return hasOpenArrayIterateDType(nodep->subDTypep()->skipRefp()); return false; } @@ -3767,7 +3769,7 @@ private: void checkConstantOrReplace(AstNode* nodep, const string& message) { // See also V3WidthSel::checkConstantOrReplace // Note can't call V3Const::constifyParam(nodep) here, as constify may change nodep on us! - if (!nodep->castConst()) { + if (!VN_IS(nodep, Const)) { nodep->v3error(message); nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Unsized32(), 1)); pushDeletep(nodep); VL_DANGLING(nodep); diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index d64742d69..44bbbcfb1 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -101,7 +101,7 @@ private: // Recurse to handle the data type, as may change the size etc of this type if (!nodep->user1()) nodep->accept(*this); // Look for duplicate - if (AstBasicDType* bdtypep = nodep->castBasicDType()) { + if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) { AstBasicDType* newp = nodep->findInsertSameDType(bdtypep); if (newp != bdtypep && debug()>=9) { UINFO(9,"dtype replacement "); nodep->dumpSmall(cout); diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 721020133..fe82726e6 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -62,7 +62,7 @@ private: void checkConstantOrReplace(AstNode* nodep, const string& message) { // See also V3Width::checkConstantOrReplace // Note can't call V3Const::constifyParam(nodep) here, as constify may change nodep on us! - if (!nodep->castConst()) { + if (!VN_IS(nodep, Const)) { nodep->v3error(message); nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Unsized32(), 1)); pushDeletep(nodep); VL_DANGLING(nodep); @@ -83,8 +83,8 @@ private: UINFO(9," fromData start ddtypep = "<castAttrOf()) { - basefromp = basefromp->castAttrOf()->fromp(); + if (VN_IS(basefromp, AttrOf)) { + basefromp = VN_CAST(basefromp, AttrOf)->fromp(); continue; } break; @@ -93,17 +93,17 @@ private: AstNodeDType* ddtypep = basefromp->dtypep()->skipRefp(); AstNode* errp = ddtypep; UINFO(9," fromData.ddtypep = "<castNodeArrayDType()) { + if (const AstNodeArrayDType* adtypep = VN_CAST(ddtypep, NodeArrayDType)) { fromRange = adtypep->declRange(); } - else if (AstNodeClassDType* adtypep = ddtypep->castNodeClassDType()) { + else if (const AstNodeClassDType* adtypep = VN_CAST(ddtypep, NodeClassDType)) { fromRange = adtypep->declRange(); } - else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) { + else if (AstBasicDType* adtypep = VN_CAST(ddtypep, BasicDType)) { if (adtypep->isRanged()) { if (adtypep->rangep() - && (!adtypep->rangep()->msbp()->castConst() - || !adtypep->rangep()->lsbp()->castConst())) + && (!VN_IS(adtypep->rangep()->msbp(), Const) + || !VN_IS(adtypep->rangep()->lsbp(), Const))) nodep->v3fatalSrc("Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep) fromRange = adtypep->declRange(); } else { @@ -123,10 +123,10 @@ private: // have to deal with signed math and related 32bit sign extension problems if (rhs == 0) { return lhsp; - } else if (lhsp->castConst()) { + } else if (VN_IS(lhsp, Const)) { // Optional vs just making add/sub below, but saves constification some work V3Number num (lhsp->fileline(), lhsp->width()); - num.opSub(lhsp->castConst()->num(), V3Number(lhsp->fileline(), 32, rhs)); + num.opSub(VN_CAST(lhsp, Const)->num(), V3Number(lhsp->fileline(), 32, rhs)); num.isSigned(lhsp->isSigned()); AstNode* newp = new AstConst(lhsp->fileline(), num); return newp; @@ -207,7 +207,7 @@ private: AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; UINFO(6," ddtypep "<castUnpackArrayDType()) { + if (AstUnpackArrayDType* adtypep = VN_CAST(ddtypep, UnpackArrayDType)) { // SELBIT(array, index) -> ARRAYSEL(array, index) AstNode* subp = rhsp; if (fromRange.lo()!=0 || fromRange.hi()<0) { @@ -219,7 +219,7 @@ private: if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } - else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) { + else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex) AstNode* subp = rhsp; if (fromRange.lo()!=0 || fromRange.hi()<0) { @@ -245,7 +245,7 @@ private: if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } - else if (ddtypep->castBasicDType()) { + else if (VN_IS(ddtypep, BasicDType)) { // SELBIT(range, index) -> SEL(array, index, 1) AstSel* newp = new AstSel (nodep->fileline(), fromp, @@ -257,7 +257,7 @@ private: if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } - else if (ddtypep->castNodeClassDType()) { // It's packed, so a bit from the packed struct + else if (VN_IS(ddtypep, NodeClassDType)) { // It's packed, so a bit from the packed struct // SELBIT(range, index) -> SEL(array, index, 1) AstSel* newp = new AstSel (nodep->fileline(), fromp, @@ -292,13 +292,13 @@ private: AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* msbp = nodep->rhsp()->unlinkFrBack(); AstNode* lsbp = nodep->thsp()->unlinkFrBack(); - vlsint32_t msb = msbp->castConst()->toSInt(); - vlsint32_t lsb = lsbp->castConst()->toSInt(); + vlsint32_t msb = VN_CAST(msbp, Const)->toSInt(); + vlsint32_t lsb = VN_CAST(lsbp, Const)->toSInt(); vlsint32_t elem = (msb>lsb) ? (msb-lsb+1) : (lsb-msb+1); FromData fromdata = fromDataForArray(nodep, fromp, false); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; - if (ddtypep->castUnpackArrayDType()) { + if (VN_IS(ddtypep, UnpackArrayDType)) { // Slice extraction if (fromRange.elements() == elem && fromRange.lo() == lsb) { // Extracting whole of original array @@ -313,7 +313,7 @@ private: nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } } - else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) { + else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELEXTRACT(array, msb, lsb) -> SEL(array, lsb*width-of-subindex, width-of-subindex*(msb-lsb)) if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0) adtypep->v3fatalSrc("Array extraction with width miscomputed " @@ -339,7 +339,7 @@ private: if (newp->widthMin()!=(int)newp->widthConst()) nodep->v3fatalSrc("Width mismatch"); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } - else if (ddtypep->castBasicDType()) { + else if (VN_IS(ddtypep, BasicDType)) { if (fromRange.littleEndian()) { // Below code assumes big bit endian; just works out if we swap int x = msb; msb = lsb; lsb = x; @@ -359,7 +359,7 @@ private: //if (debug()>=9) newp->dumpTree(cout,"--SELEXnew: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } - else if (ddtypep->castNodeClassDType()) { + else if (VN_IS(ddtypep, NodeClassDType)) { // Classes aren't little endian if (lsb > msb) { nodep->v3error("["<lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* widthp = nodep->thsp()->unlinkFrBack(); - int width = widthp->castConst()->toSInt(); + int width = VN_CAST(widthp, Const)->toSInt(); if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "<prettyName()); if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<prettyName()); FromData fromdata = fromDataForArray(nodep, fromp, width!=1); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; - if (ddtypep->castBasicDType() - || ddtypep->castPackArrayDType() - || (ddtypep->castNodeClassDType() - && ddtypep->castNodeClassDType()->packedUnsup())) { + if (VN_IS(ddtypep, BasicDType) + || VN_IS(ddtypep, PackArrayDType) + || (VN_IS(ddtypep, NodeClassDType) + && VN_CAST(ddtypep, NodeClassDType)->packedUnsup())) { int elwidth = 1; AstNode* newwidthp = widthp; - if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) { + if (const AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { elwidth = adtypep->width() / fromRange.elements(); newwidthp = new AstConst (nodep->fileline(),AstConst::Unsized32(), width * elwidth); } AstNode* newlsbp = NULL; - if (nodep->castSelPlus()) { + if (VN_IS(nodep, SelPlus)) { if (fromRange.littleEndian()) { // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width) newlsbp = newSubNeg((fromRange.hi()-width+1), rhsp); @@ -427,7 +427,7 @@ private: // SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width) newlsbp = newSubNeg(rhsp, fromRange.lo()); } - } else if (nodep->castSelMinus()) { + } else if (VN_IS(nodep, SelMinus)) { if (fromRange.littleEndian()) { // SELMINUS(from,msb,width) -> SEL(from, msb-[bit]) newlsbp = newSubNeg(fromRange.hi(), rhsp); diff --git a/src/astgen b/src/astgen old mode 100755 new mode 100644 index 5fe7e481c..5b0d61793 --- a/src/astgen +++ b/src/astgen @@ -237,27 +237,45 @@ sub write_visitor { sub write_intf { my $fh = open_file(@_); + + print $fh "\n"; + print $fh " // These for use by VN_IS macro only\n"; foreach my $type (sort (keys %Classes)) { - next if $type eq "Node"; # Special, just a return (this); - printf $fh " Ast%-16s cast${type}();\n" - ,$type."*"; + print $fh " static bool privateIs",$type,"(const AstNode* nodep);\n"; } + + print $fh "\n"; + print $fh " // These for use by VN_CAST macro only\n"; + foreach my $type (sort (keys %Classes)) { + print $fh " static Ast",$type,"* privateCast",$type,"(AstNode* nodep);\n"; + } + foreach my $type (sort (keys %Classes)) { + print $fh " static const Ast",$type,"* privateConstCast",$type,"(const AstNode* nodep);\n"; + } + $fh->close(); } sub write_impl { my $fh = open_file(@_); + + print $fh "\n"; + print $fh " // These for use by VN_IS macro only\n"; foreach my $type (sort (keys %Classes)) { - next if $type eq "Node"; # Special, just a return (this); - # For performance, prefer static_cast where we can if (children_of($type)) { - printf $fh "inline Ast%-16s AstNode::cast${type}() { return (dynamic_cast(this)); }\n" - ,$type."*"; + print $fh "inline bool AstNode::privateIs",$type,"(const AstNode* nodep) { return (bool)(dynamic_cast(nodep)); }\n"; } else { - printf $fh "inline Ast%-16s AstNode::cast${type}() { return (this && this->type() == AstType::at${type}) ? static_cast(this) : NULL; }\n" - ,$type."*"; + print $fh "inline bool AstNode::privateIs",$type,"(const AstNode* nodep) { return nodep && nodep->type() == AstType::at",$type,"; }\n"; } } + + foreach my $type (sort (keys %Classes)) { + print $fh "inline Ast",$type,"* AstNode::privateCast",$type,"(AstNode* nodep) { return dynamic_cast(nodep); }\n"; + } + foreach my $type (sort (keys %Classes)) { + print $fh "inline const Ast",$type,"* AstNode::privateConstCast",$type,"(const AstNode* nodep) { return dynamic_cast(nodep); }\n"; + } + $fh->close(); } @@ -405,12 +423,14 @@ sub tree_line { next if $subnode =~ /^\$([a-z0-9]+)$/gi; # "$lhs" is just a comment that this op has a lhs $mif .= " && " if $mif; my $subnodeif = $subnode; + $subnodeif =~ s/\$([a-zA-Z0-9]+)\.cast([A-Z][A-Za-z0-9]+)$/VN_IS(nodep->$1(),$2)/g; $subnodeif =~ s/\$([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)$/nodep->$1()->$2()/g; $subnodeif = add_nodep($subnodeif); $mif .= $subnodeif; } my $exec_func = treeop_exec_func($self, $to); + while ($exec_func =~ s/([-()a-zA-Z0-9_>]+)->cast([A-Z][A-Za-z0-9]+)\(\)/VN_CAST($1,$2)/) {} $self->{treeop}{$type} ||= []; my $n = $#{$self->{treeop}{$type}} + 1; @@ -601,7 +621,7 @@ sub tree_base { " nodep->lhsp()->iterateAndNext(*this);\n", @out_for_type_sc); $self->print(" nodep->rhsp()->iterateAndNext(*this);\n", - " AstNodeTriop *tnp = nodep->castNodeTriop();\n", + " AstNodeTriop *tnp = VN_CAST(nodep, NodeTriop);\n", " if (tnp && tnp->thsp()) tnp->thsp()->iterateAndNext(*this);\n", @out_for_type, " }\n") if ($out_for_type[0]); diff --git a/src/verilog.l b/src/verilog.l index 8b9ea5540..72ae21907 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -1073,11 +1073,11 @@ void V3ParseImp::lexToken() { AstNode* scp = foundp->nodep(); yylval.scp = scp; UINFO(7," lexToken: Found "<castTypedef()) token = yaID__aTYPE; - else if (scp->castTypedefFwd()) token = yaID__aTYPE; - else if (scp->castPackage()) token = yaID__aPACKAGE; - //UNSUP else if (scp->castClass()) token = yaID__aCLASS; - //UNSUP else if (scp->castCoverGroup()) token = yaID__aCOVERGROUP; + if (VN_IS(scp, Typedef)) token = yaID__aTYPE; + else if (VN_IS(scp, TypedefFwd)) token = yaID__aTYPE; + else if (VN_IS(scp, Package)) token = yaID__aPACKAGE; + //UNSUP else if (VN_IS(scp, NodeClass)) token = yaID__aCLASS; + //UNSUP else if (VN_IS(scp, CoverGroup)) token = yaID__aCOVERGROUP; else token = yaID__ETC; } else { // Not found yylval.scp = NULL; diff --git a/src/verilog.y b/src/verilog.y index 31a374b14..f9751bf66 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -128,7 +128,7 @@ public: pkgp = PARSEP->rootp()->dollarUnitPkgAddp(); SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global } else { - pkgp = symp->nodep()->castPackage(); + pkgp = VN_CAST(symp->nodep(), Package); } return pkgp; } @@ -145,12 +145,12 @@ public: rangearraysp = rangesp; // Already a range; everything is an array } else { AstNodeRange* finalp = rangesp; - while (finalp->nextp()) finalp=finalp->nextp()->castNodeRange(); + while (finalp->nextp()) finalp = VN_CAST(finalp->nextp(), Range); if (finalp != rangesp) { finalp->unlinkFrBack(); rangearraysp = rangesp; } - if (AstRange* finalRangep = finalp->castRange()) { // not an UnsizedRange + if (AstRange* finalRangep = VN_CAST(finalp, Range)) { // not an UnsizedRange if (dtypep->implicit()) { // It's no longer implicit but a real logic type AstBasicDType* newp = new AstBasicDType(dtypep->fileline(), AstBasicDTypeKwd::LOGIC, @@ -749,7 +749,7 @@ package_import_itemList: package_import_item: // ==IEEE: package_import_item yaID__aPACKAGE yP_COLONCOLON package_import_itemObj - { $$ = new AstPackageImport($1, $1->castPackage(), *$3); + { $$ = new AstPackageImport($1, VN_CAST($1, Package), *$3); SYMP->importItem($1,*$3); } ; @@ -770,7 +770,7 @@ package_export_itemList: package_export_item: // ==IEEE: package_export_item yaID__aPACKAGE yP_COLONCOLON package_import_itemObj - { $$ = new AstPackageExport($1, $1->castPackage(), *$3); + { $$ = new AstPackageExport($1, VN_CAST($1, Package), *$3); SYMP->exportItem($1,*$3); } ; @@ -1497,7 +1497,7 @@ variable_dimensionListE: // IEEE: variable_dimension + empty variable_dimensionList: // IEEE: variable_dimension + empty variable_dimension { $$ = $1; } - | variable_dimensionList variable_dimension { $$ = $1->addNext($2)->castNodeRange(); } + | variable_dimensionList variable_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); } ; variable_dimension: // ==IEEE: variable_dimension @@ -1836,7 +1836,7 @@ conditional_generate_construct: // ==IEEE: conditional_generate_construct loop_generate_construct: // ==IEEE: loop_generate_construct yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' ~c~generate_block_or_null { // Convert BEGIN(...) to BEGIN(GENFOR(...)), as we need the BEGIN to hide the local genvar - AstBegin* lowerBegp = $9->castBegin(); + AstBegin* lowerBegp = VN_CAST($9, Begin); if ($9 && !lowerBegp) $9->v3fatalSrc("Child of GENFOR should have been begin"); if (!lowerBegp) lowerBegp = new AstBegin($1,"genblk",NULL,true); // Empty body AstNode* lowerNoBegp = lowerBegp->stmtsp(); @@ -1845,7 +1845,7 @@ loop_generate_construct: // ==IEEE: loop_generate_construct AstBegin* blkp = new AstBegin($1,lowerBegp->name(),NULL,true); // V3LinkDot detects BEGIN(GENFOR(...)) as a special case AstNode* initp = $3; AstNode* varp = $3; - if (varp->castVar()) { // Genvar + if (VN_IS(varp, Var)) { // Genvar initp = varp->nextp(); initp->unlinkFrBackWithNext(); // Detach 2nd from varp, make 1st init blkp->addStmtsp(varp); @@ -2009,7 +2009,7 @@ packed_dimensionListE: // IEEE: [{ packed_dimension }] packed_dimensionList: // IEEE: { packed_dimension } packed_dimension { $$ = $1; } - | packed_dimensionList packed_dimension { $$ = $1->addNext($2)->castNodeRange(); } + | packed_dimensionList packed_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); } ; packed_dimension: // ==IEEE: packed_dimension @@ -2116,12 +2116,12 @@ cellpinList: cellparamItList: // IEEE: list_of_parameter_assignmente cellparamItemE { $$ = $1; } - | cellparamItList ',' cellparamItemE { $$ = $1->addNextNull($3)->castPin(); } + | cellparamItList ',' cellparamItemE { $$ = VN_CAST($1->addNextNull($3), Pin); } ; cellpinItList: // IEEE: list_of_port_connections cellpinItemE { $$ = $1; } - | cellpinItList ',' cellpinItemE { $$ = $1->addNextNull($3)->castPin(); } + | cellpinItList ',' cellpinItemE { $$ = VN_CAST($1->addNextNull($3), Pin); } ; cellparamItemE: // IEEE: named_parameter_assignment + empty @@ -2194,8 +2194,8 @@ event_control: // ==IEEE: event_control event_expression: // IEEE: event_expression - split over several senitem { $$ = $1; } - | event_expression yOR senitem { $$ = $1->addNextNull($3)->castNodeSenItem(); } - | event_expression ',' senitem { $$ = $1->addNextNull($3)->castNodeSenItem(); } /* Verilog 2001 */ + | event_expression yOR senitem { $$ = VN_CAST($1->addNextNull($3), NodeSenItem); } + | event_expression ',' senitem { $$ = VN_CAST($1->addNextNull($3), NodeSenItem); } /* Verilog 2001 */ ; senitem: // IEEE: part of event_expression, non-'OR' ',' terms @@ -2646,7 +2646,7 @@ system_t_call: // IEEE: system_tf_call (as task) | yaD_IGNORE '(' exprList ')' { $$ = new AstSysIgnore($1,$3); } // | yaD_DPI parenE { $$ = new AstTaskRef($1,*$1,NULL); } - | yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList($$->castTaskRef()); } + | yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); } | yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); } @@ -2691,7 +2691,7 @@ system_f_call: // IEEE: system_tf_call (as func) | yaD_IGNORE '(' exprList ')' { $$ = new AstConst($2,V3Number($2,"'b0")); } // Unsized 0 // | yaD_DPI parenE { $$ = new AstFuncRef($1,*$1,NULL); } - | yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList($$->castFuncRef()); } + | yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, FuncRef)); } // | yD_BITS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); } | yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); } @@ -2772,7 +2772,7 @@ exprOrDataType: // expr | data_type: combined to prevent conflicts list_of_argumentsE: // IEEE: [list_of_arguments] argsDottedList { $$ = $1; } - | argsExprListE { if ($1->castArg() && $1->castArg()->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()' + | argsExprListE { if (VN_IS($1, Arg) && VN_CAST($1, Arg)->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()' /*cont*/ else $$ = $1; } | argsExprListE ',' argsDottedList { $$ = $1->addNextNull($3); } ; @@ -3728,7 +3728,7 @@ ps_id_etc: // package_scope + general id ps_type: // IEEE: ps_parameter_identifier | ps_type_identifier // Even though we looked up the type and have a AstNode* to it, // we can't fully resolve it because it may have been just a forward definition. - package_scopeIdFollowsE yaID__aTYPE { $$ = new AstRefDType($2, *$2); $$->castRefDType()->packagep($1); } + package_scopeIdFollowsE yaID__aTYPE { $$ = new AstRefDType($2, *$2); VN_CAST($$, RefDType)->packagep($1); } // // Simplify typing - from ps_covergroup_identifier //UNSUP package_scopeIdFollowsE yaID__aCOVERGROUP { $$=$1; $$=$1+$2; } ; @@ -3748,7 +3748,7 @@ package_scopeIdFollows: // IEEE: package_scope yD_UNIT { SYMP->nextId(PARSEP->rootp()); } /*cont*/ yP_COLONCOLON { $$ = GRAMMARP->unitPackage($1); } | yaID__aPACKAGE { SYMP->nextId($1); } - /*cont*/ yP_COLONCOLON { $$ = $1->castPackage(); } + /*cont*/ yP_COLONCOLON { $$ = VN_CAST($1, Package); } //UNSUP yLOCAL__COLONCOLON { PARSEP->symTableNextId($1); } //UNSUP /*cont*/ yP_COLONCOLON { UNSUP } ; @@ -3848,26 +3848,26 @@ AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int v AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { // Remove any UnsizedRange's from list for (AstNodeRange* nodep = nrangep, *nextp; nodep; nodep=nextp) { - nextp = nrangep->nextp()->castNodeRange(); - if (!nodep->castRange()) { + nextp = VN_CAST(nrangep->nextp(), NodeRange); + if (!VN_IS(nodep, Range)) { nodep->v3error("Unsupported or syntax error: Unsized range in cell or other declaration"); nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep); } } - return nrangep->castRange(); + return VN_CAST(nrangep, Range); } AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nrangep, bool isPacked) { // Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE) AstNodeDType* arrayp = basep; if (nrangep) { // Maybe no range - return unmodified base type - while (nrangep->nextp()) nrangep = nrangep->nextp()->castNodeRange(); + while (nrangep->nextp()) nrangep = VN_CAST(nrangep->nextp(), NodeRange); while (nrangep) { - AstNodeRange* prevp = nrangep->backp()->castNodeRange(); + AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange); if (prevp) nrangep->unlinkFrBack(); - AstRange* rangep = nrangep->castRange(); + AstRange* rangep = VN_CAST(nrangep, Range); if (!rangep) { - if (!nrangep->castUnsizedRange()) nrangep->v3fatalSrc("Expected range or unsized range"); + if (!VN_IS(nrangep, UnsizedRange)) nrangep->v3fatalSrc("Expected range or unsized range"); arrayp = new AstUnsizedArrayDType(nrangep->fileline(), VFlagChildDType(), arrayp); } else if (isPacked) { arrayp = new AstPackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep); @@ -3922,7 +3922,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeR if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) { nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); } - if (dtypep->castParseTypeDType()) { + if (VN_IS(dtypep, ParseTypeDType)) { // Parser needs to know what is a type AstNode* newp = new AstTypedefFwd(fileline, name); nodep->addNext(newp);