P4C
The P4 Compiler
Loading...
Searching...
No Matches
default_next.h
1
19#ifndef BF_P4C_MAU_DEFAULT_NEXT_H_
20#define BF_P4C_MAU_DEFAULT_NEXT_H_
21
22#include "bf-p4c/ir/control_flow_visitor.h"
23#include "bf-p4c/ir/table_tree.h"
24#include "bf-p4c/phv/utils/utils.h" // for operator<<(ordered_set)
25#include "lib/ordered_map.h"
26#include "lib/ordered_set.h"
27#include "mau_visitor.h"
28#include "next_table.h"
29
30using namespace P4;
31
33 int id = -1;
34 static int id_counter;
35 const bool &long_branch_disabled;
36 std::set<cstring> *errors;
39
40 bool preorder(const IR::Expression *) override { return false; }
41
42 bool preorder(const IR::MAU::Table *tbl) override {
43 LOG3(id << ": DefaultNext::preorder(" << tbl->name << ") prev=" << DBPrint::Brief
44 << prev_tbls << DBPrint::Reset);
45 if (tbl->is_detached_attached_tbl) return true;
46 if (tbl->run_before_exit) collect_run_before_exit_table(tbl);
47 for (auto prev : prev_tbls) {
48 if (possible_nexts.count(prev)) {
49 // Disabling for JBay, really only used for the characterize power, and necessary
50 // to run until that pass is converted to a ControlFlowVisitor
51 if (!possible_nexts.at(prev).count(tbl) && long_branch_disabled) {
52 error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
53 "%1% is applied in multiple "
54 "places, and the next-table information cannot correctly propagate "
55 "through this multiple application",
56 prev);
57 if (errors) errors->insert(prev->externalName());
58 }
59 }
60 possible_nexts[prev].insert(tbl);
61 }
62 prev_tbls.clear();
63 return true;
64 }
65
66 void collect_run_before_exit_table(const IR::MAU::Table *rbe_table) {
67 run_before_exit_tables[rbe_table->gress].push_back(rbe_table);
68 }
69
70 void postorder(const IR::MAU::Table *tbl) override {
71 LOG3(id << ": DefaultNext::postorder(" << tbl->name << ")");
72 prev_tbls.insert(tbl);
73 }
74
75 DefaultNext *clone() const override {
76 auto *rv = new DefaultNext(*this);
77 rv->id = ++id_counter;
78 LOG3(id << ": DefaultNext::clone -> " << rv->id);
79 return rv;
80 }
81
82 void flow_merge(Visitor &a_) override {
83 auto &a = dynamic_cast<DefaultNext &>(a_);
84 LOG3(id << ": DefaultNext::flow_merge <- " << a.id);
85 prev_tbls.insert(a.prev_tbls.begin(), a.prev_tbls.end());
86 }
87 void flow_copy(::ControlFlowVisitor &a_) override {
88 auto &a = dynamic_cast<DefaultNext &>(a_);
89 prev_tbls = a.prev_tbls;
90 run_before_exit_tables = a.run_before_exit_tables;
91 }
92
93 DefaultNext(const DefaultNext &a) = default;
94
95 bool filter_join_point(const IR::Node *n) override { return !n->is<IR::MAU::TableSeq>(); }
96
97 profile_t init_apply(const IR::Node *root) override {
98 LOG3("DefaultNext starting");
99 id = id_counter = 0;
100 return MauInspector::init_apply(root);
101 }
102
103 bool preorder(const IR::BFN::Pipe *pipe) override {
104 LOG5(TableTree("ingress"_cs, pipe->thread[INGRESS].mau)
105 << TableTree("egress"_cs, pipe->thread[EGRESS].mau)
106 << TableTree("ghost"_cs, pipe->ghost_thread.ghost_mau));
107 possible_nexts.clear();
108 prev_tbls.clear();
109 return true;
110 }
111
112 void postorder(const IR::BFN::Pipe *) override {
113 if (long_branch_disabled) {
114 for (auto prev : prev_tbls) {
115 if (possible_nexts.count(prev)) {
116 error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
117 "%1% is applied in multiple "
118 "places, and the next-table information cannot correctly propagate "
119 "through this multiple application",
120 prev);
121 if (errors) errors->insert(prev->externalName());
122 }
123 }
124 }
125 }
126
127 public:
128 std::map<gress_t, std::vector<const IR::MAU::Table *>> run_before_exit_tables;
129
130 explicit DefaultNext(const bool &lbd, std::set<cstring> *errs = nullptr)
131 : long_branch_disabled(lbd),
132 errors(errs),
133 possible_nexts(*new std::remove_reference<decltype(possible_nexts)>::type) {
134 joinFlows = false;
135 visitDagOnce = false;
136 BackwardsCompatibleBroken = true;
137 }
138
139 const IR::MAU::Table *next(const IR::MAU::Table *t) const {
140 if (possible_nexts.count(t)) {
141 BUG_CHECK(!possible_nexts.at(t).empty(), "unexpected empty set");
142 return possible_nexts.at(t).front();
143 }
144 return nullptr;
145 }
146
147 ordered_set<const IR::MAU::Table *> possible_next(const IR::MAU::Table *t) const {
148 if (possible_nexts.count(t)) return possible_nexts.at(t);
149 return {};
150 }
151
152 ordered_set<const IR::MAU::Table *> possible_next(cstring name) const {
153 for (auto &pn : possible_nexts) {
154 if (pn.first->name == name) return pn.second;
155 if (pn.first->match_table && pn.first->externalName() == name) return pn.second;
156 }
157 return {};
158 }
159
160 const IR::MAU::Table *next_in_thread(const IR::MAU::Table *t) const {
161 if (auto *n = next(t))
162 if (n->gress == t->gress) return n;
163 return nullptr;
164 }
165
166 UniqueId next_in_thread_uniq_id(const IR::MAU::Table *t) const {
167 if (auto *n = next(t))
168 if (n->gress == t->gress) return n->unique_id();
169 return UniqueId("END"_cs);
170 }
171
172 std::set<UniqueId> possible_next_uniq_id(const IR::MAU::Table *t) const {
173 std::set<UniqueId> rv;
174 for (auto n : possible_next(t))
175 if (n->gress == t->gress) rv.insert(n->unique_id());
176 if (rv.empty()) rv.insert(UniqueId("END"_cs));
177 return rv;
178 }
179
180 ordered_set<UniqueId> next_for(const IR::MAU::Table *tbl, cstring what) const override {
181 if (what == "$miss" && tbl->next.count("$try_next_stage"_cs)) what = "$try_next_stage"_cs;
182 if (tbl->actions.count(what) && tbl->actions.at(what)->exitAction) {
183 if (run_before_exit_tables.count(tbl->gress) && !tbl->run_before_exit)
184 return {(*run_before_exit_tables.at(tbl->gress).begin())->unique_id()};
185 else
186 return {};
187 }
188 if (!tbl->next.count(what)) what = "$default"_cs;
189 if (tbl->next.count(what) && !tbl->next.at(what)->empty())
190 return {tbl->next.at(what)->front()->unique_id()};
191 auto *nt = next_in_thread(tbl);
192 if (nt) return {nt->unique_id()};
193 return {};
194 }
195
196 bool uses_next_table(const IR::MAU::Table *) const override { return true; }
197
198 void dbprint(std::ostream &out) const override {
199 out << "DefaultNext:" << IndentCtl::indent;
200 for (auto &pn : possible_nexts) {
201 out << Log::endl << pn.first << ": {";
202 const char *sep = " ";
203 for (auto el : pn.second) {
204 out << sep << el;
205 sep = ", ";
206 }
207 out << (sep + 1) << "}";
208 }
209 out << IndentCtl::unindent;
210 }
211};
212
213#endif /* BF_P4C_MAU_DEFAULT_NEXT_H_ */
Definition default_next.h:32
Definition mau_visitor.h:29
Definition next_table.h:26
Definition visitor.h:463
Definition node.h:95
Definition unique_id.h:168
Definition visitor.h:78
Definition visitor.h:75
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition table_tree.h:29
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51
bool is() const noexcept
Definition rtti.h:216