P4C
The P4 Compiler
Loading...
Searching...
No Matches
allocate_phv.h
1
19#ifndef BF_P4C_PHV_ALLOCATE_PHV_H_
20#define BF_P4C_PHV_ALLOCATE_PHV_H_
21
22#include <optional>
23#include <sstream>
24
25#include "backends/tofino/bf-p4c/common/field_defuse.h"
26#include "backends/tofino/bf-p4c/ir/bitrange.h"
27#include "backends/tofino/bf-p4c/ir/gress.h"
28#include "backends/tofino/bf-p4c/parde/clot/clot_info.h"
29#include "backends/tofino/bf-p4c/phv/action_phv_constraints.h"
30#include "backends/tofino/bf-p4c/phv/action_source_tracker.h"
31#include "backends/tofino/bf-p4c/phv/alloc_setting.h"
32#include "backends/tofino/bf-p4c/phv/analysis/critical_path_clusters.h"
33#include "backends/tofino/bf-p4c/phv/analysis/dark_live_range.h"
34#include "backends/tofino/bf-p4c/phv/analysis/live_range_shrinking.h"
35#include "backends/tofino/bf-p4c/phv/collect_strided_headers.h"
36#include "backends/tofino/bf-p4c/phv/fieldslice_live_range.h"
37#include "backends/tofino/bf-p4c/phv/make_clusters.h"
38#include "backends/tofino/bf-p4c/phv/mau_backtracker.h"
39#include "backends/tofino/bf-p4c/phv/phv.h"
40#include "backends/tofino/bf-p4c/phv/phv_fields.h"
41#include "backends/tofino/bf-p4c/phv/phv_parde_mau_use.h"
42#include "backends/tofino/bf-p4c/phv/pragma/phv_pragmas.h"
43#include "backends/tofino/bf-p4c/phv/slicing/types.h"
44#include "backends/tofino/bf-p4c/phv/table_phv_constraints.h"
45#include "backends/tofino/bf-p4c/phv/utils/slice_alloc.h"
46#include "backends/tofino/bf-p4c/phv/utils/tables_to_ids.h"
47#include "backends/tofino/bf-p4c/phv/utils/utils.h"
48#include "lib/bitvec.h"
49#include "lib/symbitmatrix.h"
50
51namespace PHV {
52
55struct AllocUtils {
56 // PHV fields and clot info.
57 const PhvInfo &phv;
58 const ClotInfo &clot;
59
60 // clustering results (super clusters) and no_pack constraint found during clustering.
61 const Clustering &clustering;
62
63 // defuses and action constraints.
64 const PhvUse &uses;
65 const FieldDefUse &defuse;
66
67 // action-related constraints
68 const ActionPhvConstraints &actions;
69 const ActionSourceTracker &source_tracker;
70
71 // Metadata initialization possibilities.
72 const LiveRangeShrinking &meta_init;
73 // Dark overlay possibilities.
74 const DarkOverlay &dark_init;
75
76 // parser-related
77 const MapFieldToParserStates &field_to_parser_states;
78 const CalcParserCriticalPath &parser_critical_path;
79 const CollectParserInfo &parser_info;
80 const CollectStridedHeaders &strided_headers;
81
82 // physical live range (available only after table has been allocated)
83 const PHV::FieldSliceLiveRangeDB &physical_liverange_db;
84
85 // pragma
86 const PHV::Pragmas &pragmas;
87
88 // misc allocation settings.
89 const AllocSetting &settings;
90
91 // Collect field packing that table/ixbar would benefit from.
92 const TableFieldPackOptimization &tablePackOpt;
93
94 AllocUtils(const PhvInfo &phv, const ClotInfo &clot, const Clustering &clustering,
95 const PhvUse &uses, const FieldDefUse &defuse, const ActionPhvConstraints &actions,
96 const LiveRangeShrinking &meta_init, const DarkOverlay &dark_init,
97 const MapFieldToParserStates &field_to_parser_states,
98 const CalcParserCriticalPath &parser_critical_path,
99 const CollectParserInfo &parser_info, const CollectStridedHeaders &strided_headers,
100 const PHV::FieldSliceLiveRangeDB &physical_liverange_db,
101 const ActionSourceTracker &source_tracker, const PHV::Pragmas &pragmas,
102 const AllocSetting &settings, const TableFieldPackOptimization &tablePackOpt)
103 : phv(phv),
104 clot(clot),
105 clustering(clustering),
106 uses(uses),
107 defuse(defuse),
108 actions(actions),
109 source_tracker(source_tracker),
110 meta_init(meta_init),
111 dark_init(dark_init),
112 field_to_parser_states(field_to_parser_states),
113 parser_critical_path(parser_critical_path),
114 parser_info(parser_info),
115 strided_headers(strided_headers),
116 physical_liverange_db(physical_liverange_db),
117 pragmas(pragmas),
118 settings(settings),
119 tablePackOpt(tablePackOpt) {}
120
121 const SymBitMatrix &mutex() const { return phv.field_mutex(); }
122
123 // has_pack_conflict should be used as the only source of pack conflict checks.
124 // It checks mutex + pack conflict from mau + no pack constraint from cluster.
125 bool has_pack_conflict(const PHV::FieldSlice &fs1, const PHV::FieldSlice &fs2) const {
126 if (fs1.field() != fs2.field()) {
127 if (mutex()(fs1.field()->id, fs2.field()->id)) return false;
128 }
129 return clustering.no_pack(fs1.field(), fs2.field()) || actions.hasPackConflict(fs1, fs2);
130 }
131
132 // return true if field is used and not padding.
133 bool is_referenced(const PHV::Field *f) const { return !f->padding && uses.is_referenced(f); };
134
136 std::list<PHV::SuperCluster *> make_superclusters() const {
137 return clustering.cluster_groups();
138 }
139
140 // @returns a slicing iterator.
141 PHV::Slicing::IteratorInterface *make_slicing_ctx(const PHV::SuperCluster *sc) const;
142
143 // @returns true if @p a and @p b can be overlaid,
144 // because of their physical live ranges are disjoint and both fieldslices are
145 // qualified to be overlaid:
146 // (1) not pov, deparsed_to_tm, nor is_invalidate_from_arch.
147 // (2) not in pa_no_overlay.
148 bool can_physical_liverange_be_overlaid(const PHV::AllocSlice &a,
149 const PHV::AllocSlice &b) const;
150
152 static bool is_clot_allocated(const ClotInfo &clots, const PHV::SuperCluster &sc);
153
156 static std::list<PHV::ContainerGroup *> make_device_container_groups();
157
159 static void clear_slices(PhvInfo &phv);
160
163 static void bind_slices(const PHV::ConcreteAllocation &alloc, PhvInfo &phv);
164
168 static void sort_and_merge_alloc_slices(PhvInfo &phv);
169
174 static std::list<PHV::SuperCluster *> remove_singleton_metadata_slicelist(
175 const std::list<PHV::SuperCluster *> &cluster_groups);
176
179 static std::list<PHV::SuperCluster *> remove_unref_clusters(
180 const PhvUse &uses, const std::list<PHV::SuperCluster *> &cluster_groups_input);
181
183 static std::list<PHV::SuperCluster *> remove_clot_allocated_clusters(
184 const ClotInfo &clot, std::list<PHV::SuperCluster *> clusters);
185
188 static std::list<PHV::SuperCluster *> create_strided_clusters(
189 const CollectStridedHeaders &strided_headers,
190 const std::list<PHV::SuperCluster *> &cluster_groups);
191
195 static bool update_refs(AllocSlice &slc, const PhvInfo &p, const FieldDefUse::LocPairSet &refs,
196 FieldUse fuse);
197 static void update_slice_refs(PhvInfo &phv, const FieldDefUse &defuse);
198};
199
200namespace Diagnostics {
201
202std::string printField(const PHV::Field *f);
203std::string printSlice(const PHV::FieldSlice &slice);
204
205} // namespace Diagnostics
206
207} // namespace PHV
208
214 const ActionPhvConstraints &actions;
215 const PhvUse &uses;
216 const FieldDefUse &defuse;
217 const SymBitMatrix &mutex;
218 using FieldPair = std::pair<const PHV::Field *, const PHV::Field *>;
219 std::map<const PHV::Field *, int> opportunities;
220 std::map<FieldPair, int> opportunities_after;
221
223 std::vector<const PHV::Field *> fieldsInOrder(
224 const std::list<PHV::SuperCluster *> &sorted_clusters) const;
225
226 bool isExtractedOrUninitialized(const PHV::Field *f) const;
227 bool canPack(const PHV::Field *f1, const PHV::Field *f2) const;
228
229 public:
231 FieldPackingOpportunity(const std::list<PHV::SuperCluster *> &sorted_clusters,
232 const ActionPhvConstraints &actions, const PhvUse &uses,
233 const FieldDefUse &defuse, const SymBitMatrix &mutex);
234
236 int nOpportunities(const PHV::Field *f) const { return opportunities.at(f); }
237
244 int nOpportunitiesAfter(const PHV::Field *f1, const PHV::Field *f2) const;
245};
246
259 using ContainerAllocStatus = PHV::Allocation::ContainerAllocStatus;
260
262 using IsBetterFunc = std::function<bool(const AllocScore &left, const AllocScore &right)>;
263
266
268 static const std::vector<MetricName> g_general_metrics;
270
272 static const std::vector<MetricName> g_by_kind_metrics;
274
275 AllocScore() {}
276
282 AllocScore(const PHV::Transaction &alloc, const PhvInfo &phv, const ClotInfo &clot,
283 const PhvUse &uses, const MapFieldToParserStates &field_to_parser_states,
284 const CalcParserCriticalPath &parser_critical_path,
285 const TableFieldPackOptimization &tablePackOpt, FieldPackingOpportunity *packing,
286 const int bitmasks);
287
288 AllocScore &operator=(const AllocScore &other) = default;
289 AllocScore operator-(const AllocScore &other) const;
290 static AllocScore make_lowest() { return AllocScore(); }
291
292 private:
293 bitvec calcContainerAllocVec(const ordered_set<PHV::AllocSlice> &slices);
294
295 ContainerAllocStatus calcContainerStatus(const PHV::Container &container,
296 const ordered_set<PHV::AllocSlice> &slices);
297
298 void calcParserExtractorBalanceScore(const PHV::Transaction &alloc, const PhvInfo &phv,
299 const MapFieldToParserStates &field_to_parser_states,
300 const CalcParserCriticalPath &parser_critical_path);
301};
302
303std::ostream &operator<<(std::ostream &s, const AllocScore &score);
304
307 private:
308 cstring name_i;
309
311 FieldPackingOpportunity *packing_opportunities_i = nullptr;
312
314 bool stop_at_first_i = false;
315
317 AllocScore::IsBetterFunc is_better_i;
318
319 public:
320 ScoreContext(cstring name, bool stop_at_first, AllocScore::IsBetterFunc is_better)
321 : name_i(name), stop_at_first_i(stop_at_first), is_better_i(is_better) {}
322
323 AllocScore make_score(const PHV::Transaction &alloc, const PhvInfo &phv, const ClotInfo &clot,
324 const PhvUse &uses, const MapFieldToParserStates &field_to_parser_states,
325 const CalcParserCriticalPath &parser_critical_path,
326 const TableFieldPackOptimization &tablePackOpt,
327 const int bitmasks = 0) const;
328
329 bool is_better(const AllocScore &left, const AllocScore &right) const {
330 return is_better_i(left, right);
331 }
332
333 bool stop_at_first() const { return stop_at_first_i; }
334
336 auto cloned = *this;
337 cloned.packing_opportunities_i = packing;
338 return cloned;
339 }
340};
341
349
353 struct OverlayInfo {
354 bool control_flow_overlay;
355 bool physical_liverange_overlay;
356 bool metadata_overlay;
357 bool dark_overlay;
358 };
359 const PHV::AllocUtils &utils_i;
360
361 // Table allocation information from the previous round.
362 // TODO: legacy, this might actually never be used at all because it is
363 // initialized in value instead of references.
364 const bool disableMetadataInit;
365 // Enforce single gress parser groups
366 bool singleGressParserGroups = false;
367 // Prioritize use of ARA for overlay inits
368 bool prioritizeARAinits = false;
369
370 std::optional<PHV::Transaction> alloc_super_cluster_with_alignment(
371 const PHV::Allocation &alloc, const PHV::ContainerGroup &container_group,
372 PHV::SuperCluster &super_cluster, const AllocAlignment &alignment,
373 const std::list<const PHV::SuperCluster::SliceList *> &sorted_slice_lists,
374 const ScoreContext &score_ctx) const;
375
377 std::vector<AllocAlignment> build_alignments(int max_n,
378 const PHV::ContainerGroup &container_group,
379 const PHV::SuperCluster &super_cluster) const;
380
383 std::vector<AllocAlignment> build_slicelist_alignment(
384 const PHV::ContainerGroup &container_group, const PHV::SuperCluster &super_cluster,
385 const PHV::SuperCluster::SliceList *slice_list) const;
386
387 bool check_metadata_and_dark_overlay(
388 const PHV::Container &c, std::vector<PHV::AllocSlice> &complex_overlay_slices,
389 std::vector<PHV::AllocSlice> &candidate_slices,
390 ordered_set<PHV::AllocSlice> &new_candidate_slices, PHV::Transaction &perContainerAlloc,
392 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes,
393 std::optional<ordered_set<PHV::AllocSlice>> &allocedSlices,
394 ordered_set<PHV::AllocSlice> &metaInitSlices,
395 PHV::Allocation::LiveRangeShrinkingMap &initActions, bool &new_overlay_container,
396 const PHV::ContainerGroup &group, const bool &canDarkInitUseARA) const;
397
398 bool update_new_prim(const PHV::AllocSlice &existingSl, PHV::AllocSlice &newSl,
399 ordered_set<PHV::AllocSlice> &toBeRemovedFromAlloc) const;
400
401 std::optional<std::vector<PHV::AllocSlice>> prepare_candidate_slices(
402 PHV::SuperCluster::SliceList &slices, const PHV::Container &c,
403 const PHV::Allocation::ConditionalConstraint &start_positions) const;
404
405 bool try_metadata_overlay(const PHV::Container &c,
406 std::optional<ordered_set<PHV::AllocSlice>> &allocedSlices,
407 const PHV::AllocSlice &slice,
408 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes,
409 ordered_set<PHV::AllocSlice> &new_candidate_slices,
410 ordered_set<PHV::AllocSlice> &metaInitSlices,
412 PHV::Transaction &perContainerAlloc,
413 const PHV::Allocation::MutuallyLiveSlices &alloced_slices,
414 PHV::Allocation::MutuallyLiveSlices &actual_cntr_state) const;
415
416 bool try_dark_overlay(std::vector<PHV::AllocSlice> &dark_slices,
417 PHV::Transaction &perContainerAlloc, const PHV::Container &c,
418 std::vector<PHV::AllocSlice> &candidate_slices,
419 ordered_set<PHV::AllocSlice> &new_candidate_slices,
420 bool &new_overlay_container, ordered_set<PHV::AllocSlice> &metaInitSlices,
421 const PHV::ContainerGroup &group, const bool &canDarkInitUseARA) const;
422
423 bool try_pack_slice_list(
424 std::vector<PHV::AllocSlice> &candidate_slices, PHV::Transaction &perContainerAlloc,
426 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes, const PHV::Container &c,
427 const PHV::SuperCluster &super_cluster,
428 std::optional<PHV::Allocation::ConditionalConstraints> &action_constraints,
429 int &num_bitmasks) const;
430
431 bool try_place_wide_arith_hi(const PHV::ContainerGroup &group, const PHV::Container &c,
432 PHV::SuperCluster::SliceList *hi_slice,
433 const PHV::SuperCluster &super_cluster,
434 PHV::Transaction &this_alloc, const ScoreContext &score_ctx) const;
435
441 bool find_previous_allocation(
442 PHV::Container &previous_container,
444 const PHV::Allocation::ConditionalConstraint &start_positions,
445 PHV::SuperCluster::SliceList &slices, const PHV::ContainerGroup &group,
446 const PHV::Allocation &alloc) const;
447
448 public:
449 CoreAllocation(const PHV::AllocUtils &utils, bool disable_metainit)
450 : utils_i(utils), disableMetadataInit(disable_metainit) {}
451
453 static bool can_overlay(const SymBitMatrix &mutually_exclusive_field_ids, const PHV::Field *f,
454 const ordered_set<PHV::AllocSlice> &slices);
455
457 static bool some_overlay(const SymBitMatrix &mutually_exclusive_field_ids, const PHV::Field *f,
458 const ordered_set<PHV::AllocSlice> &slices);
459
463 const ordered_set<PHV::AllocSlice> &allocated) const;
464
466 bool hasARAinits(ordered_set<PHV::AllocSlice> slices) const;
467
469 bool satisfies_constraints(std::vector<PHV::AllocSlice> slices,
470 const PHV::Allocation &alloc) const;
471
473 bool satisfies_constraints(const PHV::ContainerGroup &group, const PHV::Field *f) const;
474
477 const PHV::FieldSlice &slice) const;
478
482 bool satisfies_constraints(const PHV::Allocation &alloc, const PHV::AllocSlice &slice,
484 std::vector<PHV::AllocSlice> &candidate_slices) const;
485
488 static bool satisfies_constraints(const PHV::ContainerGroup &container_group,
489 const PHV::SuperCluster &cluster_group);
490
491 // Set/Get single-gress Parser groups
492 void set_single_gress_parser_group() { singleGressParserGroups = true; }
493 bool get_single_gress_parser_group() { return singleGressParserGroups; }
494
495 // Set/Get ARA init priority
496 void set_prioritize_ARA_inits() { prioritizeARAinits = true; }
497 bool get_prioririze_ARA_inits() { return prioritizeARAinits; }
498
520 std::optional<PHV::Transaction> try_alloc(const PHV::Allocation &alloc,
521 const PHV::ContainerGroup &group,
522 PHV::SuperCluster &cluster, int max_alignment_tries,
523 const ScoreContext &score_ctx) const;
524
525 std::optional<const PHV::SuperCluster::SliceList *> find_first_unallocated_slicelist(
526 const PHV::Allocation &alloc, const std::list<PHV::ContainerGroup *> &container_groups,
527 const PHV::SuperCluster &cluster) const;
528
534 std::optional<PHV::Transaction> try_deparser_zero_alloc(const PHV::Allocation &alloc,
535 PHV::SuperCluster &cluster,
536 PhvInfo &phv) const;
537
538 bool checkDarkOverlay(const std::vector<PHV::AllocSlice> &candidate_slices,
539 const PHV::Transaction &alloc) const;
540
542 bool rangesOverlap(const PHV::AllocSlice &slice, const IR::BFN::ParserPrimitive *prim) const;
543
547 bool checkParserExtractions(const std::vector<PHV::AllocSlice> &candidate_slices,
548 const PHV::Transaction &alloc) const;
549
581 std::optional<PHV::Transaction> tryAllocSliceList(
582 const PHV::Allocation &alloc, const PHV::ContainerGroup &group,
583 const PHV::SuperCluster &super_cluster,
584 const PHV::Allocation::ConditionalConstraint &start_positions,
585 const ScoreContext &score_ctx) const;
586
589 std::optional<PHV::Transaction> tryAllocSliceList(
590 const PHV::Allocation &alloc, const PHV::ContainerGroup &group,
591 const PHV::SuperCluster &super_cluster, const PHV::SuperCluster::SliceList &slice_list,
592 const ordered_map<PHV::FieldSlice, int> &start_positions,
593 const ScoreContext &score_ctx) const;
594
595 bool generateNewAllocSlices(const PHV::AllocSlice &origSlice,
596 const ordered_set<PHV::AllocSlice> &alloced_slices,
597 PHV::DarkInitMap &slices,
598 ordered_set<PHV::AllocSlice> &new_candidate_slices,
599 PHV::Transaction &alloc_attempt,
600 const PHV::Allocation::MutuallyLiveSlices &container_state) const;
601
602 bool hasCrossingLiveranges(std::vector<PHV::AllocSlice> candidate_slices,
603 ordered_set<PHV::AllocSlice> alloc_slices) const;
604
614 const PHV::SuperCluster &sc,
615 const std::vector<PHV::AllocSlice> &candidates,
616 const PHV::Container &c) const;
617};
618
619enum class AllocResultCode {
620 UNKNOWN, // default value
621 SUCCESS, // All fields allocated
622 FAIL, // Some fields unallocated
623 FAIL_UNSAT_SLICING // Some fields CANNOT be allocated due to slicing
624};
625
627 AllocResultCode status;
628 PHV::Transaction transaction;
629 std::list<const PHV::SuperCluster *> remaining_clusters;
630 // To avoid copy on those large objects, constructor only takes rvalue,
631 // so use std::move() if needed.
632 AllocResult(AllocResultCode r, PHV::Transaction &&t, // NOLINT
633 std::list<const PHV::SuperCluster *> &&c)
634 : status(r), transaction(t), remaining_clusters(c) {}
635};
636
651 protected:
652 const cstring name;
653 const PHV::AllocUtils &utils_i;
654 const CoreAllocation &core_alloc_i;
655
656 public:
657 AllocationStrategy(cstring name, const PHV::AllocUtils &utils, const CoreAllocation &core)
658 : name(name), utils_i(utils), core_alloc_i(core) {}
659
668 const std::list<PHV::SuperCluster *> &cluster_groups_input,
669 const std::list<PHV::ContainerGroup *> &container_groups) = 0;
670};
671
673 cstring name;
674 // heuristics of alloc score:
675 AllocScore::IsBetterFunc is_better;
676 // if max_failure_retry > 1, will retry (n-1) times by allocating
677 // previsouly failed fields at the beginning of the allocation.
678 int max_failure_retry;
679 // try to split a supercluster for max_slicing_try times then allocate
680 // for best score.
681 int max_slicing;
682 // the number of alignments of slicelists generated.
683 // TODO: currently stopped at the first alloc-able alignment.
684 int max_sl_alignment;
685 // unsupported devices for this config.
686 std::optional<std::unordered_set<Device::Device_t>> unsupported_devices;
687 // enable validation on pre-sliced super clusters to avoid creating unallocatable
688 // clusters at preslicing.
689 bool pre_slicing_validation;
690 // enable AlwaysRun Action use for dark spills and zero-initialization during dark overlays
691 bool enable_ara_in_overlays;
692};
693
695 private:
696 const PHV::Allocation &empty_alloc_i;
697 const BruteForceStrategyConfig &config_i;
698 std::optional<const PHV::SuperCluster::SliceList *> unallocatable_list_i;
699 int pipe_id_i;
700 PhvInfo &phv_i; // mutable because of deparsed zero allocation.
701
702 public:
704 const CoreAllocation &core, const PHV::Allocation &empty_alloc,
705 const BruteForceStrategyConfig &config, int pipeId, PhvInfo &phv);
706
708 const std::list<PHV::SuperCluster *> &cluster_groups_input,
709 const std::list<PHV::ContainerGroup *> &container_groups) override;
710
711 std::optional<const PHV::SuperCluster::SliceList *> get_unallocatable_list() const {
712 return unallocatable_list_i;
713 }
714
715 int getPipeId() const { return pipe_id_i; }
716
717 protected:
718 AllocResult tryAllocationFailuresFirst(
719 const PHV::Allocation &alloc, const std::list<PHV::SuperCluster *> &cluster_groups_input,
720 const std::list<PHV::ContainerGroup *> &container_groups,
721 const ordered_set<const PHV::Field *> &failures);
722
723 std::list<PHV::SuperCluster *> crush_clusters(
724 const std::list<PHV::SuperCluster *> &cluster_groups);
725
727 std::list<PHV::SuperCluster *> preslice_clusters(
728 const std::list<PHV::SuperCluster *> &cluster_groups,
729 const std::list<PHV::ContainerGroup *> &container_groups,
730 std::list<const PHV::SuperCluster *> &unsliceable);
731
733 void sortClusters(std::list<PHV::SuperCluster *> &cluster_groups);
734
735 bool tryAllocSlicing(const std::list<PHV::SuperCluster *> &slicing,
736 const std::list<PHV::ContainerGroup *> &container_groups,
737 PHV::Transaction &slicing_alloc, const ScoreContext &score_ctx);
738
739 bool tryAllocStride(const std::list<PHV::SuperCluster *> &stride,
740 const std::list<PHV::ContainerGroup *> &container_groups,
741 PHV::Transaction &stride_alloc, const ScoreContext &score_ctx);
742
743 bool tryAllocStrideWithLeaderAllocated(const std::list<PHV::SuperCluster *> &stride,
744 PHV::Transaction &leader_alloc,
745 const ScoreContext &score_ctx);
746
747 bool tryAllocSlicingStrided(unsigned num_strides, const std::list<PHV::SuperCluster *> &slicing,
748 const std::list<PHV::ContainerGroup *> &container_groups,
749 PHV::Transaction &slicing_alloc, const ScoreContext &score_ctx);
750
751 std::optional<PHV::Transaction> tryVariousSlicing(
752 PHV::Transaction &rst, PHV::SuperCluster *cluster_group,
753 const std::list<PHV::ContainerGroup *> &container_groups, const ScoreContext &score_ctx,
754 std::stringstream &alloc_history);
755
756 std::list<PHV::SuperCluster *> allocLoop(
757 PHV::Transaction &rst, std::list<PHV::SuperCluster *> &cluster_groups,
758 const std::list<PHV::ContainerGroup *> &container_groups, const ScoreContext &score_ctx);
759
762 std::list<PHV::SuperCluster *> allocDeparserZeroSuperclusters(
763 PHV::Transaction &rst, std::list<PHV::SuperCluster *> &cluster_groups);
764
772 const std::set<PHV::Allocation::AvailableSpot> &spots);
773
783 std::list<PHV::SuperCluster *> pounderRoundAllocLoop(
784 PHV::Transaction &rst, std::list<PHV::SuperCluster *> &cluster_groups,
785 const std::list<PHV::ContainerGroup *> &container_groups);
787 // return unallocatable slice list by allocating superclusters to an empty PHV.
788 std::optional<const PHV::SuperCluster::SliceList *> diagnose_slicing(
789 const std::list<PHV::SuperCluster *> &slicing,
790 const std::list<PHV::ContainerGroup *> &container_groups) const;
791
792 // return unallocatable slice list.
793 // It will try to slice @p sliced further and allocate to an empty PHV.
794 // The reason why this function will try to split further is because that
795 // there can be valid presliced cluster that is too large for a single container group.
796 std::optional<const PHV::SuperCluster::SliceList *> preslice_validation(
797 const std::list<PHV::SuperCluster *> &sliced,
798 const std::list<PHV::ContainerGroup *> &container_groups) const;
799
801};
802
813class AllocatePHV : public Visitor {
814 private:
815 const PHV::AllocUtils &utils_i;
816 const MauBacktracker &mau_i;
817 CoreAllocation core_alloc_i;
818 PhvInfo &phv_i;
819 const IR::BFN::Pipe *root = nullptr;
820 // const DependencyGraph &deps_i;
821 PHV::ConcreteAllocation *alloc = nullptr;
822 std::list<const PHV::SuperCluster *> &unallocated_i;
826 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override;
827
830 static void formatAndThrowUnsat(const std::list<const PHV::SuperCluster *> &unallocated);
831
835 static bool diagnoseSuperCluster(const PHV::SuperCluster *sc, const PHV::AllocUtils &utils);
836
838 AllocResult brute_force_alloc(
840 std::vector<const PHV::SuperCluster::SliceList *> &unallocatable_lists,
841 std::list<PHV::SuperCluster *> &cluster_groups,
842 const std::list<PHV::ContainerGroup *> &container_groups, const int pipe_id) const;
843
844 public:
845 AllocatePHV(const PHV::AllocUtils &utils, const MauBacktracker &mau, PhvInfo &phv,
846 // const DependencyGraph &deps,
847 std::list<const PHV::SuperCluster *> &unallocated)
848 : utils_i(utils),
849 mau_i(mau),
850 core_alloc_i(utils, mau.disableMetadataInitialization()),
851 phv_i(phv),
852 // deps_i(deps),
853 unallocated_i(unallocated) {}
854
858 static bool diagnoseFailures(const std::list<const PHV::SuperCluster *> &unallocated,
859 const PHV::AllocUtils &utils);
860
863 static void formatAndThrowError(const PHV::Allocation &alloc,
864 const std::list<const PHV::SuperCluster *> &unallocated);
865
866 PHV::ConcreteAllocation *getAllocation() { return alloc; }
867};
868
874 const PHV::AllocUtils &utils_i;
875 CoreAllocation core_alloc_i;
876 PhvInfo &phv_i;
877 PHV::AllocSetting &settings_i;
878
879 // fields to be allocated.
880 const ordered_set<PHV::Field *> &temp_vars_i;
881
882 // This pass does not traverse IR.
883 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override;
884
885 public:
886 explicit IncrementalPHVAllocation(const ordered_set<PHV::Field *> &temp_vars,
887 const PHV::AllocUtils &utils, PhvInfo &phv,
888 PHV::AllocSetting &settings)
889 : utils_i(utils),
890 core_alloc_i(utils, true),
891 phv_i(phv),
892 settings_i(settings),
893 temp_vars_i(temp_vars) {}
894};
895
896#endif /* BF_P4C_PHV_ALLOCATE_PHV_H_ */
Definition action_phv_constraints.h:107
bool hasPackConflict(const PHV::FieldSlice fs1, const PHV::FieldSlice fs2) const
Definition action_phv_constraints.h:825
Definition allocate_phv.h:813
static bool diagnoseFailures(const std::list< const PHV::SuperCluster * > &unallocated, const PHV::AllocUtils &utils)
Definition allocate_phv.cpp:4285
static void formatAndThrowError(const PHV::Allocation &alloc, const std::list< const PHV::SuperCluster * > &unallocated)
Definition allocate_phv.cpp:4463
Definition allocate_phv.h:650
virtual AllocResult tryAllocation(const PHV::Allocation &alloc, const std::list< PHV::SuperCluster * > &cluster_groups_input, const std::list< PHV::ContainerGroup * > &container_groups)=0
Definition allocate_phv.h:694
void sortClusters(std::list< PHV::SuperCluster * > &cluster_groups)
Sort list of superclusters into the order in which they should be allocated.
Definition allocate_phv.cpp:4979
AllocResult tryAllocation(const PHV::Allocation &alloc, const std::list< PHV::SuperCluster * > &cluster_groups_input, const std::list< PHV::ContainerGroup * > &container_groups) override
Definition allocate_phv.cpp:4940
std::optional< PHV::Transaction > tryVariousSlicing(PHV::Transaction &rst, PHV::SuperCluster *cluster_group, const std::list< PHV::ContainerGroup * > &container_groups, const ScoreContext &score_ctx, std::stringstream &alloc_history)
Definition allocate_phv.cpp:5548
std::list< PHV::SuperCluster * > preslice_clusters(const std::list< PHV::SuperCluster * > &cluster_groups, const std::list< PHV::ContainerGroup * > &container_groups, std::list< const PHV::SuperCluster * > &unsliceable)
slice clusters into clusters with container-sized chunks.
Definition allocate_phv.cpp:4797
std::list< PHV::SuperCluster * > pounderRoundAllocLoop(PHV::Transaction &rst, std::list< PHV::SuperCluster * > &cluster_groups, const std::list< PHV::ContainerGroup * > &container_groups)
Definition allocate_phv.cpp:4698
ordered_set< bitvec > calc_slicing_schemas(const PHV::SuperCluster *sc, const std::set< PHV::Allocation::AvailableSpot > &spots)
Definition allocate_phv.cpp:4594
std::list< PHV::SuperCluster * > allocDeparserZeroSuperclusters(PHV::Transaction &rst, std::list< PHV::SuperCluster * > &cluster_groups)
Definition allocate_phv.cpp:4635
Definition optimize_phv.h:64
Definition parser_critical_path.h:131
Definition clot_info.h:41
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 allocate_phv.h:352
std::optional< PHV::Transaction > tryAllocSliceList(const PHV::Allocation &alloc, const PHV::ContainerGroup &group, const PHV::SuperCluster &super_cluster, const PHV::Allocation::ConditionalConstraint &start_positions, const ScoreContext &score_ctx) const
Definition allocate_phv.cpp:2800
std::optional< PHV::Transaction > try_alloc(const PHV::Allocation &alloc, const PHV::ContainerGroup &group, PHV::SuperCluster &cluster, int max_alignment_tries, const ScoreContext &score_ctx) const
Definition allocate_phv.cpp:3744
static bool some_overlay(const SymBitMatrix &mutually_exclusive_field_ids, const PHV::Field *f, const ordered_set< PHV::AllocSlice > &slices)
Definition allocate_phv.cpp:1158
std::optional< PHV::Transaction > try_deparser_zero_alloc(const PHV::Allocation &alloc, PHV::SuperCluster &cluster, PhvInfo &phv) const
Definition allocate_phv.cpp:4655
bool satisfies_constraints(std::vector< PHV::AllocSlice > slices, const PHV::Allocation &alloc) const
Definition allocate_phv.cpp:1211
PHV::Transaction make_speculated_alloc(const PHV::Transaction &alloc, const PHV::SuperCluster &sc, const std::vector< PHV::AllocSlice > &candidates, const PHV::Container &c) const
bool hasARAinits(ordered_set< PHV::AllocSlice > slices) const
@look for ARA inits in set of slices
Definition allocate_phv.cpp:1179
static bool can_overlay(const SymBitMatrix &mutually_exclusive_field_ids, const PHV::Field *f, const ordered_set< PHV::AllocSlice > &slices)
Definition allocate_phv.cpp:1150
bool rangesOverlap(const PHV::AllocSlice &slice, const IR::BFN::ParserPrimitive *prim) const
Do the slice and prim have overlapping field ranges.
Definition allocate_phv.cpp:1986
bool can_physical_liverange_overlay(const PHV::AllocSlice &slice, const ordered_set< PHV::AllocSlice > &allocated) const
Definition allocate_phv.cpp:1165
bool checkParserExtractions(const std::vector< PHV::AllocSlice > &candidate_slices, const PHV::Transaction &alloc) const
Definition allocate_phv.cpp:2009
Definition dark_live_range.h:389
Definition allocate_phv.h:213
FieldPackingOpportunity(const std::list< PHV::SuperCluster * > &sorted_clusters, const ActionPhvConstraints &actions, const PhvUse &uses, const FieldDefUse &defuse, const SymBitMatrix &mutex)
sorted_clusters is a list of clusters that we will allocated, in this order.
Definition allocate_phv.cpp:5766
int nOpportunitiesAfter(const PHV::Field *f1, const PHV::Field *f2) const
Definition allocate_phv.cpp:5789
int nOpportunities(const PHV::Field *f) const
How many fields, after f is allocated, can be packed with f.
Definition allocate_phv.h:236
Definition allocate_phv.h:873
Definition live_range_shrinking.h:183
Definition mau_backtracker.h:29
bool disableMetadataInitialization() const
Definition mau_backtracker.h:105
Definition node.h:94
Definition symbitmatrix.h:27
Definition visitor.h:75
Definition bitvec.h:120
Definition cstring.h:85
Definition ordered_map.h:32
ActionSourceTracker collects all source-to-destination for all field slices.
Definition action_source_tracker.h:49
Definition slice_alloc.h:136
Definition phv/utils/utils.h:117
Definition phv/utils/utils.h:506
Definition phv/utils/utils.h:37
Definition phv.h:176
Definition phv_fields.h:154
int id
Unique field ID.
Definition phv_fields.h:164
bool padding
True if this Field is a padding field.
Definition phv_fields.h:222
Definition phv_fields.h:898
const PHV::Field * field() const override
Definition phv_fields.h:977
Definition fieldslice_live_range.h:152
Definition phv.h:248
Definition phv_pragmas.h:46
The interface that the iterator must satisfy.
Definition slicing/types.h:108
Definition phv/utils/utils.h:1049
Definition phv/utils/utils.h:561
bool is_referenced(const PHV::Field *f) const
Definition phv_parde_mau_use.cpp:179
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
ScoreContext can compute a alloc score for an PHV::Transaction.
Definition allocate_phv.h:306
Definition table_phv_constraints.h:97
Definition field_defuse.h:77
The namespace encapsulating PHV-related stuff.
Definition gateway.h:32
Definition alloc_setting.h:25
AllocAlignment has two maps used by tryAllocSliceList.
Definition allocate_phv.h:343
ordered_map< PHV::FieldSlice, int > slice_alignment
a slice_alignment maps field slice to start bit location in a container.
Definition allocate_phv.h:345
ordered_map< const PHV::AlignedCluster *, int > cluster_alignment
a cluster_alignment maps aligned cluster to start bit location in a container.
Definition allocate_phv.h:347
Definition allocate_phv.h:626
Definition allocate_phv.h:258
std::function< bool(const AllocScore &left, const AllocScore &right)> IsBetterFunc
IsBetterFunc returns true if left is better than right.
Definition allocate_phv.h:262
static const std::vector< MetricName > g_by_kind_metrics
container-kind-specific scores.
Definition allocate_phv.h:786
cstring MetricName
type of the name of a metric.
Definition allocate_phv.h:265
static const std::vector< MetricName > g_general_metrics
general metrics
Definition allocate_phv.h:780
Definition allocate_phv.h:672
Collects header stacks that require strided allocation (in a parser loop).
Definition collect_strided_headers.h:28
Map field to the parser states in which they are extracted or assigned from checksums.
Definition phv_fields.h:1755
Definition allocate_phv.h:55
static std::list< PHV::SuperCluster * > remove_clot_allocated_clusters(const ClotInfo &clot, std::list< PHV::SuperCluster * > clusters)
Definition allocate_phv.cpp:771
static bool is_clot_allocated(const ClotInfo &clots, const PHV::SuperCluster &sc)
Definition allocate_phv.cpp:688
static void bind_slices(const PHV::ConcreteAllocation &alloc, PhvInfo &phv)
Definition allocate_phv.cpp:3847
static std::list< PHV::SuperCluster * > remove_unref_clusters(const PhvUse &uses, const std::list< PHV::SuperCluster * > &cluster_groups_input)
Definition allocate_phv.cpp:757
static void clear_slices(PhvInfo &phv)
clear alloc_slices allocated in phv, if any.
Definition allocate_phv.cpp:3842
static std::list< PHV::SuperCluster * > remove_singleton_metadata_slicelist(const std::list< PHV::SuperCluster * > &cluster_groups)
Definition allocate_phv.cpp:717
static std::list< PHV::ContainerGroup * > make_device_container_groups()
Definition allocate_phv.cpp:3809
static void sort_and_merge_alloc_slices(PhvInfo &phv)
Definition allocate_phv.cpp:4036
std::list< PHV::SuperCluster * > make_superclusters() const
Definition allocate_phv.h:136
static std::list< PHV::SuperCluster * > create_strided_clusters(const CollectStridedHeaders &strided_headers, const std::list< PHV::SuperCluster * > &cluster_groups)
Definition allocate_phv.cpp:3937
static bool update_refs(AllocSlice &slc, const PhvInfo &p, const FieldDefUse::LocPairSet &refs, FieldUse fuse)
Definition allocate_phv.cpp:3872