parent
0c8c7fb03c
commit
b26658fd96
|
@ -119,13 +119,25 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
m_constp = constp;
|
||||
m_msb = constp->widthMin() - 1;
|
||||
}
|
||||
// updateBitRange(), limitBitRangeToLsb(), and polarity() must be called during ascending
|
||||
// back to the root.
|
||||
void updateBitRange(int newLsb, int newMsb) {
|
||||
if ((m_lsb <= m_msb && newLsb > newMsb) || (m_lsb > m_msb && m_lsb < newLsb)) {
|
||||
// When the new bit range is out of m_refp, clear polarity because nodes below is
|
||||
// shifted out to zero.
|
||||
// This kind of clear may happen several times. e.g. (!(1'b1 >> 1)) >> 1
|
||||
polarity(true);
|
||||
}
|
||||
m_lsb = newLsb;
|
||||
m_msb = newMsb;
|
||||
}
|
||||
void updateBitRange(const AstCCast* castp) {
|
||||
m_msb = std::min(m_msb, m_lsb + castp->width() - 1);
|
||||
updateBitRange(m_lsb, std::min(m_msb, m_lsb + castp->width() - 1));
|
||||
}
|
||||
void updateBitRange(const AstShiftR* shiftp) {
|
||||
m_lsb += VN_AS(shiftp->rhsp(), Const)->toUInt();
|
||||
updateBitRange(m_lsb + VN_AS(shiftp->rhsp(), Const)->toUInt(), m_msb);
|
||||
}
|
||||
void limitBitRangeToLsb() { m_msb = std::min(m_msb, m_lsb); }
|
||||
void limitBitRangeToLsb() { updateBitRange(m_lsb, 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; }
|
||||
|
@ -467,6 +479,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
// Don't restore m_polarity for Xor as it counts parity of the entire tree
|
||||
if (!isXorTree()) m_polarity = !m_polarity;
|
||||
if (m_leafp && castp) m_leafp->updateBitRange(castp);
|
||||
if (m_leafp) m_leafp->polarity(!m_leafp->polarity());
|
||||
}
|
||||
void visit(AstWordSel* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
|
@ -479,7 +492,6 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
void visit(AstVarRef* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
m_leafp->setLeaf(nodep);
|
||||
m_leafp->polarity(m_polarity);
|
||||
}
|
||||
void visit(AstConst* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
|
|
|
@ -154,6 +154,7 @@ module Test(/*AUTOARG*/
|
|||
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]));
|
||||
bug6016 i_bug6016(.clk(clk), .in(d[10]));
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -593,4 +594,32 @@ module bug5993(input wire clk, input wire in);
|
|||
in4 <= in ? 8'b00111__0__10 : 8'b00111__1__10;
|
||||
checkd(wire_2, 1'b0);
|
||||
end
|
||||
endmodule
|
||||
|
||||
// See issue #6016
|
||||
// When traversing a tree, a signal may be shifted out.
|
||||
// Then the polarity has to be cleared, but was not.
|
||||
// "(!in[18]) > 1" should be 0, but was not.
|
||||
module bug6016(input wire clk, input wire in);
|
||||
reg in0;
|
||||
reg signed [7:0] in4;
|
||||
wire [1:0] wire_0;
|
||||
wire out20;
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
assign wire_0 = in4[0:0] ? ({{7{in4[3:1]}}, 12'd201} & 2'h2) : (!(in0) >> 9'b1111);
|
||||
// verilator lint_on WIDTH
|
||||
assign out20 = wire_0[0:0];
|
||||
|
||||
logic in_s1 = 1'b0;
|
||||
always @(posedge clk) begin
|
||||
in_s1 <= in;
|
||||
if (in) begin
|
||||
in4 <= 8'b1111_1110;
|
||||
in0 <= 1'b0;
|
||||
end
|
||||
if (in_s1) begin
|
||||
if (out20 != 1'b0) $stop;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
Loading…
Reference in New Issue