32 static constexpr int EXACT_GROUPS = 8;
33 static constexpr int EXACT_BYTES_PER_GROUP = 16;
34 static constexpr int HASH_TABLES = 16;
35 static constexpr int HASH_GROUPS = 8;
36 static constexpr int HASH_INDEX_GROUPS = 4;
37 static constexpr int HASH_SINGLE_BITS = 12;
38 static constexpr int HASH_PARITY_BIT = 51;
39 static constexpr int RAM_SELECT_BIT_START = 40;
40 static constexpr int RAM_LINE_SELECT_BITS = 10;
41 static constexpr int HASH_MATRIX_SIZE = RAM_SELECT_BIT_START + HASH_SINGLE_BITS;
42 static constexpr int HASH_DIST_SLICES = 3;
43 static constexpr int HASH_DIST_BITS = 16;
44 static constexpr int HASH_DIST_EXPAND_BITS = 7;
45 static constexpr int HASH_DIST_MAX_MASK_BITS = HASH_DIST_BITS + HASH_DIST_EXPAND_BITS;
46 static constexpr int HASH_DIST_UNITS = 2;
47 static constexpr int TOFINO_METER_ALU_BYTE_OFFSET = 8;
48 static constexpr int LPF_INPUT_BYTES = 4;
49 static constexpr int TERNARY_GROUPS = StageUse::MAX_TERNARY_GROUPS;
50 static constexpr int BYTE_GROUPS = StageUse::MAX_TERNARY_GROUPS/2;
51 static constexpr int TERNARY_BYTES_PER_GROUP = 5;
52 static constexpr int TERNARY_BYTES_PER_BIG_GROUP = 11;
53 static constexpr int GATEWAY_SEARCH_BYTES = 4;
54 static constexpr int RESILIENT_MODE_HASH_BITS = 51;
55 static constexpr int FAIR_MODE_HASH_BITS = 14;
56 static constexpr int METER_ALU_HASH_BITS = 52;
57 static constexpr int METER_ALU_HASH_PARITY_BYTE_START = 48;
58 static constexpr int METER_PRECOLOR_SIZE = 2;
59 static constexpr int REPEATING_CONSTRAINT_SECT = 4;
60 static constexpr int MAX_HASH_BITS = 52;
62 le_bitrange(RAM_SELECT_BIT_START, METER_ALU_HASH_BITS-1);
63 static constexpr le_bitrange INDEX_BIT_RANGE(
int group) {
64 return le_bitrange(group*RAM_LINE_SELECT_BITS, (group+1)*RAM_LINE_SELECT_BITS - 1); }
65 static constexpr int INDEX_RANGE_SUBGROUP(
le_bitrange r) {
return r.
lo / RAM_LINE_SELECT_BITS; }
67 static int get_meter_alu_hash_bits() {
69 if (!BackendOptions().disable_gfm_parity)
70 return METER_ALU_HASH_BITS - 1;
71 return METER_ALU_HASH_BITS;
74 static int get_hash_single_bits() {
75 static bool disable_gfm_parity = BackendOptions().disable_gfm_parity;
77 if (!disable_gfm_parity)
78 return HASH_SINGLE_BITS - 1;
79 return HASH_SINGLE_BITS;
83 static int get_hash_matrix_size() {
84 return RAM_SELECT_BIT_START + get_hash_single_bits();
87 static int get_max_hash_bits() {
89 if (!BackendOptions().disable_gfm_parity)
90 return MAX_HASH_BITS - 1;
95 using byte_speciality_t = ::IXBar::byte_speciality_t;
97 static constexpr auto NONE = ::IXBar::NONE;
98 static constexpr auto ATCAM_DOUBLE = ::IXBar::ATCAM_DOUBLE;
99 static constexpr auto ATCAM_INDEX = ::IXBar::ATCAM_INDEX;
100 static constexpr auto RANGE_LO = ::IXBar::RANGE_LO;
101 static constexpr auto RANGE_HI = ::IXBar::RANGE_HI;
102 static constexpr auto BYTE_SPECIALITIES = ::IXBar::BYTE_SPECIALITIES;
105 using parity_status_t = ::IXBar::parity_status_t;
107 static constexpr auto PARITY_NONE = ::IXBar::PARITY_NONE;
108 static constexpr auto PARITY_ENABLED = ::IXBar::PARITY_ENABLED;
109 static constexpr auto PARITY_DISABLED = ::IXBar::PARITY_DISABLED;
120 if (ternary)
return ternary_use;
123 std::multimap<PHV::Container, Loc> exact_fields;
124 std::multimap<PHV::Container, Loc> ternary_fields;
125 std::multimap<PHV::Container, Loc> &fields(
bool ternary) {
126 return ternary ? ternary_fields : exact_fields; }
129 std::map<PHV::Container, std::set<cstring>> field_users;
134 unsigned hash_index_inuse[HASH_INDEX_GROUPS] = { 0 };
137 unsigned hash_single_bit_inuse[HASH_SINGLE_BITS] = { 0 };
139 unsigned hash_group_use[HASH_GROUPS] = { 0 };
144 parity_status_t hash_group_parity_use[HASH_GROUPS] = { PARITY_NONE };
147 bitvec hash_used_per_function[HASH_GROUPS] = {
bitvec() };
149 int hash_dist_groups[HASH_DIST_UNITS] = {-1, -1};
150 friend class IXBarRealign;
157 return byte_group_use; }
160 unsigned toIXBarOutputByte(
bool ternary,
int group,
int byte) {
163 unsigned mid_byte_count = (group / 2) + (group % 2);
164 offset = (group / 2) * 10 + (group % 2) * 5 +
byte + mid_byte_count;
166 offset = group * 16 + byte;
172 std::set<cstring> dleft_updates;
175 using byte_type_t = ::IXBar::byte_type_t;
177 static constexpr auto NO_BYTE_TYPE = ::IXBar::NO_BYTE_TYPE;
178 static constexpr auto ATCAM = ::IXBar::ATCAM;
179 static constexpr auto PARTITION_INDEX = ::IXBar::PARTITION_INDEX;
180 static constexpr auto RANGE = ::IXBar::RANGE;
181 using HashDistDest_t = ::IXBar::HashDistDest_t;
183 static constexpr auto HD_IMMED_LO = ::IXBar::HD_IMMED_LO;
184 static constexpr auto HD_IMMED_HI = ::IXBar::HD_IMMED_HI;
185 static constexpr auto HD_STATS_ADR = ::IXBar::HD_STATS_ADR;
186 static constexpr auto HD_METER_ADR = ::IXBar::HD_METER_ADR;
187 static constexpr auto HD_ACTIONDATA_ADR = ::IXBar::HD_ACTIONDATA_ADR;
188 static constexpr auto HD_PRECOLOR = ::IXBar::HD_PRECOLOR;
189 static constexpr auto HD_HASHMOD = ::IXBar::HD_HASHMOD;
190 static constexpr auto HD_DESTS = ::IXBar::HD_DESTS;
193 bool gw_search_bus =
false;
194 int gw_search_bus_bytes = 0;
195 bool gw_hash_group =
false;
196 parity_status_t parity = PARITY_NONE;
198 bool search_data()
const {
return gw_search_bus || gw_hash_group; }
199 bool is_parity_enabled()
const override {
return parity == PARITY_ENABLED; }
201 HashDistDest_t hash_dist_type = HD_DESTS;
202 std::string hash_dist_used_for()
const override {
203 return IXBar::hash_dist_name(hash_dist_type); }
206 unsigned hash_table_inputs[HASH_GROUPS] = { 0 };
208 bitvec hash_seed[HASH_GROUPS];
218 : field(f), group(g), lo(l), bit(b), width(w), valid(
false) {}
219 Bits(
cstring f,
int g,
int l,
int b,
int w,
bool v)
220 : field(f), group(g), lo(l), bit(b), width(w), valid(v) {}
221 int hi()
const {
return lo + width - 1; } };
226 bool allocated =
false;
230 std::map<int, const IR::Expression *> computed_expressions;
237 computed_expressions.clear();
240 const std::map<int, const IR::Expression *> &hash_computed_expressions()
const override {
241 return meter_alu_hash.computed_expressions; }
245 bool allocated =
false;
247 bitvec galois_matrix_bits;
249 std::map<int, le_bitrange> galois_start_bit_to_p4_hash;
250 const IR::Expression *hash_gen_expr =
nullptr;
256 galois_matrix_bits.clear();
257 galois_start_bit_to_p4_hash.clear();
260 int hash_dist_hash_group()
const override {
return hash_dist_hash.group; }
263 bool allocated =
false;
273 } proxy_hash_key_use;
276 unsigned data_bytemask = 0;
277 unsigned hash_bytemask = 0;
279 void clear() { data_bytemask = hash_bytemask = 0; }
280 bool empty()
const {
return !data_bytemask && !hash_bytemask; }
287 void clear()
override {
288 ::IXBar::Use::clear();
289 gw_search_bus =
false;
290 gw_search_bus_bytes = 0;
291 gw_hash_group =
false;
292 parity = PARITY_NONE;
293 hash_dist_type = HD_DESTS;
294 for (
auto &ht : hash_table_inputs) ht = 0;
295 for (
auto &hs : hash_seed) hs.clear();
297 meter_alu_hash.clear();
298 hash_dist_hash.clear();
299 proxy_hash_key_use.clear();
300 salu_input_source.clear();
301 field_list_order.clear();
303 Use *clone()
const override {
return new Use(*
this); }
304 bool empty()
const override {
305 return ::IXBar::Use::empty() && bit_use.empty() &&
306 !meter_alu_hash.allocated && !hash_dist_hash.allocated &&
307 !proxy_hash_key_use.allocated && salu_input_source.empty(); }
308 void dbprint(std::ostream &)
const override;
310 void add(
const Use &alloc);
313 unsigned compute_hash_tables()
override;
315 const IR::MAU::Table *)
const override {
return false; }
316 void emit_ixbar_asm(
const PhvInfo &phv, std::ostream& out,
indent_t indent,
317 const TableMatch *fmt,
const IR::MAU::Table *)
const override;
318 void emit_salu_bytemasks(std::ostream &out,
indent_t indent)
const override;
321 std::map<
int, std::map<int, Slice>> &sort)
const override;
322 bitvec galois_matrix_bits()
const override {
return hash_dist_hash.galois_matrix_bits; }
323 int hash_groups()
const override;
325 bitvec meter_bit_mask()
const override {
return meter_alu_hash.bit_mask; }
326 int ternary_align(
const Loc &)
const override;
327 int total_input_bits()
const override {
329 for (
auto fl : field_list_order) {
330 rv += fl->type->width_bits(); }
333 const char *way_source_kind()
const override {
return "group"; }
353 const IR::MAU::HashDist *created_hd;
357 bool chained_addr =
false;
358 bitvec possible_shifts()
const;
362 : func(f), bits_in_use(b), dest(d), shift(s) {}
364 return std::tie(dest, shift, bits_in_use, chained_addr) <
365 std::tie(hd.dest, hd.shift, hd.bits_in_use, hd.chained_addr);
374 const IR::MAU::HashDist *created_hd =
nullptr;
376 bool is_dynamic()
const {
return !dyn_hash_name.isNull(); }
389 std::set<cstring> outputs;
391 int hash_group()
const;
392 bitvec destinations()
const;
393 bitvec galois_matrix_bits()
const;
396 std::string used_for()
const;
400 ir_allocations.clear();
411 static unsigned hash_table_inputs(
const HashDistUse &hdu);
417 const IR::MAU::Table *tbl;
424 void build_action_data_req(
const IR::MAU::HashDist *hd);
425 void build_req(
const IR::MAU::HashDist *hd,
const IR::Node *rel_node,
426 bool created_hd =
false);
428 void build_function(
const IR::MAU::HashDist *hd,
P4HashFunction **func,
430 bool preorder(
const IR::MAU::HashDist *)
override;
431 bool preorder(
const IR::MAU::TableSeq *)
override {
return false; }
432 bool preorder(
const IR::MAU::AttachedOutput *)
override {
return false; }
433 bool preorder(
const IR::MAU::StatefulCall *)
override {
return false; }
436 void immediate_inputs();
438 bool allocate_hash_dist();
439 XBarHashDist(
IXBar &s,
const PhvInfo &p,
const IR::MAU::Table *t,
442 : self(s), phv(p), tbl(t), af(a), lo(l), resources(r), attached_entries(ae) {}
446 enum AvailBytesPerRepeatingSect_t { AV_FULL = 1, AV_HALF = 2, AV_BYTE = 4 };
450 enum type_t { MATCH, HASH_DIST, FREE };
472 std::array<bitvec, REPEATING_CONSTRAINT_SECT> _free = { {
bitvec() } };
475 for (
auto bit : can_use)
480 bitvec max_free()
const {
return free(
bitvec(0, REPEATING_CONSTRAINT_SECT)); }
481 bool attempted =
false;
482 bool hash_open[2] = {
true,
true };
483 type_t hash_table_type[2] = { FREE, FREE };
484 int range_index = -1;
486 bool hash_dist_avail(
int ht)
const {
487 return hash_table_type[ht] == HASH_DIST || hash_table_type[ht] == FREE;
490 bool hash_dist_only(
int ht)
const {
491 return hash_table_type[ht] == HASH_DIST;
494 void dbprint(std::ostream &out)
const {
495 out << group <<
" found: 0x" << found <<
" free: 0x" << max_free();
498 int total_avail()
const {
return found.popcount() + max_free().popcount(); }
499 bool range_set()
const {
return range_index != -1; }
501 bool is_better_group(
const grp_use &b,
bool prefer_found,
502 int required_allocation_bytes, std::map<int, int> &constraints_to_reqs)
const;
503 explicit grp_use(
int g) : group(g) {}
506 using mid_byte_use = grp_use;
512 int max_search_buses = -1;
513 int index_groups = 0;
515 bool hash_dist =
false;
516 bool requires_versioning =
false;
524 rv.index_groups = HASH_DIST_SLICES;
526 rv.index_groups = HASH_INDEX_GROUPS;
527 rv.select_bits = IXBar::get_hash_single_bits();
532 bool fit_requirements(
bitvec hash_matrix_in_use)
const;
536 : index_groups(ig), select_bits(sb), hash_dist(hd) {}
548 std::map<cstring, bitvec> fields_needed;
549 const IR::MAU::Table *tbl;
551 profile_t init_apply(
const IR::Node *root)
override;
552 bool preorder(
const IR::MAU::StatefulAlu *)
override;
553 bool preorder(
const IR::MAU::SaluAction *)
override;
554 bool preorder(
const IR::Expression *e)
override;
555 bool preorder(
const IR::MAU::HashDist *)
override;
556 bool preorder(
const IR::MAU::IXBarExpression *)
override;
558 bool preorder(
const IR::Annotation *)
override {
return false; }
559 bool preorder(
const IR::Declaration_Instance *)
override {
return false; }
560 bool preorder(
const IR::MAU::Selector *)
override {
return false; }
562 static void collapse_contained(std::map<le_bitrange, const IR::Expression *> &m);
567 : phv(phv), map_alloc(ma), field_list_order(flo), tbl(t) {}
571 std::vector<const IR::MAU::IXBarExpression *> hash_sources;
576 bool allocMatch(
bool ternary,
const IR::MAU::Table *tbl,
const PhvInfo &phv, Use &alloc,
578 bool allocPartition(
const IR::MAU::Table *tbl,
const PhvInfo &phv, Use &alloc,
580 int getHashGroup(
unsigned hash_table_input,
const hash_matrix_reqs *hm_reqs =
nullptr);
581 void getHashDistGroups(
unsigned hash_table_input,
int hash_group_opt[HASH_DIST_UNITS]);
582 bool allocProxyHash(
const IR::MAU::Table *tbl,
const PhvInfo &phv,
583 const LayoutOption *lo, Use &alloc, Use &proxy_hash_alloc);
584 bool allocProxyHashKey(
const IR::MAU::Table *tbl,
const PhvInfo &phv,
const LayoutOption *lo,
585 Use &proxy_hash_alloc, hash_matrix_reqs &hm_reqs);
587 bool allocAllHashWays(
bool ternary,
const IR::MAU::Table *tbl, Use &alloc,
588 const LayoutOption *layout_option,
size_t start,
size_t last,
589 const hash_matrix_reqs &hm_reqs);
590 bool allocHashWay(
const IR::MAU::Table *tbl,
const LayoutOption *layout_option,
591 size_t index, std::map<int, bitvec> &slice_to_select_bits, Use &alloc,
592 unsigned local_hash_table_input,
unsigned hf_hash_table_input,
int hash_group);
593 bool allocGateway(
const IR::MAU::Table *,
const PhvInfo &phv, Use &alloc,
595 bool allocSelector(
const IR::MAU::Selector *,
const IR::MAU::Table *,
const PhvInfo &phv,
597 bool allocStateful(
const IR::MAU::StatefulAlu *,
const IR::MAU::Table *,
const PhvInfo &phv,
598 Use &alloc,
bool on_search_bus);
599 bool allocMeter(
const IR::MAU::Meter *,
const IR::MAU::Table *,
const PhvInfo &phv,
600 Use &alloc,
bool on_search_bus);
605 bool allocTable(
const IR::MAU::Table *tbl,
const IR::MAU::Table *gw,
const PhvInfo &phv,
609 void update(
cstring name, const ::IXBar::Use &alloc)
override;
610 void update(
cstring name,
const HashDistUse &hash_dist_alloc);
612 void update(
const IR::MAU::Table *tbl)
override;
613 void add_collisions()
override;
614 void verify_hash_matrix()
const override;
615 void dbprint(std::ostream &)
const override;
618 for (
auto &p : Values(exact_fields.equal_range(c)))
619 if (exact_use.at(p.group, p.byte).second/8 ==
byte)
623 unsigned find_balanced_group(Use &alloc,
int way_size);
628 unsigned byte_mask = ~0U);
631 bitvec can_use_from_flags(
int flags)
const;
632 int groups(
bool ternary)
const;
633 int mid_bytes(
bool ternary)
const;
634 int bytes_per_group(
bool ternary)
const;
636 void increase_ternary_ixbar_space(
int &groups_needed,
int &nibbles_needed,
637 bool requires_versioning);
639 int &groups_needed,
int &mid_bytes_needed,
bool requires_versioning);
645 hash_matrix_reqs &hm_reqs,
unsigned byte_mask);
652 hash_matrix_reqs &hm_reqs);
653 grp_use::type_t is_group_for_hash_dist(
int hash_table);
654 bool violates_hash_constraints(safe_vector <grp_use> &order,
bool hash_dist,
int group,
661 bool ternary,
bool hash_dist,
unsigned byte_mask);
663 int &match_bytes_placed,
int search_bus);
665 bool ternary,
int &match_bytes_placed,
int search_bus,
bool &prefer_half_bytes,
666 bool only_alloc_nibble);
672 bool &prefer_half_bytes,
bool only_alloc_nibble);
675 int byte,
size_t &index,
int &free_bytes,
int &ixbar_bytes_placed,
676 int &match_bytes_placed,
int search_bus,
int *range_index);
680 int nibbles_needed,
int &bytes_to_allocate);
683 bool ternary,
bool prefer_found,
int required_allocation_bytes);
688 int groups_needed,
bool hash_dist,
unsigned byte_mask);
693 int &bytes_to_allocate,
bool hash_dist,
694 unsigned byte_mask,
int search_bus);
696 hash_matrix_reqs match_hash_reqs(
const LayoutOption *lo,
size_t start,
size_t end,
698 void layout_option_calculation(
const LayoutOption *layout_option,
699 size_t &start,
size_t &last);
701 int max_bit_to_byte(
bitvec bit_mask);
702 int max_index_group(
int max_bit);
703 int max_index_single_bit(
int max_bit);
704 unsigned index_groups_used(
bitvec bv)
const;
705 unsigned select_bits_used(
bitvec bv)
const;
706 bool hash_use_free(
int max_group,
int max_single_bit,
unsigned hash_table_input);
707 void write_hash_use(
int max_group,
int max_single_bit,
unsigned hash_table_input,
711 bool setup_stateful_search_bus(
const IR::MAU::StatefulAlu *salu, Use &alloc,
712 const FindSaluSources &sources,
unsigned &byte_mask);
713 bool setup_stateful_hash_bus(
const PhvInfo &,
const IR::MAU::StatefulAlu *salu, Use &alloc,
714 const FindSaluSources &sources);
717 std::map<int, le_bitrange> &bit_starts,
719 void determine_proxy_hash_alg(
const PhvInfo &,
const IR::MAU::Table *tbl, Use &use,
int group);
721 bool isHashDistAddress(HashDistDest_t dest)
const;
723 void determineHashDistInUse(
int hash_group,
bitvec &units_in_use,
bitvec &hash_bits_in_use);
724 void buildHashDistIRUse(HashDistAllocPostExpand &alloc_req, HashDistUse &use,
726 bitvec total_post_expand_bits,
const IR::MAU::Table* tbl,
cstring name);
728 unsigned hash_table_input,
int asm_unit,
bitvec hash_bits_used, HashDistDest_t dest,
732 bool allocHashDistSection(
bitvec post_expand_bits,
bitvec possible_shifts,
int hash_group,
733 int &unit_allocated,
bitvec &hash_bits_allocated);
734 bool allocHashDistWideAddress(
bitvec post_expand_bits,
bitvec possible_shifts,
int hash_group,
735 bool chained_addr,
int &unit_allocated,
bitvec &hash_bits_allocated);
737 const PhvInfo &phv,
cstring name,
const IR::MAU::Table* tbl,
bool second_try);
738 void createChainedHashDist(
const HashDistUse &hd_alloc, HashDistUse &chained_hd_alloc,
740 void update_hash_parity(
IXBar::Use &use,
int hash_group);
741 parity_status_t update_hash_parity(
int hash_group);