コード例 #1
0
    virtual void visit(AstUdpTable* nodep, AstNUser*) {
	UINFO(5,"UDPTABLE  "<<nodep<<endl);
	if (!v3Global.opt.bboxUnsup()) {
	    // We don't warn until V3Inst, so that UDPs that are in libraries and
	    // never used won't result in any warnings.
	} else {
	    // Massive hack, just tie off all outputs so our analysis can proceed
	    AstVar* varoutp = NULL;
	    for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
		if (AstVar* varp = stmtp->castVar()) {
		    if (varp->isInput()) {
		    } else if (varp->isOutput()) {
			if (varoutp) { varp->v3error("Multiple outputs not allowed in udp modules"); }
			varoutp = varp;
			// Tie off
			m_modp->addStmtp(new AstAssignW(varp->fileline(),
							new AstVarRef(varp->fileline(), varp, true),
							new AstConst(varp->fileline(), AstConst::LogicFalse())));
		    } else {
			varp->v3error("Only inputs and outputs are allowed in udp modules");
		    }
		}
	    }
	    nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
	}
    }
コード例 #2
0
ファイル: V3Combine.cpp プロジェクト: RCSL-HKUST/heterosim
    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
	    }
	}
    }
コード例 #3
0
ファイル: V3Unroll.cpp プロジェクト: jeras/verilator
 bool canSimulate(AstNode *nodep) {
     SimulateVisitor simvis;
     AstNode* clonep = nodep->cloneTree(true);
     simvis.mainCheckTree(clonep);
     pushDeletep(clonep); clonep = NULL;
     return simvis.optimizable();
 }
コード例 #4
0
ファイル: V3Param.cpp プロジェクト: kkudrolli/Team-SDK-545
    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);
    }
コード例 #5
0
ファイル: V3Delayed.cpp プロジェクト: torc-isi/torc
    void checkActivePost(AstVarRef* varrefp, AstActive* oldactivep) {
	// Check for MULTIDRIVEN, and if so make new sentree that joins old & new sentree
	if (!oldactivep) varrefp->v3fatalSrc("<= old dly assignment not put under sensitivity block");
	if (oldactivep->sensesp() != m_activep->sensesp()) {
	    if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
		&& !varrefp->varp()->user2()) {
		varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName());
		varrefp->v3warn(MULTIDRIVEN,"... Location of first driving block");
		oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
		varrefp->varp()->user2(true);
	    }
	    UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
	    UINFO(4,"  Act: "<<m_activep<<endl);
	    UINFO(4,"  Act: "<<oldactivep<<endl);
	    // Make a new sensitivity list, which is the combination of both blocks
	    AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
	    AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
	    AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
	    if (senb) treep->addSensesp(senb);
	    if (AstSenTree* storep = oldactivep->sensesStorep()) {
		storep->unlinkFrBack();
		pushDeletep(storep);
	    }
	    oldactivep->sensesStorep(treep);
	    oldactivep->sensesp(treep);
	}
    }
コード例 #6
0
ファイル: V3Unroll.cpp プロジェクト: phb/verilator-asserts
    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
	    }
	}
    }
コード例 #7
0
ファイル: V3Unroll.cpp プロジェクト: phb/verilator-asserts
    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");
	    }
	}
    }
コード例 #8
0
    // VISITORS
    virtual void visit(AstCell* nodep, AstNUser*) {
	if (nodep->rangep()) {
	    m_cellRangep = nodep->rangep();
	    UINFO(4,"  CELL   "<<nodep<<endl);
	    // Make all of the required clones
	    m_instLsb = m_cellRangep->lsbConst();
	    for (m_instNum = m_instLsb; m_instNum<=m_cellRangep->msbConst(); m_instNum++) {
		AstCell* newp = nodep->cloneTree(false);
		nodep->addNextHere(newp);
		// Remove ranging and fix name
		newp->rangep()->unlinkFrBack()->deleteTree();
		// Somewhat illogically, we need to rename the orignal name of the cell too.
		// as that is the name users expect for dotting
		// The spec says we add [x], but that won't work in C...
		newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
		newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
		// Fixup pins
		newp->pinsp()->iterateAndNext(*this);
		if (debug()==9) { newp->dumpTree(cout,"newcell: "); cout<<endl; }
	    }

	    // Done.  Delete original
	    m_cellRangep=NULL;
	    nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
	}
    }
コード例 #9
0
    // VISITORS  //========== Statements
    virtual void visit(AstPslDefClock* nodep, AstNUser*) {
	nodep->iterateChildren(*this);
	// Store the new default clock, reset on new module
	m_seniDefaultp = nodep->sensesp();
	// Trash it
	nodep->unlinkFrBack();
	pushDeletep(nodep); nodep=NULL;
    }
コード例 #10
0
ファイル: V3WidthSel.cpp プロジェクト: phb/verilator-asserts
    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);
	}
    }
コード例 #11
0
ファイル: V3Combine.cpp プロジェクト: RCSL-HKUST/heterosim
    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);
    }
コード例 #12
0
ファイル: V3LinkJump.cpp プロジェクト: RCSL-HKUST/heterosim
    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);
    }
コード例 #13
0
    virtual void visit(AstIf* nodep, AstNUser*) {
	if (nodep->user1SetOnce()) return;
	if (nodep->uniquePragma() || nodep->unique0Pragma()) {
	    AstNodeIf* ifp = nodep;
	    AstNode* propp = NULL;
	    bool hasDefaultElse = false;
	    do {
		// If this statement ends with 'else if', then nextIf will point to the
		// nextIf statement.  Otherwise it will be null.
		AstNodeIf* nextifp = dynamic_cast<AstNodeIf*>(ifp->elsesp());
		ifp->condp()->iterateAndNext(*this);

		// Recurse into the true case.
		ifp->ifsp()->iterateAndNext(*this);
		
		// If the last else is not an else if, recurse into that too.
		if (ifp->elsesp() && !nextifp) {
		    ifp->elsesp()->iterateAndNext(*this);
		}
		
		// Build a bitmask of the true predicates
	        AstNode* predp = ifp->condp()->cloneTree(false);
	        if (propp) {
		    propp = new AstConcat(nodep->fileline(), predp, propp);
		} else {
		    propp = predp;
		}

		// Record if this ends with an 'else' that does not have an if
		if (ifp->elsesp() && !nextifp) {
		    hasDefaultElse = true;
		}
		
		ifp = nextifp;
	    } while (ifp);

	    AstNode *newifp = nodep->cloneTree(false);
	    bool allow_none = nodep->unique0Pragma();
	    
	    // Note: if this ends with an 'else', then we don't need to validate that one of the
	    // predicates evaluates to true.
	    AstNode* ohot = ((allow_none || hasDefaultElse)
			     ? (new AstOneHot0(nodep->fileline(), propp))->castNode()
			     : (new AstOneHot (nodep->fileline(), propp))->castNode());
	    AstIf* checkifp = new AstIf (nodep->fileline(),
					 new AstLogNot (nodep->fileline(), ohot),
					 newFireAssert(nodep, "'unique if' statement violated"),
					 newifp);
	    checkifp->branchPred(AstBranchPred::BP_UNLIKELY);
	    nodep->replaceWith(checkifp);
	    pushDeletep(nodep);
	} else {
	    nodep->iterateChildren(*this);
	}
    }
コード例 #14
0
ファイル: V3LinkJump.cpp プロジェクト: RCSL-HKUST/heterosim
    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);
    }
コード例 #15
0
    virtual void visit(AstPragma* nodep, AstNUser*) {
	if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) {
	    if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module\n");
	    m_modp->modPublic(true);
	    nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
	}
	else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) {
	    if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task\n");
	    m_ftaskp->taskPublic(true);
	    m_modp->modPublic(true);  // Need to get to the task...
	    nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
	}
	else if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
	    if (!v3Global.opt.coverageLine()) {  // No need for block statements; may optimize better without
		nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
	    }
	}
	else {
	    nodep->iterateChildren(*this);
	}
    }
コード例 #16
0
    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); nodep=NULL;
    }
コード例 #17
0
ファイル: V3Combine.cpp プロジェクト: RCSL-HKUST/heterosim
    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);
    }
コード例 #18
0
    virtual void visit(AstBegin* nodep, AstNUser*) {
	// Begin blocks were only useful in variable creation, change names and delete
	UINFO(8,"  "<<nodep<<endl);
	string oldScope = m_namedScope;
	string oldUnnamed = m_unnamedScope;
	{
	    UINFO(8,"nname "<<m_namedScope<<endl);
	    if (nodep->name() != "") {  // Else unneeded unnamed block
		// Create data for dotted variable resolution
		string dottedname = nodep->name() + "__DOT__";  // So always found
		string::size_type pos;
		while ((pos=dottedname.find("__DOT__")) != string::npos) {
		    string ident = dottedname.substr(0,pos);
		    dottedname = dottedname.substr(pos+strlen("__DOT__"));
		    if (!nodep->unnamed()) {
			if (m_namedScope=="") m_namedScope = ident;
			else m_namedScope = m_namedScope + "__DOT__"+ident;
		    }
		    if (m_unnamedScope=="") m_unnamedScope = ident;
		    else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
		    // Create CellInline for dotted var resolution
		    if (!m_ftaskp) {
			AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
								   m_unnamedScope, "__BEGIN__");
			m_modp->addInlinesp(inlinep);  // Must be parsed before any AstCells
		    }
		}
	    }

	    // Remap var names and replace lower Begins
	    nodep->stmtsp()->iterateAndNext(*this);
	    if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier");
	}
	m_namedScope = oldScope;
	m_unnamedScope = oldUnnamed;

	// Cleanup
	AstNode* addsp = NULL;
	if (AstNode* stmtsp = nodep->stmtsp()) {
	    stmtsp->unlinkFrBackWithNext();
	    if (addsp) { addsp = addsp->addNextNull(stmtsp); } else { addsp = stmtsp; }
	}
	if (addsp) {
	    nodep->replaceWith(addsp);
	} else {
	    nodep->unlinkFrBack();
	}
	pushDeletep(nodep); nodep=NULL;
    }
コード例 #19
0
    void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep,
			 AstNode* stmtsp, const string& message) {
	propp->unlinkFrBack();
	sentreep->unlinkFrBack();
	if (stmtsp) stmtsp->unlinkFrBack();
	//
	AstNode* bodysp = NULL;
	bool selfDestruct = false;
	if (AstPslCover* snodep = nodep->castPslCover()) {
	    if (!v3Global.opt.coverageUser()) {
		selfDestruct = true;
	    } else {
		// V3Coverage assigned us a bucket to increment.
		AstCoverInc* covincp = snodep->coverincp()->castCoverInc();
		if (!covincp) snodep->v3fatalSrc("Missing AstCoverInc under assertion");
		covincp->unlinkFrBack();
		if (message!="") covincp->declp()->comment(message);
		bodysp = covincp;
	    }
	} else if (nodep->castPslAssert()) {
	    bodysp = newFireAssert(nodep,message);
	    // We assert the property is always true... so report when it fails
	    // (Note this is opposite the behavior of coverage statements.)
	    // Need: 'never' operator: not hold in current or any future cycle
	    propp = new AstLogNot (nodep->fileline(), propp);
	} else {
	    nodep->v3fatalSrc("Unknown node type");
	}
	if (stmtsp) bodysp = bodysp->addNext(stmtsp);
	AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
	bodysp = ifp;
	if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
	//
	AstNode* newp = new AstAlways (nodep->fileline(),
				       VAlwaysKwd::ALWAYS,
				       sentreep,
				       bodysp);
	// Install it
	if (selfDestruct) {
	    // Delete it after making the tree.  This way we can tell the user
	    // if it wasn't constructed nicely or has other errors without needing --coverage.
	    newp->deleteTree();
	    nodep->unlinkFrBack();
	} else {
	    nodep->replaceWith(newp);
	}
	// Bye
	pushDeletep(nodep); nodep=NULL;
    }
コード例 #20
0
ファイル: V3Combine.cpp プロジェクト: RCSL-HKUST/heterosim
    void walkEmptyFuncs() {
	for (V3Hashed::iterator it = m_hashed.begin(); it != m_hashed.end(); ++it) {
	    AstNode* node1p = it->second;
	    AstCFunc* oldfuncp = node1p->castCFunc();
	    if (oldfuncp
		&& oldfuncp->emptyBody()
		&& !oldfuncp->dontCombine()) {
		UINFO(5,"     EmptyFunc "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
		// Mark user3p on entire old tree, so we don't process it more
		CombMarkVisitor visitor(oldfuncp);
		m_call.replaceFunc(oldfuncp, NULL);
		oldfuncp->unlinkFrBack();
		pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
	    }
	}
    }
コード例 #21
0
ファイル: V3GenClk.cpp プロジェクト: jeras/verilator
    //----
    virtual void visit(AstVarRef* nodep) {
	// Consumption/generation of a variable,
	AstVarScope* vscp = nodep->varScopep();
	if (!vscp) nodep->v3fatalSrc("Scope not assigned");
	if (m_activep && !nodep->user3()) {
	    nodep->user3(true);
	    if (vscp->isCircular()) {
		UINFO(8,"  VarActReplace "<<nodep<<endl);
		// Replace with the new variable
		AstVarScope* newvscp = genInpClk(vscp);
		AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue());
		nodep->replaceWith(newrefp);
		pushDeletep(nodep); VL_DANGLING(nodep);
	    }
	}
    }
コード例 #22
0
ファイル: V3Unroll.cpp プロジェクト: phb/verilator-asserts
    virtual void visit(AstVarRef* nodep, AstNUser*) {
	if (m_varModeCheck
	    && nodep->varp() == m_forVarp
	    && nodep->varScopep() == m_forVscp
	    && nodep->lvalue()) {
	    UINFO(8,"   Itervar assigned to: "<<nodep<<endl);
	    m_varAssignHit = true;
	}

	if (m_varModeReplace
	    && nodep->varp() == m_forVarp
	    && nodep->varScopep() == m_forVscp
	    && !nodep->lvalue()) {
	    AstNode* newconstp = m_varValuep->cloneTree(false);
	    nodep->replaceWith(newconstp);
	    pushDeletep(nodep);
	}
    }
コード例 #23
0
    virtual void visit(AstPslClocked* nodep, AstNUser*) {
	nodep->iterateChildren(*this);
	if (m_senip) {
	    nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
	}
	// Block is the new expression to evaluate
	AstNode* blockp = nodep->propp()->unlinkFrBack();
	if (nodep->disablep()) {
	    blockp = new AstAnd(nodep->disablep()->fileline(),
				new AstNot(nodep->disablep()->fileline(),
					   nodep->disablep()->unlinkFrBack()),
				blockp);
	}
	// Unlink and just keep a pointer to it, convert to sentree as needed
	m_senip = nodep->sensesp();
	nodep->replaceWith(blockp);
	pushDeletep(nodep); nodep=NULL;
    }
コード例 #24
0
    // METHODS
    void readModNames() {
	// Look at all modules, and store pointers to all module names
	for (AstNodeModule* nextp,* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nextp) {
	    nextp = nodep->nextp()->castNodeModule();
	    AstNode* foundp = m_mods.rootp()->findIdFallback(nodep->name())->nodep();
	    if (foundp && foundp != nodep) {
		if (!(foundp->fileline()->warnIsOff(V3ErrorCode::MODDUP) || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP))) {
		    nodep->v3warn(MODDUP,"Duplicate declaration of module: "<<nodep->prettyName()<<endl
				  <<foundp->warnMore()<<"... Location of original declaration");
		}
		nodep->unlinkFrBack();
		pushDeletep(nodep); nodep=NULL;
	    } else if (!foundp) {
		m_mods.rootp()->insert(nodep->name(), new VSymEnt(&m_mods, nodep));
	    }
	}
	//if (debug()>=9) m_mods.dump(cout, "-syms: ");
    }
コード例 #25
0
ファイル: V3LinkJump.cpp プロジェクト: RCSL-HKUST/heterosim
    virtual void visit(AstReturn* nodep, AstNUser*) {
	nodep->iterateChildren(*this);
	AstFunc* funcp = m_ftaskp->castFunc();
	if (!m_ftaskp) { nodep->v3error("Return isn't underneath a task or function"); }
	else if (funcp  && !nodep->lhsp()) { nodep->v3error("Return underneath a function should have return value"); }
	else if (!funcp &&  nodep->lhsp()) { nodep->v3error("Return underneath a task shouldn't have return value"); }
	else {
	    if (funcp && nodep->lhsp()) {
		// Set output variable to return value
		nodep->addPrev(new AstAssign(nodep->fileline(),
					     new AstVarRef(nodep->fileline(), funcp->fvarp()->castVar(), true),
					     nodep->lhsp()->unlinkFrBackWithNext()));
	    }
	    // Jump to the end of the function call
	    AstJumpLabel* labelp = findAddLabel(m_ftaskp, false);
	    nodep->addPrev(new AstJumpGo(nodep->fileline(), labelp));
	}
	nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
    }
コード例 #26
0
ファイル: V3ActiveTop.cpp プロジェクト: RCSL-HKUST/heterosim
    virtual void visit(AstActive* nodep, AstNUser*) {
	UINFO(4,"   ACTIVE "<<nodep<<endl);
	V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
	AstSenTree* sensesp = nodep->sensesp();
	if (!sensesp) nodep->v3fatalSrc("NULL");
	if (sensesp->sensesp()
	    && sensesp->sensesp()->castSenItem()
	    && sensesp->sensesp()->castSenItem()->isNever()) {
	    // Never executing.  Kill it.
	    if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
	    nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
	    return;
	}
	// Copy combo tree to settlement tree with duplicated statements
	if (sensesp->hasCombo()) {
	    AstSenTree* newsentreep
		= new AstSenTree (nodep->fileline(),
				  new AstSenItem (nodep->fileline(), AstSenItem::Settle()));
	    AstActive* newp = new AstActive(nodep->fileline(),"settle", newsentreep);
	    newp->sensesStorep(newsentreep);
	    if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->cloneTree(true));
	    nodep->addNextHere(newp);
	}
	// Move the SENTREE for each active up to the global level.
	// This way we'll easily see what clock domains are identical
	AstSenTree* wantp = m_finder.getSenTree(nodep->fileline(), sensesp);
	UINFO(4,"   lookdone\n");
	if (wantp != sensesp) {
	    // Move the active's contents to the other active
	    UINFO(4,"   merge active "<<sensesp<<" into "<<wantp<<endl);
	    if (nodep->sensesStorep()) {
		if (sensesp != nodep->sensesStorep()) nodep->v3fatalSrc("sensesStore should have been deleted earlier if different\n");
		sensesp->unlinkFrBack();
		// There may be other references to same sense tree,
		// we'll be removing all references when we get to them,
		// but don't dangle our pointer yet!
		pushDeletep(sensesp);
	    }
	    nodep->sensesp(wantp);
	}
	// No need to do statements under it, they're already moved.
	//nodep->iterateChildren(*this);
    }
コード例 #27
0
    virtual void visit(AstBind* nodep, AstNUser*) {
	// Bind: Has cells underneath that need to be put into the new module, and cells which need resolution
	// TODO this doesn't allow bind to dotted hier names, that would require
	// this move to post param, which would mean we do not auto-read modules
	// and means we cannot compute module levels until later.
	UINFO(4,"Link Bind: "<<nodep<<endl);
	AstNodeModule* modp = resolveModule(nodep,nodep->name());
	if (modp) {
	    AstNode* cellsp = nodep->cellsp()->unlinkFrBackWithNext();
	    // Module may have already linked, so need to pick up these new cells
	    AstNodeModule* oldModp = m_modp;
	    {
		m_modp = modp;
		modp->addStmtp(cellsp);  // Important that this adds to end, as next iterate assumes does all cells
		cellsp->iterateAndNext(*this);
	    }
	    m_modp = oldModp;
	}
	pushDeletep(nodep->unlinkFrBack());
    }
コード例 #28
0
ファイル: V3Unroll.cpp プロジェクト: phb/verilator-asserts
    bool simulateTree(AstNode *nodep, const V3Number *loopValue, AstNode *dtypep, V3Number &outNum) {
	AstNode* clone = nodep->cloneTree(true);
	if (!clone) {
	    nodep->v3fatalSrc("Failed to clone tree");
	    return false;
	}
	if (loopValue) {
	    m_varValuep = new AstConst (nodep->fileline(), *loopValue);
	    // Iteration requires a back, so put under temporary node
	    AstBegin* tempp = new AstBegin (nodep->fileline(), "[EditWrapper]", clone);
	    m_varModeReplace = true;
	    tempp->stmtsp()->iterateAndNext(*this);
	    m_varModeReplace = false;
	    clone = tempp->stmtsp()->unlinkFrBackWithNext();
	    tempp->deleteTree();
	    tempp = NULL;
	    pushDeletep(m_varValuep); m_varValuep = NULL;
	}
	SimulateVisitor simvis;
	simvis.mainParamEmulate(clone);
	if (!simvis.optimizable()) {
	    UINFO(3, "Unable to simulate" << endl);
	    if (debug()>=9) nodep->dumpTree(cout,"- _simtree: ");
	    return false;
	}
	// Fetch the result
	V3Number* res = simvis.fetchNumberNull(clone);
	if (!res) {
	    UINFO(3, "No number returned from simulation" << endl);
	    return false;
	}
	// Patch up datatype
	if (dtypep) {
	    AstConst new_con (clone->fileline(), *res);
	    new_con.dtypeFrom(dtypep);
	    outNum = new_con.num();
	    return true;
	}
	outNum = *res;
	return true;
    }
コード例 #29
0
    void detectDuplicates() {
	UINFO(9,"Finding duplicates\n");
	// Note uses user4
	V3Hashed  hashed;	// Duplicate code detection
	// Hash all of the original signals we toggle cover
	for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
	    AstCoverToggle* nodep = *it;
	    hashed.hashAndInsert(nodep->origp());
	}
	// Find if there are any duplicates
	for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
	    AstCoverToggle* nodep = *it;
	    if (nodep->backp()) {   // nodep->backp() is null if we already detected it's a duplicate and unlinked it
		// Want to choose a base node, and keep finding duplicates that are identical
		// This prevents making chains where a->b, then c->d, then b->c, as we'll find a->b, a->c, a->d directly.
		while (1) {
		    V3Hashed::iterator dupit = hashed.findDuplicate(nodep->origp());
		    if (dupit == hashed.end()) break;
		    //
		    AstNode* duporigp = hashed.iteratorNodep(dupit);
		    // Note hashed will point to the original variable (what's duplicated), not the covertoggle,
		    // but we need to get back to the covertoggle which is immediately above, so:
		    AstCoverToggle* removep = duporigp->backp()->castCoverToggle();
		    if (!removep) nodep->v3fatalSrc("CoverageJoin duplicate of wrong type");
		    UINFO(8,"  Orig "<<nodep<<" -->> "<<nodep->incp()->declp()<<endl);
		    UINFO(8,"   dup "<<removep<<" -->> "<<removep->incp()->declp()<<endl);
		    // The CoverDecl the duplicate pointed to now needs to point to the original's data
		    // IE the duplicate will get the coverage number from the non-duplicate
		    AstCoverDecl* datadeclp = nodep->incp()->declp()->dataDeclThisp();
		    removep->incp()->declp()->dataDeclp (datadeclp);
		    UINFO(8,"   new "<<removep->incp()->declp()<<endl);
		    // Mark the found node as a duplicate of the first node
		    // (Not vice-versa as we have the iterator for the found node)
		    removep->unlinkFrBack();  pushDeletep(removep); removep=NULL;
		    // Remove node from comparison so don't hit it again
		    hashed.erase(dupit);
		    ++m_statToggleJoins;
		}
	    }
	}
    }
コード例 #30
0
ファイル: V3Assert.cpp プロジェクト: torc-isi/torc
    void newVAssertion(AstVAssert* nodep, AstNode* propp) {
	propp->unlinkFrBackWithNext();
	AstNode* passsp = nodep->passsp(); if (passsp) passsp->unlinkFrBackWithNext();
	AstNode* failsp = nodep->failsp(); if (failsp) failsp->unlinkFrBackWithNext();
	//
	if (nodep->castVAssert()) {
	    if (passsp) passsp = newIfAssertOn(passsp);
	    if (failsp) failsp = newIfAssertOn(failsp);
	} else {
	    nodep->v3fatalSrc("Unknown node type");
	}

	AstIf* ifp = new AstIf (nodep->fileline(), propp, passsp, failsp);
	AstNode* newp = ifp;
	if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
	//
	// Install it
	nodep->replaceWith(newp);
	// Bye
	pushDeletep(nodep); nodep=NULL;
    }