diff --git a/Changes b/Changes index 5af9a7e0c..3dad4084c 100644 --- a/Changes +++ b/Changes @@ -35,6 +35,7 @@ Verilator 5.019 devel * Fix trace when using SystemC with certain configurations (#4676). [Anthony Donlon] * Fix C++20 compilation errors (#4670). * Fix compilers seeing empty input due to file system races (#4708). [Flavien Solt] +* Fix shift of > 32-bit number (#4719). [Flavien Solt] * Fix 0**0 with wide numbers (#4721). [Flavien Solt] diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 83747bb31..37fe52981 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1221,13 +1221,16 @@ class ConstVisitor final : public VNVisitor { } bool operandHugeShiftL(const AstNodeBiop* nodep) { return (VN_IS(nodep->rhsp(), Const) && !VN_AS(nodep->rhsp(), Const)->num().isFourState() - && (VN_AS(nodep->rhsp(), Const)->toUInt() >= static_cast(nodep->width())) + && (!VN_AS(nodep->rhsp(), Const)->num().fitsInUInt() // > 2^32 shift + || (VN_AS(nodep->rhsp(), Const)->toUInt() + >= static_cast(nodep->width()))) && nodep->lhsp()->isPure()); } bool operandHugeShiftR(const AstNodeBiop* nodep) { return (VN_IS(nodep->rhsp(), Const) && !VN_AS(nodep->rhsp(), Const)->num().isFourState() - && (VN_AS(nodep->rhsp(), Const)->toUInt() - >= static_cast(nodep->lhsp()->width())) + && (!VN_AS(nodep->rhsp(), Const)->num().fitsInUInt() // > 2^32 shift + || (VN_AS(nodep->rhsp(), Const)->toUInt() + >= static_cast(nodep->lhsp()->width()))) && nodep->lhsp()->isPure()); } bool operandIsTwo(const AstNode* nodep) { diff --git a/src/V3Global.cpp b/src/V3Global.cpp index 3b1a3487c..35fec0f0a 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -54,7 +54,7 @@ void V3Global::readFiles() { if (v3Global.opt.std()) { parser.parseFile(new FileLine{V3Options::getStdPackagePath()}, V3Options::getStdPackagePath(), false, - "Cannot find verilated_std.sv containing built-in std:: definitions:"); + "Cannot find verilated_std.sv containing built-in std:: definitions: "); } // Read top module diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 91403a532..cc2afeb61 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -896,14 +896,20 @@ string V3Number::toDecimalU() const VL_MT_STABLE { //====================================================================== // ACCESSORS - as numbers +bool V3Number::fitsInUInt() const VL_MT_SAFE { + if (isFourState()) return false; + // We allow wide numbers that represent values <= 32 bits + for (int i = 1; i < words(); ++i) { + if (m_data.num()[i].m_value) return false; + } + return true; +} uint32_t V3Number::toUInt() const VL_MT_SAFE { UASSERT(!isFourState(), "toUInt with 4-state " << *this); // We allow wide numbers that represent values <= 32 bits - for (int i = 1; i < words(); ++i) { - if (m_data.num()[i].m_value) { - v3error("Value too wide for 32-bits expected in this context " << *this); - break; - } + if (VL_UNCOVERABLE(!fitsInUInt())) { + v3error("Value too wide for 32-bits expected in this context " // LCOV_EXCL_LINE + << *this); } return m_data.num()[0].m_value; } diff --git a/src/V3Number.h b/src/V3Number.h index acab8420e..e695f717d 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -638,6 +638,7 @@ public: bool isAnyXZ() const; bool isAnyZ() const VL_MT_SAFE; bool isMsbXZ() const { return bitIsXZ(m_data.width() - 1); } + bool fitsInUInt() const VL_MT_SAFE; uint32_t toUInt() const VL_MT_SAFE; int32_t toSInt() const VL_MT_SAFE; uint64_t toUQuad() const VL_MT_SAFE; diff --git a/test_regress/t/t_math_shift_over_bad.pl b/test_regress/t/t_math_shift_huge.pl similarity index 72% rename from test_regress/t/t_math_shift_over_bad.pl rename to test_regress/t/t_math_shift_huge.pl index 9c9fb65a0..8c2ca139b 100755 --- a/test_regress/t/t_math_shift_over_bad.pl +++ b/test_regress/t/t_math_shift_huge.pl @@ -2,17 +2,15 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } # DESCRIPTION: Verilator: Verilog Test driver/expect definition # -# Copyright 2010 by Wilson Snyder. This program is free software; you +# Copyright 2023 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(linter => 1); +scenarios(simulator => 1); -lint( - fails => 1, - expect_filename => $Self->{golden_filename}, +compile( ); ok(1); diff --git a/test_regress/t/t_math_shift_huge.v b/test_regress/t/t_math_shift_huge.v new file mode 100644 index 000000000..900bbc188 --- /dev/null +++ b/test_regress/t/t_math_shift_huge.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Outputs + outl, outr, + // Inputs + lhs + ); + input [95:0] lhs; + output [95:0] outl; + output [95:0] outr; + + assign outl = lhs << 95'hffff_00000000; + assign outr = lhs >> 95'hffff_00000000; + +endmodule diff --git a/test_regress/t/t_math_shift_over_bad.out b/test_regress/t/t_math_shift_over_bad.out deleted file mode 100644 index 09004172d..000000000 --- a/test_regress/t/t_math_shift_over_bad.out +++ /dev/null @@ -1,5 +0,0 @@ -%Error: t/t_math_shift_over_bad.v:19:20: Value too wide for 32-bits expected in this context 64'h123456789abcdef - : ... note: In instance 't' - 19 | assign o = i << 64'h01234567_89abcdef; - | ^~~~~~~~~~~~~~~~~~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_math_shift_over_bad.v b/test_regress/t/t_math_shift_over_bad.v deleted file mode 100644 index 3df5d7b74..000000000 --- a/test_regress/t/t_math_shift_over_bad.v +++ /dev/null @@ -1,21 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain, for -// any use, without warranty, 2016 by Wilson Snyder. -// SPDX-License-Identifier: CC0-1.0 - -module t (/*AUTOARG*/ - // Outputs - o, - // Inputs - clk, i - ); - - input clk; - - input [31:0] i; - output [31:0] o; - - assign o = i << 64'h01234567_89abcdef; - -endmodule