P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
graphs.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef BACKENDS_GRAPHS_GRAPHS_H_
18#define BACKENDS_GRAPHS_GRAPHS_H_
19
20#include "config.h"
21
22// Shouldn't happen as cmake will not try to build this backend if the boost
23// graph headers couldn't be found.
24#ifndef HAVE_LIBBOOST_GRAPH
25#error "This backend requires the boost graph headers, which could not be found"
26#endif
27
28#include <map>
29#include <optional>
30#include <utility> // std::pair
31#include <vector>
32
33#include <boost/graph/adjacency_list.hpp>
34#include <boost/graph/graph_traits.hpp>
35#include <boost/graph/graphviz.hpp>
36
37#include "frontends/p4/parserCallGraph.h"
38#include "ir/ir.h"
39#include "ir/visitor.h"
40
41namespace P4 {
42
43class ReferenceMap;
44class TypeMap;
45
46} // namespace P4
47
48namespace graphs {
49
51 public:
52 virtual ~EdgeTypeIface() {}
53 virtual cstring label() const = 0;
54};
55
57 public:
58 EdgeUnconditional() = default;
59 cstring label() const override { return ""; };
60};
61
62class EdgeIf : public EdgeTypeIface {
63 public:
64 enum class Branch { TRUE, FALSE };
65 explicit EdgeIf(Branch branch) : branch(branch) {}
66 cstring label() const override {
67 switch (branch) {
68 case Branch::TRUE:
69 return "TRUE";
70 case Branch::FALSE:
71 return "FALSE";
72 }
73 BUG("unreachable");
74 return "";
75 };
76
77 private:
78 Branch branch;
79};
80
81class EdgeSwitch : public EdgeTypeIface {
82 public:
83 explicit EdgeSwitch(const IR::Expression *labelExpr) : labelExpr(labelExpr) {}
84 cstring label() const override {
85 std::stringstream sstream;
86 labelExpr->dbprint(sstream);
87 return cstring(sstream);
88 };
89
90 private:
91 const IR::Expression *labelExpr;
92};
93
94class Graphs : public Inspector {
95 public:
96 enum class VertexType {
97 TABLE,
98 KEY,
99 ACTION,
100 CONDITION,
101 SWITCH,
102 STATEMENTS,
103 CONTROL,
104 OTHER,
105 STATE,
106 EMPTY
107 };
108 struct Vertex {
109 cstring name;
110 VertexType type;
111 };
112
113 // The boost graph support for graphviz subgraphs is not very intuitive. In
114 // particular the write_graphviz code assumes the existence of a lot of
115 // properties. See
116 // https://stackoverflow.com/questions/29312444/how-to-write-graphviz-subgraphs-with-boostwrite-graphviz
117 // for more information.
118 using GraphvizAttributes = std::map<cstring, cstring>;
119 using vertexProperties = boost::property<boost::vertex_attribute_t, GraphvizAttributes, Vertex>;
120 using edgeProperties = boost::property<
121 boost::edge_attribute_t, GraphvizAttributes,
122 boost::property<boost::edge_name_t, cstring, boost::property<boost::edge_index_t, int>>>;
123 using graphProperties = boost::property<
124 boost::graph_name_t, cstring,
125 boost::property<
126 boost::graph_graph_attribute_t, GraphvizAttributes,
127 boost::property<boost::graph_vertex_attribute_t, GraphvizAttributes,
128 boost::property<boost::graph_edge_attribute_t, GraphvizAttributes>>>>;
129 using Graph_ = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
130 vertexProperties, edgeProperties, graphProperties>;
131 using Graph = boost::subgraph<Graph_>;
132 using vertex_t = boost::graph_traits<Graph>::vertex_descriptor;
133
134 using Parents = std::vector<std::pair<vertex_t, EdgeTypeIface *>>;
135
136 // merge misc control statements (action calls, extern method calls,
137 // assignments) into a single vertex to reduce graph complexity
138 std::optional<vertex_t> merge_other_statements_into_vertex();
139
140 vertex_t add_vertex(const cstring &name, VertexType type);
141 vertex_t add_and_connect_vertex(const cstring &name, VertexType type);
142 void add_edge(const vertex_t &from, const vertex_t &to, const cstring &name);
150 void add_edge(const vertex_t &from, const vertex_t &to, const cstring &name,
151 unsigned cluster_id);
152
154 public:
155 void operator()(Graph &g) const {
156 auto vertices = boost::vertices(g);
157 for (auto &vit = vertices.first; vit != vertices.second; ++vit) {
158 const auto &vinfo = g[*vit];
159 auto attrs = boost::get(boost::vertex_attribute, g);
160 attrs[*vit]["label"] = vinfo.name;
161 attrs[*vit]["style"] = vertexTypeGetStyle(vinfo.type);
162 attrs[*vit]["shape"] = vertexTypeGetShape(vinfo.type);
163 attrs[*vit]["margin"] = vertexTypeGetMargin(vinfo.type);
164 }
165 auto edges = boost::edges(g);
166 for (auto &eit = edges.first; eit != edges.second; ++eit) {
167 auto attrs = boost::get(boost::edge_attribute, g);
168 attrs[*eit]["label"] = boost::get(boost::edge_name, g, *eit);
169 }
170 }
171
172 private:
173 static cstring vertexTypeGetShape(VertexType type) {
174 switch (type) {
175 case VertexType::TABLE:
176 case VertexType::ACTION:
177 return "ellipse";
178 default:
179 return "rectangle";
180 }
181 BUG("unreachable");
182 return "";
183 }
184
185 static cstring vertexTypeGetStyle(VertexType type) {
186 switch (type) {
187 case VertexType::CONTROL:
188 return "dashed";
189 case VertexType::EMPTY:
190 return "invis";
191 case VertexType::KEY:
192 case VertexType::CONDITION:
193 case VertexType::SWITCH:
194 return "rounded";
195 default:
196 return "solid";
197 }
198 BUG("unreachable");
199 return "";
200 }
201
202 static cstring vertexTypeGetMargin(VertexType type) {
203 switch (type) {
204 default:
205 return "";
206 }
207 }
208 }; // end class GraphAttributeSetter
209
210 protected:
211 Graph *g{nullptr};
212 vertex_t start_v{};
213 vertex_t exit_v{};
214 Parents parents{};
215 std::vector<const IR::Statement *> statementsStack{};
216
217 private:
223 void limitStringSize(std::stringstream &sstream, std::stringstream &helper_sstream);
224};
225
226} // namespace graphs
227
228#endif /* BACKENDS_GRAPHS_GRAPHS_H_ */
Definition cstring.h:72
Definition graphs.h:62
Definition graphs.h:81
Definition graphs.h:50
Definition graphs.h:56
Definition graphs.h:94
Definition graphs.h:108
Definition applyOptionsPragmas.cpp:24
Definition controls.cpp:29