Internals: Refactor into V3Width enumSelect function

This commit is contained in:
Wilson Snyder 2024-10-07 21:28:29 -04:00
parent 13c7b6e827
commit b873c23cf2
4 changed files with 655 additions and 650 deletions

View File

@ -3326,27 +3326,9 @@ class WidthVisitor final : public VNVisitor {
}
}
}
// Need a runtime lookup table. Yuk.
const uint64_t msbdim = enumMaxValue(nodep, adtypep);
const bool assoc = msbdim > ENUM_LOOKUP_BITS;
if (assoc) {
AstVar* const varp = enumVarp(adtypep, attrType, true, 0);
AstNode* const newp = new AstAssocSel{nodep->fileline(), newVarRefDollarUnit(varp),
nodep->fromp()->unlinkFrBack()};
newp->dtypeFrom(adtypep); // To prevent a later ENUMVALUE
nodep->replaceWith(newp);
} else {
const int selwidth = V3Number::log2b(msbdim) + 1; // Width to address a bit
AstVar* const varp = enumVarp(adtypep, attrType, false, (1ULL << selwidth) - 1);
AstNode* const newp = new AstArraySel{
nodep->fileline(), newVarRefDollarUnit(varp),
// Select in case widths are off due to msblen!=width
// We return "random" values if outside the range, which is fine
// as next/previous on illegal values just need something good out
new AstSel{nodep->fileline(), nodep->fromp()->unlinkFrBack(), 0, selwidth}};
newp->dtypeFrom(adtypep); // To prevent a later ENUMVALUE
nodep->replaceWith(newp);
}
AstNodeExpr* const newp
= enumSelect(nodep->fromp()->unlinkFrBack(), adtypep, attrType);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else {
nodep->v3error("Unknown built-in enum method " << nodep->prettyNameQ());
@ -7764,6 +7746,30 @@ class WidthVisitor final : public VNVisitor {
}
return pair.first->second;
}
AstNodeExpr* enumSelect(AstNodeExpr* nodep, AstEnumDType* adtypep, VAttrType attrType) {
// Return expression to get given attrType information from a enum's value (nodep)
// Need a runtime lookup table. Yuk.
const uint64_t msbdim = enumMaxValue(nodep, adtypep);
const bool assoc = msbdim > ENUM_LOOKUP_BITS;
if (assoc) {
AstVar* const varp = enumVarp(adtypep, attrType, true, 0);
AstNodeExpr* const newp
= new AstAssocSel{nodep->fileline(), newVarRefDollarUnit(varp), nodep};
newp->dtypeFrom(adtypep); // To prevent a later ENUMVALUE
return newp;
} else {
const int selwidth = V3Number::log2b(msbdim) + 1; // Width to address a bit
AstVar* const varp = enumVarp(adtypep, attrType, false, (1ULL << selwidth) - 1);
AstNodeExpr* const newp = new AstArraySel{
nodep->fileline(), newVarRefDollarUnit(varp),
// Select in case widths are off due to msblen!=width
// We return "random" values if outside the range, which is fine
// as next/previous on illegal values just need something good out
new AstSel{nodep->fileline(), nodep, 0, selwidth}};
newp->dtypeFrom(adtypep); // To prevent a later ENUMVALUE
return newp;
}
}
PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) {
PatVecMap patmap;

View File

@ -1,9 +1,8 @@
%Error: t/t_enum_huge_methods_bad.v:15:18: Value too wide for 64-bits expected in this context 160'h12344567abcd12344567abcd
15 | ELARGE = 160'h1234_4567_abcd_1234_4567_abcd
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_enum_huge_methods_bad.v:30:21: Unsupported: enum next/prev/name method on enum with > 64 bits
: ... note: In instance 't'
%Error-UNSUPPORTED: t/t_enum_huge_methods_bad.v:30:19: Unsupported: enum next/prev/name method on enum with > 64 bits
30 | $display(e.name);
| ^~~~
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff