11 using namespace circt;
14 void FSMTransitionEdge::erase() {
17 prevUse->nextUse = nextUse;
19 nextState->firstUse = nextUse;
22 nextUse->prevUse = prevUse;
23 currentState->eraseTransitionEdge(
this);
26 void FSMStateNode::eraseTransitionEdge(FSMTransitionEdge *edge) {
27 edge->getTransition().erase();
28 transitions.erase(edge);
31 FSMTransitionEdge *FSMStateNode::addTransitionEdge(FSMStateNode *nextState,
33 auto *transitionEdge =
new FSMTransitionEdge(
this, transition, nextState);
34 nextState->recordUse(transitionEdge);
35 transitions.push_back(transitionEdge);
36 return transitionEdge;
39 void FSMStateNode::recordUse(FSMTransitionEdge *transition) {
40 transition->nextUse = firstUse;
42 firstUse->prevUse = transition;
43 firstUse = transition;
46 FSMGraph::FSMGraph(Operation *op) {
47 machine = dyn_cast<MachineOp>(op);
48 assert(machine &&
"Expected a fsm::MachineOp");
51 for (
auto stateOp : machine.getOps<
StateOp>()) {
53 auto *currentStateNode = getOrAddState(stateOp);
55 for (
auto transitionOp : stateOp.getTransitions().getOps<
TransitionOp>()) {
56 auto *nextStateNode = getOrAddState(transitionOp.getNextStateOp());
57 currentStateNode->addTransitionEdge(nextStateNode, transitionOp);
62 FSMStateNode *FSMGraph::lookup(StringAttr name) {
63 auto it = nodeMap.find(name);
64 if (it != nodeMap.end())
69 FSMStateNode *FSMGraph::lookup(
StateOp state) {
70 return lookup(state.getNameAttr());
73 FSMStateNode *FSMGraph::getOrAddState(
StateOp state) {
76 auto *&node = nodeMap[state.getNameAttr()];
78 node =
new FSMStateNode(state);
79 nodes.push_back(node);
84 FSMStateNode *FSMGraph::createState(OpBuilder &builder, Location loc,
86 OpBuilder::InsertionGuard g(builder);
87 builder.setInsertionPointToEnd(&getMachine().getBody().front());
88 auto stateOp = builder.create<
StateOp>(loc, name);
89 return getOrAddState(stateOp);
92 FSMTransitionEdge *FSMGraph::createTransition(OpBuilder &builder, Location loc,
94 auto *currentStateNode = getOrAddState(from);
95 auto *nextStateNode = getOrAddState(to);
96 OpBuilder::InsertionGuard g(builder);
98 builder.setInsertionPointToEnd(&from.getTransitions().getBlocks().front());
100 return currentStateNode->addTransitionEdge(nextStateNode, transition);
103 void FSMGraph::eraseState(
StateOp state) {
104 auto *stateNode = getOrAddState(state);
106 for (
auto *incomingTransition : llvm::make_early_inc_range(stateNode->uses()))
107 incomingTransition->erase();
109 for (
auto *outgoingTransitions : llvm::make_early_inc_range(*stateNode))
110 outgoingTransitions->erase();
111 nodeMap.erase(state.getNameAttr());
112 nodes.erase(stateNode);
115 void FSMGraph::renameState(
StateOp state, StringRef name) {
116 auto *stateNode = getOrAddState(state);
119 state.setName(nameStrAttr);
122 auto updateTransitions = [&](
auto &&transitionRange) {
123 for (
auto *transition : transitionRange) {
124 auto transitionOp = transition->getTransition();
125 transitionOp->setAttr(transitionOp.getNextStateAttrName(), nameStrAttr);
129 updateTransitions(stateNode->uses());
130 updateTransitions(*stateNode);
133 nodeMap.erase(state.getNameAttr());
134 nodeMap[nameStrAttr] = stateNode;
assert(baseType &&"element must be base type")
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.