From 0f528d136d0e9ba10867154e1ed49eb3cf7eed25 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 10 May 2025 13:59:56 -0400 Subject: [PATCH] Fix arithmetic right-shift by constants over 32 bits (#5994). --- Changes | 1 + src/V3Number.cpp | 24 +++++++++--------------- test_regress/t/t_math_shiftrs2.py | 18 ++++++++++++++++++ test_regress/t/t_math_shiftrs2.v | 22 ++++++++++++++++++++++ 4 files changed, 50 insertions(+), 15 deletions(-) create mode 100755 test_regress/t/t_math_shiftrs2.py create mode 100644 test_regress/t/t_math_shiftrs2.v diff --git a/Changes b/Changes index ccf94390d..068b67749 100644 --- a/Changes +++ b/Changes @@ -26,6 +26,7 @@ Verilator 5.037 devel * Fix inconsistent assignment error with split-var (#5984) (#5988). [Yutetsu TAKATSUKASA] * Fix AstAssignW conversion (#5991) (#5992). [Ryszard Rozak, Antmicro Ltd.] * Fix const-bit-op-tree with single-bit masks (#5993) (#5998). [Yutetsu TAKATSUKASA] +* Fix arithmetic right-shift by constants over 32 bits (#5994). Verilator 5.036 2025-04-27 diff --git a/src/V3Number.cpp b/src/V3Number.cpp index f0280076c..13a1984fb 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -1853,23 +1853,17 @@ V3Number& V3Number::opShiftRS(const V3Number& lhs, const V3Number& rhs, uint32_t NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); if (rhs.isFourState()) return setAllBitsX(); setZero(); - for (int bit = 32; bit < rhs.width(); ++bit) { - for (int sbit = 0; sbit < width(); ++sbit) { - setBit(sbit, lhs.bitIs(lbits - 1)); // 0/1/X/Z - } - if (rhs.bitIs1(lbits - 1)) setAllBits1(); // -1 else 0 - return *this; // shift of over 2^32 must be -1/0 - } - const uint32_t rhsval = rhs.toUInt(); - if (rhsval < static_cast(lhs.width())) { - for (int bit = 0; bit < width(); ++bit) { - setBit(bit, lhs.bitIsExtend(bit + rhsval, lbits)); - } - } else { - for (int bit = 0; bit < width(); ++bit) { - setBit(bit, lhs.bitIs(lbits - 1)); // 0/1/X/Z + const bool overflow = rhs.width() > 32 && !rhs.isBitsZero(rhs.width() - 1, 32); + if (!overflow) { + const uint32_t rhsval = rhs.toUInt(); + if (rhsval < static_cast(lhs.width())) { + for (int bit = 0; bit < width(); ++bit) { + setBit(bit, lhs.bitIsExtend(bit + rhsval, lbits)); + } + return *this; } } + for (int bit = 0; bit < width(); ++bit) setBit(bit, lhs.bitIs(lbits - 1)); // '0/'1/'x/'z return *this; } diff --git a/test_regress/t/t_math_shiftrs2.py b/test_regress/t/t_math_shiftrs2.py new file mode 100755 index 000000000..bd059b0f2 --- /dev/null +++ b/test_regress/t/t_math_shiftrs2.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') + +test.compile(verilator_flags2=['--binary']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_math_shiftrs2.v b/test_regress/t/t_math_shiftrs2.v new file mode 100644 index 000000000..541902b6b --- /dev/null +++ b/test_regress/t/t_math_shiftrs2.v @@ -0,0 +1,22 @@ +// 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 + +`define stop $stop +`define checkd(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__, `__LINE__, (gotv), (expv)); `stop; end while(0); + +module top(out35); + output wire [2:0] out35; + wire signed [2:0] wire_4; + assign wire_4 = 3'b011; + assign out35 = (wire_4 >>> 36'hffff_ffff_f); + + initial begin + #10; + `checkd(out35, '0); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule