P4C
The P4 Compiler
Loading...
Searching...
No Matches
graphs.h
1/*
2 * SPDX-FileCopyrightText: 2013 Barefoot Networks, Inc.
3 * Copyright 2013-present Barefoot Networks, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef BACKENDS_GRAPHS_GRAPHS_H_
9#define BACKENDS_GRAPHS_GRAPHS_H_
10
11#include "config.h"
12#include "lib/cstring.h"
13
16#ifndef HAVE_LIBBOOST_GRAPH
17#error "This backend requires the boost graph headers, which could not be found"
18#endif
19
20#include <map>
21#include <optional>
22#include <utility> // std::pair
23#include <vector>
24
25#include <boost/graph/adjacency_list.hpp>
26#include <boost/graph/graph_traits.hpp>
27#include <boost/graph/graphviz.hpp>
28
29#include "frontends/p4/parserCallGraph.h"
30#include "ir/ir.h"
31#include "ir/visitor.h"
32
33namespace P4 {
34
35class ReferenceMap;
36class TypeMap;
37
38} // namespace P4
39
40namespace P4::graphs {
41
42using namespace P4::literals;
43
45 public:
46 virtual ~EdgeTypeIface() {}
47 virtual cstring label() const = 0;
48};
49
50class EdgeUnconditional : public EdgeTypeIface {
51 public:
52 EdgeUnconditional() = default;
53 cstring label() const override { return cstring::empty; };
54};
55
56class EdgeIf : public EdgeTypeIface {
57 public:
58 enum class Branch { TRUE, FALSE };
59 explicit EdgeIf(Branch branch) : branch(branch) {}
60 cstring label() const override {
61 switch (branch) {
62 case Branch::TRUE:
63 return "TRUE"_cs;
64 case Branch::FALSE:
65 return "FALSE"_cs;
66 }
67 BUG("unreachable");
68 return cstring::empty;
69 };
70
71 private:
72 Branch branch;
73};
74
75class EdgeSwitch : public EdgeTypeIface {
76 public:
77 explicit EdgeSwitch(const IR::Expression *labelExpr) : labelExpr(labelExpr) {}
78 cstring label() const override {
79 std::stringstream sstream;
80 labelExpr->dbprint(sstream);
81 return cstring(sstream);
82 };
83
84 private:
85 const IR::Expression *labelExpr;
86};
87
88class Graphs : public Inspector {
89 public:
90 enum class VertexType {
91 TABLE,
92 KEY,
93 ACTION,
94 CONDITION,
95 SWITCH,
96 STATEMENTS,
97 CONTROL,
98 OTHER,
99 STATE,
100 EMPTY
101 };
102 struct Vertex {
103 cstring name;
104 VertexType type;
105 };
106
112 using GraphvizAttributes = std::map<cstring, cstring>;
113 using vertexProperties = boost::property<boost::vertex_attribute_t, GraphvizAttributes, Vertex>;
114 using edgeProperties = boost::property<
115 boost::edge_attribute_t, GraphvizAttributes,
116 boost::property<boost::edge_name_t, cstring, boost::property<boost::edge_index_t, int>>>;
117 using graphProperties = boost::property<
118 boost::graph_name_t, std::string,
119 boost::property<
120 boost::graph_graph_attribute_t, GraphvizAttributes,
121 boost::property<boost::graph_vertex_attribute_t, GraphvizAttributes,
122 boost::property<boost::graph_edge_attribute_t, GraphvizAttributes>>>>;
123 using Graph_ = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
124 vertexProperties, edgeProperties, graphProperties>;
125 using Graph = boost::subgraph<Graph_>;
126 using vertex_t = boost::graph_traits<Graph>::vertex_descriptor;
127
128 using Parents = std::vector<std::pair<vertex_t, EdgeTypeIface *>>;
129
132 std::optional<vertex_t> merge_other_statements_into_vertex();
133
134 vertex_t add_vertex(const cstring &name, VertexType type);
135 vertex_t add_and_connect_vertex(const cstring &name, VertexType type);
136 void add_edge(const vertex_t &from, const vertex_t &to, const cstring &name);
143 void add_edge(const vertex_t &from, const vertex_t &to, const cstring &name,
144 unsigned cluster_id);
145
147 public:
148 void operator()(Graph &g) const {
149 auto vertices = boost::vertices(g);
150 for (auto &vit = vertices.first; vit != vertices.second; ++vit) {
151 const auto &vinfo = g[*vit];
152 auto attrs = boost::get(boost::vertex_attribute, g);
153 attrs[*vit]["label"_cs] = vinfo.name;
154 attrs[*vit]["style"_cs] = vertexTypeGetStyle(vinfo.type);
155 attrs[*vit]["shape"_cs] = vertexTypeGetShape(vinfo.type);
156 attrs[*vit]["margin"_cs] = vertexTypeGetMargin(vinfo.type);
157 }
158 auto edges = boost::edges(g);
159 for (auto &eit = edges.first; eit != edges.second; ++eit) {
160 auto attrs = boost::get(boost::edge_attribute, g);
161 attrs[*eit]["label"_cs] = boost::get(boost::edge_name, g, *eit);
162 }
163 }
164
165 private:
166 static cstring vertexTypeGetShape(VertexType type) {
167 switch (type) {
168 case VertexType::TABLE:
169 case VertexType::ACTION:
170 return "ellipse"_cs;
171 default:
172 return "rectangle"_cs;
173 }
174 BUG("unreachable");
175 return cstring::empty;
176 }
177
178 static cstring vertexTypeGetStyle(VertexType type) {
179 switch (type) {
180 case VertexType::CONTROL:
181 return "dashed"_cs;
182 case VertexType::EMPTY:
183 return "invis"_cs;
184 case VertexType::KEY:
185 case VertexType::CONDITION:
186 case VertexType::SWITCH:
187 return "rounded"_cs;
188 default:
189 return "solid"_cs;
190 }
191 BUG("unreachable");
192 return cstring::empty;
193 }
194
195 static cstring vertexTypeGetMargin(VertexType type) {
196 switch (type) {
197 default:
198 return cstring::empty;
199 }
200 }
201 }; // end class GraphAttributeSetter
202
203 protected:
204 Graph *g{nullptr};
205 vertex_t start_v{};
206 vertex_t exit_v{};
207 Parents parents{};
208 std::vector<const IR::Statement *> statementsStack{};
209
210 private:
215 void limitStringSize(std::stringstream &sstream, std::stringstream &helper_sstream);
216};
217
218} // namespace P4::graphs
219
220#endif /* BACKENDS_GRAPHS_GRAPHS_H_ */
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition typeMap.h:32
Definition cstring.h:85
Definition graphs.h:44
Definition graphs.h:88
std::optional< vertex_t > merge_other_statements_into_vertex()
Definition graphs.cpp:50
std::map< cstring, cstring > GraphvizAttributes
Definition graphs.h:112
Definition graphs.h:102
Definition controls.cpp:19
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13