示例#1
0
    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
	    }
	}
    }
示例#2
0
    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);
	}
    }
示例#3
0
    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");
	    }
	}
    }
示例#4
0
    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: ");
    }
示例#5
0
    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;
        }
    }
示例#6
0
    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);
    }
示例#7
0
    // 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);
	}
    }
示例#8
0
    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);
    }
示例#9
0
    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);
    }
示例#10
0
    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);
    }
示例#11
0
    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");
	}
    }
示例#12
0
    //! 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);
	}
    }
示例#13
0
    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
	    }
	}
    }
示例#14
0
    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);
	    }
	}
    }
示例#15
0
    // 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);
	}
    }
示例#16
0
    // 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);
	}
    }
示例#17
0
    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);
	}
    }
示例#18
0
    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);
    }
示例#19
0
 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);
     }
 }
示例#20
0
    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);
    }
示例#21
0
    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);
    }
示例#22
0
    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);
    }
示例#23
0
    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);
	}
    }
示例#24
0
    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);
    }
示例#25
0
    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());
    }
示例#26
0
    // 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);
    }
示例#27
0
    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);
    }
示例#28
0
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");
		}
	    }
	}
    }
}
示例#29
0
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);
}
示例#30
0
    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;
	    }
	}
    }