docc 0.8.3 (0d44999b)
C++ API Reference
Loading...
Searching...
No Matches
data_flow_graph.h
Go to the documentation of this file.
1#pragma once
2
3#include <boost/graph/graphviz.hpp>
4#include <nlohmann/json.hpp>
5#include <optional>
6#include <string>
7#include <vector>
8
14#include "sdfg/graph/graph.h"
17
18using json = nlohmann::json;
19
20namespace sdfg {
21
22namespace builder {
23class SDFGBuilder;
25} // namespace builder
26
27namespace data_flow {
28
32
33private:
34 // Remark: Exclusive resource
35 graph::Graph graph_;
36 std::unordered_map<graph::Vertex, std::unique_ptr<data_flow::DataFlowNode>, boost::hash<graph::Vertex>> nodes_;
37 std::unordered_map<graph::Edge, std::unique_ptr<data_flow::Memlet>, boost::hash<graph::Edge>> edges_;
38
39 Element* parent_;
40
41 // Cached canonical order; reset by the builders on every structural change.
42 mutable std::optional<std::list<const DataFlowNode*>> topological_order_;
43
44 bool is_valid_topological_order(const std::list<const DataFlowNode*>& order) const;
45
46 std::list<const DataFlowNode*> boost_topological_sort() const;
47
48 std::list<const DataFlowNode*> semantic_topological_sort() const;
49
50 const std::list<const DataFlowNode*>& cached_topological_order() const;
51
52public:
53 DataFlowGraph() = default;
55
56 ~DataFlowGraph() = default;
57
60
61 void validate(const Function& function) const;
62
63 const Element* get_parent() const;
64
66
67 auto nodes() const {
68 return std::views::values(this->nodes_) | std::views::transform(helpers::indirect<data_flow::DataFlowNode>) |
70 };
71
72 auto nodes() {
73 return std::views::values(this->nodes_) | std::views::transform(helpers::indirect<data_flow::DataFlowNode>);
74 };
75
76 auto edges() const {
77 return std::views::values(this->edges_) | std::views::transform(helpers::indirect<data_flow::Memlet>) |
78 std::views::transform(helpers::add_const<data_flow::Memlet>);
79 };
80
81 auto edges() {
82 return std::views::values(this->edges_) | std::views::transform(helpers::indirect<data_flow::Memlet>);
83 };
84
85 auto in_edges(const data_flow::DataFlowNode& node) const {
86 auto [eb, ee] = boost::in_edges(node.vertex(), this->graph_);
87 auto edges = std::ranges::subrange(eb, ee);
88
89 auto memlets = std::views::transform(
90 edges,
91 [&lookup_table = this->edges_](const graph::Edge& edge) -> data_flow::Memlet& {
92 return *(lookup_table.find(edge)->second);
93 }
94 ) |
95 std::views::transform(helpers::add_const<data_flow::Memlet>);
96
97 return memlets;
98 };
99
101 auto [eb, ee] = boost::in_edges(node.vertex(), this->graph_);
102 auto edges = std::ranges::subrange(eb, ee);
103
104 auto memlets =
105 std::views::transform(edges, [&lookup_table = this->edges_](const graph::Edge& edge) -> data_flow::Memlet& {
106 return *(lookup_table.find(edge)->second);
107 });
108
109 return memlets;
110 };
111
112 const data_flow::Memlet* in_edge_for_connector(const data_flow::CodeNode& node, const std::string& conn) const;
113 data_flow::Memlet* in_edge_for_connector(const data_flow::CodeNode& node, const std::string& conn);
114
120
127
128
129 std::vector<data_flow::Memlet*> in_edges_by_connector(const data_flow::CodeNode& node);
130
131 std::vector<const data_flow::Memlet*> in_edges_by_connector(const data_flow::CodeNode& node) const;
132
133 auto out_edges(const data_flow::DataFlowNode& node) const {
134 auto [eb, ee] = boost::out_edges(node.vertex(), this->graph_);
135 auto edges = std::ranges::subrange(eb, ee);
136
137 auto memlets = std::views::transform(
138 edges,
139 [&lookup_table = this->edges_](const graph::Edge& edge) -> data_flow::Memlet& {
140 return *(lookup_table.find(edge)->second);
141 }
142 ) |
143 std::views::transform(helpers::add_const<data_flow::Memlet>);
144
145 return memlets;
146 };
147
149 auto [eb, ee] = boost::out_edges(node.vertex(), this->graph_);
150 auto edges = std::ranges::subrange(eb, ee);
151
152 auto memlets =
153 std::views::transform(edges, [&lookup_table = this->edges_](const graph::Edge& edge) -> data_flow::Memlet& {
154 return *(lookup_table.find(edge)->second);
155 });
156
157 return memlets;
158 };
159
160 std::vector<const data_flow::Memlet*>
161 out_edges_for_connector(const data_flow::CodeNode& node, const std::string& conn) const;
162 std::vector<data_flow::Memlet*> out_edges_for_connector(const data_flow::CodeNode& node, const std::string& conn);
163
164 std::vector<data_flow::Memlet*> out_edges_by_connector(const data_flow::CodeNode& node);
165
166 std::vector<const data_flow::Memlet*> out_edges_by_connector(const data_flow::CodeNode& node) const;
167
168 size_t in_degree(const data_flow::DataFlowNode& node) const;
169
170 size_t out_degree(const data_flow::DataFlowNode& node) const;
171
172 void replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression);
173 void replace(const symbolic::ExpressionMapping& replacements);
174
175 /***** Section: Analysis *****/
176
177 std::unordered_set<const data_flow::Tasklet*> tasklets() const;
178
179 std::unordered_set<data_flow::Tasklet*> tasklets();
180
181 std::unordered_set<const data_flow::LibraryNode*> library_nodes() const;
182
183 std::unordered_set<data_flow::LibraryNode*> library_nodes();
184
185 std::unordered_set<const data_flow::AccessNode*> data_nodes() const;
186
187 std::unordered_set<data_flow::AccessNode*> data_nodes();
188
189 std::unordered_set<const data_flow::AccessNode*> reads() const;
190
191 std::unordered_set<const data_flow::AccessNode*> writes() const;
192
193 std::unordered_set<const data_flow::DataFlowNode*> sources() const;
194
195 std::unordered_set<data_flow::DataFlowNode*> sources();
196
197 std::unordered_set<const data_flow::DataFlowNode*> sinks() const;
198
199 std::unordered_set<data_flow::DataFlowNode*> sinks();
200
201 std::unordered_set<const data_flow::DataFlowNode*> predecessors(const data_flow::DataFlowNode& node) const;
202
203 std::unordered_set<const data_flow::DataFlowNode*> successors(const data_flow::DataFlowNode& node) const;
204
205 std::list<const data_flow::DataFlowNode*> topological_sort() const;
206
207 std::list<data_flow::DataFlowNode*> topological_sort();
208
209 const std::list<const data_flow::DataFlowNode*>& topological_order() const;
210
213
214 std::unordered_map<std::string, const data_flow::AccessNode*> dominators() const;
215
216 std::unordered_map<std::string, const data_flow::AccessNode*> post_dominators() const;
217
218 std::unordered_map<std::string, data_flow::AccessNode*> post_dominators();
219
221
222 const std::pair<size_t, const std::unordered_map<const data_flow::DataFlowNode*, size_t>>
224
225 template<typename T>
227 if (this->library_nodes().size() != 1) {
228 return nullptr;
229 }
230 if (!this->tasklets().empty()) {
231 return nullptr;
232 }
233 data_flow::LibraryNode* lib_node = *this->library_nodes().begin();
234 return dynamic_cast<T*>(lib_node);
235 };
236
249 const AccessNode* find_standalone_entry(const Memlet* input_edge) const;
250
258 const AccessNode* find_standalone_exit(const Memlet* output_edge) const;
259};
260
261} // namespace data_flow
262} // namespace sdfg
Access nodes for reading/writing data in the dataflow graph.
Definition element.h:159
Definition function.h:43
Definition sdfg_builder.h:13
Note: Even though the class references unique_ptr, it will never delete an SDFG it has a reference to...
Definition structured_sdfg_builder.h:44
Node representing access to a data container in the dataflow graph.
Definition access_node.h:84
Base class for computational nodes with inputs and outputs.
Definition code_node.h:88
const AccessNode * find_standalone_exit(const Memlet *output_edge) const
Same as [find_standalone_entry] find an access node that is standalone, so that we can recreate the a...
const data_flow::Memlet * in_edge_for_connector(const data_flow::CodeNode &node, const std::string &conn) const
std::unordered_set< const data_flow::LibraryNode * > library_nodes() const
void validate(const Function &function) const
std::unordered_set< const data_flow::AccessNode * > writes() const
void replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression)
std::unordered_map< std::string, const data_flow::AccessNode * > dominators() const
size_t in_degree(const data_flow::DataFlowNode &node) const
std::unordered_set< const data_flow::DataFlowNode * > successors(const data_flow::DataFlowNode &node) const
const data_flow::Memlet * in_edge_if_single(const data_flow::AccessNode &node) const
Will return the single input edge if it exists.
std::vector< data_flow::Memlet * > in_edges_by_connector(const data_flow::CodeNode &node)
std::unordered_set< data_flow::DataFlowNode * > sources()
auto out_edges(const data_flow::DataFlowNode &node) const
Definition data_flow_graph.h:133
std::unordered_set< const data_flow::DataFlowNode * > predecessors(const data_flow::DataFlowNode &node) const
const AccessNode * find_standalone_entry(const Memlet *input_edge) const
For the given input, identify a standalone input from which one could use to replace the following da...
std::unordered_set< data_flow::LibraryNode * > library_nodes()
std::unordered_set< data_flow::AccessNode * > data_nodes()
std::vector< data_flow::Memlet * > out_edges_by_connector(const data_flow::CodeNode &node)
std::unordered_set< const data_flow::Tasklet * > tasklets() const
std::vector< data_flow::Memlet * > out_edges_for_connector(const data_flow::CodeNode &node, const std::string &conn)
std::unordered_set< data_flow::DataFlowNode * > sinks()
auto out_edges(const data_flow::DataFlowNode &node)
Definition data_flow_graph.h:148
std::vector< const data_flow::Memlet * > out_edges_for_connector(const data_flow::CodeNode &node, const std::string &conn) const
auto all_simple_paths(const data_flow::DataFlowNode &src, const data_flow::DataFlowNode &dst) const
T * is_a_library_node()
Definition data_flow_graph.h:226
std::unordered_map< std::string, data_flow::AccessNode * > post_dominators()
auto edges() const
Definition data_flow_graph.h:76
std::vector< const data_flow::Memlet * > in_edges_by_connector(const data_flow::CodeNode &node) const
auto in_edges(const data_flow::DataFlowNode &node) const
Definition data_flow_graph.h:85
const std::list< const data_flow::DataFlowNode * > & topological_order() const
data_flow::Memlet * in_edge_for_connector(const data_flow::CodeNode &node, const std::string &conn)
std::list< data_flow::DataFlowNode * > topological_sort()
std::unordered_set< const data_flow::DataFlowNode * > sinks() const
void invalidate_topological_order()
Must be called after any change that can affect topological_sort() (nodes, edges, access-node names).
const Element * get_parent() const
std::vector< const data_flow::Memlet * > out_edges_by_connector(const data_flow::CodeNode &node) const
std::list< const data_flow::DataFlowNode * > topological_sort() const
std::unordered_set< const data_flow::AccessNode * > data_nodes() const
std::unordered_set< const data_flow::AccessNode * > reads() const
std::unordered_map< std::string, const data_flow::AccessNode * > post_dominators() const
const std::pair< size_t, const std::unordered_map< const data_flow::DataFlowNode *, size_t > > weakly_connected_components() const
DataFlowGraph(Element *parent)
data_flow::Memlet * in_edge_if_single(const data_flow::AccessNode &node)
DataFlowGraph & operator=(const DataFlowGraph &)=delete
auto nodes() const
Definition data_flow_graph.h:67
std::unordered_set< data_flow::Tasklet * > tasklets()
void replace(const symbolic::ExpressionMapping &replacements)
DataFlowGraph(const DataFlowGraph &graph)=delete
auto nodes()
Definition data_flow_graph.h:72
auto in_edges(const data_flow::DataFlowNode &node)
Definition data_flow_graph.h:100
std::unordered_set< const data_flow::DataFlowNode * > sources() const
const data_flow::Memlet * in_edge(const data_flow::AccessNode &node) const
size_t out_degree(const data_flow::DataFlowNode &node) const
auto edges()
Definition data_flow_graph.h:81
Abstract base class for all dataflow graph nodes.
Definition data_flow_node.h:106
graph::Vertex vertex() const
Get the graph vertex for this node.
Base class for all library nodes in the dataflow graph.
Definition library_node.h:106
Edge in the dataflow graph representing data movement.
Definition memlet.h:131
Base class for all nodes in the dataflow graph.
SymEngine::RCP< const SymEngine::Basic > Expression
Reference-counted pointer to a symbolic expression (SymEngine Basic).
Definition symbolic.h:83
SymEngine::map_basic_basic ExpressionMapping
Definition symbolic.h:109
nlohmann::json json
Definition interstate_edge.h:14
Library node definitions for calling functions beyond simple instructions.
Edges in the dataflow graph representing data movement.
Definition function_builder.h:10
Definition access_node.h:67
Definition graph.h:22
boost::graph_traits< Graph >::edge_descriptor Edge
Definition graph.h:26
boost::adjacency_list< boost::listS, boost::listS, boost::bidirectionalS > Graph
Definition graph.h:24
const T & add_const(T &s)
Definition helpers.h:44
T & indirect(const std::unique_ptr< T > &ptr)
Definition helpers.h:39
Definition analysis.h:7
Symbolic system for integer-based symbol analysis.
Simple computational operations in the dataflow graph.