19#ifndef BF_P4C_PHV_PHV_FIELDS_H_
20#define BF_P4C_PHV_PHV_FIELDS_H_
26#include <boost/range/irange.hpp>
28#include "backends/tofino/bf-p4c/bf-p4c-options.h"
29#include "backends/tofino/bf-p4c/device.h"
30#include "backends/tofino/bf-p4c/ir/bitrange.h"
31#include "backends/tofino/bf-p4c/ir/thread_visitor.h"
32#include "backends/tofino/bf-p4c/ir/tofino_write_context.h"
33#include "backends/tofino/bf-p4c/lib/assoc.h"
34#include "backends/tofino/bf-p4c/lib/cmp.h"
35#include "backends/tofino/bf-p4c/lib/union_find.hpp"
36#include "backends/tofino/bf-p4c/phv/constraints/constraints.h"
37#include "backends/tofino/bf-p4c/phv/phv.h"
38#include "backends/tofino/bf-p4c/phv/phv_parde_mau_use.h"
39#include "backends/tofino/bf-p4c/phv/utils/slice_alloc.h"
41#include "lib/algorithm.h"
43#include "lib/ordered_map.h"
44#include "lib/ordered_set.h"
46#include "lib/safe_vector.h"
47#include "lib/symbitmatrix.h"
58 bool isByteAligned()
const {
return align == 0; }
68using SolitaryReason = Constraints::SolitaryConstraint::SolitaryReason;
69using DigestType = Constraints::DigestConstraint::DigestType;
70using AlignmentReason = Constraints::AlignmentConstraint::AlignmentReason;
74enum class FieldKind :
unsigned short {
80enum class FieldAccessType { NONE = 0, R = 1, W = 2, RW = 3 };
85 enum class Type { PARSER, TABLE, DEPARSER };
94 BUG_CHECK(type != Type::TABLE,
"Improper usage of PHV::AllocContext interface");
99 BUG_CHECK(
table,
"Improper usage of PHV::AllocContext interface");
103 bool is_parser()
const {
return type == Type::PARSER; }
104 bool is_deparser()
const {
return type == Type::DEPARSER; }
105 bool is_table()
const {
return type == Type::TABLE; }
109 else if (is_deparser())
110 return "DEPARSER"_cs;
116 static const AllocContext *PARSER;
117 static const AllocContext *DEPARSER;
124 if (!unit)
return nullptr;
125 if (unit->is<IR::BFN::ParserState>() || unit->is<IR::BFN::Parser>() ||
126 unit->is<IR::BFN::GhostParser>())
128 if (unit->to<IR::BFN::Deparser>())
return DEPARSER;
130 BUG(
"Improper usage of PHV::AllocContext interface. Not a parser, deparser, or table: %1%",
134std::ostream &operator<<(std::ostream &,
const AllocContext &);
139 const IR::MAU::Instruction *inst;
140 FieldAccessType rw_type;
143 FieldOperation(
bool is_bitwise_op,
bool is_salu_inst,
const IR::MAU::Instruction *inst,
145 : is_bitwise_op(is_bitwise_op),
146 is_salu_inst(is_salu_inst),
174 if (BackendOptions().arch ==
"tna") {
175 return name.startsWith(
"ghost::");
177 if (
name.startsWith(
"ghost::"))
return true;
181 if (
name.startsWith(
"ingress::"))
return false;
182 if (
name.startsWith(
"egress::"))
return false;
190 return name.startsWith(
"__phv_dummy_padding__");
235 HAS_PHV_ALLOCATION = 1 << 1,
236 FULLY_PHV_ALLOCATED = 1 << 2,
237 HAS_CLOT_ALLOCATION = 1 << 3,
240 typedef unsigned AllocState;
247 return rhs.member_field == this->member_field && rhs.field_list == this->field_list;
250 } mirror_field_list = {
nullptr, -1};
290 std::optional<cstring> externalName_i;
295 bool flexible_i =
false;
296 bool parsed_i =
false;
297 bool deparsed_i =
false;
312 bool deparsed_bottom_bits_i =
false;
313 bool deparsed_top_bits_i =
false;
315 bool exact_containers_i =
false;
317 bool deparsed_to_tm_i =
false;
318 size_t numNoPack = 0;
321 bool is_checksummed_i =
false;
322 bool mocha_i =
false;
326 bool deparser_zero_i =
false;
328 bool write_force_immediate_i =
false;
335 bool ignore_alloc_i =
false;
338 bool fixed_size_i =
false;
340 bool same_container_group_i =
false;
345 PHV::Size prefer_container_size_i = PHV::Size::null;
353 bool no_holes_i =
false;
355 bool upcasted_i =
false;
363 int maxContainerBytes_i = -1;
369 std::vector<le_bitrange> no_split_ranges_i;
382 bool is_marshaled_i =
false;
386 std::optional<bitvec> limited_container_ids_i = std::nullopt;
392 int no_split_container_size_i = -1;
398 bool avoid_alloc_i =
false;
404 friend std::ostream &operator<<(std::ostream &out,
const Field &field);
407 bool is_flexible()
const {
return flexible_i; }
408 void set_flexible(
bool b) { flexible_i = b; }
411 bool is_mocha_candidate()
const {
return mocha_i; }
412 bool is_dark_candidate()
const {
return dark_i; }
413 bool is_deparser_zero_candidate()
const {
return deparser_zero_i; }
414 void set_mocha_candidate(
bool c) { mocha_i = c; }
415 void set_dark_candidate(
bool c) { dark_i = c; }
416 void set_deparser_zero_candidate(
bool c) { deparser_zero_i = c; }
418 bool is_ignore_alloc()
const {
return ignore_alloc_i; }
419 void set_ignore_alloc(
bool b) { ignore_alloc_i = b; }
421 bool is_avoid_alloc()
const {
return avoid_alloc_i; }
422 void set_avoid_alloc(
bool a) { avoid_alloc_i = a; }
424 bool is_padding()
const {
return padding; }
425 void set_padding(
bool p) {
padding = p; }
426 bool is_overlayable()
const {
return overlayable; }
428 bool is_fixed_size_header()
const {
return fixed_size_i; }
429 void set_fixed_size_header(
bool f) { fixed_size_i = f; }
431 bool emitted()
const {
return emitted_i; }
432 void set_emitted(
bool b) {
emitted_i = b; }
434 bool is_upcasted()
const {
return upcasted_i; }
435 void set_upcasted(
bool c) { upcasted_i = c; }
440 bool parsed()
const {
return parsed_i; }
441 void set_parsed(
bool b) { parsed_i = b; }
445 void set_deparsed(
bool b) { deparsed_i = b; }
447 bool is_solitary()
const {
return solitary_i.hasConstraint(); }
448 void set_solitary(uint32_t reason) { solitary_i.addConstraint(reason); }
452 bool is_digest()
const {
return digest_i.hasConstraint(); }
453 void set_digest(uint32_t source) { digest_i.addConstraint(source); }
459 void set_alignment(
unsigned r,
unsigned v) { alignment_i.addConstraint(r, v); }
460 void erase_alignment() { alignment_i.eraseConstraint(); }
463 bool deparsed_bottom_bits()
const {
return deparsed_bottom_bits_i; }
464 void set_deparsed_bottom_bits(
bool b) { deparsed_bottom_bits_i = b; }
465 bool deparsed_top_bits()
const {
return deparsed_top_bits_i; }
466 void set_deparsed_top_bits(
bool b) { deparsed_top_bits_i = b; }
467 bool exact_containers()
const {
return exact_containers_i; }
468 void set_exact_containers(
bool b) { exact_containers_i = b; }
469 void set_written_in_force_immediate(
bool b) { write_force_immediate_i = b; }
470 bool written_in_force_immediate_table()
const {
return write_force_immediate_i; }
472 void set_no_split_container_size(
int size) { no_split_container_size_i =
size; }
473 int no_split_container_size()
const {
return no_split_container_size_i; }
474 bool no_split()
const;
475 void set_no_split(
bool b);
476 bool no_split_at(
int pos)
const;
477 bool has_no_split_at_pos()
const;
480 bool same_container_group()
const {
return same_container_group_i; }
481 void set_same_container_group(
bool b) { same_container_group_i = b; }
483 bool no_holes()
const {
return no_holes_i; }
484 void set_no_holes(
bool b) { no_holes_i = b; }
486 void set_prefer_container_size(
PHV::Size cnt_size) { prefer_container_size_i = cnt_size; }
487 PHV::Size prefer_container_size()
const {
return prefer_container_size_i; }
489 bool used_in_wide_arith()
const {
return wide_arith_start_bit_.size() > 0; }
491 bool bit_used_in_wide_arith(
int slice_bit)
const {
492 for (
auto bit : wide_arith_start_bit_) {
493 if (slice_bit >= bit && slice_bit < (bit + 64))
return true;
497 bool bit_is_wide_arith_lo(
int slice_bit)
const {
498 for (
auto bit : wide_arith_start_bit_) {
499 if (slice_bit < (bit + 32))
return true;
506 bool add_wide_arith_start_bit(
int start_bit) {
507 for (
auto bit : wide_arith_start_bit_) {
508 if (bit != start_bit) {
511 if (bit < start_bit && start_bit < (bit + 64))
return false;
512 if (start_bit < bit && bit < (start_bit + 64))
return false;
515 wide_arith_start_bit_.insert(start_bit);
518 std::vector<le_bitrange> no_split_ranges()
const {
return no_split_ranges_i; }
520 bool deparsed_to_tm()
const {
return deparsed_to_tm_i; }
521 void set_deparsed_to_tm(
bool b) { deparsed_to_tm_i = b; }
523 bool is_marshaled()
const {
return is_marshaled_i; }
524 void set_is_marshaled(
bool b) { is_marshaled_i = b; }
526 bool is_checksummed()
const {
return is_checksummed_i; }
527 void set_is_checksummed(
bool b) { is_checksummed_i = b; }
533 void set_limited_container_ids(
const std::optional<bitvec> &ids) {
534 limited_container_ids_i = ids;
536 const std::optional<bitvec> &limited_container_ids()
const {
return limited_container_ids_i; }
544 void set_num_pack_conflicts(
size_t no) { numNoPack = no; }
546 size_t num_pack_conflicts()
const {
return numNoPack; }
548 bool hasMaxContainerBytesConstraint()
const {
return maxContainerBytes_i != -1; }
550 int getMaxContainerBytes()
const {
return maxContainerBytes_i; }
552 void setMaxContainerBytes(
int size) { maxContainerBytes_i =
size; }
586 SliceMatch useTblRefs = SliceMatch::DFLT)
const;
589 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
595 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
600 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
612 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
617 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
627 SliceMatch useTblRefs = SliceMatch::DFLT)
const;
643 SliceMatch useTblRefs = SliceMatch::DFLT)
const;
647 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
652 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
663 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
669 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
674 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
686 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
692 SliceMatch useTblRefs = SliceMatch::DFLT)
const {
698 int container_bytes(std::optional<le_bitrange> bits = std::nullopt)
const;
708 alloc_slice_i.emplace_back(f, c, fb, cb, w, a);
709 unsigned size = alloc_slice_i.size();
710 return &(alloc_slice_i[
size - 1]);
729 std::sort(alloc_slice_i.begin(), alloc_slice_i.end(),
731 if (l.field_slice().lo != r.field_slice().lo)
732 return l.field_slice().lo > r.field_slice().lo;
733 return l.getEarliestLiveness().first > r.getEarliestLiveness().first;
802 int start = 8 * (
offset / 8);
803 int len = (8 * ROUNDUP(
offset +
size, 8)) - start;
809 return (s & HAS_PHV_ALLOCATION) || (s & FULLY_PHV_ALLOCATED);
811 bool hasClotAllocation(AllocState s)
const {
return s & HAS_CLOT_ALLOCATION; }
816 bool fullyPhvAllocated(AllocState s)
const {
return s & FULLY_PHV_ALLOCATED; }
817 bool partiallyPhvAllocated(AllocState s)
const {
820 bool isReferenced(AllocState s)
const {
return (s & REFERENCED) ||
hasAllocation(s); }
829 std::map<PHV::Size, bitvec> startBitsByContainerSize_i;
833 for (
auto size : Device::phvSpec().containerSizes())
859 virtual int size()
const = 0;
862 template <
typename T>
863 const T &as()
const {
864 return dynamic_cast<const T &
>(
this);
866 template <
typename T>
867 const T *to()
const {
868 return dynamic_cast<const T *
>(
this);
870 template <
typename T>
872 return to<T>() !=
nullptr;
884 explicit Constant(
const IR::Constant *value) : value(value) {
885 range_i = {0, value->type->width_bits() - 1};
888 int size()
const override {
return value->type->width_bits(); }
889 const PHV::Field *field()
const override {
return nullptr; }
890 const le_bitrange &range()
const override {
return range_i; }
891 const IR::Constant *value;
903 std::optional<FieldAlignment> alignment_i = std::nullopt;
918 "Trying to create field sub-slice larger than the original slice");
921 explicit operator bool()
const {
return field_i !=
nullptr; }
928 int start = 8 * ((field_i->
offset + range_i.
lo) / 8);
929 int len = (8 * ROUNDUP(field_i->
offset + range_i.
hi + 1, 8)) - start;
936 std::stringstream ss;
937 ss << field_i->
name <<
"[" << range_i.
hi <<
":" << range_i.
lo <<
"]";
941 bool operator==(
const FieldSlice &other)
const override {
942 return field_i == other.field() && range_i == other.range();
945 bool operator<(
const FieldSlice &other)
const override {
946 if (field_i != other.field())
return Field::less(field_i, other.field());
947 if (range_i.
lo != other.range().lo)
return range_i.
lo < other.range().lo;
948 return range_i.
hi < other.range().hi;
955 int size()
const override {
return range_i.
size(); }
959 std::optional<FieldAlignment>
alignment()
const {
return alignment_i; }
969 return FieldKind::pov;
971 return FieldKind::metadata;
973 return FieldKind::header;
993 int container_bytes()
const {
return field_i->
container_bytes(range_i); }
999 void foreach_byte(
const IR::MAU::Table *ctxt,
const PHV::FieldUse *use, FN fn)
const {
1003 bool is_unallocated()
const {
return field_i->
is_unallocated(); }
1005 friend size_t hash_value(
const FieldSlice &fs) {
1007 boost::hash_combine(h, fs.field()->id);
1008 boost::hash_combine(h, fs.range().lo);
1009 boost::hash_combine(h, fs.range().hi);
1019 bool operator==(
const FieldRange &other)
const {
1020 return (field_name == other.field_name) && range == other.range;
1023 bool operator<(
const FieldRange &other)
const {
1024 if (field_name != other.field_name)
return (field_name < other.field_name);
1025 if (range.
lo != other.range.
lo)
return range.
lo < other.range.
lo;
1026 return range.
hi < other.range.
hi;
1029 bool has_conflict(
const FieldRange fld_range)
const {
return (conflicts.count(fld_range) > 0); }
1035 using FieldRange = std::pair<const PHV::Field *, le_bitrange>;
1039 std::optional<FieldRange> slice;
1045 bool is_fs()
const {
return slice.has_value(); }
1046 const FieldRange &fs()
const {
return *slice; }
1049 return slice->second.size();
1061std::ostream &operator<<(std::ostream &out,
const Field &);
1062std::ostream &operator<<(std::ostream &out,
const Field *);
1063std::ostream &operator<<(std::ostream &out,
const PackingLayout &);
1064std::ostream &operator<<(std::ostream &out,
const PackingLayout *);
1072using InsertionConstraints = std::pair<std::set<UniqueId>, std::set<UniqueId>>;
1101 static int deparser_stage;
1102 static bool darkSpillARA;
1103 static const bool DARK_SPILL_ARA_DEFAULT =
true;
1140 BUG_CHECK(0 <=
size,
"PhvInfo::StructInfo with negative size");
1142 "PhvInfo::StructInfo with negative first field offset");
1154 using FieldBit = std::pair<const PHV::Field *, int>;
1155 UnionFind<FieldBit> same_byte_bits;
1159 void clear() { same_byte_bits.clear(); }
1162 const SymBitMatrix &field_mutex()
const {
return field_mutex_i; }
1163 const SymBitMatrix &metadata_mutex()
const {
return metadata_mutex_i; }
1164 const SymBitMatrix &dark_mutex()
const {
return dark_mutex_i; }
1165 const SymBitMatrix &deparser_no_pack_mutex()
const {
return deparser_no_pack_i; }
1166 const SymBitMatrix &digest_no_pack_mutex()
const {
return digest_no_pack_i; }
1167 const SameContainerAllocConstraint &same_container_alloc_constraint()
const {
1168 return same_container_alloc_i;
1171 SymBitMatrix &metadata_mutex() {
return metadata_mutex_i; }
1173 SymBitMatrix &deparser_no_pack_mutex() {
return deparser_no_pack_i; }
1174 SymBitMatrix &digest_no_pack_mutex() {
return digest_no_pack_i; }
1176 SymBitMatrix &getBridgedExtractedTogether() {
return bridged_extracted_together_i; }
1177 const SymBitMatrix &getBridgedExtractedTogether()
const {
return bridged_extracted_together_i; }
1178 SameContainerAllocConstraint &same_container_alloc_constraint() {
1179 return same_container_alloc_i;
1183 BUG_CHECK(f1 && f2,
"No PHV field");
1184 return bridged_extracted_together_i(f1->
id, f2->
id);
1187 SymBitMatrix &getMutuallyAligned() {
return mutually_aligned_i; }
1188 const SymBitMatrix &getMutuallyAligned()
const {
return mutually_aligned_i; }
1190 BUG_CHECK(f1 && f2,
"No PHV field");
1191 return mutually_aligned_i(f1->
id, f2->
id);
1195 BUG_CHECK(f1 && f2,
"No PHV field");
1196 mutually_aligned_i(f1->
id, f2->
id) =
true;
1200 BUG_CHECK(f1 && f2,
"No PHV field");
1201 deparser_no_pack_i(f1->
id, f2->
id) =
true;
1205 BUG_CHECK(f1 && f2,
"No PHV field");
1206 field_no_pack_i(f1->
id, f2->
id) =
true;
1210 BUG_CHECK(f1 && f2,
"No PHV field");
1211 field_no_pack_i(f1->
id, f2->
id) =
false;
1215 BUG_CHECK(f1 && f2,
"No PHV field");
1216 digest_no_pack_i(f1->
id, f2->
id) =
true;
1220 BUG_CHECK(f1 && f2,
"No PHV field");
1221 digest_no_pack_i(f1->
id, f2->
id) =
false;
1225 BUG_CHECK(f1 && f2,
"No PHV field");
1226 field_mutex_i(f1->
id, f2->
id) =
true;
1230 BUG_CHECK(f1 && f2,
"No PHV field");
1231 field_mutex_i(f1->
id, f2->
id) =
false;
1235 BUG_CHECK(f1 && f2,
"No PHV field");
1236 metadata_mutex_i(f1->
id, f2->
id) =
true;
1240 BUG_CHECK(f1 && f2,
"No PHV field");
1241 dark_mutex_i(f1->
id, f2->
id) =
true;
1245 BUG_CHECK(f1 && f2,
"No PHV field");
1246 return field_mutex_i(f1->
id, f2->
id);
1250 BUG_CHECK(f1 && f2,
"No PHV field");
1251 return metadata_mutex_i(f1->
id, f2->
id);
1255 BUG_CHECK(f1 && f2,
"No PHV field");
1256 return dark_mutex_i(f1->
id, f2->
id);
1260 BUG_CHECK(f1 && f2,
"No PHV field");
1261 return deparser_no_pack_i(f1->
id, f2->
id);
1265 BUG_CHECK(f1 && f2,
"No PHV field");
1266 return field_no_pack_i(f1->
id, f2->
id);
1270 BUG_CHECK(f1 && f2,
"No PHV field");
1271 return digest_no_pack_i(f1->
id, f2->
id);
1274 unsigned sizeFieldNoPack() {
return field_no_pack_i.size(); }
1278 constantExtractedInSameState.clear();
1279 sameStateConstantExtraction.clear();
1289 sameStateConstantExtraction.makeUnion(f, g);
1290 constantExtractedInSameState[f->
id] =
true;
1291 constantExtractedInSameState[g->
id] =
true;
1294 const UnionFind<PHV::Field *> &getSameSetConstantExtraction()
const {
1295 return sameStateConstantExtraction;
1298 UnionFind<PHV::Field *> &getSameSetConstantExtraction() {
return sameStateConstantExtraction; }
1300 bool hasParserConstantExtract(
const PHV::Field *f)
const {
1301 return constantExtractedInSameState[f->
id];
1308 bool add_table_constraints(gress_t grs, IR::MAU::Table *tbl, InsertionConstraints cnstrs) {
1310 (alwaysRunTables.count(grs) ? (alwaysRunTables[grs].count(tbl) ?
true :
false) :
false);
1313 (alwaysRunTables[grs])[tbl] = cnstrs;
1315 (alwaysRunTables[grs])[tbl].first.insert(cnstrs.first.begin(), cnstrs.first.end());
1316 (alwaysRunTables[grs])[tbl].second.insert(cnstrs.second.begin(), cnstrs.second.end());
1319 return !has_constrs;
1323 void clearARAconstraints() { alwaysRunTables.clear(); }
1325 static void clearMinStageInfo() { PhvInfo::table_to_min_stages.clear(); }
1326 static void clearPhysicalStageInfo() { PhvInfo::table_to_physical_stages.clear(); }
1328 static void resetDeparserStage() { PhvInfo::deparser_stage = -1; }
1330 static void setDeparserStage(
int stage) { PhvInfo::deparser_stage = stage; }
1332 static int getDeparserStage() {
return PhvInfo::deparser_stage; }
1334 static std::set<int> minStages(
const IR::MAU::Table *tbl);
1335 static std::set<int> physicalStages(
const IR::MAU::Table *tbl);
1337 static void addMinStageEntry(
const IR::MAU::Table *tbl,
int stage,
1338 bool remove_prev_stages =
false);
1339 static void setPhysicalStages(
const IR::MAU::Table *tbl,
const std::set<int> &stage);
1341 static bool hasMinStageEntry(
const IR::MAU::Table *tbl);
1343 static cstring reportMinStages();
1345 static void resetDarkSpillARA() { darkSpillARA = DARK_SPILL_ARA_DEFAULT; }
1350 bool darkLivenessOkay(
const IR::MAU::Table *gateway,
const IR::MAU::Table *t)
const;
1354 return same_container_alloc_i.same_container(a, b);
1359 std::map<cstring, PHV::Field> all_fields;
1364 std::map<cstring, StructInfo> all_structs;
1387 bool alloc_done_ =
false;
1388 bool pov_alloc_done =
false;
1389 bool trivial_alloc_ =
false;
1427 SameContainerAllocConstraint same_container_alloc_i;
1431 std::set<PHV::Container> zeroContainers[2];
1445 typedef std::pair<cstring, cstring> tpair;
1450 UnionFind<PHV::Field *> sameStateConstantExtraction;
1453 bitvec constantExtractedInSameState;
1457 void add_hdr(
cstring headerName,
const IR::Type_StructLike *type, gress_t gress,
1459 void add_struct(
cstring structName,
const IR::Type_StructLike *type, gress_t gress,
bool meta,
1460 bool bridged,
int offset);
1461 void addPadding(
const IR::Padding *padding, gress_t gress);
1463 template <
typename Iter>
1468 iterator(Iter i) : it(i) {}
1469 bool operator==(iterator a) {
return it == a.it; }
1470 bool operator!=(iterator a) {
return it != a.it; }
1471 iterator &operator++() {
1475 iterator &operator--() {
1479 decltype(**it) operator*() {
return **it; }
1480 decltype(*it) operator->() {
return *it; }
1486 friend struct MarkBridgedMetadataFields;
1501 void addTempVar(
const IR::TempVar *tempVar, gress_t gress);
1502 bool isTempVar(
const PHV::Field *f)
const {
return fields_to_tempvars_i.count(f) > 0; }
1504 return size_t(idx) < by_id.size() ? by_id.at(idx) : 0;
1509 PHV::Field *field(
int idx) {
return (
size_t)idx < by_id.size() ? by_id.at(idx) : 0; }
1511 return const_cast<PHV::Field *
>(
const_cast<const PhvInfo *
>(
this)->field(name));
1514 return const_cast<PHV::Field *
>(
const_cast<const PhvInfo *
>(
this)->field(e, bits));
1517 return const_cast<PHV::Field *
>(
const_cast<const PhvInfo *
>(
this)->field(fr, bits));
1519 bool has_struct_info(
cstring name)
const;
1524 const StructInfo struct_info(
cstring name)
const;
1525 const StructInfo struct_info(
const IR::HeaderRef *hr)
const {
1526 return struct_info(hr->toString());
1528 const std::map<cstring, PHV::Field> &get_all_fields()
const {
return all_fields; }
1529 size_t num_fields()
const {
return all_fields.size(); }
1534 PHV::Field *add(
cstring fieldName, gress_t gress,
int size,
int offset,
bool isMetadata,
1535 bool isPOV,
bool bridged =
false,
bool isPad =
false,
1536 bool isOverlayable =
false,
bool isFlexible =
false,
1537 bool isFixedSizeHeader =
false,
1538 std::optional<Util::SourceInfo> srcInfo = std::nullopt);
1540 PHV::Field *create_dummy_padding(
size_t sz, gress_t gress,
bool overlayable =
true);
1542 std::vector<PHV::AllocSlice> get_alloc(
const IR::Expression *f,
1550 iterator<safe_vector<PHV::Field *>::iterator> begin() {
return by_id.begin(); }
1551 iterator<safe_vector<PHV::Field *>::iterator> end() {
return by_id.end(); }
1552 iterator<safe_vector<PHV::Field *>::const_iterator> begin()
const {
return by_id.begin(); }
1553 iterator<safe_vector<PHV::Field *>::const_iterator> end()
const {
return by_id.end(); }
1555 bool alloc_done()
const {
return alloc_done_; }
1556 bool trivial_alloc()
const {
return trivial_alloc_; }
1557 void set_done(
bool trivial =
false) {
1559 trivial_alloc_ = trivial;
1606 const IR::MAU::Table *ctxt,
const PHV::FieldUse *use =
nullptr)
const {
1631 std::optional<cstring>
get_alias_name(
const IR::Expression *expr)
const;
1635 if (aliasMap.count(f1))
1636 BUG_CHECK(aliasMap[f1] == f2,
"Multiple aliases with the same field found");
1642 externalNameMap[externalName] = f;
1653 if (aliasMap.count(f))
return aliasMap.at(f);
1659 return zeroContainers[gr];
1664 zeroContainers[gr].insert(c);
1665 BUG_CHECK(zeroContainers[gr].size() <= 1,
1666 "Only two zero containers allowed: one for each gress");
1674 metadataDeps[t1->name].insert(t2->name);
1675 reverseMetadataDeps[t2->name].insert(t1->name);
1677 auto table_pair = std::make_pair(t1->name, t2->name);
1678 if (metadataDepFields.emplace(table_pair, slice).second) {
1679 LOG5(
" Adding tables " << t1->name <<
" --> " << t2->name
1680 <<
" with metadata dependent field " << slice);
1688 if (!reverseMetadataDeps.count(t->name))
return emptySet;
1689 return reverseMetadataDeps.at(t->name);
1694 return metadataDeps;
1699 return reverseMetadataDeps;
1704 return metadataDepFields;
1710 std::function<
bool(
const PHV::Field *)> *f =
nullptr,
1748 bool preorder(
const IR::BFN::ParserState *state)
override;
1759 field_to_parser_states;
1764 container_to_parser_states;
1770 std::map<const IR::BFN::ParserState *, const IR::BFN::Parser *> state_to_parser;
1778 field_to_parser_states.clear();
1779 field_to_writes.clear();
1780 container_to_parser_states.clear();
1781 container_to_writes.clear();
1782 write_to_state.clear();
1783 state_to_parser.clear();
1784 state_to_writes.clear();
1785 return Inspector::init_apply(root);
1788 bool preorder(
const IR::BFN::ParserChecksumWritePrimitive *checksum)
override {
1789 if (
auto dest = checksum->getWriteDest()) add_field(dest->field, checksum);
1793 bool preorder(
const IR::BFN::Extract *extract)
override {
1794 if (
auto lval = extract->dest->to<IR::BFN::FieldLVal>()) add_field(lval->field, extract);
1799 void add_field(
const IR::Expression *field,
const IR::BFN::ParserPrimitive *prim) {
1800 if (
auto *f = phv_i.field(field)) {
1801 auto state = findContext<IR::BFN::ParserState>();
1802 auto parser = findContext<IR::BFN::Parser>();
1804 field_to_parser_states[f].insert(state);
1805 state_to_parser[state] = parser;
1807 field_to_writes[f].insert(prim);
1808 write_to_state[prim] = state;
1809 state_to_writes[state].insert(prim);
1811 if (phv_i.alloc_done()) {
1813 for (
auto &alloc : phv_i.get_alloc(field, PHV::AllocContext::PARSER, &use)) {
1814 auto cont = alloc.container();
1815 container_to_parser_states[cont].insert(state);
1816 container_to_writes[cont].insert(prim);
1828std::ostream &operator<<(std::ostream &,
const PhvInfo &);
1829std::ostream &operator<<(std::ostream &,
const PHV::FieldAccessType &);
1831std::ostream &operator<<(std::ostream &,
const PhvInfo::SameContainerAllocConstraint::FieldBit &);
1843ostream &operator<<(ostream &,
const list<::PHV::Field *> &);
1844ostream &operator<<(ostream &,
const set<const ::PHV::Field *> &);
Definition phv_fields.cpp:1246
Definition phv_fields.cpp:1266
Definition constraints.h:149
Definition constraints.h:90
Definition constraints.h:56
Definition ir/pass_manager.h:40
Definition symbitmatrix.h:27
Definition source_file.h:131
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition phv_fields.h:855
Represents a PHV-allocation context: a parser, a table, or a deparser.
Definition phv_fields.h:83
const IR::MAU::Table * table
Populated iff type is TABLE.
Definition phv_fields.h:89
static const AllocContext * of_unit(const IR::BFN::Unit *unit)
Definition phv_fields.h:123
Definition slice_alloc.h:136
Definition phv_fields.h:880
Definition phv_fields.h:154
void eraseAlignment()
Erase the alignment requirement for this field.
Definition phv_fields.cpp:1071
nw_bitrange validContainerRange_i
Definition phv_fields.h:203
const safe_vector< PHV::AllocSlice > & get_alloc() const
Definition phv_fields.h:717
const PHV::AllocSlice & for_bit(int bit) const
Definition phv_fields.cpp:799
size_t alloc_size() const
Definition phv_fields.h:722
std::optional< FieldAlignment > alignment
Definition phv_fields.h:198
void updateValidContainerRange(nw_bitrange newValidRange)
Definition phv_fields.cpp:1193
int size
Total size of Field in bits.
Definition phv_fields.h:194
int id
Unique field ID.
Definition phv_fields.h:164
bool overlayable
Definition phv_fields.h:226
bool isCompilerGeneratedPaddingField() const
Definition phv_fields.h:189
void setExternalName(cstring name)
Definition phv_fields.h:767
void foreach_alloc(const le_bitrange *r, const PHV::AllocContext *ctxt, const PHV::FieldUse *use, std::function< void(const PHV::AllocSlice &)> fn, SliceMatch useTblRefs=SliceMatch::DFLT) const
Definition phv_fields.h:684
bool hasPhvAllocation(AllocState s) const
Utility functions to get field allocation status.
Definition phv_fields.h:808
int offset
Offset of lsb from lsb (last) bit of containing header.
Definition phv_fields.h:206
void sort_alloc()
Sort by field MSB.
Definition phv_fields.h:728
bool padding
True if this Field is a padding field.
Definition phv_fields.h:222
bitvec getStartBits(PHV::Size size) const
Definition phv_fields.cpp:1086
bool invalidate_from_arch_i
Definition phv_fields.h:216
const std::vector< PHV::AllocSlice > get_combined_alloc_bytes(const PHV::AllocContext *ctxt, const PHV::FieldUse *use, SliceMatch useTblRefs=SliceMatch::DFLT) const
Definition phv_fields.cpp:807
bool deparsed() const
Definition phv_fields.h:444
bool operator<(const Field &other) const
Orders by name.
Definition phv_fields.h:841
le_bitrange byteAlignedRangeInBits() const
Definition phv_fields.h:801
cstring externalName() const
Definition phv_fields.h:759
cstring name
Definition phv_fields.h:161
void set_alloc(const safe_vector< PHV::AllocSlice > &alloc)
Set all allocated slices of this field.
Definition phv_fields.h:714
void setStartBits(PHV::Size size, bitvec startPositions)
Definition phv_fields.cpp:1079
std::optional< Util::SourceInfo > srcInfo
Associate source info to each field.
Definition phv_fields.h:273
bool intrinsic_i
True if this Field is intrinsic.
Definition phv_fields.h:212
void add_alloc(const PHV::AllocSlice &alloc)
Allocate a slice of this field.
Definition phv_fields.h:704
bool pov
True if this Field is a validity bit.
Definition phv_fields.h:253
cstring header() const
Definition phv_fields.h:285
bool isPacketField() const
Definition phv_fields.h:555
void foreach_alloc(const PHV::AllocContext *ctxt, const PHV::FieldUse *use, std::function< void(const PHV::AllocSlice &)> fn, SliceMatch useTblRefs=SliceMatch::DFLT) const
Definition phv_fields.h:661
bool bridged
True if this Field is metadata bridged from ingress to egress.
Definition phv_fields.h:219
bool is_tphv_candidate(const PhvUse &uses) const
Definition phv_fields.cpp:1001
const PHV::Field * aliasSource
Definition phv_fields.h:270
int container_bytes(std::optional< le_bitrange > bits=std::nullopt) const
Definition phv_fields.cpp:776
const std::vector< PHV::AllocSlice > get_combined_alloc_slices(le_bitrange bits, const PHV::AllocContext *ctxt, const PHV::FieldUse *use) const
Definition phv_fields.cpp:865
bool hasAllocation(AllocState s) const
Determines whether s has a PHV allocation or a CLOT allocation.
Definition phv_fields.h:814
bool is_unallocated() const
Definition phv_fields.h:725
bool hasExternalName() const
Definition phv_fields.h:763
bool isGhostField() const
Definition phv_fields.h:173
void clear_alloc()
Clear any PHV allocation for this field.
Definition phv_fields.h:701
void setStartBitsToLowerBitsOfBottomByte()
Definition phv_fields.cpp:1091
void updateAlignment(PHV::AlignmentReason, const FieldAlignment &newAlignment, const Util::SourceInfo &newAlignmentSource)
Definition phv_fields.cpp:1016
void foreach_byte(const le_bitrange *r, const PHV::AllocContext *ctxt, const PHV::FieldUse *use, std::function< void(const PHV::AllocSlice &)> fn, SliceMatch useTblRefs=SliceMatch::DFLT) const
Definition phv_fields.h:610
std::list< std::pair< FieldAlignment, Util::SourceInfo > > alignmentSources
List of alignment sources for this field (mainly for error printing)
Definition phv_fields.h:200
nw_bitrange validContainerRange() const
Definition phv_fields.h:797
void foreach_byte(le_bitrange r, const PHV::AllocContext *ctxt, const PHV::FieldUse *use, std::function< void(const PHV::AllocSlice &)> fn, SliceMatch useTblRefs=SliceMatch::DFLT) const
Definition phv_fields.cpp:900
gress_t gress
Whether the Field is ingress or egress.
Definition phv_fields.h:167
void foreach_alloc(le_bitrange r, const PHV::AllocContext *ctxt, const PHV::FieldUse *use, std::function< void(const PHV::AllocSlice &)> fn, SliceMatch useTblRefs=SliceMatch::DFLT) const
Definition phv_fields.cpp:960
bool metadata
True if this Field is metadata.
Definition phv_fields.h:209
void clearExternalName()
Clear the external name, if any has been set.
Definition phv_fields.h:770
bool emitted_i
True if this field is emitted by the deparser onto the wire.
Definition phv_fields.h:229
Definition phv_fields.h:898
const PHV::Field * field() const override
Definition phv_fields.h:977
FieldSlice(const Field *field)
Create a slice that holds the entirety of field.
Definition phv_fields.h:912
le_bitrange byteAlignedRangeInBits() const
Definition phv_fields.h:927
const le_bitrange & range() const override
Definition phv_fields.h:980
bool is_tphv_candidate(const PhvUse &uses) const
Definition phv_fields.cpp:1006
bool is_whole_field() const
Definition phv_fields.h:983
FieldSlice(FieldSlice slice, le_bitrange range)
Creates a subslice of the field of slice from range.lo to range.hi.
Definition phv_fields.h:916
FieldKind kind() const
Kind of field of this slice.
Definition phv_fields.h:965
int size() const override
Total size of FieldSlice in bits.
Definition phv_fields.h:955
bitvec getStartBits(PHV::Size size) const
Definition phv_fields.cpp:1174
std::optional< FieldAlignment > alignment() const
Definition phv_fields.h:959
nw_bitrange validContainerRange() const
See documentation for Field::validContainerRange().
Definition phv_fields.h:962
gress_t gress() const
Whether the Field is ingress or egress.
Definition phv_fields.h:952
Definition phv_fields.h:1038
Definition phv_fields.h:1095
const std::set< PHV::Container > & getZeroContainers(gress_t gr) const
Definition phv_fields.h:1658
const PHV::Field * getAliasDestination(const PHV::Field *f) const
Definition phv_fields.h:1652
void clear_container_to_fields()
Definition phv_fields.h:1564
std::optional< cstring > get_alias_name(const IR::Expression *expr) const
Definition phv_fields.cpp:650
const ordered_set< cstring > getReverseMetadataDeps(const IR::MAU::Table *t) const
Definition phv_fields.h:1686
const IR::TempVar * getTempVar(const PHV::Field *f) const
Definition phv_fields.cpp:196
void addExternalNameMapEntry(PHV::Field *f, cstring externalName)
Adds an entry to the externalNameMap.
Definition phv_fields.h:1641
void addAliasMapEntry(const PHV::Field *f1, const PHV::Field *f2)
Adds an entry to the aliasMap.
Definition phv_fields.h:1634
const ordered_map< tpair, const PHV::FieldSlice * > & getMetadataDepFields() const
Definition phv_fields.h:1703
void clearConstantExtractionState()
Clear the state maintained corresponding to constant extractors.
Definition phv_fields.h:1277
bitvec bits_allocated(const PHV::Container, const PHV::AllocContext *ctxt=nullptr, const PHV::FieldUse *use=nullptr) const
Definition phv_fields.cpp:537
void addZeroContainer(gress_t gr, PHV::Container c)
adds container to the set of deparsed zero containers.
Definition phv_fields.h:1663
cstring full_hdr_name(const cstring &name) const
Definition phv_fields.cpp:213
void add_container_to_field_entry(const PHV::Container c, const PHV::Field *f)
Definition phv_fields.cpp:502
const PhvInfo::StructInfo * hdr(const cstring &name_) const
Get information about a collection of header or metadata fields, based on the partial or complete nam...
Definition phv_fields.cpp:271
std::vector< PHV::AllocSlice > get_slices_in_container(const PHV::Container c) const
Definition phv_fields.cpp:513
ordered_map< PHV::Container, std::vector< PHV::AllocSlice > > ContainterToSliceMap
Definition phv_fields.h:1708
void addMetadataDependency(const IR::MAU::Table *t1, const IR::MAU::Table *t2, const PHV::FieldSlice *slice=nullptr)
Definition phv_fields.h:1672
void get_hdr_fields(cstring name_, ordered_set< const PHV::Field * > &flds) const
Definition phv_fields.cpp:250
const ordered_set< const PHV::Field * > & fields_in_container(const PHV::Container c) const
Definition phv_fields.cpp:507
void mergeConstantExtracts(PHV::Field *f, PHV::Field *g)
Definition phv_fields.h:1288
void insertConstantExtractField(PHV::Field *f)
Definition phv_fields.h:1284
const ordered_map< const PHV::Field *, const PHV::Field * > & getAliasMap() const
Definition phv_fields.h:1646
const ordered_map< cstring, ordered_set< cstring > > & getReverseMetadataDeps() const
Definition phv_fields.h:1698
const ordered_map< cstring, ordered_set< cstring > > & getMetadataDeps() const
Definition phv_fields.h:1693
Definition phv_parde_mau_use.h:154
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
The namespace encapsulating PHV-related stuff.
Definition gateway.h:32
gress_t gress
gress
Definition phv_fields.h:1058
Size
all possible PHV container sizes in BFN devices
Definition phv.h:110
safe_vector< FieldRangeOrPadding > layout
actual layout
Definition phv_fields.h:1056
Definition phv_fields.h:1034
Definition phv_fields.cpp:1438
Create and store a PHV::Field for each header and metadata field, and for TempVars....
Definition phv_fields.h:1735
Definition phv_fields.h:51
unsigned align
bit in byte alignment of the field in little endian order
Definition phv_fields.h:61
Map field to the parser states in which they are extracted or assigned from checksums.
Definition phv_fields.h:1755
Definition lib/bitrange.h:158
Definition lib/bitrange.h:190
int lo
Definition lib/bitrange.h:694
ssize_t size() const
Definition lib/bitrange.h:539
int hi
Definition lib/bitrange.h:700
bool contains(int index) const
Definition lib/bitrange.h:594
A mirror field points to its field list (one of eight)
Definition phv_fields.h:243
Definition phv_fields.h:136
Definition phv_fields.h:1014
Pretty-print all fields.
Definition phv_fields.h:1106
void generate_field_histogram(gress_t) const
Definition phv_fields.cpp:2550
Definition phv_fields.h:1153
PHV-related info about structs, i.e. collections of header or metadata fields.
Definition phv_fields.h:1120
bool metadata
True if this is a metadata struct; false for headers.
Definition phv_fields.h:1122
boost::integer_range< int > field_ids() const
Returns the half-open range of field IDs for this struct.
Definition phv_fields.h:1146
int size
Definition phv_fields.h:1134
int first_field_id
Definition phv_fields.h:1130
gress_t gress
Gress of this struct.
Definition phv_fields.h:1125