19#ifndef BF_P4C_PHV_ALLOCATE_PHV_H_
20#define BF_P4C_PHV_ALLOCATE_PHV_H_
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"
80 const CollectParserInfo &parser_info;
106 clustering(clustering),
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),
120 tablePackOpt(tablePackOpt) {}
122 const SymBitMatrix &mutex()
const {
return phv.field_mutex(); }
130 return clustering.no_pack(fs1.
field(), fs2.
field()) || actions.hasPackConflict(fs1, fs2);
134 bool is_referenced(
const PHV::Field *f)
const {
return !f->
padding && uses.is_referenced(f); };
138 return clustering.cluster_groups();
176 const std::list<PHV::SuperCluster *> &cluster_groups);
181 const PhvUse &uses,
const std::list<PHV::SuperCluster *> &cluster_groups_input);
185 const ClotInfo &clot, std::list<PHV::SuperCluster *> clusters);
191 const std::list<PHV::SuperCluster *> &cluster_groups);
201namespace Diagnostics {
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;
224 std::vector<const PHV::Field *> fieldsInOrder(
225 const std::list<PHV::SuperCluster *> &sorted_clusters)
const;
227 bool isExtractedOrUninitialized(
const PHV::Field *f)
const;
260 using ContainerAllocStatus = PHV::Allocation::ContainerAllocStatus;
263 using IsBetterFunc = std::function<bool(
const AllocScore &left,
const AllocScore &right)>;
294 bitvec calcContainerAllocVec(
const ordered_set<PHV::AllocSlice> &slices);
296 ContainerAllocStatus calcContainerStatus(
const PHV::Container &container,
297 const ordered_set<PHV::AllocSlice> &slices);
299 void calcParserExtractorBalanceScore(
const PHV::Transaction &alloc,
const PhvInfo &phv,
300 const MapFieldToParserStates &field_to_parser_states,
301 const CalcParserCriticalPath &parser_critical_path);
304std::ostream &operator<<(std::ostream &s,
const AllocScore &score);
315 bool stop_at_first_i =
false;
322 : name_i(name), stop_at_first_i(stop_at_first), is_better_i(is_better) {}
328 const int bitmasks = 0)
const;
331 return is_better_i(left, right);
334 bool stop_at_first()
const {
return stop_at_first_i; }
338 cloned.packing_opportunities_i = packing;
353class CoreAllocation {
355 bool control_flow_overlay;
356 bool physical_liverange_overlay;
357 bool metadata_overlay;
365 const bool disableMetadataInit;
367 bool singleGressParserGroups =
false;
369 bool prioritizeARAinits =
false;
371 std::optional<PHV::Transaction> alloc_super_cluster_with_alignment(
374 const std::list<const PHV::SuperCluster::SliceList *> &sorted_slice_lists,
378 std::vector<AllocAlignment> build_alignments(
int max_n,
384 std::vector<AllocAlignment> build_slicelist_alignment(
386 const PHV::SuperCluster::SliceList *slice_list)
const;
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,
393 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes,
396 PHV::Allocation::LiveRangeShrinkingMap &initActions,
bool &new_overlay_container,
402 std::optional<std::vector<PHV::AllocSlice>> prepare_candidate_slices(
404 const PHV::Allocation::ConditionalConstraint &start_positions)
const;
409 std::optional<PHV::Allocation::LiveRangeShrinkingMap> &initNodes,
412 PHV::Allocation::LiveRangeShrinkingMap &initActions,
414 const PHV::Allocation::MutuallyLiveSlices &alloced_slices,
415 PHV::Allocation::MutuallyLiveSlices &actual_cntr_state)
const;
417 bool try_dark_overlay(std::vector<PHV::AllocSlice> &dark_slices,
419 std::vector<PHV::AllocSlice> &candidate_slices,
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,
429 std::optional<PHV::Allocation::ConditionalConstraints> &action_constraints,
430 int &num_bitmasks)
const;
433 PHV::SuperCluster::SliceList *hi_slice,
442 bool find_previous_allocation(
445 const PHV::Allocation::ConditionalConstraint &start_positions,
451 : utils_i(utils), disableMetadataInit(disable_metainit) {}
485 std::vector<PHV::AllocSlice> &candidate_slices)
const;
493 void set_single_gress_parser_group() { singleGressParserGroups =
true; }
494 bool get_single_gress_parser_group() {
return singleGressParserGroups; }
497 void set_prioritize_ARA_inits() { prioritizeARAinits =
true; }
498 bool get_prioririze_ARA_inits() {
return prioritizeARAinits; }
526 std::optional<const PHV::SuperCluster::SliceList *> find_first_unallocated_slicelist(
527 const PHV::Allocation &alloc,
const std::list<PHV::ContainerGroup *> &container_groups,
539 bool checkDarkOverlay(
const std::vector<PHV::AllocSlice> &candidate_slices,
585 const PHV::Allocation::ConditionalConstraint &start_positions,
592 const PHV::SuperCluster &super_cluster,
const PHV::SuperCluster::SliceList &slice_list,
598 PHV::DarkInitMap &slices,
601 const PHV::Allocation::MutuallyLiveSlices &container_state)
const;
603 bool hasCrossingLiveranges(std::vector<PHV::AllocSlice> candidate_slices,
616 const std::vector<PHV::AllocSlice> &candidates,
620enum class AllocResultCode {
628 AllocResultCode status;
630 std::list<const PHV::SuperCluster *> remaining_clusters;
634 std::list<const PHV::SuperCluster *> &&c)
635 : status(r), transaction(t), remaining_clusters(c) {}
651class AllocationStrategy {
659 : name(name), utils_i(utils), core_alloc_i(core) {}
669 const std::list<PHV::SuperCluster *> &cluster_groups_input,
670 const std::list<PHV::ContainerGroup *> &container_groups) = 0;
679 int max_failure_retry;
685 int max_sl_alignment;
687 std::optional<std::unordered_set<Device::Device_t>> unsupported_devices;
690 bool pre_slicing_validation;
692 bool enable_ara_in_overlays;
695class BruteForceAllocationStrategy :
public AllocationStrategy {
699 std::optional<const PHV::SuperCluster::SliceList *> unallocatable_list_i;
709 const std::list<PHV::SuperCluster *> &cluster_groups_input,
710 const std::list<PHV::ContainerGroup *> &container_groups)
override;
712 std::optional<const PHV::SuperCluster::SliceList *> get_unallocatable_list()
const {
713 return unallocatable_list_i;
716 int getPipeId()
const {
return pipe_id_i; }
720 const PHV::Allocation &alloc,
const std::list<PHV::SuperCluster *> &cluster_groups_input,
721 const std::list<PHV::ContainerGroup *> &container_groups,
724 std::list<PHV::SuperCluster *> crush_clusters(
725 const std::list<PHV::SuperCluster *> &cluster_groups);
729 const std::list<PHV::SuperCluster *> &cluster_groups,
730 const std::list<PHV::ContainerGroup *> &container_groups,
731 std::list<const PHV::SuperCluster *> &unsliceable);
734 void sortClusters(std::list<PHV::SuperCluster *> &cluster_groups);
736 bool tryAllocSlicing(
const std::list<PHV::SuperCluster *> &slicing,
737 const std::list<PHV::ContainerGroup *> &container_groups,
740 bool tryAllocStride(
const std::list<PHV::SuperCluster *> &stride,
741 const std::list<PHV::ContainerGroup *> &container_groups,
744 bool tryAllocStrideWithLeaderAllocated(
const std::list<PHV::SuperCluster *> &stride,
748 bool tryAllocSlicingStrided(
unsigned num_strides,
const std::list<PHV::SuperCluster *> &slicing,
749 const std::list<PHV::ContainerGroup *> &container_groups,
754 const std::list<PHV::ContainerGroup *> &container_groups,
const ScoreContext &score_ctx,
755 std::stringstream &alloc_history);
757 std::list<PHV::SuperCluster *> allocLoop(
759 const std::list<PHV::ContainerGroup *> &container_groups,
const ScoreContext &score_ctx);
773 const std::set<PHV::Allocation::AvailableSpot> &spots);
786 const std::list<PHV::ContainerGroup *> &container_groups);
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;
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;
814class AllocatePHV :
public Visitor {
820 const IR::BFN::Pipe *root =
nullptr;
823 std::list<const PHV::SuperCluster *> &unallocated_i;
827 const IR::Node *apply_visitor(
const IR::Node *root,
const char *name = 0)
override;
831 static void formatAndThrowUnsat(
const std::list<const PHV::SuperCluster *> &unallocated);
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;
848 std::list<const PHV::SuperCluster *> &unallocated)
854 unallocated_i(unallocated) {}
859 static bool diagnoseFailures(
const std::list<const PHV::SuperCluster *> &unallocated,
865 const std::list<const PHV::SuperCluster *> &unallocated);
874class IncrementalPHVAllocation :
public Visitor {
884 const IR::Node *apply_visitor(
const IR::Node *root,
const char *name = 0)
override;
891 core_alloc_i(utils,
true),
893 settings_i(settings),
894 temp_vars_i(temp_vars) {}
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 symbitmatrix.h:27
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_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_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