P4C
The P4 Compiler
Loading...
Searching...
No Matches
make_clusters.h
1
19#ifndef BF_P4C_PHV_MAKE_CLUSTERS_H_
20#define BF_P4C_PHV_MAKE_CLUSTERS_H_
21
22#include "backends/tofino/bf-p4c/common/field_defuse.h"
23#include "backends/tofino/bf-p4c/ir/bitrange.h"
24#include "backends/tofino/bf-p4c/ir/thread_visitor.h"
25#include "backends/tofino/bf-p4c/ir/tofino_write_context.h"
26#include "backends/tofino/bf-p4c/lib/union_find.hpp"
27#include "backends/tofino/bf-p4c/mau/gateway.h"
28#include "backends/tofino/bf-p4c/mau/table_dependency_graph.h"
29#include "backends/tofino/bf-p4c/mau/table_mutex.h"
30#include "backends/tofino/bf-p4c/phv/action_phv_constraints.h"
31#include "backends/tofino/bf-p4c/phv/alloc_setting.h"
32#include "backends/tofino/bf-p4c/phv/analysis/pack_conflicts.h"
33#include "backends/tofino/bf-p4c/phv/phv.h"
34#include "backends/tofino/bf-p4c/phv/phv_parde_mau_use.h"
35#include "backends/tofino/bf-p4c/phv/pragma/pa_byte_pack.h"
36#include "backends/tofino/bf-p4c/phv/pragma/pa_container_size.h"
37#include "backends/tofino/bf-p4c/phv/utils/utils.h"
38#include "ir/ir.h"
39#include "ir/visitor.h"
40#include "lib/map.h"
41#include "lib/ordered_map.h"
42#include "lib/ordered_set.h"
43#include "lib/range.h"
44
45namespace PHV {
46class Field;
47} // namespace PHV
48
49class PhvInfo;
50
67class Clustering : public PassManager {
68 PhvInfo &phv_i;
69 PhvUse &uses_i;
70 const PackConflicts &conflicts_i;
71 const PragmaContainerSize &pa_container_sizes_i;
72 const PragmaBytePack &pa_byte_pack_i;
73 const FieldDefUse &defuse_i;
74 const DependencyGraph &deps_i;
75 const TablesMutuallyExclusive &table_mutex_i;
76 const PHV::AllocSetting &settings_i;
77
79 std::list<PHV::AlignedCluster *> aligned_clusters_i;
80
83 std::list<PHV::RotationalCluster *> rotational_clusters_i;
84
87 std::list<PHV::SuperCluster *> super_clusters_i;
88
92 inconsistent_extract_no_packs_i;
93
96
101 UnionFind<const PHV::Field *> complex_validity_bits_i;
102
105 std::vector<PHV::FieldSlice> slices(const PHV::Field *field, le_bitrange range) const;
106
109 PHV::RotationalCluster *insert_rotational_cluster(PHV::Field *f);
110
113 class ClearClusteringStructs : public Inspector {
114 Clustering &self;
115 Visitor::profile_t init_apply(const IR::Node *node) override;
116
117 public:
118 explicit ClearClusteringStructs(Clustering &self) : self(self) {}
119 };
120
127 class FindComplexValidityBits : public Inspector {
128 Clustering &self;
129 PhvInfo &phv_i;
130
131 bool preorder(const IR::MAU::Instruction *) override;
132 void end_apply() override;
133
134 public:
135 explicit FindComplexValidityBits(Clustering &self) : self(self), phv_i(self.phv_i) {}
136 };
137
157 class MakeSlices : public Inspector {
158 Clustering &self;
159 PhvInfo &phv_i;
160 const PragmaContainerSize &pa_sizes_i;
161
165 std::vector<ordered_set<PHV::FieldSlice>> equivalences_i;
166
169 profile_t init_apply(const IR::Node *root) override;
170
171 bool preorder(const IR::MAU::Table *tbl) override;
172
175 bool preorder(const IR::Expression *) override;
176
179 void postorder(const IR::MAU::Instruction *) override;
180
181 // TODO: Add a check for shrinking casts that fails if any are
182 // detected.
183
185 void end_apply() override;
186
187 public:
188 explicit MakeSlices(Clustering &self, const PragmaContainerSize &pa)
189 : self(self), phv_i(self.phv_i), pa_sizes_i(pa) {}
190
194 bool updateSlices(const PHV::Field *field, le_bitrange range);
195 };
196
197 MakeSlices slice_i;
198
199 class MakeAlignedClusters : public Inspector {
200 Clustering &self;
201 PhvInfo &phv_i;
202 const PhvUse &uses_i;
203
205 UnionFind<PHV::FieldSlice> union_find_i;
206
208 profile_t init_apply(const IR::Node *root) override;
209
211 bool preorder(const IR::MAU::Instruction *inst) override;
212
217 bool preorder(const IR::MAU::Table *tbl) override;
218
220 void end_apply() override;
221
222 public:
223 explicit MakeAlignedClusters(Clustering &self)
224 : self(self), phv_i(self.phv_i), uses_i(self.uses_i) {}
225 };
226
227 class MakeRotationalClusters : public Inspector {
228 Clustering &self;
229 PhvInfo &phv_i;
230
233 UnionFind<PHV::AlignedCluster *> union_find_i;
234
238
241 Visitor::profile_t init_apply(const IR::Node *) override;
242
245 bool preorder(const IR::MAU::Instruction *) override;
246
249 void end_apply() override;
250
251 public:
252 explicit MakeRotationalClusters(Clustering &self) : self(self), phv_i(self.phv_i) {}
253 };
254
293 class CollectInconsistentFlexibleFieldExtract : public Inspector {
294 Clustering &self;
295 const PhvInfo &phv_i;
296 std::map<int, std::vector<const PHV::Field *>> headers_i;
297 using ExtractVec = std::set<std::pair<nw_bitrange, const PHV::Field *>>;
298 std::vector<ExtractVec> extracts_i;
299
300 Visitor::profile_t init_apply(const IR::Node *root) override {
301 auto rv = Inspector::init_apply(root);
302 headers_i.clear();
303 extracts_i.clear();
304 return rv;
305 }
306
307 void save_header_layout(const IR::HeaderRef *hr);
308 bool preorder(const IR::ConcreteHeaderRef *) override;
309 bool preorder(const IR::HeaderStackItemRef *) override;
310 bool preorder(const IR::BFN::ParserState *state) override;
311 void end_apply() override;
312
313 public:
314 explicit CollectInconsistentFlexibleFieldExtract(Clustering &self, const PhvInfo &phv)
315 : self(self), phv_i(phv) {}
316 };
317
323 class CollectPlaceTogetherConstraints : public Inspector {
324 Clustering &self;
325 PhvInfo &phv_i;
326 const PackConflicts &conflicts_i;
327 const ActionPhvConstraints &actions_i;
328 const CollectInconsistentFlexibleFieldExtract &inconsistent_extract_i;
329
330 // Reason of why fieldslices must be placed together.
331 // NOTE: the lower the number, the higher the priority(more constraints).
332 // This priority is used by the solver algorithm.
333 enum class Reason : int {
334 PaBytePack = 0, // pa_byte_pack pragma
335 Header = 1, // parsed + deparsed
336 Resubmit = 2, // 8-bytes limit + deparsed
337 Mirror = 3, // deparsed
338 Learning = 4, // no_pack in same byte, handled in phv_fields: aligment = 0
339 Pktgen = 5, // unknown
340 BridgedTogether = 6, // egress metadata that are bridged together
341 ConstrainedMeta = 7, // metadata with constraints like solitary needs to in a list.
342 PaContainerSize = 8, // metadata with pa_container_size pragmas.
343 };
344
347 std::map<Reason, std::vector<PHV::SuperCluster::SliceList *>> place_together_i;
348
352
355 ordered_set<int> headers_i;
356
359 ordered_set<PHV::SuperCluster::SliceList *> bridged_extracted_together_i;
360
362 Visitor::profile_t init_apply(const IR::Node *root) override {
363 auto rv = Inspector::init_apply(root);
364 place_together_i.clear();
365 slice_lists_i.clear();
366 headers_i.clear();
367 bridged_extracted_together_i.clear();
368 return rv;
369 };
370
372 void end_apply() override;
373
383 void solve_place_together_constraints();
384
387 void pack_pa_byte_pack_and_update_alignment();
388
390 void pack_pa_container_sized_metadata();
391
396 void pack_constrained_metadata();
397
400 void pack_bridged_extracted_together();
401
403 void pack_pov_bits();
404
406 void visit_header_ref(const IR::HeaderRef *hr);
407
409 void visit_digest_fieldlist(const IR::BFN::DigestFieldList *fl, int skip, Reason reason);
410
412 bool preorder(const IR::ConcreteHeaderRef *) override;
413
415 bool preorder(const IR::HeaderStackItemRef *) override;
416
418 bool preorder(const IR::BFN::Digest *) override;
419
422 bool preorder(const IR::BFN::ParserState *state) override;
423
424 public:
425 explicit CollectPlaceTogetherConstraints(
426 Clustering &self, const ActionPhvConstraints &actions,
427 const CollectInconsistentFlexibleFieldExtract &inconsistent)
428 : self(self),
429 phv_i(self.phv_i),
430 conflicts_i(self.conflicts_i),
431 actions_i(actions),
432 inconsistent_extract_i(inconsistent) {}
433
434 ordered_set<PHV::SuperCluster::SliceList *> get_slice_lists() const {
435 return slice_lists_i;
436 }
437 };
438
439 class MakeSuperClusters : public Inspector {
440 Clustering &self;
441 PhvInfo &phv_i;
442 const CollectPlaceTogetherConstraints &place_togethers_i;
443
445 Visitor::profile_t init_apply(const IR::Node *) override;
446
449 void end_apply() override;
450
455 void addPaddingForMarshaledFields(ordered_set<const PHV::RotationalCluster *> &cluster_set,
457
458 public:
459 explicit MakeSuperClusters(Clustering &self,
460 const CollectPlaceTogetherConstraints &place_togethers)
461 : self(self), phv_i(self.phv_i), place_togethers_i(place_togethers) {}
462 };
463
464 class ValidateClusters : public Inspector {
465 private:
466 Clustering &self;
467 const MauBacktracker &mau_bt;
468
469 profile_t init_apply(const IR::Node *root) override;
470
471 // basic checks: slicelist is not empty, no duplicated fieldslices.
472 static void validate_basics(const std::list<PHV::SuperCluster *> &clusters);
473
478 static void validate_deparsed_zero_clusters(const std::list<PHV::SuperCluster *> &clusters);
479
480 // size % 8 = 0 if exact_containers
481 static std::optional<cstring> validate_exact_container_lists(
482 const std::list<PHV::SuperCluster *> &clusters, const PhvUse &uses);
483
484 // alignments of fieldslices in list must be all sat.
485 static void validate_alignments(const std::list<PHV::SuperCluster *> &clusters,
486 const PhvUse &uses);
487
488 // inconsistent extractions cannot share fields in a same byte of a header.
489 static void validate_extract_from_flexible(
490 const std::list<PHV::SuperCluster *> &clusters,
491 std::function<bool(const PHV::Field *a, const PHV::Field *b)> no_pack);
492
493 // if field->same_container_group, then all the fieldslices of the field must
494 // be in the same super cluster.
495 static void validate_same_container_group_fields(
496 const std::list<PHV::SuperCluster *> &clusters,
497 const ordered_map<const PHV::Field *, std::list<PHV::FieldSlice>> &field_to_slices);
498
499 public:
500 explicit ValidateClusters(Clustering &c, const MauBacktracker &mau_bt)
501 : self(c), mau_bt(mau_bt) {}
502 };
503
504 class UpdateSameContainerAllocConstraint : public Inspector {
505 private:
506 Clustering &self;
507
508 profile_t init_apply(const IR::Node *root) override;
509
510 public:
511 explicit UpdateSameContainerAllocConstraint(Clustering &c) : self(c) {}
512 };
513
514 public:
515 Clustering(PhvInfo &p, PhvUse &u, const PackConflicts &c, const PragmaContainerSize &pa_sz,
516 const PragmaBytePack &pa_byte_pack, const ActionPhvConstraints &a,
517 const FieldDefUse &defuse, const DependencyGraph &deps,
518 const TablesMutuallyExclusive &table_mutex, const PHV::AllocSetting &settings,
519 const MauBacktracker &mau_bt)
520 : phv_i(p),
521 uses_i(u),
522 conflicts_i(c),
523 pa_container_sizes_i(pa_sz),
524 pa_byte_pack_i(pa_byte_pack),
525 defuse_i(defuse),
526 deps_i(deps),
527 table_mutex_i(table_mutex),
528 settings_i(settings),
529 slice_i(*this, pa_sz) {
530 auto *inconsistent_extracts =
531 new CollectInconsistentFlexibleFieldExtract(*this, this->phv_i);
532 auto *place_togethers =
533 new CollectPlaceTogetherConstraints(*this, a, *inconsistent_extracts);
534 addPasses({
535 new ClearClusteringStructs(*this), // clears pre-existing maps
536 new FindComplexValidityBits(*this), // populates complex_validity_bits_i
537 &slice_i,
538 new MakeAlignedClusters(*this), // populates aligned_clusters_i
539 new MakeRotationalClusters(*this), // populates rotational_clusters_i
540 inconsistent_extracts, place_togethers,
541 new MakeSuperClusters(*this, *place_togethers), // populates super_clusters_i
542 new ValidateClusters(*this, mau_bt), // validate clustering is correct.
543 new UpdateSameContainerAllocConstraint(*this) // update SameContainerAllocConstraint
544 });
545 }
546
548 const std::list<PHV::SuperCluster *> &cluster_groups() const { return super_clusters_i; }
549
552 bool no_pack(const PHV::Field *a, const PHV::Field *b) const {
553 return inconsistent_extract_no_packs_i.count(a) &&
554 inconsistent_extract_no_packs_i.at(a).count(b);
555 }
556};
557
558#endif /* BF_P4C_PHV_MAKE_CLUSTERS_H_ */
Definition action_phv_constraints.h:107
Builds "clusters" of field slices that must be placed in the same group.
Definition make_clusters.h:67
bool no_pack(const PHV::Field *a, const PHV::Field *b) const
Definition make_clusters.h:552
const std::list< PHV::SuperCluster * > & cluster_groups() const
Definition make_clusters.h:548
Definition mau_backtracker.h:29
Definition node.h:94
Definition visitor.h:400
Definition ir/pass_manager.h:40
Definition visitor.h:78
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv_fields.h:154
Definition phv/utils/utils.h:939
Definition pack_conflicts.h:36
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
Definition pa_byte_pack.h:39
Definition pa_container_size.h:39
Definition mau/table_mutex.h:110
Definition assoc.h:403
Definition field_defuse.h:77
The namespace encapsulating PHV-related stuff.
Definition gateway.h:32
Definition alloc_setting.h:25
Definition table_dependency_graph.h:52