P4C
The P4 Compiler
Loading...
Searching...
No Matches
allocate_phv.h
1
18
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
55class AllocUtils {
56 public:
57 // PHV fields and clot info.
58 const PhvInfo &phv;
59 const ClotInfo &clot;
60
61 // clustering results (super clusters) and no_pack constraint found during clustering.
62 const Clustering &clustering;
63
64 // defuses and action constraints.
65 const PhvUse &uses;
66 const FieldDefUse &defuse;
67
68 // action-related constraints
69 const ActionPhvConstraints &actions;
70 const ActionSourceTracker &source_tracker;
71
72 // Metadata initialization possibilities.
73 const LiveRangeShrinking &meta_init;
74 // Dark overlay possibilities.
75 const DarkOverlay &dark_init;
76
77 // parser-related
78 const MapFieldToParserStates &field_to_parser_states;
79 const CalcParserCriticalPath &parser_critical_path;
80 const CollectParserInfo &parser_info;
81 const CollectStridedHeaders &strided_headers;
82
83 // physical live range (available only after table has been allocated)
84 const PHV::FieldSliceLiveRangeDB &physical_liverange_db;
85
86 // pragma
87 const PHV::Pragmas &pragmas;
88
89 // misc allocation settings.
90 const AllocSetting &settings;
91
92 // Collect field packing that table/ixbar would benefit from.
93 const TableFieldPackOptimization &tablePackOpt;
94
95 AllocUtils(const PhvInfo &phv, const ClotInfo &clot, const Clustering &clustering,
96 const PhvUse &uses, const FieldDefUse &defuse, const ActionPhvConstraints &actions,
97 const LiveRangeShrinking &meta_init, const DarkOverlay &dark_init,
98 const MapFieldToParserStates &field_to_parser_states,
99 const CalcParserCriticalPath &parser_critical_path,
100 const CollectParserInfo &parser_info, const CollectStridedHeaders &strided_headers,
101 const PHV::FieldSliceLiveRangeDB &physical_liverange_db,
102 const ActionSourceTracker &source_tracker, const PHV::Pragmas &pragmas,
103 const AllocSetting &settings, const TableFieldPackOptimization &tablePackOpt)
104 : phv(phv),
105 clot(clot),
106 clustering(clustering),
107 uses(uses),
108 defuse(defuse),
109 actions(actions),
110 source_tracker(source_tracker),
111 meta_init(meta_init),
112 dark_init(dark_init),
113 field_to_parser_states(field_to_parser_states),
114 parser_critical_path(parser_critical_path),
115 parser_info(parser_info),
116 strided_headers(strided_headers),
117 physical_liverange_db(physical_liverange_db),
118 pragmas(pragmas),
119 settings(settings),
120 tablePackOpt(tablePackOpt) {}
121
122 const SymBitMatrix &mutex() const { return phv.field_mutex(); }
123
124 // has_pack_conflict should be used as the only source of pack conflict checks.
125 // It checks mutex + pack conflict from mau + no pack constraint from cluster.
126 bool has_pack_conflict(const PHV::FieldSlice &fs1, const PHV::FieldSlice &fs2) const {
127 if (fs1.field() != fs2.field()) {
128 if (mutex()(fs1.field()->id, fs2.field()->id)) return false;
129 }
130 return clustering.no_pack(fs1.field(), fs2.field()) || actions.hasPackConflict(fs1, fs2);
131 }
132
133 // return true if field is used and not padding.
134 bool is_referenced(const PHV::Field *f) const { return !f->padding && uses.is_referenced(f); };
135
137 std::list<PHV::SuperCluster *> make_superclusters() const {
138 return clustering.cluster_groups();
139 }
140
141 // @returns a slicing iterator.
142 PHV::Slicing::IteratorInterface *make_slicing_ctx(const PHV::SuperCluster *sc) const;
143
144 // @returns true if @p a and @p b can be overlaid,
145 // because of their physical live ranges are disjoint and both fieldslices are
146 // qualified to be overlaid:
147 // (1) not pov, deparsed_to_tm, nor is_invalidate_from_arch.
148 // (2) not in pa_no_overlay.
149 bool can_physical_liverange_be_overlaid(const PHV::AllocSlice &a,
150 const PHV::AllocSlice &b) const;
151
153 static bool is_clot_allocated(const ClotInfo &clots, const PHV::SuperCluster &sc);
154
157 static std::list<PHV::ContainerGroup *> make_device_container_groups();
158
160 static void clear_slices(PhvInfo &phv);
161
164 static void bind_slices(const PHV::ConcreteAllocation &alloc, PhvInfo &phv);
165
169 static void sort_and_merge_alloc_slices(PhvInfo &phv);
170
175 static std::list<PHV::SuperCluster *> remove_singleton_metadata_slicelist(
176 const std::list<PHV::SuperCluster *> &cluster_groups);
177
180 static std::list<PHV::SuperCluster *> remove_unref_clusters(
181 const PhvUse &uses, const std::list<PHV::SuperCluster *> &cluster_groups_input);
182
184 static std::list<PHV::SuperCluster *> remove_clot_allocated_clusters(
185 const ClotInfo &clot, std::list<PHV::SuperCluster *> clusters);
186
189 static std::list<PHV::SuperCluster *> create_strided_clusters(
190 const CollectStridedHeaders &strided_headers,
191 const std::list<PHV::SuperCluster *> &cluster_groups);
192
196 static bool update_refs(AllocSlice &slc, const PhvInfo &p, const FieldDefUse::LocPairSet &refs,
197 FieldUse fuse);
198 static void update_slice_refs(PhvInfo &phv, const FieldDefUse &defuse);
199};
200
201namespace Diagnostics {
202
203std::string printField(const PHV::Field *f);
204std::string printSlice(const PHV::FieldSlice &slice);
205
206} // namespace Diagnostics
207
208} // namespace PHV
209
215 const ActionPhvConstraints &actions;
216 const PhvUse &uses;
217 const FieldDefUse &defuse;
218 const SymBitMatrix &mutex;
219 using FieldPair = std::pair<const PHV::Field *, const PHV::Field *>;
220 std::map<const PHV::Field *, int> opportunities;
221 std::map<FieldPair, int> opportunities_after;
222
224 std::vector<const PHV::Field *> fieldsInOrder(
225 const std::list<PHV::SuperCluster *> &sorted_clusters) const;
226
227 bool isExtractedOrUninitialized(const PHV::Field *f) const;
228 bool canPack(const PHV::Field *f1, const PHV::Field *f2) const;
229
230 public:
232 FieldPackingOpportunity(const std::list<PHV::SuperCluster *> &sorted_clusters,
233 const ActionPhvConstraints &actions, const PhvUse &uses,
234 const FieldDefUse &defuse, const SymBitMatrix &mutex);
235
237 int nOpportunities(const PHV::Field *f) const { return opportunities.at(f); }
238
245 int nOpportunitiesAfter(const PHV::Field *f1, const PHV::Field *f2) const;
246};
247
259struct AllocScore {
260 using ContainerAllocStatus = PHV::Allocation::ContainerAllocStatus;
261
263 using IsBetterFunc = std::function<bool(const AllocScore &left, const AllocScore &right)>;
264
267
269 static const std::vector<MetricName> g_general_metrics;
271
273 static const std::vector<MetricName> g_by_kind_metrics;
275
276 AllocScore() {}
277
283 AllocScore(const PHV::Transaction &alloc, const PhvInfo &phv, const ClotInfo &clot,
284 const PhvUse &uses, const MapFieldToParserStates &field_to_parser_states,
285 const CalcParserCriticalPath &parser_critical_path,
286 const TableFieldPackOptimization &tablePackOpt, FieldPackingOpportunity *packing,
287 const int bitmasks);
288
289 AllocScore &operator=(const AllocScore &other) = default;
290 AllocScore operator-(const AllocScore &other) const;
291 static AllocScore make_lowest() { return AllocScore(); }
292
293 private:
294 bitvec calcContainerAllocVec(const ordered_set<PHV::AllocSlice> &slices);
295
296 ContainerAllocStatus calcContainerStatus(const PHV::Container &container,
297 const ordered_set<PHV::AllocSlice> &slices);
298
299 void calcParserExtractorBalanceScore(const PHV::Transaction &alloc, const PhvInfo &phv,
300 const MapFieldToParserStates &field_to_parser_states,
301 const CalcParserCriticalPath &parser_critical_path);
302};
303
304std::ostream &operator<<(std::ostream &s, const AllocScore &score);
305
307class ScoreContext {
308 private:
309 cstring name_i;
310
312 FieldPackingOpportunity *packing_opportunities_i = nullptr;
313
315 bool stop_at_first_i = false;
316
318 AllocScore::IsBetterFunc is_better_i;
319
320 public:
321 ScoreContext(cstring name, bool stop_at_first, AllocScore::IsBetterFunc is_better)
322 : name_i(name), stop_at_first_i(stop_at_first), is_better_i(is_better) {}
323
324 AllocScore make_score(const PHV::Transaction &alloc, const PhvInfo &phv, const ClotInfo &clot,
325 const PhvUse &uses, const MapFieldToParserStates &field_to_parser_states,
326 const CalcParserCriticalPath &parser_critical_path,
327 const TableFieldPackOptimization &tablePackOpt,
328 const int bitmasks = 0) const;
329
330 bool is_better(const AllocScore &left, const AllocScore &right) const {
331 return is_better_i(left, right);
332 }
333
334 bool stop_at_first() const { return stop_at_first_i; }
335
336 ScoreContext with(FieldPackingOpportunity *packing) {
337 auto cloned = *this;
338 cloned.packing_opportunities_i = packing;
339 return cloned;
340 }
341};
342
350
353class CoreAllocation {
354 struct OverlayInfo {
355 bool control_flow_overlay;
356 bool physical_liverange_overlay;
357 bool metadata_overlay;
358 bool dark_overlay;
359 };
360 const PHV::AllocUtils &utils_i;
361
362 // Table allocation information from the previous round.
363 // TODO: legacy, this might actually never be used at all because it is
364 // initialized in value instead of references.
365 const bool disableMetadataInit;
366 // Enforce single gress parser groups
367 bool singleGressParserGroups = false;
368 // Prioritize use of ARA for overlay inits
369 bool prioritizeARAinits = false;
370
371 std::optional<PHV::Transaction> alloc_super_cluster_with_alignment(
372 const PHV::Allocation &alloc, const PHV::ContainerGroup &container_group,
373 PHV::SuperCluster &super_cluster, const AllocAlignment &alignment,
374 const std::list<const PHV::SuperCluster::SliceList *> &sorted_slice_lists,
375 const ScoreContext &score_ctx) const;
376
378 std::vector<AllocAlignment> build_alignments(int max_n,
379 const PHV::ContainerGroup &container_group,
380 const PHV::SuperCluster &super_cluster) const;
381
384 std::vector<AllocAlignment> build_slicelist_alignment(
385 const PHV::ContainerGroup &container_group, const PHV::SuperCluster &super_cluster,
386 const PHV::SuperCluster::SliceList *slice_list) const;
387
388 bool check_metadata_and_dark_overlay(
389 const PHV::Container &c, std::vector<PHV::AllocSlice> &complex_overlay_slices,
390 std::vector<PHV::AllocSlice> &candidate_slices,
391 ordered_set<PHV::AllocSlice> &new_candidate_slices, PHV::Transaction &perContainerAlloc,
393 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes,
394 std::optional<ordered_set<PHV::AllocSlice>> &allocedSlices,
395 ordered_set<PHV::AllocSlice> &metaInitSlices,
396 PHV::Allocation::LiveRangeShrinkingMap &initActions, bool &new_overlay_container,
397 const PHV::ContainerGroup &group, const bool &canDarkInitUseARA) const;
398
399 bool update_new_prim(const PHV::AllocSlice &existingSl, PHV::AllocSlice &newSl,
400 ordered_set<PHV::AllocSlice> &toBeRemovedFromAlloc) const;
401
402 std::optional<std::vector<PHV::AllocSlice>> prepare_candidate_slices(
403 PHV::SuperCluster::SliceList &slices, const PHV::Container &c,
404 const PHV::Allocation::ConditionalConstraint &start_positions) const;
405
406 bool try_metadata_overlay(const PHV::Container &c,
407 std::optional<ordered_set<PHV::AllocSlice>> &allocedSlices,
408 const PHV::AllocSlice &slice,
409 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes,
410 ordered_set<PHV::AllocSlice> &new_candidate_slices,
411 ordered_set<PHV::AllocSlice> &metaInitSlices,
412 PHV::Allocation::LiveRangeShrinkingMap &initActions,
413 PHV::Transaction &perContainerAlloc,
414 const PHV::Allocation::MutuallyLiveSlices &alloced_slices,
415 PHV::Allocation::MutuallyLiveSlices &actual_cntr_state) const;
416
417 bool try_dark_overlay(std::vector<PHV::AllocSlice> &dark_slices,
418 PHV::Transaction &perContainerAlloc, const PHV::Container &c,
419 std::vector<PHV::AllocSlice> &candidate_slices,
420 ordered_set<PHV::AllocSlice> &new_candidate_slices,
421 bool &new_overlay_container, ordered_set<PHV::AllocSlice> &metaInitSlices,
422 const PHV::ContainerGroup &group, const bool &canDarkInitUseARA) const;
423
424 bool try_pack_slice_list(
425 std::vector<PHV::AllocSlice> &candidate_slices, PHV::Transaction &perContainerAlloc,
426 PHV::Allocation::LiveRangeShrinkingMap &initActions,
427 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes, const PHV::Container &c,
428 const PHV::SuperCluster &super_cluster,
429 std::optional<PHV::Allocation::ConditionalConstraints> &action_constraints,
430 int &num_bitmasks) const;
431
432 bool try_place_wide_arith_hi(const PHV::ContainerGroup &group, const PHV::Container &c,
433 PHV::SuperCluster::SliceList *hi_slice,
434 const PHV::SuperCluster &super_cluster,
435 PHV::Transaction &this_alloc, const ScoreContext &score_ctx) const;
436
442 bool find_previous_allocation(
443 PHV::Container &previous_container,
445 const PHV::Allocation::ConditionalConstraint &start_positions,
446 PHV::SuperCluster::SliceList &slices, const PHV::ContainerGroup &group,
447 const PHV::Allocation &alloc) const;
448
449 public:
450 CoreAllocation(const PHV::AllocUtils &utils, bool disable_metainit)
451 : utils_i(utils), disableMetadataInit(disable_metainit) {}
452
454 static bool can_overlay(const SymBitMatrix &mutually_exclusive_field_ids, const PHV::Field *f,
455 const ordered_set<PHV::AllocSlice> &slices);
456
458 static bool some_overlay(const SymBitMatrix &mutually_exclusive_field_ids, const PHV::Field *f,
459 const ordered_set<PHV::AllocSlice> &slices);
460
464 const ordered_set<PHV::AllocSlice> &allocated) const;
465
467 bool hasARAinits(ordered_set<PHV::AllocSlice> slices) const;
468
470 bool satisfies_constraints(std::vector<PHV::AllocSlice> slices,
471 const PHV::Allocation &alloc) const;
472
474 bool satisfies_constraints(const PHV::ContainerGroup &group, const PHV::Field *f) const;
475
478 const PHV::FieldSlice &slice) const;
479
483 bool satisfies_constraints(const PHV::Allocation &alloc, const PHV::AllocSlice &slice,
485 std::vector<PHV::AllocSlice> &candidate_slices) const;
486
489 static bool satisfies_constraints(const PHV::ContainerGroup &container_group,
490 const PHV::SuperCluster &cluster_group);
491
492 // Set/Get single-gress Parser groups
493 void set_single_gress_parser_group() { singleGressParserGroups = true; }
494 bool get_single_gress_parser_group() { return singleGressParserGroups; }
495
496 // Set/Get ARA init priority
497 void set_prioritize_ARA_inits() { prioritizeARAinits = true; }
498 bool get_prioririze_ARA_inits() { return prioritizeARAinits; }
499
521 std::optional<PHV::Transaction> try_alloc(const PHV::Allocation &alloc,
522 const PHV::ContainerGroup &group,
523 PHV::SuperCluster &cluster, int max_alignment_tries,
524 const ScoreContext &score_ctx) const;
525
526 std::optional<const PHV::SuperCluster::SliceList *> find_first_unallocated_slicelist(
527 const PHV::Allocation &alloc, const std::list<PHV::ContainerGroup *> &container_groups,
528 const PHV::SuperCluster &cluster) const;
529
535 std::optional<PHV::Transaction> try_deparser_zero_alloc(const PHV::Allocation &alloc,
536 PHV::SuperCluster &cluster,
537 PhvInfo &phv) const;
538
539 bool checkDarkOverlay(const std::vector<PHV::AllocSlice> &candidate_slices,
540 const PHV::Transaction &alloc) const;
541
543 bool rangesOverlap(const PHV::AllocSlice &slice, const IR::BFN::ParserPrimitive *prim) const;
544
548 bool checkParserExtractions(const std::vector<PHV::AllocSlice> &candidate_slices,
549 const PHV::Transaction &alloc) const;
550
582 std::optional<PHV::Transaction> tryAllocSliceList(
583 const PHV::Allocation &alloc, const PHV::ContainerGroup &group,
584 const PHV::SuperCluster &super_cluster,
585 const PHV::Allocation::ConditionalConstraint &start_positions,
586 const ScoreContext &score_ctx) const;
587
590 std::optional<PHV::Transaction> tryAllocSliceList(
591 const PHV::Allocation &alloc, const PHV::ContainerGroup &group,
592 const PHV::SuperCluster &super_cluster, const PHV::SuperCluster::SliceList &slice_list,
593 const ordered_map<PHV::FieldSlice, int> &start_positions,
594 const ScoreContext &score_ctx) const;
595
596 bool generateNewAllocSlices(const PHV::AllocSlice &origSlice,
597 const ordered_set<PHV::AllocSlice> &alloced_slices,
598 PHV::DarkInitMap &slices,
599 ordered_set<PHV::AllocSlice> &new_candidate_slices,
600 PHV::Transaction &alloc_attempt,
601 const PHV::Allocation::MutuallyLiveSlices &container_state) const;
602
603 bool hasCrossingLiveranges(std::vector<PHV::AllocSlice> candidate_slices,
604 ordered_set<PHV::AllocSlice> alloc_slices) const;
605
615 const PHV::SuperCluster &sc,
616 const std::vector<PHV::AllocSlice> &candidates,
617 const PHV::Container &c) const;
618};
619
620enum class AllocResultCode {
621 UNKNOWN, // default value
622 SUCCESS, // All fields allocated
623 FAIL, // Some fields unallocated
624 FAIL_UNSAT_SLICING // Some fields CANNOT be allocated due to slicing
625};
626
627struct AllocResult {
628 AllocResultCode status;
629 PHV::Transaction transaction;
630 std::list<const PHV::SuperCluster *> remaining_clusters;
631 // To avoid copy on those large objects, constructor only takes rvalue,
632 // so use std::move() if needed.
633 AllocResult(AllocResultCode r, PHV::Transaction &&t, // NOLINT
634 std::list<const PHV::SuperCluster *> &&c)
635 : status(r), transaction(t), remaining_clusters(c) {}
636};
637
651class AllocationStrategy {
652 protected:
653 const cstring name;
654 const PHV::AllocUtils &utils_i;
655 const CoreAllocation &core_alloc_i;
656
657 public:
658 AllocationStrategy(cstring name, const PHV::AllocUtils &utils, const CoreAllocation &core)
659 : name(name), utils_i(utils), core_alloc_i(core) {}
660
669 const std::list<PHV::SuperCluster *> &cluster_groups_input,
670 const std::list<PHV::ContainerGroup *> &container_groups) = 0;
671};
672
674 cstring name;
675 // heuristics of alloc score:
676 AllocScore::IsBetterFunc is_better;
677 // if max_failure_retry > 1, will retry (n-1) times by allocating
678 // previsouly failed fields at the beginning of the allocation.
679 int max_failure_retry;
680 // try to split a supercluster for max_slicing_try times then allocate
681 // for best score.
682 int max_slicing;
683 // the number of alignments of slicelists generated.
684 // TODO: currently stopped at the first alloc-able alignment.
685 int max_sl_alignment;
686 // unsupported devices for this config.
687 std::optional<std::unordered_set<Device::Device_t>> unsupported_devices;
688 // enable validation on pre-sliced super clusters to avoid creating unallocatable
689 // clusters at preslicing.
690 bool pre_slicing_validation;
691 // enable AlwaysRun Action use for dark spills and zero-initialization during dark overlays
692 bool enable_ara_in_overlays;
693};
694
695class BruteForceAllocationStrategy : public AllocationStrategy {
696 private:
697 const PHV::Allocation &empty_alloc_i;
698 const BruteForceStrategyConfig &config_i;
699 std::optional<const PHV::SuperCluster::SliceList *> unallocatable_list_i;
700 int pipe_id_i;
701 PhvInfo &phv_i; // mutable because of deparsed zero allocation.
702
703 public:
704 BruteForceAllocationStrategy(const cstring name, const PHV::AllocUtils &utils,
705 const CoreAllocation &core, const PHV::Allocation &empty_alloc,
706 const BruteForceStrategyConfig &config, int pipeId, PhvInfo &phv);
707
709 const std::list<PHV::SuperCluster *> &cluster_groups_input,
710 const std::list<PHV::ContainerGroup *> &container_groups) override;
711
712 std::optional<const PHV::SuperCluster::SliceList *> get_unallocatable_list() const {
713 return unallocatable_list_i;
714 }
715
716 int getPipeId() const { return pipe_id_i; }
717
718 protected:
719 AllocResult tryAllocationFailuresFirst(
720 const PHV::Allocation &alloc, const std::list<PHV::SuperCluster *> &cluster_groups_input,
721 const std::list<PHV::ContainerGroup *> &container_groups,
722 const ordered_set<const PHV::Field *> &failures);
723
724 std::list<PHV::SuperCluster *> crush_clusters(
725 const std::list<PHV::SuperCluster *> &cluster_groups);
726
728 std::list<PHV::SuperCluster *> preslice_clusters(
729 const std::list<PHV::SuperCluster *> &cluster_groups,
730 const std::list<PHV::ContainerGroup *> &container_groups,
731 std::list<const PHV::SuperCluster *> &unsliceable);
732
734 void sortClusters(std::list<PHV::SuperCluster *> &cluster_groups);
735
736 bool tryAllocSlicing(const std::list<PHV::SuperCluster *> &slicing,
737 const std::list<PHV::ContainerGroup *> &container_groups,
738 PHV::Transaction &slicing_alloc, const ScoreContext &score_ctx);
739
740 bool tryAllocStride(const std::list<PHV::SuperCluster *> &stride,
741 const std::list<PHV::ContainerGroup *> &container_groups,
742 PHV::Transaction &stride_alloc, const ScoreContext &score_ctx);
743
744 bool tryAllocStrideWithLeaderAllocated(const std::list<PHV::SuperCluster *> &stride,
745 PHV::Transaction &leader_alloc,
746 const ScoreContext &score_ctx);
747
748 bool tryAllocSlicingStrided(unsigned num_strides, const std::list<PHV::SuperCluster *> &slicing,
749 const std::list<PHV::ContainerGroup *> &container_groups,
750 PHV::Transaction &slicing_alloc, const ScoreContext &score_ctx);
751
752 std::optional<PHV::Transaction> tryVariousSlicing(
753 PHV::Transaction &rst, PHV::SuperCluster *cluster_group,
754 const std::list<PHV::ContainerGroup *> &container_groups, const ScoreContext &score_ctx,
755 std::stringstream &alloc_history);
756
757 std::list<PHV::SuperCluster *> allocLoop(
758 PHV::Transaction &rst, std::list<PHV::SuperCluster *> &cluster_groups,
759 const std::list<PHV::ContainerGroup *> &container_groups, const ScoreContext &score_ctx);
760
763 std::list<PHV::SuperCluster *> allocDeparserZeroSuperclusters(
764 PHV::Transaction &rst, std::list<PHV::SuperCluster *> &cluster_groups);
765
773 const std::set<PHV::Allocation::AvailableSpot> &spots);
774
781 * Try to slice and allocate each cluster by trying the slicing schemas returned from
782 * calc_slicing_schema, in order.
783 */
784 std::list<PHV::SuperCluster *> pounderRoundAllocLoop(
785 PHV::Transaction &rst, std::list<PHV::SuperCluster *> &cluster_groups,
786 const std::list<PHV::ContainerGroup *> &container_groups);
787
788 // return unallocatable slice list by allocating superclusters to an empty PHV.
789 std::optional<const PHV::SuperCluster::SliceList *> diagnose_slicing(
790 const std::list<PHV::SuperCluster *> &slicing,
791 const std::list<PHV::ContainerGroup *> &container_groups) const;
792
793 // return unallocatable slice list.
794 // It will try to slice @p sliced further and allocate to an empty PHV.
795 // The reason why this function will try to split further is because that
796 // there can be valid presliced cluster that is too large for a single container group.
797 std::optional<const PHV::SuperCluster::SliceList *> preslice_validation(
798 const std::list<PHV::SuperCluster *> &sliced,
799 const std::list<PHV::ContainerGroup *> &container_groups) const;
800
802};
803
814class AllocatePHV : public Visitor {
815 private:
816 const PHV::AllocUtils &utils_i;
817 const MauBacktracker &mau_i;
818 CoreAllocation core_alloc_i;
819 PhvInfo &phv_i;
820 const IR::BFN::Pipe *root = nullptr;
821 // const DependencyGraph &deps_i;
822 PHV::ConcreteAllocation *alloc = nullptr;
823 std::list<const PHV::SuperCluster *> &unallocated_i;
827 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override;
828
831 static void formatAndThrowUnsat(const std::list<const PHV::SuperCluster *> &unallocated);
832
836 static bool diagnoseSuperCluster(const PHV::SuperCluster *sc, const PHV::AllocUtils &utils);
837
839 AllocResult brute_force_alloc(
841 std::vector<const PHV::SuperCluster::SliceList *> &unallocatable_lists,
842 std::list<PHV::SuperCluster *> &cluster_groups,
843 const std::list<PHV::ContainerGroup *> &container_groups, const int pipe_id) const;
844
845 public:
846 AllocatePHV(const PHV::AllocUtils &utils, const MauBacktracker &mau, PhvInfo &phv,
847 // const DependencyGraph &deps,
848 std::list<const PHV::SuperCluster *> &unallocated)
849 : utils_i(utils),
850 mau_i(mau),
851 core_alloc_i(utils, mau.disableMetadataInitialization()),
852 phv_i(phv),
853 // deps_i(deps),
854 unallocated_i(unallocated) {}
855
859 static bool diagnoseFailures(const std::list<const PHV::SuperCluster *> &unallocated,
860 const PHV::AllocUtils &utils);
861
864 static void formatAndThrowError(const PHV::Allocation &alloc,
865 const std::list<const PHV::SuperCluster *> &unallocated);
866
867 PHV::ConcreteAllocation *getAllocation() { return alloc; }
868};
869
874class IncrementalPHVAllocation : public Visitor {
875 const PHV::AllocUtils &utils_i;
876 CoreAllocation core_alloc_i;
877 PhvInfo &phv_i;
878 PHV::AllocSetting &settings_i;
879
880 // fields to be allocated.
881 const ordered_set<PHV::Field *> &temp_vars_i;
882
883 // This pass does not traverse IR.
884 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override;
885
886 public:
887 explicit IncrementalPHVAllocation(const ordered_set<PHV::Field *> &temp_vars,
888 const PHV::AllocUtils &utils, PhvInfo &phv,
889 PHV::AllocSetting &settings)
890 : utils_i(utils),
891 core_alloc_i(utils, true),
892 phv_i(phv),
893 settings_i(settings),
894 temp_vars_i(temp_vars) {}
895};
896
897#endif /* BF_P4C_PHV_ALLOCATE_PHV_H_ */
Definition action_phv_constraints.h:107
static bool diagnoseFailures(const std::list< const PHV::SuperCluster * > &unallocated, const PHV::AllocUtils &utils)
Definition allocate_phv.cpp:4283
static void formatAndThrowError(const PHV::Allocation &alloc, const std::list< const PHV::SuperCluster * > &unallocated)
Definition allocate_phv.cpp:4461
virtual AllocResult tryAllocation(const PHV::Allocation &alloc, const std::list< PHV::SuperCluster * > &cluster_groups_input, const std::list< PHV::ContainerGroup * > &container_groups)=0
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:4977
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:4938
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:5546
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:4795
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:4696
ordered_set< bitvec > calc_slicing_schemas(const PHV::SuperCluster *sc, const std::set< PHV::Allocation::AvailableSpot > &spots)
Definition allocate_phv.cpp:4592
std::list< PHV::SuperCluster * > allocDeparserZeroSuperclusters(PHV::Transaction &rst, std::list< PHV::SuperCluster * > &cluster_groups)
Definition allocate_phv.cpp:4633
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
Definition allocate_phv.h:353
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:2798
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:3742
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:4653
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:214
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:5764
int nOpportunitiesAfter(const PHV::Field *f1, const PHV::Field *f2) const
Definition allocate_phv.cpp:5787
int nOpportunities(const PHV::Field *f) const
How many fields, after f is allocated, can be packed with f.
Definition allocate_phv.h:237
Definition live_range_shrinking.h:183
Map field to the parser states in which they are extracted or assigned from checksums.
Definition phv_fields.h:1755
Definition mau_backtracker.h:29
bool disableMetadataInitialization() const
Definition mau_backtracker.h:105
Definition node.h:94
Definition symbitmatrix.h:27
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
ActionSourceTracker collects all source-to-destination for all field slices.
Definition action_source_tracker.h:49
Definition slice_alloc.h:136
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:3845
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:3840
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:3807
static void sort_and_merge_alloc_slices(PhvInfo &phv)
Definition allocate_phv.cpp:4034
std::list< PHV::SuperCluster * > make_superclusters() const
Definition allocate_phv.h:137
static std::list< PHV::SuperCluster * > create_strided_clusters(const CollectStridedHeaders &strided_headers, const std::list< PHV::SuperCluster * > &cluster_groups)
Definition allocate_phv.cpp:3935
static bool update_refs(AllocSlice &slc, const PhvInfo &p, const FieldDefUse::LocPairSet &refs, FieldUse fuse)
Definition allocate_phv.cpp:3870
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
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:307
Definition table_phv_constraints.h:97
Definition field_defuse.h:77
std::pair< HalfOpenRange< Unit, Order >, HalfOpenRange< Unit, Order > > operator-(HalfOpenRange< Unit, Order > left, HalfOpenRange< Unit, Order > right)
Definition lib/bitrange.h:716
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:344
ordered_map< PHV::FieldSlice, int > slice_alignment
a slice_alignment maps field slice to start bit location in a container.
Definition allocate_phv.h:346
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:348
Definition allocate_phv.h:627
Definition allocate_phv.h:259
cstring MetricName
type of the name of a metric.
Definition allocate_phv.h:266
std::function< bool(const AllocScore &left, const AllocScore &right)> IsBetterFunc
IsBetterFunc returns true if left is better than right.
Definition allocate_phv.h:263
static const std::vector< MetricName > g_by_kind_metrics
container-kind-specific scores.
Definition allocate_phv.h:786
static const std::vector< MetricName > g_general_metrics
general metrics
Definition allocate_phv.h:780
Definition allocate_phv.h:673
Collects header stacks that require strided allocation (in a parser loop).
Definition collect_strided_headers.h:28