Beispiel #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);
    }
Beispiel #2
0
    AstVar* getBlockTemp(AstNode* nodep) {
	string newvarname = ((string)"__Vtemp"+cvtToStr(m_modp->varNumGetInc()));
	AstVar* varp = new AstVar (nodep->fileline(), AstVarType::STMTTEMP, newvarname,
				   nodep->dtypep());
	m_funcp->addInitsp(varp);
	return varp;
    }
    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();
    }
Beispiel #4
0
    virtual void visit(AstFinal* nodep, AstNUser*) {
	// Relink to CFUNC for the final
	UINFO(4,"    FINAL "<<nodep<<endl);
	if (!nodep->bodysp()) { // Empty, Kill it.
	    nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
	    return;
	}
	ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
	if (!m_scopeFinalp) {
	    m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final_"+m_namer.scopep()->nameDotless(), m_namer.scopep());
	    m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
	    m_scopeFinalp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
	    m_scopeFinalp->dontCombine(true);
	    m_scopeFinalp->formCallTree(true);
	    m_scopeFinalp->slow(true);
	    m_namer.scopep()->addActivep(m_scopeFinalp);
	}
	nodep->unlinkFrBack();
	m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName()));
	m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
	nodep->deleteTree(); VL_DANGLING(nodep);
    }
Beispiel #5
0
    void makePublicFuncWrappers() {
	// We recorded all public functions in m_modFuncs.
	// If for any given name only one function exists, we can use that function directly.
	// If multiple functions exist, we need to select the appropriate scope.
	for (FuncMmap::iterator it = m_modFuncs.begin(); it!=m_modFuncs.end(); ++it) {
	    string name = it->first;
	    AstCFunc* topFuncp = it->second;
	    FuncMmap::iterator nextIt1 = it; ++nextIt1;
	    bool moreOfSame1 =  (nextIt1!=m_modFuncs.end() && nextIt1->first == name);
	    if (moreOfSame1) {
		// Multiple functions under this name, need a wrapper function
		UINFO(6,"  Wrapping "<<name<<" multifuncs\n");
		AstCFunc* newfuncp = topFuncp->cloneTree(false);
		if (newfuncp->initsp())  newfuncp->initsp()->unlinkFrBackWithNext()->deleteTree();
		if (newfuncp->stmtsp())  newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree();
		if (newfuncp->finalsp()) newfuncp->finalsp()->unlinkFrBackWithNext()->deleteTree();
		newfuncp->name(name);
		newfuncp->isStatic(false);
		newfuncp->addInitsp(
		    new AstCStmt(newfuncp->fileline(),
				 EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
		newfuncp->addInitsp(new AstCStmt(newfuncp->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
		topFuncp->addNextHere(newfuncp);
		// In the body, call each function if it matches the given scope
		for (FuncMmap::iterator eachIt = it; eachIt!=m_modFuncs.end() && eachIt->first==name; ++eachIt) {
		    it = eachIt;
		    AstCFunc* funcp = eachIt->second;
		    FuncMmap::iterator nextIt2 = eachIt; ++nextIt2;
		    bool moreOfSame =  (nextIt2!=m_modFuncs.end() && nextIt2->first == name);
		    if (!funcp->scopep()) funcp->v3fatalSrc("Not scoped");

		    UINFO(6,"     Wrapping "<<name<<" "<<funcp<<endl);
		    UINFO(6,"  at "<<newfuncp->argTypes()<<" und "<<funcp->argTypes()<<endl);
		    funcp->declPrivate(true);
		    AstNode* argsp = NULL;
		    for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
			if (AstVar* portp = stmtp->castVar()) {
			    if (portp->isIO() && !portp->isFuncReturn()) {
				argsp = argsp->addNextNull(new AstVarRef(portp->fileline(), portp,
									 portp->isOutput()));
			    }
			}
		    }

		    AstNode* returnp = new AstCReturn (funcp->fileline(),
						       new AstCCall (funcp->fileline(),
								     funcp,
								     argsp));

		    if (moreOfSame) {
			AstIf* ifp = new AstIf (funcp->fileline(),
						new AstEq(funcp->fileline(),
							  new AstCMath(funcp->fileline(),
								       "this", 64),
							  new AstCMath(funcp->fileline(),
								       string("&(")
								       +funcp->scopep()->nameVlSym()
								       +")", 64)),
						returnp, NULL);
			newfuncp->addStmtsp(ifp);
		    } else {
			newfuncp->addStmtsp(returnp);
		    }
		}
		// Not really any way the user could do this, and we'd need to come up with some return value
		//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DT_DISPLAY,
		//				      string("%%Error: ")+name+"() called with bad scope", NULL));
		//newfuncp->addStmtsp(new AstStop (newfuncp->fileline()));
		if (debug()>=9) newfuncp->dumpTree(cout,"   newfunc: ");
	    } else {
		// Only a single function under this name, we can simply rename it
		UINFO(6,"  Wrapping "<<name<<" just one "<<topFuncp<<endl);
		topFuncp->name(name);
	    }
	}
    }
Beispiel #6
0
    // VISITORS
    virtual void visit(AstTopScope* nodep) {
	UINFO(4," TOPSCOPE   "<<nodep<<endl);
	m_topScopep=nodep;
	m_scopep = nodep->scopep();
	if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
	//VV*****  We reset all user1p()
	AstNode::user1ClearTree();
	// Make top functions
	{
	    AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
	    funcp->argTypes(EmitCBaseVisitor::symClassVar());
	    funcp->dontCombine(true);
	    funcp->symProlog(true);
	    funcp->isStatic(true);
	    funcp->entryPoint(true);
	    m_scopep->addActivep(funcp);
	    m_evalFuncp = funcp;
	}
	{
	    AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
	    funcp->argTypes(EmitCBaseVisitor::symClassVar());
	    funcp->dontCombine(true);
	    funcp->slow(true);
	    funcp->symProlog(true);
	    funcp->isStatic(true);
	    funcp->entryPoint(true);
	    m_scopep->addActivep(funcp);
	    m_initFuncp = funcp;
	}
	{
	    AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
	    funcp->skipDecl(true);
	    funcp->dontCombine(true);
	    funcp->slow(true);
	    funcp->isStatic(false);
	    funcp->entryPoint(true);
	    funcp->addInitsp(new AstCStmt(nodep->fileline(),
					  EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
	    funcp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
	    m_scopep->addActivep(funcp);
	    m_finalFuncp = funcp;
	}
	{
	    AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
	    funcp->argTypes(EmitCBaseVisitor::symClassVar());
	    funcp->dontCombine(true);
	    funcp->slow(true);
	    funcp->isStatic(true);
	    funcp->symProlog(true);
	    funcp->entryPoint(true);
	    m_scopep->addActivep(funcp);
	    m_settleFuncp = funcp;
	}
	// Process the activates
        iterateChildren(nodep);
	// Done, clear so we can detect errors
	UINFO(4," TOPSCOPEDONE "<<nodep<<endl);
	clearLastSen();
	m_topScopep=NULL;
	m_scopep = NULL;
    }