40 std::map<const PHV::Field *, std::set<const PHV::Field *>> pov_bit_to_fields;
42 std::map<const PHV::Field *, const IR::Expression *> phv_field_to_expr;
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);
50 phv_field_to_expr[pov_bit] = emit->povBit->field;
51 phv_field_to_expr[source] = emit->source->field;
53 pov_bit_to_fields[pov_bit].insert(source);
58 profile_t rv = Inspector::init_apply(root);
59 pov_bit_to_fields.clear();
60 phv_field_to_expr.clear();
70 const std::map<const PHV::Field *, std::set<const PHV::Field *>> &pov_bit_to_fields;
72 std::map<gress_t, ordered_set<const PHV::Field *>> invalidated_header_pov_bits;
74 std::map<const PHV::Field *, const PHV::Field *> invalidated_field_to_pov_bit;
76 std::map<const PHV::Field *, ordered_set<const PHV::Field *>>
77 pov_bit_to_invalidated_checksum_fields;
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) {}
84 bool preorder(
const IR::MAU::Primitive *p)
override {
85 auto table = findContext<IR::MAU::Table>();
86 auto gress = table->gress;
88 if (p->name ==
"modify_field") {
89 auto dst = p->operands[0]->to<IR::Member>();
90 auto src = p->operands[1]->to<IR::Constant>();
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);
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");
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);
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);
120 LOG4(
"checksum payload field " << field->name <<
" can be invalidated");
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();
145 std::map<const PHV::Field *, const IR::TempVar *> pov_bit_to_parsed_valid_bit;
148 : phv(phv), invalidated_headers(invalidated_headers) {}
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");
155 BUG_CHECK(pos != std::string::npos,
"pov bit name does not end with $valid?");
157 std::string parsed_valid_bit_name = pov_bit_name.replace(pos, 7,
"$parsed");
159 auto parsed_valid_bit =
160 new IR::TempVar(IR::Type::Bits::get(1),
false,
cstring(parsed_valid_bit_name));
162 LOG4(
"created " << parsed_valid_bit_name);
163 return parsed_valid_bit;
166 bool preorder(IR::BFN::ParserState *state)
override {
169 for (
auto stmt : state->statements) {
170 statements.push_back(stmt);
172 if (
auto extract = stmt->to<IR::BFN::Extract>()) {
173 auto dest = phv.field(extract->dest->field);
174 if (!dest || !dest->pov)
continue;
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;
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);
187 state->statements = statements;
193 profile_t rv = ParserModifier::init_apply(root);
194 pov_bit_to_parsed_valid_bit.clear();
203 const std::map<const PHV::Field *, const IR::Expression *> &phv_field_to_expr;
207 std::map<gress_t, std::vector<IR::MAU::Table *>> tables_to_insert;
208 IR::MAU::Table *create_actions(gress_t gress,
210 IR::BFN::Pipe *pipe) {
211 auto action =
new IR::MAU::Action(
"__reset_invalidated_checksum_fields__");
212 action->default_allowed = action->init_default =
true;
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);
229 toString(gress) +
"_reset_invalidated_checksum_fields_" + cstring::to_cstring(
id++);
230 auto t =
new IR::MAU::Table(table_name, gress);
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());
240 IR::MAU::Table *create_reset_table(gress_t gress,
const PHV::Field *pov_bit,
242 IR::BFN::Pipe *pipe) {
243 auto ac = create_actions(gress, fields_to_reset, pipe);
246 cstring gateway_name = toString(gress) +
"_reset_invalidated_checksum_fields_cond_" +
247 cstring::to_cstring(
id++);
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);
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);
255 gw->is_compiler_generated =
true;
256 gw->next.emplace(
"$true"_cs,
new IR::MAU::TableSeq(ac));
261 IR::MAU::TableSeq *preorder(IR::MAU::TableSeq *seq)
override {
264 gress_t gress = VisitingThread(
this);
266 if (tables_to_insert.count(gress)) {
267 auto &tables = tables_to_insert.at(gress);
269 LOG4(tables.size() <<
" reset invalidated checksum fields table to insert at "
272 for (
auto t : tables) seq->tables.push_back(t);
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;
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);
297 auto t = create_reset_table(gress, pov_bit, fields_to_reset, pipe);
298 tables_to_insert[gress].push_back(t);
306 profile_t rv = MauTransform::init_apply(root);
307 tables_to_insert.clear();
313 const std::map<const PHV::Field *, const IR::Expression *> &phv_field_to_expr,
316 : phv_field_to_expr(phv_field_to_expr),
317 invalidated_headers(invalidated_headers),
318 parsed_valid_bits(parsed_valid_bits) {}
330 auto collect_invalidated_headers =
333 auto insert_parsed_valid_bits =
337 collect_pov_bit_to_fields->phv_field_to_expr, *collect_invalidated_headers,
338 *insert_parsed_valid_bits);
340 addPasses({collect_pov_bit_to_fields, collect_invalidated_headers, insert_parsed_valid_bits,
341 insert_reset_tables});