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;
58 static constexpr int PAYLOAD_COUNT = 2;
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;
74 static constexpr int LOGICAL_ROW_MISSING_OFLOW = 8;
108 struct search_bus_info {
111 int width_section = 0;
116 search_bus_info(
cstring n,
int ws,
int hg)
117 : name(n), width_section(ws), hash_group(hg), init(
true) {}
119 bool operator==(
const search_bus_info &sbi) {
120 return name == sbi.name && width_section == sbi.width_section &&
121 hash_group == sbi.hash_group;
124 bool operator!=(
const search_bus_info &sbi) {
return !operator==(sbi); }
126 bool free() {
return !init; }
128 friend std::ostream &operator<<(std::ostream &,
const search_bus_info &);
130 struct result_bus_info {
132 int width_section = 0;
133 int logical_table = 0;
138 result_bus_info(
cstring n,
int ws,
int lt)
139 : name(n), width_section(ws), logical_table(lt), init(
true) {}
141 bool operator==(
const result_bus_info &mbi) {
142 return name == mbi.name && width_section == mbi.width_section &&
143 logical_table == mbi.logical_table;
146 bool operator!=(
const result_bus_info &mbi) {
return !operator==(mbi); }
147 bool free() {
return !init; }
149 friend std::ostream &operator<<(std::ostream &,
const result_bus_info &);
152 unsigned sram_inuse[SRAM_ROWS] = {0};
164 int tcam_midbyte_use[TCAM_ROWS / 2][TCAM_COLUMNS] = {{-1}};
172 unsigned mapram_inuse[SRAM_ROWS] = {0};
174 bool gw_bytes_reserved[SRAM_ROWS][BUS_COUNT] = {{
false}};
179 int logical_tables = 0;
180 int match_tables = 0;
181 int result_bus_min = 0;
182 int atcam_tables = 0;
186 int action_tables = 0;
187 int action_bus_min = 0;
189 int ternary_tables = 0;
190 int ternary_TCAMs = 0;
191 int stats_tables = 0;
193 int meter_tables = 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;
203 void clear() { memset(
this, 0,
sizeof(mem_info)); }
205 int total_RAMs()
const {
206 return match_RAMs + action_RAMs + stats_RAMs + meter_RAMs + selector_RAMs + tind_RAMs;
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;
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;
223 const IR::MAU::Table *table;
224 const ::IXBar::Use *match_ixbar;
228 std::map<UniqueId, Memories::Use> *memuse;
231 int provided_entries;
236 int total_entries()
const {
237 return std::accumulate(calc_entries_per_uid.begin(), calc_entries_per_uid.end(), 0);
239 int attached_gw_bytes = 0;
240 int stage_table = -1;
242 table_alloc *table_link =
nullptr;
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,
260 attached_entries(attached_entries),
261 attached_gw_bytes(0),
263 table_link(
nullptr) {}
264 void link_table(table_alloc *ta) { table_link = ta; }
265 int analysis_priority()
const;
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;
272 const IR::MAU::AttachedMemory *at =
nullptr,
bool is_gw =
false,
273 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP)
const;
276 const IR::MAU::AttachedMemory *at =
nullptr,
277 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP)
const;
280 const IR::MAU::AttachedMemory *at =
nullptr,
281 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP)
const;
283 int logical_tables_allowed = LOGICAL_TABLES;
285 friend std::ostream &operator<<(std::ostream &out,
const Memories::table_alloc &ta);
295 int logical_table = -1;
296 int vpn_increment = 1;
300 const IR::MAU::AttachedMemory *attached =
nullptr;
301 UniqueAttachedId::pre_placed_type_t ppt = UniqueAttachedId::NO_PP;
302 int recent_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;
327 int left_to_place()
const {
328 BUG_CHECK(placed <= needed,
"Placed more color map RAMs than actually needed");
329 return needed - placed;
332 bool require_stats()
const {
return cma == IR::MAU::ColorMapramAddress::STATS; }
338 SRAM_group *sel_group =
nullptr;
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;
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;
359 bool all_placed()
const {
return sel_all_placed() && action_all_placed(); }
361 bool is_act_corr_group(SRAM_group *corr) {
362 return action_groups.find(corr) != action_groups.end();
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;
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;
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;
387 bool requires_ab =
false;
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);
400 result_bus_info build_result_bus(
int width_sect)
const;
402 int left_to_place()
const {
403 BUG_CHECK(placed <= depth,
"Placed more than needed");
404 return depth - placed;
406 bool all_placed()
const {
407 BUG_CHECK(placed <= depth,
"Placed more than needed");
408 return (depth == placed);
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;
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())
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;
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;
438 return left_to_place();
442 int maprams_left_to_place()
const {
443 if (is_synth_type())
return left_to_place() + cm.left_to_place();
449 bool same_wide_action(
const SRAM_group &a);
450 int calculate_next_vpn()
const {
return placed * vpn_increment + vpn_offset; }
453 struct match_selection {
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;
462 enum switchbox_t { ACTION = 0, SYNTH, OFLOW, SWBOX_TYPES };
464 struct LogicalRowUser {
465 SRAM_group *group =
nullptr;
466 switchbox_t bus = SWBOX_TYPES;
470 operator bool()
const {
return group !=
nullptr; }
473 map_RAM_mask.clear();
480 bool set()
const {
return !(RAM_mask.empty() && map_RAM_mask.empty()); }
482 bitvec color_map_RAM_mask()
const {
483 BUG_CHECK(group->type == SRAM_group::METER,
484 "Cannot get color map RAMs of "
486 return map_RAM_mask - (RAM_mask >> LEFT_SIDE_COLUMNS);
489 void dbprint(std::ostream &out)
const {
490 out << *group <<
" bus " << bus <<
" RAM mask: 0x" << RAM_mask <<
" map RAM mask: 0x"
493 LogicalRowUser(SRAM_group *g, switchbox_t b) : group(g), bus(b) {}
498 SRAM_group *group =
nullptr;
500 unsigned mapram_mask = 0;
501 operator bool()
const {
return group !=
nullptr; }
512 void dbprint(std::ostream &out)
const {
513 out << *group <<
" RAM mask: 0x" <<
P4::hex(mask) <<
" map RAM mask: 0x"
519 enum RAM_side_t { LEFT = 0, RIGHT, RAM_SIDES };
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,
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,
580 bool action_candidate_prefer_sel(SRAM_group *max_req, SRAM_group *synth, SRAM_group *curr_oflow,
581 SRAM_group *sel_oflow,
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;
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,
594 int RAMs_avaialble,
bool is_synth_type)
const;
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);
603 SRAM_group *curr_oflow, SRAM_group *sel_oflow);
605 SRAM_group **synth_oflow, RAM_side_t side)
const;
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();
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);
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);
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);
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);
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();
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();
669 void action_bus_users_log();
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();
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();
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);
699 void add_table(
const IR::MAU::Table *t,
const IR::MAU::Table *gw,
TableResourceAlloc *resources,
703 void shrink_allowed_lts() { logical_tables_allowed--; }
705 BUG(
"SCM Not supported on this device");
707 void printOn(std::ostream &)
const;
708 void visitUse(
const Use &, std::function<
void(
cstring &, update_type_t)> fn);
711 &sram_print_search_bus,
712 &sram_print_result_bus,
722 for (
auto arr : arrays)
723 for (
int r = 0; r < arr->rows(); r++)
724 for (
int c = 0; c < arr->cols(); c++)
727 sram_info[arr->at(r, c)] = 0;
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)) {