diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a8bc3140f..2ffe7a706 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1452,6 +1452,8 @@ private: if (!itemp->valuep()) { if (num.isEqZero() && itemp != nodep->itemsp()) itemp->v3error("Enum value illegally wrapped around (IEEE 2017 6.19)"); + if (num.isFourState()) + itemp->v3error("Enum value that is unassigned cannot follow value with X/Zs (IEEE 2017 6.19)"); if (!nodep->dtypep()->basicp() && !nodep->dtypep()->basicp()->keyword().isIntNumeric()) { itemp->v3error("Enum names without values only allowed on numeric types"); @@ -1459,7 +1461,12 @@ private: } itemp->valuep(new AstConst(itemp->fileline(), num)); } - num.opAssign(VN_CAST(itemp->valuep(), Const)->num()); + + AstConst* constp = VN_CAST(itemp->valuep(), Const); + if (constp->num().isFourState() && nodep->dtypep()->basicp() + && !nodep->dtypep()->basicp()->isFourstate()) + itemp->v3error("Enum value with X/Zs cannot be assigned to non-fourstate type (IEEE 2019 6.19)"); + num.opAssign(constp->num()); // Look for duplicates if (inits.find(num) != inits.end()) { // IEEE says illegal AstNode* otherp = inits.find(num)->second; @@ -1471,7 +1478,7 @@ private: } else { inits.insert(make_pair(num, itemp)); } - num.opAdd(one, VN_CAST(itemp->valuep(), Const)->num()); + num.opAdd(one, constp->num()); } } virtual void visit(AstEnumItem* nodep) { diff --git a/test_regress/t/t_enum_x_bad.out b/test_regress/t/t_enum_x_bad.out new file mode 100644 index 000000000..6677ff6dc --- /dev/null +++ b/test_regress/t/t_enum_x_bad.out @@ -0,0 +1,9 @@ +%Error: t/t_enum_x_bad.v:8: Enum value with X/Zs cannot be assigned to non-fourstate type (IEEE 2019 6.19) + : ... In instance t + enum bit [1:0] { BADX = 2'b1x } BAD1; + ^~~~ +%Error: t/t_enum_x_bad.v:11: Enum value that is unassigned cannot follow value with X/Zs (IEEE 2017 6.19) + : ... In instance t + e1 + ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_enum_x_bad.pl b/test_regress/t/t_enum_x_bad.pl new file mode 100755 index 000000000..573f98f12 --- /dev/null +++ b/test_regress/t/t_enum_x_bad.pl @@ -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 2008 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(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_enum_x_bad.v b/test_regress/t/t_enum_x_bad.v new file mode 100644 index 000000000..876ef29d5 --- /dev/null +++ b/test_regress/t/t_enum_x_bad.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2009 by Wilson Snyder. + +module t (/*AUTOARG*/); + + enum bit [1:0] { BADX = 2'b1x } BAD1; + + enum logic [3:0] { e0 = 4'b1xx1, + e1 + } BAD2; + + initial begin + $stop; + end + +endmodule