virtual void visit(AstWhile* nodep, AstNUser*) { nodep->iterateChildren(*this); if (m_varModeCheck || m_varModeReplace) { } else { // Constify before unroll call, as it may change what is underneath. if (nodep->precondsp()) V3Const::constifyEdit(nodep->precondsp()); // precondsp may change if (nodep->condp()) V3Const::constifyEdit(nodep->condp()); // condp may change // Grab initial value AstNode* initp = NULL; // Should be statement before the while. if (nodep->backp()->nextp() == nodep) initp=nodep->backp(); if (initp) { V3Const::constifyEdit(initp); VL_DANGLING(initp); } if (nodep->backp()->nextp() == nodep) initp=nodep->backp(); // Grab assignment AstNode* incp = NULL; // Should be last statement if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp()); if (nodep->incsp()) incp = nodep->incsp(); else { for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} if (incp) { V3Const::constifyEdit(incp); VL_DANGLING(incp); } for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} // Again, as may have changed } // And check it if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, nodep->bodysp())) { pushDeletep(nodep); VL_DANGLING(nodep); // Did replacement } } }
void visitEqNeqCase(AstNodeBiop* nodep) { UINFO(4," N/EQCASE->EQ "<<nodep<<endl); V3Const::constifyEdit(nodep->lhsp()); // lhsp may change V3Const::constifyEdit(nodep->rhsp()); // rhsp may change if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) { // Both sides are constant, node can be constant V3Const::constifyEdit(nodep); VL_DANGLING(nodep); return; } else { AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* newp; // If we got ==1'bx it can never be true (but 1'bx==1'bx can be!) if (((lhsp->castConst() && lhsp->castConst()->num().isFourState()) || (rhsp->castConst() && rhsp->castConst()->num().isFourState()))) { V3Number num (nodep->fileline(), 1, (nodep->castEqCase()?0:1)); newp = new AstConst (nodep->fileline(), num); lhsp->deleteTree(); VL_DANGLING(lhsp); rhsp->deleteTree(); VL_DANGLING(rhsp); } else { if (nodep->castEqCase()) newp = new AstEq (nodep->fileline(), lhsp, rhsp); else newp = new AstNeq (nodep->fileline(), lhsp, rhsp); } nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); // Iterate tree now that we may have gotten rid of Xs newp->iterateChildren(*this); } }
virtual void visit(AstGenFor* nodep, AstNUser*) { if (!m_generate || m_varModeReplace) { nodep->iterateChildren(*this); } // else V3Param will recursively call each for loop to be unrolled for us if (m_varModeCheck || m_varModeReplace) { } else { // Constify before unroll call, as it may change what is underneath. if (nodep->initsp()) V3Const::constifyEdit(nodep->initsp()); // initsp may change if (nodep->condp()) V3Const::constifyEdit(nodep->condp()); // condp may change if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp()); // incsp may change if (nodep->condp()->isZero()) { // We don't need to do any loops. Remove the GenFor, // Genvar's don't care about any initial assignments. // // Note normal For's can't do exactly this deletion, as // we'd need to initialize the variable to the initial // condition, but they'll become while's which can be // deleted by V3Const. nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } else if (forUnrollCheck(nodep, nodep->initsp(), NULL, nodep->condp(), nodep->incsp(), nodep->bodysp())) { pushDeletep(nodep); VL_DANGLING(nodep); // Did replacement } else { nodep->v3error("For loop doesn't have genvar index, or is malformed"); } } }
void replaceCaseFast(AstCase* nodep) { // CASEx(cexpr,.... // -> tree of IF(msb, IF(msb-1, 11, 10) // IF(msb-1, 01, 00)) AstNode* cexprp = nodep->exprp()->unlinkFrBack(); if (debug()>=9) { for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) { if (AstNode* itemp = m_valueItem[i]) { UINFO(9,"Value "<<hex<<i<<" "<<itemp<<endl); } } } // Handle any assertions replaceCaseParallel(nodep, m_caseNoOverlapsAllCovered); AstNode::user3ClearTree(); AstNode* ifrootp = replaceCaseFastRecurse(cexprp, m_caseWidth-1, 0UL); // Case expressions can't be linked twice, so clone them if (ifrootp && !ifrootp->user3()) ifrootp = ifrootp->cloneTree(true); if (ifrootp) nodep->replaceWith(ifrootp); else nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep); cexprp->deleteTree(); VL_DANGLING(cexprp); if (debug()>=9) ifrootp->dumpTree(cout," _simp: "); }
void mergeEnd() { if (!m_mgAssignps.empty()) { uint32_t items = m_mgIndexHi - m_mgIndexLo + 1; UINFO(9, "End merge iter="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo <<" "<<m_mgAssignps[0]<<endl); if (items >= RELOOP_MIN_ITERS) { UINFO(6, "Reloop merging items="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo <<" "<<m_mgAssignps[0]<<endl); ++m_statReloops; m_statReItems += items; // Transform first assign into for loop body AstNodeAssign* bodyp = m_mgAssignps.front(); if (bodyp->lhsp() != m_mgSelLp) bodyp->v3fatalSrc("Corrupt queue/state"); FileLine* fl = bodyp->fileline(); AstVar* itp = findCreateVarTemp(fl, m_mgCfuncp); AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true), new AstConst(fl, m_mgIndexLo)); AstNode* condp = new AstLte(fl, new AstVarRef(fl, itp, false), new AstConst(fl, m_mgIndexHi)); AstNode* incp = new AstAssign(fl, new AstVarRef(fl, itp, true), new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, false))); AstWhile* whilep = new AstWhile(fl, condp, NULL, incp); initp->addNext(whilep); bodyp->replaceWith(initp); whilep->addBodysp(bodyp); // Replace constant index with new loop index AstNode* lbitp = m_mgSelLp->bitp(); lbitp->replaceWith(new AstVarRef(fl, itp, false)); lbitp->deleteTree(); VL_DANGLING(lbitp); if (m_mgSelRp) { // else constant and no replace AstNode* rbitp = m_mgSelRp->bitp(); rbitp->replaceWith(new AstVarRef(fl, itp, false)); rbitp->deleteTree(); VL_DANGLING(lbitp); } if (debug()>=9) initp->dumpTree(cout, "-new: "); if (debug()>=9) whilep->dumpTree(cout, "-new: "); // Remove remaining assigns for (AssVec::iterator it=m_mgAssignps.begin(); it!=m_mgAssignps.end(); ++it) { AstNodeAssign* assp = *it; if (assp != bodyp) { assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp); } } } // Setup for next merge m_mgAssignps.clear(); m_mgSelLp = NULL; m_mgSelRp = NULL; m_mgVarrefLp = NULL; m_mgVarrefRp = NULL; m_mgConstRp = NULL; } }
void walkReplace(AstNode* node1p, AstNode* node2p, AstNode* last1p, AstNode* last2p) { // Final node in linked list, maybe null if all statements to be grabbed // Make new function string oldname = m_funcp->name(); string::size_type pos; if ((pos=oldname.find("_common")) != string::npos) { oldname.erase(pos); } if ((pos=oldname.find("__")) != string::npos) { oldname.erase(pos); } AstCFunc* newfuncp = new AstCFunc(node1p->fileline(), oldname+"_common"+cvtToStr(++m_modNFuncs), NULL); m_modp->addStmtp(newfuncp); // Create calls AstCCall* call1p = new AstCCall(node1p->fileline(), newfuncp); AstCCall* call2p = new AstCCall(node2p->fileline(), newfuncp); // Grab statement bodies AstNRelinker relink1Handle; AstNRelinker relink2Handle; for (AstNode* nextp, *walkp = node1p; 1; walkp = nextp) { nextp = walkp->nextp(); if (walkp==node1p) walkp->unlinkFrBack(&relink1Handle); else { walkp->unlinkFrBack(); node1p->addNext(walkp); } if (walkp==last1p) break; } for (AstNode* nextp, *walkp = node2p; 1; walkp = nextp) { nextp = walkp->nextp(); if (walkp==node2p) walkp->unlinkFrBack(&relink2Handle); else { walkp->unlinkFrBack(); node2p->addNext(walkp); } if (walkp==last2p) break; } // Move node1 statements to new function newfuncp->addStmtsp(node1p); //newfuncp->dumpTree(cout," newfunctree: "); // Mark node2 statements as dead CombMarkVisitor visitor(node2p); pushDeletep(node2p); // Delete later // Link in new function relink1Handle.relink(call1p); relink2Handle.relink(call2p); // Hash the new function hashFunctions(newfuncp); m_call.addCall(call1p); m_call.addCall(call2p); // If either new statement makes a func with only a single call, replace // the above callers to call it directly replaceOnlyCallFunc(call1p); VL_DANGLING(call1p); replaceOnlyCallFunc(call2p); VL_DANGLING(call2p); }
// VISITORS virtual void visit(AstCase* nodep) { V3Case::caseLint(nodep); nodep->iterateChildren(*this); if (debug()>=9) nodep->dumpTree(cout," case_old: "); if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) { // It's a simple priority encoder or complete statement // we can make a tree of statements to avoid extra comparisons ++m_statCaseFast; replaceCaseFast(nodep); VL_DANGLING(nodep); } else { ++m_statCaseSlow; replaceCaseComplicated(nodep); VL_DANGLING(nodep); } }
virtual void visit(AstGenCase* nodep, AstNUser*) { UINFO(9," GENCASE "<<nodep<<endl); AstNode* keepp = NULL; nodep->exprp()->iterateAndNext(*this); V3Case::caseLint(nodep); V3Width::widthParamsEdit(nodep); // Param typed widthing will NOT recurse the body, // don't trigger errors yet. V3Const::constifyParamsEdit(nodep->exprp()); // exprp may change AstConst* exprp = nodep->exprp()->castConst(); // Constify for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstNode* ep = itemp->condsp(); ep; ) { AstNode* nextp = ep->nextp(); //May edit list ep->iterateAndNext(*this); V3Const::constifyParamsEdit(ep); VL_DANGLING(ep); // ep may change ep = nextp; } } // Item match for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { if (!itemp->isDefault()) { for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) { if (AstConst* ccondp = ep->castConst()) { V3Number match (nodep->fileline(), 1); match.opEq(ccondp->num(), exprp->num()); if (!keepp && match.isNeqZero()) { keepp = itemp->bodysp(); } } else { itemp->v3error("Generate Case item does not evaluate to constant"); } } } } // Else default match for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { if (itemp->isDefault()) { if (!keepp) keepp=itemp->bodysp(); } } // Replace if (keepp) { keepp->unlinkFrBackWithNext(); nodep->replaceWith(keepp); } else nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep); }
virtual void visit(AstRepeat* nodep, AstNUser*) { // So later optimizations don't need to deal with them, // REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- } // Note var can be signed or unsigned based on original number. AstNode* countp = nodep->countp()->unlinkFrBackWithNext(); string name = string("__Vrepeat")+cvtToStr(m_repeatNum++); // Spec says value is integral, if negative is ignored AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, nodep->findSigned32DType()); varp->usedLoopIdx(true); m_modp->addStmtp(varp); AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), countp); AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), new AstConst(nodep->fileline(), 1))); V3Number zero (nodep->fileline(), 32, 0); zero.isSigned(true); AstNode* zerosp = new AstConst(nodep->fileline(), zero); AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), zerosp); AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext(); AstNode* newp = new AstWhile(nodep->fileline(), condp, bodysp, decp); initsp = initsp->addNext(newp); newp = initsp; nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); }
virtual void visit(AstUnlinkedVarXRef* nodep, AstNUser*) { m_unlinkedTxt.clear(); nodep->cellrefp()->iterate(*this); nodep->varxrefp()->dotted(m_unlinkedTxt); nodep->replaceWith(nodep->varxrefp()->unlinkFrBack()); pushDeletep(nodep); VL_DANGLING(nodep); }
virtual void visit(AstGenIf* nodep, AstNUser*) { UINFO(9," GENIF "<<nodep<<endl); nodep->condp()->iterateAndNext(*this); // We suppress errors when widthing params since short-circuiting in // the conditional evaluation may mean these error can never occur. We // then make sure that short-circuiting is used by constifyParamsEdit. V3Width::widthGenerateParamsEdit(nodep); // Param typed widthing will // NOT recurse the body. V3Const::constifyGenerateParamsEdit(nodep->condp()); // condp may change if (AstConst* constp = nodep->condp()->castConst()) { AstNode* keepp = (constp->isZero() ? nodep->elsesp() : nodep->ifsp()); if (keepp) { keepp->unlinkFrBackWithNext(); nodep->replaceWith(keepp); } else { nodep->unlinkFrBack(); } nodep->deleteTree(); VL_DANGLING(nodep); // Normal edit rules will now recurse the replacement } else { nodep->condp()->v3error("Generate If condition must evaluate to constant"); } }
//! Parameter subsitution for generated for loops. //! @todo Unlike generated IF, we don't have to worry about short-circuiting the conditional //! expression, since this is currently restricted to simple comparisons. If we ever do //! move to more generic constant expressions, such code will be needed here. virtual void visit(AstBegin* nodep, AstNUser*) { if (nodep->genforp()) { AstGenFor* forp = nodep->genforp()->castGenFor(); if (!forp) nodep->v3fatalSrc("Non-GENFOR under generate-for BEGIN"); // We should have a GENFOR under here. We will be replacing the begin, // so process here rather than at the generate to avoid iteration problems UINFO(9," BEGIN "<<nodep<<endl); UINFO(9," GENFOR "<<forp<<endl); V3Width::widthParamsEdit(forp); // Param typed widthing will NOT recurse the body // Outer wrapper around generate used to hold genvar, and to insure genvar // doesn't conflict in V3LinkDot resolution with other genvars // Now though we need to change BEGIN("zzz",GENFOR(...)) to // a BEGIN("zzz__BRA__{loop#}__KET__") string beginName = nodep->name(); // Leave the original Begin, as need a container for the (possible) GENVAR // Note V3Unroll will replace some AstVarRef's to the loop variable with constants V3Unroll::unrollGen(forp, beginName); VL_DANGLING(forp); // Blocks were constructed under the special begin, move them up // Note forp is null, so grab statements again if (AstNode* stmtsp = nodep->genforp()) { stmtsp->unlinkFrBackWithNext(); nodep->addNextHere(stmtsp); // Note this clears nodep->genforp(), so begin is no longer special } } else { nodep->iterateChildren(*this); } }
void replaceFunc (AstCFunc* oldfuncp, AstCFunc* newfuncp) { if (oldfuncp==newfuncp) return; if (newfuncp) { UINFO(4, " Replace "<<oldfuncp<<" -WITH-> "<<newfuncp<<endl); } else UINFO(4, " Remove "<<oldfuncp<<endl); pair <CallMmap::iterator,CallMmap::iterator> eqrange = m_callMmap.equal_range(oldfuncp); for (CallMmap::iterator nextit = eqrange.first; nextit != eqrange.second;) { CallMmap::iterator eqit = nextit++; AstCCall* callp = eqit->second; if (!callp->user3()) { // !already done UINFO(4, " Called "<<callp<<endl); if (callp->funcp() != oldfuncp) callp->v3fatalSrc("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 callp->replaceWith(newp); addCall(newp); // Fix the table } else { // Just deleting empty function callp->unlinkFrBack(); } callp->user3(true); // Dead now pushDeletep(callp); VL_DANGLING(callp); m_callMmap.erase(eqit); // Fix the table } } }
void optimize_orphans() { // Remove states that don't come from start // Presumably the previous optimization orphaned them. // Vertex::m_user begin: 1 indicates on the work list, 2 processed // (Otherwise we might have nodes on the list twice, and reference after deleting them.) m_graphp->userClearVertices(); DfaVertex* startp = graphp()->findStart(); stack<V3GraphVertex*> workps; workps.push(startp); // Mark all nodes connected to start while (!workps.empty()) { V3GraphVertex* vertexp = workps.top(); workps.pop(); vertexp->user(2); // Processed // Add nodes from here to the work list for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { V3GraphVertex* tovertexp = edgep->top(); if (!tovertexp->user()) { workps.push(tovertexp); tovertexp->user(1); } } } // Delete all nodes not connected for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) { nextp = vertexp->verticesNextp(); if (!vertexp->user()) { vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp); } } }
// VISITORS virtual void visit(AstNodeVarRef* nodep, AstNUser*) { if (nodep->varScopep() == m_elimVarScp) { // Substitute in the new tree // 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"); AstNode* substp = m_replaceTreep->cloneTree(false); if (nodep->castNodeVarRef() && substp->castNodeVarRef() && nodep->same(substp)) { // Prevent a infinite loop... substp->v3fatalSrc("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. // However a VARREF should point to the original as it's otherwise confusing // to throw warnings that point to a PIN rather than where the pin us used. if (substp->castVarRef()) substp->fileline(nodep->fileline()); // Make the substp an rvalue like nodep. This facilitate the hashing in dedupe. if (AstNodeVarRef* varrefp = substp->castNodeVarRef()) varrefp->lvalue(false); nodep->replaceWith(substp); nodep->deleteTree(); VL_DANGLING(nodep); } }
// VISITORS virtual void visit(AstVarScope* nodep, AstNUser*) { if (AstNodeAssign* assp = nodep->valuep()->castNodeAssign()) { UINFO(5," Removeassign "<<assp<<endl); AstNode* valuep = assp->rhsp(); valuep->unlinkFrBack(); assp->replaceWith(valuep); assp->deleteTree(); VL_DANGLING(assp); } }
void checkConstantOrReplace(AstNode* nodep, const string& message) { // See also V3Width::checkConstantOrReplace // Note can't call V3Const::constifyParam(nodep) here, as constify may change nodep on us! if (!nodep->castConst()) { nodep->v3error(message); nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Unsized32(), 1)); pushDeletep(nodep); VL_DANGLING(nodep); } }
virtual void visit(AstInitial* nodep) { AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName()); nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { stmtsp->unlinkFrBackWithNext(); cmtp->addNextHere(stmtsp); } nodep->deleteTree(); VL_DANGLING(nodep); }
explicit RemovePlaceholdersVisitor(AstNode* nodep) { iterate(nodep); for (NodeSet::const_iterator it = m_removeSet.begin(); it != m_removeSet.end(); ++it) { AstNode* np = *it; np->unlinkFrBack(); // Without next np->deleteTree(); VL_DANGLING(np); } }
virtual void visit(AstIsUnknown* nodep) { nodep->iterateChildren(*this); // Ahh, we're two state, so this is easy UINFO(4," ISUNKNOWN->0 "<<nodep<<endl); V3Number zero (nodep->fileline(), 1, 0); AstConst* newp = new AstConst (nodep->fileline(), zero); nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); }
virtual void visit(AstBreak* nodep, AstNUser*) { nodep->iterateChildren(*this); if (!m_loopp) { nodep->v3error("break isn't underneath a loop"); } else { // Jump to the end of the loop AstJumpLabel* labelp = findAddLabel(m_loopp, false); nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp)); } nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep); }
void replaceFuncWFunc(AstCFunc* oldfuncp, AstCFunc* newfuncp) { UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl); UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl); // Mark user3p on entire old tree, so we don't process it more ++m_statCombs; CombMarkVisitor visitor(oldfuncp); m_call.replaceFunc(oldfuncp, newfuncp); oldfuncp->unlinkFrBack(); pushDeletep(oldfuncp); VL_DANGLING(oldfuncp); }
virtual void visit(AstPragma* nodep) { if (nodep->pragType() == AstPragmaType::INLINE_MODULE) { //UINFO(0,"PRAG MARK "<<m_modp<<endl); if (!m_modp) { nodep->v3error("Inline pragma not under a module"); } else { m_modp->user1(1); } nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell... } else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) { if (!m_modp) { nodep->v3error("Inline pragma not under a module"); } else { cantInline("Pragma NO_INLINE_MODULE",false); } nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell... } else { nodep->iterateChildren(*this); } }
virtual void visit(AstContinue* nodep, AstNUser*) { nodep->iterateChildren(*this); if (!m_loopp) { nodep->v3error("continue isn't underneath a loop"); } else { // Jump to the end of this iteration // If a "for" loop then need to still do the post-loop increment AstJumpLabel* labelp = findAddLabel(m_loopp, true); nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp)); } nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep); }
virtual void visit(AstAlways* nodep, AstNUser*) { // Move always to appropriate ACTIVE based on its sense list UINFO(4," ALW "<<nodep<<endl); //if (debug()>=9) nodep->dumpTree(cout," Alw: "); if (!nodep->bodysp()) { // Empty always. Kill it. nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); return; } visitAlways(nodep, nodep->sensesp(), nodep->keyword()); }
// VISITORS //========== Statements virtual void visit(AstClocking* nodep, AstNUser*) { UINFO(8," CLOCKING"<<nodep<<endl); // Store the new default clock, reset on new module m_seniDefaultp = nodep->sensesp(); // Trash it, keeping children if (nodep->bodysp()) { nodep->replaceWith(nodep->bodysp()->unlinkFrBack()); } else { nodep->unlinkFrBack(); } pushDeletep(nodep); VL_DANGLING(nodep); }
virtual void visit(AstNodeAssign* nodep, AstNUser*) { if (nodep->user2() < 2) return; // Don't need clones m_selBits.clear(); UINFO(4, "Cloning "<<nodep->user2()<<" times: "<<nodep<<endl); for (int i = 0; i < nodep->user2(); ++i) { // Clone the node and iterate over the clone m_vecIdx = -1; AstNodeAssign* clonep = nodep->cloneTree(false)->castNodeAssign(); clonep->iterateChildren(*this); nodep->addNextHere(clonep); } nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); }
void GateVisitor::replaceAssigns() { for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) { // Take the Comments/assigns that were moved to the VarScope and change them to a // simple value assignment AstVarScope* vscp = vvertexp->varScp(); if (vscp->valuep() && !vscp->valuep()->castNodeMath()) { //if (debug()>9) vscp->dumpTree(cout, "-vscPre: "); while (AstNode* delp=vscp->valuep()->castComment()) { delp->unlinkFrBack()->deleteTree(); VL_DANGLING(delp); } if (AstInitial* delp=vscp->valuep()->castInitial()) { AstNode* bodyp=delp->bodysp(); bodyp->unlinkFrBackWithNext(); delp->replaceWith(bodyp); delp->deleteTree(); VL_DANGLING(delp); } if (AstAlways* delp=vscp->valuep()->castAlways()) { AstNode* bodyp=delp->bodysp(); bodyp->unlinkFrBackWithNext(); delp->replaceWith(bodyp); delp->deleteTree(); VL_DANGLING(delp); } if (AstNodeAssign* delp=vscp->valuep()->castNodeAssign()) { AstNode* rhsp=delp->rhsp(); rhsp->unlinkFrBack(); delp->replaceWith(rhsp); delp->deleteTree(); VL_DANGLING(delp); } //if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<<endl;} if (!vscp->valuep()->castNodeMath() || vscp->valuep()->nextp()) { vscp->dumpTree(cerr, "vscStrange: "); vscp->v3fatalSrc("Value of varscope not mathematical\n"); } } } } }
void V3Stats::statsReport() { UINFO(2,__FUNCTION__<<": "<<endl); // Open stats file string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__stats.txt"; std::ofstream* ofp (V3File::new_ofstream(filename)); if (ofp->fail()) v3fatal("Can't write "<<filename); StatsReport reporter (ofp); // Cleanup ofp->close(); delete ofp; VL_DANGLING(ofp); }
void deadCheckVar() { // Delete any unused varscopes for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) { AstVarScope* vscp = *it; if (vscp->user1() == 0) { UINFO(4," Dead "<<vscp<<endl); pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp); for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) { AstNodeAssign* assp = it->second; UINFO(4," Dead assign "<<assp<<endl); assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp); } vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp); } } for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) { if ((*it)->user1() == 0) { UINFO(4," Dead "<<(*it)<<endl); (*it)->unlinkFrBack()->deleteTree(); (*it)=NULL; } } }