diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 1a3dae823..6c760998e 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -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 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); diff --git a/test_regress/t/t_math_countbits.v b/test_regress/t/t_math_countbits.v index e82c9ee93..de02ccb5c 100644 --- a/test_regress/t/t_math_countbits.v +++ b/test_regress/t/t_math_countbits.v @@ -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