Fix assertion failure in bitOpTree opt (#2899)
* Tests: Add another testcase that triggers assertion failure in bitOpTree opt. * Fix assertion failure in bitOpTree opt reported in #2891. Consider the follwoing case. CCast -> WordSel -> VarRef(leaf) * Make sure that m_bitPolarity is expanded enough.
This commit is contained in:
parent
2022ec43cf
commit
4351abfe71
|
|
@ -96,11 +96,6 @@ class ConstBitOpTreeVisitor final : public AstNVisitor {
|
||||||
ConstBitOpTreeVisitor* m_parentp; // ConstBitOpTreeVisitor that holds this VarInfo
|
ConstBitOpTreeVisitor* m_parentp; // ConstBitOpTreeVisitor that holds this VarInfo
|
||||||
AstVarRef* m_refp; // Points the variable that this VarInfo covers
|
AstVarRef* m_refp; // Points the variable that this VarInfo covers
|
||||||
V3Number m_bitPolarity; // Coefficient of each bit
|
V3Number m_bitPolarity; // Coefficient of each bit
|
||||||
static int widthOfRef(AstVarRef* refp) {
|
|
||||||
if (AstWordSel* selp = VN_CAST(refp->backp(), WordSel)) return selp->width();
|
|
||||||
if (AstCCast* castp = VN_CAST(refp->backp(), CCast)) return castp->width();
|
|
||||||
return refp->width();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -108,6 +103,30 @@ class ConstBitOpTreeVisitor final : public AstNVisitor {
|
||||||
bool sameVarAs(const AstNodeVarRef* otherp) const { return m_refp->sameGateTree(otherp); }
|
bool sameVarAs(const AstNodeVarRef* otherp) const { return m_refp->sameGateTree(otherp); }
|
||||||
void setPolarity(bool compBit, int bit) {
|
void setPolarity(bool compBit, int bit) {
|
||||||
UASSERT_OBJ(!hasConstantResult(), m_refp, "Already has result of " << m_constResult);
|
UASSERT_OBJ(!hasConstantResult(), m_refp, "Already has result of " << m_constResult);
|
||||||
|
UASSERT_OBJ(bit < VL_QUADSIZE, m_refp,
|
||||||
|
"bit:" << bit << " is too big after V3Expand"
|
||||||
|
<< " back:" << m_refp->backp());
|
||||||
|
if (bit >= m_bitPolarity.width()) { // Need to expand m_bitPolarity
|
||||||
|
const V3Number oldPol = std::move(m_bitPolarity);
|
||||||
|
// oldPol.width() is 8, 16, or 32 because this visitor is called after V3Expand
|
||||||
|
// newWidth is increased by 2x because
|
||||||
|
// - CCast will cast to such bitwidth anyway
|
||||||
|
// - can avoid frequent expansion
|
||||||
|
int newWidth = oldPol.width();
|
||||||
|
while (bit >= newWidth) newWidth *= 2;
|
||||||
|
m_bitPolarity = V3Number{m_refp, newWidth};
|
||||||
|
UASSERT_OBJ(newWidth == 16 || newWidth == 32 || newWidth == 64, m_refp,
|
||||||
|
"bit:" << bit << " newWidth:" << newWidth);
|
||||||
|
m_bitPolarity.setAllBitsX();
|
||||||
|
for (int i = 0; i < oldPol.width(); ++i) {
|
||||||
|
if (oldPol.bitIs0(i))
|
||||||
|
m_bitPolarity.setBit(i, '0');
|
||||||
|
else if (oldPol.bitIs1(i))
|
||||||
|
m_bitPolarity.setBit(i, '1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UASSERT_OBJ(bit < m_bitPolarity.width(), m_refp,
|
||||||
|
"bit:" << bit << " width:" << m_bitPolarity.width() << m_refp);
|
||||||
if (m_bitPolarity.bitIsX(bit)) { // The bit is not yet set
|
if (m_bitPolarity.bitIsX(bit)) { // The bit is not yet set
|
||||||
m_bitPolarity.setBit(bit, compBit);
|
m_bitPolarity.setBit(bit, compBit);
|
||||||
} else { // Priviously set the bit
|
} else { // Priviously set the bit
|
||||||
|
|
@ -129,7 +148,7 @@ class ConstBitOpTreeVisitor final : public AstNVisitor {
|
||||||
FileLine* fl = m_refp->fileline();
|
FileLine* fl = m_refp->fileline();
|
||||||
AstNode* srcp = VN_CAST(m_refp->backp(), WordSel);
|
AstNode* srcp = VN_CAST(m_refp->backp(), WordSel);
|
||||||
if (!srcp) srcp = m_refp;
|
if (!srcp) srcp = m_refp;
|
||||||
const int width = widthOfRef(m_refp);
|
const int width = m_bitPolarity.width();
|
||||||
|
|
||||||
if (hasConstantResult())
|
if (hasConstantResult())
|
||||||
return new AstConst{fl,
|
return new AstConst{fl,
|
||||||
|
|
@ -160,7 +179,7 @@ class ConstBitOpTreeVisitor final : public AstNVisitor {
|
||||||
VarInfo(ConstBitOpTreeVisitor* parent, AstVarRef* refp)
|
VarInfo(ConstBitOpTreeVisitor* parent, AstVarRef* refp)
|
||||||
: m_parentp(parent)
|
: m_parentp(parent)
|
||||||
, m_refp(refp)
|
, m_refp(refp)
|
||||||
, m_bitPolarity(refp, widthOfRef(refp)) {
|
, m_bitPolarity(refp, refp->isWide() ? VL_EDATASIZE : refp->width()) {
|
||||||
m_bitPolarity.setAllBitsX();
|
m_bitPolarity.setAllBitsX();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
scenarios(simulator => 1);
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
compile(
|
compile(
|
||||||
verilator_flags2=>["-Wno-UNOPTTHREADS", "--stats", "--coverage"],
|
verilator_flags2=>["-Wno-UNOPTTHREADS", "--stats", "--coverage", "--trace"],
|
||||||
);
|
);
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
|
|
|
||||||
|
|
@ -20,19 +20,20 @@ module t(/*AUTOARG*/
|
||||||
logic bank_rd_vec_m3;
|
logic bank_rd_vec_m3;
|
||||||
always_ff @(posedge clk) bank_rd_vec_m3 <= crc[33];
|
always_ff @(posedge clk) bank_rd_vec_m3 <= crc[33];
|
||||||
|
|
||||||
|
logic [3:0][31:0] data_i;
|
||||||
wire out;
|
wire [3:0] out;
|
||||||
|
for (genvar i = 0; i < 4; ++i) begin
|
||||||
|
always_ff @(posedge clk) data_i[i] <= crc[63:32];
|
||||||
ecc_check_pipe u_bank_data_ecc_check(
|
ecc_check_pipe u_bank_data_ecc_check(
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.bank_rd_m3 (bank_rd_vec_m3),
|
.bank_rd_m3 (bank_rd_vec_m3),
|
||||||
.data_i (in),
|
.data_i ({1'b0, data_i[i]}),
|
||||||
.ecc_err_o (out)
|
.ecc_err_o (out[i])
|
||||||
);
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// Aggregate outputs into a single result vector
|
// Aggregate outputs into a single result vector
|
||||||
wire [63:0] result = {63'b0, out};
|
wire [63:0] result = {60'b0, out};
|
||||||
|
|
||||||
// Test loop
|
// Test loop
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
|
|
@ -54,7 +55,7 @@ module t(/*AUTOARG*/
|
||||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||||
// What checksum will we end up with (above print should match)
|
// What checksum will we end up with (above print should match)
|
||||||
`define EXPECTED_SUM 64'h768b162c5835e35b
|
`define EXPECTED_SUM 64'ha2601675a6ae4972
|
||||||
if (sum !== `EXPECTED_SUM) $stop;
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue