P4C
The P4 Compiler
Loading...
Searching...
No Matches
phv/utils/utils.h
1
19#ifndef BF_P4C_PHV_UTILS_UTILS_H_
20#define BF_P4C_PHV_UTILS_UTILS_H_
21
22#include <optional>
23
24#include "bf-p4c/ir/bitrange.h"
25#include "bf-p4c/ir/gress.h"
26#include "bf-p4c/phv/error.h"
27#include "bf-p4c/phv/phv.h"
28#include "bf-p4c/phv/phv_fields.h"
29#include "bf-p4c/phv/pragma/pa_no_init.h"
30#include "bf-p4c/phv/utils/slice_alloc.h"
31#include "lib/bitvec.h"
32#include "lib/symbitmatrix.h"
33
34namespace PHV {
35
39 const PHV::Size size_i;
40
42 std::set<PHV::Type> types_i;
43
45 std::vector<PHV::Container> containers_i;
46
48 bitvec ids_i;
49
50 public:
54 ContainerGroup(PHV::Size size, const std::vector<PHV::Container> containers);
55
59 ContainerGroup(PHV::Size size, bitvec container_group);
60
61 using const_iterator = std::vector<PHV::Container>::const_iterator;
62 const_iterator begin() const { return containers_i.begin(); }
63 const_iterator end() const { return containers_i.end(); }
64
66 bool empty() const { return containers_i.empty(); }
67
69 size_t size() const { return containers_i.size(); }
70
72 PHV::Size width() const { return size_i; }
73
75 const std::set<PHV::Type> types() const { return types_i; }
76
78 bool hasType(PHV::Type t) const { return types_i.count(t); }
79
81 bool is(PHV::Kind k) const {
82 for (auto t : types_i)
83 if (t.kind() == k) return true;
84 return false;
85 }
86
88 bool is(PHV::Size s) const { return s == size_i; }
89
91 bitvec ids() const { return ids_i; }
92
94 bool contains(PHV::Container c) const {
95 return std::find(containers_i.begin(), containers_i.end(), c) != containers_i.end();
96 }
97
101 for (auto c : containers_i)
102 if (c.is(kind)) rs.insert(c);
103 return rs;
104 }
105};
106
107using DarkInitMap = std::vector<DarkInitEntry>;
108
109// TODO: Better way to structure Transactions to avoid this circular
110// dependency?
111class Transaction;
112
118 public:
119 friend class AllocationReport;
120
121 using GressAssignment = std::optional<gress_t>;
124 enum class ContainerAllocStatus { EMPTY, PARTIAL, FULL };
125 enum class ExtractSource { NONE, PACKET, NON_PACKET };
126
134 GressAssignment gress;
135 GressAssignment parserGroupGress;
136 GressAssignment deparserGroupGress;
138 ContainerAllocStatus alloc_status;
139 ExtractSource parserExtractGroupSource;
140 };
141
142 using const_iterator = ordered_map<PHV::Container, ContainerStatus>::const_iterator;
143
152 std::optional<PHV::Container> container;
153
154 explicit ConditionalConstraintData(int bit, PHV::Container c, bool rotate = false)
155 : bitPosition(bit), rotationAllowed(rotate), container(c) {}
156
157 explicit ConditionalConstraintData(int bit, bool rotate = false)
158 : bitPosition(bit), rotationAllowed(rotate), container(std::nullopt) {}
159
160 ConditionalConstraintData()
161 : bitPosition(-1), rotationAllowed(false), container(std::nullopt) {}
162
163 bool operator==(ConditionalConstraintData &other) const {
164 return bitPosition == other.bitPosition && rotationAllowed == other.rotationAllowed &&
165 container == other.container;
166 }
167 };
168
170 using ConditionalConstraints = ordered_map<int, ConditionalConstraint>;
171
172 using FieldStatus = ordered_set<AllocSlice>;
173
174 protected:
175 // These are copied from parent to child on creating a transaction, and
176 // from child to parent on committing.
177 const PhvInfo *phv_i;
178 const PhvUse *uses_i;
180
181 // For efficiency, these are NOT copied from parent to child. Changes in
182 // the child are copied back to the parent on commit. However, parent info
183 // is copied to the child when queried, as a caching optimization.
184 mutable ordered_map<PHV::Container, ContainerStatus> container_status_i;
201 mutable ordered_map<PHV::Container, bitvec> dark_containers_read_allocated_i;
203 mutable DarkInitMap init_map_i;
204
207 mutable ordered_map<gress_t,
210
211 bool isTrivial;
212
213 Allocation(const PhvInfo &phv, const PhvUse &uses, bool isTrivial = false)
214 : phv_i(&phv), uses_i(&uses), isTrivial(isTrivial) {}
215
218
219 private:
222 virtual bool addStatus(PHV::Container c, const ContainerStatus &status);
223
225 virtual void addMetaInitPoints(const AllocSlice &slice, const ActionSet &actions);
226
229 virtual void addSlice(PHV::Container c, AllocSlice slice);
230
233 virtual void setGress(PHV::Container c, GressAssignment gress);
234
237 virtual void setParserGroupGress(PHV::Container c, GressAssignment gress);
238
241 virtual void setDeparserGroupGress(PHV::Container c, GressAssignment gress);
242
245 virtual void setParserExtractGroupSource(PHV::Container c, ExtractSource source);
246
247 public:
251 virtual const ContainerStatus *getStatus(const PHV::Container &c) const = 0;
252
256 virtual FieldStatus getStatus(const PHV::Field *f) const = 0;
257 virtual void foreach_slice(const PHV::Field *f,
258 std::function<void(const AllocSlice &)> cb) const = 0;
259
260 friend class Transaction;
261
263 virtual const_iterator begin() const = 0;
264 virtual const_iterator end() const = 0;
265
268 virtual std::optional<ActionSet> getInitPoints(const AllocSlice &slice) const;
269
271 virtual size_t size() const = 0;
272
274 virtual bool contains(PHV::Container c) const = 0;
275
278 const IR::MAU::Action *act) const;
279
281 virtual ActionSet getInitPointsForField(const PHV::Field *f) const;
282
285
289 const MapFieldToParserStates &field_to_parser_states) const;
290
293 void foreach_slice(PHV::Container c, std::function<void(const AllocSlice &)> cb) const;
294
297 void foreach_slice(PHV::Container c, int stage, PHV::FieldUse access,
298 std::function<void(const AllocSlice &)> cb) const;
299
302 bool addDarkAllocation(const AllocSlice &slice);
303
306 virtual bool isDarkReadAvailable(PHV::Container c, unsigned minStage, unsigned maxStage) const {
307 if (!dark_containers_write_allocated_i.count(c)) return true;
308 for (unsigned i = minStage; i <= maxStage; i++)
309 if (dark_containers_write_allocated_i.at(c)[i]) return false;
310 return true;
311 }
312
315 virtual bool isDarkWriteAvailable(PHV::Container c, unsigned minStage,
316 unsigned maxStage) const {
317 if (!dark_containers_read_allocated_i.count(c)) return true;
318 for (unsigned i = minStage; i <= maxStage; i++)
319 if (dark_containers_read_allocated_i.at(c)[i]) return false;
320 return true;
321 }
322
326 PHV::FieldUse access) const;
327 void foreach_slice(PHV::Container c, le_bitrange range,
328 std::function<void(const AllocSlice &)> cb) const;
329
330 void foreach_slice(PHV::Container c, le_bitrange range, int stage, PHV::FieldUse access,
331 std::function<void(const AllocSlice &)> cb) const;
332
360 virtual std::vector<MutuallyLiveSlices> slicesByLiveness(PHV::Container c) const;
361
380 virtual MutuallyLiveSlices slicesByLiveness(const PHV::Container c, const AllocSlice &sl) const;
381 virtual MutuallyLiveSlices byteSlicesByLiveness(const PHV::Container c, const AllocSlice &sl,
382 const PragmaNoInit &noInit) const;
383 virtual MutuallyLiveSlices slicesByLiveness(const PHV::Container c,
384 std::vector<AllocSlice> &slices) const;
385
388 virtual MutuallyLiveSlices liverange_overlapped_slices(
389 const PHV::Container c, const std::vector<AllocSlice> &slices) const;
390
397 PHV::FieldUse access) const;
398
399 void foreach_slice(const PHV::Field *f, le_bitrange range,
400 std::function<void(const AllocSlice &)> cb) const;
401 void foreach_slice(const PHV::Field *f, le_bitrange range, int stage, PHV::FieldUse access,
402 std::function<void(const AllocSlice &)> cb) const;
403
408 return slices(f, StartLen(0, f->size));
409 }
410
412 PHV::FieldUse access) const {
413 return slices(f, StartLen(0, f->size), stage, access);
414 }
415
417 virtual GressAssignment gress(const PHV::Container &c) const;
418
422 virtual GressAssignment parserGroupGress(PHV::Container c) const;
423
427 virtual GressAssignment deparserGroupGress(PHV::Container c) const;
428
430 virtual ContainerAllocStatus alloc_status(PHV::Container c) const;
431
434 virtual ExtractSource parserExtractGroupSource(PHV::Container c) const;
435
438
446 virtual void allocate(const AllocSlice slice, LiveRangeShrinkingMap *initNodes = nullptr,
447 bool singleGressParserGroup = false);
448
449 virtual void removeAllocatedSlice(const ordered_set<PHV::AllocSlice> &slices);
450
453 virtual void addMetadataInitialization(AllocSlice slice, LiveRangeShrinkingMap initNodes);
454
456 void addARAedge(gress_t grs, const IR::MAU::Table *src, const IR::MAU::Table *dst) const;
457
460 const ordered_map<gress_t,
462 getARAedges() const {
463 return ara_edges;
464 }
465
466 std::string printARAedges() const;
467
469 virtual cstring toString() const;
470
472 virtual Transaction makeTransaction() const;
473
477
479 Transaction *clone(const Allocation &parent) const;
480
483 PHV::Container container;
484 GressAssignment gress;
485 GressAssignment parserGroupGress;
486 GressAssignment deparserGroupGress;
487 ExtractSource parserExtractGroupSource;
488 int n_bits;
489 AvailableSpot(const PHV::Container &c, const GressAssignment &gress,
490 const GressAssignment &parserGroupGress,
491 const GressAssignment &deparserGroupGress,
492 const ExtractSource &parserExtractGroupSource, int n_bits)
493 : container(c),
494 gress(gress),
495 parserGroupGress(parserGroupGress),
496 deparserGroupGress(deparserGroupGress),
497 parserExtractGroupSource(parserExtractGroupSource),
498 n_bits(n_bits) {}
499 bool operator<(const AvailableSpot &other) const { return n_bits < other.n_bits; }
500 };
501
503 std::set<AvailableSpot> available_spots() const;
504};
505
507 static ContainerStatus emptyContainerStatus;
508
513 ConcreteAllocation(const PhvInfo &phv, const PhvUse &, bitvec containers, bool trivial);
514
515 public:
519 const ContainerStatus *getStatus(const PHV::Container &c) const override;
520
524 FieldStatus getStatus(const PHV::Field *f) const override;
525 void foreach_slice(const PHV::Field *f,
526 std::function<void(const AllocSlice &)> cb) const override;
527
532 explicit ConcreteAllocation(const PhvInfo &, const PhvUse &, bool trivial = false);
533
535 const_iterator begin() const override { return container_status_i.begin(); }
536 const_iterator end() const override { return container_status_i.end(); }
537
539 size_t size() const override { return container_status_i.size(); }
540
542 bool contains(PHV::Container c) const override;
543
548};
549
561class Transaction : public Allocation {
562 const Allocation *parent_i;
563
564 public:
568 const ContainerStatus *getStatus(const PHV::Container &c) const override;
569
573 FieldStatus getStatus(const PHV::Field *f) const override;
574 void foreach_slice(const PHV::Field *f,
575 std::function<void(const AllocSlice &)> cb) const override;
576
577 public:
579 explicit Transaction(const Allocation &parent)
580 : Allocation(*parent.phv_i, *parent.uses_i), parent_i(&parent) {
581 BUG_CHECK(&parent != this, "Creating transaction with self as parent");
582
583 for (const auto &map_entry : parent.getARAedges()) {
584 auto grs = map_entry.first;
585
586 for (const auto &src2dsts : map_entry.second) {
587 auto *src_tbl = src2dsts.first;
588
589 for (auto *dst_tbl : src2dsts.second) {
590 this->addARAedge(grs, src_tbl, dst_tbl);
591 }
592 }
593 }
594 }
595
599 void printMetaInitPoints() const;
600
602 virtual ~Transaction() {}
603
606 const_iterator begin() const override;
607
610 const_iterator end() const override;
611
613 size_t size() const override { return parent_i->size(); }
614
616 bool contains(PHV::Container c) const override { return parent_i->contains(c); }
617
620
623
625 std::optional<ActionSet> getInitPoints(const AllocSlice &slice) const override;
626
629 return container_status_i;
630 }
631
634
635 const ordered_map<const PHV::Field *, FieldStatus> &getFieldStatus() const {
636 return field_status_i;
637 }
638
644
651
654 const IR::MAU::Action *act) const override {
655 const ordered_set<const PHV::Field *> parentInits = parent_i->getMetadataInits(act);
656 if (!init_writes_i.count(act)) return parentInits;
658 rv.insert(parentInits.begin(), parentInits.end());
659 auto inits = init_writes_i.at(act);
660 rv.insert(inits.begin(), inits.end());
661 return rv;
662 }
663
666 ActionSet getInitPointsForField(const PHV::Field *f) const override {
667 ActionSet rs = parent_i->getInitPointsForField(f);
668 for (auto kv : meta_init_points_i) {
669 if (kv.first.field() != f) continue;
670 rs.insert(kv.second.begin(), kv.second.end());
671 }
672 return rs;
673 }
674
677 const ordered_map<gress_t,
679 getARAedges() const {
680 // if (ara_edges.count(grs)) return ara_edges.at(grs);
681 return ara_edges;
682
683 // ordered_map<IR::MAU::Table*, std::set<IR::MAU::Table*>> empty_map;
684 // return empty_map;
685 }
686
689 bool isDarkReadAvailable(PHV::Container c, unsigned minStage,
690 unsigned maxStage) const override {
691 return (Allocation::isDarkReadAvailable(c, minStage, maxStage) ||
692 parent_i->isDarkReadAvailable(c, minStage, maxStage));
693 }
694
697 bool isDarkWriteAvailable(PHV::Container c, unsigned minStage,
698 unsigned maxStage) const override {
699 return (Allocation::isDarkWriteAvailable(c, minStage, maxStage) ||
700 parent_i->isDarkWriteAvailable(c, minStage, maxStage));
701 }
702
705 container_status_i.clear();
706 meta_init_points_i.clear();
707 init_writes_i.clear();
708 field_status_i.clear();
710 dark_containers_read_allocated_i.clear();
711 init_map_i.clear();
712 state_to_containers_i.clear();
713 count_by_status_i = parent_i->count_by_status_i;
714 ara_edges.clear();
715 }
716
718 const Allocation *getParent() const { return parent_i; }
719};
720
723 private:
724 static int nextId;
725
726 public:
727 int uid = nextId++;
730 virtual bool okIn(PHV::Kind kind) const = 0;
731
734 virtual int exact_containers() const = 0;
735
737 virtual int max_width() const = 0;
738
741 virtual int num_constraints() const = 0;
742
744 virtual size_t aggregate_size() const = 0;
745
748 virtual bool deparsed() const = 0;
749
751 virtual bool contains(const PHV::Field *f) const = 0;
752
754 virtual bool contains(const PHV::FieldSlice &slice) const = 0;
755
757 virtual gress_t gress() const = 0;
758};
759
761template <typename Cluster>
763 using OptFieldSlice = std::optional<PHV::FieldSlice>;
768 Cluster *lo;
770 Cluster *hi;
771};
772
792 PHV::Kind kind_i;
793 gress_t gress_i = INGRESS;
794
797
798 int id_i; // this cluster's id
799 int exact_containers_i;
800 int max_width_i;
801 int num_constraints_i;
802 size_t aggregate_size_i;
803 bool hasDeparsedFields_i;
804
807 std::optional<FieldAlignment> alignment_i;
808
821 std::optional<le_bitrange> validContainerStartRange(PHV::Size container_size) const;
822
824 static std::optional<le_bitrange> validContainerStartRange(const PHV::FieldSlice &slice,
825 PHV::Size container_size);
826
828 void set_cluster_id();
829
832 void initialize_constraints();
833
834 public:
835 template <typename Iterable>
836 AlignedCluster(PHV::Kind kind, Iterable slices) : kind_i(kind) {
837 set_cluster_id();
838 for (auto &slice : slices) slices_i.insert(slice);
839 initialize_constraints();
840 }
841
844 bool operator==(const AlignedCluster &other) const;
845
847 int id() const { return id_i; }
848
851 bool okIn(PHV::Kind kind) const override;
852
856 std::optional<unsigned> alignment() const {
857 if (alignment_i) return alignment_i->align;
858 return std::nullopt;
859 }
860
875 bitvec validContainerStart(PHV::Size container_size) const;
876
879
881 const ordered_set<PHV::FieldSlice> &slices() const { return slices_i; }
882
883 using const_iterator = ordered_set<PHV::FieldSlice>::const_iterator;
884 const_iterator begin() const { return slices_i.begin(); }
885 const_iterator end() const { return slices_i.end(); }
886
887 // TODO: Revisit the following stats/constraints getters.
888
891 int exact_containers() const override { return exact_containers_i; }
892
894 int max_width() const override { return max_width_i; }
895
898 int num_constraints() const override { return num_constraints_i; }
899
901 size_t aggregate_size() const override { return aggregate_size_i; }
902
905 bool deparsed() const override { return hasDeparsedFields_i; }
906
908 bool contains(const PHV::Field *f) const override;
909
911 bool contains(const PHV::FieldSlice &slice) const override;
912
914 gress_t gress() const override { return gress_i; }
915
929 std::optional<SliceResult<AlignedCluster>> slice(int pos) const;
930
933 PHV::Kind kind() { return kind_i; }
934};
935
942
945
948
949 // Statstics gathered from clusters.
950 PHV::Kind kind_i = PHV::Kind::tagalong;
951 gress_t gress_i = INGRESS;
952 int exact_containers_i = 0;
953 int max_width_i = 0;
954 int num_constraints_i = 0;
955 size_t aggregate_size_i = 0;
956 bool hasDeparsedFields_i = false;
957
958 public:
960
962 bool operator==(const RotationalCluster &other) const;
963
965 const ordered_set<PHV::FieldSlice> &slices() const { return slices_i; }
966
968 const ordered_set<AlignedCluster *> &clusters() const { return clusters_i; }
969
973 auto it = slices_to_clusters_i.find(slice);
974 BUG_CHECK(it != slices_to_clusters_i.end(), "Field %1% not in cluster group",
975 cstring::to_cstring(slice));
976 return *it->second;
977 }
978
981 bool okIn(PHV::Kind kind) const override;
982
984 int exact_containers() const override { return exact_containers_i; }
985
987 int max_width() const override { return max_width_i; }
988
990 int num_constraints() const override { return num_constraints_i; }
991
993 size_t aggregate_size() const override { return aggregate_size_i; }
994
997 bool deparsed() const override { return hasDeparsedFields_i; }
998
1000 bool contains(const PHV::Field *f) const override;
1001
1003 bool contains(const PHV::FieldSlice &slice) const override;
1004
1006 gress_t gress() const override { return gress_i; }
1007
1022 std::optional<SliceResult<RotationalCluster>> slice(int pos) const;
1023};
1024
1050 public:
1051 using SliceList = std::list<PHV::FieldSlice>;
1052
1053 private:
1055 ordered_set<SliceList *> slice_lists_i;
1056
1060
1064
1065 // Statstics gathered from clusters.
1066 PHV::Kind kind_i = PHV::Kind::tagalong;
1067 gress_t gress_i = INGRESS;
1068 int exact_containers_i = 0;
1069 int max_width_i = 0;
1070 int num_constraints_i = 0;
1071 size_t aggregate_size_i = 0;
1072 size_t num_pack_conflicts_i = 0;
1073 bool hasDeparsedFields_i = false;
1074 bool needsStridedAlloc_i = false;
1075
1076 public:
1079
1081 bool operator==(const SuperCluster &other) const;
1082
1084 const ordered_set<const RotationalCluster *> &clusters() const { return clusters_i; }
1085
1087 const ordered_set<SliceList *> &slice_lists() const { return slice_lists_i; }
1088
1091
1095 const RotationalCluster &cluster(const PHV::FieldSlice &slice) const {
1096 auto it = slices_to_clusters_i.find(slice);
1097 BUG_CHECK(it != slices_to_clusters_i.end(), "Field %1% not in cluster group %2%",
1098 cstring::to_cstring(slice), cstring::to_cstring(this));
1099 return *it->second;
1100 }
1101
1106 BUG_CHECK(slices_to_clusters_i.find(slice) != slices_to_clusters_i.end(),
1107 "Field %1% not in cluster group", cstring::to_cstring(slice));
1108 return slices_to_clusters_i.at(slice)->cluster(slice);
1109 }
1110
1115 ordered_set<SliceList *> new_slice_lists;
1116 for (auto *c1 : clusters_i) {
1117 new_clusters_i.insert(c1);
1118 }
1119 for (auto *c2 : sc1->clusters_i) {
1120 new_clusters_i.insert(c2);
1121 }
1122 for (auto *sl1 : slice_lists_i) {
1123 new_slice_lists.insert(sl1);
1124 }
1125 for (auto *sl2 : sc1->slice_lists_i) {
1126 new_slice_lists.insert(sl2);
1127 }
1128 return new SuperCluster(new_clusters_i, new_slice_lists);
1129 }
1130
1132 SuperCluster *merge(const SuperCluster *sc1) const;
1133
1143
1147 bool needToMergeForWideArith(const SuperCluster *sc) const;
1148
1151 SuperCluster::SliceList *findLinkedWideArithSliceList(const SuperCluster::SliceList *sl) const;
1152
1155 bool okIn(PHV::Kind kind) const override;
1156
1158 int exact_containers() const override { return exact_containers_i; }
1159
1161 int max_width() const override { return max_width_i; }
1162
1164 int num_constraints() const override { return num_constraints_i; }
1165
1167 size_t aggregate_size() const override { return aggregate_size_i; }
1168
1172 size_t num_pack_conflicts() const { return num_pack_conflicts_i; }
1173
1175 void calc_pack_conflicts();
1176
1179 bool deparsed() const override { return hasDeparsedFields_i; }
1180
1182 bool needsStridedAlloc() const { return needsStridedAlloc_i; }
1183
1184 void needsStridedAlloc(bool val) { needsStridedAlloc_i = val; }
1185
1187 bool contains(const PHV::Field *f) const override;
1188
1190 bool contains(const PHV::FieldSlice &slice) const override;
1191
1194
1196 gress_t gress() const override { return gress_i; }
1197
1199 void forall_fieldslices(const std::function<void(const PHV::FieldSlice &)> func) const {
1200 for (const auto &kv : slices_to_clusters_i) {
1201 func(kv.first);
1202 }
1203 }
1204
1206 bool any_of_fieldslices(const std::function<bool(const PHV::FieldSlice &)> func) const {
1207 for (const auto &kv : slices_to_clusters_i) {
1208 if (func(kv.first)) return true;
1209 }
1210 return false;
1211 }
1212
1214 bool all_of_fieldslices(const std::function<bool(const PHV::FieldSlice &)> func) const {
1215 for (const auto &kv : slices_to_clusters_i) {
1216 if (!func(kv.first)) return false;
1217 }
1218 return true;
1219 }
1220
1222 bool is_deparser_zero_candidate() const;
1223
1226 static bool is_well_formed(const SuperCluster *sc, PHV::Error *err = new PHV::Error());
1227
1229 static int slice_list_total_bits(const SliceList &list);
1230
1232 static std::vector<le_bitrange> slice_list_exact_containers(const SliceList &list);
1233
1235 static bool slice_list_has_exact_containers(const SliceList &list);
1236
1238 static std::vector<SuperCluster::SliceList *> slice_list_split_by_byte(
1239 const SuperCluster::SliceList &sl);
1240};
1241
1242std::ostream &operator<<(std::ostream &out, const Allocation &);
1243std::ostream &operator<<(std::ostream &out, const Allocation *);
1244std::ostream &operator<<(std::ostream &out, const Allocation::ExtractSource &);
1245std::ostream &operator<<(std::ostream &out, const ContainerGroup &);
1246std::ostream &operator<<(std::ostream &out, const ContainerGroup *);
1247std::ostream &operator<<(std::ostream &out, const AlignedCluster &);
1248std::ostream &operator<<(std::ostream &out, const AlignedCluster *);
1249std::ostream &operator<<(std::ostream &out, const RotationalCluster &);
1250std::ostream &operator<<(std::ostream &out, const RotationalCluster *);
1251std::ostream &operator<<(std::ostream &out, const SuperCluster &);
1252std::ostream &operator<<(std::ostream &out, const SuperCluster *);
1253std::ostream &operator<<(std::ostream &out, const SuperCluster::SliceList &);
1254std::ostream &operator<<(std::ostream &out, const SuperCluster::SliceList *);
1255
1257bool operator<(PHV::Allocation::ContainerAllocStatus, PHV::Allocation::ContainerAllocStatus);
1258bool operator<=(PHV::Allocation::ContainerAllocStatus, PHV::Allocation::ContainerAllocStatus);
1259bool operator>(PHV::Allocation::ContainerAllocStatus, PHV::Allocation::ContainerAllocStatus);
1260bool operator>=(PHV::Allocation::ContainerAllocStatus, PHV::Allocation::ContainerAllocStatus);
1261
1262} // namespace PHV
1263
1264namespace P4 {
1265// TODO: This should go in the public repo, in `p4c/lib/ordered_set.h`.
1266template <typename T>
1267std::ostream &operator<<(std::ostream &out, const ordered_set<T> &set) {
1268 out << "{ ";
1269 unsigned count = 0U;
1270 for (const auto &elt : set) {
1271 out << elt;
1272 count++;
1273 if (count < set.size()) out << ", ";
1274 }
1275 out << " }";
1276 return out;
1277}
1278} // namespace P4
1279
1280#endif /* BF_P4C_PHV_UTILS_UTILS_H_ */
Definition bitvec.h:120
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv/utils/utils.h:789
PHV::Kind kind()
Definition phv/utils/utils.h:933
const ordered_set< PHV::FieldSlice > & slices() const
Definition phv/utils/utils.h:881
gress_t gress() const override
Definition phv/utils/utils.h:914
int max_width() const override
Definition phv/utils/utils.h:894
int exact_containers() const override
Definition phv/utils/utils.h:891
bitvec validContainerStart(PHV::Size container_size) const
Definition phv/utils/utils.cpp:1368
std::optional< unsigned > alignment() const
Definition phv/utils/utils.h:856
size_t aggregate_size() const override
Definition phv/utils/utils.h:901
bool contains(const PHV::Field *f) const override
Definition phv/utils/utils.cpp:1415
bool okIn(PHV::Kind kind) const override
Definition phv/utils/utils.cpp:1366
bool operator==(const AlignedCluster &other) const
Definition phv/utils/utils.cpp:1210
int num_constraints() const override
Definition phv/utils/utils.h:898
std::optional< SliceResult< AlignedCluster > > slice(int pos) const
Definition phv/utils/utils.cpp:1427
int id() const
Definition phv/utils/utils.h:847
bool deparsed() const override
Definition phv/utils/utils.h:905
Definition slice_alloc.h:136
Definition phv/utils/utils.h:117
const ordered_map< gress_t, ordered_map< const IR::MAU::Table *, std::set< const IR::MAU::Table * > > > & getARAedges() const
Definition phv/utils/utils.h:462
ordered_map< AllocSlice, ActionSet > meta_init_points_i
Definition phv/utils/utils.h:188
bool addDarkAllocation(const AllocSlice &slice)
Definition phv/utils/utils.cpp:200
cstring commit(Transaction &view)
Definition phv/utils/utils.cpp:567
virtual MutuallyLiveSlices liverange_overlapped_slices(const PHV::Container c, const std::vector< AllocSlice > &slices) const
Definition phv/utils/utils.cpp:290
void addARAedge(gress_t grs, const IR::MAU::Table *src, const IR::MAU::Table *dst) const
Add a pair of tables in the ara_edges for a new ARA table.
Definition phv/utils/utils.cpp:125
ordered_map< PHV::Container, bitvec > dark_containers_write_allocated_i
Definition phv/utils/utils.h:200
virtual const ContainerStatus * getStatus(const PHV::Container &c) const =0
virtual ActionSet getInitPointsForField(const PHV::Field *f) const
Definition phv/utils/utils.cpp:675
virtual void addMetadataInitialization(AllocSlice slice, LiveRangeShrinkingMap initNodes)
Definition phv/utils/utils.cpp:189
std::set< AvailableSpot > available_spots() const
Return a set of available spots of this allocation.
Definition phv/utils/utils.cpp:722
virtual GressAssignment parserGroupGress(PHV::Container c) const
Definition phv/utils/utils.cpp:906
ordered_set< AllocSlice > slices(PHV::Container c) const
Definition phv/utils/utils.cpp:944
virtual ExtractSource parserExtractGroupSource(PHV::Container c) const
Definition phv/utils/utils.cpp:927
virtual const ordered_set< const PHV::Field * > getMetadataInits(const IR::MAU::Action *act) const
Definition phv/utils/utils.cpp:668
virtual GressAssignment gress(const PHV::Container &c) const
Definition phv/utils/utils.cpp:899
int empty_containers(PHV::Size size) const
Definition phv/utils/utils.cpp:424
virtual bool isDarkWriteAvailable(PHV::Container c, unsigned minStage, unsigned maxStage) const
Definition phv/utils/utils.h:315
const ordered_set< unsigned > getTagalongCollectionsUsed() const
Definition phv/utils/utils.cpp:684
virtual bool isDarkReadAvailable(PHV::Container c, unsigned minStage, unsigned maxStage) const
Definition phv/utils/utils.h:306
ordered_map< gress_t, ordered_map< const IR::MAU::Table *, std::set< const IR::MAU::Table * > > > ara_edges
Definition phv/utils/utils.h:209
DarkInitMap init_map_i
Initialization information about allocating to dark containers during certain stages.
Definition phv/utils/utils.h:203
virtual const_iterator begin() const =0
Iterate through container-->allocation slices.
virtual size_t size() const =0
virtual std::vector< MutuallyLiveSlices > slicesByLiveness(PHV::Container c) const
Definition phv/utils/utils.cpp:366
virtual bool contains(PHV::Container c) const =0
virtual ContainerAllocStatus alloc_status(PHV::Container c) const
Definition phv/utils/utils.cpp:920
virtual cstring toString() const
Definition phv/utils/utils.cpp:666
ordered_map< const IR::BFN::ParserState *, std::set< PHV::Container > > state_to_containers_i
parser state to containers
Definition phv/utils/utils.h:194
ordered_set< PHV::AllocSlice > slices(const PHV::Field *f) const
Definition phv/utils/utils.h:407
const ordered_map< const IR::BFN::ParserState *, std::set< PHV::Container > > & getParserStateToContainers(const PhvInfo &phv, const MapFieldToParserStates &field_to_parser_states) const
Definition phv/utils/utils.cpp:703
virtual FieldStatus getStatus(const PHV::Field *f) const =0
virtual GressAssignment deparserGroupGress(PHV::Container c) const
Definition phv/utils/utils.cpp:913
virtual void allocate(const AllocSlice slice, LiveRangeShrinkingMap *initNodes=nullptr, bool singleGressParserGroup=false)
Definition phv/utils/utils.cpp:435
virtual std::optional< ActionSet > getInitPoints(const AllocSlice &slice) const
Definition phv/utils/utils.cpp:809
virtual Transaction makeTransaction() const
Create a Transaction based on this Allocation.
Definition phv/utils/utils.cpp:663
ordered_map< AllocSlice, ActionSet > & get_meta_init_points() const
Definition phv/utils/utils.h:217
ordered_map< const IR::MAU::Action *, ordered_set< const PHV::Field * > > init_writes_i
Definition phv/utils/utils.h:191
Definition phv/utils/utils.h:133
Definition report.h:26
An interface for gathering statistics common across each kind of cluster.
Definition phv/utils/utils.h:722
virtual int max_width() const =0
virtual int exact_containers() const =0
virtual bool okIn(PHV::Kind kind) const =0
virtual bool contains(const PHV::FieldSlice &slice) const =0
virtual int num_constraints() const =0
virtual gress_t gress() const =0
virtual bool contains(const PHV::Field *f) const =0
virtual bool deparsed() const =0
virtual size_t aggregate_size() const =0
Definition phv/utils/utils.h:506
bool contains(PHV::Container c) const override
Definition phv/utils/utils.cpp:805
size_t size() const override
Definition phv/utils/utils.h:539
void deallocate(const ordered_set< PHV::AllocSlice > &slices)
Definition phv/utils/utils.cpp:854
const ContainerStatus * getStatus(const PHV::Container &c) const override
Definition phv/utils/utils.cpp:832
const_iterator begin() const override
Iterate through container-->allocation slices.
Definition phv/utils/utils.h:535
Definition phv/utils/utils.h:37
PHV::Size width() const
Definition phv/utils/utils.h:72
ContainerGroup(PHV::Size size, const std::vector< PHV::Container > containers)
Definition phv/utils/utils.cpp:44
bool hasType(PHV::Type t) const
Definition phv/utils/utils.h:78
bool empty() const
Definition phv/utils/utils.h:66
bool contains(PHV::Container c) const
Definition phv/utils/utils.h:94
bool is(PHV::Kind k) const
Definition phv/utils/utils.h:81
size_t size() const
Definition phv/utils/utils.h:69
const std::set< PHV::Type > types() const
Definition phv/utils/utils.h:75
bool is(PHV::Size s) const
Definition phv/utils/utils.h:88
bitvec ids() const
Definition phv/utils/utils.h:91
const ordered_set< PHV::Container > getAllContainersOfKind(PHV::Kind kind) const
Definition phv/utils/utils.h:99
Definition phv.h:176
Definition backends/tofino/bf-p4c/phv/error.h:37
Definition phv_fields.h:154
int size
Total size of Field in bits.
Definition phv_fields.h:194
Definition phv_fields.h:898
Definition phv.h:248
Definition phv/utils/utils.h:939
std::optional< SliceResult< RotationalCluster > > slice(int pos) const
Definition phv/utils/utils.cpp:1512
bool operator==(const RotationalCluster &other) const
Semantic equality.
Definition phv/utils/utils.cpp:1483
const ordered_set< AlignedCluster * > & clusters() const
Definition phv/utils/utils.h:968
gress_t gress() const override
Definition phv/utils/utils.h:1006
int num_constraints() const override
Definition phv/utils/utils.h:990
const AlignedCluster & cluster(const PHV::FieldSlice &slice) const
Definition phv/utils/utils.h:972
bool okIn(PHV::Kind kind) const override
Definition phv/utils/utils.cpp:1500
bool deparsed() const override
Definition phv/utils/utils.h:997
size_t aggregate_size() const override
Definition phv/utils/utils.h:993
bool contains(const PHV::Field *f) const override
Definition phv/utils/utils.cpp:1502
const ordered_set< PHV::FieldSlice > & slices() const
Definition phv/utils/utils.h:965
int max_width() const override
Definition phv/utils/utils.h:987
int exact_containers() const override
Definition phv/utils/utils.h:984
Definition phv/utils/utils.h:1049
const ordered_set< const RotationalCluster * > & clusters() const
Definition phv/utils/utils.h:1084
SuperCluster::SliceList * findLinkedWideArithSliceList(const SuperCluster::SliceList *sl) const
Definition phv/utils/utils.cpp:1715
const RotationalCluster & cluster(const PHV::FieldSlice &slice) const
Definition phv/utils/utils.h:1095
ordered_set< PHV::FieldSlice > slices() const
Definition phv/utils/utils.cpp:1759
static std::vector< le_bitrange > slice_list_exact_containers(const SliceList &list)
Definition phv/utils/utils.cpp:1900
bool needsStridedAlloc() const
Definition phv/utils/utils.h:1182
int exact_containers() const override
Definition phv/utils/utils.h:1158
bool any_of_fieldslices(const std::function< bool(const PHV::FieldSlice &)> func) const
Definition phv/utils/utils.h:1206
bool contains(const PHV::Field *f) const override
Definition phv/utils/utils.cpp:1747
gress_t gress() const override
Definition phv/utils/utils.h:1196
static std::vector< SuperCluster::SliceList * > slice_list_split_by_byte(const SuperCluster::SliceList &sl)
Definition phv/utils/utils.cpp:1913
bool okIn(PHV::Kind kind) const override
Definition phv/utils/utils.cpp:1611
int max_width() const override
Definition phv/utils/utils.h:1161
void calc_pack_conflicts()
calculates the value of num_pack_conflicts_i (to be performed after PackConflicts analysis)
Definition phv/utils/utils.cpp:1566
SuperCluster * merge(const SuperCluster *sc1)
Definition phv/utils/utils.h:1113
static bool slice_list_has_exact_containers(const SliceList &list)
Definition phv/utils/utils.cpp:1909
SuperCluster * mergeAndSortBasedOnWideArith(const SuperCluster *sc1) const
Definition phv/utils/utils.cpp:1627
size_t num_pack_conflicts() const
Definition phv/utils/utils.h:1172
bool is_deparser_zero_candidate() const
Definition phv/utils/utils.cpp:1767
const ordered_set< SliceList * > & slice_lists() const
Definition phv/utils/utils.h:1087
bool needToMergeForWideArith(const SuperCluster *sc) const
Definition phv/utils/utils.cpp:1692
bool all_of_fieldslices(const std::function< bool(const PHV::FieldSlice &)> func) const
Apply func on all field slices in this super cluster.
Definition phv/utils/utils.h:1214
size_t aggregate_size() const override
Definition phv/utils/utils.h:1167
static int slice_list_total_bits(const SliceList &list)
Definition phv/utils/utils.cpp:1893
void forall_fieldslices(const std::function< void(const PHV::FieldSlice &)> func) const
Apply func on all field slices in this super cluster.
Definition phv/utils/utils.h:1199
const ordered_set< const SliceList * > & slice_list(const PHV::FieldSlice &slice) const
Definition phv/utils/utils.cpp:1604
int num_constraints() const override
Definition phv/utils/utils.h:1164
static bool is_well_formed(const SuperCluster *sc, PHV::Error *err=new PHV::Error())
Definition phv/utils/utils.cpp:1778
const AlignedCluster & aligned_cluster(const PHV::FieldSlice &slice) const
Definition phv/utils/utils.h:1105
bool operator==(const SuperCluster &other) const
Semantic equality.
Definition phv/utils/utils.cpp:1573
bool deparsed() const override
Definition phv/utils/utils.h:1179
Definition phv/utils/utils.h:561
bool contains(PHV::Container c) const override
Definition phv/utils/utils.h:616
size_t size() const override
Definition phv/utils/utils.h:613
const ordered_set< const PHV::Field * > getMetadataInits(const IR::MAU::Action *act) const override
Definition phv/utils/utils.h:653
std::optional< ActionSet > getInitPoints(const AllocSlice &slice) const override
Definition phv/utils/utils.cpp:814
void printMetaInitPoints() const
Definition phv/utils/utils.cpp:819
ActionSet getInitPointsForField(const PHV::Field *f) const override
Definition phv/utils/utils.h:666
void clearTransactionStatus()
Clears any allocation added to this transaction.
Definition phv/utils/utils.h:704
cstring getTransactionDiff() const
Definition phv/utils/utils.cpp:1096
const Allocation * getParent() const
Returns the allocation that this transaction is based on.
Definition phv/utils/utils.h:718
ordered_map< PHV::Container, ContainerStatus > get_actual_diff() const
Returns the actual diff of outstanding writes in this view.
Definition phv/utils/utils.cpp:1075
bool isDarkWriteAvailable(PHV::Container c, unsigned minStage, unsigned maxStage) const override
Definition phv/utils/utils.h:697
cstring getTransactionSummary() const
Definition phv/utils/utils.cpp:1151
const ordered_map< PHV::Container, ContainerStatus > & getTransactionStatus() const
Returns the outstanding writes in this view.
Definition phv/utils/utils.h:628
virtual ~Transaction()
Destructor declaration. Does nothing but quiets warnings.
Definition phv/utils/utils.h:602
bool isDarkReadAvailable(PHV::Container c, unsigned minStage, unsigned maxStage) const override
Definition phv/utils/utils.h:689
const ordered_map< gress_t, ordered_map< const IR::MAU::Table *, std::set< const IR::MAU::Table * > > > & getARAedges() const
Definition phv/utils/utils.h:679
const ordered_map< const IR::MAU::Action *, ordered_set< const PHV::Field * > > & getInitWrites() const
Definition phv/utils/utils.h:647
const_iterator begin() const override
Definition phv/utils/utils.cpp:935
const_iterator end() const override
Definition phv/utils/utils.cpp:939
const ContainerStatus * getStatus(const PHV::Container &c) const override
Definition phv/utils/utils.cpp:996
Transaction(const Allocation &parent)
Constructor.
Definition phv/utils/utils.h:579
const ordered_map< AllocSlice, ActionSet > & getMetaInitPoints() const
Definition phv/utils/utils.h:641
Definition phv.h:114
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
Definition assoc.h:403
Adds the no_init pragma to the specified fields with the specified gress.
Definition pa_no_init.h:35
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
ordered_map< PHV::FieldSlice, std::pair< PHV::FieldSlice, OptFieldSlice > > slice_map
Definition phv/utils/utils.h:766
Size
all possible PHV container sizes in BFN devices
Definition phv.h:110
Cluster * lo
A new cluster containing the lower field slices.
Definition phv/utils/utils.h:768
Cluster * hi
A new cluster containing the higher field slices.
Definition phv/utils/utils.h:770
Kind
Definition phv.h:44
The result of slicing a cluster.
Definition phv/utils/utils.h:762
STL namespace.
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
Available bits of this allocation.
Definition phv/utils/utils.h:482
Definition phv/utils/utils.h:146
bool rotationAllowed
Boolean set to true if AllocatePHV can use rotationally equivalent bitPosition.
Definition phv/utils/utils.h:150
std::optional< PHV::Container > container
Specific container to which the slice must be allocated.
Definition phv/utils/utils.h:152
int bitPosition
Bit position to which the FieldSlice must be aligned.
Definition phv/utils/utils.h:148