19#ifndef BACKENDS_TOFINO_BF_P4C_COMMON_BRIDGED_PACKING_H_
20#define BACKENDS_TOFINO_BF_P4C_COMMON_BRIDGED_PACKING_H_
24#include "backends/tofino/bf-p4c/bf-p4c-options.h"
25#include "backends/tofino/bf-p4c/common/extract_maupipe.h"
26#include "backends/tofino/bf-p4c/common/field_defuse.h"
27#include "backends/tofino/bf-p4c/common/pragma/collect_global_pragma.h"
28#include "backends/tofino/bf-p4c/logging/source_info_logging.h"
29#include "backends/tofino/bf-p4c/midend/blockmap.h"
30#include "backends/tofino/bf-p4c/midend/normalize_params.h"
31#include "backends/tofino/bf-p4c/midend/param_binding.h"
32#include "backends/tofino/bf-p4c/midend/simplify_references.h"
33#include "backends/tofino/bf-p4c/midend/type_checker.h"
34#include "backends/tofino/bf-p4c/phv/action_phv_constraints.h"
35#include "backends/tofino/bf-p4c/phv/constraints/constraints.h"
36#include "backends/tofino/bf-p4c/phv/phv.h"
37#include "backends/tofino/bf-p4c/phv/phv_fields.h"
38#include "frontends/common/resolveReferences/referenceMap.h"
39#include "frontends/common/resolveReferences/resolveReferences.h"
40#include "frontends/p4/methodInstance.h"
41#include "frontends/p4/typeMap.h"
58using FieldListEntry = std::pair<int, const IR::Type *>;
61using RepackedHeaders = std::vector<std::pair<const IR::HeaderOrMetadata *, std::string>>;
109 bool preorder(
const IR::BFN::Unit *unit)
override {
110 if (unit->thread() == EGRESS)
return false;
115 void postorder(
const IR::BFN::AliasMember *mem)
override;
116 void end_apply()
override;
119 explicit CollectIngressBridgedFields(
const PhvInfo &phv) : phv(phv) {}
151 candidateSourcesInParser;
154 explicit CollectEgressBridgedFields(
const PhvInfo &p) : phv(p) {}
160 bool preorder(
const IR::BFN::Extract *extract)
override;
161 void end_apply()
override;
186 FieldToFieldSet parserAlignedFields;
188 FieldToFieldSet reverseParserAlignMap;
191 parserAlignedFields.clear();
192 reverseParserAlignMap.clear();
193 return Inspector::init_apply(root);
196 bool preorder(
const IR::BFN::Extract *e)
override;
199 explicit GatherParserExtracts(
const PhvInfo &p) : phv(p) {}
201 bool count(
const PHV::Field *f)
const {
return parserAlignedFields.count(f); }
205 if (!parserAlignedFields.count(f))
return emptySet;
206 return parserAlignedFields.at(f);
209 bool revCount(
const PHV::Field *f)
const {
return reverseParserAlignMap.count(f); }
213 if (!reverseParserAlignMap.count(f))
return emptySet;
214 return reverseParserAlignMap.at(f);
217 const FieldToFieldSet &getAlignedMap()
const {
return parserAlignedFields; }
218 const FieldToFieldSet &getReverseMap()
const {
return reverseParserAlignMap; }
221template <
typename NodeType,
typename Func,
typename Func2>
222void forAllMatchingDoPreAndPostOrder(
const IR::Node *root, Func &&function, Func2 &&function2) {
224 explicit NodeVisitor(Func &&function, Func2 &&function2)
225 : function(function), function2(function2) {}
228 bool preorder(
const NodeType *node)
override {
232 void postorder(
const NodeType *node)
override { function2(node); }
234 root->apply(NodeVisitor(std::forward<Func>(function), std::forward<Func2>(function2)));
237template <
typename NodeType,
typename Func>
238void forAllMatchingDoPostOrder(
const IR::Node *root, Func &&function) {
240 explicit NodeVisitor(Func &&function) : function(function) {}
242 void postorder(
const NodeType *node)
override { function(node); }
244 root->apply(NodeVisitor(std::forward<Func>(function)));
272 FieldToFieldSet digestFieldMap;
273 FieldToFieldSet reverseDigestFieldMap;
276 const FieldToFieldSet &getDigestMap()
const {
return digestFieldMap; }
278 const FieldToFieldSet &getReverseDigestMap()
const {
return reverseDigestFieldMap; }
281 explicit GatherDigestFields(
const PhvInfo &p) : phv(p) {}
282 bool preorder(
const IR::BFN::DigestFieldList *fl)
override;
283 bool preorder(
const IR::HeaderOrMetadata *hdr)
override;
284 void end_apply()
override;
343 bool preorder(
const IR::HeaderOrMetadata *)
override;
344 bool preorder(
const IR::BFN::DigestFieldList *)
override;
346 void end_apply()
override;
353 template <
typename NodeType,
typename Func,
typename Func2>
354 void forAllMatching(
const IR::Node *root, Func &&function, Func2 &&function2) {
356 explicit NodeVisitor(Func &&function, Func2 &&function2)
357 : function(function), function2(function2) {}
360 bool preorder(
const NodeType *node)
override {
364 void postorder(
const NodeType *node)
override { function2(node); }
366 root->apply(NodeVisitor(std::forward<Func>(function), std::forward<Func2>(function2)));
374 ingressBridgedFields(b),
375 egressBridgedFields(e),
376 parserAlignedFields(g),
378 actionConstraints(a) {}
384class GatherAlignmentConstraints :
public PassManager {
393 : collectIngressBridgedFields(p),
394 collectEgressBridgedFields(p),
395 collectParserAlignedFields(p),
396 collectDigestFields(p) {
398 &collectIngressBridgedFields,
399 &collectEgressBridgedFields,
400 &collectParserAlignedFields,
401 &collectDigestFields,
403 collectParserAlignedFields, collectDigestFields, a),
440class ConstraintSolver {
442 z3::context &context;
444 PackingConstraints &packingConstraints;
448 DebugInfo &debug_info;
459 std::vector<const PHV::Field *> insert_padding(std::vector<std::pair<unsigned, std::string>> &);
461 void dump_unsat_core();
464 explicit ConstraintSolver(
const PhvInfo &p, z3::context &context, z3::optimize &
solver,
465 PackingConstraints &pc,
AllConstraints &constraints, DebugInfo &dbg)
469 packingConstraints(pc),
470 constraints(constraints),
478 void print_assertions();
546 phvFieldToStructFieldMap;
553 PackingCandidateFields &packingCandidateFields;
554 PackingConstraints &packingConstraints;
567 PackingCandidateFields &pcf, PackingConstraints &pc)
572 packingCandidateFields(pcf),
573 packingConstraints(pc) {}
576 bool preorder(
const IR::HeaderOrMetadata *hdr)
override;
577 bool preorder(
const IR::BFN::DigestFieldList *dfl)
override;
580 void set_pipeline_name(
cstring name) { pipelineName = name; }
595 : repackedTypes(r) {}
597 bool preorder(
const IR::BFN::Type_FixedSizeHeader *h)
override {
598 auto width = [&](
const IR::Type_StructLike *s) ->
int {
600 for (
auto f : s->fields) rv += f->type->width_bits();
606 for (
auto f : fields)
607 if (f->hasAnnotation(
"padding"_cs)) count++;
612 auto genPadding = [&](
int size,
int id) {
613 cstring padFieldName =
"__pad_" + cstring::to_cstring(
id);
614 const IR::StructField *padField =
615 new IR::StructField(padFieldName,
616 {
new IR::Annotation(
IR::ID(
"padding"), {}),
617 new IR::Annotation(
IR::ID(
"overlayable"), {})},
618 IR::Type::Bits::get(size));
622 size_t bits =
static_cast<size_t>(width(h));
623 ERROR_CHECK(bits <= Device::pardeSpec().bitResubmitSize(),
"%1% digest limited to %2% bits",
624 h->name, Device::pardeSpec().bitResubmitSize());
625 auto pad_size = h->fixed_size - bits;
628 fields->append(h->fields);
629 auto index = countPadding(h->fields);
631 auto padding = genPadding(pad_size, index++);
632 fields->push_back(padding);
635 auto newType =
new IR::Type_Header(h->name, *fields);
636 repackedTypes.emplace(h->name, newType);
655 const IR::Node *postorder(IR::HeaderOrMetadata *h)
override;
656 const IR::Node *postorder(IR::BFN::DigestFieldList *d)
override;
657 const IR::BFN::DigestFieldList *repackFieldList(
658 cstring digest, std::vector<FieldListEntry> repackedFieldIndices,
659 const IR::Type_StructLike *repackedHeaderType,
660 const IR::BFN::DigestFieldList *origFieldList)
const;
663 const IR::Node *postorder(IR::Type_StructLike *h)
override;
664 const IR::Node *postorder(IR::StructExpression *h)
override;
667bool findFlexibleAnnotation(
const IR::Type_StructLike *);
681 return Inspector::init_apply(root);
684 bool preorder(
const IR::BFN::DeparserParameter *p)
override;
688 : phv(p), params(f) {}
699 static constexpr char const *PHASE0_PARSER_STATE_NAME =
"ingress::$phase0";
702 noPackFields.clear();
703 return Inspector::init_apply(root);
706 bool preorder(
const IR::BFN::ParserState *p)
override;
708 bool preorder(
const IR::BFN::DigestFieldList *d)
override;
712 : phv(p), noPackFields(f) {}
725 RepackedHeaders repacked;
727 std::unordered_set<std::string> hdrs;
731 bool preorder(
const IR::HeaderOrMetadata *h)
override;
734 void end_apply()
override;
737 std::string getFieldName(std::string hdr,
const IR::StructField *field)
const;
740 std::string pretty_print(
const IR::HeaderOrMetadata *h, std::string hdr)
const;
743 std::string strip_prefix(
cstring str, std::string pre);
746 explicit LogRepackedHeaders(
const PhvInfo &p) : phv(p) {}
748 std::string asm_output()
const;
755 explicit LogFlexiblePacking(
const PhvInfo &phv)
766class GatherPackingConstraintFromSinglePipeline :
public PassManager {
785 explicit GatherPackingConstraintFromSinglePipeline(
PhvInfo &p,
const PhvUse &u,
791 std::string asm_output()
const;
805 std::vector<const IR::BFN::Pipe *> pipe;
815 PackingCandidateFields packingCandidateFields;
816 PackingConstraints packingConstraints;
817 PackedFields packedFields;
822 DebugInfo debug_info;
830 void set_pipeline_name(
cstring name) { pipelineName = name; }
833 packWithConstraintSolver.set_pipeline_name(pipelineName);
834 packWithConstraintSolver.optimize();
837 void solve() { packWithConstraintSolver.solve(); }
839 void end_apply()
override;
841 void print_packing_candidate_fields()
const {
842 for (
auto &[hdr_type, fields] : packingCandidateFields) {
843 LOG3(
"Packing candidate fields for " << hdr_type <<
":");
844 for (
auto f : fields) {
849 void check_conflicting_constraints();
926using PipeAndGress = std::pair<std::pair<cstring, gress_t>, std::pair<cstring, gress_t>>;
936 const IR::Type *type;
941 bool operator<(
const Use &other)
const {
942 return std::tie(type, name, method, thread) <
943 std::tie(other.type, other.name, other.method, other.thread);
946 bool operator==(
const Use &other)
const {
947 return std::tie(type, name, method, thread) ==
948 std::tie(other.type, other.name, other.method, other.thread);
954 friend std::ostream &operator<<(std::ostream &,
const Use &u);
958 : refMap(refMap), typeMap(typeMap) {}
960 void postorder(
const IR::MethodCallExpression *mc)
override;
966 IR::BFN::Pipe::thread_t thread;
990 std::vector<const IR::BFN::Pipe *> *generate_bridge_pairs(std::vector<BridgeContext> &);
992 bool preorder(
const IR::P4Program *program)
override;
993 void end_apply(
const IR::Node *)
override;
1003class BridgedPacking :
public PassManager {
1027class SubstitutePackedHeaders :
public PassManager {
1042 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:303
Definition bridged_packing.h:146
ordered_map< cstring, cstring > bridged_to_orig
Map: bridged field name -> original field name.
Definition bridged_packing.h:157
Definition collect_global_pragma.h:28
Definition bridged_packing.h:105
ordered_map< cstring, cstring > bridged_to_orig
Key: bridged field name, value: original field name.
Definition bridged_packing.h:122
The class uses the Z3 solver to generate packing for a set of PHV fields given a set of constraints.
Definition bridged_packing.h:440
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:264
bool preorder(const IR::BFN::DigestFieldList *fl) override
Definition bridged_packing.cpp:169
Definition bridged_packing.h:766
Definition backends/tofino/bf-p4c/logging/pass_manager.h:36
Definition map_tables_to_actions.h:29
Definition mau_backtracker.h:29
Definition indexed_vector.h:40
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition symbitmatrix.h:27
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv_fields.h:154
Definition pack_conflicts.h:36
Definition bridged_packing.h:524
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
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
Definition pa_no_pack.h:28
Definition mau/table_mutex.h:110
ordered_map< cstring, const IR::Type_StructLike * > RepackedHeaderTypes
Adjusted packing of bridged and fixed-size headers; output of BFN::BridgedPacking,...
Definition bridged_packing.h:84
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:47
Definition bridged_packing.h:963
Definition bridged_packing.h:935
Definition table_dependency_graph.h:52