diff --git a/Changes b/Changes index 2b3e63fac..a2b96cf76 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,7 @@ Verilator 5.017 devel * Support resizing function call inout arguments (#4467). * Support converting parameters inside modules to localparams (#4511). [Anthony Donlon] * Fix conversion of impure logical expressions to bit expressions (#487 partial) (#4437). [Ryszard Rozak, Antmicro Ltd.] +* Fix enum functions in localparams (#3999). [Andrew Nolte] * Fix passing arguments by reference (#3385 partial) (#4489). [Ryszard Rozak, Antmicro Ltd.] * Fix multithreading handling to separate by code units that use/never use it (#4228). [Mariusz Glebocki, Antmicro Ltd.] * Fix usage of annotation options (#4486) (#4504). [Michal Czyz] diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index b8ee2c72e..e1353b9a1 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -754,10 +754,14 @@ class AstEnumDType final : public AstNodeDType { // Parents: TYPEDEF/MODULE // @astgen op1 := childDTypep : Optional[AstNodeDType] // @astgen op2 := itemsp : List[AstEnumItem] +public: + using TableMap = std::map; + private: string m_name; // Name from upper typedef, if any AstNodeDType* m_refDTypep = nullptr; // Elements are of this type after V3Width const int m_uniqueNum = 0; + TableMap m_tableMap; // Created table for V3Width only to remove duplicates public: AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstEnumItem* itemsp) @@ -770,9 +774,12 @@ public: widthFromSub(subDTypep()); } ASTGEN_MEMBERS_AstEnumDType; + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); + BROKEN_RTN(std::any_of(m_tableMap.begin(), m_tableMap.end(), + [](const auto& p) { return !p.second->brokeExists(); })); return nullptr; } void cloneRelink() override { @@ -809,6 +816,8 @@ public: return count; } bool isCompound() const override { return false; } + TableMap& tableMap() { return m_tableMap; } + const TableMap& tableMap() const { return m_tableMap; } }; class AstIfaceRefDType final : public AstNodeDType { // Reference to an interface, either for a port, or inside parent cell diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 1d6468001..7f7e8214f 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -7193,8 +7193,9 @@ private: } AstVar* enumVarp(AstEnumDType* nodep, VAttrType attrType, bool assoc, uint32_t msbdim) { // Return a variable table which has specified dimension properties for this variable - const auto pos = m_tableMap.find(std::make_pair(nodep, attrType)); - if (pos != m_tableMap.end()) return pos->second; + const auto& tableMapr = nodep->tableMap(); + const auto pos = tableMapr.find(attrType); + if (pos != tableMapr.end()) return pos->second; UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " assoc=" << assoc << " max=" << msbdim << " for " << nodep << endl); AstNodeDType* basep; @@ -7276,7 +7277,7 @@ private: } } userIterate(varp, nullptr); // May have already done $unit so must do this var - m_tableMap.emplace(std::make_pair(nodep, attrType), varp); + nodep->tableMap().emplace(attrType, varp); return varp; } diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 959bde51b..ec538084c 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -184,13 +184,18 @@ private: nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - void visit(AstNodeDType* nodep) override { // + void visit(AstNodeDType* nodep) override { + // Note some specific dtypes have unique visitors visitIterateNodeDType(nodep); } void visit(AstNodeUOrStructDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); } + void visit(AstEnumDType* nodep) override { + nodep->tableMap().clear(); // Only needed up through V3Width process + visitIterateNodeDType(nodep); + } void visit(AstParamTypeDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); diff --git a/test_regress/t/t_enum_const_methods.v b/test_regress/t/t_enum_const_methods.v index e5ce9e979..547a19a02 100644 --- a/test_regress/t/t_enum_const_methods.v +++ b/test_regress/t/t_enum_const_methods.v @@ -36,11 +36,20 @@ module t (); localparam string e0_name = get_name(E0); + function automatic enm_t get_2(); + enm_t enm; + enm = E0; + return enm.next.next; + endfunction + + localparam enm_t enum_2 = get_2(); + initial begin if (enum_first != E0) $stop; if (enum_last != E2) $stop; if (enum_second != E1) $stop; if (e0_name != "E0") $stop; + if (enum_2 != E2) $stop; $write("*-* All Finished *-*\n"); $finish; end