diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 04ea33435..3ce2f1087 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -125,6 +125,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { void updateBitRange(const AstShiftR* shiftp) { m_lsb += VN_AS(shiftp->rhsp(), Const)->toUInt(); } + void limitBitRangeToLsb() { m_msb = std::min(m_msb, m_lsb); } int wordIdx() const { return m_wordIdx; } void wordIdx(int i) { m_wordIdx = i; } bool polarity() const { return m_polarity; } @@ -538,6 +539,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { Restorer restorer{*this}; incrOps(nodep, __LINE__); iterateConst(nodep->rhsp()); + if (m_leafp) m_leafp->limitBitRangeToLsb(); CONST_BITOP_RETURN_IF(m_failed, nodep->rhsp()); restorer.disableRestore(); // Now all checks passed } else if (nodep->type() == m_rootp->type()) { // And, Or, Xor diff --git a/test_regress/t/t_opt_const.v b/test_regress/t/t_opt_const.v index 5abf755f1..970774fe3 100644 --- a/test_regress/t/t_opt_const.v +++ b/test_regress/t/t_opt_const.v @@ -153,6 +153,7 @@ module Test(/*AUTOARG*/ bug4857 i_bug4857(.clk(clk), .in(d), .out(bug4857_out)); bug4864 i_bug4864(.clk(clk), .in(d), .out(bug4864_out)); bug5186 i_bug5186(.clk(clk), .in(d), .out(bug5186_out)); + bug5993 i_bug5993(.clk(clk), .in(d[10])); endmodule @@ -566,3 +567,30 @@ module bug5186(input wire clk, input wire [31:0] in, output out); result <= bad; assign out = result; endmodule + + +// See issue #5993 +// "in4[18]" is just one bit width, so " >> 8'd1" shifts out the bit. +// BitOpTree ignored implicit "& 1". It caused the bug" +module bug5993(input wire clk, input wire in); + + reg in3; + reg [23:16] in4; + + task automatic checkd(logic gotv, logic expv); + if ((gotv) !== (expv)) begin + $write("%%Error: got=%0d exp=%0d\n", gotv, expv); + $stop; + end + endtask + + // verilator lint_off WIDTH + wire wire_2 = in3 ? {4{14'b010111101}} : (in4[18] >> 8'b1); + // verilator lint_on WIDTH + + always @(posedge clk) begin + in3 <= '0; + in4 <= in ? 8'b00111__0__10 : 8'b00111__1__10; + checkd(wire_2, 1'b0); + end +endmodule diff --git a/test_regress/t/t_opt_const_dfg.py b/test_regress/t/t_opt_const_dfg.py index ffdca2c4f..6fd2ea9bc 100755 --- a/test_regress/t/t_opt_const_dfg.py +++ b/test_regress/t/t_opt_const_dfg.py @@ -18,7 +18,7 @@ test.compile(verilator_flags2=["-Wno-UNOPTTHREADS", "--stats", test.pli_filename test.execute() if test.vlt: - test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 39) + test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 43) test.file_grep(test.stats, r'SplitVar, packed variables split automatically\s+(\d+)', 1) test.passes()