diff --git a/src/V3Const.cpp b/src/V3Const.cpp index e6ef5843e..522c0c3a6 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1892,6 +1892,8 @@ class ConstVisitor final : public VNVisitor { } void replaceShiftOp(AstNodeBiop* nodep) { UINFO(5, "SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) " << nodep << endl); + const int width = nodep->width(); + const int widthMin = nodep->widthMin(); VNRelinker handle; nodep->unlinkFrBack(&handle); AstNodeBiop* const lhsp = VN_AS(nodep->lhsp(), NodeBiop); @@ -1908,6 +1910,7 @@ class ConstVisitor final : public VNVisitor { AstNodeBiop* const newp = lhsp; newp->lhsp(shift1p); newp->rhsp(shift2p); + newp->dtypeChgWidth(width, widthMin); // The new AND must have width of the original SHIFT handle.relink(newp); iterate(newp); // Further reduce, either node may have more reductions. } diff --git a/test_regress/t/t_const_opt.v b/test_regress/t/t_const_opt.v index 37e7568bb..3151eb44d 100644 --- a/test_regress/t/t_const_opt.v +++ b/test_regress/t/t_const_opt.v @@ -62,7 +62,7 @@ module t(/*AUTOARG*/ $write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum); if (crc !== 64'hc77bb9b3784ea091) $stop; // What checksum will we end up with (above print should match) -`define EXPECTED_SUM 64'h7f4e4dade589ada1 +`define EXPECTED_SUM 64'hd1610f7181cbc1b4 if (sum !== `EXPECTED_SUM) $stop; $write("*-* All Finished *-*\n"); @@ -94,10 +94,11 @@ module Test(/*AUTOARG*/ logic bug3824_out; logic bug4059_out; logic bug4832_out; + logic bug4837_out; output logic o; - logic [15:0] tmp; + logic [16:0] tmp; assign o = ^tmp; always_ff @(posedge clk) begin @@ -129,6 +130,7 @@ module Test(/*AUTOARG*/ tmp[13]<= bug3824_out; tmp[14]<= bug4059_out; tmp[15]<= bug4832_out; + tmp[16]<= bug4837_out; end bug3182 i_bug3182(.in(d[4:0]), .out(bug3182_out)); @@ -141,6 +143,7 @@ module Test(/*AUTOARG*/ bug3824 i_bug3824(.clk(clk), .in(d), .out(bug3824_out)); bug4059 i_bug4059(.clk(clk), .in(d), .out(bug4059_out)); bug4832 i_bug4832(.clk(clk), .in(d), .out(bug4832_out)); + bug4837 i_bug4837(.clk(clk), .in(d), .out(bug4837_out)); endmodule @@ -422,3 +425,28 @@ module bug4832(input wire clk, input wire [31:0] in, output out); end assign out = result_and ^ result_or; endmodule + +/// See issue #4837 and $4841 +// replaceShiftOp() in V3Const did not update widthMin, then bit-op-tree opt. +// was wrongly triggered for the subtree. +// replaceShiftOp() transforms as below: +// SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) +// AND after the transformation must have same minWidth as the original SHIFT +// e.g. SHIFTL(AND(a, b), 1) => AND(SHIFTL(a, 1), SHIFTL(b, 1)) +// AND in the result must have 1 bit larger widthMin than the original AND +module bug4837(input wire clk, input wire [31:0] in, output out); + logic [95:0] d; + always_ff @(posedge clk) + d <= {d[63:0], in}; + + wire celloutsig_0z; + wire [1:0] celloutsig_1z; + wire celloutsig_2z; + wire [95:0] out_data; + assign celloutsig_0z = d[83] < d[74]; + assign celloutsig_1z = { d[54], celloutsig_0z } & { d[42], celloutsig_0z }; + assign celloutsig_2z = d[65:64] < d[83:82]; + assign { out_data[33:32], out_data[0] } = { celloutsig_1z, celloutsig_2z }; + + assign out = out_data[33] ^ out_data[32] ^ out_data[0]; +endmodule