26#ifndef BF_P4C_MAU_TABLE_PLACEMENT_H_
27#define BF_P4C_MAU_TABLE_PLACEMENT_H_
31#include "backends/tofino/bf-p4c/backend.h"
32#include "backends/tofino/bf-p4c/mau/dynamic_dep_metrics.h"
33#include "backends/tofino/bf-p4c/mau/mau_visitor.h"
34#include "backends/tofino/bf-p4c/mau/resource.h"
35#include "backends/tofino/bf-p4c/mau/resource_estimate.h"
36#include "backends/tofino/bf-p4c/mau/table_flow_graph.h"
37#include "backends/tofino/bf-p4c/mau/table_mutex.h"
38#include "backends/tofino/bf-p4c/mau/table_summary.h"
39#include "lib/ordered_set.h"
73 const IR::MAU::Table *table;
88 static int placement_round;
90 bool can_split(
const IR::MAU::Table *,
const IR::MAU::AttachedMemory *);
92 std::map<const IR::MAU::Table *, struct TableInfo> tblInfo;
93 std::vector<struct TableInfo *> tblByUid;
94 std::map<cstring, struct TableInfo *> tblByName;
95 std::map<const IR::MAU::TableSeq *, struct TableSeqInfo> seqInfo;
96 std::map<const IR::MAU::AttachedMemory *, ordered_set<const IR::MAU::Table *>> attached_to;
97 std::set<const IR::MAU::Table *> not_eligible;
98 int uid(
const IR::MAU::Table *t) {
return tblInfo.at(t).uid; }
99 int uid(
cstring t) {
return tblByName.at(t)->uid; }
100 int uid(
const IR::MAU::TableSeq *t) {
101 if (seqInfo.count(t) == 0)
return -1;
102 return seqInfo.at(t).uid;
104 const IR::MAU::Table *getTblByName(
cstring t) {
105 if (
auto *ti = get(tblByName, t)) {
108 LOG5(
"No tbl info found for table : " << t);
118 bool limit_tmp_creation;
138 DOWNWARD_DOM_FRONTIER,
146 bool backtrack(trigger &)
override;
156 std::map<cstring, std::map<cstring, RejectReason>> rejected_placements;
157 void reject_placement(
const Placed *of, choice_t reason,
const Placed *better);
160 std::array<bool, 3> table_in_gress = {{
false,
false,
false}};
162 bool ignoreContainerConflicts =
false;
163 bool limit_tmp_creation =
false;
164 std::array<const IR::MAU::Table *, 2> starter_pistol = {{
nullptr,
nullptr}};
165 bool alloc_done =
false;
167 profile_t init_apply(
const IR::Node *root)
override;
168 void end_apply()
override { placement_round++; };
170 bool try_pick_layout(
const gress_t &gress, std::vector<Placed *> tables_to_allocate,
171 std::vector<Placed *> tables_placed);
172 bool try_alloc_adb(
const gress_t &gress, std::vector<Placed *> tables_to_allocate,
173 std::vector<Placed *> tables_placed);
174 bool try_alloc_imem(
const gress_t &gress, std::vector<Placed *> tables_to_allocate,
175 std::vector<Placed *> tables_placed);
177 bool try_alloc_ixbar(Placed *next, std::vector<Placed *> allocated_layout);
178 bool try_alloc_format(Placed *next,
bool gw_linked);
179 bool try_alloc_mem(Placed *next, std::vector<Placed *> whole_stage);
180 void setup_detached_gateway(IR::MAU::Table *tbl,
const Placed *placed);
181 void filter_layout_options(Placed *pl);
182 bool disable_split_layout(
const IR::MAU::Table *tbl);
184 bool shrink_attached_tbl(Placed *next,
bool first_time,
bool &done_shrink);
185 bool shrink_estimate(Placed *next,
int &srams_left,
int &tcams_left,
int min_entries);
186 bool shrink_preferred_lo(Placed *next);
187 TableSummary::PlacementResult try_alloc_all(Placed *next, std::vector<Placed *> whole_stage,
188 const char *what,
bool no_memory =
false);
196 friend std::ostream &operator<<(std::ostream &out, choice_t choice);
201 std::multimap<cstring, const Placed *> table_placed;
202 std::multimap<cstring, const Placed *>::const_iterator find_placed(
cstring name)
const;
203 void find_dependency_stages(
204 const IR::MAU::Table *tbl,
207 template <
class... Args>
208 void error(Args... args) {
210 auto msg = ctxt.errorReporter().format_message(args...);
211 LOG5(
" defer error: " << msg);
212 summary.addPlacementError(msg);
214 int errorCount()
const {
return P4::errorCount() + summary.placementErrorCount(); }
240 std::map<cstring, save_placement_t> saved_placements;
241 int backtrack_count = 0;
242 int MaxBacktracksPerPipe = 32;
243 bool resource_mode =
false;
244 std::map<cstring, std::set<int>> bt_attempts;
247 std::optional<BacktrackPlacement *> find_previous_placement(
const Placed *best,
int offset,
248 bool local_bt,
int process_stage);
249 std::optional<BacktrackPlacement *> find_backtrack_point(
const Placed *,
int,
bool);
250 bool is_better(
const Placed *,
const Placed *, TablePlacement::choice_t &);
251 int get_control_anti_split_adj_score(
const Placed *)
const;
256 bool preorder(
const IR::BFN::Pipe *)
override;
260 bool are_metadata_deps_satisfied(
const Placed *placed,
const IR::MAU::Table *t)
const;
262 bool can_place_with_partly_placed(
const IR::MAU::Table *tbl,
265 bool gateway_thread_can_start(
const IR::MAU::Table *,
const Placed *placed);
266 IR::MAU::Table *create_starter_table(gress_t gress);
268 template <
class... Args>
269 void error(Args... args) {
272 int errorCount()
const {
return self.errorCount(); }
273 std::pair<bool, const Placed *> alt_table_placement(
const IR::BFN::Pipe *pipe);
274 const Placed *default_table_placement(
const IR::BFN::Pipe *pipe);
287 IR::Node *preorder(IR::MAU::TableSeq *)
override;
288 IR::Node *postorder(IR::MAU::TableSeq *)
override;
289 IR::Node *preorder(IR::MAU::Table *)
override;
290 IR::Node *postorder(IR::MAU::Table *)
override;
291 IR::Node *preorder(IR::MAU::BackendAttached *)
override;
292 IR::Node *preorder(IR::BFN::Pipe *pipe)
override;
293 IR::Node *postorder(IR::BFN::Pipe *pipe)
override;
295 IR::MAU::Table::Layout &gw_layout);
297 int stage_table = -1, IR::MAU::Table **last =
nullptr);
300 int stage_table = -1);
301 void table_set_resources(IR::MAU::Table *tbl,
const TableResourceAlloc *res,
const int entries);
302 template <
class... Args>
303 void error(Args... args) {
306 int errorCount()
const {
return self.errorCount(); }
309std::ostream &operator<<(std::ostream &out, TablePlacement::choice_t choice);
314 using TableFieldSlices = std::map<IR::MAU::Table *, PHV::FieldSlice>;
316 struct AlwaysRunKey {
320 bool operator<(
const AlwaysRunKey &ark)
const {
321 if (stage != ark.stage)
return stage < ark.stage;
322 return gress < ark.gress;
325 AlwaysRunKey(
int s, gress_t g) : stage(s), gress(g) {}
328 std::map<AlwaysRunKey, ordered_set<const IR::MAU::Table *>> ar_tables_per_stage;
329 std::map<AlwaysRunKey, const IR::MAU::Table *> merge_per_stage;
330 std::map<AlwaysRunKey, std::set<int>> merged_ar_minStages;
336 typedef std::map<const IR::MAU::Table *, int> premerge_table_stg_t;
340 bool mergedARAwitNewStage;
343 auto rv = PassManager::init_apply(node);
344 ar_tables_per_stage.clear();
345 merge_per_stage.clear();
346 merged_ar_minStages.clear();
347 written_fldSlice.clear();
348 read_fldSlice.clear();
349 premergeLRstart.clear();
350 premergeLRend.clear();
351 mergedARAwitNewStage =
false;
354 LOG7(
"MIN STAGE DEPARSER stage: " << self.phv.getDeparserStage());
355 LOG7(PhvInfo::reportMinStages());
356 LOG7(
"DG DEPARSER stage: " << (self.deps.max_min_stage + 1));
364 bool preorder(
const IR::MAU::Table *)
override;
365 bool preorder(
const IR::MAU::Primitive *)
override;
366 void end_apply()
override;
374 const IR::MAU::Table *preorder(IR::MAU::Table *)
override;
375 void end_apply()
override;
391 std::map<PHV::AllocSlice *, std::pair<bool, bool>> sliceLRmodifies;
393 bool preorder(
const IR::MAU::Table *)
override;
394 bool preorder(
const IR::Expression *)
override;
395 void end_apply()
override;
401 const IR::MAU::Table *ar_replacement(
int st, gress_t gress) {
402 AlwaysRunKey ark(st, gress);
403 if (ar_tables_per_stage.count(ark) == 0)
404 BUG(
"MergeAlwaysRunActions cannot find stage of an always run table");
405 auto set = ar_tables_per_stage.at(ark);
406 return *(set.begin());
409 template <
class... Args>
410 void error(Args... args) {
413 int errorCount()
const {
return self.errorCount(); }
417 addPasses({
new Scan(*
this),
new Update(*
this),
new FindDependencyGraph(self.phv, self.deps),
418 new UpdateAffectedTableMinStage(*
this)});
Definition bf-p4c-options.h:28
Definition table_dependency_graph.h:938
Definition table_dependency_graph.h:972
Definition table_placement.cpp:1525
Definition table_placement.cpp:4032
Definition table_placement.cpp:855
Definition table_placement.cpp:1427
Definition table_placement.cpp:1056
Definition table_placement.cpp:1288
Definition table_placement.h:217
Definition table_placement.cpp:953
Definition dynamic_dep_metrics.h:28
Definition table_dependency_graph.h:1033
Definition payload_gateway.h:31
Definition table_layout.h:83
Definition mau_backtracker.h:29
Definition mau_visitor.h:29
Definition table_placement.h:311
static BaseCompileContext & get()
Definition compile_context.cpp:61
Definition ir/pass_manager.h:40
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition phv_fields.h:1095
Definition mau/table_mutex.h:160
Definition attached_info.h:235
Definition table_placement.h:51
static bool can_duplicate(const IR::MAU::AttachedMemory *)
Definition table_placement.cpp:2378
const Placed * add_starter_pistols(const Placed *done, const Placed **best, const StageUseEstimate ¤t)
Definition table_placement.cpp:3076
bool can_split(const IR::MAU::Table *, const IR::MAU::AttachedMemory *)
Check if an indirect attached table can be split acorss stages.
Definition table_placement.cpp:2388
Definition table_placement.h:150
Definition table_placement.h:71
Definition table_placement.h:79
Definition table_summary.h:158
Definition mau/table_mutex.h:110
Definition tofino_write_context.h:24
bool pick_layout_option(Placed *next, std::vector< Placed * > allocated_layout)
Definition table_placement.cpp:1736
Definition table_placement.cpp:1964
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51
unsigned errorCount()
Definition lib/error.h:35
Definition table_placement.cpp:474
Definition table_dependency_graph.h:52
Definition resource_estimate.h:29
Definition table_placement.h:117
Definition table_placement.cpp:553
Definition table_summary.h:168