Example #1
0
void V3Hashed::erase(iterator it) {
    AstNode* nodep = iteratorNodep(it);
    UINFO(8,"   erase "<<nodep<<endl);
    if (!nodep->user4p()) nodep->v3fatalSrc("Called removeNode on non-hashed node");
    m_hashMmap.erase(it);
    nodep->user4p(NULL);   // So we don't allow removeNode again
}
Example #2
0
    virtual void visit(AstVarRef* nodep, AstNUser*) {
	if (nodep->lvalue()) {
	    AstVarScope* vscp = nodep->varScopep();
	    if (nodep->varp()->isSigPublic()) {
		// Public signals shouldn't be changed, pli code might be messing with them
		scoreboardPli(nodep);
	    }
	    // If another lvalue in this node, give up optimizing.
	    // We could just not optimize this variable, but we've already marked the
	    // other variable as optimizable, so we can instead pretend it's a PLI node.
	    if (m_stmtVscp) {
		UINFO(5, "   Multiple lvalues in one statement: "<<nodep<<endl);
		scoreboardPli(nodep);  // This will set m_stmtInPli
	    }
	    m_stmtVscp = vscp;
	    // Find, or make new Vertex
	    GaterVarVertex* vertexp = (GaterVarVertex*)(vscp->user1p());
	    if (!vertexp) {
		vertexp = new GaterVarVertex(&m_graph, vscp);
		vscp->user1p(vertexp);
	    }
	    new GaterEdge(&m_graph, m_aboveVertexp, vertexp, m_aboveTrue);
	    if (m_stmtInPli) {
		new GaterEdge(&m_graph, m_pliVertexp, vertexp, VU_PLI);
	    }
	}
    }
Example #3
0
    // VISITORS
    virtual void visit(AstNodeModule* nodep, AstNUser*) {
	UINFO(4," MOD   "<<nodep<<endl);
	m_modp = nodep;
	m_constXCvt = true;
	nodep->iterateChildren(*this);
	m_modp = NULL;
    }
Example #4
0
    void moveVars() {
	for (vector<AstVar*>::iterator it = m_varps.begin(); it != m_varps.end(); ++it) {
	    AstVar* nodep = *it;
	    if (nodep->valuep()) clearOptimizable(nodep,"HasInitValue");
	    if (!VarFlags(nodep).m_stdFuncAsn) clearStdOptimizable(nodep,"NoStdAssign");
	    VarFlags flags (nodep);
	    if ((nodep->isMovableToBlock() // Blocktemp
		 || !flags.m_notStd)	// Or used only in block
		&& !flags.m_notOpt	// Optimizable
		&& nodep->user1p()) {	// Single cfunc
		// We don't need to test for tracing; it would be in the tracefunc if it was needed
		UINFO(4,"  ModVar->BlkVar "<<nodep<<endl);
		++m_statLocVars;
		AstCFunc* newfuncp = nodep->user1p()->castCFunc();
		nodep->unlinkFrBack();
		newfuncp->addInitsp(nodep);
		// Done
		flags.m_done = true;
		flags.setNodeFlags(nodep);
	    } else {
		clearOptimizable(nodep, "NotDone");
	    }
	}
	m_varps.clear();
    }
Example #5
0
    virtual void visit(AstVarRef* nodep) {
	if (!VarFlags(nodep->varp()).m_notOpt) {
	    if (!m_cfuncp) {	// Not in function, can't optimize
		clearOptimizable(nodep->varp(), "BVnofunc");
	    }
	    else {
		// If we're scoping down to it, it isn't really in the same block
		if (!nodep->hierThis()) clearOptimizable(nodep->varp(),"HierRef");
		// Allow a variable to appear in only a single function
		AstNode* oldfunc = nodep->varp()->user1p();
		if (!oldfunc) {
		    UINFO(4,"      BVnewref "<<nodep<<endl);
		    nodep->varp()->user1p(m_cfuncp); // Remember where it was used
		} else if (m_cfuncp == oldfunc) {
		    // Same usage
		} else {
		    // Used in multiple functions
		    clearOptimizable(nodep->varp(),"BVmultiF");
		}
		// First varref in function must be assignment found earlier
		AstVarRef* firstasn = (AstVarRef*)(nodep->varp()->user4p());
		if (firstasn && nodep!=firstasn) {
		    clearStdOptimizable(nodep->varp(),"notFirstAsn");
		    nodep->varp()->user4p(NULL);
		}
	    }
	}
	// No iterate; Don't want varrefs under it
    }
Example #6
0
    // VISITORS
    virtual void visit(AstNodeModule* nodep, AstNUser*) {
	m_stmtCnt = 0;
	m_modp = nodep;
	m_modp->user2(CIL_MAYBE);
	if (m_modp->castIface()) {
	    // Inlining an interface means we no longer have a cell handle to resolve to.
	    // If inlining moves post-scope this can perhaps be relaxed.
	    cantInline("modIface",true);
	}
	if (m_modp->modPublic()) cantInline("modPublic",false);
	//
	nodep->iterateChildren(*this);
	//
	bool userinline = nodep->user1();
	int allowed = nodep->user2();
	int refs = nodep->user3();
	// Should we automatically inline this module?
	// inlineMult = 2000 by default.  If a mod*#instances is < this # nodes, can inline it
	bool doit = ((allowed == CIL_NOTSOFT || allowed == CIL_MAYBE)
		     && (userinline
			 || ((allowed == CIL_MAYBE)
			     && (refs==1
				 || m_stmtCnt < INLINE_MODS_SMALLER
				 || v3Global.opt.inlineMult() < 1
				 || refs*m_stmtCnt < v3Global.opt.inlineMult()))));
	// Packages aren't really "under" anything so they confuse this algorithm
	if (nodep->castPackage()) doit = false;
	UINFO(4, " Inline="<<doit<<" Possible="<<allowed<<" Usr="******" Refs="<<refs<<" Stmts="<<m_stmtCnt
	      <<"  "<<nodep<<endl);
	nodep->user1(doit);
	m_modp = NULL;
    }
Example #7
0
    // VISITORS
    virtual void visit(AstAlways* nodep, AstNUser*) {
	UINFO(4,"   ALW   "<<nodep<<endl);
	if (debug()>=9) nodep->dumpTree(cout,"   alwIn:: ");
	scoreboardClear();
	processBlock(nodep->bodysp());
	if (debug()>=9) nodep->dumpTree(cout,"   alwOut: ");
    }
Example #8
0
void V3GenClk::genClkAll(AstNetlist* nodep) {
    UINFO(2,__FUNCTION__<<": "<<endl);
    {
        GenClkReadVisitor visitor (nodep);
    }  // Destruct before checking
    V3Global::dumpCheckGlobalTree("genclk", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
Example #9
0
void V3Localize::localizeAll(AstNetlist* nodep) {
    UINFO(2,__FUNCTION__<<": "<<endl);
    LocalizeVisitor visitor (nodep);
    // Fix up hiernames
    LocalizeDehierVisitor dvisitor (nodep);
    V3Global::dumpCheckGlobalTree("localize.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
Example #10
0
    virtual void visit(AstNodeStmt* nodep, AstNUser*) {
	uint32_t oldstate = m_state;
	// Find if children want to delete this or not.
	// Note children may bicker, and want to both keep and delete (branches on a if)
	uint32_t childstate;
	{
	    m_state = STATE_UNKNOWN;
	    nodep->iterateChildren(*this);
	    childstate = m_state;
	}
	m_state = oldstate;
	UINFO(9,"    Did state="<<childstate<<"  "<<nodep<<endl);

	// Indeterminate (statement with no lvalue), so keep only in original
	if (childstate == STATE_UNKNOWN) {
	    if (m_original) childstate |= STATE_KEEP;
	    else childstate |= STATE_DELETE;
	}

	if ((childstate & STATE_DELETE) && !(childstate & STATE_KEEP)) {
	    nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
	    // Pass upwards we did delete
	    m_state |= STATE_DELETE;
	} else {
	    // Pass upwards we must keep
	    m_state |= STATE_KEEP;
	}
    }
Example #11
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); nodep=NULL;
	    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(); lhsp=NULL;
		rhsp->deleteTree(); rhsp=NULL;
	    } else {
		if (nodep->castEqCase())
		newp = new AstEq (nodep->fileline(), lhsp, rhsp);
		else newp = new AstNeq (nodep->fileline(), lhsp, rhsp);
	    }
	    nodep->replaceWith(newp);
	    nodep->deleteTree(); nodep=NULL;
	    // Iterate tree now that we may have gotten rid of Xs
	    newp->iterateChildren(*this);
	}
    }
Example #12
0
    virtual void visit(AstNodeModule* nodep, AstNUser*) {
	UINFO(4," MOD   "<<nodep<<endl);
	m_modp = nodep;
	m_modNFuncs = 0;
	m_hashed.clear();
	// Compute hash of all statement trees in the function
	m_state = STATE_HASH;
	nodep->iterateChildren(*this);
	m_state = STATE_IDLE;
	if (debug()>=9) {
	    m_hashed.dumpFilePrefixed("combine");
	}
	// Walk the hashes removing empty functions
	if (emptyFunctionDeletion()) {
	    walkEmptyFuncs();
	}
	// Walk the hashes looking for duplicate functions
	if (duplicateFunctionCombine()) {
	    walkDupFuncs();
	}
	// Walk the statements looking for large replicated code sections
	if (statementCombine()) {
	    m_state = STATE_DUP;
	    nodep->iterateChildren(*this);
	    m_state = STATE_IDLE;
	}
	m_modp = NULL;
    }
Example #13
0
    virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
	// Track what scope it was originally under so V3LinkDot can resolve it
	string newname = m_cellp->name();
	if (nodep->inlinedDots() != "") { newname += "." + nodep->inlinedDots(); }
	nodep->inlinedDots(newname);
	UINFO(8,"   "<<nodep<<endl);
	nodep->iterateChildren(*this);
    }
    DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep=NULL) {
	DfaVertex* vertexp = new DfaVertex (graphp());
	vertexp->color(1);  // Mark as dfa
	if (nfaTemplatep && nfaTemplatep->start()) vertexp->start(true);
	if (nfaTemplatep && nfaTemplatep->accepting()) vertexp->accepting(true);
	UINFO(9, "        New "<<vertexp<<endl);
	return vertexp;
    }
    virtual void visit(AstCell* nodep, AstNUser*) {
	UINFO(4,"  CELL   "<<nodep<<endl);
	m_cellp = nodep;
	//VV*****  We reset user1p() on each cell!!!
	AstNode::user1ClearTree();
	nodep->iterateChildren(*this);
	m_cellp = NULL;
    }
Example #16
0
    // VISITORS
    bool cantUnroll(AstNode* nodep, const char* reason) {
	if (m_generate) {
	    nodep->v3error("Unsupported: Can't unroll generate for; "<<reason);
	}
	UINFO(3,"   Can't Unroll: "<<reason<<" :"<<nodep<<endl);
	V3Stats::addStatSum(string("Unrolling gave up, ")+reason, 1);
	return false;
    }
Example #17
0
    virtual void visit(AstCoverToggle* nodep, AstNUser*) {
	// Add to list of blocks under this scope
	UINFO(4,"    Move "<<nodep<<endl);
	AstNode* clonep = nodep->cloneTree(false);
	nodep->user2p(clonep);
	m_scopep->addActivep(clonep);
	clonep->iterateChildren(*this);	// We iterate under the *clone*
    }
Example #18
0
    virtual void visit(AstVarScope* nodep, AstNUser*) {
	if (nodep->isCircular()) {
	    UINFO(8,"  CIRC "<<nodep<<endl);
	    if (!nodep->user1SetOnce()) {
		genChangeDet(nodep);
	    }
	}
    }
Example #19
0
void V3Life::lifeAll(AstNetlist* nodep) {
    UINFO(2,__FUNCTION__<<": "<<endl);
    {
        LifeState state;
        LifeTopVisitor visitor (nodep, &state);
    }  // Destruct before checking
    V3Global::dumpCheckGlobalTree("life", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
Example #20
0
    virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
	// Copy under the scope but don't recurse
	UINFO(4,"    Move "<<nodep<<endl);
	AstNode* clonep = nodep->cloneTree(false);
	nodep->user2p(clonep);
	m_scopep->addActivep(clonep);
	clonep->iterateChildren(*this);	// We iterate under the *clone*
    }
Example #21
0
    virtual void visit(AstInitial* nodep, AstNUser*) {
	// Relink to IACTIVE, unless already under it
	UINFO(4,"    INITIAL "<<nodep<<endl);
	ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
	AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
	nodep->unlinkFrBack();
	wantactivep->addStmtsp(nodep);
    }
Example #22
0
    virtual void visit(AstActive* nodep) {
	UINFO(8,"ACTIVE "<<nodep<<endl);
	m_activep = nodep;
        if (!nodep->sensesp()) nodep->v3fatalSrc("Unlinked");
        iterateChildren(nodep->sensesp());  // iterateAndNext?
	m_activep = NULL;
        iterateChildren(nodep);
    }
Example #23
0
 // EmitSplitVisitor visits through always block *nodep
 // and generates its split blocks, writing the split blocks
 // into *newBlocksp.
 EmitSplitVisitor(AstAlways* nodep,
                  const IfColorVisitor* ifColorp,
                  AlwaysVec* newBlocksp)
     : m_origAlwaysp(nodep)
     , m_ifColorp(ifColorp)
     , m_newBlocksp(newBlocksp) {
     UINFO(6, "  splitting always " << nodep << endl);
 }
 void drivenBit (int bit, int width) {
     UINFO(9, "set d["<<(bit+width-1)<<":"<<bit<<"] "<<m_varp->name()<<endl);
     for (int i=0; i<width; i++) {
         if (bitNumOk(bit+i)) {
             m_flags[(bit+i)*FLAGS_PER_BIT + FLAG_DRIVEN] = true;
         }
     }
 }
    // METHODS
    virtual void visit(AstVarRef* nodep, AstNUser*) {
	if (nodep->lvalue()) {
	    if (nodep->varScopep()==m_splitVscp) {
		UINFO(6,"       CL VAR "<<nodep<<endl);
		m_matches = true;
	    }
	}
    }
    // METHODS
    void splitAlways(AstAlways* nodep) {
	UINFO(3,"Split  "<<nodep<<endl);
	UINFO(3,"   For "<<m_splitVscp<<endl);
	if (debug()>=9) nodep->dumpTree(cout,"-in  : ");
	// Duplicate it and link in
	AstAlways* newp = nodep->cloneTree(false);
	newp->user1(true);  // So we don't clone it again
	nodep->addNextHere(newp);
	{   // Delete stuff we don't want in old
	    SplitAsCleanVisitor visitor (nodep, m_splitVscp, false);
	    if (debug()>=9) nodep->dumpTree(cout,"-out0: ");
	}
	{   // Delete stuff we don't want in new
	    SplitAsCleanVisitor visitor (newp, m_splitVscp, true);
	    if (debug()>=9) newp->dumpTree(cout,"-out1: ");
	}
    }
Example #27
0
 //--------------------
 // Default
 virtual void visit(AstNode* nodep) {
     // **** SPECIAL default type that sets PLI_ORDERING
     if (!m_stmtStackps.empty() && !nodep->isPure()) {
         UINFO(9,"         NotSplittable "<<nodep<<endl);
         scoreboardPli(nodep);
     }
     iterateChildren(nodep);
 }
Example #28
0
    // VISITORS
    virtual void visit(AstScope* nodep, AstNUser*) {
	// Create required actives and add to scope
	UINFO(4," SCOPE   "<<nodep<<endl);
	// Clear last scope's names, and collect this scope's existing names
	m_namer.main(nodep);
	m_scopeFinalp = NULL;
	nodep->iterateChildren(*this);
    }
Example #29
0
 virtual void visit(AstNodeIf* nodep) {
     UINFO(4,"     IF "<<nodep<<endl);
     m_curIfConditional = nodep;
     iterateAndNextNull(nodep->condp());
     m_curIfConditional = NULL;
     scanBlock(nodep->ifsp());
     scanBlock(nodep->elsesp());
 }
Example #30
0
    virtual void visit(AstVarRef* nodep, AstNUser*) {
	if (!nodep->user2Inc()) {  // Not done yet
	    if (m_inDly && nodep->lvalue()) {
		UINFO(4,"AssignDlyVar: "<<nodep<<endl);
		markVarUsage(nodep->varScopep(), VU_DLY);
		if (!m_activep) nodep->v3fatalSrc("<= 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\n");
		AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
		if (dlyvscp) {  // Multiple use of delayed variable
		    AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
		    checkActivePost(nodep, oldactivep);
		}
		if (!dlyvscp) {  // First use of this delayed variable
		    string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
		    dlyvscp = createVarSc(oldvscp, newvarname, 0);
		    AstNodeAssign* prep
			= new AstAssignPre (nodep->fileline(),
					    new AstVarRef(nodep->fileline(), dlyvscp, true),
					    new AstVarRef(nodep->fileline(), oldvscp, false));
		    AstNodeAssign* postp
			= new AstAssignPost (nodep->fileline(),
					     new AstVarRef(nodep->fileline(), oldvscp, true),
					     new AstVarRef(nodep->fileline(), dlyvscp, false));
		    postp->lhsp()->user2(true);	// Don't detect this assignment
		    oldvscp->user1p(dlyvscp);  // So we can find it later
		    // Make new ACTIVE with identical sensitivity tree
		    AstActive* newactp = createActivePost(nodep);
		    dlyvscp->user2p(newactp);
		    newactp->addStmtsp(prep);	// Add to FRONT of statements
		    newactp->addStmtsp(postp);
		}
		AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
		newrefp->user2(true);  // No reason to do it again
		nodep->replaceWith(newrefp); nodep->deleteTree(); nodep=NULL;
	    }
	    else if (!m_inDly && nodep->lvalue()) {
		//UINFO(9,"NBA "<<nodep<<endl);
		if (!m_inInitial) {
		    UINFO(4,"AssignNDlyVar: "<<nodep<<endl);
		    markVarUsage(nodep->varScopep(), VU_NONDLY);
		}
	    }
	}
    }