示例#1
0
    void createDeepTemp(AstNode* nodep) {
	UINFO(6,"  Deep  "<<nodep<<endl);
	//if (debug()>=9) nodep->dumpTree(cout,"deep:");

	string newvarname = ((string)"__Vdeeptemp"+cvtToStr(m_modp->varNumGetInc()));
	AstVar* varp = new AstVar (nodep->fileline(), AstVarType::STMTTEMP, newvarname,
				   // Width, not widthMin, as we may be in middle of BITSEL expression which
				   // though it's one bit wide, needs the mask in the upper bits.
				   // (Someday we'll have a valid 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");
	m_funcp->addInitsp(varp);
	// Replace node tree with reference to var
	AstVarRef* newp = new AstVarRef (nodep->fileline(), varp, false);
	nodep->replaceWith(newp);
	// Put assignment before the referencing statement
	AstAssign* assp = new AstAssign (nodep->fileline(),
					 new AstVarRef(nodep->fileline(), varp, true),
					 nodep);
	AstNRelinker linker2;
	m_stmtp->unlinkFrBack(&linker2);
	assp->addNext(m_stmtp);
	linker2.relink(assp);
    }
示例#2
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);
     }
 }
示例#3
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);
	}
    }
示例#4
0
    void replaceDisplay(AstDisplay* nodep, const string& prefix) {
	nodep->displayType(AstDisplayType::DT_WRITE);
	nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
	AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
	timesp = timesp->addNext(new AstTime(nodep->fileline()));
	nodep->fmtp()->exprsp(timesp);
	if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
	    nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
	}
    }
示例#5
0
    AstJumpLabel* findAddLabel(AstNode* nodep, bool endOfIter) {
	// Put label under given node, and if WHILE optionally at end of iteration
	UINFO(4,"Create label for "<<nodep<<endl);
	if (nodep->castJumpLabel()) return nodep->castJumpLabel(); // Done

	AstNode* underp = NULL;
	bool     under_and_next = true;
	if (nodep->castBegin()) underp = nodep->castBegin()->stmtsp();
	else if (nodep->castNodeFTask()) underp = nodep->castNodeFTask()->stmtsp();
	else if (nodep->castWhile()) {
	    if (endOfIter) {
		// Note we jump to end of bodysp; a FOR loop has its increment under incsp() which we don't skip
		underp = nodep->castWhile()->bodysp();
	    } else {
		underp = nodep; under_and_next=false; // IE we skip the entire while
	    }
	}
	else {
	    nodep->v3fatalSrc("Unknown jump point for break/disable/continue");
	    return NULL;
	}
	// Skip over variables as we'll just move them in a momement
	// Also this would otherwise prevent us from using a label twice
	// see t_func_return test.
	while (underp && underp->castVar()) underp = underp->nextp();
	if (underp) UINFO(5,"  Underpoint is "<<underp<<endl);

	if (!underp) {
	    nodep->v3fatalSrc("Break/disable/continue not under expected statement");
	    return NULL;
	} else if (underp->castJumpLabel()) {
	    return underp->castJumpLabel();
	} else { // Move underp stuff to be under a new label
	    AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), NULL);

	    AstNRelinker repHandle;
	    if (under_and_next) underp->unlinkFrBackWithNext(&repHandle);
	    else underp->unlinkFrBack(&repHandle);
	    repHandle.relink(labelp);

	    labelp->addStmtsp(underp);
	    // Keep any AstVars under the function not under the new JumpLabel
	    for (AstNode* nextp, *varp=underp; varp; varp = nextp) {
		nextp = varp->nextp();
		if (varp->castVar()) {
		    labelp->addPrev(varp->unlinkFrBack());
		}
	    }
	    return labelp;
	}
    }
示例#6
0
    void insertBeforeStmt(AstNode* newp) {
	// Insert newp before m_stmtp
	if (m_inWhilep) {
	    // Statements that are needed for the 'condition' in a while actually have to
	    // be put before & after the loop, since we can't do any statements in a while's (cond).
	    m_inWhilep->addPrecondsp(newp);
	} else if (m_inTracep) {
	    m_inTracep->addPrecondsp(newp);
	} else if (m_stmtp) {
	    AstNRelinker linker;
	    m_stmtp->unlinkFrBack(&linker);
	    newp->addNext(m_stmtp);
	    linker.relink(newp);
	} else {
	    newp->v3fatalSrc("No statement insertion point.");
	}
    }
示例#7
0
    virtual AstNUser* visit(GateVarVertex *vvertexp, AstNUser*) {
	// Check that we haven't been here before
	if (vvertexp->varScp()->user2()) return NULL;
	vvertexp->varScp()->user2(true);

	AstNodeVarRef* dupVarRefp = (AstNodeVarRef*) vvertexp->iterateInEdges(*this, (AstNUser*) vvertexp);

	if (dupVarRefp && vvertexp->inSize1()) {
	    V3GraphEdge* edgep = vvertexp->inBeginp();
	    GateLogicVertex* lvertexp = (GateLogicVertex*)edgep->fromp();
	    if (!vvertexp->dedupable()) vvertexp->varScp()->v3fatalSrc("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();
		GateVarVertex* dupVvertexp = (GateVarVertex*) (dupVarScopep->user1p());
		UINFO(4,"replacing " << vvertexp << " with " << dupVvertexp << endl);
		++m_numDeduped;
		// Replace all of this varvertex's consumers with dupVarRefp
		for (V3GraphEdge* outedgep = vvertexp->outBeginp();outedgep;) {
		    GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(outedgep->top());
		    AstNode* consumerp = consumeVertexp->nodep();
		    GateElimVisitor elimVisitor(consumerp,vvertexp->varScp(),dupVarRefp);
		    outedgep = outedgep->relinkFromp(dupVvertexp);
		}

		// Propogate attributes
		dupVvertexp->propagateAttrClocksFrom(vvertexp);

		// Remove inputs links
		while (V3GraphEdge* inedgep = vvertexp->inBeginp()) {
		    inedgep->unlinkDelete(); VL_DANGLING(inedgep);
		}
		// replaceAssigns() does the deleteTree on lvertexNodep in a later step
		AstNode* lvertexNodep = lvertexp->nodep();
		lvertexNodep->unlinkFrBack();
		vvertexp->varScp()->valuep(lvertexNodep);
		lvertexNodep = NULL;
		vvertexp->user(true);
		lvertexp->user(true);
	    }
	}
	return NULL;
    }
示例#8
0
void GateVisitor::consumedMove() {
    // Remove unused logic (logic that doesn't hit a combo block or a display statement)
    // We need the "usually" block logic to do a better job at this
    for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(vertexp)) {
	    if (!vvertexp->consumed() && !vvertexp->user()) {
		UINFO(8, "Unconsumed "<<vvertexp->varScp()<<endl);
	    }
	}
	if (GateLogicVertex* lvertexp = dynamic_cast<GateLogicVertex*>(vertexp)) {
	    AstNode* nodep = lvertexp->nodep();
	    AstActive* oldactp = lvertexp->activep();  // NULL under cfunc
	    if (!lvertexp->consumed() && oldactp) {
		// Eventually: Move the statement to a new active block with "tracing-on" sensitivity
		UINFO(8,"    Remove unconsumed "<<nodep<<endl);
		nodep->unlinkFrBack();
		pushDeletep(nodep); VL_DANGLING(nodep);
	    }
	}
    }
}
示例#9
0
    void reorderBlock(AstNode* nodep) {
	// Reorder statements in the completed graph

	// Map the rank numbers into nodes they associate with
        typedef std::multimap<uint32_t,AstNode*> RankNodeMap;
        RankNodeMap rankMap;
	int currOrder = 0;	// Existing sequence number of assignment
	for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
	    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
	    rankMap.insert(make_pair(vvertexp->rank(), nextp));
	    nextp->user4(++currOrder);   // Record current ordering
	}

	// Is the current ordering OK?
	bool leaveAlone=true;
	int newOrder = 0;	// New sequence number of assignment
        for (RankNodeMap::const_iterator it = rankMap.begin();
             it != rankMap.end(); ++it) {
            AstNode* nextp = it->second;
            if (++newOrder != nextp->user4()) leaveAlone=false;
        }
	if (leaveAlone) {
	    UINFO(6,"   No changes\n");
	} else {
	    AstNRelinker replaceHandle;	// Where to add the list
            AstNode* newListp = NULL;
            for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) {
                AstNode* nextp = it->second;
                UINFO(6, "   New order: "<<nextp<<endl);
                if (nextp == nodep) nodep->unlinkFrBack(&replaceHandle);
                else nextp->unlinkFrBack();
                if (newListp) newListp = newListp->addNext(nextp);
                else newListp = nextp;
            }
            replaceHandle.relink(newListp);
	} // leaveAlone
    }
示例#10
0
void GateVisitor::optimizeSignals(bool allowMultiIn) {
    for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
	if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
	    if (vvertexp->inEmpty()) {
		vvertexp->clearReducibleAndDedupable("inEmpty");	// Can't deal with no sources
		if (!vvertexp->isTop()		// Ok if top inputs are driverless
		    && !vvertexp->varScp()->varp()->valuep()
		    && !vvertexp->varScp()->varp()->isSigPublic()) {
		    UINFO(4, "No drivers "<<vvertexp->varScp()<<endl);
		    if (0) {
			// If we warned here after constant propagation, what the user considered
			// reasonable logic may have disappeared.  Issuing a warning would
			// thus be confusing.  V3Undriven now handles this.
			vvertexp->varScp()->varp()->v3warn(UNDRIVEN,"Signal has no drivers "
							   <<vvertexp->scopep()->prettyName()<<"."
							   <<vvertexp->varScp()->varp()->prettyName());
		    }
		}
	    }
	    else if (!vvertexp->inSize1()) {
		vvertexp->clearReducibleAndDedupable("size!1");	// Can't deal with more than one src
	    }
	    // Reduce it?
	    if (!vvertexp->reducible()) {
		UINFO(8, "SigNotRed "<<vvertexp->name()<<endl);
	    } else {
		UINFO(8, "Sig "<<vvertexp->name()<<endl);
		GateLogicVertex* logicVertexp = dynamic_cast<GateLogicVertex*>
		    (vvertexp->inBeginp()->fromp());
		UINFO(8, "  From "<<logicVertexp->name()<<endl);
		AstNode* logicp = logicVertexp->nodep();
		if (logicVertexp->reducible()) {
		    // Can we eliminate?
		    GateOkVisitor okVisitor(logicp, vvertexp->isClock(), false);
		    bool multiInputs = okVisitor.rhsVarRefs().size() > 1;
		    // Was it ok?
		    bool doit = okVisitor.isSimple();
		    if (doit && multiInputs) {
			if (!allowMultiIn) doit = false;
			// Doit if one input, or not used, or used only once, ignoring traces
			int n=0;
			for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
			    GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
			    if (!consumeVertexp->slow()) { // Not tracing or other slow path junk
				if (edgep->top()->outBeginp()) {  // Destination is itself used
				    n += edgep->weight();
				}
			    }
			    if (n>1) {
				doit = false;
				break;
			    }
			}
		    }
		    // Process it
		    if (!doit) {
			if (allowMultiIn && (debug()>=9)) {
			    UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
				  <<" ob"<<vvertexp->outBeginp()<<" on"<<(vvertexp->outBeginp()?vvertexp->outBeginp()->outNextp():0)
				  <<" "<<vvertexp->name()
				  <<endl);
			    for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
				GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
				UINFO(9, "    edge "<<edgep<<" to: "<<consumeVertexp->nodep()<<endl);
			    }
			    for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
				GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->fromp());
				UINFO(9, "    edge "<<edgep<<" from: "<<consumeVertexp->nodep()<<endl);
			    }
			}
		    }
		    else {
			AstNode* substp = okVisitor.substTree();
			if (debug()>=5) logicp->dumpTree(cout,"\telimVar:  ");
			if (debug()>=5) substp->dumpTree(cout,"\t  subst:  ");
			++m_statSigs;
			bool removedAllUsages = true;
			for (V3GraphEdge* edgep = vvertexp->outBeginp();
			     edgep; ) {
			    GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
			    AstNode* consumerp = consumeVertexp->nodep();
			    if (!elimLogicOkOutputs(consumeVertexp, okVisitor/*ref*/)) {
				// Cannot optimize this replacement
				removedAllUsages = false;
				edgep = edgep->outNextp();
			    } else {
				optimizeElimVar(vvertexp->varScp(), substp, consumerp);
				// If the new replacement referred to a signal,
				// Correct the graph to point to this new generating variable
				const GateVarRefList& rhsVarRefs = okVisitor.rhsVarRefs();
				for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
				     it != rhsVarRefs.end(); ++it) {
				    AstVarScope* newvarscp = (*it)->varScopep();
				    UINFO(9,"         Point-to-new vertex "<<newvarscp<<endl);
				    GateVarVertex* varvertexp = makeVarVertex(newvarscp);
				    new V3GraphEdge(&m_graph, varvertexp, consumeVertexp, 1);
				    // Propagate clock attribute onto generating node
				    varvertexp->propagateAttrClocksFrom(vvertexp);
				}
				// Remove the edge
				edgep->unlinkDelete(); VL_DANGLING(edgep);
				++m_statRefs;
				edgep = vvertexp->outBeginp();
			    }
			}
			if (removedAllUsages) {
			    // Remove input links
			    while (V3GraphEdge* edgep = vvertexp->inBeginp()) {
				edgep->unlinkDelete(); VL_DANGLING(edgep);
			    }
			    // Clone tree so we remember it for tracing, and keep the pointer
			    // to the "ALWAYS" part of the tree as part of this statement
			    // That way if a later signal optimization that retained a pointer to the always
			    // can optimize it further
			    logicp->unlinkFrBack();
			    vvertexp->varScp()->valuep(logicp);
			    logicp = NULL;
			    // Mark the vertex so we don't mark it as being unconsumed in the next step
			    vvertexp->user(true);
			    logicVertexp->user(true);
			}
		    }
		}
	    }
	}
    }
}
示例#11
0
文件: V3Case.cpp 项目: grg/verilator
    void replaceCaseComplicated(AstCase* nodep) {
	// CASEx(cexpr,ITEM(icond1,istmts1),ITEM(icond2,istmts2),ITEM(default,istmts3))
	// ->  IF((cexpr==icond1),istmts1,
	//		         IF((EQ (AND MASK cexpr) (AND MASK icond1)
	//				,istmts2, istmts3
	AstNode* cexprp = nodep->exprp()->unlinkFrBack();
	// We'll do this in two stages.  First stage, convert the conditions to
	// the appropriate IF AND terms.
	if (debug()>=9) nodep->dumpTree(cout,"    _comp_IN:   ");
	bool hadDefault = false;
	for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
	    if (!itemp->condsp()) {
		// Default clause.  Just make true, we'll optimize it away later
		itemp->condsp(new AstConst(itemp->fileline(), AstConst::LogicTrue()));
		hadDefault = true;
	    } else {
		// Expressioned clause
		AstNode* icondNextp = NULL;
		AstNode* ifexprp = NULL;	// If expression to test
		for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) {
		    icondNextp = icondp->nextp();
		    icondp->unlinkFrBack();

		    AstNode* condp = NULL;  // Default is to use and1p/and2p
		    AstConst* iconstp = icondp->castConst();
		    if (iconstp && neverItem(nodep, iconstp)) {
			// X in casez can't ever be executed
			icondp->deleteTree(); icondp=NULL; iconstp=NULL;
			// For simplicity, make expression that is not equal, and let later
			// optimizations remove it
			condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
		    } else if (AstInsideRange* irangep = icondp->castInsideRange()) {
			// Similar logic in V3Width::visit(AstInside)
			AstNode* ap = AstGte::newTyped(itemp->fileline(),
						       cexprp->cloneTree(false),
						       irangep->lhsp()->unlinkFrBack());
			AstNode* bp = AstLte::newTyped(itemp->fileline(),
						       cexprp->cloneTree(false),
						       irangep->rhsp()->unlinkFrBack());
			condp = new AstAnd(itemp->fileline(), ap, bp);
		    } else if (iconstp && iconstp->num().isFourState()
			       && (nodep->casex() || nodep->casez() || nodep->caseInside())) {
			V3Number nummask (itemp->fileline(), iconstp->width());
			nummask.opBitsNonX(iconstp->num());
			V3Number numval  (itemp->fileline(), iconstp->width());
			numval.opBitsOne(iconstp->num());
			AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
						    new AstConst(itemp->fileline(), nummask));
			AstNode* and2p = new AstAnd(itemp->fileline(),
						    new AstConst(itemp->fileline(), numval),
						    new AstConst(itemp->fileline(), nummask));
			icondp->deleteTree(); icondp=NULL; iconstp=NULL;
			condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
		    } else {
			// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
			AstNode* and1p = cexprp->cloneTree(false);
			AstNode* and2p = icondp;
			condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
		    }
		    if (!ifexprp) {
			ifexprp = condp;
		    } else {
			ifexprp = new AstLogOr(itemp->fileline(), ifexprp, condp);
		    }
		}
		// Replace expression in tree
		itemp->condsp(ifexprp);
	    }
	}
	cexprp->deleteTree(); cexprp=NULL;
	if (!hadDefault) {
	    // If there was no default, add a empty one, this greatly simplifies below code
	    // and constant propagation will just eliminate it for us later.
	    nodep->addItemsp(new AstCaseItem(nodep->fileline(),
					     new AstConst(nodep->fileline(), AstConst::LogicTrue()),
					     NULL));
	}
	if (debug()>=9) nodep->dumpTree(cout,"    _comp_COND: ");
	// Now build the IF statement tree
	// The tree can be quite huge.  Pull ever group of 8 out, and make a OR tree.
	// This reduces the depth for the bottom elements, at the cost of some of the top elements.
	// If we ever have profiling data, we should pull out the most common item from here and
	// instead make it the first IF branch.
	int depth = 0;
	AstNode* grouprootp = NULL;
	AstIf* groupnextp = NULL;
	AstIf* itemnextp = NULL;
	for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
	    AstNode* istmtsp = itemp->bodysp();   // Maybe null -- no action.
	    if (istmtsp) istmtsp->unlinkFrBackWithNext();
	    // Expressioned clause
	    AstNode* ifexprp = itemp->condsp()->unlinkFrBack();
	    {   // Prepare for next group
		if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
		if (depth == 1) {  // First group or starting new group
		    itemnextp = NULL;
		    AstIf* newp = new AstIf(itemp->fileline(), ifexprp->cloneTree(true), NULL, NULL);
		    if (groupnextp) groupnextp->addElsesp(newp);
		    else grouprootp = newp;
		    groupnextp = newp;
		} else { // Continue group, modify if condition to OR in this new condition
		    AstNode* condp = groupnextp->condp()->unlinkFrBack();
		    groupnextp->condp(new AstOr(ifexprp->fileline(),
						condp,
						ifexprp->cloneTree(true)));
		}
	    }
	    {   // Make the new lower IF and attach in the tree
		AstNode* itemexprp = ifexprp;  ifexprp=NULL;
		if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
		    itemexprp->deleteTree(); itemexprp=NULL;
		    itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
		}
		AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
		if (itemnextp) itemnextp->addElsesp(newp);
		else groupnextp->addIfsp(newp);  // First in a new group
		itemnextp = newp;
	    }
	}
	if (debug()>=9) nodep->dumpTree(cout,"    _comp_TREE: ");
	// Handle any assertions
	replaceCaseParallel(nodep, false);
	// Replace the CASE... with IF...
	if (debug()>=9) grouprootp->dumpTree(cout,"     _new: ");
	if (grouprootp) nodep->replaceWith(grouprootp);
	else nodep->unlinkFrBack();
	nodep->deleteTree(); nodep=NULL;
    }
示例#12
0
    virtual void visit(AstAssignW* nodep, AstNUser*) {
	// Note: this detects and expands tristates of the forms:
	// assign x = (OE) ?  y  : 'hZ;
	// assign x = (OE) ? 'hz :  y;

	// see if this a COND and separate out the __en logic from the output logic if it is
	if (AstCond* condp = nodep->rhsp()->castCond()) {
	    //if (debug()>=9) nodep->dumpTree(cout,"-   cond-in: ");
	    AstNode* oep = condp->condp();
	    AstNode* expr1p = condp->expr1p();
	    AstNode* expr2p = condp->expr2p();
	    AstNode* enrhsp;
	    AstNode* outrhsp;

	    if (expr1p->castConst() && expr1p->castConst()->num().isAllZ()) {
		enrhsp = new AstNot(oep->fileline(), oep->unlinkFrBack());
		outrhsp = expr2p->unlinkFrBack();
	    } else if (expr2p->castConst() && expr2p->castConst()->num().isAllZ()){
		enrhsp = oep->unlinkFrBack();
		outrhsp = expr1p->unlinkFrBack();
	    } else {
		// not a tristate or not in a form we recgonize, so exit and move on.
		return;
	    }

	    AstNode* outp = nodep->lhsp()->unlinkFrBack();;
	    AstVarRef* outrefp = NULL;
	    if (outp->castVarRef()) {
		outrefp = outp->castVarRef();
	    } else if (outp->castSel()) {
		outrefp = outp->castSel()->fromp()->castVarRef();
	    } else {
		nodep->v3error("Can't find LHS varref");
	    }

	    createEnableVar(outp, outrefp, enrhsp, outrhsp->width());

	    // replace the old assign logic with the new one
	    AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
	    //if (debug()>=9) newassp->dumpTreeAndNext(cout,"-   cond-out: ");
	    nodep->replaceWith(newassp);
	    nodep->deleteTree(); nodep=NULL;
	    newassp->iterateChildren(*this);

	}
	// How about a tri gate?
	else if (AstBufIf1* bufp = nodep->rhsp()->castBufIf1()) {
	    //if (debug()>=9) nodep->dumpTree(cout,"-   tri-in : ");
	    AstNode* enrhsp = bufp->lhsp()->unlinkFrBack();
	    AstNode* outrhsp = bufp->rhsp()->unlinkFrBack();

	    AstNode* outp = nodep->lhsp()->unlinkFrBack();;
	    AstVarRef* outrefp = NULL;
	    if (outp->castVarRef()) {
		outrefp = outp->castVarRef();
	    } else if (outp->castSel()) {
		outrefp = outp->castSel()->fromp()->castVarRef();
	    } else {
		nodep->v3error("Can't find LHS varref");
	    }

	    createEnableVar(outp, outrefp, enrhsp, outrhsp->width());

	    // replace the old assign logic with the new one
	    AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
	    //if (debug()>=9) newassp->dumpTreeAndNext(cout,"-   tri-out: ");
	    nodep->replaceWith(newassp);
	    nodep->deleteTree(); nodep=NULL;
	    newassp->iterateChildren(*this);
	}
	else {
	    nodep->iterateChildren(*this);
	}
    }
示例#13
0
    void reorderBlock(AstNode* nodep) {
	// Reorder statements in the completed graph
	AstAlways* splitAlwaysp = nodep->backp()->castAlways();

	// Map the rank numbers into nodes they associate with
	typedef multimap<uint32_t,AstNode*> RankNodeMap;
	typedef map<uint32_t,RankNodeMap> ColorRankMap;
	ColorRankMap colorRankMap;
	uint32_t firstColor = 0;  bool multiColors = false;
	int currOrder = 0;	// Existing sequence number of assignment
	for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
	    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
	    if (!splitAlwaysp) vvertexp->splitColor(1);  // All blocks remain as-is
	    RankNodeMap& rankMap = colorRankMap[vvertexp->splitColor()];
	    rankMap.insert(make_pair(vvertexp->rank(), nextp));
	    if (firstColor && firstColor != vvertexp->splitColor()) multiColors = true;
	    firstColor = vvertexp->splitColor();
	    nextp->user4(++currOrder);   // Record current ordering
	}
	// If there was only one color, we don't need multiple always blocks
	if (!multiColors) splitAlwaysp = NULL;

	// Is the current ordering OK?
	bool leaveAlone=true;
	if (splitAlwaysp) leaveAlone=false;
	int newOrder = 0;	// New sequence number of assignment
	for (ColorRankMap::iterator colorIt = colorRankMap.begin(); colorIt != colorRankMap.end(); ++colorIt) {
	    RankNodeMap& rankMap = colorIt->second;
	    for (RankNodeMap::iterator it = rankMap.begin(); it != rankMap.end(); ++it) {
		AstNode* nextp = it->second;
		if (++newOrder != nextp->user4()) leaveAlone=false;
	    }
	}
	if (leaveAlone) {
	    UINFO(6,"   No changes\n");
	} else {
	    AstNRelinker replaceHandle;	// Where to add the list
	    AstNode* addAfterp = splitAlwaysp;

	    for (ColorRankMap::iterator colorIt = colorRankMap.begin(); colorIt != colorRankMap.end(); ++colorIt) {
		uint32_t color = colorIt->first;
		RankNodeMap& rankMap = colorIt->second;
		AstNode* newListp = NULL;
		for (RankNodeMap::iterator it = rankMap.begin(); it != rankMap.end(); ++it) {
		    AstNode* nextp = it->second;
		    UINFO(6, "    Color="<<color<<"  New order: "<<nextp<<endl);
		    if (nextp == nodep && !splitAlwaysp) nodep->unlinkFrBack(&replaceHandle);
		    else nextp->unlinkFrBack();
		    newListp = newListp->addNext(nextp);
		}
		if (splitAlwaysp) {
		    ++m_statSplits;
		    AstAlways* alwaysp = new AstAlways(newListp->fileline(), VAlwaysKwd::ALWAYS, NULL, NULL);
		    addAfterp->addNextHere(alwaysp);  addAfterp=alwaysp;
		    alwaysp->addStmtp(newListp);
		} else {
		    // Just reordering
		    replaceHandle.relink(newListp);
		}
	    }
	    if (splitAlwaysp) {
		pushDeletep(splitAlwaysp->unlinkFrBack());
	    }
	} // leaveAlone
    }