diff --git a/include/verilated.h b/include/verilated.h index 6cce56a65..297c013da 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -221,13 +221,6 @@ public: //========================================================================= // Declare nets -#ifndef VL_ST_SIG -# define VL_ST_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits -# define VL_ST_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits -# define VL_ST_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits -# define VL_ST_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits -# define VL_ST_SIGW(name,msb,lsb,words) WData name[words] ///< Declare signal, 65+ bits -#endif #ifndef VL_SIG # define VL_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits # define VL_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index fabe9ed8f..58872b4a8 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -226,72 +226,92 @@ string AstVar::verilogKwd() const { } } -string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const { +class AstVar::VlArgTypeRecurseInfo { +public: + bool m_named; + bool m_forFunc; + bool m_mayParen; + string m_namespc; + string paren(const string& s) { + if (m_mayParen) { m_mayParen = false; return " ("+s+")"; } + else return s; + } +}; + +string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc) const { UASSERT_OBJ(!forReturn, this, "Internal data is never passed as return, but as first argument"); - string otype; - AstBasicDType* bdtypep = basicp(); - bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING; - if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) { - otype += "const char*"; - } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) { - otype += "const VerilatedScope*"; - } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "double"; - } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "float"; - } else if (strtype) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "std::string"; - } else if (widthMin() <= 8) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "CData"; - } else if (widthMin() <= 16) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "SData"; - } else if (widthMin() <= VL_WORDSIZE) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "IData"; - } else if (isQuad()) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "QData"; - } else if (isWide()) { - if (forFunc && isReadOnly()) otype += "const "; - otype += "WData"; // []'s added later - } + VlArgTypeRecurseInfo info; + info.m_named = named; + info.m_forFunc = forFunc; + info.m_mayParen = false; + info.m_namespc = namespc; - bool mayparen = false; // Need paren, to handle building "(& name)[2]" - string oname; - if (isDpiOpenArray() - || (isWide() && !strtype) - || (forFunc && (isWritable() - || direction()==VDirection::REF - || direction()==VDirection::CONSTREF - || (strtype && isNonOutput())))) { - oname += "&"; - mayparen = true; - } - if (named) oname += " "+VIdProtect::protectIf(name(), protect()); + string ostatic; + if (isStatic() && info.m_namespc.empty()) ostatic = "static "; + return ostatic + vlArgTypeRecurse(dtypep(), &info, ""); +} - string oarray; - if (isDpiOpenArray() || direction().isRefOrConstRef()) { - for (AstNodeDType* dtp=dtypep(); dtp; ) { - dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node - if (AstUnpackArrayDType* adtypep = VN_CAST(dtp, UnpackArrayDType)) { - if (mayparen) { oname = " ("+oname+")"; mayparen = false; } - oarray += "["+cvtToStr(adtypep->declRange().elements())+"]"; - dtp = adtypep->subDTypep(); - } else break; +string AstVar::vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* infop, + const string& inarray) const { + dtypep = dtypep->skipRefp(); + if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { + string oarray = "["+cvtToStr(adtypep->declRange().elements())+"]"; + return vlArgTypeRecurse(adtypep->subDTypep(), infop, inarray+oarray); + } else if (AstBasicDType* bdtypep = basicp()) { + string otype; + string oarray = inarray; + bool strtype = bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::STRING; + string bitvec; + if (bdtypep && !bdtypep->isOpaque() && !v3Global.opt.protectIds()) { + bitvec = ("/*"+cvtToStr(bdtypep->lsb()+bdtypep->width()-1) + +":"+cvtToStr(bdtypep->lsb())+"*/"); } + if ((infop->m_forFunc && isReadOnly()) + || bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR + || bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) otype += "const "; + if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) { + otype += "char*"; + } else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) { + otype += "VerilatedScope*"; + } else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) { + otype += "double"; + } else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) { + otype += "float"; + } else if (strtype) { + otype += "std::string"; + } else if (widthMin() <= 8) { + otype += "CData"+bitvec; + } else if (widthMin() <= 16) { + otype += "SData"+bitvec; + } else if (widthMin() <= VL_WORDSIZE) { + otype += "IData"+bitvec; + } else if (isQuad()) { + otype += "QData"+bitvec; + } else if (isWide()) { + otype += "WData"+bitvec; // []'s added later + oarray += "["+cvtToStr(widthWords())+"]"; + } + + string oname; + if (isDpiOpenArray() + || (infop->m_forFunc && (isWritable() + || direction() == VDirection::REF + || direction() == VDirection::CONSTREF + || (strtype && isNonOutput())))) { + oname += "&"; + infop->m_mayParen = true; + } + if (infop->m_named) { + oname += " "; + if (!infop->m_namespc.empty()) oname += infop->m_namespc+"::"; + oname += VIdProtect::protectIf(name(), protect()); + } + if (!oarray.empty()) oname = infop->paren(oname); + return otype+oname+oarray; + } else { + v3fatalSrc("Unknown data type in var type emitter: "<prettyName()); } - if (isWide() && !strtype) { - if (mayparen) { oname = " ("+oname+")"; mayparen = false; } - oarray += "["+cvtToStr(widthWords())+"]"; - } - if (mayparen) { } - return otype+oname+oarray; } string AstVar::vlEnumType() const { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index af9b25451..019e79cd8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1271,7 +1271,7 @@ public: string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument // Return Verilator internal type for argument: CData, SData, IData, WData - string vlArgType(bool named, bool forReturn, bool forFunc) const; + string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc="") const; string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc string vlPropInit() const; // Return VerilatorVarProps initializer @@ -1410,6 +1410,10 @@ public: void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } string mtasksString() const; +private: + class VlArgTypeRecurseInfo; + string vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* infop, + const string& oarray) const; }; class AstDefParam : public AstNode { diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 9bc2f9b13..a3fab3bdc 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1303,71 +1303,34 @@ public: void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { AstBasicDType* basicp = nodep->basicp(); UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type"); - if (nodep->isIO()) { - if (nodep->isSc()) { - m_ctorVarsVec.push_back(nodep); - if (nodep->attrScClocked() && nodep->isReadOnly()) { - puts("sc_in_clk "); - } else { - if (nodep->isInoutish()) puts("sc_inout<"); - else if (nodep->isWritable()) puts("sc_out<"); - else if (nodep->isNonOutput()) puts("sc_in<"); - else nodep->v3fatalSrc("Unknown type"); - - puts(nodep->scType()); - puts("> "); - } - puts(nodep->nameProtect()); - emitDeclArrayBrackets(nodep); - puts(";\n"); - } else if (basicp && basicp->isOpaque()) { - // strings and other fundamental c types; no VL_ macro can be used - puts(nodep->vlArgType(true, false, false)); - emitDeclArrayBrackets(nodep); - puts(";\n"); - } else { // C++ signals - if (nodep->isInoutish()) puts("VL_INOUT"); - else if (nodep->isWritable()) puts("VL_OUT"); - else if (nodep->isNonOutput()) puts("VL_IN"); + if (nodep->isIO() && nodep->isSc()) { + m_ctorVarsVec.push_back(nodep); + if (nodep->attrScClocked() && nodep->isReadOnly()) { + puts("sc_in_clk "); + } else { + if (nodep->isInoutish()) puts("sc_inout<"); + else if (nodep->isWritable()) puts("sc_out<"); + else if (nodep->isNonOutput()) puts("sc_in<"); else nodep->v3fatalSrc("Unknown type"); - if (nodep->isQuad()) puts("64"); - else if (nodep->widthMin() <= 8) puts("8"); - else if (nodep->widthMin() <= 16) puts("16"); - else if (nodep->isWide()) puts("W"); - - puts("("+nodep->nameProtect()); - emitDeclArrayBrackets(nodep); - // If it's a packed struct/array then nodep->width is the whole - // thing, msb/lsb is just lowest dimension - puts(","+cvtToStr(basicp->lsb()+nodep->width()-1) - +","+cvtToStr(basicp->lsb())); - if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords())); - puts(");\n"); + puts(nodep->scType()); + puts("> "); } - } else if (basicp && basicp->isOpaque()) { - // strings and other fundamental c types - puts(nodep->vlArgType(true, false, false)); + puts(nodep->nameProtect()); emitDeclArrayBrackets(nodep); puts(";\n"); - } else { - // Arrays need a small alignment, but may need different padding after. - // For example three VL_SIG8's needs alignment 1 but size 3. - if (nodep->isStatic() && prefixIfImp=="") puts("static "); - if (nodep->isStatic()) puts("VL_ST_"); else puts("VL_"); - if (nodep->widthMin() <= 8) { - puts("SIG8("); - } else if (nodep->widthMin() <= 16) { - puts("SIG16("); - } else if (nodep->isQuad()) { - puts("SIG64("); - } else if (!nodep->isWide()) { - puts("SIG("); - } else { - puts("SIGW("); - } - if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); } - puts(nodep->nameProtect()); + } else if (nodep->isIO() && basicp && !basicp->isOpaque()) { + if (nodep->isInoutish()) puts("VL_INOUT"); + else if (nodep->isWritable()) puts("VL_OUT"); + else if (nodep->isNonOutput()) puts("VL_IN"); + else nodep->v3fatalSrc("Unknown type"); + + if (nodep->isQuad()) puts("64"); + else if (nodep->widthMin() <= 8) puts("8"); + else if (nodep->widthMin() <= 16) puts("16"); + else if (nodep->isWide()) puts("W"); + + puts("("+nodep->nameProtect()); emitDeclArrayBrackets(nodep); // If it's a packed struct/array then nodep->width is the whole // thing, msb/lsb is just lowest dimension @@ -1375,6 +1338,10 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { +","+cvtToStr(basicp->lsb())); if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords())); puts(");\n"); + } else { + // strings and other fundamental c types + puts(nodep->vlArgType(true, false, false, prefixIfImp)); + puts(";\n"); } }