Fix enum functions in localparams (#3999).

This commit is contained in:
Wilson Snyder 2023-10-06 22:38:46 -04:00
parent 800a789f50
commit 0e0df1fb3b
5 changed files with 29 additions and 4 deletions

View File

@ -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]

View File

@ -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<VAttrType, AstVar*>;
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

View File

@ -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;
}

View File

@ -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);

View File

@ -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