P4C
The P4 Compiler
Loading...
Searching...
No Matches
reset_invalidated_checksum_headers.h
1
19#ifndef BF_P4C_PARDE_RESET_INVALIDATED_CHECKSUM_HEADERS_H_
20#define BF_P4C_PARDE_RESET_INVALIDATED_CHECKSUM_HEADERS_H_
21
22#include "backends/tofino/bf-p4c/phv/phv_fields.h"
23#include "ir/ir.h"
24
38 const PhvInfo &phv;
39
40 std::map<const PHV::Field *, std::set<const PHV::Field *>> pov_bit_to_fields;
41
42 std::map<const PHV::Field *, const IR::Expression *> phv_field_to_expr;
43
44 explicit CollectPovBitToFields(const PhvInfo &phv) : phv(phv) {}
45
46 bool preorder(const IR::BFN::EmitField *emit) override {
47 auto pov_bit = phv.field(emit->povBit->field);
48 auto source = phv.field(emit->source->field);
49
50 phv_field_to_expr[pov_bit] = emit->povBit->field;
51 phv_field_to_expr[source] = emit->source->field;
52
53 pov_bit_to_fields[pov_bit].insert(source);
54 return false;
55 }
56
57 Visitor::profile_t init_apply(const IR::Node *root) override {
58 profile_t rv = Inspector::init_apply(root);
59 pov_bit_to_fields.clear();
60 phv_field_to_expr.clear();
61 return rv;
62 }
63};
64
69 const PhvInfo &phv;
70 const std::map<const PHV::Field *, std::set<const PHV::Field *>> &pov_bit_to_fields;
71
72 std::map<gress_t, ordered_set<const PHV::Field *>> invalidated_header_pov_bits;
73
74 std::map<const PHV::Field *, const PHV::Field *> invalidated_field_to_pov_bit;
75
76 std::map<const PHV::Field *, ordered_set<const PHV::Field *>>
77 pov_bit_to_invalidated_checksum_fields;
78
80 const PhvInfo &phv,
81 const std::map<const PHV::Field *, std::set<const PHV::Field *>> &pov_bit_to_fields)
82 : phv(phv), pov_bit_to_fields(pov_bit_to_fields) {}
83
84 bool preorder(const IR::MAU::Primitive *p) override {
85 auto table = findContext<IR::MAU::Table>();
86 auto gress = table->gress;
87
88 if (p->name == "modify_field") {
89 auto dst = p->operands[0]->to<IR::Member>();
90 auto src = p->operands[1]->to<IR::Constant>();
91
92 if (dst && dst->member == "$valid" && src && src->asInt() == 0) {
93 auto dst_field = phv.field(dst);
94 invalidated_header_pov_bits[gress].insert(dst_field);
95
96 if (pov_bit_to_fields.count(dst_field)) {
97 for (auto f : pov_bit_to_fields.at(dst_field)) {
98 invalidated_field_to_pov_bit[f] = dst_field;
99 LOG4(f->name << " can be invalidated");
100 }
101 }
102 }
103 }
104
105 return false;
106 }
107
108 bool preorder(const IR::BFN::EmitChecksum *checksum) override {
109 auto csum_dest = phv.field(checksum->dest->field);
110 for (auto source : checksum->sources) {
111 auto field = phv.field(source->field->field);
112
113 if (invalidated_field_to_pov_bit.count(field)) {
114 auto pov_bit = invalidated_field_to_pov_bit.at(field);
115 if (pov_bit->header() == csum_dest->header()) continue;
116 auto checksum_pov_bit = phv.field(checksum->povBit->field);
117 if (pov_bit != checksum_pov_bit) {
118 pov_bit_to_invalidated_checksum_fields[pov_bit].insert(field);
119
120 LOG4("checksum payload field " << field->name << " can be invalidated");
121 }
122 }
123 }
124
125 return false;
126 }
127
128 Visitor::profile_t init_apply(const IR::Node *root) override {
129 profile_t rv = Inspector::init_apply(root);
130 invalidated_field_to_pov_bit.clear();
131 invalidated_header_pov_bits.clear();
132 pov_bit_to_invalidated_checksum_fields.clear();
133 return rv;
134 }
135};
136
141 const PhvInfo &phv;
142 const CollectInvalidatedHeaders &invalidated_headers;
143
144 public:
145 std::map<const PHV::Field *, const IR::TempVar *> pov_bit_to_parsed_valid_bit;
146
147 InsertParsedValidBits(const PhvInfo &phv, const CollectInvalidatedHeaders &invalidated_headers)
148 : phv(phv), invalidated_headers(invalidated_headers) {}
149
150 private:
151 IR::TempVar *create_parsed_valid_bit(const PHV::Field *pov_bit) {
152 std::string pov_bit_name(pov_bit->name.c_str());
153 auto pos = pov_bit_name.find("$valid");
154
155 BUG_CHECK(pos != std::string::npos, "pov bit name does not end with $valid?");
156
157 std::string parsed_valid_bit_name = pov_bit_name.replace(pos, 7, "$parsed");
158
159 auto parsed_valid_bit =
160 new IR::TempVar(IR::Type::Bits::get(1), false, cstring(parsed_valid_bit_name));
161
162 LOG4("created " << parsed_valid_bit_name);
163 return parsed_valid_bit;
164 }
165
166 bool preorder(IR::BFN::ParserState *state) override {
168
169 for (auto stmt : state->statements) {
170 statements.push_back(stmt);
171
172 if (auto extract = stmt->to<IR::BFN::Extract>()) {
173 auto dest = phv.field(extract->dest->field);
174 if (!dest || !dest->pov) continue;
175
176 if (invalidated_headers.pov_bit_to_invalidated_checksum_fields.count(dest)) {
177 auto parsed_valid_bit = create_parsed_valid_bit(dest);
178 pov_bit_to_parsed_valid_bit[dest] = parsed_valid_bit;
179
180 auto rval = new IR::BFN::ConstantRVal(IR::Type::Bits::get(1), 1);
181 auto extract = new IR::BFN::Extract(parsed_valid_bit, rval);
182 statements.push_back(extract);
183 }
184 }
185 }
186
187 state->statements = statements;
188
189 return true;
190 }
191
192 Visitor::profile_t init_apply(const IR::Node *root) override {
193 profile_t rv = ParserModifier::init_apply(root);
194 pov_bit_to_parsed_valid_bit.clear();
195 return rv;
196 }
197};
198
203 const std::map<const PHV::Field *, const IR::Expression *> &phv_field_to_expr;
204 const CollectInvalidatedHeaders &invalidated_headers;
205 const InsertParsedValidBits &parsed_valid_bits;
206
207 std::map<gress_t, std::vector<IR::MAU::Table *>> tables_to_insert;
208 IR::MAU::Table *create_actions(gress_t gress,
209 const ordered_set<const PHV::Field *> &fields_to_reset,
210 IR::BFN::Pipe *pipe) {
211 auto action = new IR::MAU::Action("__reset_invalidated_checksum_fields__");
212 action->default_allowed = action->init_default = true;
213
214 for (auto field : fields_to_reset) {
215 auto field_expr = phv_field_to_expr.at(field);
216 auto reset = new IR::MAU::Instruction(
217 "set"_cs, field_expr, new IR::Constant(IR::Type_Bits::get(field->size), 0));
218 action->action.push_back(reset);
219 auto *annotation = new IR::Annotation(IR::ID("pa_no_overlay"),
220 {new IR::StringLiteral(IR::ID(toString(gress))),
221 new IR::StringLiteral(IR::ID(field->name))});
222 pipe->global_pragmas.push_back(annotation);
223 LOG3("Added pa_no_overlay pragma on field: " << field->name
224 << " in gress: " << field->gress);
225 }
226
227 static int id = 0;
228 auto table_name =
229 toString(gress) + "_reset_invalidated_checksum_fields_" + cstring::to_cstring(id++);
230 auto t = new IR::MAU::Table(table_name, gress);
231
232 t->is_compiler_generated = true;
233 t->run_before_exit = true;
234 t->actions[action->name] = action;
235 t->match_table = new IR::P4Table(table_name.c_str(), new IR::TableProperties());
236
237 return t;
238 }
239
240 IR::MAU::Table *create_reset_table(gress_t gress, const PHV::Field *pov_bit,
241 const ordered_set<const PHV::Field *> &fields_to_reset,
242 IR::BFN::Pipe *pipe) {
243 auto ac = create_actions(gress, fields_to_reset, pipe);
244
245 static int id = 0;
246 cstring gateway_name = toString(gress) + "_reset_invalidated_checksum_fields_cond_" +
247 cstring::to_cstring(id++);
248
249 auto pov_bit_expr = phv_field_to_expr.at(pov_bit);
250 auto parsed_valid_bit = parsed_valid_bits.pov_bit_to_parsed_valid_bit.at(pov_bit);
251
252 auto cond = new IR::LAnd(new IR::LNot(pov_bit_expr), parsed_valid_bit);
253 auto gw = new IR::MAU::Table(gateway_name, gress, cond);
254
255 gw->is_compiler_generated = true;
256 gw->next.emplace("$true"_cs, new IR::MAU::TableSeq(ac));
257
258 return gw;
259 }
260
261 IR::MAU::TableSeq *preorder(IR::MAU::TableSeq *seq) override {
262 prune();
263
264 gress_t gress = VisitingThread(this);
265
266 if (tables_to_insert.count(gress)) {
267 auto &tables = tables_to_insert.at(gress);
268
269 LOG4(tables.size() << " reset invalidated checksum fields table to insert at "
270 << gress);
271
272 for (auto t : tables) seq->tables.push_back(t);
273 }
274
275 return seq;
276 }
277
278 IR::BFN::Pipe *preorder(IR::BFN::Pipe *pipe) override {
279 for (auto &gf : invalidated_headers.invalidated_header_pov_bits) {
280 auto gress = gf.first;
281
282 for (auto pov_bit : gf.second) {
283 if (invalidated_headers.pov_bit_to_invalidated_checksum_fields.count(pov_bit)) {
284 auto &fields_to_reset =
285 invalidated_headers.pov_bit_to_invalidated_checksum_fields.at(pov_bit);
286
287 // At the end of the control flow, insert table to reset invalidated header:
288 //
289 // if (hdr.$parsed && !hdr.$valid)
290 // hdr = 0;
291 //
292 // For now, create one table for each invalidated header.
293 //
294 // Combine multiple headers into single table? What's the tradeoff?
295 // IMEM capacity, instr color, and induces no overlay constraint? TODO
296 //
297 auto t = create_reset_table(gress, pov_bit, fields_to_reset, pipe);
298 tables_to_insert[gress].push_back(t);
299 }
300 }
301 }
302 return pipe;
303 }
304
305 Visitor::profile_t init_apply(const IR::Node *root) override {
306 profile_t rv = MauTransform::init_apply(root);
307 tables_to_insert.clear();
308 return rv;
309 }
310
311 public:
313 const std::map<const PHV::Field *, const IR::Expression *> &phv_field_to_expr,
314 const CollectInvalidatedHeaders &invalidated_headers,
315 const InsertParsedValidBits &parsed_valid_bits)
316 : phv_field_to_expr(phv_field_to_expr),
317 invalidated_headers(invalidated_headers),
318 parsed_valid_bits(parsed_valid_bits) {}
319};
320
326 public:
327 explicit ResetInvalidatedChecksumHeaders(const PhvInfo &phv) {
328 auto collect_pov_bit_to_fields = new CollectPovBitToFields(phv);
329
330 auto collect_invalidated_headers =
331 new CollectInvalidatedHeaders(phv, collect_pov_bit_to_fields->pov_bit_to_fields);
332
333 auto insert_parsed_valid_bits =
334 new InsertParsedValidBits(phv, *collect_invalidated_headers);
335
336 auto insert_reset_tables = new InsertTableToResetInvalidatedHeaders(
337 collect_pov_bit_to_fields->phv_field_to_expr, *collect_invalidated_headers,
338 *insert_parsed_valid_bits);
339
340 addPasses({collect_pov_bit_to_fields, collect_invalidated_headers, insert_parsed_valid_bits,
341 insert_reset_tables});
342 }
343};
344
345#endif /* BF_P4C_PARDE_RESET_INVALIDATED_CHECKSUM_HEADERS_H_ */
Definition mau_visitor.h:55
Definition node.h:94
Definition vector.h:59
Definition visitor.h:400
Definition ir/pass_manager.h:40
Definition visitor.h:78
Definition cstring.h:85
Definition ordered_set.h:32
Definition phv_fields.h:154
cstring name
Definition phv_fields.h:161
Definition phv_fields.h:1095
Definition reset_invalidated_checksum_headers.h:140
Definition reset_invalidated_checksum_headers.h:202
Top level PassManager.
Definition reset_invalidated_checksum_headers.h:325
Definition reset_invalidated_checksum_headers.h:68
Definition parde_visitor.h:117
Definition parde_visitor.h:78
Definition reset_invalidated_checksum_headers.h:37
Definition id.h:28