Support enum.next with a parameter
This commit is contained in:
parent
36c4a24661
commit
7126293086
|
|
@ -3550,38 +3550,43 @@ 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");
|
||||||
const uint32_t stepWidth = VN_AS(stepp, Const)->toUInt();
|
AstNodeExpr* const newp = new AstConst{stepp->fileline(), 1};
|
||||||
if (stepWidth == 0) {
|
stepp->replaceWith(newp);
|
||||||
// Step of 0 "legalizes" like $cast, use .next.prev
|
stepp = newp;
|
||||||
AstMethodCall* const newp = new AstMethodCall{
|
}
|
||||||
nodep->fileline(),
|
const uint32_t stepWidth = VN_AS(stepp, Const)->toUInt();
|
||||||
new AstMethodCall{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
if (stepWidth == 0) {
|
||||||
"next", nullptr},
|
// Step of 0 "legalizes" like $cast, use .next.prev
|
||||||
"prev", nullptr};
|
AstMethodCall* const newp = new AstMethodCall{
|
||||||
// No dtype assigned, we will recurse the new method and replace
|
nodep->fileline(),
|
||||||
nodep->replaceWith(newp);
|
new AstMethodCall{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
"next", nullptr},
|
||||||
return;
|
"prev", nullptr};
|
||||||
} else if (stepWidth != 1) {
|
// No dtype assigned, we will recurse the new method and replace
|
||||||
// Unroll of enumVar.next(k) to enumVar.next(1).next(k - 1)
|
nodep->replaceWith(newp);
|
||||||
nodep->pinsp()->unlinkFrBack();
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
AstMethodCall* const clonep = nodep->cloneTree(false);
|
return;
|
||||||
VN_AS(stepp, Const)->num().setLong(1);
|
} else if (stepWidth != 1) {
|
||||||
AstConst* const constp = new AstConst(nodep->fileline(), stepWidth - 1);
|
// Unroll of enumVar.next(k) to enumVar.next(1).next(k - 1)
|
||||||
AstArg* const argp = new AstArg{nodep->fileline(), "", constp};
|
nodep->pinsp()->unlinkFrBack();
|
||||||
AstMethodCall* const newp
|
AstMethodCall* const clonep = nodep->cloneTree(false);
|
||||||
= new AstMethodCall{nodep->fileline(), clonep, nodep->name(), argp};
|
VN_AS(stepp, Const)->num().setLong(1);
|
||||||
// No dtype assigned, we will recurse the new method and replace
|
AstConst* const constp = new AstConst(nodep->fileline(), stepWidth - 1);
|
||||||
nodep->replaceWith(newp);
|
AstArg* const argp = new AstArg{nodep->fileline(), "", constp};
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
AstMethodCall* const newp
|
||||||
return;
|
= new AstMethodCall{nodep->fileline(), clonep, nodep->name(), argp};
|
||||||
}
|
// No dtype assigned, we will recurse the new method and replace
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AstNodeExpr* const newp
|
AstNodeExpr* const newp
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Reference in New Issue