From 8548ecfdacb5872a75b1bb9242ed434ae48e3d68 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 6 Jul 2019 12:57:50 -0400 Subject: [PATCH] Internals: Add UASSERT_OBJ macro to replace hand-done ifs. No functional change intended. This makes it easier to filter out correctly zero code-coverage lines. --- src/V3Active.cpp | 14 ++-- src/V3ActiveTop.cpp | 12 ++- src/V3Assert.cpp | 7 +- src/V3Ast.cpp | 62 ++++++++------- src/V3AstNodes.cpp | 12 +-- src/V3AstNodes.h | 2 +- src/V3Begin.cpp | 2 +- src/V3Broken.cpp | 68 +++++++---------- src/V3Case.cpp | 2 +- src/V3Cdc.cpp | 4 +- src/V3Changed.cpp | 6 +- src/V3Clean.cpp | 3 +- src/V3ClkGater.cpp | 16 ++-- src/V3Clock.cpp | 15 ++-- src/V3Combine.cpp | 5 +- src/V3Const.cpp | 29 +++---- src/V3CoverageJoin.cpp | 2 +- src/V3Delayed.cpp | 22 +++--- src/V3Depth.cpp | 4 +- src/V3Descope.cpp | 8 +- src/V3EmitC.cpp | 64 ++++++++-------- src/V3EmitCSyms.cpp | 2 +- src/V3EmitV.cpp | 16 ++-- src/V3Error.h | 18 +++-- src/V3Expand.cpp | 22 +++--- src/V3Gate.cpp | 33 ++++---- src/V3GenClk.cpp | 10 +-- src/V3GraphAlg.cpp | 2 +- src/V3GraphDfa.cpp | 7 +- src/V3GraphPathChecker.cpp | 5 +- src/V3GraphStream.h | 14 ++-- src/V3Hashed.cpp | 23 +++--- src/V3Inline.cpp | 14 ++-- src/V3Inst.cpp | 10 +-- src/V3InstrCount.cpp | 22 ++---- src/V3Life.cpp | 6 +- src/V3LifePost.cpp | 19 ++--- src/V3LinkCells.cpp | 2 +- src/V3LinkDot.cpp | 150 ++++++++++++++++++------------------- src/V3LinkJump.cpp | 8 +- src/V3LinkLevel.cpp | 4 +- src/V3LinkParse.cpp | 27 +++---- src/V3LinkResolve.cpp | 6 +- src/V3Localize.cpp | 2 +- src/V3Order.cpp | 40 +++++----- src/V3Param.cpp | 21 +++--- src/V3ParseGrammar.cpp | 5 +- src/V3ParseSym.h | 18 ++--- src/V3Partition.cpp | 60 +++++++-------- src/V3Reloop.cpp | 4 +- src/V3Scope.cpp | 14 ++-- src/V3Simulate.h | 32 ++++---- src/V3Slice.cpp | 7 +- src/V3Split.cpp | 15 ++-- src/V3Subst.cpp | 4 +- src/V3Table.cpp | 15 ++-- src/V3Task.cpp | 45 +++++------ src/V3Trace.cpp | 33 ++++---- src/V3TraceDecl.cpp | 2 +- src/V3Tristate.cpp | 9 ++- src/V3Unknown.cpp | 6 +- src/V3Unroll.cpp | 12 ++- src/V3Width.cpp | 122 +++++++++++++++++------------- src/V3WidthCommit.h | 2 +- src/V3WidthSel.cpp | 30 ++++---- src/verilog.y | 2 +- 66 files changed, 626 insertions(+), 653 deletions(-) diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 0c4118a3f..aeec064a5 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -66,7 +66,7 @@ private: // METHODS void addActive(AstActive* nodep) { - if (!m_scopep) nodep->v3fatalSrc("NULL scope"); + UASSERT_OBJ(m_scopep, nodep, "NULL scope"); m_scopep->addActivep(nodep); } // VISITORS @@ -314,7 +314,8 @@ private: && 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."); + UASSERT_OBJ(!oldsensesp->sensesp()->nextp(), nodep, + "Never senitem should be alone, else the never should be eliminated."); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); return; } @@ -391,11 +392,10 @@ private: } virtual void visit(AstSenGate* nodep) { AstSenItem* subitemp = nodep->sensesp(); - if (subitemp->edgeType() != AstEdgeType::ET_ANYEDGE - && subitemp->edgeType() != AstEdgeType::ET_POSEDGE - && subitemp->edgeType() != AstEdgeType::ET_NEGEDGE) { - nodep->v3fatalSrc("Strange activity type under SenGate"); - } + UASSERT_OBJ(subitemp->edgeType() == AstEdgeType::ET_ANYEDGE + || subitemp->edgeType() == AstEdgeType::ET_POSEDGE + || subitemp->edgeType() == AstEdgeType::ET_NEGEDGE, + nodep, "Strange activity type under SenGate"); iterateChildren(nodep); } virtual void visit(AstSenItem* nodep) { diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index f567bb4e6..f6d175d94 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -72,14 +72,13 @@ private: UINFO(4," ACTIVE "<sensesp(); - if (!sensesp) nodep->v3fatalSrc("NULL"); + UASSERT_OBJ(sensesp, nodep, "NULL"); if (sensesp->sensesp() && VN_IS(sensesp->sensesp(), SenItem) && VN_CAST(sensesp->sensesp(), SenItem)->isNever()) { // Never executing. Kill it. - if (VL_UNCOVERABLE(sensesp->sensesp()->nextp())) { - nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated."); - } + UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep, + "Never senitem should be alone, else the never should be eliminated."); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); return; } @@ -101,9 +100,8 @@ private: // Move the active's contents to the other active UINFO(4," merge active "<sensesStorep()) { - if (VL_UNCOVERABLE(sensesp != nodep->sensesStorep())) { - nodep->v3fatalSrc("sensesStore should have been deleted earlier if different"); - } + UASSERT_OBJ(sensesp == nodep->sensesStorep(), nodep, + "sensesStore should have been deleted earlier if different"); sensesp->unlinkFrBack(); // There may be other references to same sense tree, // we'll be removing all references when we get to them, diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 543c2c90a..b2b7ad401 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -120,7 +120,7 @@ private: } else { // V3Coverage assigned us a bucket to increment. AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc); - if (!covincp) snodep->v3fatalSrc("Missing AstCoverInc under assertion"); + UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion"); covincp->unlinkFrBack(); if (message!="") covincp->declp()->comment(message); bodysp = covincp; @@ -317,10 +317,11 @@ private: iterateChildren(nodep); uint32_t ticks = 1; if (nodep->ticksp()) { - if (!VN_IS(nodep->ticksp(), Const)) nodep->v3fatalSrc("Expected constant ticks, checked in V3Width"); + UASSERT_OBJ(VN_IS(nodep->ticksp(), Const), nodep, + "Expected constant ticks, checked in V3Width"); ticks = VN_CAST(nodep->ticksp(), Const)->toUInt(); } - if (ticks<1) nodep->v3fatalSrc("0 tick should have been checked in V3Width"); + UASSERT_OBJ(ticks>=1, nodep, "0 tick should have been checked in V3Width"); AstNode* inp = nodep->exprp()->unlinkFrBack(); AstVar* invarp = NULL; AstSenTree* sentreep = nodep->sentreep(); sentreep->unlinkFrBack(); diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 13635bc14..e62def7a7 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -248,7 +248,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next) AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { // Add to m_nextp, returns this - UDEBUGONLY(if (!newp) nodep->v3fatalSrc("Null item passed to addNext");); + UDEBUGONLY(UASSERT_OBJ(newp, nodep, "Null item passed to addNext");); nodep->debugTreeChange("-addNextThs: ", __LINE__, false); newp->debugTreeChange("-addNextNew: ", __LINE__, true); if (!nodep) { // verilog.y and lots of other places assume this @@ -259,7 +259,8 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { if (oldtailp->m_nextp) { if (oldtailp->m_headtailp) { oldtailp = oldtailp->m_headtailp; // This=beginning of list, jump to end - UDEBUGONLY(if (oldtailp->m_nextp) nodep->v3fatalSrc("Node had next, but headtail says it shouldn't");); + UDEBUGONLY(UASSERT_OBJ(!oldtailp->m_nextp, nodep, + "Node had next, but headtail says it shouldn't");); } else { // Though inefficent, we are occasionally passed a addNext in the middle of a list. while (oldtailp->m_nextp != NULL) oldtailp = oldtailp->m_nextp; @@ -337,9 +338,9 @@ void AstNode::addNextHere(AstNode* newp) { void AstNode::setOp1p(AstNode* newp) { UASSERT(newp, "Null item passed to setOp1p"); - UDEBUGONLY(if (m_op1p) this->v3fatalSrc("Adding to non-empty, non-list op1");); - UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node");); - UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1");); + UDEBUGONLY(UASSERT_OBJ(!m_op1p, this, "Adding to non-empty, non-list op1");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_backp, newp, "Adding already linked node");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_nextp, newp, "Adding list to non-list op1");); this->debugTreeChange("-setOp1pThs: ", __LINE__, false); newp->debugTreeChange("-setOp1pNew: ", __LINE__, true); m_op1p = newp; @@ -350,9 +351,9 @@ void AstNode::setOp1p(AstNode* newp) { void AstNode::setOp2p(AstNode* newp) { UASSERT(newp, "Null item passed to setOp2p"); - UDEBUGONLY(if (m_op2p) this->v3fatalSrc("Adding to non-empty, non-list op2");); - UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node");); - UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2");); + UDEBUGONLY(UASSERT_OBJ(!m_op2p, this, "Adding to non-empty, non-list op2");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_backp, newp, "Adding already linked node");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_nextp, newp, "Adding list to non-list op2");); this->debugTreeChange("-setOp2pThs: ", __LINE__, false); newp->debugTreeChange("-setOp2pNew: ", __LINE__, true); m_op2p = newp; @@ -363,9 +364,9 @@ void AstNode::setOp2p(AstNode* newp) { void AstNode::setOp3p(AstNode* newp) { UASSERT(newp, "Null item passed to setOp3p"); - UDEBUGONLY(if (m_op3p) this->v3fatalSrc("Adding to non-empty, non-list op3");); - UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node");); - UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3");); + UDEBUGONLY(UASSERT_OBJ(!m_op3p, this, "Adding to non-empty, non-list op3");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_backp, newp, "Adding already linked node");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_nextp, newp, "Adding list to non-list op3");); this->debugTreeChange("-setOp3pThs: ", __LINE__, false); newp->debugTreeChange("-setOp3pNew: ", __LINE__, true); m_op3p = newp; @@ -376,9 +377,9 @@ void AstNode::setOp3p(AstNode* newp) { void AstNode::setOp4p(AstNode* newp) { UASSERT(newp, "Null item passed to setOp4p"); - UDEBUGONLY(if (m_op4p) this->v3fatalSrc("Adding to non-empty, non-list op4");); - UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node");); - UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4");); + UDEBUGONLY(UASSERT_OBJ(!m_op4p, this, "Adding to non-empty, non-list op4");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_backp, newp, "Adding already linked node");); + UDEBUGONLY(UASSERT_OBJ(!newp->m_nextp, newp, "Adding list to non-list op4");); this->debugTreeChange("-setOp4pThs: ", __LINE__, false); newp->debugTreeChange("-setOp4pNew: ", __LINE__, true); m_op4p = newp; @@ -580,9 +581,11 @@ void AstNode::relinkOneLink(AstNode*& pointpr, // Ref to pointer that gets set // Insert the whole old list following the new node's list. // Thus a unlink without next, followed by relink, gives the same list. AstNode* newlistlastp = newp->m_headtailp; - if (newlistlastp->m_nextp && newlistlastp!=newp) newp->v3fatalSrc("Headtailp tail isn't at the tail"); + UASSERT_OBJ(!(newlistlastp->m_nextp && newlistlastp!=newp), newp, + "Headtailp tail isn't at the tail"); AstNode* oldlistlastp = pointpr->m_headtailp; - if (oldlistlastp->m_nextp && oldlistlastp!=pointpr) newp->v3fatalSrc("Old headtailp tail isn't at the tail"); + UASSERT_OBJ(!(oldlistlastp->m_nextp && oldlistlastp!=pointpr), newp, + "Old headtailp tail isn't at the tail"); // Next links newlistlastp->m_nextp = pointpr; pointpr->m_backp = newlistlastp; @@ -772,14 +775,15 @@ void AstNode::iterateAndNext(AstNVisitor& v) { // there's no lower level reason yet though the back must exist. AstNode* nodep = this; #ifdef VL_DEBUG // Otherwise too hot of a function for debug - if (VL_UNCOVERABLE(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back"); + UASSERT_OBJ(!(nodep && !nodep->m_backp), nodep, + "iterateAndNext node has no back"); #endif if (nodep) ASTNODE_PREFETCH(nodep->m_nextp); while (nodep) { // effectively: if (!this) return; // Callers rely on this if (nodep->m_nextp) ASTNODE_PREFETCH(nodep->m_nextp->m_nextp); AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited // Desirable check, but many places where multiple iterations are OK - //if (VL_UNCOVERABLE(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits"); + // UASSERT_OBJ(!niterp->m_iterpp, niterp, "IterateAndNext under iterateAndNext may miss edits"); // Optimization note: Doing PREFETCH_RW on m_iterpp is a net even // cppcheck-suppress nullPointer niterp->m_iterpp = &niterp; @@ -856,7 +860,7 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) { else if (this->m_backp->m_op3p == this) nextnodepp = &(this->m_backp->m_op3p); else if (this->m_backp->m_op4p == this) nextnodepp = &(this->m_backp->m_op4p); else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp); - if (!nextnodepp) this->v3fatalSrc("Node's back doesn't point to forward to node itself"); + UASSERT_OBJ(nextnodepp, this, "Node's back doesn't point to forward to node itself"); { nodep->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced } @@ -934,13 +938,11 @@ V3Hash::V3Hash(const string& name) { void AstNode::checkTreeIter(AstNode* backp) { // private: Check a tree and children - if (backp != this->backp()) { - this->v3fatalSrc("Back node inconsistent"); - } + UASSERT_OBJ(backp == this->backp(), this, "Back node inconsistent"); 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"); + UASSERT_OBJ(!(op1p()||op2p()||op3p()||op4p()), this, + "Terminal operation with non-terminals"); } if (m_op1p) m_op1p->checkTreeIterList(this); if (m_op2p) m_op2p->checkTreeIterList(this); @@ -955,12 +957,13 @@ void AstNode::checkTreeIterList(AstNode* backp) { AstNode* tailp = this; for (AstNode* nodep=headp; nodep; nodep=nodep->nextp()) { nodep->checkTreeIter(backp); - if (headp!=this && nextp()) this->v3fatalSrc("Headtailp should be null in middle of lists"); + UASSERT_OBJ(headp==this || !nextp(), this, + "Headtailp should be null in middle of lists"); tailp = nodep; backp = nodep; } - if (headp->m_headtailp != tailp) headp->v3fatalSrc("Tail in headtailp is inconsistent"); - if (tailp->m_headtailp != headp) tailp->v3fatalSrc("Head in headtailp is inconsistent"); + UASSERT_OBJ(headp->m_headtailp == tailp, headp, "Tail in headtailp is inconsistent"); + UASSERT_OBJ(tailp->m_headtailp == headp, tailp, "Head in headtailp is inconsistent"); } void AstNode::checkTree() { @@ -1096,12 +1099,13 @@ void AstNode::v3errorEnd(std::ostringstream& str) const { // Data type conversion void AstNode::dtypeChgSigned(bool flag) { - if (!dtypep()) this->v3fatalSrc("No dtype when changing to (un)signed"); + UASSERT_OBJ(dtypep(), this, "No dtype when changing to (un)signed"); dtypeChgWidthSigned(dtypep()->width(), dtypep()->widthMin(), flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); } void AstNode::dtypeChgWidth(int width, int widthMin) { - if (!dtypep()) this->v3fatalSrc("No dtype when changing width"); // Use ChgWidthSigned(...UNSIGNED) otherwise + UASSERT_OBJ(dtypep(), this, + "No dtype when changing width"); // Use ChgWidthSigned(...UNSIGNED) otherwise dtypeChgWidthSigned(width, widthMin, dtypep()->numeric()); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 2883999ea..83a2024fc 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -642,28 +642,28 @@ string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const { } bool AstSenTree::hasClocked() const { - if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); + UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); 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"); + UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); 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"); + UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); 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"); + UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isCombo()) return true; } @@ -764,12 +764,12 @@ AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) { // Special walking tree inserters void AstNode::addBeforeStmt(AstNode* newp, AstNode*) { - if (!backp()) newp->v3fatalSrc("Can't find current statement to addBeforeStmt"); + UASSERT_OBJ(backp(), newp, "Can't find current statement to addBeforeStmt"); // Look up; virtual call will find where to put it this->backp()->addBeforeStmt(newp, this); } void AstNode::addNextStmt(AstNode* newp, AstNode*) { - if (!backp()) newp->v3fatalSrc("Can't find current statement to addNextStmt"); + UASSERT_OBJ(backp(), newp, "Can't find current statement to addNextStmt"); // Look up; virtual call will find where to put it this->backp()->addNextStmt(newp, this); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 8e589f08a..46a08aac1 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1941,7 +1941,7 @@ public: AstBind(FileLine* fl, const string& name, AstNode* cellsp) : AstNode(fl) , m_name(name) { - if (!VN_IS(cellsp, Cell)) cellsp->v3fatalSrc("Only cells allowed to be bound"); + UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only cells allowed to be bound"); addNOp1p(cellsp); } ASTNODE_NODE_FUNCS(Bind) diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 9389c4358..f39cb48be 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -141,7 +141,7 @@ private: // Remap var names and replace lower Begins iterateAndNextNull(nodep->stmtsp()); - if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier"); + UASSERT_OBJ(!nodep->genforp(), nodep, "GENFORs should have been expanded earlier"); } m_namedScope = oldScope; m_unnamedScope = oldUnnamed; diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index fcec7e9e7..437e62013 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -60,10 +60,9 @@ public: // Called by operator delete on any node - only if VL_LEAK_CHECKS if (debug()>=9) cout<<"-nodeDel: "<second & FLAG_ALLOCATED))) { - reinterpret_cast(nodep) - ->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted"); - } + UASSERT_OBJ(!(iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)), + reinterpret_cast(nodep), + "Deleting AstNode object that was never tracked or already deleted"); if (iter!=s_nodes.end()) s_nodes.erase(iter); } #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4 @@ -74,9 +73,8 @@ public: // Called by operator new on any node - only if VL_LEAK_CHECKS if (debug()>=9) cout<<"-nodeNew: "<second & FLAG_ALLOCATED))) { - nodep->v3fatalSrc("Newing AstNode object that is already allocated"); - } + UASSERT_OBJ(!(iter !=s_nodes.end() && (iter->second & FLAG_ALLOCATED)), + nodep, "Newing AstNode object that is already allocated"); if (iter == s_nodes.end()) { int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2 s_nodes.insert(make_pair(nodep, flags)); @@ -101,14 +99,12 @@ public: nodep->v3fatalSrc("AstNode is in tree, but not allocated"); #endif } else { - if (VL_UNCOVERABLE(!(iter->second & FLAG_ALLOCATED))) { #ifdef VL_LEAK_CHECKS - nodep->v3fatalSrc("AstNode is in tree, but not allocated"); + UASSERT_OBJ(iter->second & FLAG_ALLOCATED, nodep, + "AstNode is in tree, but not allocated"); #endif - } - if (VL_UNCOVERABLE(iter->second & FLAG_IN_TREE)) { - nodep->v3fatalSrc("AstNode is already in tree at another location"); - } + UASSERT_OBJ(!(iter->second & FLAG_IN_TREE), nodep, + "AstNode is already in tree at another location"); } int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0); if (iter == s_nodes.end()) { @@ -230,36 +226,31 @@ public: class BrokenCheckVisitor : public AstNVisitor { private: void checkWidthMin(const AstNode* nodep) { - if (VL_UNCOVERABLE(nodep->width() != nodep->widthMin() - && v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH)) { - nodep->v3fatalSrc("Width != WidthMin"); - } + UASSERT_OBJ(nodep->width() == nodep->widthMin() + || v3Global.widthMinUsage() != VWidthMinUsage::MATCHES_WIDTH, + nodep, "Width != WidthMin"); } void processAndIterate(AstNode* nodep) { BrokenTable::setUnder(nodep, true); const char* whyp = nodep->broken(); - if (VL_UNCOVERABLE(whyp)) { - nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<dtypep()) { - if (VL_UNCOVERABLE(!nodep->dtypep()->brokeExists())) { - nodep->v3fatalSrc("Broken link in node->dtypep() to " - <dtypep())); - } else if (VL_UNCOVERABLE(!VN_IS(nodep->dtypep(), NodeDType))) { - nodep->v3fatalSrc("Non-dtype link in node->dtypep() to " - <dtypep())); - } + UASSERT_OBJ(nodep->dtypep()->brokeExists(), nodep, + "Broken link in node->dtypep() to "<dtypep())); + UASSERT_OBJ(VN_IS(nodep->dtypep(), NodeDType), nodep, + "Non-dtype link in node->dtypep() to "<dtypep())); } if (v3Global.assertDTypesResolved()) { if (nodep->hasDType()) { - if (VL_UNCOVERABLE(!nodep->dtypep())) nodep->v3fatalSrc( - "No dtype on node with hasDType(): "<prettyTypeName()); + UASSERT_OBJ(nodep->dtypep(), nodep, + "No dtype on node with hasDType(): "<prettyTypeName()); } else { - if (VL_UNCOVERABLE(nodep->dtypep())) nodep->v3fatalSrc( - "DType on node without hasDType(): "<prettyTypeName()); + UASSERT_OBJ(!nodep->dtypep(), nodep, + "DType on node without hasDType(): "<prettyTypeName()); } - if (VL_UNCOVERABLE(nodep->getChildDTypep())) nodep->v3fatalSrc( - "childDTypep() non-null on node after should have removed"); + UASSERT_OBJ(!nodep->getChildDTypep(), nodep, + "childDTypep() non-null on node after should have removed"); if (const AstNodeDType* dnodep = VN_CAST(nodep, NodeDType)) checkWidthMin(dnodep); } checkWidthMin(nodep); @@ -268,12 +259,11 @@ private: } virtual void visit(AstNodeAssign* nodep) { processAndIterate(nodep); - if (VL_UNCOVERABLE(v3Global.assertDTypesResolved() - && nodep->brokeLhsMustBeLvalue() - && VN_IS(nodep->lhsp(), NodeVarRef) - && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue())) { - nodep->v3fatalSrc("Assignment LHS is not an lvalue"); - } + UASSERT_OBJ(!(v3Global.assertDTypesResolved() + && nodep->brokeLhsMustBeLvalue() + && VN_IS(nodep->lhsp(), NodeVarRef) + && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()), + nodep, "Assignment LHS is not an lvalue"); } virtual void visit(AstNode* nodep) { processAndIterate(nodep); diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 781f8d793..3b81b9cc9 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -171,7 +171,7 @@ private: for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { //if (debug()>=9) icondp->dumpTree(cout, " caseitem: "); AstConst* iconstp = VN_CAST(icondp, Const); - if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this"); + UASSERT_OBJ(iconstp, nodep, "above 'can't parse' should have caught this"); if (neverItem(nodep, iconstp)) { // X in casez can't ever be executed } else { diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 49c3cbc69..6a571daf2 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -633,9 +633,9 @@ private: } virtual void visit(AstNodeVarRef* nodep) { if (m_scopep) { - if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block"); + UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block"); AstVarScope* varscp = nodep->varScopep(); - if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); + UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); CdcVarVertex* varvertexp = makeVarVertex(varscp); UINFO(5," VARREF to "<addStmtsp(new AstCReturn(m_scopetopp->fileline(), callp)); } else { AstCReturn* returnp = VN_CAST(m_tlChgFuncp->stmtsp(), CReturn); - if (!returnp) m_scopetopp->v3fatalSrc("Lost CReturn in top change function"); + UASSERT_OBJ(returnp, m_scopetopp, "Lost CReturn in top change function"); // This is currently using AstLogOr which will shortcut the // evaluation if any function returns true. This is likely what // we want and is similar to the logic already in use inside @@ -260,8 +260,8 @@ private: AstNode::user1ClearTree(); // Create the change detection function AstScope* scopep = nodep->scopep(); - if (!scopep) nodep->v3fatalSrc("No scope found on top level," - " perhaps you have no statements?"); + UASSERT_OBJ(scopep, nodep, + "No scope found on top level, perhaps you have no statements?"); m_statep->m_scopetopp = scopep; // Create a wrapper change detection function that calls each change detection function diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 9330ff134..7379904d4 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -78,7 +78,8 @@ private: } else { nodep->dtypeChgWidth(width, nodep->widthMin()); AstNodeDType* new_dtypep2 = nodep->dtypep(); - if (new_dtypep2 == old_dtypep) nodep->v3fatalSrc("Dtype didn't change when width changed"); + UASSERT_OBJ(new_dtypep2 != old_dtypep, nodep, + "Dtype didn't change when width changed"); old_dtypep->user3p(new_dtypep2); // Remember for next time } } diff --git a/src/V3ClkGater.cpp b/src/V3ClkGater.cpp index dec3b6126..4cce3f1b5 100644 --- a/src/V3ClkGater.cpp +++ b/src/V3ClkGater.cpp @@ -557,11 +557,10 @@ class GaterVisitor : public GaterBaseVisitor { for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { if (GaterVarVertex* vVxp = dynamic_cast(vertexp)) { - if (!vVxp->inBeginp()) { - // At this point, any variable not linked is an error - // (It should have at least landed under the Head node) - vVxp->nodep()->v3fatalSrc("Variable became stranded in clk gate detection"); - } + // At this point, any variable not linked is an error + // (It should have at least landed under the Head node) + UASSERT_OBJ(vVxp->inBeginp(), vVxp->nodep(), + "Variable became stranded in clk gate detection"); if (!lastVxp || vVxp->sortCmp(lastVxp)) { // Different sources for this new node color++; @@ -612,7 +611,7 @@ class GaterVisitor : public GaterBaseVisitor { // Edges from IFs represent a real IF branch in the equation tree //UINFO(9," ifver "<dotColor()<nodep()->condp()->cloneTree(true); - if (!eqnp) cVxp->nodep()->v3fatalSrc("null condition"); + UASSERT_OBJ(eqnp, cVxp->nodep(), "null condition"); if (cedgep->ifelseFalse()) { eqnp = new AstNot(eqnp->fileline(), eqnp); } @@ -646,7 +645,8 @@ class GaterVisitor : public GaterBaseVisitor { lastExprp = newExprFromGraph(vVxp); } // Mark variable to move - if (vVxp->nodep()->user2p()) vVxp->nodep()->v3fatalSrc("One variable got marked under two gaters"); + UASSERT_OBJ(!vVxp->nodep()->user2p(), vVxp->nodep(), + "One variable got marked under two gaters"); vVxp->nodep()->user2p(lastExprp); m_statBits += vVxp->nodep()->width(); // Moving a wide bus counts more! // There shouldn't be two possibilities we want to @@ -675,7 +675,7 @@ class GaterVisitor : public GaterBaseVisitor { #else // Make a SenGate AstSenItem* oldsenitemsp = VN_CAST(nodep->sensesp()->sensesp(), SenItem); - if (!oldsenitemsp) nodep->v3fatalSrc("SenTree doesn't have any SenItem under it"); + UASSERT_OBJ(oldsenitemsp, nodep, "SenTree doesn't have any SenItem under it"); AstSenTree* sensesp = new AstSenTree(nodep->fileline(), new AstSenGate(nodep->fileline(), diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 45066e4df..162413e7b 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -179,7 +179,7 @@ private: } AstIf* makeActiveIf(AstSenTree* sensesp) { AstNode* senEqnp = createSenseEquation(sensesp->sensesp()); - if (!senEqnp) sensesp->v3fatalSrc("No sense equation, shouldn't be in sequent activation."); + UASSERT_OBJ(senEqnp, sensesp, "No sense equation, shouldn't be in sequent activation."); AstIf* newifp = new AstIf(sensesp->fileline(), senEqnp, NULL, NULL); return (newifp); } @@ -193,7 +193,8 @@ private: UINFO(4," TOPSCOPE "<scopep(); - if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?"); + UASSERT_OBJ(m_scopep, nodep, + "No scope found on top level, perhaps you have no statements?"); //VV***** We reset all user1p() AstNode::user1ClearTree(); // Make top functions @@ -263,7 +264,7 @@ private: m_scopep = nodep; iterateChildren(nodep); if (AstNode* movep = nodep->finalClksp()) { - if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope"); + UASSERT_OBJ(m_topScopep, nodep, "Final clocks under non-top scope"); movep->unlinkFrBackWithNext(); m_evalFuncp->addFinalsp(movep); } @@ -346,13 +347,14 @@ private: if (!m_topScopep || !nodep->stmtsp()) { // Not at the top or empty block... // Only empty blocks should be leftover on the non-top. Killem. - if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active"); + UASSERT_OBJ(!nodep->stmtsp(), nodep, "Non-empty lower active"); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (m_mtaskBodyp) { UINFO(4," TR ACTIVE "<stmtsp()->unlinkFrBackWithNext(); if (nodep->hasClocked()) { - if (nodep->hasInitial()) nodep->v3fatalSrc("Initial block should not have clock sensitivity"); + UASSERT_OBJ(!nodep->hasInitial(), nodep, + "Initial block should not have clock sensitivity"); if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) { UINFO(4," sameSenseTree\n"); } else { @@ -377,7 +379,8 @@ private: AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext(); if (nodep->hasClocked()) { // Remember the latest sensitivity so we can compare it next time - if (nodep->hasInitial()) nodep->v3fatalSrc("Initial block should not have clock sensitivity"); + UASSERT_OBJ(!nodep->hasInitial(), nodep, + "Initial block should not have clock sensitivity"); if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) { UINFO(4," sameSenseTree\n"); } else { diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index 6fd1f1b2c..6b5d270a1 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -96,7 +96,8 @@ public: AstCCall* callp = eqit->second; if (!callp->user3()) { // !already done UINFO(4, " Called "<funcp() != oldfuncp) callp->v3fatalSrc("Call list broken, points to call w/different func"); + UASSERT_OBJ(callp->funcp() == oldfuncp, callp, + "Call list broken, points to call w/different func"); if (newfuncp) { AstCCall* newp = new AstCCall(callp, newfuncp); // Special new AstCCall form above transfers children of callp to newfuncp @@ -236,7 +237,7 @@ private: V3Hash hashval = it->first; AstNode* node1p = it->second; if (!VN_IS(node1p, CFunc)) continue; - if (hashval.isIllegal()) node1p->v3fatalSrc("Illegal (unhashed) nodes"); + UASSERT_OBJ(!hashval.isIllegal(), node1p, "Illegal (unhashed) nodes"); for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) { AstNode* node2p = eqit->second; if (!(eqit->first == hashval)) break; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 9bd55a591..562dd423c 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -589,9 +589,8 @@ private: void replaceNum(AstNode* oldp, const V3Number& num) { // Replace oldp node with a constant set to specified value UASSERT(oldp, "Null old"); - if (VN_IS(oldp, Const) && !VN_CAST(oldp, Const)->num().isFourState()) { - oldp->v3fatalSrc("Already constant??"); - } + UASSERT_OBJ(!(VN_IS(oldp, Const) && !VN_CAST(oldp, Const)->num().isFourState()), + oldp, "Already constant??"); AstNode* newp = new AstConst(oldp->fileline(), num); newp->dtypeFrom(oldp); if (debug()>5) oldp->dumpTree(cout, " const_old: "); @@ -810,7 +809,8 @@ private: int rstart = rselp->lsbConst(); int rwidth = rselp->widthConst(); - if ((rstart + rwidth) != lstart) nodep->v3fatalSrc("tried to merge two selects which are not adjacent"); + UASSERT_OBJ((rstart + rwidth) == lstart, nodep, + "tried to merge two selects which are not adjacent"); AstSel* newselp = new AstSel(lselp->fromp()->fileline(), rselp->fromp()->cloneTree(false), rstart, lwidth+rwidth); UINFO(5, "merged two adjacent sel "<width()-1; int lsb1 = msb2+1; int msb1 = lsb1+lc1p->width()-1; - if (msb1!=(conp->width()-1)) nodep->v3fatalSrc("Width calc mismatch"); + UASSERT_OBJ(msb1 == (conp->width()-1), nodep, "Width calc mismatch"); // Form ranges AstSel* sel1p = new AstSel(conp->fileline(), rhsp, lsb1, msb1-lsb1+1); AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2-lsb2+1); @@ -1081,7 +1081,7 @@ private: newp = AstNode::addNext(newp, asn1ap); newp = AstNode::addNext(newp, asn2ap); } else { - if (!m_modp) nodep->v3fatalSrc("Not under module"); + UASSERT_OBJ(m_modp, nodep, "Not under module"); // We could create just one temp variable, but we'll get better optimization // if we make one per term. string name1 = (string("__Vconcswap")+cvtToStr(m_modp->varNumGetInc())); @@ -1234,7 +1234,7 @@ private: } else { // Fetch the result V3Number* outnump = simvis.fetchNumberNull(nodep); - if (!outnump) nodep->v3fatalSrc("No number returned from simulation"); + UASSERT_OBJ(outnump, nodep, "No number returned from simulation"); // Replace it replaceNum(nodep,*outnump); VL_DANGLING(nodep); } @@ -1440,7 +1440,7 @@ private: AstNode* fromp = repp->lhsp(); 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"); + UASSERT_OBJ(fromp->width(), nodep, "Not widthed"); if ((lsbp->toUInt() / fromp->width()) != ((lsbp->toUInt()+nodep->width()-1) / fromp->width())) return false; // @@ -1500,7 +1500,7 @@ private: void replaceSelIntoBiop(AstSel* nodep) { // SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit)) AstNodeBiop* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), NodeBiop); - if (!fromp) nodep->v3fatalSrc("Called on non biop"); + UASSERT_OBJ(fromp, nodep, "Called on non biop"); AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); AstNode* widthp = nodep->widthp()->unlinkFrBack(); // @@ -1517,7 +1517,7 @@ private: void replaceSelIntoUniop(AstSel* nodep) { // SEL(NOT(a),1,bit) => NOT(SEL(a,bit)) AstNodeUniop* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), NodeUniop); - if (!fromp) nodep->v3fatalSrc("Called on non biop"); + UASSERT_OBJ(fromp, nodep, "Called on non biop"); AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); AstNode* widthp = nodep->widthp()->unlinkFrBack(); // @@ -1564,7 +1564,7 @@ private: } virtual void visit(AstNodeVarRef* nodep) { iterateChildren(nodep); - if (!nodep->varp()) nodep->v3fatalSrc("Not linked"); + UASSERT_OBJ(nodep->varp(), nodep, "Not linked"); bool did = false; if (m_doV && nodep->varp()->valuep() && !m_attrp) { //if (debug()) valuep->dumpTree(cout, " visitvaref: "); @@ -1627,7 +1627,7 @@ private: } virtual void visit(AstEnumItemRef* nodep) { iterateChildren(nodep); - if (!nodep->itemp()) nodep->v3fatalSrc("Not linked"); + UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); bool did = false; if (nodep->itemp()->valuep()) { //if (debug()) nodep->varp()->valuep()->dumpTree(cout, " visitvaref: "); @@ -1682,7 +1682,7 @@ private: UINFO(8,"senItem(NOT...) "<edgeType( nodep->edgeType().invert() ); AstNodeVarRef* senvarp = VN_CAST(lastSensp->unlinkFrBack(), NodeVarRef); - if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable"); + UASSERT_OBJ(senvarp, sensp, "Non-varref sensitivity variable"); sensp->replaceWith(senvarp); sensp->deleteTree(); VL_DANGLING(sensp); } else if (!m_doNConst // Deal with later when doNConst missing @@ -1690,7 +1690,8 @@ private: || VN_IS(nodep->sensp(), Const))) { } else if (nodep->isIllegal()) { // Deal with later } else { - if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable"); + UASSERT_OBJ(!(nodep->hasVar() && !nodep->varrefp()), nodep, + "Null sensitivity variable"); } } virtual void visit(AstSenGate* nodep) { diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index 41549f032..53f03e8f9 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -81,7 +81,7 @@ private: // duplicated), not the covertoggle, but we need to get back to the // covertoggle which is immediately above, so: AstCoverToggle* removep = VN_CAST(duporigp->backp(), CoverToggle); - if (!removep) nodep->v3fatalSrc("CoverageJoin duplicate of wrong type"); + UASSERT_OBJ(removep, nodep, "CoverageJoin duplicate of wrong type"); UINFO(8," Orig "<> "<incp()->declp()<> "<incp()->declp()<scopep()) oldvarscp->v3fatalSrc("Var unscoped"); + UASSERT_OBJ(oldvarscp->scopep(), oldvarscp, "Var unscoped"); AstVar* varp; AstNodeModule* addmodp = oldvarscp->scopep()->modp(); // We need a new AstVar, but only one for all scopes, to match the new AstVarScope @@ -158,7 +158,7 @@ private: } void checkActivePost(AstVarRef* varrefp, AstActive* oldactivep) { // Check for MULTIDRIVEN, and if so make new sentree that joins old & new sentree - if (!oldactivep) varrefp->v3fatalSrc("<= old dly assignment not put under sensitivity block"); + UASSERT_OBJ(oldactivep, varrefp, "<= old dly assignment not put under sensitivity block"); if (oldactivep->sensesp() != m_activep->sensesp()) { if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN) && !varrefp->varp()->user2()) { @@ -203,10 +203,9 @@ private: } else { arrayselp = VN_CAST(lhsp, ArraySel); } - if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?"); - if (VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType)) { - nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); - } + UASSERT_OBJ(arrayselp, nodep, "No arraysel under bitsel?"); + UASSERT_OBJ(!VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType), nodep, + "ArraySel with unpacked arrays should have been removed in V3Slice"); UINFO(4,"AssignDlyArray: "<v3fatalSrc("No var underneath arraysels"); - if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); + UASSERT_OBJ(varrefp, nodep, "No var underneath arraysels"); + UASSERT_OBJ(varrefp->varScopep(), varrefp, "Var didn't get varscoped in V3Scope.cpp"); varrefp->unlinkFrBack(); AstVar* oldvarp = varrefp->varp(); int modVecNum = m_scopeVecMap[varrefp->varScopep()]++; @@ -333,7 +332,8 @@ private: // Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*, // we can share the IF statement too postLogicp = VN_CAST(finalp->user4p(), If); - if (!postLogicp) nodep->v3fatalSrc("Delayed assignment misoptimized; prev var found w/o associated IF"); + UASSERT_OBJ(postLogicp, nodep, + "Delayed assignment misoptimized; prev var found w/o associated IF"); } else { postLogicp = new AstIf(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, false), @@ -400,12 +400,12 @@ private: if (m_inDly && nodep->lvalue()) { UINFO(4,"AssignDlyVar: "<varScopep(), VU_DLY); - if (!m_activep) nodep->v3fatalSrc("<= not under sensitivity block"); + UASSERT_OBJ(m_activep, nodep, "<= not under sensitivity block"); 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"); + UASSERT_OBJ(oldvscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); AstVarScope* dlyvscp = VN_CAST(oldvscp->user1p(), VarScope); if (dlyvscp) { // Multiple use of delayed variable AstActive* oldactivep = VN_CAST(dlyvscp->user2p(), Active); diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index e50220545..6c7df0df6 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -66,7 +66,7 @@ private: // bitmask instead of widths....) // See t_func_crc for an example test that requires this VFlagLogicPacked(), nodep->width()); - if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function"); + UASSERT_OBJ(m_funcp, nodep, "Deep expression not under a function"); m_funcp->addInitsp(varp); // Replace node tree with reference to var AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, false); @@ -134,7 +134,7 @@ private: // Marking of non-static functions (because they might need "this") // (Here instead of new vistor after V3Descope just to avoid another visitor) void needNonStaticFunc(AstNode* nodep) { - if (!m_funcp) nodep->v3fatalSrc("Non-static accessor not under a function"); + UASSERT_OBJ(m_funcp, nodep, "Non-static accessor not under a function"); if (m_funcp->isStatic().trueU()) { UINFO(5,"Mark non-public due to "<isStatic(false); diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 6d3ff5880..9c7511885 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -182,7 +182,7 @@ private: AstCFunc* funcp = eachIt->second; FuncMmap::iterator nextIt2 = eachIt; ++nextIt2; bool moreOfSame = (nextIt2!=m_modFuncs.end() && nextIt2->first == name); - if (!funcp->scopep()) funcp->v3fatalSrc("Not scoped"); + UASSERT_OBJ(funcp->scopep(), funcp, "Not scoped"); UINFO(6," Wrapping "<argTypes()<<" und "<argTypes()<v3fatalSrc("Node not under scope"); + UASSERT_OBJ(m_scopep, nodep, "Node not under scope"); bool hierThis; nodep->hiername(descopedName(nodep->varScopep()->scopep(), hierThis/*ref*/, nodep->varScopep()->varp())); @@ -266,8 +266,8 @@ private: //UINFO(9," "<v3fatalSrc("Node not under scope"); - if (!nodep->funcp()->scopep()) nodep->v3fatalSrc("CFunc not under scope"); + UASSERT_OBJ(m_scopep, nodep, "Node not under scope"); + UASSERT_OBJ(nodep->funcp()->scopep(), nodep, "CFunc not under scope"); bool hierThis; nodep->hiername(descopedName(nodep->funcp()->scopep(), hierThis/*ref*/)); // Can't do this, as we may have more calls later diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 8b601261f..3ae9c0827 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -89,7 +89,7 @@ public: puts(nodep->dtypep()->charIQWN()); } void emitScIQW(AstVar* nodep) { - if (!nodep->isSc()) nodep->v3fatalSrc("emitting SystemC operator on non-SC variable"); + UASSERT_OBJ(nodep->isSc(), nodep, "emitting SystemC operator on non-SC variable"); puts(nodep->isScBigUint() ? "SB" : nodep->isScUint() ? "SU" : nodep->isScBv() ? "SW" @@ -632,9 +632,9 @@ public: } virtual void visit(AstReplicate* nodep) { if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) { - if ((static_cast(VN_CAST(nodep->rhsp(), Const)->toUInt()) - * nodep->lhsp()->widthMin()) != nodep->widthMin()) - nodep->v3fatalSrc("Replicate non-constant or width miscomputed"); + UASSERT_OBJ((static_cast(VN_CAST(nodep->rhsp(), Const)->toUInt()) + * nodep->lhsp()->widthMin()) == nodep->widthMin(), + nodep, "Replicate non-constant or width miscomputed"); puts("VL_REPLICATE_"); emitIQW(nodep); puts("OI("); @@ -798,7 +798,7 @@ public: } virtual void visit(AstConst* nodep) { if (nodep->isWide()) { - if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Constant w/ no temp"); + UASSERT_OBJ(m_wideTempRefp, nodep, "Wide Constant w/ no temp"); emitConstant(nodep, m_wideTempRefp, ""); m_wideTempRefp = NULL; // We used it, barf if set it a second time } else { @@ -909,8 +909,8 @@ class EmitCImp : EmitCStmts { else { AstNode* lhsp = changep->lhsp(); AstNode* rhsp = changep->rhsp(); - 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?"); + UASSERT_OBJ(VN_IS(lhsp, VarRef) || VN_IS(lhsp, ArraySel), changep, "Not ref?"); + UASSERT_OBJ(VN_IS(rhsp, VarRef) || VN_IS(rhsp, ArraySel), changep, "Not ref?"); for (int word=0; word < (changep->lhsp()->isWide() ? changep->lhsp()->widthWords() : 1); ++word) { @@ -1164,9 +1164,8 @@ class EmitCImp : EmitCStmts { } virtual void visit(AstExecGraph* nodep) { - if (nodep != v3Global.rootp()->execGraphp()) { - nodep->v3fatalSrc("ExecGraph should be a singleton!"); - } + UASSERT_OBJ(nodep == v3Global.rootp()->execGraphp(), nodep, + "ExecGraph should be a singleton!"); // The location of the AstExecGraph within the containing _eval() // function is where we want to invoke the graph and wait for it to // complete. Do that now. @@ -1185,10 +1184,8 @@ class EmitCImp : EmitCStmts { const ExecMTask* etp = dynamic_cast(vxp); if (etp->threadRoot()) execMTasks.push_back(etp); } - if (execMTasks.size() > - static_cast(v3Global.opt.threads())) { - nodep->v3fatalSrc("More root mtasks than available threads"); - } + UASSERT_OBJ(execMTasks.size() <= static_cast(v3Global.opt.threads()), + nodep, "More root mtasks than available threads"); if (!execMTasks.empty()) { for (uint32_t i = 0; i < execMTasks.size(); ++i) { @@ -1256,7 +1253,7 @@ public: void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { AstBasicDType* basicp = nodep->basicp(); - if (!basicp) nodep->v3fatalSrc("Unimplemented: Outputting this data type"); + UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type"); if (nodep->isIO()) { if (nodep->isSc()) { m_ctorVarsVec.push_back(nodep); @@ -1417,7 +1414,8 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, case 't': detail = true; detailp = thsp; break; case 'P': if (nodep->isWide()) { - if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Op w/ no temp, perhaps missing op in V3EmitC?"); + UASSERT_OBJ(m_wideTempRefp, nodep, + "Wide Op w/ no temp, perhaps missing op in V3EmitC?"); COMMA; puts(m_wideTempRefp->hiername()); puts(m_wideTempRefp->varp()->name()); @@ -1448,8 +1446,8 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, break; case 'i': COMMA; - if (!detailp) { nodep->v3fatalSrc("emitOperator() references undef node"); } - else iterateAndNextNull(detailp); + UASSERT_OBJ(detailp, nodep, "emitOperator() references undef node"); + iterateAndNextNull(detailp); needComma = true; break; default: @@ -1654,7 +1652,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, case '^': displayArg(nodep,&elistp,isScan, vfmt,'^'); break; // Realtime case 'v': displayArg(nodep, &elistp, isScan, vfmt, 'v'); break; case 'm': { - if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName"); + UASSERT_OBJ(scopenamep, nodep, "Display with %m but no AstScopeName"); string suffix = scopenamep->scopePrettySymName(); if (suffix=="") emitDispState.pushFormat("%S"); else emitDispState.pushFormat("%N"); // Add a . when needed @@ -1687,7 +1685,7 @@ void EmitCImp::emitVarReset(AstVar* varp) { if (varp->isIO() && m_modp->isTop() && optSystemC()) { // System C top I/O doesn't need loading, as the lower level subinst code does it.} } else if (varp->isParam()) { - if (!varp->valuep()) varp->v3fatalSrc("No init for a param?"); + UASSERT_OBJ(varp->valuep(), varp, "No init for a param?"); // If a simple CONST value we initialize it using an enum // If an ARRAYINIT we initialize it using an initial block similar to a signal //puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n"); @@ -1705,7 +1703,8 @@ void EmitCImp::emitVarReset(AstVar* varp) { 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"); + UASSERT_OBJ(initarp->defaultp() || index==pos, initarp, + "Not enough values in array initalizement"); emitSetVarConstant(varp->name()+"["+cvtToStr(index)+"]", VN_CAST(itemp, Const)); } } else { @@ -1722,9 +1721,8 @@ void EmitCImp::emitVarReset(AstVar* varp) { arrayp; arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; - if (VL_UNCOVERABLE(arrayp->msb() < arrayp->lsb())) { - varp->v3fatalSrc("Should have swapped msb & lsb earlier."); - } + UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, + "Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";"); @@ -1780,7 +1778,7 @@ void EmitCImp::emitCoverageDecl(AstNodeModule* modp) { void EmitCImp::emitMTaskVertexCtors(bool* firstp) { AstExecGraph* execGraphp = v3Global.rootp()->execGraphp(); - if (!execGraphp) v3Global.rootp()->v3fatalSrc("Should have an execGraphp"); + UASSERT_OBJ(execGraphp, v3Global.rootp(), "Root should have an execGraphp"); const V3Graph* depGraphp = execGraphp->depGraphp(); unsigned finalEdgesInCt = 0; @@ -1962,9 +1960,8 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { arrayp; arrayp = VN_CAST(elementp, UnpackArrayDType)) { int vecnum = vects++; - if (VL_UNCOVERABLE(arrayp->msb() < arrayp->lsb())) { - varp->v3fatalSrc("Should have swapped msb & lsb earlier."); - } + UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, + "Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); // MSVC++ pre V7 doesn't support 'for (int ...)', // so declare in sep block @@ -2062,9 +2059,8 @@ void EmitCImp::emitSensitives() { arrayp; arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; - if (VL_UNCOVERABLE(arrayp->msb() < arrayp->lsb())) { - varp->v3fatalSrc("Should have swapped msb & lsb earlier."); - } + UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, + "Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(arrayp->lsb())+";"); @@ -2404,7 +2400,7 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) { if (modp->isTop() && v3Global.opt.mtasks()) { // Emit the mtask func prototypes. AstExecGraph* execGraphp = v3Global.rootp()->execGraphp(); - if (!execGraphp) v3Global.rootp()->v3fatalSrc("Root should have an execGraphp"); + UASSERT_OBJ(execGraphp, v3Global.rootp(), "Root should have an execGraphp"); const V3Graph* depGraphp = execGraphp->depGraphp(); for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { @@ -2424,7 +2420,7 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) { void EmitCImp::emitMTaskState() { ofp()->putsPrivate(true); AstExecGraph* execGraphp = v3Global.rootp()->execGraphp(); - if (!execGraphp) v3Global.rootp()->v3fatalSrc("Root should have an execGraphp"); + UASSERT_OBJ(execGraphp, v3Global.rootp(), "Root should have an execGraphp"); const V3Graph* depGraphp = execGraphp->depGraphp(); for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); @@ -2566,7 +2562,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) { for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { 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?"); + UASSERT_OBJ(varp->valuep(), nodep, "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 diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 0636cfed4..0d4e79b11 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -206,7 +206,7 @@ class EmitCSyms : EmitCBaseVisitor { m_scopeNames.insert(make_pair(name, ScopeNameData(name, nodep->scopePrettySymName()))); } if (nodep->dpiExport()) { - if (!m_funcp) nodep->v3fatalSrc("ScopeName not under DPI function"); + UASSERT_OBJ(m_funcp, nodep, "ScopeName not under DPI function"); m_scopeFuncs.insert(make_pair(name + " " + m_funcp->name(), ScopeFuncData(nodep, m_funcp, m_modp))); } else { diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 0ff07b863..2dd747cd4 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -403,23 +403,23 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { case 'f': putfs(nodep, ""); break; case 'k': putbs(""); break; case 'l': { - if (!lhsp) { nodep->v3fatalSrc("emitVerilog() references undef node"); } - else iterateAndNextNull(lhsp); + UASSERT_OBJ(lhsp, nodep, "emitVerilog() references undef node"); + iterateAndNextNull(lhsp); break; } case 'r': { - if (!rhsp) { nodep->v3fatalSrc("emitVerilog() references undef node"); } - else iterateAndNextNull(rhsp); + UASSERT_OBJ(rhsp, nodep, "emitVerilog() references undef node"); + iterateAndNextNull(rhsp); break; } case 't': { - if (!thsp) { nodep->v3fatalSrc("emitVerilog() references undef node"); } - else iterateAndNextNull(thsp); + UASSERT_OBJ(thsp, nodep, "emitVerilog() references undef node"); + iterateAndNextNull(thsp); break; } case 'd': { - if (!nodep->dtypep()) { nodep->v3fatalSrc("emitVerilog() references undef node"); } - else iterateAndNextNull(nodep->dtypep()); + UASSERT_OBJ(nodep->dtypep(), nodep, "emitVerilog() references undef node"); + iterateAndNextNull(nodep->dtypep()); break; } default: diff --git a/src/V3Error.h b/src/V3Error.h index 5eadec8d0..7e68dee7e 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -310,11 +310,17 @@ inline void v3errorEndFatal(std::ostringstream& sstr) { # define UDEBUGONLY(stmts) {if (0) {stmts}} #endif -#define UASSERT(condition,stmsg) { if (VL_UNCOVERABLE(!(condition))) { v3fatalSrc(stmsg); }} +// Assertion without object, generally UOBJASSERT preferred +#define UASSERT(condition,stmsg) \ + do { if (VL_UNCOVERABLE(!(condition))) { v3fatalSrc(stmsg); }} while(0) +// Assertion with object +#define UASSERT_OBJ(condition,obj,stmsg) \ + do { if (VL_UNCOVERABLE(!(condition))) { (obj)->v3fatalSrc(stmsg); }} while(0) // For use in V3Ast static functions only #define UASSERT_STATIC(condition,stmsg) \ - { if (VL_UNCOVERABLE(!(condition))) { \ - std::cerr<<"Internal Error: "<<__FILE__<<":"< will work to control UINFOs in /// that class: -#define VL_DEBUG_FUNC static int debug() { \ +#define VL_DEBUG_FUNC \ + static int debug() { \ static int level = -1; \ if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__); \ return level; \ diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 0b5ebcab4..0206c3b72 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -239,9 +239,8 @@ private: } bool expandWide(AstNodeAssign* nodep, AstArraySel* rhsp) { UINFO(8," Wordize ASSIGN(ARRAYSEL) "<dtypep()->skipRefp(), UnpackArrayDType))) { - nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice"); - } + UASSERT_OBJ(!VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType), nodep, + "ArraySel with unpacked arrays should have been removed in V3Slice"); for (int w=0; wwidthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone(rhsp, w)); } @@ -324,11 +323,9 @@ private: newp = new AstCCast(nodep->fileline(), lhsp, nodep); } } else { // Long - if (lhsp->isQuad() || lhsp->isWide()) { - nodep->v3fatalSrc("extending larger thing into smaller?"); - } else { - lhsp->dtypeFrom(nodep); // Just mark it, else nop - } + UASSERT_OBJ(!(lhsp->isQuad() || lhsp->isWide()), nodep, + "extending larger thing into smaller?"); + lhsp->dtypeFrom(nodep); // Just mark it, else nop } replaceWithDelete(nodep, newp); VL_DANGLING(nodep); } @@ -349,7 +346,7 @@ private: if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); // Remember, Sel's may have non-integer rhs, so need to optimize for that! - if (nodep->widthMin() != nodep->widthConst()) nodep->v3fatalSrc("Width mismatch"); + UASSERT_OBJ(nodep->widthMin() == nodep->widthConst(), nodep, "Width mismatch"); if (VN_IS(nodep->backp(), NodeAssign) && nodep==VN_CAST(nodep->backp(), NodeAssign)->lhsp()) { // Sel is an LHS assignment select @@ -468,7 +465,7 @@ private: } bool expandWide(AstNodeAssign* nodep, AstSel* rhsp) { - if (nodep->widthMin() != rhsp->widthConst()) nodep->v3fatalSrc("Width mismatch"); + UASSERT_OBJ(nodep->widthMin() == rhsp->widthConst(), nodep, "Width mismatch"); if (VN_IS(rhsp->lsbp(), Const) && VL_BITBIT_I(rhsp->lsbConst())==0) { int lsb = rhsp->lsbConst(); UINFO(8," Wordize ASSIGN(SEL,align) "<rhsp(), Const); - if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!"); + UASSERT_OBJ(constp, nodep, + "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); @@ -756,7 +754,7 @@ private: AstNode* lhsp = rhsp->lhsp(); int lhswidth = lhsp->widthMin(); const AstConst* constp = VN_CAST(rhsp->rhsp(), Const); - if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!"); + UASSERT_OBJ(constp, rhsp, "Replication value isn't a constant. Checked earlier!"); uint32_t times = constp->toUInt(); for (int w=0; wwidthWords(); w++) { AstNode* newp; diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index e7d6e9a40..aa2d5c418 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -435,9 +435,9 @@ private: } virtual void visit(AstNodeVarRef* nodep) { if (m_scopep) { - if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block"); + UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block"); AstVarScope* varscp = nodep->varScopep(); - if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); + UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); GateVarVertex* vvertexp = makeVarVertex(varscp); UINFO(5," VARREF to "<setIsClock(); @@ -509,10 +509,9 @@ private: m_inSlow = lastslow; } virtual void visit(AstConcat* 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"); - } + UASSERT_OBJ(!(VN_IS(nodep->backp(), NodeAssign) + && VN_CAST(nodep->backp(), NodeAssign)->lhsp()==nodep), + nodep, "Concat on LHS of assignment; V3Const should have deleted it"); iterateChildren(nodep); } @@ -850,14 +849,14 @@ private: // It's possible we substitute into something that will be reduced more later, // however, as we never delete the top Always/initial statement, all should be well. m_didReplace = true; - if (nodep->lvalue()) nodep->v3fatalSrc("Can't replace lvalue assignments with const var"); + UASSERT_OBJ(!nodep->lvalue(), nodep, + "Can't replace lvalue assignments with const var"); AstNode* substp = m_replaceTreep->cloneTree(false); - if (VN_IS(nodep, NodeVarRef) - && VN_IS(substp, NodeVarRef) - && nodep->same(substp)) { - // Prevent an infinite loop... - substp->v3fatalSrc("Replacing node with itself; perhaps circular logic?"); - } + UASSERT_OBJ(!(VN_IS(nodep, NodeVarRef) + && VN_IS(substp, NodeVarRef) + && nodep->same(substp)), + // Prevent an infinite loop... + substp, "Replacing node with itself; perhaps circular logic?"); // Which fileline() to use? // If replacing with logic, an error/warning is likely to want to point to the logic // IE what we're replacing with. @@ -1044,9 +1043,8 @@ public: AstNode* lhsp = m_assignp->lhsp(); // Possible todo, handle more complex lhs expressions if (AstNodeVarRef* lhsVarRefp = VN_CAST(lhsp, NodeVarRef)) { - if (lhsVarRefp->varScopep() != consumerVarScopep) { - consumerVarScopep->v3fatalSrc("Consumer doesn't match lhs of assign"); - } + UASSERT_OBJ(lhsVarRefp->varScopep() == consumerVarScopep, + consumerVarScopep, "Consumer doesn't match lhs of assign"); if (AstNodeAssign* dup = m_ghash.hashAndFindDupe(m_assignp, activep, m_ifCondp)) { return static_cast(dup->lhsp()); } @@ -1081,7 +1079,8 @@ private: if (dupVarRefp) { // visit(GateLogicVertex*...) returned match V3GraphEdge* edgep = vvertexp->inBeginp(); GateLogicVertex* lvertexp = static_cast(edgep->fromp()); - if (!vvertexp->dedupable()) vvertexp->varScp()->v3fatalSrc("GateLogicVertex* visit should have returned NULL if consumer var vertex is not dedupable."); + UASSERT_OBJ(vvertexp->dedupable(), vvertexp->varScp(), + "GateLogicVertex* visit should have returned NULL if consumer var vertex is not dedupable."); GateOkVisitor okVisitor(lvertexp->nodep(), false, true); if (okVisitor.isSimple()) { AstVarScope* dupVarScopep = dupVarRefp->varScopep(); diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index a91338f8a..faf1ea9fd 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -87,7 +87,7 @@ private: AstNode::user2ClearTree(); // user2p() used on entire tree AstScope* scopep = nodep->scopep(); - if (!scopep) nodep->v3fatalSrc("No scope found on top level"); + UASSERT_OBJ(scopep, nodep, "No scope found on top level"); m_scopetopp = scopep; iterateChildren(nodep); @@ -96,7 +96,7 @@ private: virtual void visit(AstVarRef* nodep) { // Consumption/generation of a variable, AstVarScope* vscp = nodep->varScopep(); - if (!vscp) nodep->v3fatalSrc("Scope not assigned"); + UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (m_activep && !nodep->user3()) { nodep->user3(true); if (vscp->isCircular()) { @@ -111,7 +111,7 @@ private: } virtual void visit(AstActive* nodep) { m_activep = nodep; - if (!nodep->sensesp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked"); iterateChildren(nodep->sensesp()); // iterateAndNext? m_activep = NULL; iterateChildren(nodep); @@ -191,7 +191,7 @@ private: virtual void visit(AstVarRef* nodep) { // Consumption/generation of a variable, AstVarScope* vscp = nodep->varScopep(); - if (!vscp) nodep->v3fatalSrc("Scope not assigned"); + UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (m_activep) { UINFO(8," VarAct "<user1(true); @@ -212,7 +212,7 @@ private: virtual void visit(AstActive* nodep) { UINFO(8,"ACTIVE "<sensesp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked"); iterateChildren(nodep->sensesp()); // iterateAndNext? m_activep = NULL; iterateChildren(nodep); diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index 31eda865a..b45c93e40 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -579,7 +579,7 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) { // Compute fanouts of each node // If forward edge, don't double count that fanout if (vertexp->user() == 2) return vertexp->fanout(); // Already processed it - if (vertexp->user() == 1) vertexp->v3fatalSrc("Loop found, backward edges should be dead"); + UASSERT_OBJ(vertexp->user() != 1, vertexp, "Loop found, backward edges should be dead"); vertexp->user(1); double fanout = 0; for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index af315adae..f48abb712 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -40,7 +40,7 @@ DfaVertex* DfaGraph::findStart() { vertexp; vertexp=vertexp->verticesNextp()) { if (DfaVertex* vvertexp = dynamic_cast(vertexp)) { if (vvertexp->start()) { - if (startp) vertexp->v3fatalSrc("Multiple start points in NFA graph"); + UASSERT_OBJ(!startp, vertexp, "Multiple start points in NFA graph"); startp = vvertexp; } } else { @@ -118,9 +118,8 @@ private: DfaVertex* nfaStatep = static_cast(dfaEdgep->top()); hash ^= hashVertex(nfaStatep); if (debug()) { - if (nfaStatep->user()==m_step) { - nfaStatep->v3fatalSrc("DFA state points to duplicate NFA state."); - } + UASSERT_OBJ(nfaStatep->user() != m_step, nfaStatep, + "DFA state points to duplicate NFA state."); nfaStatep->user(m_step); } } diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index 5996ad32a..36c22b255 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -94,9 +94,8 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) { GraphPCNode* ourUserp = static_cast(vertexp->userp()); if (checkOnly) { - if (VL_UNCOVERABLE(ourUserp->m_cp[way] != critPathCost)) { - vertexp->v3fatalSrc("Validation of critical paths failed"); - } + UASSERT_OBJ(ourUserp->m_cp[way] == critPathCost, + vertexp, "Validation of critical paths failed"); } else { ourUserp->m_cp[way] = critPathCost; } diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index b3d5fa554..8ab5dd8e3 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -60,9 +60,7 @@ private: // Decrement blocking edges count, return true if the vertex is // newly unblocked bool unblock() { - if (VL_UNCOVERABLE(m_numBlockingEdges <= 0)) { - vertexp()->v3fatalSrc("Underflow of blocking edges"); - } + UASSERT_OBJ(m_numBlockingEdges > 0, vertexp(), "Underflow of blocking edges"); m_numBlockingEdges--; return (m_numBlockingEdges == 0); } @@ -210,9 +208,8 @@ private: typename WaitingVertices::iterator it = m_waitingVertices.find(toVertexp); - if (VL_UNCOVERABLE(it == m_waitingVertices.end())) { - toVertexp->v3fatalSrc("Found edge into vertex not in waiting list."); - } + UASSERT_OBJ(it != m_waitingVertices.end(), toVertexp, + "Found edge into vertex not in waiting list."); if (it->second.unblock()) { m_readyVertices.insert(it->second); m_waitingVertices.erase(it); @@ -225,9 +222,8 @@ private: typename WaitingVertices::iterator it = m_waitingVertices.find(fromVertexp); - if (VL_UNCOVERABLE(it == m_waitingVertices.end())) { - fromVertexp->v3fatalSrc("Found edge into vertex not in waiting list."); - } + UASSERT_OBJ(it != m_waitingVertices.end(), fromVertexp, + "Found edge into vertex not in waiting list."); if (it->second.unblock()) { m_readyVertices.insert(it->second); m_waitingVertices.erase(it); diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index ae9d0d27f..aa9696e8e 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -59,16 +59,15 @@ private: void nodeHashIterate(AstNode* nodep) { V3Hash thisHash; if (!m_cacheInUser4 || !nodep->user4()) { - 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)"); - } + UASSERT_OBJ(!(VN_IS(nodep->backp(), CFunc) + && !(VN_IS(nodep, NodeStmt) || VN_IS(nodep, CFunc))), nodep, + "Node "<prettyTypeName() + <<" in statement position but not marked stmt (node under function)"); V3Hash oldHash = m_lowerHash; { m_lowerHash = nodep->sameHash(); - if (m_lowerHash.isIllegal()) { - nodep->v3fatalSrc("sameHash function undefined (returns 0) for node under CFunc."); - } + UASSERT_OBJ(!m_lowerHash.isIllegal(), nodep, + "sameHash function undefined (returns 0) for node under CFunc."); // For identical nodes, the type should be the same thus // dtypep should be the same too m_lowerHash = V3Hash(m_lowerHash, V3Hash(nodep->type()<<6, @@ -132,8 +131,8 @@ void V3Hashed::hash(AstNode* nodep) { } bool V3Hashed::sameNodes(AstNode* node1p, AstNode* node2p) { - if (!node1p->user4p()) node1p->v3fatalSrc("Called isIdentical on non-hashed nodes"); - if (!node2p->user4p()) node2p->v3fatalSrc("Called isIdentical on non-hashed nodes"); + UASSERT_OBJ(node1p->user4p(), node1p, "Called isIdentical on non-hashed nodes"); + UASSERT_OBJ(node2p->user4p(), node2p, "Called isIdentical on non-hashed nodes"); return (node1p->user4p() == node2p->user4p() // Same hash && node1p->sameTree(node2p)); } @@ -141,7 +140,7 @@ bool V3Hashed::sameNodes(AstNode* node1p, AstNode* node2p) { void V3Hashed::erase(iterator it) { AstNode* nodep = iteratorNodep(it); UINFO(8," erase "<user4p()) nodep->v3fatalSrc("Called removeNode on non-hashed node"); + UASSERT_OBJ(nodep->user4p(), nodep, "Called removeNode on non-hashed node"); m_hashMmap.erase(it); nodep->user4p(NULL); // So we don't allow removeNode again } @@ -196,7 +195,7 @@ void V3Hashed::dumpFile(const string& filename, bool tree) { V3Hashed::iterator V3Hashed::findDuplicate(AstNode* nodep) { UINFO(8," findD "<user4p()) nodep->v3fatalSrc("Called findDuplicate on non-hashed node"); + UASSERT_OBJ(nodep->user4p(), nodep, "Called findDuplicate on non-hashed node"); std::pair eqrange = mmap().equal_range(nodeHash(nodep)); for (HashMmap::iterator eqit = eqrange.first; eqit != eqrange.second; ++eqit) { AstNode* node2p = eqit->second; @@ -209,7 +208,7 @@ V3Hashed::iterator V3Hashed::findDuplicate(AstNode* nodep) { V3Hashed::iterator V3Hashed::findDuplicate(AstNode* nodep, V3HashedUserCheck* checkp) { UINFO(8," findD "<user4p()) nodep->v3fatalSrc("Called findDuplicate on non-hashed node"); + UASSERT_OBJ(nodep->user4p(), nodep, "Called findDuplicate on non-hashed node"); std::pair eqrange = mmap().equal_range(nodeHash(nodep)); for (HashMmap::iterator eqit = eqrange.first; eqit != eqrange.second; ++eqit) { diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 77583b075..bd8ec18f5 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -306,9 +306,8 @@ private: 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"); - } + UASSERT_OBJ(exprconstp || exprvarrefp, nodep, + "Unknown interconnect type; pinReconnectSimple should have cleared up"); if (exprconstp) { m_modp->addStmtp(new AstAssignW(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), @@ -318,7 +317,7 @@ private: // the logic changes up and down; if we aliased, we might // remove the change detection on the output variable. UINFO(9,"public pin assign: "<isNonOutput()) nodep->v3fatalSrc("Outputs only - inputs use AssignAlias"); + UASSERT_OBJ(!nodep->isNonOutput(), nodep, "Outputs only - inputs use AssignAlias"); m_modp->addStmtp( new AstAssignW(nodep->fileline(), new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), @@ -555,12 +554,11 @@ private: // delete it in later optimizations. AstVar* pinOldVarp = pinp->modVarp(); AstVar* pinNewVarp = pinOldVarp->clonep(); - if (!pinNewVarp) pinOldVarp->v3fatalSrc("Cloning failed"); + UASSERT_OBJ(pinNewVarp, pinOldVarp, "Cloning failed"); AstNode* connectRefp = pinp->exprp(); - if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) { - pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up"); - } + UASSERT_OBJ(VN_IS(connectRefp, Const) || VN_IS(connectRefp, VarRef), pinp, + "Unknown interconnect type; pinReconnectSimple should have cleared up"); V3Inst::checkOutputShort(pinp); // Propagate any attributes across the interconnect diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 910015802..862b98bc5 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -75,9 +75,8 @@ private: V3Inst::pinReconnectSimple(nodep, m_cellp, false); // Make an ASSIGNW (expr, pin) AstNode* exprp = nodep->exprp()->cloneTree(false); - if (exprp->width() != nodep->modVarp()->width()) { - nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple"); - } + UASSERT_OBJ(exprp->width() == nodep->modVarp()->width(), nodep, + "Width mismatch, should have been handled in pinReconnectSimple"); if (nodep->modVarp()->isInoutish()) { nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator"); } else if (nodep->modVarp()->isWritable()) { @@ -104,7 +103,8 @@ private: nodep->modVarp(), m_cellp->name(), false); 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"); + UASSERT_OBJ(refp || xrefp, exprp, + "Interfaces: Pin is not connected to a VarRef or VarXRef"); AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, exprp); m_cellp->addNextHere(assp); } else { @@ -249,7 +249,7 @@ private: virtual void visit(AstCell* nodep) { UINFO(4," CELL "<modp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->modp(), nodep, "Unlinked"); m_deModVars.main(nodep->modp()); // if (nodep->rangep()) { diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 9d76176c9..35e372de5 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -100,10 +100,9 @@ private: // (which at the V3Order stage represent verilog tasks, not to // the CFuncs that V3Order will generate.) So don't check for // collisions in CFuncs. - if (nodep->user5p()) { - nodep->v3fatalSrc("Node originally inserted below logic vertex " - <(nodep->user5p())); - } + UASSERT_OBJ(!nodep->user5p(), nodep, + "Node originally inserted below logic vertex " + <(nodep->user5p())); nodep->user5p(const_cast(reinterpret_cast(m_startNodep))); } @@ -235,25 +234,20 @@ private: // are no actives-under-actives. In any case, check that we're at // root: markCost(nodep); - if (nodep != m_startNodep) { - nodep->v3fatalSrc("Multiple actives, or not start node"); - } + UASSERT_OBJ(nodep == m_startNodep, nodep, "Multiple actives, or not start node"); } virtual void visit(AstCCall* nodep) { VisitBase vb(this, nodep); iterateChildren(nodep); m_tracingCall = true; iterate(nodep->funcp()); - if (m_tracingCall) { - nodep->v3fatalSrc("visit(AstCFunc) should have cleared m_tracingCall."); - } + UASSERT_OBJ(!m_tracingCall, nodep, "visit(AstCFunc) should have cleared m_tracingCall."); } virtual void visit(AstCFunc* nodep) { // Don't count a CFunc other than by tracing a call or counting it // from the root - if (!m_tracingCall && (nodep != m_startNodep)) { - nodep->v3fatalSrc("AstCFunc not under AstCCall, or not start node"); - } + UASSERT_OBJ(m_tracingCall || nodep == m_startNodep, nodep, + "AstCFunc not under AstCCall, or not start node"); m_tracingCall = false; bool saved_inCFunc = m_inCFunc; m_inCFunc = true; @@ -287,7 +281,7 @@ public: InstrCountDumpVisitor(AstNode* nodep, std::ostream* osp) : m_osp(osp), m_depth(0) { // No check for NULL output, so... - if (!osp) nodep->v3fatalSrc("Don't call if not dumping"); + UASSERT_OBJ(osp, nodep, "Don't call if not dumping"); if (nodep) iterate(nodep); } virtual ~InstrCountDumpVisitor() {} diff --git a/src/V3Life.cpp b/src/V3Life.cpp index a34493aa2..c123eef7e 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -299,10 +299,10 @@ private: virtual void visit(AstVarRef* nodep) { // Consumption/generation of a variable, // it's used so can't elim assignment before this use. - if (!nodep->varScopep()) nodep->v3fatalSrc("NULL"); + UASSERT_OBJ(nodep->varScopep(), nodep, "NULL"); // AstVarScope* vscp = nodep->varScopep(); - if (!vscp) nodep->v3fatalSrc("Scope not assigned"); + UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (nodep->lvalue()) { m_sideEffect = true; // $sscanf etc may have RHS vars that are lvalues m_lifep->complexAssign(vscp); @@ -324,7 +324,7 @@ private: // Has to be direct assignment without any EXTRACTing. 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"); + UASSERT_OBJ(vscp, nodep, "Scope lost on variable"); m_lifep->simpleAssign(vscp, nodep); } else { iterateAndNextNull(nodep->lhsp()); diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index b9e84c42d..232dca01d 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -60,7 +60,7 @@ private: // VISITORS virtual void visit(AstVarRef* nodep) { AstVarScope* vscp = nodep->varScopep(); - if (!vscp) nodep->v3fatalSrc("Scope not assigned"); + UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (AstVarScope* newvscp = reinterpret_cast(vscp->user4p())) { UINFO(9, " Replace "<fileline(), newvscp, nodep->lvalue()); @@ -267,14 +267,12 @@ private: iterateChildren(nodep); if (v3Global.opt.mtasks()) { - if (!m_mtasksGraphp) { - nodep->v3fatalSrc("Should have initted m_mtasksGraphp by now"); - } + UASSERT_OBJ(m_mtasksGraphp, nodep, + "Should have initted m_mtasksGraphp by now"); m_checker.reset(new GraphPathChecker(m_mtasksGraphp)); } else { - if (m_mtasksGraphp) { - nodep->v3fatalSrc("Did not expect any m_mtasksGraphp in serial mode"); - } + UASSERT_OBJ(!m_mtasksGraphp, nodep, + "Did not expect any m_mtasksGraphp in serial mode"); } // Find all assignposts. Determine which ones can be @@ -289,7 +287,7 @@ private: virtual void visit(AstVarRef* nodep) { // Consumption/generation of a variable, AstVarScope* vscp = nodep->varScopep(); - if (!vscp) nodep->v3fatalSrc("Scope not assigned"); + UASSERT_OBJ(vscp, nodep, "Scope not assigned"); LifeLocation loc(m_execMTaskp, ++m_sequence); if (nodep->lvalue()) { @@ -311,9 +309,8 @@ private: if (AstVarRef* rhsp = VN_CAST(nodep->rhsp(), VarRef)) { // rhsp is the dly var AstVarScope* dlyVarp = rhsp->varScopep(); - if (m_assignposts.find(dlyVarp) != m_assignposts.end()) { - nodep->v3fatalSrc("LifePostLocation attempted duplicate dlyvar map addition"); - } + UASSERT_OBJ(m_assignposts.find(dlyVarp) == m_assignposts.end(), nodep, + "LifePostLocation attempted duplicate dlyvar map addition"); LifeLocation loc(m_execMTaskp, ++m_sequence); m_assignposts[dlyVarp] = LifePostLocation(loc, nodep); } diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 66f073c1b..095be6f4f 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -250,7 +250,7 @@ private: virtual void visit(AstPackageImport* nodep) { // Package Import: We need to do the package before the use of a package iterateChildren(nodep); - if (!nodep->packagep()) nodep->v3fatalSrc("Unlinked package"); // Parser should set packagep + UASSERT_OBJ(nodep->packagep(), nodep, "Unlinked package"); // Parser should set packagep new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index e0d9672c3..8cb23439e 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -248,7 +248,7 @@ public: symp->fallbackp(NULL); rootEntp()->insert("$unit ", symp); // Space so can never name conflict with user code // - if (m_dunitEntp) nodep->v3fatalSrc("Call insertDUnit only once"); + UASSERT_OBJ(!m_dunitEntp, nodep, "Call insertDUnit only once"); m_dunitEntp = symp; } VSymEnt* insertTopCell(AstNodeModule* nodep, const string& scopename) { @@ -265,7 +265,7 @@ public: } VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* modSymp, AstCell* nodep, const string& scopename) { - if (!abovep) nodep->v3fatalSrc("Null symbol table inserting node"); + UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9," INSERTcel se"<v3fatalSrc("Null symbol table inserting node"); + UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9," INSERTinl se"<v3fatalSrc("Null symbol table inserting node"); + UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9," INSERTblk se"<name()); - if (it == m_nameScopeSymMap.end()) { - nodep->v3fatalSrc("Scope never assigned a symbol entry?"); - } + UASSERT_OBJ(it != m_nameScopeSymMap.end(), nodep, + "Scope never assigned a symbol entry?"); return it->second; } void implicitOkAdd(AstNodeModule* nodep, const string& varname) { @@ -401,7 +400,7 @@ public: AstVar* varp = varSymp ? VN_CAST(varSymp->nodep(), Var) : NULL; UINFO(9, " insAllIface se"<subDTypep()); - if (!ifacerefp) varp->v3fatalSrc("Non-ifacerefs on list!"); + UASSERT_OBJ(ifacerefp, varp, "Non-ifacerefs on list!"); if (!ifacerefp->ifaceViaCellp()) { if (!ifacerefp->cellp()) { // Probably a NotFoundModule, or a normal module if made mistake ifacerefp->v3error("Cannot find file containing interface: " @@ -444,10 +443,9 @@ public: // a child cell connecting to that interface // Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell UINFO(9," insertScopeAlias se"<nodep(), Cell) - && !VN_IS(VN_CAST(rhsp->nodep(), Cell)->modp(), Iface)) { - rhsp->nodep()->v3fatalSrc("Got a non-IFACE alias RHS"); - } + UASSERT_OBJ(!(VN_IS(rhsp->nodep(), Cell) + && !VN_IS(VN_CAST(rhsp->nodep(), Cell)->modp(), Iface)), + rhsp->nodep(), "Got a non-IFACE alias RHS"); m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp)); } void computeScopeAliases() { @@ -714,7 +712,7 @@ class LinkDotFindVisitor : public AstNVisitor { <origName())); } else if (doit) { UINFO(4," Link Module: "<dead()) nodep->v3fatalSrc("Module in cell tree mislabeled as dead?"); + UASSERT_OBJ(!nodep->dead(), nodep, "Module in cell tree mislabeled as dead?"); VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); m_packagep = VN_CAST(nodep, Package); if (standalonePkg) { @@ -757,7 +755,8 @@ class LinkDotFindVisitor : public AstNVisitor { m_packagep = NULL; } virtual void visit(AstScope* nodep) { - if (!m_statep->forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope"); + UASSERT_OBJ(m_statep->forScopeCreation(), nodep, + "Scopes should only exist right after V3Scope"); // Ignored. Processed in next step } virtual void visit(AstCell* nodep) { @@ -782,10 +781,9 @@ class LinkDotFindVisitor : public AstNVisitor { string baddot; VSymEnt* okSymp; aboveSymp = m_statep->findDotted(aboveSymp, scope, baddot, okSymp); - if (!aboveSymp) { - nodep->v3fatalSrc("Can't find cell insertion point at '" - <prettyName()); - } + UASSERT_OBJ(aboveSymp, nodep, + "Can't find cell insertion point at '" + <prettyName()); } { m_scope = m_scope+"."+nodep->name(); @@ -814,10 +812,9 @@ class LinkDotFindVisitor : public AstNVisitor { string baddot; VSymEnt* okSymp; aboveSymp = m_statep->findDotted(aboveSymp, dotted, baddot, okSymp); - if (!aboveSymp) { - nodep->v3fatalSrc("Can't find cellinline insertion point at '" - <prettyName()); - } + UASSERT_OBJ(aboveSymp, nodep, + "Can't find cellinline insertion point at '" + <prettyName()); m_statep->insertInline(aboveSymp, m_modSymp, nodep, ident); } else { // No __DOT__, just directly underneath m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name()); @@ -882,7 +879,7 @@ class LinkDotFindVisitor : public AstNVisitor { virtual void visit(AstNodeFTask* nodep) { // NodeTask: Remember its name for later resolution UINFO(5," "<v3fatalSrc("Function/Task not under module?"); + UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Function/Task not under module?"); // Remember the existing symbol table scope VSymEnt* oldCurSymp = m_curSymp; { @@ -917,7 +914,7 @@ class LinkDotFindVisitor : public AstNVisitor { } virtual void visit(AstVar* nodep) { // Var: Remember its name for later resolution - if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Var not under module?"); + UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?"); iterateChildren(nodep); if (!m_statep->forScopeCreation()) { // Find under either a task or the module's vars @@ -965,7 +962,8 @@ class LinkDotFindVisitor : public AstNVisitor { // Then have "input foo" and "real foo" so the // dtype comes from the other side. AstNodeDType* newdtypep = nodep->subDTypep(); - if (!newdtypep || !nodep->childDTypep()) findvarp->v3fatalSrc("No child type?"); + UASSERT_OBJ(newdtypep && nodep->childDTypep(), findvarp, + "No child type?"); bdtypep->unlinkFrBack()->deleteTree(); newdtypep->unlinkFrBack(); findvarp->childDTypep(newdtypep); @@ -1027,18 +1025,18 @@ class LinkDotFindVisitor : public AstNVisitor { } virtual void visit(AstTypedef* nodep) { // Remember its name for later resolution - if (!m_curSymp) nodep->v3fatalSrc("Typedef not under module?"); + UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module?"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } virtual void visit(AstParamTypeDType* nodep) { - if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module?"); + UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module?"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } virtual void visit(AstCFunc* nodep) { // For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist - if (m_statep->forScopeCreation()) nodep->v3fatalSrc("No CFuncs expected in tree yet"); + UASSERT_OBJ(!m_statep->forScopeCreation(), nodep, "No CFuncs expected in tree yet"); } virtual void visit(AstEnumItem* nodep) { // EnumItem: Remember its name for later resolution @@ -1186,7 +1184,8 @@ private: UINFO(5," "<dead() || !nodep->user4()) { UINFO(4,"Mark dead module "<forPrearray()) nodep->v3fatalSrc("Dead module persisted past where should have removed"); + UASSERT_OBJ(m_statep->forPrearray(), nodep, + "Dead module persisted past where should have removed"); // Don't remove now, because we may have a tree of // parameterized modules with VARXREFs into the deleted module // region. V3Dead should cleanup. @@ -1266,7 +1265,7 @@ private: virtual void visit(AstAssignAlias* nodep) { // 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"); + UASSERT_OBJ(!m_statep->forPrimary(), nodep, "Assign aliases unexpected pre-dot"); if (AstVarRef* forrefp = VN_CAST(nodep->lhsp(), VarRef)) { pinImplicitExprRecurse(forrefp); } @@ -1317,7 +1316,8 @@ class LinkDotScopeVisitor : public AstNVisitor { } virtual void visit(AstScope* nodep) { UINFO(8," SCOPE "<forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope"); + UASSERT_OBJ(m_statep->forScopeCreation(), nodep, + "Scopes should only exist right after V3Scope"); // Using the CELL names, we created all hierarchy. We now need to match this Scope // up with the hierarchy created by the CELL names. m_modSymp = m_statep->getScopeSym(nodep); @@ -1335,20 +1335,21 @@ class LinkDotScopeVisitor : public AstNVisitor { // Find the interface cell the var references AstIfaceRefDType* dtypep = LinkDotState::ifaceRefFromArray(nodep->varp()->dtypep()); - if (!dtypep) nodep->v3fatalSrc("Non AstIfaceRefDType on isIfaceRef() var"); + UASSERT_OBJ(dtypep, nodep, "Non AstIfaceRefDType on isIfaceRef() var"); UINFO(9,"Iface parent dtype "<cellName(); string baddot; VSymEnt* okSymp; VSymEnt* cellSymp = m_statep->findDotted(m_modSymp, ifcellname, baddot, okSymp); - if (!cellSymp) nodep->v3fatalSrc("No symbol for interface cell: " - <prettyName(ifcellname)); + UASSERT_OBJ(cellSymp, nodep, + "No symbol for interface cell: "<prettyName(ifcellname)); UINFO(5, " Found interface cell: se"<nodep()<modportName()!="") { VSymEnt* mpSymp = m_statep->findDotted(m_modSymp, ifcellname, baddot, okSymp); - if (!mpSymp) { nodep->v3fatalSrc("No symbol for interface modport: " - <prettyName(dtypep->modportName())); } - else cellSymp = mpSymp; + UASSERT_OBJ(mpSymp, nodep, + "No symbol for interface modport: " + <prettyName(dtypep->modportName())); + cellSymp = mpSymp; UINFO(5, " Found modport cell: se" <nodep()<=9) nodep->dumpTree(cout, "-\t\t\t\talias: "); AstVarScope* fromVscp = VN_CAST(nodep->lhsp(), VarRef)->varScopep(); AstVarScope* toVscp = VN_CAST(nodep->rhsp(), VarRef)->varScopep(); - if (!fromVscp || !toVscp) nodep->v3fatalSrc("Bad alias scopes"); + UASSERT_OBJ(fromVscp && toVscp, nodep, "Bad alias scopes"); fromVscp->user2p(toVscp); iterateChildren(nodep); } @@ -1381,7 +1382,8 @@ class LinkDotScopeVisitor : public AstNVisitor { { 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"); + UASSERT_OBJ(refp || xrefp, nodep, + "Unsupported: Non Var(X)Ref attached to interface pin"); string inl = ((xrefp && xrefp->inlinedDots().size()) ? (xrefp->inlinedDots() + "__DOT__") : ""); VSymEnt* symp = NULL; @@ -1397,7 +1399,7 @@ class LinkDotScopeVisitor : public AstNVisitor { } if (!symp) UINFO(9,"No symbol for interface alias rhs (" <v3fatalSrc("No symbol for interface alias rhs"); + UASSERT_OBJ(symp, nodep, "No symbol for interface alias rhs"); UINFO(5, " Found a linked scope RHS: "<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"); + UASSERT_OBJ(refp || xrefp, nodep, + "Unsupported: Non Var(X)Ref attached to interface pin"); string scopename = refp ? refp->varp()->name() : xrefp->dotted()+"."+xrefp->name(); string baddot; VSymEnt* okSymp; VSymEnt* symp = m_statep->findDotted(m_modSymp, scopename, baddot, okSymp); - if (!symp) nodep->v3fatalSrc("No symbol for interface alias lhs"); + UASSERT_OBJ(symp, nodep, "No symbol for interface alias lhs"); UINFO(5, " Found a linked scope LHS: "<nodep()<modp()) { - nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out - } - else { + UASSERT_OBJ(nodep->modp(), nodep, + "Cell has unlinked module"); // V3LinkCell should have errored out + { if (VN_IS(nodep->modp(), NotFoundModule)) { // Prevent warnings about missing pin connects if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree(); @@ -1751,7 +1753,7 @@ private: checkNoDot(nodep); iterateChildren(nodep); if (!nodep->modVarp()) { - if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?"); + UASSERT_OBJ(m_pinSymp, nodep, "Pin not under cell?"); VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name()); const char* whatp = nodep->param() ? "parameter pin" : "pin"; if (!foundp) { @@ -1852,8 +1854,8 @@ private: UINFO(9," linkPARSEREF "<v3fatalSrc("NULL lookup symbol table"); - if (!m_statep->forPrimary()) nodep->v3fatalSrc("ParseRefs should no longer exist"); + UASSERT_OBJ(m_ds.m_dotSymp, nodep, "NULL lookup symbol table"); + UASSERT_OBJ(m_statep->forPrimary(), nodep, "ParseRefs should no longer exist"); DotStates lastStates = m_ds; bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed if (start) { @@ -1879,11 +1881,10 @@ private: expectWhat = "scope/variable"; allowScope = true; allowVar = true; - if (!VN_IS(m_ds.m_dotp->lhsp(), PackageRef)) { - m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); - } + UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), + m_ds.m_dotp->lhsp(), "Bad package link"); packagep = VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(); - if (!packagep) m_ds.m_dotp->lhsp()->v3fatalSrc("Bad package link"); + UASSERT_OBJ(packagep, m_ds.m_dotp->lhsp(), "Bad package link"); m_ds.m_dotSymp = m_statep->getNodeSym(packagep); m_ds.m_dotPos = DP_SCOPE; } else if (m_ds.m_dotPos == DP_SCOPE) { @@ -1931,13 +1932,13 @@ private: 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"); + UASSERT_OBJ(cellEntp, nodep, "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 ? VN_CAST(ifaceSymp->nodep(), Var) : NULL; - if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: " - <name()); @@ -1956,7 +1957,7 @@ private: else if (AstVar* varp = foundToVarp(foundp, nodep, false)) { AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(varp->subDTypep()); if (ifacerefp) { - if (!ifacerefp->ifaceViaCellp()) ifacerefp->v3fatalSrc("Unlinked interface"); + UASSERT_OBJ(ifacerefp->ifaceViaCellp(), ifacerefp, "Unlinked interface"); // Really this is a scope reference into an interface UINFO(9,"varref-ifaceref "<name()); @@ -2011,7 +2012,7 @@ private: <prettyName()); } else { AstCell* cellp = VN_CAST(m_ds.m_dotSymp->nodep(), Cell); - if (!cellp) nodep->v3fatalSrc("Modport not referenced from a cell"); + UASSERT_OBJ(cellp, nodep, "Modport not referenced from a cell"); AstIface* ifacep = VN_CAST(cellp->modp(), Iface); //string cellName = m_ds.m_dotText; // Use cellp->name m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name()); @@ -2081,7 +2082,7 @@ private: iterateChildren(nodep); if (!nodep->varp()) { UINFO(9," linkVarRef se"<findIdFallback(nodep->name()); if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : NULL) { nodep->varp(varp); @@ -2110,10 +2111,9 @@ private: dotSymp = m_modSymp; // Dotted lookup is always relative to module, as maybe variable name lower down with same scope name we want to ignore (t_math_divw) string inl = AstNode::dedotName(nodep->inlinedDots()); dotSymp = m_statep->findDotted(dotSymp, inl, baddot, okSymp); - if (!dotSymp) { - nodep->v3fatalSrc("Couldn't resolve inlined scope '" - <inlinedDots()); - } + UASSERT_OBJ(dotSymp, nodep, + "Couldn't resolve inlined scope '" + <inlinedDots()); } dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, okSymp); // Maybe NULL if (!m_statep->forScopeCreation()) { @@ -2190,12 +2190,10 @@ private: if (nodep->user3SetOnce()) return; UINFO(8," "<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"); - } + UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), + m_ds.m_dotp->lhsp(), "Bad package link"); + UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), + m_ds.m_dotp->lhsp(), "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; @@ -2369,12 +2367,10 @@ private: // Resolve its reference if (nodep->user3SetOnce()) return; if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { - 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"); - } + UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), + m_ds.m_dotp->lhsp(), "Bad package link"); + UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), + m_ds.m_dotp->lhsp(), "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; diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 8436f646b..05ac4f506 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -81,12 +81,10 @@ private: // Also this would otherwise prevent us from using a label twice // see t_func_return test. 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 (VN_IS(underp, JumpLabel)) { + 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); diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index b619dab40..1c3b618c3 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -80,7 +80,7 @@ void V3LinkLevel::modSortByLevel() { // pointers, may have a stale m_iterp() needing cleanup nodep->unlinkFrBack(); } - if (v3Global.rootp()->modulesp()) v3Global.rootp()->v3fatalSrc("Unlink didn't work"); + UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work"); for (ModVec::iterator it = vec.begin(); it != vec.end(); ++it) { AstNodeModule* nodep = *it; v3Global.rootp()->addModulep(nodep); @@ -132,7 +132,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { AstNodeModule* newmodp = rootp->modulesp(); - if (!newmodp || !newmodp->isTop()) rootp->v3fatalSrc("No TOP module found to insert under"); + UASSERT_OBJ(newmodp && newmodp->isTop(), rootp, "No TOP module found to insert under"); // Find all duplicate signal names (if multitop) typedef vl_unordered_set NameSet; diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 53eecbd63..e11a55a38 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -241,62 +241,62 @@ private: iterateChildren(nodep); if (nodep->attrType() == AstAttrType::DT_PUBLIC) { AstTypedef* typep = VN_CAST(nodep->backp(), Typedef); - if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef"); + UASSERT_OBJ(typep, nodep, "Attribute not attached to typedef"); typep->attrPublic(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_CLOCK) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrScClocked(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClockEn(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRWPublic(true); m_varp->sigModPublic(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRWPublic(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRdPublic(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRWPublic(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrIsolateAssign(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrSFormat(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_SC_BV) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrScBv(true); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClocker(AstVarAttrClocker::CLOCKER_YES); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) { - if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClocker(AstVarAttrClocker::CLOCKER_NO); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } @@ -337,7 +337,8 @@ private: 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"); + UASSERT_OBJ(backp, nodep, + "Implicit enum/struct type created under unexpected node type"); AstNodeDType* dtypep = nodep->childDTypep(); dtypep->unlinkFrBack(); 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 diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index a075f0455..06065dc95 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -240,12 +240,12 @@ private: virtual void visit(AstPragma* nodep) { if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) { - if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module"); + UASSERT_OBJ(m_modp, nodep, "PUBLIC_MODULE not under a module"); m_modp->modPublic(true); nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep); } else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) { - if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task"); + UASSERT_OBJ(m_ftaskp, nodep, "PUBLIC_TASK not under a task"); m_ftaskp->taskPublic(true); m_modp->modPublic(true); // Need to get to the task... nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep); @@ -387,7 +387,7 @@ private: iterateChildren(nodep); // Cleanup old-school displays without format arguments if (!nodep->hasFormat()) { - if (nodep->text()!="") nodep->v3fatalSrc("Non-format $sformatf should have \"\" format"); + UASSERT_OBJ(nodep->text()=="", nodep, "Non-format $sformatf should have \"\" format"); if (VN_IS(nodep->exprsp(), Const) && VN_CAST(nodep->exprsp(), Const)->num().isFromString()) { AstConst* fmtp = VN_CAST(nodep->exprsp()->unlinkFrBack(), Const); diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index aad36a43e..b9095d18f 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -173,7 +173,7 @@ private: for (; nodep; nodep=nodep->nextp()) { 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"); + UASSERT_OBJ(varrefp->lvalue(), varrefp, "LHS assignment not lvalue"); if (!varrefp->varp()->user4p()) { UINFO(4," FuncAsn "<varp()->user4p(varrefp); diff --git a/src/V3Order.cpp b/src/V3Order.cpp index fe7a32dcf..1e9f04d3f 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -202,7 +202,7 @@ public: // METHODS OrderVarVertex* newVarUserVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varscp, WhichVertex type, bool* createdp=NULL) { - if (type>=WV_MAX) varscp->v3fatalSrc("Bad case"); + UASSERT_OBJ(type < WV_MAX, varscp, "Bad case"); OrderVarVertex* vertexp = m_vertexp[type]; if (!vertexp) { UINFO(6,"New vertex "<sensesp()) nodep->v3fatalSrc("NULL"); + UASSERT_OBJ(m_activep && m_activep->sensesp(), nodep, "NULL"); // If inside combo logic, ignore the domain, we'll assign one based on interconnect AstSenTree* startDomainp = m_activep->sensesp(); if (startDomainp->hasCombo()) startDomainp=NULL; @@ -963,7 +963,7 @@ private: } virtual void visit(AstTopScope* nodep) { // Process the last thing we're finishing - if (m_topScopep) nodep->v3fatalSrc("Only one topscope should ever be created"); + UASSERT_OBJ(!m_topScopep, nodep, "Only one topscope should ever be created"); UINFO(2," Loading tree...\n"); //VV***** We reset userp() AstNode::user1ClearTree(); @@ -1022,7 +1022,8 @@ private: m_activeSenVxp = NULL; m_inClocked = nodep->hasClocked(); // Grab the sensitivity list - if (nodep->sensesStorep()) nodep->v3fatalSrc("Senses should have been activeTop'ed to be global!"); + UASSERT_OBJ(!nodep->sensesStorep(), nodep, + "Senses should have been activeTop'ed to be global!"); iterate(nodep->sensesp()); // Collect statements under it iterateChildren(nodep); @@ -1040,15 +1041,15 @@ private: virtual void visit(AstNodeVarRef* nodep) { if (m_scopep) { AstVarScope* varscp = nodep->varScopep(); - if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp"); + UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); if (m_inSenTree) { // Add CLOCK dependency... This is a root of the tree we'll trace - if (nodep->lvalue()) nodep->v3fatalSrc("How can a sensitivity be setting a var?"); + UASSERT_OBJ(!nodep->lvalue(), nodep, "How can a sensitivity be setting a var?"); OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_STD); varVxp->isClock(true); new OrderEdge(&m_graph, varVxp, m_activeSenVxp, WEIGHT_MEDIUM); } else { - if (!m_logicVxp) nodep->v3fatalSrc("Var ref not under a logic block"); + UASSERT_OBJ(m_logicVxp, nodep, "Var ref not under a logic block"); // What new directions is this used // We don't want to add extra edges if the logic block has many usages of same var bool gen = false; @@ -1307,8 +1308,8 @@ static bool domainsExclusive(const AstSenTree* fromp, const AstSenTree* top) { 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"); - if (!toSenListp) top->v3fatalSrc("sensitivity list item is not an AstSenItem"); + UASSERT_OBJ(fromSenListp, fromp, "sensitivity list item is not an AstSenItem"); + UASSERT_OBJ(toSenListp, top, "sensitivity list item is not an AstSenItem"); if (fromSenListp->nextp()) return false; if (toSenListp->nextp()) return false; @@ -1337,9 +1338,8 @@ inline void OrderMoveDomScope::ready(OrderVisitor* ovp) { // Mark one vertex as finished, remove from ready list if done inline void OrderMoveDomScope::movedVertex(OrderVisitor* ovp, OrderMoveVertex* vertexp) { - if (!m_onReadyList) { - vertexp->v3fatalSrc("Moving vertex from ready when nothing was on que as ready."); - } + UASSERT_OBJ(m_onReadyList, vertexp, + "Moving vertex from ready when nothing was on que as ready."); if (m_readyVertices.empty()) { // Else more work to get to later m_onReadyList = false; m_readyDomScopeE.unlink(ovp->m_pomReadyDomScope, this); @@ -1406,9 +1406,8 @@ void OrderVisitor::processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec // First make sure input path is fully recursed processInputsInIterate(vertexp, todoVec); // Propagate PrimaryIn through simple assignments - if (!vertexp->isFromInput()) { - vertexp->v3fatalSrc("processInputsOutIterate only for input marked vertexes"); - } + UASSERT_OBJ(vertexp->isFromInput(), vertexp, + "processInputsOutIterate only for input marked vertexes"); vertexp->user(3); // out-edges processed { @@ -1460,7 +1459,7 @@ void OrderVisitor::processCircular() { for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { if (edgep->weight()==0) { // was cut OrderEdge* oedgep = dynamic_cast(edgep); - if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type"); + UASSERT_OBJ(oedgep, vvertexp->varScp(), "Cuttable edge not of proper type"); UINFO(6," CutCircularO: "<name()<inBeginp(); edgep; edgep = edgep->inNextp()) { if (edgep->weight()==0) { // was cut OrderEdge* oedgep = dynamic_cast(edgep); - if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type"); + UASSERT_OBJ(oedgep, vvertexp->varScp(), "Cuttable edge not of proper type"); UINFO(6," CutCircularI: "<name()<cloneTree(false); AstNodeSenItem* newtree2p = fromVertexp->domainp()->sensesp()->cloneTree(true); - if (!newtree2p) fromVertexp->domainp()->v3fatalSrc("No senitem found under clocked domain"); + UASSERT_OBJ(newtree2p, fromVertexp->domainp(), + "No senitem found under clocked domain"); newtreep->addSensesp(newtree2p); newtree2p = NULL; // Below edit may replace it V3Const::constifyExpensiveEdit(newtreep); // Remove duplicates @@ -1759,9 +1759,7 @@ void OrderVisitor::processMoveDoneOne(OrderMoveVertex* vertexp) { void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* domScopep, int level) { - if (vertexp->domScopep() != domScopep) { - vertexp->v3fatalSrc("Domain mismatch; list misbuilt?"); - } + UASSERT_OBJ(vertexp->domScopep() == domScopep, vertexp, "Domain mismatch; list misbuilt?"); const OrderLogicVertex* lvertexp = vertexp->logicp(); const AstScope* scopep = lvertexp->scopep(); UINFO(5," POSmove l"<modVarp()<find(pinp->modVarp()); - if (cloneiter == clonemapp->end()) { - pinp->v3fatalSrc("Couldn't find pin in clone list"); - } + UASSERT_OBJ(cloneiter != clonemapp->end(), pinp, + "Couldn't find pin in clone list"); pinp->modVarp(VN_CAST(cloneiter->second, Var)); } else if (pinp->modPTypep()) { CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep()); - if (cloneiter == clonemapp->end()) { - pinp->v3fatalSrc("Couldn't find pin in clone list"); - } + UASSERT_OBJ(cloneiter != clonemapp->end(), pinp, + "Couldn't find pin in clone list"); pinp->modPTypep(VN_CAST(cloneiter->second, ParamTypeDType)); } else { @@ -318,7 +316,7 @@ private: return true; } else if (AstPin* pinp = VN_CAST(candp, Pin)) { UINFO(9,"Found interface parameter: "<exprp()) pinp->v3fatalSrc("Interface parameter pin missing expression"); + UASSERT_OBJ(pinp->exprp(), pinp, "Interface parameter pin missing expression"); nodep->replaceWith(pinp->exprp()->cloneTree(false)); VL_DANGLING(nodep); return true; } @@ -455,7 +453,7 @@ private: virtual void visit(AstBegin* nodep) { if (nodep->genforp()) { AstGenFor* forp = VN_CAST(nodep->genforp(), GenFor); - if (!forp) nodep->v3fatalSrc("Non-GENFOR under generate-for BEGIN"); + UASSERT_OBJ(forp, nodep, "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 UINFO(9," BEGIN "<modp()) nodep->v3fatalSrc("Not linked?"); + UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); // We always run this, even if no parameters, as need to look for interfaces, // and remove any recursive references { @@ -777,7 +775,8 @@ void ParamVisitor::visitCell(AstCell* nodep) { AstIfaceRefDType* cloneIrefp = portIrefp->clonep(); UINFO(8," IfaceOld "<v3fatalSrc("parameter clone didn't hit AstIfaceRefDType"); + UASSERT_OBJ(cloneIrefp, portIrefp, + "parameter clone didn't hit AstIfaceRefDType"); UINFO(8," IfaceClo "<ifacep(pinIrefp->ifaceViaCellp()); UINFO(8," IfaceNew "<modPTypep()) { AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); - if (!dtypep) pinp->v3fatalSrc("unlinked param dtype"); + UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); if (modptp->childDTypep()) { pushDeletep(modptp->childDTypep()->unlinkFrBack()); } diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index fbe43d095..420070526 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -109,9 +109,8 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, if (prevp) nrangep->unlinkFrBack(); AstRange* rangep = VN_CAST(nrangep, Range); if (!rangep) { - if (VL_UNCOVERABLE(!VN_IS(nrangep, UnsizedRange))) { - nrangep->v3fatalSrc("Expected range or unsized range"); - } + UASSERT_OBJ(VN_IS(nrangep, UnsizedRange), nrangep, + "Expected range or unsized range"); arrayp = new AstUnsizedArrayDType (nrangep->fileline(), VFlagChildDType(), arrayp); } else if (isPacked) { diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 4ba9e17b0..622261058 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -60,7 +60,7 @@ public: private: // METHODS static VSymEnt* getTable(AstNode* nodep) { - if (!nodep->user4p()) nodep->v3fatalSrc("Current symtable not found"); + UASSERT_OBJ(nodep->user4p(), nodep, "Current symtable not found"); return nodep->user4u().toSymEnt(); } @@ -116,7 +116,7 @@ public: return; } m_sympStack.pop_back(); - if (m_sympStack.empty()) { nodep->v3fatalSrc("symbol stack underflow"); return; } + UASSERT_OBJ(!m_sympStack.empty(), nodep, "symbol stack underflow"); m_symCurrentp = m_sympStack.back(); } void showUpward() { @@ -139,10 +139,9 @@ public: void importItem(AstNode* packagep, const string& id_or_star) { // Import from package::id_or_star to this VSymEnt* symp = getTable(packagep); - if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE - packagep->v3fatalSrc("Import package not found"); - return; - } + UASSERT_OBJ(symp, packagep, + // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE + "Import package not found"); // Walk old sym table and reinsert into current table // We let V3LinkDot report the error instead of us symCurrentp()->importFromPackage(&m_syms, symp, id_or_star); @@ -150,10 +149,9 @@ public: void exportItem(AstNode* packagep, const string& id_or_star) { // Export from this the remote package::id_or_star VSymEnt* symp = getTable(packagep); - if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE - packagep->v3fatalSrc("Export package not found"); - return; - } + UASSERT_OBJ(symp, packagep, + // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE + "Export package not found"); symCurrentp()->exportFromPackage(&m_syms, symp, id_or_star); } void exportStarStar(AstNode* packagep) { diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 2fb7b7073..80001e420 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -314,7 +314,7 @@ private: // important property of PartPropagateCp which allows it to be far // faster than a recursive algorithm on some graphs. CpMap::iterator it = m_seen.find(vxp); - if (it != m_seen.end()) vxp->v3fatalSrc("Set CP on node twice"); + UASSERT_OBJ(it == m_seen.end(), vxp, "Set CP on node twice"); m_seen[vxp] = cost; } uint32_t critPathCost(V3GraphVertex* vxp, GraphWay way) const { @@ -452,7 +452,7 @@ public: // This is mtaskp's relative with longest !wayward inclusive CP: EdgeSet::reverse_iterator edgeIt = edges.rbegin(); uint32_t edgeCp = (*edgeIt).value(); - if (edgeCp != cp) vxp->v3fatalSrc("CP doesn't match longest wayward edge"); + UASSERT_OBJ(edgeCp == cp, vxp, "CP doesn't match longest wayward edge"); } private: VL_UNCOPYABLE(CpCostAccessor); @@ -988,12 +988,10 @@ static void partInitHalfCriticalPaths(GraphWay way, V3Graph* mtasksp, bool check edgep; edgep = edgep->nextp(rev)) { // Run a few asserts on the initial mtask graph, // while we're iterating through... - if (edgep->weight() == 0) { - mtaskp->v3fatalSrc("Should be no cut edges in mtasks graph"); - } - if (relatives.find(edgep->furtherp(rev)) != relatives.end()) { - mtaskp->v3fatalSrc("Should be no redundant edges in mtasks graph"); - } + UASSERT_OBJ(edgep->weight() != 0, mtaskp, + "Should be no cut edges in mtasks graph"); + UASSERT_OBJ(relatives.find(edgep->furtherp(rev)) == relatives.end(), mtaskp, + "Should be no redundant edges in mtasks graph"); relatives.insert(edgep->furtherp(rev)); LogicMTask* relativep @@ -1187,9 +1185,8 @@ public: for (V3GraphEdge* edgep = itp->outBeginp(); edgep; edgep=edgep->outNextp()) { m_sb.addElem(MTaskEdge::cast(edgep)); - if (neighbors.find(edgep->top()) != neighbors.end()) { - itp->v3fatalSrc("Redundant edge found in input to PartContraction()"); - } + UASSERT_OBJ(neighbors.find(edgep->top()) == neighbors.end(), itp, + "Redundant edge found in input to PartContraction()"); neighbors.insert(edgep->top()); } siblingPairFromRelatives(GraphWay::REVERSE, itp, true); @@ -1352,12 +1349,12 @@ private: LogicMTask* otherp = (pairp->bp() == mtaskp) ? pairp->ap() : pairp->bp(); size_t erased = m_mtask2sibs[otherp].erase(pairp); - if (erased <= 0) otherp->v3fatalSrc("Expected existing mtask"); + UASSERT_OBJ(erased > 0, otherp, "Expected existing mtask"); erased = m_pairs.erase(*pairp); - if (erased <= 0) mtaskp->v3fatalSrc("Expected existing mtask"); + UASSERT_OBJ(erased > 0, mtaskp, "Expected existing mtask"); } size_t erased = m_mtask2sibs.erase(mtaskp); - if (erased <= 0) mtaskp->v3fatalSrc("Expected existing mtask"); + UASSERT_OBJ(erased > 0, mtaskp, "Expected existing mtask"); } void contract(MergeCandidate* mergeCanp) { @@ -1571,24 +1568,21 @@ private: } else if (m_slowAsserts) { // It's fine if we already have this SiblingMC, we may have // created it earlier. Just confirm that we have associated data. - if (m_mtask2sibs.find(ap) == m_mtask2sibs.end()) { - ap->v3fatalSrc("Sibling not found"); - } - if (m_mtask2sibs.find(bp) == m_mtask2sibs.end()) { - bp->v3fatalSrc("Sibling not found"); - } + UASSERT_OBJ(m_mtask2sibs.find(ap) != m_mtask2sibs.end(), ap, + "Sibling not found"); + UASSERT_OBJ(m_mtask2sibs.find(bp) != m_mtask2sibs.end(), bp, + "Sibling not found"); bool found = false; for (SibpSet::iterator it = m_mtask2sibs[ap].begin(); it != m_mtask2sibs[ap].end(); ++it) { const SiblingMC* sibsp = *it; - if (!sibsp->removedFromSb() && !m_sb.contains(sibsp)) { - ap->v3fatalSrc("One sibling must be the one we collided with"); - } + UASSERT_OBJ(!(!sibsp->removedFromSb() && !m_sb.contains(sibsp)), ap, + "One sibling must be the one we collided with"); if ( (sibsp->ap() == ap && sibsp->bp() == bp) || (sibsp->bp() == ap && sibsp->ap() == bp)) found = true; } - if (!found) ap->v3fatalSrc("Sibling not found"); + UASSERT_OBJ(found, ap, "Sibling not found"); } }; @@ -1955,7 +1949,7 @@ private: while (!rankIt->second.empty()) { LogicMTaskSet::iterator begin = rankIt->second.begin(); LogicMTask* donorp = *begin; - if (donorp == mergedp) donorp->v3fatalSrc("Donor can't be merged edge"); + UASSERT_OBJ(donorp != mergedp, donorp, "Donor can't be merged edge"); rankIt->second.erase(begin); // Merge donorp into mergedp. // Fix up the map, so donor's OLVs map to mergedp @@ -1976,9 +1970,8 @@ private: } if (lastMergedp) { - if (lastMergedp->rank() >= mergedp->rank()) { - mergedp->v3fatalSrc("Merging must be on lower rank"); - } + UASSERT_OBJ(lastMergedp->rank() < mergedp->rank(), mergedp, + "Merging must be on lower rank"); if (!lastMergedp->hasRelative(GraphWay::FORWARD, mergedp)) { new MTaskEdge(m_mtasksp, lastMergedp, mergedp, 1); } @@ -2309,7 +2302,7 @@ public: // Update the ready list size_t erased = m_ready.erase(bestMtaskp); - if (erased <= 0) bestMtaskp->v3fatalSrc("Should have erased something?"); + UASSERT_OBJ(erased > 0, bestMtaskp, "Should have erased something?"); for (V3GraphEdge* edgeOutp = bestMtaskp->outBeginp(); edgeOutp; edgeOutp = edgeOutp->outNextp()) { ExecMTask* nextp = dynamic_cast(edgeOutp->top()); @@ -2318,9 +2311,8 @@ public: "Tasks after one being assigned should not be assigned yet"); // They also should not be ready yet, since they only now // may become ready - if (m_ready.find(nextp) != m_ready.end()) { - nextp->v3fatalSrc("Tasks after one being assigned should not be ready"); - } + UASSERT_OBJ(m_ready.find(nextp) == m_ready.end(), nextp, + "Tasks after one being assigned should not be ready"); bool isReady = true; for (V3GraphEdge* edgeInp = nextp->inBeginp(); edgeInp; edgeInp = edgeInp->inNextp()) { @@ -2514,7 +2506,7 @@ void V3Partition::setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp) UASSERT(it != vx2mtaskp->end(), "MTask map can't find id"); LogicMTask* otherMTaskp = it->second; UASSERT(otherMTaskp, "NULL other Mtask"); - if (otherMTaskp == mtaskp) mtaskp->v3fatalSrc("Would create a cycle edge"); + UASSERT_OBJ(otherMTaskp != mtaskp, mtaskp, "Would create a cycle edge"); // Don't create redundant edges. if (mtaskp->hasRelative(GraphWay::FORWARD, otherMTaskp)) { @@ -2543,7 +2535,7 @@ void V3Partition::go(V3Graph* mtasksp) { for (V3GraphVertex* vxp = m_fineDepsGraphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { MTaskMoveVertex* mtmvVxp = dynamic_cast(vxp); - if (!mtmvVxp) vxp->v3fatalSrc("Every vertex here should be an MTaskMoveVertex"); + UASSERT_OBJ(mtmvVxp, vxp, "Every vertex here should be an MTaskMoveVertex"); LogicMTask* mtaskp = new LogicMTask(mtasksp, mtmvVxp); vx2mtask[mtmvVxp] = mtaskp; diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 34a13eece..3389dc662 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -82,7 +82,7 @@ private: string newvarname = string("__Vilp"); varp = new AstVar(fl, AstVarType::STMTTEMP, newvarname, VFlagLogicPacked(), 32); - if (!cfuncp) fl->v3fatalSrc("Assignment not under a function"); + UASSERT_OBJ(cfuncp, fl, "Assignment not under a function"); cfuncp->addInitsp(varp); cfuncp->user1p(varp); } @@ -101,7 +101,7 @@ private: // Transform first assign into for loop body AstNodeAssign* bodyp = m_mgAssignps.front(); - if (bodyp->lhsp() != m_mgSelLp) bodyp->v3fatalSrc("Corrupt queue/state"); + UASSERT_OBJ(bodyp->lhsp() == m_mgSelLp, bodyp, "Corrupt queue/state"); FileLine* fl = bodyp->fileline(); AstVar* itp = findCreateVarTemp(fl, m_mgCfuncp); diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 568cbf786..d18dfc04b 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -77,11 +77,11 @@ private: AstScope* scopep = it->second; if (nodep->packagep()) { PackageScopeMap::iterator it2 = m_packageScopes.find(nodep->packagep()); - if (it2==m_packageScopes.end()) nodep->v3fatalSrc("Can't locate package scope"); + UASSERT_OBJ(it2 != m_packageScopes.end(), nodep, "Can't locate package scope"); scopep = it2->second; } VarScopeMap::iterator it3 = m_varScopes.find(make_pair(nodep->varp(), scopep)); - if (it3==m_varScopes.end()) nodep->v3fatalSrc("Can't locate varref scope"); + UASSERT_OBJ(it3 != m_varScopes.end(), nodep, "Can't locate varref scope"); AstVarScope* varscp = it3->second; nodep->varScopep(varscp); } @@ -124,7 +124,7 @@ private: m_aboveCellp = cellp; m_aboveScopep = m_scopep; AstNodeModule* modp = cellp->modp(); - if (!modp) cellp->v3fatalSrc("Unlinked mod"); + UASSERT_OBJ(modp, cellp, "Unlinked mod"); iterate(modp); // Recursive call to visit(AstNodeModule) } // Done, restore vars @@ -251,7 +251,7 @@ private: if (v3Global.opt.isNoClocker(varscp->prettyName())) { nodep->attrClocker(AstVarAttrClocker::CLOCKER_NO); } - if (!m_scopep) nodep->v3fatalSrc("No scope for var"); + UASSERT_OBJ(m_scopep, nodep, "No scope for var"); m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp)); m_scopep->addVarp(varscp); } @@ -259,7 +259,7 @@ private: virtual void visit(AstVarRef* nodep) { // VarRef needs to point to VarScope // Make sure variable has made user1p. - if (!nodep->varp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->varp(), nodep, "Unlinked"); if (nodep->varp()->isIfaceRef()) { nodep->varScopep(NULL); } else { @@ -378,9 +378,9 @@ private: UINFO(9," Old pkg-taskref "<packagep()) { // Point to the clone - if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); AstNodeFTask* newp = VN_CAST(nodep->taskp()->user2p(), NodeFTask); - if (!newp) nodep->v3fatalSrc("No clone for package function"); + UASSERT_OBJ(newp, nodep, "No clone for package function"); nodep->taskp(newp); UINFO(9," New pkg-taskref "<v3fatalSrc("No value found for node."); + UASSERT_OBJ(nump, nodep, "No value found for node."); //UINFO(9," fetch num "<<*nump<<" on "<v3fatalSrc("No value found for node."); + UASSERT_OBJ(nump, nodep, "No value found for node."); return nump; } private: @@ -314,7 +314,7 @@ private: AstNode* vscp; if (m_scoped) vscp = nodep->varScopep(); else vscp = nodep->varp(); - if (!vscp) nodep->v3fatalSrc("Not linked"); + UASSERT_OBJ(vscp, nodep, "Not linked"); return vscp; } int unrollCount() { @@ -347,7 +347,7 @@ private: virtual void visit(AstVarRef* nodep) { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate - if (!nodep->varp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->varp(), nodep, "Unlinked"); iterateChildren(nodep->varp()); AstNode* vscp = varOrScope(nodep); @@ -391,9 +391,9 @@ private: } } if (!m_checkOnly && optimizable()) { // simulating - if (nodep->lvalue()) { - nodep->v3fatalSrc("LHS varref should be handled in AstAssign visitor."); - } else { + UASSERT_OBJ(!nodep->lvalue(), nodep, + "LHS varref should be handled in AstAssign visitor."); + { // Return simulation value - copy by reference instead of value for speed V3Number* nump = fetchNumberNull(vscp); if (!nump) { @@ -447,7 +447,7 @@ private: } virtual void visit(AstEnumItemRef* nodep) { checkNodeInfo(nodep); - if (!nodep->itemp()) nodep->v3fatalSrc("Not linked"); + UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); if (!m_checkOnly && optimizable()) { AstNode* valuep = nodep->itemp()->valuep(); if (valuep) { @@ -572,9 +572,8 @@ private: iterateAndNextNull(nodep->rhsp()); // Value to assign handleAssignSelRecurse(nodep, selp, varrefp/*ref*/, lsb/*ref*/, 0); if (!m_checkOnly && optimizable()) { - if (!varrefp) { - nodep->v3fatalSrc("Indicated optimizable, but no variable found on RHS of select"); - } + UASSERT_OBJ(varrefp, nodep, + "Indicated optimizable, but no variable found on RHS of select"); AstNode* vscp = varOrScope(varrefp); V3Number outnum = V3Number(nodep); if (V3Number* vscpnump = fetchOutNumberNull(vscp)) { @@ -796,9 +795,9 @@ private: UINFO(5," FUNCREF "<taskp(), NodeFTask); - if (!funcp) nodep->v3fatalSrc("Not linked"); + UASSERT_OBJ(funcp, nodep, "Not linked"); if (m_params) { V3Width::widthParamsEdit(funcp); } VL_DANGLING(funcp); // Make sure we've sized the function - funcp = VN_CAST(nodep->taskp(), NodeFTask); if (!funcp) nodep->v3fatalSrc("Not linked"); + funcp = VN_CAST(nodep->taskp(), NodeFTask); UASSERT_OBJ(funcp, nodep, "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 @@ -832,7 +831,7 @@ private: m_callStack.pop_front(); if (!m_checkOnly && optimizable()) { // Grab return value from output variable (if it's a function) - if (!funcp->fvarp()) nodep->v3fatalSrc("Function reference points at non-function"); + UASSERT_OBJ(funcp->fvarp(), nodep, "Function reference points at non-function"); newNumber(nodep, *fetchNumber(funcp->fvarp())); } } @@ -947,10 +946,7 @@ private: } void mainGuts(AstNode* nodep) { iterate(nodep); - if (m_jumpp) { - m_jumpp->v3fatalSrc("JumpGo branched to label that wasn't found"); - m_jumpp = NULL; - } + UASSERT_OBJ(!m_jumpp, m_jumpp, "JumpGo branched to label that wasn't found"); } public: // CONSTRUCTORS diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 589f5799a..d0bd73b68 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -161,9 +161,8 @@ class SliceVisitor : public AstNVisitor { } virtual void visit(AstInitArray* nodep) { - if (VL_UNCOVERABLE(m_assignp)) { - nodep->v3fatalSrc("Array initialization should have been removed earlier"); - } + UASSERT_OBJ(!m_assignp, nodep, + "Array initialization should have been removed earlier"); } void expandBiOp(AstNodeBiop* nodep) { @@ -202,7 +201,7 @@ class SliceVisitor : public AstNVisitor { } } } - if (!logp) nodep->v3fatalSrc("Unpacked array with empty indices range"); + UASSERT_OBJ(logp, nodep, "Unpacked array with empty indices range"); nodep->replaceWith(logp); pushDeletep(nodep); VL_DANGLING(nodep); nodep = logp; diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 9ffe49b77..13b9a46af 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -309,7 +309,7 @@ private: //UINFO(9," push "<user3p()) nodep->v3fatalSrc("user3p should not be used; cleared in processBlock"); + UASSERT_OBJ(!nodep->user3p(), nodep, "user3p should not be used; cleared in processBlock"); nodep->user3p(vertexp); } void scoreboardPopStmt() { @@ -365,7 +365,7 @@ protected: virtual void visit(AstVarRef* nodep) { if (!m_stmtStackps.empty()) { AstVarScope* vscp = nodep->varScopep(); - if (!vscp) nodep->v3fatalSrc("Not linked"); + UASSERT_OBJ(vscp, nodep, "Not linked"); if (!nodep->varp()->isConst()) { // Constant lookups can be ignored // --- // NOTE: Formerly at this location we would avoid @@ -518,7 +518,7 @@ protected: for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); uint32_t color = vvertexp->color(); - if (!color) nextp->v3fatalSrc("No node color assigned"); + UASSERT_OBJ(color, nextp, "No node color assigned"); if (lastOfColor[color]) { new SplitStrictEdge(&m_graph, lastOfColor[color], vvertexp); } @@ -580,9 +580,8 @@ protected: AstNode* firstp = nodep; // We may reorder, and nodep is no longer first. void* oldBlockUser3 = nodep->user3p(); // May be overloaded in below loop, save it nodep->user3p(NULL); - if (!nodep->firstAbovep()) { - nodep->v3fatalSrc("Node passed is in next list; should have processed all list at once"); - } + UASSERT_OBJ(nodep->firstAbovep(), nodep, + "Node passed is in next list; should have processed all list at once"); // Process it if (!nodep->nextp()) { // Just one, so can't reorder. Just look for more blocks/statements. @@ -656,7 +655,7 @@ public: const ColorSet& colors() const { return m_colors; } const ColorSet& colors(AstNodeIf* nodep) const { IfColorMap::const_iterator it = m_ifColors.find(nodep); - if (it == m_ifColors.end()) nodep->v3fatalSrc("Unknown node in split color() map"); + UASSERT_OBJ(it != m_ifColors.end(), nodep, "Unknown node in split color() map"); return it->second; } @@ -758,7 +757,7 @@ protected: // for such an embedded if. // Each leaf must have a user3p - if (!nodep->user3p()) nodep->v3fatalSrc("null user3p in V3Split leaf"); + UASSERT_OBJ(nodep->user3p(), nodep, "null user3p in V3Split leaf"); // Clone the leaf into its new always block SplitLogicVertex* vxp = reinterpret_cast(nodep->user3p()); diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index 4b8d485fb..87eda4bde 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -136,7 +136,7 @@ public: if (!m_varp->isWide() && !m_whole.m_complex && m_whole.m_assignp && !m_wordAssign) { AstNodeAssign* assp = m_whole.m_assignp; - if (!assp) errp->v3fatalSrc("Reading whole that was never assigned"); + UASSERT_OBJ(assp, errp, "Reading whole that was never assigned"); return (assp->rhsp()); } else { return NULL; @@ -145,7 +145,7 @@ public: AstNode* substWord(AstNode* errp, int word) { // Return what to substitute given word number for if (!m_whole.m_complex && !m_whole.m_assignp && !m_words[word].m_complex) { AstNodeAssign* assp = getWordAssignp(word); - if (!assp) errp->v3fatalSrc("Reading a word that was never assigned, or bad word #"); + UASSERT_OBJ(assp, errp, "Reading a word that was never assigned, or bad word #"); return (assp->rhsp()); } else { return NULL; diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 4204dfa47..e6445a11e 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -310,16 +310,15 @@ private: shift += invscp->width(); // We're just using32 bit arithmetic, because there's no // way the input table can be 2^32 bytes! - if (shift>31) nodep->v3fatalSrc("shift overflow"); + UASSERT_OBJ(shift <= 32, nodep, "shift overflow"); UINFO(8," Input "<name()<<" = "<<*(simvis.fetchNumber(invscp))<v3fatalSrc("Optimizable cleared, even though earlier test run said not: " - <v3fatalSrc("InitArray requires us to have the values in inValue order"); - } + UASSERT_OBJ(inValue == inValueNextInitArray, nodep, + "InitArray requires us to have the values in inValue order"); + inValueNextInitArray++; AstNode* setp = new AstConst(nodep->fileline(), outputChgMask); VN_CAST(chgVscp->varp()->valuep(), InitArray)->addValuep(setp); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 92df33120..0b26fae56 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -120,12 +120,12 @@ public: // METHODS AstScope* getScope(AstNodeFTask* nodep) { AstScope* scopep = VN_CAST(nodep->user3p(), Scope); - if (!scopep) nodep->v3fatalSrc("No scope for function"); + UASSERT_OBJ(scopep, nodep, "No scope for function"); return scopep; } AstVarScope* findVarScope(AstScope* scopep, AstVar* nodep) { VarToScopeMap::iterator iter = m_varToScopeMap.find(make_pair(scopep, nodep)); - if (iter == m_varToScopeMap.end()) nodep->v3fatalSrc("No scope for var"); + UASSERT_OBJ(iter != m_varToScopeMap.end(), nodep, "No scope for var"); return iter->second; } bool ftaskNoInline(AstNodeFTask* nodep) { @@ -199,7 +199,7 @@ private: pushDeletep(m_assignwp); m_assignwp = NULL; } // We make multiple edges if a task is called multiple times from another task. - if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked task"); + UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked task"); new TaskEdge(&m_callGraph, m_curVxp, getFTaskVertex(nodep->taskp())); } virtual void visit(AstNodeFTask* nodep) { @@ -269,7 +269,7 @@ private: if (nodep->varp()->user2p()) { // It's being converted to an alias. UINFO(9, " relinkVar "<varp()->user2p())<<" "<varp()->user2p(), VarScope); - if (!newvscp) nodep->v3fatalSrc("not linked"); + UASSERT_OBJ(newvscp, nodep, "not linked"); nodep->varScopep(newvscp); nodep->varp(nodep->varScopep()->varp()); nodep->name(nodep->varp()->name()); @@ -362,7 +362,7 @@ private: AstNode* createInlinedFTask(AstNodeFTaskRef* refp, const string& namePrefix, AstVarScope* outvscp) { // outvscp is the variable for functions only, if NULL, it's a task - if (!refp->taskp()) refp->v3fatalSrc("Unlinked?"); + UASSERT_OBJ(refp->taskp(), refp, "Unlinked?"); AstNode* newbodysp = AstNode::cloneTreeNull(refp->taskp()->stmtsp(), true); // Maybe NULL AstNode* beginp = new AstComment(refp->fileline(), string("Function: ")+refp->name()); if (newbodysp) beginp->addNext(newbodysp); @@ -397,7 +397,7 @@ private: if (AstVarRef* varrefp = VN_CAST(pinp, VarRef)) { // Connect to this exact variable AstVarScope* localVscp = varrefp->varScopep(); - if (!localVscp) varrefp->v3fatalSrc("Null var scope"); + UASSERT_OBJ(localVscp, varrefp, "Null var scope"); portp->user2p(localVscp); pushDeletep(pinp); } else { @@ -442,7 +442,7 @@ private: } } } - if (refp->pinsp()) refp->v3fatalSrc("Pin wasn't removed by above loop"); + UASSERT_OBJ(!refp->pinsp(), refp, "Pin wasn't removed by above loop"); { AstNode* nextstmtp; for (AstNode* stmtp = beginp; stmtp; stmtp=nextstmtp) { @@ -479,9 +479,9 @@ private: AstNode* createNonInlinedFTask(AstNodeFTaskRef* refp, const string& namePrefix, AstVarScope* outvscp) { // outvscp is the variable for functions only, if NULL, it's a task - if (!refp->taskp()) refp->v3fatalSrc("Unlinked?"); + UASSERT_OBJ(refp->taskp(), refp, "Unlinked?"); AstCFunc* cfuncp = m_statep->ftaskCFuncp(refp->taskp()); - if (!cfuncp) refp->v3fatalSrc("No non-inline task associated with this task call?"); + UASSERT_OBJ(cfuncp, refp, "No non-inline task associated with this task call?"); // AstNode* beginp = new AstComment(refp->fileline(), string("Function: ")+refp->name()); AstCCall* ccallp = new AstCCall(refp->fileline(), cfuncp, NULL); @@ -543,7 +543,7 @@ private: if (refp->taskp()->dpiContext()) { // __Vscopep AstNode* snp = refp->scopeNamep()->unlinkFrBack(); - if (!snp) refp->v3fatalSrc("Missing scoping context"); + UASSERT_OBJ(snp, refp, "Missing scoping context"); ccallp->addArgsp(snp); // __Vfilenamep ccallp->addArgsp(new AstCMath(refp->fileline(), @@ -967,7 +967,7 @@ private: AstVar* rtnvarp = NULL; if (nodep->isFunction()) { AstVar* portp = VN_CAST(nodep->fvarp(), Var); - if (!portp) nodep->v3fatalSrc("function without function output variable"); + UASSERT_OBJ(portp, nodep, "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.)"); if (ftaskNoInline || nodep->dpiExport()) portp->funcReturn(false); // Converting return to 'outputs' @@ -986,7 +986,8 @@ private: if (nodep->dpiImport()) { if (nodep->dpiOpenChild()) { // The parent will make the dpi proto - if (nodep->dpiOpenParent()) nodep->v3fatalSrc("DPI task should be parent or wrapper, not both"); + UASSERT_OBJ(!nodep->dpiOpenParent(), nodep, + "DPI task should be parent or wrapper, not both"); } else { // Parent or not open child, make wrapper string dpiproto = dpiprotoName(nodep, rtnvarp); @@ -1066,7 +1067,8 @@ private: } if (nodep->dpiExport()) { - AstScopeName* snp = nodep->scopeNamep(); if (!snp) nodep->v3fatalSrc("Missing scoping context"); + AstScopeName* snp = nodep->scopeNamep(); + UASSERT_OBJ(snp, nodep, "Missing scoping context"); snp->dpiExport(true); // The AstScopeName is really a statement(ish) for tracking, not a function snp->unlinkFrBack(); cfuncp->addInitsp(snp); @@ -1138,7 +1140,7 @@ private: // Return node that must be visited, if any // See also AstNode::addBeforeStmt; this predates that function if (debug()>=9) { nodep->dumpTree(cout, "-newstmt:"); } - if (!m_insStmtp) nodep->v3fatalSrc("Function not underneath a statement"); + UASSERT_OBJ(m_insStmtp, nodep, "Function not underneath a statement"); AstNode* visitp = NULL; if (m_insMode == IM_BEFORE) { // Add the whole thing before insertAt @@ -1153,7 +1155,7 @@ private: else if (m_insMode == IM_WHILE_PRECOND) { UINFO(5," IM_While_Precond "<v3fatalSrc("Insert should be under WHILE"); + UASSERT_OBJ(whilep, nodep, "Insert should be under WHILE"); whilep->addPrecondsp(newp); visitp = newp; } @@ -1184,11 +1186,11 @@ private: m_scopep = NULL; } virtual void visit(AstNodeFTaskRef* nodep) { - if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked?"); + UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked?"); iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs UINFO(4," FTask REF "<=9) { nodep->dumpTree(cout, "-inlfunc:"); } - if (!m_scopep) nodep->v3fatalSrc("func ref not under scope"); + UASSERT_OBJ(m_scopep, nodep, "func ref not under scope"); string namePrefix = ((VN_IS(nodep, FuncRef) ? "__Vfunc_":"__Vtask_") +nodep->taskp()->shortName()+"__"+cvtToStr(m_modNCalls++)); // Create output variable @@ -1209,7 +1211,7 @@ private: // Replace the ref AstNode* visitp = NULL; if (VN_IS(nodep, FuncRef)) { - if (!nodep->taskp()->isFunction()) nodep->v3fatalSrc("func reference to non-function"); + UASSERT_OBJ(nodep->taskp()->isFunction(), nodep, "func reference to non-function"); AstVarRef* outrefp = new AstVarRef(nodep->fileline(), outvscp, false); nodep->replaceWith(outrefp); // Insert new statements @@ -1349,7 +1351,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) typedef std::map NameToIndex; NameToIndex nameToIndex; V3TaskConnects tconnects; - if (!nodep->taskp()) nodep->v3fatalSrc("unlinked"); + UASSERT_OBJ(nodep->taskp(), nodep, "unlinked"); // Find ports int tpinnum = 0; @@ -1374,7 +1376,8 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) bool reorganize = false; for (AstNode* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) { nextp = pinp->nextp(); - AstArg* argp = VN_CAST(pinp, Arg); if (!argp) pinp->v3fatalSrc("Non-arg under ftask reference"); + AstArg* argp = VN_CAST(pinp, Arg); + UASSERT_OBJ(argp, pinp, "Non-arg under ftask reference"); if (argp->name() != "") { // By name NameToIndex::iterator it = nameToIndex.find(argp->name()); @@ -1460,7 +1463,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) while (nodep->pinsp()) nodep->pinsp()->unlinkFrBack(); // Must unlink each pin, not all pins linked together as one list for (int i=0; iv3fatalSrc("Lost argument in func conversion"); + UASSERT_OBJ(argp, nodep, "Lost argument in func conversion"); nodep->addPinsp(argp); } } diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 6883f76b3..a4e4ee8a3 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -131,7 +131,8 @@ public: virtual FileLine* fileline() const { return nodep()->fileline(); } TraceTraceVertex* duplicatep() const { return m_duplicatep; } void duplicatep(TraceTraceVertex* dupp) { - if (duplicatep()) nodep()->v3fatalSrc("Assigning duplicatep() to already duplicated node"); + UASSERT_OBJ(!duplicatep(), nodep(), + "Assigning duplicatep() to already duplicated node"); m_duplicatep = dupp; } }; @@ -205,10 +206,9 @@ private: if (TraceTraceVertex* vvertexp = dynamic_cast(itp)) { AstTraceInc* nodep = vvertexp->nodep(); if (nodep->valuep()) { - if (nodep->valuep()->backp() != nodep) { - nodep->v3fatalSrc("Trace duplicate back needs consistency," - " so we can map duplicates back to TRACEINCs"); - } + UASSERT_OBJ(nodep->valuep()->backp() == nodep, nodep, + "Trace duplicate back needs consistency," + " so we can map duplicates back to TRACEINCs"); hashed.hash(nodep->valuep()); UINFO(8, " Hashed "<valuep()) <<" "<backp(), TraceInc); - if (!dupincp) nodep->v3fatalSrc("Trace duplicate of wrong type"); + UASSERT_OBJ(dupincp, nodep, "Trace duplicate of wrong type"); TraceTraceVertex* dupvertexp = dynamic_cast(dupincp->user1u().toGraphVertex()); UINFO(8," Orig "<inBeginp(); edgep; edgep=edgep->inNextp()) { TraceActivityVertex* actVtxp = dynamic_cast(edgep->fromp()); - if (!actVtxp) vvertexp->nodep()->v3fatalSrc("Tracing a node with FROM non activity"); + UASSERT_OBJ(actVtxp, vvertexp->nodep(), + "Tracing a node with FROM non activity"); if (actVtxp->activityAlways()) { alwaysEdgep = edgep; break; @@ -438,7 +439,8 @@ private: for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { TraceActivityVertex* cfvertexp = dynamic_cast(edgep->fromp()); - if (!cfvertexp) vvertexp->nodep()->v3fatalSrc("Should have been function pointing to this trace"); + UASSERT_OBJ(cfvertexp, vvertexp->nodep(), + "Should have been function pointing to this trace"); UINFO(9," Activity: "<activityAlways()) { // If code 0, we always trace; ignore other codes @@ -550,7 +552,8 @@ private: dupvertexp = dupvertexp->duplicatep(); UINFO(9," dupOf "<nodep()) <<" "<duplicatep()) dupvertexp->nodep()->v3fatalSrc("Original node was marked as a duplicate"); + UASSERT_OBJ(!dupvertexp->duplicatep(), dupvertexp->nodep(), + "Original node was marked as a duplicate"); } if (dupvertexp != vvertexp) { @@ -644,7 +647,7 @@ private: } virtual void visit(AstTopScope* nodep) { AstScope* scopep = nodep->scopep(); - if (!scopep) nodep->v3fatalSrc("No scope found on top level"); + UASSERT_OBJ(scopep, nodep, "No scope found on top level"); m_highScopep = scopep; iterateChildren(nodep); } @@ -692,21 +695,21 @@ private: } virtual void visit(AstTraceInc* nodep) { UINFO(8," TRACE "<v3fatalSrc("Traces should have been removed in prev step."); + UASSERT_OBJ(!m_finding, nodep, "Traces should have been removed in prev step."); nodep->unlinkFrBack(); V3GraphVertex* vertexp = new TraceTraceVertex(&m_graph, nodep); nodep->user1p(vertexp); - if (!m_funcp || (!m_chgFuncp || !m_fullFuncp)) nodep->v3fatalSrc("Trace not under func"); + UASSERT_OBJ(m_funcp && m_chgFuncp && m_fullFuncp, nodep, "Trace not under func"); m_tracep = nodep; iterateChildren(nodep); m_tracep = NULL; } virtual void visit(AstVarRef* nodep) { if (m_tracep) { - if (!nodep->varScopep()) nodep->v3fatalSrc("No var scope?"); - if (nodep->lvalue()) nodep->v3fatalSrc("Lvalue in trace? Should be const."); + UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?"); + UASSERT_OBJ(!nodep->lvalue(), nodep, "Lvalue in trace? Should be const."); V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex(); if (!varVtxp) { varVtxp = new TraceVarVertex(&m_graph, nodep->varScopep()); @@ -720,7 +723,7 @@ private: } } else if (m_funcp && m_finding && nodep->lvalue()) { - if (!nodep->varScopep()) nodep->v3fatalSrc("No var scope?"); + UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?"); V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp); V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex(); if (varVtxp) { // else we're not tracing this signal diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 1cf84cd20..e0fa66dd8 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -157,7 +157,7 @@ private: // it uses spaces to separate hierarchy components. m_traShowname = AstNode::vcdName(scopep->name() + " " + varp->name()); if (m_traShowname.substr(0, 4) == "TOP ") m_traShowname.replace(0, 4, ""); - if (!m_initSubFuncp) nodep->v3fatalSrc("NULL"); + UASSERT_OBJ(m_initSubFuncp, nodep, "NULL"); m_traVscp = nodep; m_traValuep = NULL; diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index ffe3d7d8f..af32f18cb 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -300,12 +300,12 @@ class TristatePinVisitor : public TristateBaseVisitor { } virtual void visit(AstArraySel* nodep) { // Doesn't work because we'd set lvalue on the array index's var - if (m_lvalue) nodep->v3fatalSrc("ArraySel conversion to output, under tristate node"); + UASSERT_OBJ(!m_lvalue, nodep, "ArraySel conversion to output, under tristate node"); iterateChildren(nodep); } virtual void visit(AstSliceSel* nodep) { // Doesn't work because we'd set lvalue on the array index's var - if (m_lvalue) nodep->v3fatalSrc("SliceSel conversion to output, under tristate node"); + UASSERT_OBJ(!m_lvalue, nodep, "SliceSel conversion to output, under tristate node"); iterateChildren(nodep); } virtual void visit(AstNode* nodep) { @@ -1155,7 +1155,7 @@ class TristateVisitor : public TristateBaseVisitor { AstVar* outModVarp = static_cast(nodep->modVarp()->user4p()); if (!outModVarp) { // At top, no need for __out as might be input only. Otherwise resolvable. - if (!m_modp->isTop()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(m_modp->isTop(), nodep, "Unlinked"); } else { AstNode* outexprp = nodep->exprp()->cloneTree(false); // Note has lvalue() set outpinp = new AstPin(nodep->fileline(), @@ -1305,7 +1305,8 @@ class TristateVisitor : public TristateBaseVisitor { virtual void visit(AstNodeModule* nodep) { UINFO(8, nodep<v3fatalSrc("Modules under modules not supported"); // Lots of per-module state breaks + UASSERT_OBJ(!m_graphing, nodep, + "Modules under modules not supported"); // Lots of per-module state breaks // Clear state m_tgraph.clear(); m_unique = 0; diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 70a0cb7fa..da2a2e0f0 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -110,7 +110,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 = VN_CAST(prep->user2p(), If)) { - if (needDly) prep->v3fatalSrc("Should have already converted to non-delay"); + UASSERT_OBJ(!needDly, prep, "Should have already converted to non-delay"); AstNRelinker replaceHandle; AstNode* earliercondp = ifp->condp()->unlinkFrBack(&replaceHandle); AstNode* newp = new AstLogAnd(condp->fileline(), @@ -285,7 +285,7 @@ private: } else { // Make a Vxrand variable // We use the special XTEMP type so it doesn't break pure functions - if (!m_modp) nodep->v3fatalSrc("X number not under module"); + UASSERT_OBJ(m_modp, nodep, "X number not under module"); string newvarname = (string("__Vxrand") +cvtToStr(m_modp->varNumGetInc())); AstVar* newvarp @@ -391,7 +391,7 @@ private: // Find range of dtype we are selecting from int declElements = -1; AstNodeDType* dtypep = nodep->fromp()->dtypep()->skipRefp(); - if (!dtypep) nodep->v3fatalSrc("Select of non-selectable type"); + UASSERT_OBJ(dtypep, nodep, "Select of non-selectable type"); if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { declElements = adtypep->elementsConst(); } else { diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index f394ceed9..b58b3c80e 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -107,16 +107,17 @@ private: // Initial value check 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"); + UASSERT_OBJ(!(initp->nextp() && initp->nextp()!=nodep), nodep, + "initial assignment shouldn't be a list"); 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"); + UASSERT_OBJ(!condp->nextp(), nodep, "conditional shouldn't be a list"); // // Assignment of next value check 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"); + UASSERT_OBJ(!incAssp->nextp(), nodep, "increment shouldn't be a list"); m_forVarp = VN_CAST(initAssp->lhsp(), VarRef)->varp(); m_forVscp = VN_CAST(initAssp->lhsp(), VarRef)->varScopep(); @@ -190,10 +191,7 @@ private: bool simulateTree(AstNode *nodep, const V3Number *loopValue, AstNode *dtypep, V3Number &outNum) { AstNode* clonep = nodep->cloneTree(true); - if (!clonep) { - nodep->v3fatalSrc("Failed to clone tree"); - return false; - } + UASSERT_OBJ(clonep, nodep, "Failed to clone tree"); if (loopValue) { m_varValuep = new AstConst(nodep->fileline(), *loopValue); // Iteration requires a back, so put under temporary node diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 5db742e51..e133db637 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -561,7 +561,7 @@ private: // LSB is self-determined (IEEE 2012 11.5.1) // We also use SELs to shorten a signed constant etc, in this case they are signed. if (nodep->didWidth()) return; - if (!m_vup) nodep->v3fatalSrc("Select under an unexpected context"); + UASSERT_OBJ(m_vup, nodep, "Select under an unexpected context"); if (m_vup->prelim()) { if (debug()>=9) nodep->dumpTree(cout, "-selWidth: "); userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); @@ -576,7 +576,7 @@ private: nodep->dtypeSetLogicBool(); return; } int width = nodep->widthConst(); - if (!nodep->dtypep()) nodep->v3fatalSrc("dtype wasn't set") // by V3WidthSel + UASSERT_OBJ(nodep->dtypep(), nodep, "dtype wasn't set"); // by V3WidthSel if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) { nodep->v3error("Unsupported: MSB < LSB of bit extract: " @@ -952,7 +952,8 @@ private: break; case AstAttrType::DIM_DIMENSIONS: case AstAttrType::DIM_UNPK_DIMENSIONS: { - if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression"); + UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, + "Unsized expression"); std::pair dim = nodep->fromp()->dtypep()->dimensions(true); int val = (nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS ? dim.second : (dim.first+dim.second)); @@ -967,7 +968,8 @@ private: case AstAttrType::DIM_LOW: case AstAttrType::DIM_RIGHT: case AstAttrType::DIM_SIZE: { - if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression"); + UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, + "Unsized expression"); std::pair dim = nodep->fromp()->dtypep()->skipRefp()->dimensions(true); uint32_t msbdim = dim.first+dim.second; @@ -977,7 +979,8 @@ private: nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); } else { // Need a runtime lookup table. Yuk. - if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression"); + UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, + "Unsized expression"); AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim); AstNode* dimp = nodep->dimp()->unlinkFrBack(); AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false); @@ -1083,7 +1086,7 @@ private: if (nodep->subDTypep()) nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); // Effectively nodep->dtypeFrom(nodep->dtypeSkipRefp()); // But might be recursive, so instead manually recurse into the referenced type - if (!nodep->defp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->defp(), nodep, "Unlinked"); nodep->dtypeFrom(nodep->defp()); userIterate(nodep->defp(), NULL); nodep->widthFromSub(nodep->subDTypep()); @@ -1129,7 +1132,7 @@ private: // The cast may change signing, but we don't know the sign yet. Make it so. // Note we don't sign lhsp() that would make the algorithm O(n^2) if lots of casting. AstBasicDType* basicp = nodep->dtypep()->basicp(); - if (!basicp) nodep->v3fatalSrc("Unimplemented: Casting non-simple data type"); + UASSERT_OBJ(basicp, nodep, "Unimplemented: Casting non-simple data type"); // When implement more complicated types need to convert childDTypep to // dtypep() not as a child if (!basicp->isDouble() && !nodep->lhsp()->isDouble()) { @@ -1162,7 +1165,8 @@ 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 (!VN_IS(nodep->rhsp(), Const)) nodep->v3fatalSrc("Unsupported: Non-const cast of size"); + UASSERT_OBJ(VN_IS(nodep->rhsp(), Const), nodep, + "Unsupported: Non-const cast of size"); //if (debug()) nodep->dumpTree(cout, " CastSizePre: "); if (m_vup->prelim()) { int width = VN_CAST(nodep->rhsp(), Const)->toSInt(); @@ -1215,7 +1219,7 @@ private: // with non-constant range gets size 1, not size 0. So use didWidth(). if (nodep->didWidth()) return; if (nodep->doingWidth()) { // Early exit if have circular parameter definition - if (!nodep->valuep()) nodep->v3fatalSrc("circular, but without value"); + UASSERT_OBJ(nodep->valuep(), nodep, "circular, but without value"); nodep->v3error("Variable's initial value is circular: "<prettyName()); pushDeletep(nodep->valuep()->unlinkFrBack()); nodep->valuep(new AstConst(nodep->fileline(), AstConst::LogicTrue())); @@ -1227,7 +1231,7 @@ private: // Make sure dtype is sized if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep)); nodep->dtypep(iterateEditDTypep(nodep, nodep->dtypep())); - if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype determined for var"); + UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype determined for var"); if (VN_IS(nodep->dtypeSkipRefp(), UnsizedArrayDType)) { if (!(m_ftaskp && m_ftaskp->dpiImport())) { nodep->v3error("Unsized/open arrays ('[]') are only supported in DPI imports"); @@ -1328,7 +1332,7 @@ private: // Note genvar's are also entered as integers nodep->dtypeFrom(nodep->varp()); if (VN_IS(nodep->backp(), NodeAssign) && nodep->lvalue()) { // On LHS - if (!nodep->widthMin()) nodep->v3fatalSrc("LHS var should be size complete"); + UASSERT_OBJ(nodep->widthMin(), nodep, "LHS var should be size complete"); } //if (debug()>=9) nodep->dumpTree(cout, " VRout "); if (nodep->lvalue() && nodep->varp()->direction() == VDirection::CONSTREF) { @@ -1397,7 +1401,7 @@ private: virtual void visit(AstEnumItem* nodep) { UINFO(5," ENUMITEM "<dtypep(); - if (!vdtypep) nodep->v3fatalSrc("ENUMITEM not under ENUM"); + UASSERT_OBJ(vdtypep, nodep, "ENUMITEM not under ENUM"); nodep->dtypep(vdtypep); if (nodep->valuep()) { // else the value will be assigned sequentially // Default type is int, but common to assign narrower values, so minwidth from value @@ -1411,11 +1415,11 @@ private: if (!nodep->itemp()->didWidth()) { // We need to do the whole enum en-mass AstNode* enump = nodep->itemp(); - if (!enump) nodep->v3fatalSrc("EnumItemRef not linked"); + UASSERT_OBJ(enump, nodep, "EnumItemRef not linked"); for (; enump; enump=enump->backp()) { if (VN_IS(enump, EnumDType)) break; } - if (!enump) nodep->v3fatalSrc("EnumItemRef can't deref back to an Enum"); + UASSERT_OBJ(enump, nodep, "EnumItemRef can't deref back to an Enum"); userIterate(enump, m_vup); VL_DANGLING(enump); // parent's connection to enump may be relinked } nodep->dtypeFrom(nodep->itemp()); @@ -1424,7 +1428,7 @@ private: // InitArray has type of the array; children are array values if (m_vup->prelim()) { // First stage evaluation AstNodeDType* vdtypep = m_vup->dtypep(); - if (!vdtypep) nodep->v3fatalSrc("InitArray type not assigned by AstPattern/Var visitor"); + UASSERT_OBJ(vdtypep, nodep, "InitArray type not assigned by AstPattern/Var visitor"); nodep->dtypep(vdtypep); if (AstNodeArrayDType* arrayp = VN_CAST(vdtypep->skipRefp(), NodeArrayDType)) { userIterateChildren(nodep, WidthVP(arrayp->subDTypep(), BOTH).p()); @@ -1602,7 +1606,8 @@ private: if (argp->exprp()) userIterate(argp->exprp(), WidthVP(SELF, BOTH).p()); } // Find the fromp dtype - should be a class - if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression"); + UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, + "Unsized expression"); AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : NULL; UINFO(9," from dt "<fileline(), AstConst::Signed32(), 0); // Spec doesn't say what to do else newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const } - if (!newp) nodep->v3fatalSrc("Enum method (perhaps enum item) not const"); + UASSERT_OBJ(newp, nodep, "Enum method (perhaps enum item) not const"); newp->fileline(nodep->fileline()); // Use method's filename/line number to be clearer; may have warning disables nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); @@ -1665,7 +1670,7 @@ private: 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"); + UASSERT_OBJ(vconstp, nodep, "Enum item without constified value"); if (vconstp->toUQuad() >= msbdim) msbdim = vconstp->toUQuad(); } if (adtypep->itemsp()->width() > 64 || msbdim >= (1<<16)) { @@ -2053,10 +2058,11 @@ private: } virtual void visit(AstPatMember* nodep) { AstNodeDType* vdtypep = m_vup->dtypeNullp(); - if (!vdtypep) nodep->v3fatalSrc("Pattern member type not assigned by AstPattern visitor"); + UASSERT_OBJ(vdtypep, nodep, "Pattern member type not assigned by AstPattern visitor"); nodep->dtypep(vdtypep); UINFO(9," PATMEMBER "<lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed"); + UASSERT_OBJ(!nodep->lhssp()->nextp(), nodep, + "PatMember value should be singular w/replicates removed"); // Need to propagate assignment type downwards, even on prelim userIterateChildren(nodep, WidthVP(nodep->dtypep(), PRELIM).p()); iterateCheck(nodep, "Pattern value", nodep->lhssp(), ASSIGN, FINAL, vdtypep, EXTEND_LHS); @@ -2174,8 +2180,9 @@ private: { //if (debug()) nodep->dumpTree(cout, "- assin: "); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); - if (!nodep->lhsp()->dtypep()) nodep->v3fatalSrc("How can LHS be untyped?"); - if (!nodep->lhsp()->dtypep()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?"); + UASSERT_OBJ(nodep->lhsp()->dtypep(), nodep, "How can LHS be untyped?"); + UASSERT_OBJ(nodep->lhsp()->dtypep()->widthSized(), nodep, + "How can LHS be unsized?"); nodep->dtypeFrom(nodep->lhsp()); // // AstPattern needs to know the proposed data type of the lhs, so pass on the prelim @@ -2559,7 +2566,7 @@ private: userIterateChildren(nodep, NULL); if (nodep->fvarp()) { m_funcp = VN_CAST(nodep, Func); - if (!m_funcp) nodep->v3fatalSrc("FTask with function variable, but isn't a function"); + UASSERT_OBJ(m_funcp, nodep, "FTask with function variable, but isn't a function"); nodep->dtypeFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep() } nodep->didWidth(true); @@ -2599,7 +2606,7 @@ private: // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign // Function hasn't been widthed, so make it so. UINFO(5, " FTASKREF "<taskp()) nodep->v3fatalSrc("Unlinked"); + UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); if (nodep->didWidth()) return; userIterate(nodep->taskp(), NULL); // @@ -2737,8 +2744,8 @@ private: } virtual void visit(AstNode* nodep) { // Default: Just iterate - if (m_vup) nodep->v3fatalSrc("Visit function missing? Widthed expectation for this node: " - <op2p()) nodep->v3fatalSrc("For unary ops only!"); + UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!"); if (m_vup->prelim()) { iterateCheckBool(nodep, "LHS", nodep->op1p(), BOTH); nodep->dtypeSetLogicBool(); @@ -2854,7 +2861,7 @@ private: // TODO: chandle/class handle/iface handle: WildEq/WildNeq same as Eq/Neq // TODO: chandle/class handle/iface handle only allowed to self-compare or against null // TODO: chandle/class handle/iface handle no relational compares - if (!nodep->rhsp()) nodep->v3fatalSrc("For binary ops only!"); + UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(CONTEXT, PRELIM).p()); userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); @@ -2895,7 +2902,7 @@ private: // Real if and only if real_allow set // IEEE, 11.4.4: relational compares (<,>,<=,>=,==,===,!=,!==) use // "zero padding" on unsigned - if (!nodep->rhsp()) nodep->v3fatalSrc("For binary ops only!"); + UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup->prelim()) { // See similar handling in visit_cmp_eq_gt where created iterateCheckReal(nodep, "LHS", nodep->lhsp(), BOTH); @@ -2908,7 +2915,7 @@ private: // Widths: 1 bit out, lhs width == rhs width // String compare (not output) // Real if and only if real_allow set - if (!nodep->rhsp()) nodep->v3fatalSrc("For binary ops only!"); + UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup->prelim()) { // See similar handling in visit_cmp_eq_gt where created iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); @@ -2919,7 +2926,7 @@ private: void visit_Os32_string(AstNodeUniop* nodep) { // CALLER: LenN // Widths: 32 bit out - if (!nodep->lhsp()) nodep->v3fatalSrc("For unary ops only!"); + UASSERT_OBJ(nodep->lhsp(), nodep, "For unary ops only!"); if (m_vup->prelim()) { // See similar handling in visit_cmp_eq_gt where created iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); @@ -2933,7 +2940,7 @@ private: // Signed: From lhs // IEEE-2012 Table 11-21: // Widths: out width = lhs width - if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); + UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(CONTEXT, PRELIM).p()); if (!real_ok) checkCvtUS(nodep->lhsp()); @@ -2968,7 +2975,7 @@ private: // Width: Returns packed array, of size $bits(expression). // Sign: Output sign is as specified by operation // TODO: Type: Two-state if input is two-state, else four-state - if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); + UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); checkCvtUS(nodep->lhsp()); @@ -3039,7 +3046,7 @@ private: // Signed: if lhs & rhs signed // IEEE-2012 Table 11-21: // Width: max(LHS, RHS) - if (!nodep->rhsp()) nodep->v3fatalSrc("For binary ops only!"); + UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); // If errors are off, we need to follow the spec; thus we really need to do the max() // because the rhs could be larger, and we need to have proper editing to get the widths // to be the same for our operations. @@ -3152,12 +3159,15 @@ private: bool widthBad(AstNode* nodep, AstNodeDType* expDTypep) { int expWidth = expDTypep->width(); int expWidthMin = expDTypep->widthMin(); - if (!nodep->dtypep()) nodep->v3fatalSrc("Under node "<prettyTypeName() - <<" has no dtype?? Missing Visitor func?"); - if (nodep->width()==0) nodep->v3fatalSrc("Under node "<prettyTypeName() - <<" has no expected width?? Missing Visitor func?"); - if (expWidth==0) nodep->v3fatalSrc("Node "<prettyTypeName() - <<" has no expected width?? Missing Visitor func?"); + UASSERT_OBJ(nodep->dtypep(), nodep, + "Under node "<prettyTypeName() + <<" has no dtype?? Missing Visitor func?"); + UASSERT_OBJ(nodep->width() != 0, nodep, + "Under node "<prettyTypeName() + <<" has no expected width?? Missing Visitor func?"); + UASSERT_OBJ(expWidth != 0, nodep, + "Node "<prettyTypeName() + <<" has no expected width?? Missing Visitor func?"); if (expWidthMin==0) expWidthMin = expWidth; if (nodep->dtypep()->width() == expWidth) return false; if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true; @@ -3296,7 +3306,7 @@ private: return node1p->skipRefp()->similarDType(node2p->skipRefp()); } void iterateCheckFileDesc(AstNode* nodep, AstNode* underp, Stage stage) { - if (stage != BOTH) nodep->v3fatalSrc("Bad call"); + UASSERT_OBJ(stage == BOTH, nodep, "Bad call"); // underp may change as a result of replacement underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p()); AstNodeDType* expDTypep = underp->findUInt32DType(); @@ -3346,8 +3356,8 @@ private: // Coerce child to any sized-number data type; child is self-determined // i.e. isolated from expected type. // e.g. nodep=CONCAT, underp=lhs in CONCAT(lhs,rhs) - if (determ != SELF) nodep->v3fatalSrc("Bad call"); - if (stage != FINAL && stage != BOTH) nodep->v3fatalSrc("Bad call"); + UASSERT_OBJ(determ == SELF, nodep, "Bad call"); + UASSERT_OBJ(stage == FINAL || stage == BOTH, nodep, "Bad call"); // underp may change as a result of replacement if (stage & PRELIM) underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p()); underp = checkCvtUS(underp); @@ -3359,7 +3369,7 @@ private: AstNode* rhsp, Stage stage, AstNodeDType* lhsDTypep) { // Check using assignment-like context rules //if (debug()) nodep->dumpTree(cout, "-checkass: "); - if (stage != FINAL) nodep->v3fatalSrc("Bad width call"); + UASSERT_OBJ(stage == FINAL, nodep, "Bad width call"); // We iterate and size the RHS based on the result of RHS evaluation bool lhsStream = (VN_IS(nodep, NodeAssign) && VN_IS(VN_CAST(nodep, NodeAssign)->lhsp(), NodeStream)); @@ -3370,14 +3380,16 @@ private: } void iterateCheckBool(AstNode* nodep, const char* side, AstNode* underp, Stage stage) { - if (stage != BOTH) nodep->v3fatalSrc("Bad call"); // Booleans always self-determined so do BOTH at once + UASSERT_OBJ(stage == BOTH, nodep, + "Bad call"); // Booleans always self-determined so do BOTH at once // Underp is used in a self-determined but boolean context, reduce a // multibit number to one bit // stage is always BOTH so not passed as argument // underp may change as a result of replacement - if (!underp) nodep->v3fatalSrc("Node has no type"); + UASSERT_OBJ(underp, nodep, "Node has no type"); underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, BOTH).p()); - if (!underp || !underp->dtypep()) nodep->v3fatalSrc("Node has no type"); // Perhaps forgot to do a prelim visit on it? + UASSERT_OBJ(underp && underp->dtypep(), nodep, + "Node has no type"); // Perhaps forgot to do a prelim visit on it? // // For DOUBLE under a logical op, add implied test against zero, never a warning if (underp && underp->isDouble()) { @@ -3417,8 +3429,9 @@ private: // Perform data type check on underp, which is underneath nodep used for error reporting // Returns the new underp // Conversion to/from doubles and integers are before iterating. - if (stage != FINAL) nodep->v3fatalSrc("Bad state to iterateCheck"); - if (!underp || !underp->dtypep()) nodep->v3fatalSrc("Node has no type"); // Perhaps forgot to do a prelim visit on it? + UASSERT_OBJ(stage == FINAL, nodep, "Bad state to iterateCheck"); + UASSERT_OBJ(underp && underp->dtypep(), nodep, + "Node has no type"); // Perhaps forgot to do a prelim visit on it? if (expDTypep == underp->dtypep()) { // Perfect underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, FINAL).p()); } else if (expDTypep->isDouble() && underp->isDouble()) { // Also good @@ -3757,7 +3770,7 @@ private: // DTypes at parse time get added as a childDType to some node types such as AstVars. // We move them to global scope, so removing/changing a variable won't lose the dtype. AstNodeDType* dtnodep = nodep->getChildDTypep(); - if (!dtnodep) nodep->v3fatalSrc("Caller should check for NULL before calling moveChild"); + UASSERT_OBJ(dtnodep, nodep, "Caller should check for NULL before calling moveChild"); UINFO(9,"moveChildDTypeEdit "<unlinkFrBack(); // Make non-child v3Global.rootp()->typeTablep()->addTypesp(dtnodep); @@ -3773,7 +3786,7 @@ private: // Alternative is to have WidthVP return information. // or have a call outside of normal visitor land. // or have a m_return type (but need to return if width called multiple times) - if (!nodep) parentp->v3fatalSrc("Null dtype when widthing dtype"); + UASSERT_OBJ(nodep, parentp, "Null dtype when widthing dtype"); userIterate(nodep, NULL); return nodep; } @@ -3924,7 +3937,7 @@ private: } // Find valid values and populate - if (!nodep->itemsp()) nodep->v3fatalSrc("enum without items"); + UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items"); std::vector values; values.resize(msbdim+1); for (unsigned i=0; i<(msbdim+1); ++i) { @@ -3937,7 +3950,7 @@ private: for (AstEnumItem* itemp = firstp; itemp;) { AstEnumItem* nextp = VN_CAST(itemp->nextp(), EnumItem); const AstConst* vconstp = VN_CAST(itemp->valuep(), Const); - if (!vconstp) nodep->v3fatalSrc("Enum item without constified value"); + UASSERT_OBJ(vconstp, nodep, "Enum item without constified value"); uint32_t i = vconstp->toUInt(); if (attrType == AstAttrType::ENUM_NAME) { values[i] = new AstConst(nodep->fileline(), AstConst::String(), itemp->name()); @@ -3989,7 +4002,8 @@ private: UINFO(4,"Replicate openarray function "<taskp()<taskp(); oldTaskp->dpiOpenParentInc(); - if (oldTaskp->dpiOpenChild()) oldTaskp->v3fatalSrc("DPI task should be parent or child, not both"); + UASSERT_OBJ(!oldTaskp->dpiOpenChild(), oldTaskp, + "DPI task should be parent or child, not both"); AstNodeFTask* newTaskp = oldTaskp->cloneTree(false); newTaskp->dpiOpenChild(true); newTaskp->dpiOpenParentClear(); diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index bd9eb69a6..7294af4ac 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -115,7 +115,7 @@ private: } // VISITORS virtual void visit(AstConst* nodep) { - if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype"); + UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); iterate(nodep->dtypep()); // Do datatype first if (AstConst* newp = newIfConstCommitSize(nodep)) { nodep->replaceWith(newp); diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 92c85693a..886740dc7 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -84,7 +84,7 @@ private: } break; } - if (!basefromp || !basefromp->dtypep()) nodep->v3fatalSrc("Select with no from dtype"); + UASSERT_OBJ(basefromp && basefromp->dtypep(), nodep, "Select with no from dtype"); AstNodeDType* ddtypep = basefromp->dtypep()->skipRefp(); AstNode* errp = ddtypep; UINFO(9," fromData.ddtypep = "<isRanged()) { - if (adtypep->rangep() - && (!VN_IS(adtypep->rangep()->msbp(), Const) - || !VN_IS(adtypep->rangep()->lsbp(), Const))) - nodep->v3fatalSrc("Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep) + UASSERT_OBJ(!(adtypep->rangep() + && (!VN_IS(adtypep->rangep()->msbp(), Const) + || !VN_IS(adtypep->rangep()->lsbp(), Const))), + nodep, "Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep) fromRange = adtypep->declRange(); } else { nodep->v3error("Illegal bit or array select; type does not have a bit range, or bad dimension: type is " @@ -227,11 +227,10 @@ private: subp = newSubNeg(subp, fromRange.lo()); } } - if (VL_UNCOVERABLE(!fromRange.elements() - || (adtypep->width() % fromRange.elements())!=0)) { - adtypep->v3fatalSrc("Array extraction with width miscomputed " - <width()<<"/"<width() % fromRange.elements())!=0), adtypep, + "Array extraction with width miscomputed " + <width()<<"/"<width() / fromRange.elements(); AstSel* newp = new AstSel(nodep->fileline(), @@ -318,11 +317,10 @@ private: else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELEXTRACT(array, msb, lsb) -> SEL(array, // lsb*width-of-subindex, width-of-subindex*(msb-lsb)) - if (VL_UNCOVERABLE(!fromRange.elements() - || (adtypep->width() % fromRange.elements())!=0)) { - adtypep->v3fatalSrc("Array extraction with width miscomputed " - <width()<<"/"<width() % fromRange.elements())!=0), adtypep, + "Array extraction with width miscomputed " + <width()<<"/"<declElWidth(elwidth); newp->dtypeFrom(sliceDType(adtypep, msb, lsb)); //if (debug()>=9) newp->dumpTree(cout, "--EXTBTn: "); - if (newp->widthMin() != newp->widthConst()) nodep->v3fatalSrc("Width mismatch"); + UASSERT_OBJ(newp->widthMin() == newp->widthConst(), nodep, "Width mismatch"); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else if (VN_IS(ddtypep, BasicDType)) { diff --git a/src/verilog.y b/src/verilog.y index a5b5d5bf3..e32d52370 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1945,7 +1945,7 @@ 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 = VN_CAST($9, Begin); - if ($9 && !lowerBegp) $9->v3fatalSrc("Child of GENFOR should have been begin"); + UASSERT_OBJ(!($9 && !lowerBegp), $9, "Child of GENFOR should have been begin"); if (!lowerBegp) lowerBegp = new AstBegin($1,"genblk",NULL,true); // Empty body AstNode* lowerNoBegp = lowerBegp->stmtsp(); if (lowerNoBegp) lowerNoBegp->unlinkFrBackWithNext();