Support enum.next with a parameter

This commit is contained in:
Wilson Snyder 2025-08-16 21:06:35 -04:00
parent 36c4a24661
commit 7126293086
5 changed files with 1003 additions and 995 deletions

View File

@ -3550,12 +3550,18 @@ class WidthVisitor final : public VNVisitor {
} }
if (nodep->name() != "name" && nodep->pinsp()) { if (nodep->name() != "name" && nodep->pinsp()) {
AstNodeExpr* const stepp = methodArg(nodep, 0); AstNodeExpr* stepp = methodArg(nodep, 0);
VL_DO_DANGLING(V3Const::constifyParamsNoWarnEdit(stepp), stepp);
stepp = methodArg(nodep, 0);
nodep->fileline()->modifyWarnOff(V3ErrorCode::WIDTHEXPAND, true); nodep->fileline()->modifyWarnOff(V3ErrorCode::WIDTHEXPAND, true);
iterateCheckUInt32(nodep, "argument", stepp, BOTH); iterateCheckUInt32(nodep, "argument", stepp, BOTH);
if (!VN_IS(stepp, Const)) { if (!VN_IS(stepp, Const)) {
stepp->v3fatalSrc("Unsupported: enum next/prev with non-const argument"); stepp->v3warn(E_UNSUPPORTED,
} else { "Unsupported: enum next/prev with non-constant argument");
AstNodeExpr* const newp = new AstConst{stepp->fileline(), 1};
stepp->replaceWith(newp);
stepp = newp;
}
const uint32_t stepWidth = VN_AS(stepp, Const)->toUInt(); const uint32_t stepWidth = VN_AS(stepp, Const)->toUInt();
if (stepWidth == 0) { if (stepWidth == 0) {
// Step of 0 "legalizes" like $cast, use .next.prev // Step of 0 "legalizes" like $cast, use .next.prev
@ -3583,7 +3589,6 @@ class WidthVisitor final : public VNVisitor {
return; return;
} }
} }
}
AstNodeExpr* const newp AstNodeExpr* const newp
= enumSelect(nodep->fromp()->unlinkFrBack(), adtypep, attrType); = enumSelect(nodep->fromp()->unlinkFrBack(), adtypep, attrType);
nodep->replaceWith(newp); nodep->replaceWith(newp);

View File

@ -40,7 +40,7 @@ module t (/*AUTOARG*/
`checkh(e.next(2), E01); `checkh(e.next(2), E01);
`checkh(e.next(1).next(1).next(1), E03); `checkh(e.next(1).next(1).next(1), E03);
`checkh(e.next(1).next(2), E03); `checkh(e.next(1).next(2), E03);
`checkh(e.next(3), E03); `checkh(e.next(THREE), E03);
`checkh(e.prev, E01); `checkh(e.prev, E01);
`checkh(e.prev(1), E01); `checkh(e.prev(1), E01);
`checkh(e.prev(1).prev(1), E04); `checkh(e.prev(1).prev(1), E04);
@ -57,6 +57,8 @@ module t (/*AUTOARG*/
`checks(all, "E01E03E04"); `checks(all, "E01E03E04");
end end
localparam THREE = 3;
// Check runtime // Check runtime
always @ (posedge clk) begin always @ (posedge clk) begin
cyc <= cyc + 1; cyc <= cyc + 1;

View File

@ -1,5 +1,6 @@
%Error: Internal Error: t/t_enum_type_methods_bad.v:24:14: ../V3Width.cpp:#: Unsupported: enum next/prev with non-const argument %Error-UNSUPPORTED: t/t_enum_type_methods_bad.v:24:14: Unsupported: enum next/prev with non-constant argument
: ... note: In instance 't' : ... note: In instance 't'
24 | e.next(increment); 24 | e.next(increment);
| ^~~~~~~~~ | ^~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. ... 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