P4C
The P4 Compiler
Loading...
Searching...
No Matches
tofino/memories.h
1
19#ifndef BF_P4C_MAU_TOFINO_MEMORIES_H_
20#define BF_P4C_MAU_TOFINO_MEMORIES_H_
21
22#include <algorithm>
23
24#include "backends/tofino/bf-p4c/mau/action_format.h"
25#include "backends/tofino/bf-p4c/mau/attached_entries.h"
26#include "backends/tofino/bf-p4c/mau/instruction_memory.h"
27#include "backends/tofino/bf-p4c/mau/memories.h"
28#include "backends/tofino/bf-p4c/mau/table_format.h"
29#include "backends/tofino/bf-p4c/mau/tofino/input_xbar.h"
30#include "ir/ir.h"
31#include "lib/safe_vector.h"
32
33namespace Tofino {
34// Despite the namespace name, this code is shared for Tofino and JBay (Tofino 1/2)
35using namespace P4;
36
37struct Memories : public ::Memories {
38 /* track memory allocations within a single stage */
39 static constexpr int SRAM_ROWS = 8;
40 static constexpr int SRAM_COLUMNS = 10;
41 static constexpr int STASH_UNITS = 2;
42 static constexpr int LOGICAL_TABLES = 16;
43 static constexpr int LEFT_SIDE_COLUMNS = 4;
44 static constexpr int RIGHT_SIDE_COLUMNS = SRAM_COLUMNS - LEFT_SIDE_COLUMNS;
45 static constexpr int LEFT_SIDE_RAMS = LEFT_SIDE_COLUMNS * SRAM_ROWS;
46 static constexpr int RIGHT_SIDE_RAMS = RIGHT_SIDE_COLUMNS * SRAM_ROWS;
47 static constexpr int MAPRAM_COLUMNS = 6;
48 static constexpr int MAPRAM_MASK = (1U << MAPRAM_COLUMNS) - 1;
49 static constexpr int SRAM_DEPTH = 1024;
50 static constexpr int TCAM_ROWS = 12;
51 static constexpr int TCAM_COLUMNS = 2;
52 static constexpr int TCAM_DEPTH = 512;
53 static constexpr int TABLES_MAX = 16;
54 static constexpr int TERNARY_TABLES_MAX = 8;
55 static constexpr int ACTION_TABLES_MAX = 16;
56 static constexpr int GATEWAYS_PER_ROW = 2;
57 static constexpr int BUS_COUNT = 2; // search/result busses per row
58 static constexpr int PAYLOAD_COUNT = 2; // payload per row
59 static constexpr int STATS_ALUS = 4;
60 static constexpr int METER_ALUS = 4;
61 static constexpr int MAX_DATA_SWBOX_ROWS = 5;
62 static constexpr int COLOR_MAPRAM_PER_ROW = 4;
63 static constexpr int IMEM_ADDRESS_BITS = 6;
64 static constexpr int IMEM_LOOKUP_BITS = 3;
65 static constexpr int NUM_IDLETIME_BUS = 10;
66 static constexpr int MAX_PARTITION_RAMS_PER_ROW = 5;
67 static constexpr int MATCH_CENTRAL_ROW = 4;
68 static constexpr int MAX_STATS_ROW_PER_ALU = 3;
69 static constexpr int MAX_STATS_RAM_PER_ALU = MAPRAM_COLUMNS * MAX_STATS_ROW_PER_ALU;
70 static constexpr int MAX_METERS_ROW_PER_ALU = 4;
71 static constexpr int MAX_METERS_RAM_PER_ALU = MAPRAM_COLUMNS * MAX_METERS_ROW_PER_ALU;
72 static constexpr int MAX_METERS_COLOR_MAPRAM_PER_ALU = 5; // round up of 18 / 4
73
74 static constexpr int LOGICAL_ROW_MISSING_OFLOW = 8;
75
76 using Use = ::Memories::Use;
77
78 private:
108 struct search_bus_info {
109 cstring name;
110 // word number in exact match format
111 int width_section = 0; // Each search bus for a table has a particular width
112 int hash_group = 0; // Each hash function requires a different hash function
113 bool init = false;
114
115 search_bus_info() {}
116 search_bus_info(cstring n, int ws, int hg)
117 : name(n), width_section(ws), hash_group(hg), init(true) {}
118
119 bool operator==(const search_bus_info &sbi) {
120 return name == sbi.name && width_section == sbi.width_section &&
121 hash_group == sbi.hash_group;
122 }
123
124 bool operator!=(const search_bus_info &sbi) { return !operator==(sbi); }
125
126 bool free() { return !init; }
127 };
128 friend std::ostream &operator<<(std::ostream &, const search_bus_info &);
129
130 struct result_bus_info {
131 cstring name;
132 int width_section = 0; // Each width section may require a different width section
133 int logical_table = 0; // For ATCAM tables, each logical table requires a separate
134 // result bus
135 bool init = false;
136
137 result_bus_info() {}
138 result_bus_info(cstring n, int ws, int lt)
139 : name(n), width_section(ws), logical_table(lt), init(true) {}
140
141 bool operator==(const result_bus_info &mbi) {
142 return name == mbi.name && width_section == mbi.width_section &&
143 logical_table == mbi.logical_table;
144 }
145
146 bool operator!=(const result_bus_info &mbi) { return !operator==(mbi); }
147 bool free() { return !init; }
148 };
149 friend std::ostream &operator<<(std::ostream &, const result_bus_info &);
150
152 unsigned sram_inuse[SRAM_ROWS] = {0};
156 // FIXME (Refactoring): Remove sram_print_result_bus / sram_print_search_bus
157 // and move the info inside and move into main result_bus_info /
158 // search_bus_info class
163 // int tcam_group_use[TCAM_ROWS][TCAM_COLUMNS] = {{-1}};
164 int tcam_midbyte_use[TCAM_ROWS / 2][TCAM_COLUMNS] = {{-1}};
170 BFN::Alloc1D<std::pair<cstring, int>, SRAM_ROWS - 1> vert_overflow_bus;
172 unsigned mapram_inuse[SRAM_ROWS] = {0};
174 bool gw_bytes_reserved[SRAM_ROWS][BUS_COUNT] = {{false}};
177
178 struct mem_info {
179 int logical_tables = 0;
180 int match_tables = 0;
181 int result_bus_min = 0;
182 int atcam_tables = 0;
183 int match_RAMs = 0;
184 int tind_tables = 0;
185 int tind_RAMs = 0;
186 int action_tables = 0;
187 int action_bus_min = 0;
188 int action_RAMs = 0;
189 int ternary_tables = 0;
190 int ternary_TCAMs = 0;
191 int stats_tables = 0;
192 int stats_RAMs = 0;
193 int meter_tables = 0;
194 int meter_RAMs = 0;
195 int stateful_tables = 0;
196 int stateful_RAMs = 0;
197 int selector_tables = 0;
198 int selector_RAMs = 0;
199 int no_match_tables = 0;
200 int independent_gw_tables = 0;
201 int idletime_RAMs = 0;
202
203 void clear() { memset(this, 0, sizeof(mem_info)); }
204
205 int total_RAMs() const {
206 return match_RAMs + action_RAMs + stats_RAMs + meter_RAMs + selector_RAMs + tind_RAMs;
207 }
208
209 int left_side_RAMs() const { return tind_RAMs; }
210 int right_side_RAMs() const {
211 return meter_RAMs + stats_RAMs + selector_RAMs + stateful_RAMs;
212 }
213 int non_SRAM_RAMs() const { return left_side_RAMs() + right_side_RAMs() + action_RAMs; }
214 int columns(int RAMs) const { return (RAMs + SRAM_COLUMNS - 1) / SRAM_COLUMNS; }
215 bool constraint_check(int lt_allowed, cstring &failure_reason) const;
216 };
217
218 friend class SetupAttachedTables;
219
220 // The resource information required for an individual IR::MAU::Table object in a single
221 // stage. Could coordinate to multiple logical tables, (i.e. dleft or atcam tables)
222 struct table_alloc {
223 const IR::MAU::Table *table;
224 const ::IXBar::Use *match_ixbar;
225 const TableFormat::Use *table_format;
226 const InstructionMemory::Use *instr_mem;
227 const ActionData::Format::Use *action_format;
228 std::map<UniqueId, Memories::Use> *memuse;
229 const LayoutOption *layout_option;
230 ActionData::FormatType_t format_type;
231 int provided_entries;
232 attached_entries_t attached_entries;
233 // Entries per match table allocation_unit (logical table) of the table. This is
234 // used to determine the attached table requirements if direct
235 safe_vector<int> calc_entries_per_uid;
236 int total_entries() const {
237 return std::accumulate(calc_entries_per_uid.begin(), calc_entries_per_uid.end(), 0);
238 }
239 int attached_gw_bytes = 0;
240 int stage_table = -1;
241 // Linked gw/match table that uses the same result bus
242 table_alloc *table_link = nullptr;
243 // FIXME -- hack to avoid problems in payload calculation when the only reason we
244 // have a payload is to set the match address
245 bool payload_match_addr_only = false;
246 table_alloc(const IR::MAU::Table *t, const ::IXBar::Use *mi, const TableFormat::Use *tf,
248 std::map<UniqueId, Memories::Use> *mu, const LayoutOption *lo,
249 ActionData::FormatType_t ft, const int e, const int st,
250 attached_entries_t attached_entries)
251 : table(t),
252 match_ixbar(mi),
253 table_format(tf),
254 instr_mem(im),
255 action_format(af),
256 memuse(mu),
257 layout_option(lo),
258 format_type(ft),
259 provided_entries(e),
260 attached_entries(attached_entries),
261 attached_gw_bytes(0),
262 stage_table(st),
263 table_link(nullptr) {}
264 void link_table(table_alloc *ta) { table_link = ta; }
265 int analysis_priority() const;
266
267 UniqueId build_unique_id(
268 const IR::MAU::AttachedMemory *at = nullptr, bool is_gw = false, int logical_table = -1,
269 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP) const;
270
271 safe_vector<UniqueId> allocation_units(
272 const IR::MAU::AttachedMemory *at = nullptr, bool is_gw = false,
273 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP) const;
274
275 safe_vector<UniqueId> unattached_units(
276 const IR::MAU::AttachedMemory *at = nullptr,
277 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP) const;
278
279 safe_vector<UniqueId> accounted_units(
280 const IR::MAU::AttachedMemory *at = nullptr,
281 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP) const;
282 };
283 int logical_tables_allowed = LOGICAL_TABLES;
284
285 friend std::ostream &operator<<(std::ostream &out, const Memories::table_alloc &ta);
286
288 struct SRAM_group : public IHasDbPrint {
289 table_alloc *ta; // Link to the table alloc to be generated
290 int depth = 0; // Individual number of RAMs required for a group
291 int width = 0; // How wide an individual group is, only needed for exact match
292 int placed = 0; // How many have been allocated so far
293 int number = 0; // Used to keep track of wide action tables and way numbers in exact match
294 int hash_group = -1; // Which hash group the exact match way is using
295 int logical_table = -1; // For ATCAM tables, which logical table this partition is based
296 int vpn_increment = 1;
297 int vpn_offset = 0;
298 int vpn_spare = 0;
299 bool direct = false; // Whether the attached table is directly or indirectly addressed
300 const IR::MAU::AttachedMemory *attached = nullptr;
301 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP;
302 int recent_home_row = -1; // For swbox users, most recent row to oflow to
303 enum type_t {
304 EXACT,
305 ACTION,
306 STATS,
307 METER,
308 REGISTER,
309 SELECTOR,
310 TIND,
311 IDLETIME,
312 ATCAM,
313 GROUP_TYPES
314 } type;
315
316 // Color Mapram Requirements, necessary for METER groups
318 int needed = 0;
319 int placed = 0;
320 // Necessary for stats addressed color maprams
321 int home_row = -1;
322 IR::MAU::ColorMapramAddress cma = IR::MAU::ColorMapramAddress::NOT_SET;
323 bool all_placed() const {
324 BUG_CHECK(placed <= needed, "Placed more color map RAMs than actually needed");
325 return needed == placed;
326 }
327 int left_to_place() const {
328 BUG_CHECK(placed <= needed, "Placed more color map RAMs than actually needed");
329 return needed - placed;
330 }
331
332 bool require_stats() const { return cma == IR::MAU::ColorMapramAddress::STATS; }
333 };
334
335 // Linkage between selectors and the corresponding action table in order to prevent
336 // a collision on the selector overflow
338 SRAM_group *sel_group = nullptr;
339 ordered_set<SRAM_group *> action_groups;
340 bool sel_linked() { return sel_group != nullptr; }
341 bool act_linked() { return !action_groups.empty(); }
342 bool sel_all_placed() const { return sel_group->all_placed(); }
343 bool action_all_placed() const {
344 if (action_groups.empty()) BUG("No action corresponding with this selector");
345 for (auto *action_group : action_groups) {
346 if (!action_group->all_placed()) return false;
347 }
348 return true;
349 }
350 bool sel_any_placed() const { return sel_group->any_placed(); }
351 bool action_any_placed() const {
352 if (action_groups.empty()) BUG("No action corresponding with this selector");
353 for (auto *action_group : action_groups) {
354 if (action_group->any_placed()) return true;
355 }
356 return false;
357 }
358
359 bool all_placed() const { return sel_all_placed() && action_all_placed(); }
360
361 bool is_act_corr_group(SRAM_group *corr) {
362 return action_groups.find(corr) != action_groups.end();
363 }
364 bool is_sel_corr_group(SRAM_group *corr) { return corr == sel_group; }
365 bool one_action_left() const {
366 int total_unplaced_groups = 0;
367 for (auto *action_group : action_groups)
368 if (action_group->left_to_place() > 0) total_unplaced_groups++;
369 return total_unplaced_groups == 1;
370 }
371 int action_left_to_place() const {
372 int left_to_place = 0;
373 for (auto *action_group : action_groups)
374 left_to_place += action_group->left_to_place();
375 return left_to_place;
376 }
377 SRAM_group *action_group_left() {
378 if (!one_action_left())
379 BUG("Trying to call action_group_left with more than one action left");
380 for (auto *action_group : action_groups)
381 if (action_group->left_to_place() > 0) return action_group;
382 return nullptr;
383 }
384 };
385 selector_info sel;
387 bool requires_ab = false; // LPF and WRED meters require synth and action bus
388
389 SRAM_group(table_alloc *t, int d, int w, int n, type_t ty)
390 : ta(t), depth(d), width(w), number(n), type(ty) {}
391 SRAM_group(table_alloc *t, int d, int n, type_t ty)
392 : ta(t), depth(d), number(n), type(ty) {}
393 SRAM_group(table_alloc *t, int d, int w, int n, int h, type_t ty)
394 : ta(t), depth(d), width(w), number(n), hash_group(h), type(ty) {}
395 void dbprint(std::ostream &out) const;
396 search_bus_info build_search_bus(int width_sect) const {
397 return search_bus_info(ta->table->name, width_sect, hash_group);
398 }
399
400 result_bus_info build_result_bus(int width_sect) const;
401
402 int left_to_place() const {
403 BUG_CHECK(placed <= depth, "Placed more than needed");
404 return depth - placed;
405 }
406 bool all_placed() const {
407 BUG_CHECK(placed <= depth, "Placed more than needed");
408 return (depth == placed);
409 }
410 bool any_placed() { return (placed != 0); }
411 bool needs_ab() { return requires_ab && !all_placed(); }
412 bool is_synth_type() const {
413 return type == STATS || type == METER || type == REGISTER || type == SELECTOR;
414 }
415 bool sel_act_placed(SRAM_group *corr) {
416 if (type == ACTION && sel.sel_linked() && sel.is_sel_corr_group(corr) &&
417 corr->sel.action_all_placed())
418 return true;
419 else
420 return false;
421 }
422 int RAMs_required() const {
423 if (type == SELECTOR) {
424 int action_depth = 0;
425 for (auto *action_group : sel.action_groups) action_depth += action_group->depth;
426 return depth + action_depth;
427 } else {
428 return depth;
429 }
430 }
431 int total_left_to_place() const {
432 if (type == SELECTOR) {
433 int action_depth = 0;
434 for (auto *action_group : sel.action_groups)
435 action_depth += action_group->left_to_place();
436 return left_to_place() + action_depth;
437 } else {
438 return left_to_place();
439 }
440 }
441
442 int maprams_left_to_place() const {
443 if (is_synth_type()) return left_to_place() + cm.left_to_place();
444 return 0;
445 }
446
447 // cstring get_name() const;
448 UniqueId build_unique_id() const;
449 bool same_wide_action(const SRAM_group &a);
450 int calculate_next_vpn() const { return placed * vpn_increment + vpn_offset; }
451 };
452
453 struct match_selection {
454 safe_vector<int> rows;
455 safe_vector<int> cols;
456 std::map<int, int> widths;
457 std::map<int, int> search_buses;
458 std::map<int, int> result_buses;
459 unsigned column_mask = 0;
460 };
461
462 enum switchbox_t { ACTION = 0, SYNTH, OFLOW, SWBOX_TYPES };
463
464 struct LogicalRowUser {
465 SRAM_group *group = nullptr;
466 switchbox_t bus = SWBOX_TYPES;
467 bitvec RAM_mask;
468 bitvec map_RAM_mask;
469
470 operator bool() const { return group != nullptr; }
471 void clear_masks() {
472 RAM_mask.clear();
473 map_RAM_mask.clear();
474 }
475 void clear() {
476 group = nullptr;
477 bus = SWBOX_TYPES;
478 clear_masks();
479 }
480 bool set() const { return !(RAM_mask.empty() && map_RAM_mask.empty()); }
481
482 bitvec color_map_RAM_mask() const {
483 BUG_CHECK(group->type == SRAM_group::METER,
484 "Cannot get color map RAMs of "
485 " a non-METER");
486 return map_RAM_mask - (RAM_mask >> LEFT_SIDE_COLUMNS);
487 }
488
489 void dbprint(std::ostream &out) const {
490 out << *group << " bus " << bus << " RAM mask: 0x" << RAM_mask << " map RAM mask: 0x"
491 << map_RAM_mask;
492 }
493 LogicalRowUser(SRAM_group *g, switchbox_t b) : group(g), bus(b) {}
494 };
495
497 struct swbox_fill {
498 SRAM_group *group = nullptr;
499 unsigned mask = 0;
500 unsigned mapram_mask = 0;
501 operator bool() const { return group != nullptr; }
502 swbox_fill() {}
503 void clear() {
504 group = nullptr;
505 mask = 0;
506 mapram_mask = 0;
507 }
508 void clear_masks() {
509 mask = 0;
510 mapram_mask = 0;
511 }
512 void dbprint(std::ostream &out) const {
513 out << *group << " RAM mask: 0x" << P4::hex(mask) << " map RAM mask: 0x"
514 << P4::hex(mapram_mask);
515 }
516 };
517
518 // Used for array indices in allocate_all_action
519 enum RAM_side_t { LEFT = 0, RIGHT, RAM_SIDES };
520
522 safe_vector<table_alloc *> exact_tables;
523 safe_vector<SRAM_group *> exact_match_ways;
524 safe_vector<table_alloc *> atcam_tables;
525 safe_vector<SRAM_group *> atcam_partitions;
526 safe_vector<table_alloc *> ternary_tables;
527 safe_vector<table_alloc *> tind_tables;
528 safe_vector<SRAM_group *> tind_groups;
529 safe_vector<table_alloc *> action_tables;
530 safe_vector<table_alloc *> indirect_action_tables;
531 safe_vector<table_alloc *> selector_tables;
532 safe_vector<table_alloc *> stats_tables;
533 safe_vector<table_alloc *> meter_tables;
534 safe_vector<table_alloc *> stateful_tables;
535 ordered_set<SRAM_group *> action_bus_users;
536 ordered_set<SRAM_group *> synth_bus_users;
537 ordered_set<const SRAM_group *> must_place_in_half;
539 safe_vector<table_alloc *> no_match_hit_tables;
540 safe_vector<table_alloc *> no_match_miss_tables;
541 safe_vector<table_alloc *> payload_gws;
543 safe_vector<table_alloc *> no_match_gws;
544 safe_vector<table_alloc *> tind_result_bus_tables;
545 safe_vector<table_alloc *> idletime_tables;
546 safe_vector<SRAM_group *> idletime_groups;
547
548 // Switchbox Related Helper functions
549 int phys_to_log_row(int physical_row, RAM_side_t side) const;
550 int log_to_phys_row(int logical_row, RAM_side_t *side = nullptr) const;
551 void determine_synth_RAMs(int &RAMs_available, int row, const SRAM_group *curr_oflow) const;
552 void determine_action_RAMs(int &RAMs_available, int row, RAM_side_t side,
553 const safe_vector<LogicalRowUser> &lrus) const;
554 bool alu_pathway_available(SRAM_group *synth_table, int row,
555 const SRAM_group *curr_oflow) const;
556 int lowest_row_to_overflow(const SRAM_group *candidate, int row) const;
557 int open_rams_between_rows(int highest_logical_row, int lowest_logical_row, bitvec sides) const;
558 int open_maprams_between_rows(int highest_phys_row, int lowest_phys_row) const;
559 bool overflow_possible(const SRAM_group *candidate, const SRAM_group *curr_oflow, int row,
560 RAM_side_t side) const;
561 bool can_be_placed_in_half(const SRAM_group *candidate, int row, RAM_side_t side,
562 const SRAM_group *synth, int RAMs_avail_on_row) const;
563 bool break_other_overflow(const SRAM_group *candidate, const SRAM_group *curr_oflow, int row,
564 RAM_side_t side) const;
565 bool satisfy_sel_swbox_constraints(const SRAM_group *candidate, const SRAM_group *sel_oflow,
566 SRAM_group *synth) const;
567 void determine_fit_on_logical_row(SRAM_group **fit_on_logical_row, SRAM_group *candidate,
568 int RAMs_avail) const;
569 void determine_max_req(SRAM_group **max_req, SRAM_group *candidate) const;
570 void candidates_for_synth_row(SRAM_group **fit_on_logical_row, SRAM_group **largest_req,
571 int row, const SRAM_group *curr_oflow,
572 const SRAM_group *sel_oflow, int RAMs_avail) const;
573 void candidates_for_action_row(SRAM_group **fit_on_logical_row, SRAM_group **largest_req,
574 int row, RAM_side_t side, const SRAM_group *curr_oflow,
575 const SRAM_group *sel_oflow, int RAMs_avail,
576 SRAM_group *synth) const;
577 void determine_synth_logical_row_users(SRAM_group *fit_on_logical_row, SRAM_group *max_req,
578 SRAM_group *curr_oflow,
579 safe_vector<LogicalRowUser> &lrus, int RAMs_avail) const;
580 bool action_candidate_prefer_sel(SRAM_group *max_req, SRAM_group *synth, SRAM_group *curr_oflow,
581 SRAM_group *sel_oflow,
582 safe_vector<LogicalRowUser> &lrus) const;
583 void determine_action_logical_row_users(SRAM_group *fit_on_logical_row, SRAM_group *max_req,
584 SRAM_group *synth, SRAM_group *curr_oflow,
585 SRAM_group *sel_oflow,
587 int RAMs_avail) const;
588 void determine_RAM_masks(safe_vector<LogicalRowUser> &lrus, int row, RAM_side_t side,
589 int RAMs_available, bool is_synth_type) const;
590 void one_color_map_RAM_mask(LogicalRowUser &lru, bitvec &map_RAM_in_use, bool &stats_bus_used,
591 int row) const;
592 void determine_color_map_RAM_masks(safe_vector<LogicalRowUser> &lrus, int row) const;
593 void determine_logical_row_masks(safe_vector<LogicalRowUser> &lrus, int row, RAM_side_t side,
594 int RAMs_avaialble, bool is_synth_type) const;
595 void find_swbox_candidates(safe_vector<LogicalRowUser> &lrus, int row, RAM_side_t side,
596 SRAM_group *curr_oflow, SRAM_group *sel_oflow);
597 void fill_RAM_use(LogicalRowUser &lru, int row, RAM_side_t side);
598 void fill_color_map_RAM_use(LogicalRowUser &lru, int row);
599 void remove_placed_group(SRAM_group *candidate, RAM_side_t side);
600 void update_must_place_in_half(const SRAM_group *candidate, switchbox_t bus);
601 void fill_swbox_side(safe_vector<LogicalRowUser> &lrus, int row, RAM_side_t side);
602 void swbox_logical_row(safe_vector<LogicalRowUser> &lrus, int row, RAM_side_t side,
603 SRAM_group *curr_oflow, SRAM_group *sel_oflow);
604 void calculate_curr_oflow(safe_vector<LogicalRowUser> &lrus, SRAM_group **curr_oflow,
605 SRAM_group **synth_oflow, RAM_side_t side) const;
606 void calculate_sel_oflow(safe_vector<LogicalRowUser> &lrus, SRAM_group **sel_oflow) const;
607 // Switchbox related helper functions end
608
609 int allocation_count = 0;
611 unsigned side_mask(RAM_side_t side) const;
612 unsigned partition_mask(RAM_side_t side);
613 int mems_needed(int entries, int depth, int per_mem_row, bool is_twoport);
614 void clear_table_vectors();
615 void clear_uses();
616 void clear_allocation();
617 void set_logical_memuse_type(table_alloc *ta, Use::type_t type);
618 bool analyze_tables(mem_info &mi);
619 void calculate_entries();
620 void calculate_column_balance(const mem_info &mi, unsigned &row, bool &column_balance_init);
621 bool single_allocation_balance(mem_info &mi, unsigned row);
622 bool cut_from_left_side(const mem_info &mi, int left_given_columns, int right_given_columns);
623 bool allocate_all_atcam(mem_info &mi);
624 bool allocate_all_exact(unsigned column_mask);
625 safe_vector<int> way_size_calculator(int ways, int RAMs_needed);
626 safe_vector<std::pair<int, int>> available_SRAMs_per_row(unsigned mask, SRAM_group *group,
627 int width_sect);
628 safe_vector<int> available_match_SRAMs_per_row(unsigned selected_columns_mask,
629 unsigned total_mask, std::set<int> selected_rows,
630 SRAM_group *group, int width_sect);
631 void break_exact_tables_into_ways();
632 bool search_bus_available(int search_row, search_bus_info &sbi);
633 bool result_bus_available(int match_row, result_bus_info &mbi);
634 int select_search_bus(SRAM_group *group, int width_sect, int row);
635 int select_result_bus(SRAM_group *group, int width_sect, int row);
636 bool find_best_row_and_fill_out(unsigned column_mask);
637 bool fill_out_row(SRAM_group *placed_way, int row, unsigned column_mask);
638 SRAM_group *find_best_candidate(SRAM_group *placed_way, int row, int &loc);
639 void compress_ways(bool atcam);
640 void compress_row(Use &alloc);
641
642 void break_atcams_into_partitions();
643 bool determine_match_rows_and_cols(SRAM_group *group, int row, unsigned column_mask,
644 match_selection &match_select, bool atcam);
645 void fill_out_match_alloc(SRAM_group *group, match_selection &match_select, bool atcam);
646 bool find_best_partition_for_atcam(unsigned column_mask);
647 bool fill_out_partition(int row, unsigned partition_mask);
648 unsigned best_partition_side(mem_info &mi);
649 SRAM_group *best_partition_candidate(int row, unsigned column_mask, int &loc);
650
651 bool allocate_all_ternary();
652 int ternary_TCAMs_necessary(table_alloc *ta, int &midbyte);
653 bool find_ternary_stretch(int TCAMs_necessary, int &row, int &col, int midbyte,
654 bool &split_midbyte);
655
656 bool allocate_all_tind();
657 void find_tind_groups();
658 int find_best_tind_row(SRAM_group *tg, int &bus);
659 void compress_tind_groups();
660
661 bool allocate_all_swbox_users();
662 void find_swbox_bus_users();
663 void swbox_bus_selectors_indirects();
664 void swbox_bus_meters_counters();
665 void swbox_bus_stateful_alus();
666
667 void log_allocation(safe_vector<table_alloc *> *tas, UniqueAttachedId::type_t type);
668 void log_allocation(safe_vector<table_alloc *> *tas, UniqueAttachedId::pre_placed_type_t ppt);
669 void action_bus_users_log();
670 bool find_unit_gw(Memories::Use &alloc, cstring name, bool requires_search_bus);
671 bool find_search_bus_gw(table_alloc *ta, Memories::Use &alloc, cstring name);
672 bool find_result_bus_gw(Memories::Use &alloc, uint64_t payload, cstring name,
673 table_alloc *ta_no_match, int logical_table = -1);
674 uint64_t determine_payload(table_alloc *ta);
675 bool allocate_all_gw();
676 bool allocate_all_payload_gw(bool alloc_search_bus);
677 bool allocate_all_normal_gw(bool alloc_search_bus);
678 bool allocate_all_no_match_gw();
679 table_alloc *find_corresponding_exact_match(cstring name);
680 bool gw_search_bus_fit(table_alloc *ta, table_alloc *exact_ta, int row, int col);
681 bool allocate_all_no_match_miss();
682 bool allocate_all_tind_result_bus_tables();
683
684 bool find_mem_and_bus_for_idletime(std::vector<std::pair<int, std::vector<int>>> &mem_locs,
685 int &bus, int total_mem_required, bool top_half);
686 bool allocate_idletime_in_top_or_bottom_half(SRAM_group *idletime_group, bool top_or_bottom);
687 bool allocate_idletime(SRAM_group *idletime_group);
688 bool allocate_all_idletime();
689 friend std::ostream &operator<<(std::ostream &, const safe_vector<Memories::table_alloc *> &);
690
691 public:
692 bool allocate_all();
693 bool allocate_all_dummies();
694 void update(cstring name, const Use &alloc);
695 void update(const std::map<UniqueId, Use> &alloc);
696 void remove(cstring name, const Use &alloc);
697 void remove(const std::map<UniqueId, Use> &alloc);
698 void clear();
699 void add_table(const IR::MAU::Table *t, const IR::MAU::Table *gw, TableResourceAlloc *resources,
700 const LayoutOption *lo, const ActionData::Format::Use *af,
701 ActionData::FormatType_t ft, int entries, int stage_table,
702 attached_entries_t attached_entries);
703 void shrink_allowed_lts() { logical_tables_allowed--; }
704 void fill_placed_scm_table(const IR::MAU::Table *, const TableResourceAlloc *) {
705 BUG("SCM Not supported on this device");
706 }
707 void printOn(std::ostream &) const;
708 void visitUse(const Use &, std::function<void(cstring &, update_type_t)> fn);
709 const ordered_map<cstring, int> collect_sram_block_alloc_info() override {
710 const BFN::Alloc2Dbase<cstring> *arrays[] = {&tcam_use,
711 &sram_print_search_bus,
712 &sram_print_result_bus,
713 &tind_bus,
714 &action_data_bus,
715 &stash_use,
716 &sram_use,
717 &mapram_use,
718 &overflow_bus,
719 &gateway_use,
720 &payload_use};
722 for (auto arr : arrays)
723 for (int r = 0; r < arr->rows(); r++)
724 for (int c = 0; c < arr->cols(); c++)
725 if (arr->at(r, c))
726 // initialize all table sram block numbers to zero.
727 sram_info[arr->at(r, c)] = 0;
728
729 for (int r = 0; r < SRAM_ROWS; r++) {
730 for (int c = 0; c < SRAM_COLUMNS; c++) {
731 if (auto tbl = sram_use.at(r, c)) {
732 // count sram blocks
733 sram_info[tbl]++;
734 }
735 }
736 }
737 return sram_info;
738 }
739};
740
741} // namespace Tofino
742
743#endif /* BF_P4C_MAU_TOFINO_MEMORIES_H_ */
Definition attached_info.h:32
Definition alloc.h:65
Definition alloc.h:152
Definition alloc.h:76
Definition table_layout.h:34
Definition stringify.h:33
Definition unique_id.h:168
Definition bitvec.h:120
Definition cstring.h:85
Definition hex.h:27
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition tofino/memories.cpp:376
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition tofino/action_data_bus.cpp:28
Definition action_format.h:979
Definition instruction_memory.h:111
Definition memories.h:81
Definition memories.h:39
Definition table_format.h:108
Definition resource.h:37
Definition tofino/memories.h:317
Definition tofino/memories.h:337
Definition tofino/memories.h:37