Fix $countbits(..., 'x)

This commit is contained in:
Wilson Snyder 2020-11-27 20:51:32 -05:00
parent 5091298fae
commit 0c6bd42da3
2 changed files with 50 additions and 1 deletions

View File

@ -258,6 +258,42 @@ private:
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstCountBits* nodep) override {
// Ahh, we're two state, so this is easy
std::array<bool, 3> dropop;
dropop[0] = VN_IS(nodep->rhsp(), Const) && VN_CAST(nodep->rhsp(), Const)->num().isAnyX();
dropop[1] = VN_IS(nodep->thsp(), Const) && VN_CAST(nodep->thsp(), Const)->num().isAnyX();
dropop[2] = VN_IS(nodep->fhsp(), Const) && VN_CAST(nodep->fhsp(), Const)->num().isAnyX();
UINFO(4, " COUNTBITS(" << dropop[0] << dropop[1] << dropop[2] << " " << nodep << endl);
AstNode* nonXp = nullptr;
if (!dropop[0])
nonXp = nodep->rhsp();
else if (!dropop[1])
nonXp = nodep->thsp();
else if (!dropop[2])
nonXp = nodep->fhsp();
else { // Was all X-s
UINFO(4, " COUNTBITS('x)->0 " << nodep << endl);
AstConst* newp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;
}
if (dropop[0]) {
nodep->rhsp()->unlinkFrBack()->deleteTree();
nodep->rhsp(nonXp->cloneTree(true));
}
if (dropop[1]) {
nodep->thsp()->unlinkFrBack()->deleteTree();
nodep->thsp(nonXp->cloneTree(true));
}
if (dropop[2]) {
nodep->fhsp()->unlinkFrBack()->deleteTree();
nodep->fhsp(nonXp->cloneTree(true));
}
iterateChildren(nodep);
}
virtual void visit(AstConst* nodep) override {
if (m_constXCvt && nodep->num().isFourState()) {
UINFO(4, " CONST4 " << nodep << endl);

View File

@ -89,9 +89,22 @@ module t(/*AUTOARG*/
if ($countones(val) != 7) $stop;
if ($countbits(val, '0) != 25) $stop;
if ($countbits(val, '0, '1) != 32) $stop;
`ifndef VERILATOR // Unsup
// Optimization may depend on position of X, so need to walk it
if ($countbits(val, 'x) != 0) $stop;
if ($countbits(val, 'x, '1) != 7) $stop;
if ($countbits(val, '1, 'x) != 7) $stop;
if ($countbits(val, '1, '1, 'x) != 7) $stop;
if ($countbits(val, 'x, '0) != 25) $stop;
if ($countbits(val, 'x, '0, '1) != 32) $stop;
`ifndef VERILATOR
// Optimization may depend on position of Z, so need to walk it
if ($countbits(val, 'z) != 0) $stop;
if ($countbits(val, 'z, '1) != 7) $stop;
if ($countbits(val, '1, 'z) != 7) $stop;
if ($countbits(val, '1, '1, 'z) != 7) $stop;
if ($countbits(val, 'z, '0) != 25) $stop;
if ($countbits(val, 'z, '0, '1) != 32) $stop;
//
if ($countbits(val, 'x, 'z) != 0) $stop;
`endif
end