From 09dff9c3a785b5f27f900fad8d0c9bef296798d8 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 19 Nov 2022 13:30:23 -0500 Subject: [PATCH] Fix false ENUMVALUE errors in unstable branch (#3761) --- src/V3Width.cpp | 13 +++++++++- src/V3WidthCommit.h | 2 ++ test_regress/t/t_enum_type_bad.out | 6 ++--- test_regress/t/t_enum_value_assign.pl | 21 +++++++++++++++++ test_regress/t/t_enum_value_assign.v | 34 +++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100755 test_regress/t/t_enum_value_assign.pl create mode 100644 test_regress/t/t_enum_value_assign.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 3654b48f4..246c02cad 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1841,9 +1841,12 @@ private: } } void visit(AstCast* nodep) override { + if (nodep->didWidth()) return; + UINFO(9, "CAST " << nodep << endl); nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); if (m_vup->prelim()) { // if (debug()) nodep->dumpTree(cout, " CastPre: "); + // if (debug()) nodep->backp()->dumpTree(cout, " CastPreUpUp: "); userIterateAndNext(nodep->fromp(), WidthVP(SELF, PRELIM).p()); AstNodeDType* const toDtp = nodep->dtypep()->skipRefToEnump(); AstNodeDType* const fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); @@ -1878,8 +1881,10 @@ private: if (bad) { } else if (const AstBasicDType* const basicp = toDtp->basicp()) { if (!basicp->isDouble() && !fromDtp->isDouble()) { + AstNodeDType* const origDTypep = nodep->dtypep(); const int width = toDtp->width(); castSized(nodep, nodep->fromp(), width); + nodep->dtypeFrom(origDTypep); // If was enum, need dtype to preserve as enum // Note castSized might modify nodep->fromp() } else { iterateCheck(nodep, "value", nodep->fromp(), SELF, FINAL, fromDtp, EXTEND_EXP, @@ -1924,8 +1929,10 @@ private: EXTEND_EXP, false); AstNode* const underp = nodep->fromp()->unlinkFrBack(); // if (debug()) underp->dumpTree(cout, " CastRep: "); + underp->dtypeFrom(nodep); nodep->replaceWith(underp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + underp->didWidth(true); } } void visit(AstCastSize* nodep) override { @@ -2217,6 +2224,9 @@ private: // and if we keep minwidth we'll consider it unsized which is incorrect iterateCheck(nodep, "Enum value", nodep->valuep(), CONTEXT_DET, FINAL, nodep->dtypep(), EXTEND_EXP); + // Always create a cast, to avoid later ENUMVALUE warnings + nodep->valuep(new AstCast{nodep->valuep()->fileline(), nodep->valuep()->unlinkFrBack(), + nodep->dtypep()}); } } void visit(AstEnumItemRef* nodep) override { @@ -6139,12 +6149,13 @@ private: if (castable != COMPATIBLE && castable != ENUM_IMPLICIT && !VN_IS(underp, Cast) && !VN_IS(underp, CastDynamic) && !m_enumItemp && warnOn) { nodep->v3warn(ENUMVALUE, - "Illegal implicit conversion to enum " + "Implicit conversion to enum " << expDTypep->prettyDTypeNameQ() << " from " << underp->dtypep()->prettyDTypeNameQ() << " (IEEE 1800-2017 6.19.3)\n" << nodep->warnMore() << "... Suggest use enum's mnemonic, or static cast"); + if (debug()) nodep->backp()->dumpTree(cout, "- back: "); } } AstNodeDType* subDTypep = expDTypep; diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index c3823b2a4..39e1ad8c5 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -85,6 +85,7 @@ public: num.isSigned(nodep->isSigned()); AstConst* const newp = new AstConst{nodep->fileline(), num}; newp->dtypeFrom(nodep); + newp->user1(true); return newp; } else { return nullptr; @@ -163,6 +164,7 @@ private: } } void visit(AstConst* nodep) override { + if (nodep->user1SetOnce()) return; // Process once UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); iterate(nodep->dtypep()); // Do datatype first if (AstConst* const newp = newIfConstCommitSize(nodep)) { diff --git a/test_regress/t/t_enum_type_bad.out b/test_regress/t/t_enum_type_bad.out index 26fe75f83..2d782732e 100644 --- a/test_regress/t/t_enum_type_bad.out +++ b/test_regress/t/t_enum_type_bad.out @@ -1,15 +1,15 @@ -%Error-ENUMVALUE: t/t_enum_type_bad.v:28:9: Illegal implicit conversion to enum 't.e_t' from 'logic[31:0]' (IEEE 1800-2017 6.19.3) +%Error-ENUMVALUE: t/t_enum_type_bad.v:28:9: Implicit conversion to enum 't.e_t' from 'logic[31:0]' (IEEE 1800-2017 6.19.3) : ... In instance t : ... Suggest use enum's mnemonic, or static cast 28 | e = 1; | ^ ... For error description see https://verilator.org/warn/ENUMVALUE?v=latest -%Error-ENUMVALUE: t/t_enum_type_bad.v:29:9: Illegal implicit conversion to enum 't.o_t' from 't.e_t' (IEEE 1800-2017 6.19.3) +%Error-ENUMVALUE: t/t_enum_type_bad.v:29:9: Implicit conversion to enum 't.o_t' from 't.e_t' (IEEE 1800-2017 6.19.3) : ... In instance t : ... Suggest use enum's mnemonic, or static cast 29 | o = e; | ^ -%Error-ENUMVALUE: t/t_enum_type_bad.v:35:9: Illegal implicit conversion to enum 't.o_t' from 'ENUMDTYPE 't.e_t'' (IEEE 1800-2017 6.19.3) +%Error-ENUMVALUE: t/t_enum_type_bad.v:35:9: Implicit conversion to enum 't.o_t' from 'ENUMDTYPE 't.e_t'' (IEEE 1800-2017 6.19.3) : ... In instance t : ... Suggest use enum's mnemonic, or static cast 35 | o = str.m_e; diff --git a/test_regress/t/t_enum_value_assign.pl b/test_regress/t/t_enum_value_assign.pl new file mode 100755 index 000000000..1aa73f80a --- /dev/null +++ b/test_regress/t/t_enum_value_assign.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_enum_value_assign.v b/test_regress/t/t_enum_value_assign.v new file mode 100644 index 000000000..28e55cf02 --- /dev/null +++ b/test_regress/t/t_enum_value_assign.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + + localparam logic [9:0] V2 = (1 << 2); + localparam logic [9:0] V1 = (1 << 1); + localparam logic [9:0] V0 = (1 << 0); + typedef enum logic [9:0] { + ZERO = '0, + VAL0 = V0, + VAL1 = V1, + VAL01 = V0 | V1 + } enum_t; + + localparam enum_t PARAMVAL1 = VAL1; + localparam enum_t PARAMVAL1CONST = enum_t'(2); + + initial begin + enum_t e; + e = VAL01; + if (e != VAL01) $stop; + + if (PARAMVAL1 != VAL1) $stop; + if (PARAMVAL1CONST != VAL1) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule