8000 Fix wrong optimization result of shifted out variable (#6016) (#6019) · verilator/verilator@b26658f · GitHub
[go: up one dir, main page]

Skip to content

Commit b26658f

Browse files
authored
Fix wrong optimization result of shifted out variable (#6016) (#6019)
1 parent 0c8c7fb commit b26658f

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/V3Const.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,25 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
119119
m_constp = constp;
120120
m_msb = constp->widthMin() - 1;
121121
}
122+
// updateBitRange(), limitBitRangeToLsb(), and polarity() must be called during ascending
123+
// back to the root.
124+
void updateBitRange(int newLsb, int newMsb) {
125+
if ((m_lsb <= m_msb && newLsb > newMsb) || (m_lsb > m_msb && m_lsb < newLsb)) {
126+
// When the new bit range is out of m_refp, clear polarity because nodes below is
127+
// shifted out to zero.
128+
// This kind of clear may happen several times. e.g. (!(1'b1 >> 1)) >> 1
129+
polarity(true);
130+
}
131+
m_lsb = newLsb;
132+
m_msb = newMsb;
133+
}
122134
void updateBitRange(const AstCCast* castp) {
123-
m_msb = std::min(m_msb, m_lsb + castp->width() - 1);
135+
updateBitRange(m_lsb, std::min(m_msb, m_lsb + castp->width() - 1));
124136
}
125137
void updateBitRange(const AstShiftR* shiftp) {
126-
m_lsb += VN_AS(shiftp->rhsp(), Const)->toUInt();
138+
updateBitRange(m_lsb + VN_AS(shiftp->rhsp(), Const)->toUInt(), m_msb);
127139
}
128-
void limitBitRangeToLsb() { m_msb = std::min(m_msb, m_lsb); }
140+
void limitBitRangeToLsb() { updateBitRange(m_lsb, std::min(m_msb, m_lsb)); }
129141
int wordIdx() const { return m_wordIdx; }
130142
void wordIdx(int i) { m_wordIdx = i; }
131143
bool polarity() const { return m_polarity; }
@@ -467,6 +479,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
467479
// Don't restore m_polarity for Xor as it counts parity of the entire tree
468480
if (!isXorTree()) m_polarity = !m_polarity;
469481
if (m_leafp && castp) m_leafp->updateBitRange(castp);
482+
if (m_leafp) m_leafp->polarity(!m_leafp->polarity());
470483
}
471484
void visit(AstWordSel* nodep) override {
472485
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
@@ -479,7 +492,6 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
479492
void visit(AstVarRef* nodep) override {
480493
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
481494
m_leafp->setLeaf(nodep);
482-
m_leafp->polarity(m_polarity);
483495
}
484496
void visit(AstConst* nodep) override {
485497
CONST_BITOP_RETURN_IF(!m_leafp, nodep);

test_regress/t/t_opt_const.v

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ module Test(/*AUTOARG*/
154154
bug4864 i_bug4864(.clk(clk), .in(d), .out(bug4864_out));
155155
bug5186 i_bug5186(.clk(clk), .in(d), .out(bug5186_out));
156156
bug5993 i_bug5993(.clk(clk), .in(d[10]));
157+
bug6016 i_bug6016(.clk(clk), .in(d[10]));
157158

158159
endmodule
159160

@@ -593,4 +594,32 @@ module bug5993(input wire clk, input wire in);
593594
in4 <= in ? 8'b00111__0__10 : 8'b00111__1__10;
594595
checkd(wire_2, 1'b0);
595596
end
597+
endmodule
598+
599+
// See issue #6016
600+
// When traversing a tree, a signal may be shifted out.
601+
// Then the polarity has to be cleared, but was not.
602+
// "(!in[18]) > 1" should be 0, but was not.
603+
module bug6016(input wire clk, input wire in);
604+
reg in0;
605+
reg signed [7:0] in4;
606+
wire [1:0] wire_0;
607+
wire out20;
608+
609+
// verilator lint_off WIDTH
610+
assign wire_0 = in4[0:0] ? ({{7{in4[3:1]}}, 12'd201} & 2'h2) : (!(in0) >> 9'b1111);
611+
// verilator lint_on WIDTH
612+
assign out20 = wire_0[0:0];
613+
614+
logic in_s1 = 1'b0;
615+
always @(posedge clk) begin
616+
in_s1 <= in;
617+
if (in) begin
618+
in4 <= 8'b1111_1110;
619+
in0 <= 1'b0;
620+
end
621+
if (in_s1) begin
622+
if (out20 != 1'b0) $stop;
623+
end
624+
end
596625
endmodule

0 commit comments

Comments
 (0)
0