Fix FSM coverage on empty reset branches (#8005) (#8064)

This commit is contained in:
Yogish Sekhar
2026-08-08 19:44:46 +01:00
committed by GitHub
parent 7601011bba
commit dde6aa34ce
4 changed files with 441 additions and 4 deletions
+10 -4
View File
@@ -701,7 +701,9 @@ class FsmDetectVisitor final : public VNVisitor {
AstVarScope* resetStateVscp = nullptr;
const ResetAssignStatus resetStatus = FsmDetectVisitor::collectConstStateAssigns(
firstIfp->thensp(), resetStateVscp, reg.resetArcs());
if (resetStatus == ResetAssignStatus::NONE || resetStateVscp != vscp) {
if (resetStatus == ResetAssignStatus::EMPTY) {
reg.resetArcs().clear();
} else if (resetStatus == ResetAssignStatus::NONE || resetStateVscp != vscp) {
reg.resetArcs().clear();
FsmStateValue resetValue;
AstNode* const thenNodep
@@ -1040,6 +1042,7 @@ class FsmDetectVisitor final : public VNVisitor {
}
enum class ResetAssignStatus : uint8_t {
EMPTY, // Reset branch had no non-coverage statements.
NONE, // Reset branch was not the supported direct-constant shape.
SINGLE, // Exactly one supported reset assignment was collected.
MULTI_SAME_STATE // Multiple assignments to the same FSM state var; warn and ignore.
@@ -1052,7 +1055,7 @@ class FsmDetectVisitor final : public VNVisitor {
static ResetAssignStatus collectConstStateAssigns(AstNode* stmtp, AstVarScope*& stateVscp,
std::vector<FsmResetArcDesc>& resetArcs) {
AstNode* nodep = skipLeadingIgnorableStmt(stmtp);
UASSERT_OBJ(nodep, stmtp, "Empty reset branch unexpectedly survived to FSM detection");
if (!nodep) return ResetAssignStatus::EMPTY;
for (;; nodep = nodep->nextp()) {
AstVarScope* assignStateVscp = nullptr;
FsmStateValue value;
@@ -1410,7 +1413,10 @@ class FsmDetectVisitor final : public VNVisitor {
AstVarScope* resetStateVscp = nullptr;
const ResetAssignStatus resetStatus
= collectConstStateAssigns(ifp->thensp(), resetStateVscp, cand.resetArcs());
if (resetStatus == ResetAssignStatus::NONE) {
const bool emptyResetBranch = resetStatus == ResetAssignStatus::EMPTY;
if (emptyResetBranch) {
cand.resetArcs().clear();
} else if (resetStatus == ResetAssignStatus::NONE) {
cand.resetArcs().clear();
FsmStateValue resetValue;
AstNode* const thenNodep = singleMeaningfulBranch(ifp->thensp());
@@ -1425,7 +1431,7 @@ class FsmDetectVisitor final : public VNVisitor {
AstNode* const elseNodep = singleMeaningfulBranch(ifp->elsesp());
UASSERT_OBJ(elseNodep, ifp, "register reset match requires a non-empty commit branch");
if (!nodeStateVarAssign(elseNodep, stateVscp, nextVscp)) return false;
if (resetStateVscp != stateVscp) return false;
if (!emptyResetBranch && resetStateVscp != stateVscp) return false;
cand.resetCond() = describeResetCond(ifp->condp());
cand.hasResetCond(cand.resetCond().varScopep != nullptr);
} else {