diff --git a/src/V3Ast.h b/src/V3Ast.h index dbcfa1960..fa4b9083c 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2439,6 +2439,11 @@ public: const char* charIQWN() const { return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); } + string cType(const string& name, bool forFunc, bool isRef) const; + +private: + class CTypeRecursed; + CTypeRecursed cTypeRecurse(bool forFunc, bool compound) const; }; class AstNodeUOrStructDType : public AstNodeDType { diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 080d8a5c1..acd24f932 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -312,20 +312,6 @@ string AstVar::verilogKwd() const { } } -class AstVar::VlArgTypeRecursed { -public: - string m_type; // The base type, e.g.: "Foo_t"s - string m_dims; // Array dimensions, e.g.: "[3][2][1]" - string render(const string& name, bool isRef) const { - string out; - out += m_type; - out += " "; - out += isRef ? "(&" + name + ")" : name; - out += m_dims; - return out; - } -}; - 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"); @@ -334,7 +320,6 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& bool isRef = isDpiOpenArray() || (forFunc && (isWritable() || direction().isRefOrConstRef())); - VlArgTypeRecursed info = vlArgTypeRecurse(forFunc, dtypep(), false); if (forFunc && isReadOnly() && isRef) ostatic = ostatic + "const "; string oname; @@ -342,75 +327,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& if (!namespc.empty()) oname += namespc + "::"; oname += VIdProtect::protectIf(name(), protect()); } - return ostatic + info.render(oname, isRef); -} - -AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDType* dtypep, - bool compound) const { - VlArgTypeRecursed info; - - dtypep = dtypep->skipRefp(); - if (const AstAssocArrayDType* adtypep = VN_CAST_CONST(dtypep, AssocArrayDType)) { - const VlArgTypeRecursed key = vlArgTypeRecurse(false, adtypep->keyDTypep(), true); - const VlArgTypeRecursed val = vlArgTypeRecurse(false, adtypep->subDTypep(), true); - info.m_type = "VlAssocArray<" + key.m_type + ", " + val.m_type + ">"; - } else if (const AstDynArrayDType* adtypep = VN_CAST_CONST(dtypep, DynArrayDType)) { - const VlArgTypeRecursed sub = vlArgTypeRecurse(false, adtypep->subDTypep(), true); - info.m_type = "VlQueue<" + sub.m_type + ">"; - } else if (const AstQueueDType* adtypep = VN_CAST_CONST(dtypep, QueueDType)) { - const VlArgTypeRecursed sub = vlArgTypeRecurse(false, adtypep->subDTypep(), true); - info.m_type = "VlQueue<" + sub.m_type; - // + 1 below as VlQueue uses 0 to mean unlimited, 1 to mean size() max is 1 - if (adtypep->boundp()) info.m_type += ", " + cvtToStr(adtypep->boundConst() + 1); - info.m_type += ">"; - } else if (const AstClassRefDType* adtypep = VN_CAST_CONST(dtypep, ClassRefDType)) { - info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">"; - } else if (const AstUnpackArrayDType* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) { - if (compound) { - v3fatalSrc("Dynamic arrays or queues with unpacked elements are not yet supported"); - } - const VlArgTypeRecursed sub = vlArgTypeRecurse(false, adtypep->subDTypep(), compound); - info.m_type = sub.m_type; - info.m_dims = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + sub.m_dims; - } else if (const AstBasicDType* bdtypep = dtypep->basicp()) { - // We don't print msb()/lsb() as multidim packed would require recursion, - // and may confuse users as C++ data is stored always with bit 0 used - const string bitvec = (!bdtypep->isOpaque() && !v3Global.opt.protectIds()) - ? "/*" + cvtToStr(dtypep->width() - 1) + ":0*/" - : ""; - if (bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) { - info.m_type = "const char*"; - } else if (bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) { - info.m_type = "const VerilatedScope*"; - } else if (bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) { - info.m_type = "double"; - } else if (bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) { - info.m_type = "float"; - } else if (bdtypep->keyword() == AstBasicDTypeKwd::STRING) { - info.m_type = "std::string"; - } else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width - info.m_type = "CData" + bitvec; - } else if (dtypep->widthMin() <= 16) { - info.m_type = "SData" + bitvec; - } else if (dtypep->widthMin() <= VL_IDATASIZE) { - info.m_type = "IData" + bitvec; - } else if (dtypep->isQuad()) { - info.m_type = "QData" + bitvec; - } else if (dtypep->isWide()) { - if (compound) { - info.m_type = "VlWide<" + cvtToStr(dtypep->widthWords()) + "> "; - } else { - info.m_type += "WData" + bitvec; // []'s added later - info.m_dims = "[" + cvtToStr(dtypep->widthWords()) + "]"; - } - } - } else { - v3fatalSrc("Unknown data type in var type emitter: " << dtypep->prettyName()); - } - - UASSERT_OBJ(!compound || info.m_dims.empty(), this, "Declaring C array inside compound type"); - - return info; + return ostatic + dtypep()->cType(oname, forFunc, isRef); } string AstVar::vlEnumType() const { @@ -636,6 +553,92 @@ string AstVar::mtasksString() const { return os.str(); } +class AstNodeDType::CTypeRecursed { +public: + string m_type; // The base type, e.g.: "Foo_t"s + string m_dims; // Array dimensions, e.g.: "[3][2][1]" + string render(const string& name, bool isRef) const { + string out; + out += m_type; + if (name != "") out += " "; + out += isRef ? "(&" + name + ")" : name; + out += m_dims; + return out; + } +}; + +string AstNodeDType::cType(const string& name, bool forFunc, bool isRef) const { + CTypeRecursed info = cTypeRecurse(forFunc, false); + return info.render(name, isRef); +} + +AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool forFunc, bool compound) const { + CTypeRecursed info; + + const AstNodeDType* dtypep = this->skipRefp(); + if (const auto* adtypep = VN_CAST_CONST(dtypep, AssocArrayDType)) { + const CTypeRecursed key = adtypep->keyDTypep()->cTypeRecurse(false, true); + const CTypeRecursed val = adtypep->subDTypep()->cTypeRecurse(false, true); + info.m_type = "VlAssocArray<" + key.m_type + ", " + val.m_type + ">"; + } else if (const auto* adtypep = VN_CAST_CONST(dtypep, DynArrayDType)) { + const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(false, true); + info.m_type = "VlQueue<" + sub.m_type + ">"; + } else if (const auto* adtypep = VN_CAST_CONST(dtypep, QueueDType)) { + const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(false, true); + info.m_type = "VlQueue<" + sub.m_type; + // + 1 below as VlQueue uses 0 to mean unlimited, 1 to mean size() max is 1 + if (adtypep->boundp()) info.m_type += ", " + cvtToStr(adtypep->boundConst() + 1); + info.m_type += ">"; + } else if (const auto* adtypep = VN_CAST_CONST(dtypep, ClassRefDType)) { + info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">"; + } else if (const auto* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) { + if (compound) { + v3fatalSrc("Dynamic arrays or queues with unpacked elements are not yet supported"); + } + const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(false, compound); + info.m_type = sub.m_type; + info.m_dims = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + sub.m_dims; + } else if (const AstBasicDType* bdtypep = dtypep->basicp()) { + // We don't print msb()/lsb() as multidim packed would require recursion, + // and may confuse users as C++ data is stored always with bit 0 used + const string bitvec = (!bdtypep->isOpaque() && !v3Global.opt.protectIds()) + ? "/*" + cvtToStr(dtypep->width() - 1) + ":0*/" + : ""; + if (bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) { + info.m_type = "const char*"; + } else if (bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) { + info.m_type = "const VerilatedScope*"; + } else if (bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) { + info.m_type = "double"; + } else if (bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) { + info.m_type = "float"; + } else if (bdtypep->keyword() == AstBasicDTypeKwd::STRING) { + info.m_type = "std::string"; + } else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width + info.m_type = "CData" + bitvec; + } else if (dtypep->widthMin() <= 16) { + info.m_type = "SData" + bitvec; + } else if (dtypep->widthMin() <= VL_IDATASIZE) { + info.m_type = "IData" + bitvec; + } else if (dtypep->isQuad()) { + info.m_type = "QData" + bitvec; + } else if (dtypep->isWide()) { + if (compound) { + info.m_type = "VlWide<" + cvtToStr(dtypep->widthWords()) + "> "; + } else { + info.m_type += "WData" + bitvec; // []'s added later + info.m_dims = "[" + cvtToStr(dtypep->widthWords()) + "]"; + } + } + } else { + v3fatalSrc("Unknown data type in var type emitter: " << dtypep->prettyName()); + } + + UASSERT_OBJ(!compound || info.m_dims.empty(), this, "Declaring C array inside compound type"); + + return info; +} + AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) { // dimension passed from AstArraySel::dimension // Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar, diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index cf681fad5..25400841a 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2182,11 +2182,6 @@ public: void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } string mtasksString() const; - -private: - class VlArgTypeRecursed; - VlArgTypeRecursed vlArgTypeRecurse(bool forFunc, const AstNodeDType* dtypep, - bool compound) const; }; class AstDefParam : public AstNode {