string bitNames(BitNamesWhich which) {
     string bits="";
     bool prev = false;
     int msb = 0;
     // bit==-1 loops below; we do one extra iteration so end with prev=false
     for (int bit=(m_flags.size()/FLAGS_PER_BIT)-1; bit >= -1; --bit) {
         if (bit>=0
                 && ((which == BN_UNUSED && !usedFlag(bit) && drivenFlag(bit))
                     || (which == BN_UNDRIVEN && usedFlag(bit) && !drivenFlag(bit))
                     || (which == BN_BOTH && !usedFlag(bit) && !drivenFlag(bit)))) {
             if (!prev) {
                 prev=true;
                 msb = bit;
             }
         } else if (prev) {
             AstBasicDType* bdtypep = m_varp->basicp();
             int lsb = bit+1;
             if (bits != "") bits += ",";
             if (lsb==msb) {
                 bits += cvtToStr(lsb+bdtypep->lsb());
             } else {
                 if (bdtypep->littleEndian()) {
                     bits += cvtToStr(lsb+bdtypep->lsb())+":"+cvtToStr(msb+bdtypep->lsb());
                 } else {
                     bits += cvtToStr(msb+bdtypep->lsb())+":"+cvtToStr(lsb+bdtypep->lsb());
                 }
             }
             prev = false;
         }
     }
     return "["+bits+"]";
 }
Beispiel #2
0
    void addTraceDecl(const VNumRange& arrayRange) {
	VNumRange bitRange;
	AstBasicDType* bdtypep = m_traValuep->dtypep()->basicp();
	if (bdtypep) bitRange = bdtypep->nrange();
	AstTraceDecl* declp = new AstTraceDecl(m_traVscp->fileline(), m_traShowname, m_traValuep,
					       bitRange, arrayRange);

	if (m_initSubStmts && v3Global.opt.outputSplitCTrace()
	    && m_initSubStmts > v3Global.opt.outputSplitCTrace()) {
	    m_initSubFuncp = newCFuncSub(m_initFuncp);
	    m_initSubStmts = 0;
	}

	m_initSubFuncp->addStmtsp(declp);
	m_initSubStmts += EmitCBaseCounterVisitor(declp).count();

	m_chgFuncp->addStmtsp(new AstTraceInc(m_traVscp->fileline(), declp, m_traValuep->cloneTree(true)));
	// The full version will get constructed in V3Trace
    }
Beispiel #3
0
void AstTypeTable::dump(ostream& str) {
    this->AstNode::dump(str);
    for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
	if (AstBasicDType* subnodep=m_basicps[i]) {
	    str<<endl;  // Newline from caller, so newline first
	    str<<"\t\t"<<setw(8)<<AstBasicDTypeKwd(i).ascii();
	    str<<"  -> ";
	    subnodep->dump(str);
	}
    }
    for (int isbit=0; isbit<2; ++isbit) {
	for (int issigned=0; issigned<AstNumeric::_ENUM_MAX; ++issigned) {
	    LogicMap& mapr = m_logicMap[isbit][issigned];
	    for (LogicMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
		AstBasicDType* dtypep = it->second;
		str<<endl;  // Newline from caller, so newline first
		stringstream nsstr;
		nsstr<<(isbit?"bw":"lw")
		     <<it->first.first<<"/"<<it->first.second;
		str<<"\t\t"<<setw(8)<<nsstr.str();
		if (issigned) str<<" s"; else str<<" u";
		str<<"  ->  ";
		dtypep->dump(str);
	    }
	}
    }
    {
	DetailedMap& mapr = m_detailedMap;
	for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
	    AstBasicDType* dtypep = it->second;
	    str<<endl;  // Newline from caller, so newline first
	    stringstream nsstr;
	    str<<"\t\tdetailed  ->  ";
	    dtypep->dump(str);
	}
    }
    // Note get newline from caller too.
}
string AstVar::vlEnumType() const {
    string arg;
    AstBasicDType* bdtypep = basicp();
    bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
    if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
	return "VLVT_PTR";
    } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
	return "VLVT_PTR";
    } else if (strtype) {
	arg += "VLVT_STRING";
    } else if (widthMin() <= 8) {
	arg += "VLVT_UINT8";
    } else if (widthMin() <= 16) {
	arg += "VLVT_UINT16";
    } else if (widthMin() <= VL_WORDSIZE) {
	arg += "VLVT_UINT32";
    } else if (isQuad()) {
	arg += "VLVT_UINT64";
    } else if (isWide()) {
	arg += "VLVT_WDATA";
    }
    // else return "VLVT_UNKNOWN"
    return arg;
}
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
    if (forReturn) named=false;
    if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
    string arg;
    if (isWide() && isInOnly()) arg += "const ";
    AstBasicDType* bdtypep = basicp();
    bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
    if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
	arg += "const char*";
    } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
	arg += "const VerilatedScope*";
    } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
	arg += "double";
    } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
	arg += "float";
    } else if (strtype) {
	if (isInOnly()) arg += "const ";
	arg += "string";
    } else if (widthMin() <= 8) {
	arg += "CData";
    } else if (widthMin() <= 16) {
	arg += "SData";
    } else if (widthMin() <= VL_WORDSIZE) {
	arg += "IData";
    } else if (isQuad()) {
	arg += "QData";
    } else if (isWide()) {
	arg += "WData";  // []'s added later
    }
    if (isWide() && !strtype) {
	arg += " (& "+name();
	arg += ")["+cvtToStr(widthWords())+"]";
    } else {
	if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
	if (named) arg += " "+name();
    }
    return arg;
}
    static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
					  bool forTristate, bool alwaysCvt) {
	// If a pin connection is "simple" leave it as-is
	// Else create a intermediate wire to perform the interconnect
	// Return the new assignment, if one was made
	// Note this module calles cloneTree() via new AstVar
	AstVar* pinVarp = pinp->modVarp();
	AstVarRef* connectRefp = pinp->exprp()->castVarRef();
	AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp();  // Maybe NULL
	AstBasicDType* connBasicp = NULL;
	AstAssignW* assignp = NULL;
	if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
	//
	if (!alwaysCvt
	    && connectRefp
	    && connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
	    && !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
	    // Done. Same data type
	} else if (!alwaysCvt
		   && connectRefp
		   && connectRefp->varp()->isIfaceRef()) {
	    // Done. Interface
	} else if (!alwaysCvt
		   && connBasicp
		   && pinBasicp
		   && connBasicp->width() == pinBasicp->width()
		   && connBasicp->lsb() == pinBasicp->lsb()
		   && !connectRefp->varp()->isSc()	// Need the signal as a 'shell' to convert types
		   && connBasicp->width() == pinVarp->width()
		   && 1) {
	    // Done. One to one interconnect won't need a temporary variable.
	} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
	    // Done. Constant.
	} else {
	    // Make a new temp wire
	    //if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
	    AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
	    string newvarname = ((string)(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
				 +(forTristate?"t":"")  // Prevent name conflict if both tri & non-tri add signals
				 +"__"+cellp->name()+"__"+pinp->name());
	    AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
	    // Important to add statement next to cell, in case there is a generate with same named cell
	    cellp->addNextHere(newvarp);
	    if (pinVarp->isInout()) {
		pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
	    } else if (pinVarp->isOutput()) {
		// See also V3Inst
		AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
		UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
		rhsp = extendOrSel (pinp->fileline(), rhsp, pinVarp);
		pinp->exprp(new AstVarRef (newvarp->fileline(), newvarp, true));
		AstNode* rhsSelp = extendOrSel (pinp->fileline(), rhsp, pinexprp);
		assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsSelp);
	    } else {
		// V3 width should have range/extended to make the widths correct
		assignp = new AstAssignW (pinp->fileline(),
					  new AstVarRef(pinp->fileline(), newvarp, true),
					  pinexprp);
		pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
	    }
	    if (assignp) cellp->addNextHere(assignp);
	    //if (debug()) { pinp->dumpTree(cout,"-  out:"); }
	    //if (debug()) { assignp->dumpTree(cout,"- aout:"); }
	}
	return assignp;
    }
Beispiel #7
0
void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp) {
    // If a pin connection is "simple" leave it as-is
    // Else create a intermediate wire to perform the interconnect
    // Note this module calles cloneTree() via new AstVar
    AstVar* pinVarp = pinp->modVarp();
    AstVarRef* connectRefp = pinp->exprp()->castVarRef();
    AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp();  // Maybe NULL
    AstBasicDType* connBasicp = NULL;
    if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
    //
    if (connectRefp
	&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
	&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
	// Done.  Same data type
    } else if (connBasicp
	       && pinBasicp
	       && connBasicp->width() == pinBasicp->width()
	       && connBasicp->lsb() == pinBasicp->lsb()
	       && !connectRefp->varp()->isSc()	// Need the signal as a 'shell' to convert types
	       && pinp->width() == pinVarp->width()
	       && 1) {
	// Done. One to one interconnect won't need a temporary variable.
    } else if (pinp->exprp()->castConst()) {
	// Done. Constant.
    } else {
	// Make a new temp wire
	//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
	AstAssignW* assignp = NULL;
	AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
	string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
	AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
	modp->addStmtp(newvarp);
	if (pinVarp->isInout()) {
	    pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
	} else if (pinVarp->isOutput()) {
	    // See also V3Inst
	    AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
	    if (pinp->width() > rhsp->width()) {
		if (rhsp->isSigned()) {
		    rhsp = new AstExtendS(pinp->fileline(), rhsp);
		} else {
		    rhsp = new AstExtend (pinp->fileline(), rhsp);
		}
	    } else if (pinp->width() < rhsp->width()) {
		rhsp = new AstSel    (pinp->fileline(), rhsp, 0, pinp->width());
	    }
	    rhsp->widthSignedFrom(pinp);
	    assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsp);
	    pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
	} else {
	    // V3 width should have range/extended to make the widths correct
	    if (pinexprp->width() != pinVarp->width()) pinp->v3fatalSrc("Input pin width mismatch");
	    assignp = new AstAssignW (pinp->fileline(),
				      new AstVarRef(pinp->fileline(), newvarp, true),
				      pinexprp);
	    pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
	}
	pinp->widthSignedFrom(pinp->exprp());
	if (assignp) modp->addStmtp(assignp);
	//if (1||debug()) { pinp->dumpTree(cout,"  out:"); }
	//if (1||debug()) { assignp->dumpTree(cout," aout:"); }
    }
}