diff --git a/src/V3Width.cpp b/src/V3Width.cpp index bb91fc3c6..59c64c97a 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2670,33 +2670,37 @@ class WidthVisitor final : public VNVisitor { } AstBasicDType* dtype = VN_CAST(nodep->exprp()->dtypep(), BasicDType); - AstNodeDType* subDTypep = nullptr; + AstNodeDType* expDTypep = nullptr; if (dtype && dtype->isString()) { nodep->dtypeSetString(); - subDTypep = nodep->findStringDType(); + expDTypep = nodep->findStringDType(); } else if (dtype && dtype->isDouble()) { nodep->dtypeSetDouble(); - subDTypep = nodep->findDoubleDType(); + expDTypep = nodep->findDoubleDType(); } else { // Take width as maximum across all items int width = nodep->exprp()->width(); int mwidth = nodep->exprp()->widthMin(); + bool isFourstate = nodep->exprp()->dtypep()->isFourstate(); for (const AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) { width = std::max(width, itemp->width()); mwidth = std::max(mwidth, itemp->widthMin()); + isFourstate |= itemp->dtypep()->isFourstate(); } nodep->dtypeSetBit(); - subDTypep = nodep->findLogicDType(width, mwidth, nodep->exprp()->dtypep()->numeric()); + const VSigning numeric = nodep->exprp()->dtypep()->numeric(); + expDTypep = isFourstate ? nodep->findLogicDType(width, mwidth, numeric) + : nodep->findBitDType(width, mwidth, numeric); } - iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT_DET, FINAL, subDTypep, + iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT_DET, FINAL, expDTypep, EXTEND_EXP); for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // iterate may cause the node to get replaced // InsideRange will get replaced with Lte&Gte and finalized later if (!VN_IS(itemp, InsideRange)) - iterateCheck(nodep, "Inside Item", itemp, CONTEXT_DET, FINAL, subDTypep, + iterateCheck(nodep, "Inside Item", itemp, CONTEXT_DET, FINAL, expDTypep, EXTEND_EXP); } diff --git a/test_regress/t/t_inside_extend.py b/test_regress/t/t_inside_extend.py new file mode 100755 index 000000000..78d425f95 --- /dev/null +++ b/test_regress/t/t_inside_extend.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=["-Wno-WIDTH"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_inside_extend.v b/test_regress/t/t_inside_extend.v new file mode 100644 index 000000000..e388cdb58 --- /dev/null +++ b/test_regress/t/t_inside_extend.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +typedef enum bit [4:0] {V0 = 1} my_enum; +class Cls; + my_enum sp = V0; +endclass + +module t (/*AUTOARG*/); + initial begin + Cls c = new; + int i = 0; + if (i inside {c.sp}) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule