19#ifndef BACKENDS_TOFINO_BF_P4C_COMMON_BRIDGED_PACKING_H_
20#define BACKENDS_TOFINO_BF_P4C_COMMON_BRIDGED_PACKING_H_
22#include "backends/tofino/bf-p4c/bf-p4c-options.h"
23#include "backends/tofino/bf-p4c/common/extract_maupipe.h"
24#include "backends/tofino/bf-p4c/common/field_defuse.h"
25#include "backends/tofino/bf-p4c/common/pragma/collect_global_pragma.h"
26#include "backends/tofino/bf-p4c/logging/source_info_logging.h"
27#include "backends/tofino/bf-p4c/midend/blockmap.h"
28#include "backends/tofino/bf-p4c/midend/normalize_params.h"
29#include "backends/tofino/bf-p4c/midend/param_binding.h"
30#include "backends/tofino/bf-p4c/midend/simplify_references.h"
31#include "backends/tofino/bf-p4c/midend/type_checker.h"
32#include "backends/tofino/bf-p4c/phv/action_phv_constraints.h"
33#include "backends/tofino/bf-p4c/phv/constraints/constraints.h"
34#include "backends/tofino/bf-p4c/phv/phv.h"
35#include "backends/tofino/bf-p4c/phv/phv_fields.h"
36#include "frontends/common/resolveReferences/referenceMap.h"
37#include "frontends/common/resolveReferences/resolveReferences.h"
38#include "frontends/p4/methodInstance.h"
39#include "frontends/p4/typeMap.h"
57using FieldListEntry = std::pair<int, const IR::Type *>;
60using RepackedHeaders = std::vector<std::pair<const IR::HeaderOrMetadata *, std::string>>;
108 bool preorder(
const IR::BFN::Unit *unit)
override {
109 if (unit->thread() == EGRESS)
return false;
114 void postorder(
const IR::BFN::AliasMember *mem)
override;
115 void end_apply()
override;
150 candidateSourcesInParser;
159 bool preorder(
const IR::BFN::Extract *extract)
override;
160 void end_apply()
override;
190 parserAlignedFields.clear();
191 reverseParserAlignMap.clear();
192 return Inspector::init_apply(root);
195 bool preorder(
const IR::BFN::Extract *e)
override;
200 bool count(
const PHV::Field *f)
const {
return parserAlignedFields.count(f); }
204 if (!parserAlignedFields.count(f))
return emptySet;
205 return parserAlignedFields.at(f);
208 bool revCount(
const PHV::Field *f)
const {
return reverseParserAlignMap.count(f); }
212 if (!reverseParserAlignMap.count(f))
return emptySet;
213 return reverseParserAlignMap.at(f);
216 const FieldToFieldSet &getAlignedMap()
const {
return parserAlignedFields; }
217 const FieldToFieldSet &getReverseMap()
const {
return reverseParserAlignMap; }
220template <
typename NodeType,
typename Func,
typename Func2>
221void forAllMatchingDoPreAndPostOrder(
const IR::Node *root, Func &&function, Func2 &&function2) {
223 explicit NodeVisitor(Func &&function, Func2 &&function2)
224 : function(function), function2(function2) {}
227 bool preorder(
const NodeType *node)
override {
231 void postorder(
const NodeType *node)
override { function2(node); }
233 root->apply(NodeVisitor(std::forward<Func>(function), std::forward<Func2>(function2)));
236template <
typename NodeType,
typename Func>
237void forAllMatchingDoPostOrder(
const IR::Node *root, Func &&function) {
239 explicit NodeVisitor(Func &&function) : function(function) {}
241 void postorder(
const NodeType *node)
override { function(node); }
243 root->apply(NodeVisitor(std::forward<Func>(function)));
277 const FieldToFieldSet &getReverseDigestMap()
const {
return reverseDigestFieldMap; }
281 bool preorder(
const IR::BFN::DigestFieldList *fl)
override;
282 bool preorder(
const IR::HeaderOrMetadata *hdr)
override;
283 void end_apply()
override;
342 bool preorder(
const IR::HeaderOrMetadata *)
override;
343 bool preorder(
const IR::BFN::DigestFieldList *)
override;
345 void end_apply()
override;
352 template <
typename NodeType,
typename Func,
typename Func2>
353 void forAllMatching(
const IR::Node *root, Func &&function, Func2 &&function2) {
355 explicit NodeVisitor(Func &&function, Func2 &&function2)
356 : function(function), function2(function2) {}
359 bool preorder(
const NodeType *node)
override {
363 void postorder(
const NodeType *node)
override { function2(node); }
365 root->apply(NodeVisitor(std::forward<Func>(function), std::forward<Func2>(function2)));
373 ingressBridgedFields(b),
374 egressBridgedFields(e),
375 parserAlignedFields(g),
377 actionConstraints(a) {}
392 : collectIngressBridgedFields(p),
393 collectEgressBridgedFields(p),
394 collectParserAlignedFields(p),
395 collectDigestFields(p) {
397 &collectIngressBridgedFields,
398 &collectEgressBridgedFields,
399 &collectParserAlignedFields,
400 &collectDigestFields,
402 collectParserAlignedFields, collectDigestFields, a),
441 z3::context &context;
458 std::vector<const PHV::Field *> insert_padding(std::vector<std::pair<unsigned, std::string>> &);
460 void dump_unsat_core();
468 packingConstraints(pc),
469 constraints(constraints),
477 void print_assertions();
545 phvFieldToStructFieldMap;
571 packingCandidateFields(pcf),
572 packingConstraints(pc) {}
575 bool preorder(
const IR::HeaderOrMetadata *hdr)
override;
576 bool preorder(
const IR::BFN::DigestFieldList *dfl)
override;
579 void set_pipeline_name(
cstring name) { pipelineName = name; }
594 : repackedTypes(r) {}
596 bool preorder(
const IR::BFN::Type_FixedSizeHeader *h)
override {
597 auto width = [&](
const IR::Type_StructLike *s) ->
int {
599 for (
auto f : s->fields) rv += f->type->width_bits();
605 for (
auto f : fields)
606 if (f->hasAnnotation(
"padding"_cs)) count++;
611 auto genPadding = [&](
int size,
int id) {
612 cstring padFieldName =
"__pad_" + cstring::to_cstring(
id);
613 const IR::StructField *padField =
614 new IR::StructField(padFieldName,
615 {
new IR::Annotation(
IR::ID(
"padding"), {}),
616 new IR::Annotation(
IR::ID(
"overlayable"), {})},
617 IR::Type::Bits::get(size));
621 size_t bits =
static_cast<size_t>(width(h));
622 ERROR_CHECK(bits <= Device::pardeSpec().bitResubmitSize(),
"%1% digest limited to %2% bits",
624 auto pad_size = h->fixed_size - bits;
627 fields->append(h->fields);
628 auto index = countPadding(h->fields);
630 auto padding = genPadding(pad_size, index++);
631 fields->push_back(padding);
634 auto newType =
new IR::Type_Header(h->name, *fields);
635 repackedTypes.emplace(h->name, newType);
654 const IR::Node *postorder(IR::HeaderOrMetadata *h)
override;
655 const IR::Node *postorder(IR::BFN::DigestFieldList *d)
override;
656 const IR::BFN::DigestFieldList *repackFieldList(
657 cstring digest, std::vector<FieldListEntry> repackedFieldIndices,
658 const IR::Type_StructLike *repackedHeaderType,
659 const IR::BFN::DigestFieldList *origFieldList)
const;
662 const IR::Node *postorder(IR::Type_StructLike *h)
override;
663 const IR::Node *postorder(IR::StructExpression *h)
override;
666bool findFlexibleAnnotation(
const IR::Type_StructLike *);
680 return Inspector::init_apply(root);
683 bool preorder(
const IR::BFN::DeparserParameter *p)
override;
687 : phv(p), params(f) {}
698 static constexpr char const *PHASE0_PARSER_STATE_NAME =
"ingress::$phase0";
701 noPackFields.clear();
702 return Inspector::init_apply(root);
705 bool preorder(
const IR::BFN::ParserState *p)
override;
707 bool preorder(
const IR::BFN::DigestFieldList *d)
override;
711 : phv(p), noPackFields(f) {}
724 RepackedHeaders repacked;
726 std::unordered_set<std::string> hdrs;
730 bool preorder(
const IR::HeaderOrMetadata *h)
override;
733 void end_apply()
override;
736 std::string getFieldName(std::string hdr,
const IR::StructField *field)
const;
739 std::string pretty_print(
const IR::HeaderOrMetadata *h, std::string hdr)
const;
742 std::string strip_prefix(
cstring str, std::string pre);
747 std::string asm_output()
const;
790 std::string asm_output()
const;
804 std::vector<const IR::BFN::Pipe *> pipe;
829 void set_pipeline_name(
cstring name) { pipelineName = name; }
832 packWithConstraintSolver.set_pipeline_name(pipelineName);
833 packWithConstraintSolver.
optimize();
836 void solve() { packWithConstraintSolver.
solve(); }
838 void end_apply()
override;
840 void print_packing_candidate_fields()
const {
841 for (
auto &[hdr_type, fields] : packingCandidateFields) {
842 LOG3(
"Packing candidate fields for " << hdr_type <<
":");
843 for (
auto f : fields) {
848 void check_conflicting_constraints();
925using PipeAndGress = std::pair<std::pair<cstring, gress_t>, std::pair<cstring, gress_t>>;
935 const IR::Type *type;
940 bool operator<(
const Use &other)
const {
941 return std::tie(type, name, method, thread) <
942 std::tie(other.type, other.name, other.method, other.thread);
945 bool operator==(
const Use &other)
const {
946 return std::tie(type, name, method, thread) ==
947 std::tie(other.type, other.name, other.method, other.thread);
953 friend std::ostream &operator<<(std::ostream &,
const Use &u);
957 : refMap(refMap), typeMap(typeMap) {}
959 void postorder(
const IR::MethodCallExpression *mc)
override;
965 IR::BFN::Pipe::thread_t thread;
989 std::vector<const IR::BFN::Pipe *> *generate_bridge_pairs(std::vector<BridgeContext> &);
991 bool preorder(
const IR::P4Program *program)
override;
992 void end_apply(
const IR::Node *)
override;
1041 const IR::ToplevelBlock *getToplevelBlock()
const {
return evaluator->toplevel; }
Definition action_mutex.h:29
Definition action_phv_constraints.h:107
Definition extract_maupipe.h:212
Definition bf-p4c-options.h:28
Definition bridged_packing.h:929
Definition bridged_packing.h:302
Definition bridged_packing.h:145
ordered_map< cstring, cstring > bridged_to_orig
Map: bridged field name -> original field name.
Definition bridged_packing.h:156
Definition collect_global_pragma.h:28
Definition bridged_packing.h:104
ordered_map< cstring, cstring > bridged_to_orig
Key: bridged field name, value: original field name.
Definition bridged_packing.h:121
The class uses the Z3 solver to generate packing for a set of PHV fields given a set of constraints.
Definition bridged_packing.h:439
void add_constraints(cstring, ordered_set< const PHV::Field * > &)
Definition bridged_packing.cpp:1297
ordered_map< cstring, std::vector< const PHV::Field * > > solve(ordered_map< cstring, ordered_set< const PHV::Field * > > &)
Definition bridged_packing.cpp:1432
void add_mutually_aligned_constraints(ordered_set< const PHV::Field * > &)
Definition bridged_packing.cpp:1109
Definition constraints.h:149
Definition constraints.h:56
Definition bridged_packing.h:383
Definition bridged_packing.h:672
Definition bridged_packing.h:263
bool preorder(const IR::BFN::DigestFieldList *fl) override
Definition bridged_packing.cpp:169
Definition bridged_packing.h:765
Definition bridged_packing.h:693
Definition bridged_packing.h:750
Definition backends/tofino/bf-p4c/logging/pass_manager.h:36
Definition map_tables_to_actions.h:29
Definition mau_backtracker.h:29
Definition ir/pass_manager.h:40
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition symbitmatrix.h:27
Definition ordered_set.h:32
Definition phv_fields.h:154
Definition pack_conflicts.h:36
Definition bridged_packing.h:523
bool preorder(const IR::HeaderOrMetadata *hdr) override
Definition bridged_packing.cpp:1488
void optimize()
Definition bridged_packing.cpp:1628
void solve()
Definition bridged_packing.cpp:1669
void end_apply() override
Definition bridged_packing.cpp:1651
Definition param_binding.h:32
size_t bitResubmitSize() const
Definition parde_spec.h:395
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
Definition pa_no_pack.h:28
Definition bridged_packing.h:647
Definition mau/table_mutex.h:110
The pass analyzes the usage of bridged headers and adjusts their packing.
Definition bridged_packing.h:1002
Pass that collects source information.
Definition source_info_logging.h:39
Definition field_defuse.h:77
Definition tofino/bf-p4c/phv/constraints/constraints.cpp:21
@ AUTO
Creates if this is the first time writing to the log; otherwise, appends.
Definition filelog.h:43
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition phv/solver/action_constraint_solver.cpp:33
Definition bridged_packing.h:46
Definition bridged_packing.h:962
Definition bridged_packing.h:934
Definition table_dependency_graph.h:52