Exemple #1
0
    virtual void visit(AstVarScope* nodep, AstNUser*) {
	nodep->iterateChildren(*this);
	// Avoid updating this if (), instead see varp->isTrace()
	if (!nodep->varp()->isTemp() && !nodep->varp()->isFuncLocal()) {
	    UINFO(5, "    vsc "<<nodep<<endl);
	    AstVar* varp = nodep->varp();
	    AstScope* scopep = nodep->scopep();
	    // Compute show name
	    // This code assumes SPTRACEVCDC_VERSION >= 1330;
	    // it uses spaces to separate hierarchy components.
	    m_traShowname = AstNode::vcdName(scopep->name() + " " + varp->name());
	    if (m_traShowname.substr(0,4) == "TOP ") m_traShowname.replace(0,4,"");
	    if (!m_initSubFuncp) nodep->v3fatalSrc("NULL");

	    m_traVscp = nodep;
	    m_traValuep = NULL;
	    if (varIgnoreTrace(varp)) {
		addIgnore(varIgnoreTrace(varp));
	    } else {
		++m_statSigs;
		if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true);
		else m_traValuep = new AstVarRef(nodep->fileline(), nodep, false);
		{
		    // Recurse into data type of the signal; the visitors will call addTraceDecl()
		    varp->dtypeSkipRefp()->accept(*this);
		}
		// Cleanup
		if (m_traValuep) { m_traValuep->deleteTree(); m_traValuep=NULL; }
	    }
	    m_traVscp = NULL;
	    m_traValuep = NULL;
	    m_traShowname = "";
	}
    }
Exemple #2
0
    virtual void visit(AstScopeName* nodep, AstNUser*) {
	// If there's a %m in the display text, we add a special node that will contain the name()
	string prefix = (string)("__DOT__")+m_scopep->name();
	// TOP and above will be the user's name().
	// Note 'TOP.' is stripped by scopePrettyName
	// To keep correct visual order, must add before other Text's
	AstNode* afterp = nodep->scopeAttrp();
	if (afterp) afterp->unlinkFrBackWithNext();
	nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
	if (afterp) nodep->scopeAttrp(afterp);
	nodep->iterateChildren(*this);
    }
    void varsExpand() {
	// We didn'e have all m_scopes loaded when we encountered variables, so expand them now
	// It would be less code if each module inserted its own variables.
	// Someday.  For now public isn't common.
	for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
	    AstScope* scopep = it->first;  AstNodeModule* smodp = it->second;
	    for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
		AstNodeModule* modp = it->first;
		AstVar* varp = it->second;
		if (modp == smodp) {
		    // Need to split the module + var name into the original-ish full scope and variable name under that scope.
		    // The module instance name is included later, when we know the scopes this module is under
		    string whole = scopep->name()+"__DOT__"+varp->name();
		    string scpName;
		    string varBase;
		    if (whole.substr(0,10) == "__DOT__TOP") whole.replace(0,10,"");
		    string::size_type pos = whole.rfind("__DOT__");
		    if (pos != string::npos) {
			scpName = whole.substr(0,pos);
			varBase = whole.substr(pos+strlen("__DOT__"));
		    } else {
			varBase = whole;
		    }
		    //UINFO(9,"For "<<scopep->name()<<" - "<<varp->name()<<"  Scp "<<scpName<<"  Var "<<varBase<<endl);
		    string varBasePretty = AstNode::prettyName(varBase);
		    string scpPretty = AstNode::prettyName(scpName);
		    string scpSym;
		    {
			string out = scpName;
			string::size_type pos;
			while ((pos=out.find("__PVT__")) != string::npos) {
			    out.replace(pos, 7, "");
			}
			if (out.substr(0,10) == "TOP__DOT__") out.replace(0,10,"");
			if (out.substr(0,4) == "TOP.") out.replace(0,4,"");
			while ((pos=out.find(".")) != string::npos) {
			    out.replace(pos, 1, "__");
			}
			while ((pos=out.find("__DOT__")) != string::npos) {
			    out.replace(pos, 7, "__");
			}
			scpSym = out;
		    }
		    //UINFO(9," scnameins sp "<<scpName<<" sp "<<scpPretty<<" ss "<<scpSym<<endl);
		    if (m_scopeNames.find(scpSym) == m_scopeNames.end()) {
			m_scopeNames.insert(make_pair(scpSym, ScopeNameData(scpSym, scpPretty)));
		    }
		    m_scopeVars.insert(make_pair(scpSym + " " + varp->name(),
						 ScopeVarData(scpSym, varBasePretty, varp, modp, scopep)));
		}
	    }
	}
    }
Exemple #4
0
    virtual void visit(AstNodeModule* nodep, AstNUser*) {
	// Create required blocks and add to module
	string scopename;
	if (!m_aboveScopep) scopename = "TOP";
	else scopename = m_aboveScopep->name()+"."+m_aboveCellp->name();

	UINFO(4," MOD AT "<<scopename<<"  "<<nodep<<endl);
        AstNode::user1ClearTree();

	m_scopep = new AstScope((m_aboveCellp?(AstNode*)m_aboveCellp:(AstNode*)nodep)->fileline(),
				nodep, scopename, m_aboveScopep, m_aboveCellp);

	// Now for each child cell, iterate the module this cell points to
	for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp=cellnextp->nextp()) {
	    if (AstCell* cellp = cellnextp->castCell()) {
		AstScope* oldScopep = m_scopep;
		AstCell* oldAbCellp = m_aboveCellp;
		AstScope* oldAbScopep = m_aboveScopep;
		{
		    m_aboveCellp = cellp;
		    m_aboveScopep = m_scopep;
		    AstNodeModule* modp = cellp->modp();
		    if (!modp) cellp->v3fatalSrc("Unlinked mod");
		    modp->accept(*this);  // Recursive call to visit(AstNodeModule)
		}
		// Done, restore vars
		m_scopep = oldScopep;
		m_aboveCellp = oldAbCellp;
		m_aboveScopep = oldAbScopep;
	    }
	}

	// Create scope for the current usage of this module
	UINFO(4," back AT "<<scopename<<"  "<<nodep<<endl);
        AstNode::user1ClearTree();
	m_modp = nodep;
	if (m_modp->isTop()) {
	    AstTopScope* topscp = new AstTopScope(nodep->fileline(), m_scopep);
	    m_modp->addStmtp(topscp);
	} else {
	    m_modp->addStmtp(m_scopep);
	}

	// Copy blocks into this scope
	// If this is the first usage of the block ever, we can simply move the reference
	nodep->iterateChildren(*this);

	// ***Note m_scopep is passed back to the caller of the routine (above)
    }
Exemple #5
0
    string descopedName(AstScope* scopep, bool& hierThisr, AstVar* varp=NULL) {
	UASSERT(scopep, "Var/Func not scoped\n");
	hierThisr = true;
	if (varp && varp->isFuncLocal()) {
	    return "";  // Relative to function, not in this
	} else if (scopep == m_scopep && m_modp->isTop()) {
	    //return "";  // Reference to scope we're in, no need to HIER-> it
	    return "vlTOPp->";
	} else if (scopep == m_scopep && !m_modp->isTop()
		   && 0) {	// We no longer thisp-> as still get ambiguation problems
	    m_needThis = true;
	    return "thisp->";  // this-> but with restricted aliasing
	} else if (scopep->aboveScopep() && scopep->aboveScopep()==m_scopep
		   && 0  // DISABLED: GCC considers the pointers ambiguous, so goes ld/store crazy
	    ) {
	    // Reference to scope of cell directly under this module, can just "cell->"
	    string name = scopep->name();
	    string::size_type pos;
	    if ((pos = name.rfind(".")) != string::npos) {
		name.erase(0,pos+1);
	    }
	    hierThisr = false;
	    return name+"->";
	} else {
	    // Reference to something else, use global variable
	    UINFO(8,"      Descope "<<scopep<<endl);
	    UINFO(8,"           to "<<scopep->name()<<endl);
	    UINFO(8,"        under "<<m_scopep->name()<<endl);
	    hierThisr = false;
	    if (!scopep->aboveScopep()) { // Top
		return "vlTOPp->";	// == "vlSymsp->TOPp->", but GCC would suspect aliases
	    } else {
		return scopep->nameVlSym()+".";
	    }
	}
    }
void EmitCSyms::emitSymImp() {
    UINFO(6,__FUNCTION__<<": "<<endl);
    string filename = v3Global.opt.makeDir()+"/"+symClassName()+".cpp";
    AstCFile* cfilep = newCFile(filename, true/*slow*/, true/*source*/);
    cfilep->support(true);
    V3OutCFile cf (filename);
    m_ofp = &cf;
    ofp()->putsHeader();
    puts("// DESCR" "IPTION: Verilator output: Symbol table implementation internals\n");
    puts("\n");

    // Includes
    puts("#include \""+symClassName()+".h\"\n");
    for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) {
	puts("#include \""+modClassName(nodep)+".h\"\n");
    }

    //puts("\n// GLOBALS\n");

    puts("\n// FUNCTIONS\n");
    puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n");
    puts("\t// Setup locals\n");
    puts("\t: __Vm_namep(namep)\n");	// No leak, as we get destroyed when the top is destroyed
    puts("\t, __Vm_activity(false)\n");
    puts("\t, __Vm_didInit(false)\n");
    puts("\t// Setup submodule names\n");
    char comma=',';
    for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
	AstScope* scopep = it->first;  AstNodeModule* modp = it->second;
	if (modp->isTop()) {
	} else {
	    ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
	    puts("(Verilated::catName(topp->name(),");
	    // The "." is added by catName
	    putsQuoted(scopep->prettyName());
	    puts("))\n");
	    comma=',';
	}
    }
    puts("{\n");

    puts("// Pointer to top level\n");
    puts("TOPp = topp;\n");
    puts("// Setup each module's pointers to their submodules\n");
    for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
	AstScope* scopep = it->first;  AstNodeModule* modp = it->second;
	if (!modp->isTop()) {
	    string arrow = scopep->name();
	    string::size_type pos;
	    while ((pos=arrow.find(".")) != string::npos) {
		arrow.replace(pos, 1, "->");
	    }
	    if (arrow.substr(0,5) == "TOP->") arrow.replace(0,5,"TOPp->");
	    ofp()->printf("%-30s ", arrow.c_str());
	    puts(" = &");
	    puts(scopep->nameDotless()+";\n");
	}
    }

    puts("// Setup each module's pointer back to symbol table (for public functions)\n");
    puts("TOPp->__Vconfigure(this, true);\n");
    for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
	AstScope* scopep = it->first;  AstNodeModule* modp = it->second;
	if (!modp->isTop()) {
	    // first is used by AstCoverDecl's call to __vlCoverInsert
	    bool first = !modp->user1();
	    modp->user1(true);
	    puts(scopep->nameDotless()+".__Vconfigure(this, "
		 +(first?"true":"false")
		 +");\n");
	}
    }

    puts("// Setup scope names\n");
    for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
	puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
	putsQuoted(it->second.m_prettyName);
	puts(");\n");
    }

    if (v3Global.dpi()) {
	puts("// Setup export functions\n");
	puts("for (int __Vfinal=0; __Vfinal<2; __Vfinal++) {\n");
	for (ScopeFuncs::iterator it = m_scopeFuncs.begin(); it != m_scopeFuncs.end(); ++it) {
	    AstScopeName* scopep = it->second.m_scopep;
	    AstCFunc* funcp = it->second.m_funcp;
	    AstNodeModule* modp = it->second.m_modp;
	    if (funcp->dpiExport()) {
		puts("__Vscope_"+scopep->scopeSymName()+".exportInsert(__Vfinal,");
		putsQuoted(funcp->cname());
		puts(", (void*)(&");
		puts(modClassName(modp));
		puts("::");
		puts(funcp->name());
		puts("));\n");
	    }
	}
	// It would be less code if each module inserted its own variables.
	// Someday.  For now public isn't common.
	for (ScopeVars::iterator it = m_scopeVars.begin(); it != m_scopeVars.end(); ++it) {
	    AstNodeModule* modp = it->second.m_modp;
	    AstScope* scopep = it->second.m_scopep;
	    AstVar* varp = it->second.m_varp;
	    //
	    int pdim=0;
	    int udim=0;
	    string bounds;
	    if (AstBasicDType* basicp = varp->basicp()) {
		// Range is always first, it's not in "C" order
		if (basicp->isRanged()) {
		    bounds += " ,"; bounds += cvtToStr(basicp->msb());
		    bounds += ","; bounds += cvtToStr(basicp->lsb());
		    pdim++;
		}
		for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
		    dtypep = dtypep->skipRefp();  // Skip AstRefDType/AstTypedef, or return same node
		    if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
			bounds += " ,"; bounds += cvtToStr(adtypep->msb());
			bounds += ","; bounds += cvtToStr(adtypep->lsb());
			if (dtypep->castPackArrayDType()) pdim++; else udim++;
			dtypep = adtypep->subDTypep();
		    }
		    else break; // AstBasicDType - nothing below, 1
		}
	    }
	    //
	    if (pdim>1 || udim>1) {
		puts("//UNSUP ");  // VerilatedImp can't deal with >2d or packed arrays
	    }
	    puts("__Vscope_"+it->second.m_scopeName+".varInsert(__Vfinal,");
	    putsQuoted(it->second.m_varBasePretty);
	    puts(", &(");
	    if (modp->isTop()) {
		puts(scopep->nameDotless());
		puts("p->");
	    } else {
		puts(scopep->nameDotless());
		puts(".");
	    }
	    puts(varp->name());
	    puts("), ");
	    puts(varp->vlEnumType());  // VLVT_UINT32 etc
	    puts(",");
	    puts(varp->vlEnumDir());  // VLVD_IN etc
	    if (varp->isSigUserRWPublic()) puts("|VLVF_PUB_RW");
	    else if (varp->isSigUserRdPublic()) puts("|VLVF_PUB_RD");
	    puts(",");
	    puts(cvtToStr(pdim+udim));
	    puts(bounds);
	    puts(");\n");
	}
	puts("}\n");
    }

    puts("}\n");

    if (v3Global.opt.savable() ) {
	puts("\n");
	for (int de=0; de<2; ++de) {
	    string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
	    string funcname = de ? "__Vdeserialize" : "__Vserialize";
	    string op = de ? ">>" : "<<";
	    puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
	    puts(   "// LOCAL STATE\n");
	    // __Vm_namep presumably already correct
	    puts(   "os"+op+"__Vm_activity;\n");
	    puts(   "os"+op+"__Vm_didInit;\n");
	    puts(   "// SUBCELL STATE\n");
	    for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
		AstScope* scopep = it->first;  AstNodeModule* modp = it->second;
		if (!modp->isTop()) {
		    puts(   scopep->nameDotless()+"."+funcname+"(os);\n");
		}
	    }
	    puts("}\n");
	}
    }
}