CIRCT 20.0.0git
Loading...
Searching...
No Matches
FSMGraph.cpp
Go to the documentation of this file.
1//===- FSMGraph.cpp - FSM Graph ---------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11using namespace circt;
12using namespace fsm;
13
14void FSMTransitionEdge::erase() {
15 // Update the prev node to point to the next node.
16 if (prevUse)
17 prevUse->nextUse = nextUse;
18 else
19 nextState->firstUse = nextUse;
20 // Update the next node to point to the prev node.
21 if (nextUse)
22 nextUse->prevUse = prevUse;
23 currentState->eraseTransitionEdge(this);
24}
25
26void FSMStateNode::eraseTransitionEdge(FSMTransitionEdge *edge) {
27 edge->getTransition().erase();
28 transitions.erase(edge);
29}
30
31FSMTransitionEdge *FSMStateNode::addTransitionEdge(FSMStateNode *nextState,
32 TransitionOp transition) {
33 auto *transitionEdge = new FSMTransitionEdge(this, transition, nextState);
34 nextState->recordUse(transitionEdge);
35 transitions.push_back(transitionEdge);
36 return transitionEdge;
37}
38
39void FSMStateNode::recordUse(FSMTransitionEdge *transition) {
40 transition->nextUse = firstUse;
41 if (firstUse)
42 firstUse->prevUse = transition;
43 firstUse = transition;
44}
45
46FSMGraph::FSMGraph(Operation *op) {
47 machine = dyn_cast<MachineOp>(op);
48 assert(machine && "Expected a fsm::MachineOp");
49
50 // Find all states in the machine.
51 for (auto stateOp : machine.getOps<StateOp>()) {
52 // Add an edge to indicate that this state transitions to some other state.
53 auto *currentStateNode = getOrAddState(stateOp);
54
55 for (auto transitionOp : stateOp.getTransitions().getOps<TransitionOp>()) {
56 auto *nextStateNode = getOrAddState(transitionOp.getNextStateOp());
57 currentStateNode->addTransitionEdge(nextStateNode, transitionOp);
58 }
59 }
60}
61
62FSMStateNode *FSMGraph::lookup(StringAttr name) {
63 auto it = nodeMap.find(name);
64 if (it != nodeMap.end())
65 return it->second;
66 return nullptr;
67}
68
69FSMStateNode *FSMGraph::lookup(StateOp state) {
70 return lookup(state.getNameAttr());
71}
72
73FSMStateNode *FSMGraph::getOrAddState(StateOp state) {
74 // Try to insert an FSMStateNode. If its not inserted, it returns
75 // an iterator pointing to the node.
76 auto *&node = nodeMap[state.getNameAttr()];
77 if (!node) {
78 node = new FSMStateNode(state);
79 nodes.push_back(node);
80 }
81 return node;
82}
83
84FSMStateNode *FSMGraph::createState(OpBuilder &builder, Location loc,
85 StringRef name) {
86 OpBuilder::InsertionGuard g(builder);
87 builder.setInsertionPointToEnd(&getMachine().getBody().front());
88 auto stateOp = builder.create<StateOp>(loc, name);
89 return getOrAddState(stateOp);
90}
91
92FSMTransitionEdge *FSMGraph::createTransition(OpBuilder &builder, Location loc,
93 StateOp from, StateOp to) {
94 auto *currentStateNode = getOrAddState(from);
95 auto *nextStateNode = getOrAddState(to);
96 OpBuilder::InsertionGuard g(builder);
97 // Set the insertion point to the end of the transitions.
98 builder.setInsertionPointToEnd(&from.getTransitions().getBlocks().front());
99 auto transition = builder.create<TransitionOp>(loc, to);
100 return currentStateNode->addTransitionEdge(nextStateNode, transition);
101}
102
103void FSMGraph::eraseState(StateOp state) {
104 auto *stateNode = getOrAddState(state);
105
106 for (auto *incomingTransition : llvm::make_early_inc_range(stateNode->uses()))
107 incomingTransition->erase();
108
109 for (auto *outgoingTransitions : llvm::make_early_inc_range(*stateNode))
110 outgoingTransitions->erase();
111 nodeMap.erase(state.getNameAttr());
112 nodes.erase(stateNode);
113}
114
115void FSMGraph::renameState(StateOp state, StringRef name) {
116 auto *stateNode = getOrAddState(state);
117 auto nameStrAttr = StringAttr::get(state.getContext(), name);
118
119 state.setName(nameStrAttr);
120
121 // Update in- and outgoing transitions to the state.
122 auto updateTransitions = [&](auto &&transitionRange) {
123 for (auto *transition : transitionRange) {
124 auto transitionOp = transition->getTransition();
125 transitionOp->setAttr(transitionOp.getNextStateAttrName(), nameStrAttr);
126 }
127 };
128
129 updateTransitions(stateNode->uses());
130 updateTransitions(*stateNode);
131
132 // Update nodemap
133 nodeMap.erase(state.getNameAttr());
134 nodeMap[nameStrAttr] = stateNode;
135}
assert(baseType &&"element must be base type")
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition fsm.py:1