Support enum.next(k) with constant k > 1, #2125.

This commit is contained in:
Tobias Rosenkranz 2020-01-27 17:25:25 -05:00 committed by Wilson Snyder
parent 9fd81b2c6b
commit 027cce35c0
6 changed files with 80 additions and 10 deletions

View File

@ -21,6 +21,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Support string character access via indexing.
**** Support enum.next(k) with constant k > 1, #2125. [Tobias Rosenkranz]
**** Add parameter values in XML. #2110. [Pieter Kapsenberg]
**** Add loc column location in XML (replaces fl), #2122. [Pieter Kapsenberg]

View File

@ -1930,11 +1930,24 @@ private:
if (nodep->name() == "name") {
methodOkArguments(nodep, 0, 0);
} else if (nodep->pinsp()
&& !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const))) {
nodep->pinsp()->v3fatalSrc("Unsupported: enum next/prev with non-const argument");
} else if (nodep->pinsp()
&& !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)
&& VN_CAST(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)->toUInt() == 1
&& !nodep->pinsp()->nextp())) {
nodep->v3error("Unsupported: Arguments passed to enum.next method");
// Unroll of enumVar.next(k) to enumVar.next(1).next(k - 1)
AstMethodCall* clonep = nodep->cloneTree(false);
VN_CAST(VN_CAST(clonep->pinsp(), Arg)->exprp(), Const)->num().setLong(1);
uint32_t stepWidth = VN_CAST(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)->toUInt();
AstConst* constp = new AstConst(nodep->fileline(), stepWidth - 1);
AstArg* argp = new AstArg(nodep->fileline(), "", constp);
AstMethodCall* newp = new AstMethodCall(nodep->fileline(), clonep,
nodep->name(), argp);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;
}
// Need a runtime lookup table. Yuk.
// Most enums unless overridden are 32 bits, so we size array
@ -1951,7 +1964,7 @@ private:
if (vconstp->toUQuad() >= msbdim) msbdim = vconstp->toUQuad();
}
if (adtypep->itemsp()->width() > 64 || msbdim >= (1 << 16)) {
nodep->v3error("Unsupported; enum next/prev method on enum with > 10 bits");
nodep->v3error("Unsupported: enum next/prev method on enum with > 10 bits");
return;
}
}

View File

@ -34,10 +34,15 @@ module t (/*AUTOARG*/
`checkh(e.next, E04);
`checkh(e.next(), E04);
`checkh(e.next(1), E04);
//Unsup: `checkh(e.next(2), E01);
`checkh(e.next(1).next(1), E01);
`checkh(e.next(2), E01);
`checkh(e.next(1).next(1).next(1), E03);
`checkh(e.next(1).next(2), E03);
`checkh(e.next(3), E03);
`checkh(e.prev, E01);
`checkh(e.prev(1), E01);
//Unsup: `checkh(e.prev(2), E04);
`checkh(e.prev(1).prev(1), E04);
`checkh(e.prev(2), E04);
`checkh(e.num, 3);
`checks(e.name, "E03");
//
@ -61,30 +66,30 @@ module t (/*AUTOARG*/
`checks(e.name, "E01");
`checkh(e.next, E03);
`checkh(e.next(1), E03);
//Unsup: `checkh(e.next(2), E04);
`checkh(e.next(2), E04);
`checkh(e.prev, E04);
`checkh(e.prev(1), E04);
//Unsup: `checkh(e.prev(2), E03);
`checkh(e.prev(2), E03);
e <= E03;
end
else if (cyc==2) begin
`checks(e.name, "E03");
`checkh(e.next, E04);
`checkh(e.next(1), E04);
//Unsup: `checkh(e.next(2), E01);
`checkh(e.next(2), E01);
`checkh(e.prev, E01);
`checkh(e.prev(1), E01);
//Unsup: `checkh(e.prev(2), E04);
`checkh(e.prev(2), E04);
e <= E04;
end
else if (cyc==3) begin
`checks(e.name, "E04");
`checkh(e.next, E01);
`checkh(e.next(1), E01);
//Unsup: `checkh(e.next(2), E03);
`checkh(e.next(2), E03);
`checkh(e.prev, E03);
`checkh(e.prev(1), E03);
//Unsup: `checkh(e.prev(2), E01);
`checkh(e.prev(2), E01);
e <= E01;
end
else if (cyc==99) begin

View File

@ -0,0 +1,5 @@
%Error: Internal Error: t/t_enum_type_methods_bad.v:23: ../V3Width.cpp:#: Unsupported: enum next/prev with non-const argument
: ... In instance t
e.next(increment);
^~~~~~~~~
... See the manual and https://verilator.org for more assistance.

View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
fails => 1,
expect_filename => $Self->{golden_filename}
);
ok(1);
1;

View File

@ -0,0 +1,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk, increment
);
input clk;
input [1:0] increment;
typedef enum [3:0] {
E01 = 1,
E03 = 3,
E04 = 4,
E05 = 5
} my_t;
my_t e;
always @ (posedge clk) begin
e.next(increment);
$finish;
end
endmodule