13#ifndef CIRCT_DIALECT_FSM_FSMGRAPH_H
14#define CIRCT_DIALECT_FSM_FSMGRAPH_H
18#include "llvm/ADT/GraphTraits.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/iterator.h"
21#include "llvm/Support/DOTGraphTraits.h"
22#include "llvm/Support/GraphWriter.h"
33 :
public llvm::mapped_iterator<It, typename It::pointer (*)(
34 typename It::reference)> {
38 static typename Iterator::value_type *
39 addrOf(
typename Iterator::value_type &v)
noexcept {
40 return std::addressof(v);
43 :
llvm::mapped_iterator<It, typename
Iterator::pointer (*)(
44 typename
Iterator::reference)>(iterator,
50static void escape(std::string &str,
const char *c,
bool noEscape =
false) {
51 std::string replacement = std::string(c);
53 replacement = R
"(\)" + replacement;
54 str = std::regex_replace(str, std::regex(c), replacement);
59template <
typename TOpRange>
62 llvm::raw_string_ostream ss(
dump);
64 ops, ss, [&](mlir::Operation &op) { op.print(ss); },
"\\n");
75template <
typename TOpRange>
78 llvm::raw_string_ostream ss(
dump);
80 ops, ss, [&](mlir::Operation &op) { op.print(ss); },
"\n");
92 :
public llvm::ilist_node_with_parent<FSMTransitionEdge, FSMStateNode> {
142 TransitionOp transition);
155 :
public llvm::iterator_facade_base<
156 UseIterator, std::forward_iterator_tag, FSMTransitionEdge *> {
160 using llvm::iterator_facade_base<
UseIterator, std::forward_iterator_tag,
178 llvm::iterator_range<UseIterator>
uses() {
238 StateOp from, StateOp to);
263 llvm::DenseMap<Attribute, FSMStateNode *>
nodeMap;
271struct llvm::GraphTraits<
circt::fsm::FSMStateNode *> {
297struct llvm::GraphTraits<
circt::fsm::FSMGraph *>
298 :
public llvm::GraphTraits<circt::fsm::FSMStateNode *> {
306 return graph->
begin();
316struct llvm::DOTGraphTraits<
circt::fsm::FSMGraph *>
317 :
public llvm::DefaultDOTGraphTraits {
318 using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
323 return node->
getState().getSymName().str();
332 template <
typename Iterator>
339 if (!transition.hasGuard())
342 std::string
attrs =
"label=\"";
344 transition.getGuard().getOps(), [](mlir::Operation &op) {
346 if (isa<circt::fsm::ReturnOp, circt::fsm::OutputOp>(op))
347 return op.getNumOperands() != 0;
356 GraphWriter<circt::fsm::FSMGraph *> &gw) {
358 llvm::raw_ostream &os = gw.getOStream();
360 os <<
"variables [shape=record,label=\"Variables|";
362 graph->
getMachine().getOps(), [](mlir::Operation &op) {
364 return !isa<circt::fsm::StateOp>(&op);
assert(baseType &&"element must be base type")
static void dump(DIModule &module, raw_indented_ostream &os)
Graph representing FSM machines, their states and transitions between these.
FSMStateNode * createState(OpBuilder &builder, Location loc, StringRef name)
Creates a new StateOp operation in this machine and updates the graph.
FSMTransitionEdge * createTransition(OpBuilder &builder, Location loc, StateOp from, StateOp to)
Creates a new transition operation between two states and updates the graph.
NodeList nodes
The storage for graph nodes, with deterministic iteration.
FSMStateNode * lookup(StateOp op)
Look up a FSMStateNode for a state.
FSMStateNode * operator[](StateOp op)
Lookup a FSMStateNode for a state.
MachineOp getMachine() const
Return the FSM machine operation which this graph tracks.
void eraseState(StateOp state)
Removes this state from the graph.
MachineOp machine
The node under which all states are nested.
llvm::DenseMap< Attribute, FSMStateNode * > nodeMap
This maps each StateOp to its graph node.
void renameState(StateOp state, StringRef name)
Renames the 'state' to the provided 'name', and updates all referencing transitions.
detail::AddressIterator< NodeList::iterator > iterator
Iterate through all states.
FSMStateNode * getEntryNode()
Get the node corresponding to the entry state of the FSM.
FSMGraph(const FSMGraph &)=delete
llvm::iplist< FSMStateNode > NodeList
This is the list of FSMStateNodes in the graph.
FSMGraph(Operation *operation)
Create a new graph of an FSM machine operation.
FSMStateNode * getOrAddState(StateOp state)
Retrieves the state node for a 'state'.
This is a Node in the FSMGraph. Each node represents a state in the FSM.
llvm::iplist< FSMTransitionEdge > FSMTransitionList
FSMStateNode(const FSMStateNode &)=delete
FSMStateNode(StateOp state)
friend class FSMTransitionEdge
UseIterator usesBegin()
Iterate the instance records which instantiate this module.
FSMTransitionList transitions
List of outgoing transitions from this state.
StateOp getState() const
Get the state operation that this node is tracking.
FSMTransitionEdge * firstUse
List of transitions which reference this state.
void recordUse(FSMTransitionEdge *transition)
Record that a tramsition referenced this state.
void eraseTransitionEdge(FSMTransitionEdge *edge)
Erases a transition edge from this state.
friend class FSMGraph
Provide access to the constructor.
detail::AddressIterator< FSMTransitionList::iterator > iterator
Iterate outgoing FSM transitions of this state.
llvm::iterator_range< UseIterator > uses()
FSMTransitionEdge * addTransitionEdge(FSMStateNode *nextState, TransitionOp transition)
Adds a new transition edge from this state to 'nextState'.
This is an edge in the FSMGraph.
FSMStateNode * currentState
The state where this transition originates from.
TransitionOp getTransition() const
FSMStateNode * getNextState() const
Get the module which the FSM-like is instantiating.
FSMStateNode * getCurrentState() const
Get the state where the transition originates from.
friend class FSMGraphBase
TransitionOp transition
The transition that this is tracking.
FSMTransitionEdge(const FSMTransitionEdge &)=delete
void erase()
Erase this transition, removing it from the source state and the target state's use-list.
FSMTransitionEdge * prevUse
FSMStateNode * nextState
The next state of this transition.
FSMTransitionEdge(FSMStateNode *currentState, TransitionOp transition, FSMStateNode *nextState)
friend class FSMStateNode
FSMTransitionEdge * nextUse
Intrusive linked list for other uses.
static std::string dotSafeDumpOps(TOpRange ops)
static void escape(std::string &str, const char *c, bool noEscape=false)
static std::string dumpOps(TOpRange ops)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
FSMTransitionEdge * operator*() const
UseIterator(FSMStateNode *node)
bool operator==(const UseIterator &other) const
UseIterator & operator++()
FSMTransitionEdge * current
This just maps a iterator of references to an iterator of addresses.
AddressIterator(Iterator iterator)
static Iterator::value_type * addrOf(typename Iterator::value_type &v) noexcept
static std::string getNodeDescription(circt::fsm::FSMStateNode *node, circt::fsm::FSMGraph *)
static void addCustomGraphFeatures(const circt::fsm::FSMGraph *graph, GraphWriter< circt::fsm::FSMGraph * > &gw)
static std::string getEdgeAttributes(const circt::fsm::FSMStateNode *node, Iterator it, circt::fsm::FSMGraph *)
static std::string getNodeLabel(circt::fsm::FSMStateNode *node, circt::fsm::FSMGraph *)
static nodes_iterator nodes_end(circt::fsm::FSMGraph *graph)
static NodeRef getEntryNode(circt::fsm::FSMGraph *graph)
circt::fsm::FSMGraph::iterator nodes_iterator
static nodes_iterator nodes_begin(circt::fsm::FSMGraph *graph)
static ChildIteratorType child_end(NodeRef node)
circt::fsm::FSMStateNode NodeType
llvm::mapped_iterator< circt::fsm::FSMStateNode::iterator, decltype(&getNextState)> ChildIteratorType
static NodeRef getNextState(const circt::fsm::FSMTransitionEdge *transition)
static ChildIteratorType child_begin(NodeRef node)
static NodeRef getEntryNode(NodeRef node)