19#ifndef BF_P4C_MAU_INPUT_XBAR_H_
20#define BF_P4C_MAU_INPUT_XBAR_H_
25#include <unordered_set>
27#include "backends/tofino/bf-p4c/bf-p4c-options.h"
28#include "backends/tofino/bf-p4c/common/alloc.h"
29#include "backends/tofino/bf-p4c/common/asm_output.h"
30#include "backends/tofino/bf-p4c/common/slice.h"
31#include "backends/tofino/bf-p4c/device.h"
32#include "backends/tofino/bf-p4c/lib/autoclone.h"
33#include "backends/tofino/bf-p4c/lib/dyn_vector.h"
34#include "backends/tofino/bf-p4c/mau/attached_entries.h"
35#include "backends/tofino/bf-p4c/mau/ixbar_expr.h"
36#include "backends/tofino/bf-p4c/mau/table_layout.h"
37#include "backends/tofino/bf-p4c/phv/phv_fields.h"
40#include "lib/safe_vector.h"
57 static std::random_device seed_generator;
59 static std::mt19937 mersenne_generator;
71 static constexpr int LAMB_LINE_SELECT_BITS = 6;
72 static constexpr int RAM_LINE_SELECT_BITS = 10;
75 enum type { BYTE = 0, WORD = 1, NONE = 2 };
76 int group = -1,
byte = -1;
78 Loc(
int g,
int b) : group(g), byte(b) {}
79 Loc(
const Loc &) =
default;
80 explicit operator bool()
const {
return group >= 0 &&
byte >= 0; }
81 operator std::pair<int, int>()
const {
return std::make_pair(group,
byte); }
83 bool operator==(
const Loc &loc)
const {
return group == loc.group &&
byte == loc.byte; }
84 bool operator!=(
const Loc &loc)
const {
return !(*
this == loc); }
85 int getOrd(
const bool isTernary =
false)
const {
88 return Device::ixbarSpec().getTernaryOrdBase(group) + byte;
90 return Device::ixbarSpec().getExactOrdBase(group) + byte;
95 bool allocated()
const {
return group >= 0 &&
byte >= 0; }
96 type group_type()
const {
106 enum byte_speciality_t {
134 std::optional<cstring> aliasSource;
142 aliasSource = std::nullopt;
146 if (aliasSource == std::nullopt)
152 bool operator==(
const FieldInfo &fi)
const {
153 return field == fi.field &&
lo == fi.lo &&
hi == fi.hi;
155 bool operator<(
const FieldInfo &fi)
const {
156 if (field != fi.field)
return field < fi.field;
157 if (
lo != fi.lo)
return lo < fi.lo;
158 if (
hi != fi.hi)
return hi < fi.hi;
162 bool operator!=(
const FieldInfo &fi)
const {
return !((*this) == fi); }
164 int width()
const {
return hi -
lo + 1; }
166 int cont_hi()
const {
return cont_lo + width() - 1; }
172 std::string visualization_detail()
const;
177 enum byte_type_t { NO_BYTE_TYPE, ATCAM, PARTITION_INDEX, RANGE };
178 enum HashDistDest_t {
188 enum parity_status_t { PARITY_NONE, PARITY_ENABLED, PARITY_DISABLED };
202 virtual bool is_parity_enabled()
const = 0;
222 virtual Use *clone()
const = 0;
226 virtual std::string hash_dist_used_for()
const = 0;
227 virtual int hash_dist_hash_group()
const = 0;
242 unsigned specialities = 0;
245 void set_spec(byte_speciality_t bs) { specialities |= (1 << bs); }
247 void clear_spec(byte_speciality_t bs) { specialities &= ~(1 << bs); }
249 bool is_spec(byte_speciality_t bs)
const {
return specialities & (1 << bs); }
258 int range_index = -1;
261 bool proxy_hash =
false;
263 int ixbar_group_num = -1;
269 operator std::pair<PHV::Container, int>()
const {
270 return std::make_pair(container, lo);
272 bool operator==(
const std::pair<PHV::Container, int> &a)
const {
273 return container == a.first && lo == a.second;
275 bool operator==(
const Byte &b)
const {
return container == b.container && lo == b.lo; }
276 bool operator<(
const Byte &b)
const {
277 if (container != b.container)
return container < b.container;
278 if (lo != b.lo)
return lo < b.lo;
279 if (match_index != b.match_index)
return match_index < b.match_index;
282 if (specialities != b.specialities)
return specialities < b.specialities;
285 if (range_index != b.range_index)
return range_index < b.range_index;
286 if (field_bytes != b.field_bytes)
return field_bytes < b.field_bytes;
289 bool is_range()
const {
return is_spec(RANGE_LO) || is_spec(RANGE_HI); }
296 std::vector<FieldInfo> get_slices_for_visualization()
const;
297 bool is_subset(
const Byte &b)
const;
298 bool only_one_nibble_in_use()
const {
299 BUG_CHECK(!bit_use.empty(),
"IXBar byte has no data");
300 if (is_range())
return false;
301 return bit_use.getslice(0, 4).empty() || bit_use.getslice(4, 4).empty();
304 bool can_add_info(
const FieldInfo &fi)
const;
307 for (
auto &fi : field_bytes) {
321 unsigned select_mask;
324 : source(s), index(i), select(sel), select_mask(m) {}
328 bool allocated() {
return !use.empty(); }
337 virtual void clear() {
343 hash_table_inputs.clear();
347 virtual bool empty()
const {
return type == TYPES && use.empty() && way_use.empty(); }
348 virtual void dbprint(std::ostream &)
const;
359 : search_bus(sb), ixbar_group(ig), bytes(by), bits(b) {}
361 void dbprint(std::ostream &out)
const {
362 out <<
"Search bus: " << search_bus <<
", IXBar group: " << ixbar_group
363 <<
", Bytes : " << bytes <<
", Bits : " << bits;
374 virtual void add(
const Use &alloc);
378 virtual unsigned compute_hash_tables();
380 const IR::MAU::Table *)
const = 0;
381 virtual void emit_ixbar_asm(
const PhvInfo &phv, std::ostream &out,
indent_t indent,
382 const TableMatch *fmt,
const IR::MAU::Table *)
const = 0;
383 virtual void emit_salu_bytemasks(std::ostream &out,
indent_t indent)
const = 0;
386 std::map<
int, std::map<int, Slice>> &sort)
const = 0;
387 virtual bitvec galois_matrix_bits()
const = 0;
389 virtual int groups()
const;
390 virtual const std::map<int, const IR::Expression *> &hash_computed_expressions()
const = 0;
391 virtual int hash_groups()
const = 0;
393 virtual bitvec meter_bit_mask()
const = 0;
395 virtual int ternary_align(
const Loc &)
const = 0;
396 virtual int total_input_bits()
const = 0;
398 virtual const char *way_source_kind()
const = 0;
400 int bytesOnIxbar = 0;
401 for (
auto &u : use) {
402 for (
auto &fi : u.field_bytes) {
411 static HashDistDest_t dest_location(
const IR::Node *node,
bool precolor =
false);
412 static std::string hash_dist_name(HashDistDest_t dest);
419 int stage = -1, group = -1;
420 failure(
int stg,
int grp) : trigger(OTHER), stage(stg), group(grp) {}
436 const IR::MAU::Table *ctxt, std::optional<cstring> aliasSourceName,
438 byte_type_t byte_type = NO_BYTE_TYPE,
unsigned extra_align = 0,
439 int range_index = 0,
int pragma_forced_ixbar_group = -1);
444 bool hash_dist =
false;
445 bool is_atcam =
false;
446 bool partition =
false;
447 int partition_bits = 0;
449 bool repeats_allowed =
true;
458 std::map<cstring, bitvec> *fields_needed;
461 const IR::MAU::Table *tbl;
463 bool preorder(
const IR::ListExpression *)
override;
464 bool preorder(
const IR::StructExpression *)
override;
465 bool preorder(
const IR::Mask *)
override;
466 bool preorder(
const IR::MAU::TableKey *read)
override;
467 bool preorder(
const IR::Constant *c)
override;
468 bool preorder(
const IR::MAU::ActionArg *aa)
override;
469 bool preorder(
const IR::Expression *e)
override;
470 void postorder(
const IR::BFN::SignExtend *c)
override;
471 void end_apply()
override;
476 const IR::Expression *field, std::map<cstring, bitvec> *fields_needed,
478 : map_alloc(map_alloc),
479 field_list_order(field_list_order),
480 fields_needed(fields_needed),
489 virtual bool allocTable(
const IR::MAU::Table *tbl,
const IR::MAU::Table *gw,
const PhvInfo &,
492 virtual void update(
cstring name,
const Use &alloc) = 0;
495 virtual void update(
const IR::MAU::Table *tbl);
496 virtual void add_collisions() = 0;
497 virtual void verify_hash_matrix()
const = 0;
498 virtual void dbprint(std::ostream &)
const = 0;
501 static IXBar *create();
505 static void add_names(
cstring n, std::map<cstring, char> &names);
506 static void add_names(
const std::pair<PHV::Container, int> &c, std::map<cstring, char> &names);
507 static void add_names(
PHV::Container c, std::map<cstring, char> &names);
509 static void add_names(
const T &n, std::map<cstring, char> &names) {
510 for (
auto &a : n) add_names(a, names);
513 template <
class T,
int R,
int C>
515 for (
int r = 0; r < R; r++) add_names(n[r], names);
518 template <
class T,
int S>
520 for (
int i = 0; i < S; i++) add_names(n[i], names);
522 static void sort_names(std::map<cstring, char> &names);
523 static void write_one(std::ostream &out,
const std::pair<cstring, int> &f,
524 std::map<cstring, char> &fields);
525 static void write_one(std::ostream &out,
cstring n, std::map<cstring, char> &names);
526 static void write_one(std::ostream &out,
const std::pair<PHV::Container, int> &f,
527 std::map<cstring, char> &fields);
528 static void write_one(std::ostream &out,
PHV::Container f, std::map<cstring, char> &fields);
530 static void write_group(std::ostream &out,
const T &grp, std::map<cstring, char> &fields) {
531 for (
auto &a : grp) write_one(out, a, fields);
535inline std::ostream &operator<<(std::ostream &out,
const IXBar::Loc &l) {
536 return out <<
'(' << l.group <<
',' << l.byte <<
')';
538inline std::ostream &operator<<(std::ostream &out,
const IXBar::Use &u) {
543inline std::ostream &operator<<(std::ostream &out,
const IXBar::FieldInfo &fi) {
544 out << fi.visualization_detail();
548std::ostream &operator<<(std::ostream &, IXBar::Use::type_t);
549inline std::ostream &operator<<(std::ostream &out,
const IXBar::Use::Byte &b) {
550 out << b.container <<
'[' << b.lo <<
".." << (b.lo + 7) <<
']';
551 if (b.loc) out << b.loc;
552 out <<
" 0x" << b.bit_use;
553 if (b.flags) out <<
" flags=" <<
P4::hex(b.flags);
558inline std::ostream &operator<<(std::ostream &out,
const IXBar &i) {
Definition input_xbar.h:455
Definition table_layout.h:34
Definition mau/asm_output.h:85
Definition stringify.h:33
Definition ordered_map.h:32
Definition safe_vector.h:27
Definition phv_fields.h:154
cstring name
Definition phv_fields.h:161
Definition phv_fields.h:898
const PHV::Field * field() const override
Definition phv_fields.h:977
const le_bitrange & range() const override
Definition phv_fields.h:980
Definition phv_fields.h:1095
Definition mau/asm_output.h:223
Definition dyn_vector.h:27
The namespace encapsulating Barefoot/Intel-specific stuff.
Definition add_t2na_meta.cpp:21
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition resources.h:125
Definition input_xbar.h:128
FieldInfo(cstring n, int l, int h, int cl, std::optional< cstring > a)
Definition input_xbar.h:137
int cont_lo
Definition input_xbar.h:132
int pragma_forced_ixbar_group
Definition input_xbar.h:133
int hi
Definition input_xbar.h:131
int lo
Definition input_xbar.h:130
Definition input_xbar.h:443
Definition input_xbar.h:74
bool operator==(const Loc &loc) const
return the byte number in the total order
Definition input_xbar.h:83
Definition input_xbar.h:230
std::string visualization_detail() const
Definition mau/input_xbar.cpp:334
Definition input_xbar.h:352
Definition input_xbar.h:367
Definition input_xbar.h:317
Definition input_xbar.h:191
virtual safe_vector< Byte > atcam_partition(int *hash_group=nullptr) const
Definition mau/input_xbar.cpp:146
std::string used_for() const
Definition mau/input_xbar.cpp:226
virtual int gateway_group() const
Definition mau/input_xbar.cpp:174
virtual TotalBytes match_hash(safe_vector< int > *hash_groups=nullptr) const
Definition mau/input_xbar.cpp:113
virtual TotalBytes atcam_match() const
Definition mau/input_xbar.cpp:129
virtual int search_buses_single() const
Definition mau/input_xbar.cpp:158
virtual safe_vector< TotalInfo > bits_per_search_bus() const
Definition mau/input_xbar.cpp:190
Definition input_xbar.h:418
Definition input_xbar.h:69
std::map< Use::Byte, safe_vector< FieldInfo > > ContByteConversion
Definition input_xbar.h:434
Compiler generated random number function for use as hash seed on the input crossbar.
Definition input_xbar.h:56
static unsigned seed
Definition input_xbar.h:58
static std::uniform_int_distribution< unsigned > distribution1
Uniform distribution producing either a 0 or a 1.
Definition input_xbar.h:63
static std::uniform_int_distribution< unsigned > distribution10
Uniform distribution producing a 10-bit random number.
Definition input_xbar.h:61
static unsigned nextRandomNumber(unsigned numBits=1)
Definition mau/input_xbar.cpp:43
bool overlaps(ClosedRange a) const
Definition lib/bitrange.h:603