[FSMToSV] Fix bug of operations not being cloned in transition region (#8753)

Co-authored-by: Atticus Kuhn <atticusmkuhn@gmail.com>
This commit is contained in:
Atticus Kuhn 2025-07-21 17:27:07 +01:00 committed by GitHub
parent 7775fb9ee9
commit 888e6787e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 2 deletions

View File

@ -665,8 +665,18 @@ MachineOpConverter::convertState(StateOp state) {
res.outputs = outputOp.getOperands(); // 3.2
}
auto transitions = llvm::SmallVector<TransitionOp>(
state.getTransitions().getOps<TransitionOp>());
SmallVector<TransitionOp> transitions;
for (auto &op : state.getTransitions().getOps()) {
if (auto transOp = dyn_cast<TransitionOp>(op)) {
transitions.push_back(transOp);
} else {
// Clone operations which are inside `transitions` region but outside
// `guard` region.
auto opClone = b.clone(op);
for (auto [i, res] : llvm::enumerate(op.getResults()))
res.replaceAllUsesWith(opClone->getResult(i));
}
}
// 3.3, 3.4) Convert the transitions and record the next-state value
// derived from the transitions being selected in a priority-encoded manner.
auto nextStateRes = convertTransitions(state, transitions);

View File

@ -191,3 +191,38 @@ module {
}
}
}
// -----
// Test the usage of operations defined inside `transition` region but outside `guard region`
// CHECK-LABEL: hw.module @OpsInTransition(in %clk : !seq.clock, in %rst : i1) attributes {emit.fragments = [@FSM_ENUM_TYPEDEFS]} {
// CHECK: sv.alwayscomb {
// CHECK-NEXT: sv.case %[[R:.*]] : !hw.typealias<@fsm_enum_typedecls::@OpsInTransition_state_t, !hw.enum<State1, State2>>
// CHECK-NEXT: case State1: {
// CHECK-NEXT: sv.bpassign %[[STATE_NEXT:.*]], %[[B:.*]] : !hw.typealias<@fsm_enum_typedecls::@OpsInTransition_state_t, !hw.enum<State1, State2>>
// CHECK-NEXT: }
// CHECK-NEXT: case State2: {
// CHECK-NEXT: sv.bpassign %[[STATE_NEXT:.*]], %[[A:.*]] : !hw.typealias<@fsm_enum_typedecls::@OpsInTransition_state_t, !hw.enum<State1, State2>>
// CHECK-NEXT: }
// CHECK-NEXT: default: {
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: hw.output
// CHECK-NEXT: }
module {
fsm.machine @OpsInTransition() -> () attributes {initialState = "State1"} {
fsm.state @State1 output {
fsm.output
} transitions {
%false = hw.constant false
fsm.transition @State1 guard {
fsm.return %false
}
}
fsm.state @State2 output {
fsm.output
}
}
}