119 const IR::Constant *constant =
nullptr;
123 explicit Value(
const IR::Constant *c) : constant(c) {}
125 explicit Value(
const Value &other) : field(other.field), constant(other.constant) {
126 if (field && constant) BUG(
"Value cannot be both field and constant");
131 constant = other.constant;
132 if (field && constant) BUG(
"Value cannot be both field and constant");
136 std::string print()
const {
137 std::stringstream ss;
141 ss <<
"0x" << std::hex << constant << std::dec;
145 bool operator<(
const Value &other)
const {
146 if (field && other.field)
147 return field->
id < other.field->
id;
148 else if (constant && other.constant)
149 return constant->value < other.constant->value;
150 else if (field && other.constant)
152 else if (constant && other.field)
155 BUG(
"Value is neither constant nor field?");
158 bool operator==(
const Value &other)
const {
159 if (field != other.field) {
161 }
else if (constant && other.constant) {
162 if (!constant->equiv(*(other.constant)))
return false;
163 }
else if (constant != other.constant) {
234 const IR::Expression *get_valid_bit_expr(
const PHV::Field *f)
const {
235 auto vld = field_to_valid_bit.at(f);
236 return field_to_expr.at(vld);
244 bool preorder(
const IR::MAU::Instruction *instr)
override {
245 auto action = findContext<IR::MAU::Action>();
247 if (instr->operands.size() != 2)
return false;
249 auto dst = instr->operands[0];
250 auto f_dst = phv.field(dst);
252 if (f_dst && f_dst->pov) {
253 auto src = instr->operands[1];
254 auto c = src->to<IR::Constant>();
256 if (c->equiv(IR::Constant(IR::Type::Bits::get(1), 1)))
257 validate_to_action[f_dst].insert(action);
258 else if (c->equiv(IR::Constant(IR::Type::Bits::get(1), 0)))
259 invalidate_to_action[f_dst].insert(action);
266 bool preorder(
const IR::BFN::Emit *emit)
override {
267 auto pov_bit = emit->povBit->field;
268 auto f_pov_bit = phv.field(pov_bit);
269 field_to_expr[f_pov_bit] = pov_bit;
271 if (
auto ef = emit->to<IR::BFN::EmitField>()) {
272 auto f = phv.field(ef->source->field);
273 field_to_valid_bit[f] = f_pov_bit;
274 }
else if (
auto ec = emit->to<IR::BFN::EmitChecksum>()) {
275 auto f = phv.field(ec->dest->field);
276 field_to_valid_bit[f] = f_pov_bit;
278 BUG(
"Unknown deparser emit type %1%", emit);
284 void end_apply()
override {
286 LOG1(
"=== DONE collecting header validity bits ===");
289 void dbprint(std::ostream &out)
const {
290 for (
auto &kv : field_to_valid_bit)
291 out << kv.first->name <<
" : " << kv.second->name << std::endl;
318 std::map<gress_t, ordered_set<const IR::Constant *>> all_constants;
322 : phv(phv), uses(uses), defuse(defuse), dg(dg) {
324 visitDagOnce =
false;
325 BackwardsCompatibleBroken =
true;
328 const IR::MAU::Action *get_action(
const Assign *assign)
const {
329 auto action = instr_to_action.at(assign->instr);
333 const IR::MAU::Table *get_table(
const Assign *assign)
const {
334 auto action = instr_to_action.at(assign->instr);
335 auto table = action_to_table.at(action);
339 std::string print_assign_context(
const Assign *assign)
const {
340 auto action = instr_to_action.at(assign->instr);
341 auto table = action_to_table.at(action);
343 std::stringstream ss;
344 ss <<
"(" << table->name <<
" : " << action->name <<
")";
348 std::string print_assign(
const Assign *assign)
const {
349 std::stringstream ss;
351 ss << assign->print();
353 ss << print_assign_context(assign);
357 void remove_weak_field(
const PHV::Field *field) {
358 field_to_weak_assigns.erase(field);
359 read_only_weak_fields.erase(field);
363 void dbprint(std::ostream &out)
const;
366 bool filter_join_point(
const IR::Node *)
override {
return true; }
368 void flow_merge(
Visitor &other_)
override {
371 for (
auto &kv : other.field_to_weak_assigns) {
372 for (
auto a : kv.second) field_to_weak_assigns[kv.first].insert(a);
375 strong_fields.insert(other.strong_fields.begin(), other.strong_fields.end());
377 for (
auto a : strong_fields) add_strong_field(a);
379 for (
auto &kv : other.instr_to_action) instr_to_action[kv.first] = kv.second;
381 for (
auto &kv : other.action_to_table) action_to_table[kv.first] = kv.second;
386 field_to_weak_assigns = other.field_to_weak_assigns;
387 strong_fields = other.strong_fields;
388 instr_to_action = other.instr_to_action;
389 action_to_table = other.action_to_table;
397 auto rv = Inspector::init_apply(root);
399 field_to_weak_assigns.clear();
400 strong_fields.clear();
402 instr_to_action.clear();
403 action_to_table.clear();
408 void end_apply()
override {
409 add_read_only_weak_fields();
411 elim_by_strong_transitivity();
413 elim_non_byte_aligned_fields();
420 LOG1(
"=== DONE collecting weak fields ===");
424 const IR::Constant *const_src,
const IR::MAU::Instruction *instr);
426 void add_strong_field(
const PHV::Field *f, std::string reason =
"");
428 static bool other_elim_reason(
const PHV::Field *f) {
433 bool preorder(
const IR::MAU::TableKey *ixbar)
override;
434 bool preorder(
const IR::MAU::StatefulAlu *)
override {
return false; }
435 bool preorder(
const IR::MAU::Instruction *instr)
override;
441 bool is_strong_by_transitivity(
const PHV::Field *dst);
443 void add_read_only_weak_fields();
444 void get_all_constants();
446 void elim_by_strong_transitivity();
447 void elim_non_byte_aligned_fields();
459 std::vector<FieldGroup> weak_field_groups;
468 bool is_weak_assign(
const IR::MAU::Instruction *instr)
const;
470 std::string print_assign_chain(
const AssignChain &chain)
const;
472 std::string print_value_map(
const FieldGroup &weak_field_group,
485 void group_weak_fields();
487 std::vector<const IR::MAU::Table *> get_next_tables(
488 const IR::MAU::Table *curr_table,
492 const IR::MAU::Table *curr_table,
498 bool compute_all_reachable_values_at_deparser(
const FieldGroup &weak_field_group);
534 std::map<gress_t, std::vector<IR::MAU::Table *>> tables_to_insert;
552 : pov_bits(pov_bits),
553 weak_fields(values_at_deparser.weak_fields),
554 values_at_deparser(values_at_deparser) {}
556 void dbprint(std::ostream &out)
const;
560 auto it = group.begin();
564 std::vector<const IR::Expression *> get_valid_bits(
const FieldGroup &group);
568 std::vector<const IR::TempVar *> create_action_ctl_bits(
580 const IR::TempVar *find_equiv_version_bit_for_value(
const PHV::Field *f,
unsigned version,
584 const IR::TempVar *find_equiv_version_bit_for_value(
const PHV::Field *f,
589 unsigned version,
const Value &value);
593 unsigned encode_assign_chain(
const AssignChain &chain,
595 bool is_valid(
const PHV::Field *f,
const std::vector<const IR::Expression *> &vld_bits_onset);
599 IR::MAU::TableSeq *preorder(IR::MAU::TableSeq *seq)
override;
603 bool is_trivial_group(
const FieldGroup &group);
605 void resolve_trivial_group(
const FieldGroup &group);
607 std::pair<std::map<gress_t, std::vector<FieldGroup>>,
608 std::map<gress_t, std::vector<FieldGroup>>>
609 coalesce_weak_field_groups();
613 void end_apply()
override {
615 LOG1(
"=== DONE synthesizing decaf POV encoder ===");
631 std::map<gress_t, ordered_map<const IR::Constant *, std::vector<uint8_t>>> const_to_bytes;
634 std::map<gress_t, ordered_map<uint8_t, const IR::TempVar *>> byte_to_temp_var;
637 std::map<gress_t, ordered_set<uint8_t>> deparser_bytes;
640 : values_at_deparser(values_at_deparser) {}
642 void dbprint(std::ostream &out)
const;
644 bool is_inserted(
const IR::TempVar *constant)
const {
645 for (
auto &kv : byte_to_temp_var) {
646 for (
auto &bt : kv.second) {
647 if (bt.second == constant)
return true;
654 void create_temp_var_for_parser_constant_bytes(
659 void end_apply()
override {
661 LOG1(
"=== DONE inserting parser constants ===");
664 void insert_init_consts_state(IR::BFN::Parser *parser);
666 IR::BFN::Parser *preorder(IR::BFN::Parser *parser)
override;
716 : phv(phv), synth_pov_encoder(synth_pov_encoder), create_consts(create_consts) {}
719 void end_apply()
override { LOG1(
"=== DONE rewriting deparser ==="); }
722 const IR::TempVar *pov_bit);
726 const IR::Expression *find_emit_source(
const PHV::Field *field,
731 std::vector<const IR::BFN::Emit *> coalesce_disjoint_emits(
732 const std::vector<const IR::BFN::Emit *> &disjoint_emits);
734 void coalesce_emits_for_packing(
735 IR::BFN::Deparser *deparser,
738 void infer_deparser_no_repeat_constraint(
739 IR::BFN::Deparser *deparser,
742 bool preorder(IR::BFN::Deparser *deparser)
override;
763 collect_hdr_valid_bits(phv),
764 collect_weak_fields(phv, uses, defuse, dg),
765 values_at_deparser(collect_weak_fields),
766 synth_pov_encoder(collect_hdr_valid_bits, values_at_deparser),
767 create_consts(values_at_deparser),
768 rewrite_weak_fields(values_at_deparser, synth_pov_encoder),
769 rewrite_deparser(phv, synth_pov_encoder, create_consts) {
771 &uses, &collect_hdr_valid_bits, &collect_weak_fields, &values_at_deparser,
774 &rewrite_weak_fields,