diff --git a/Changes b/Changes index eba22c063..12858d5d7 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,7 @@ Verilator 5.037 devel * Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu] * Fix filename backslash escapes in C code (#5947). * Fix sign extension of signed compared with unsigned case items (#5968). +* Fix constant propagation making upper bits Xs (#5969). Verilator 5.036 2025-04-27 diff --git a/src/V3Number.cpp b/src/V3Number.cpp index a324e0644..3161a5b52 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -516,6 +516,12 @@ V3Number& V3Number::setValue1() { return *this; } +void V3Number::setBitX0(int bit) { + // Selection beyond bounds after V3Premit needs to have 0s + // in upper bits. Contrast to setAllBitsXRemoved which honors xAssign + setBit(bit, v3Global.constRemoveXs() ? 0 : 'x'); +} + V3Number& V3Number::setMask(int nbits, int lsb) { setZero(); for (int bit = lsb; bit < lsb + nbits; bit++) setBit(bit, 1); @@ -2324,7 +2330,7 @@ V3Number& V3Number::opSel(const V3Number& lhs, uint32_t msbval, uint32_t lsbval) if (ibit >= 0 && ibit < lhs.width() && ibit <= static_cast(msbval)) { setBit(bit, lhs.bitIs(ibit)); } else { - setBit(bit, 'x'); + setBitX0(bit); } ++ibit; } @@ -2345,7 +2351,7 @@ V3Number& V3Number::opSelInto(const V3Number& lhs, int lsbval, int width) { if (ibit >= 0 && ibit < lhs.width()) { setBit(bit, lhs.bitIs(ibit)); } else { - setBit(bit, 'x'); + setBitX0(bit); } ibit++; } diff --git a/src/V3Number.h b/src/V3Number.h index 3b46b2e05..231dd6ccd 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -356,6 +356,7 @@ public: V3Number& setLong(uint32_t value); V3Number& setLongS(int32_t value); V3Number& setDouble(double value); + void setBitX0(int bit); void setBit(int bit, char value) { // Note: must be initialized as number and pre-zeroed! if (bit >= m_data.width()) return; const uint32_t mask = (1UL << (bit & 31)); @@ -654,8 +655,7 @@ public: uint32_t countBits(const V3Number& ctrl) const; uint32_t countBits(const V3Number& ctrl1, const V3Number& ctrl2, const V3Number& ctrl3) const; uint32_t countOnes() const; - uint32_t - mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0. + uint32_t mostSetBitP1() const; // Highest bit set + 1, e.g. for 16 return 5, for 0 return 0 // Operators bool operator<(const V3Number& rhs) const { return isLtXZ(rhs); } diff --git a/test_regress/t/t_select_c.py b/test_regress/t/t_select_c.py new file mode 100755 index 000000000..8a08e98cd --- /dev/null +++ b/test_regress/t/t_select_c.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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_st') + +test.compile(verilator_flags2=['--binary --fno-expand']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_select_c.v b/test_regress/t/t_select_c.v new file mode 100644 index 000000000..c4ae30a64 --- /dev/null +++ b/test_regress/t/t_select_c.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + // verilator lint_off WIDTH + // verilator lint_off IMPLICIT + wire [22:0] w274; + wire w412; + wire w413; + wire w509; + + assign w104 = ! w509; + assign w201 = w258 > 12'hab7; + assign w204 = 7'h7f <= w104; + wire [11:0] w258 = 3'h3 || w274; + assign w538 = w412 ? out21 : w201; + wire [16:0] w539 = w413 ? w538 : 17'h00570; + wire [21:5] out21 = w204; + assign out51 = w539[0]; + + initial begin + $display("%0d", out51); + end +endmodule