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+"]"; }
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 }
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; }
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:"); } } }