62 enum type_t { INVALID, EXACT, TERNARY, BYTE, GATEWAY, XCMP } type;
63 Group() : index(-1), type(INVALID) {}
64 Group(Group::type_t t,
int i) : index(i), type(t) {}
65 explicit operator bool()
const {
return type != INVALID; }
66 bool operator==(
const Group &a)
const {
return type == a.type && index == a.index; }
67 bool operator<(
const Group &a)
const {
68 return (type << 16) + index < (a.type << 16) + a.index;
73 enum type_t { INVALID, EXACT, XCMP } type;
74 HashTable() : index(-1), type(INVALID) {}
75 HashTable(type_t t,
int i) : index(i), type(t) {}
76 explicit operator bool()
const {
return type != INVALID; }
77 bool operator==(
const HashTable &a)
const {
return type == a.type && index == a.index; }
78 bool operator<(
const HashTable &a)
const {
79 return (type << 16) + index < (a.type << 16) + a.index;
81 std::string toString()
const;
89 explicit Input(
const Phv::Ref &a) : what(a), lo(-1), hi(-1) {}
90 Input(
const Phv::Ref &a,
int s) : what(a), lo(s), hi(-1) {}
91 Input(
const Phv::Ref &a,
int l,
int h) : what(a), lo(l), hi(h) {}
92 unsigned size()
const {
return hi - lo + 1; }
98 bool seed_parity =
false;
102 std::map<HashTable, std::map<int, HashCol>> hash_tables;
104 std::map<HashTable, unsigned> hash_table_parity;
105 std::map<unsigned, HashGrp> hash_groups;
106 static bool conflict(
const std::vector<Input> &a,
const std::vector<Input> &b);
107 static bool conflict(
const std::map<int, HashCol> &,
const std::map<int, HashCol> &,
int * = 0);
109 bool copy_existing_hash(
HashTable ht, std::pair<const int, HashCol> &col);
110 uint64_t hash_columns_used(
HashTable hash);
111 uint64_t hash_columns_used(
unsigned id) {
112 BUG_CHECK(
id < Target::EXACT_HASH_TABLES(),
"%d out of range for exact hash",
id);
113 return hash_columns_used(
HashTable(HashTable::EXACT,
id));
115 bool can_merge(HashGrp &a, HashGrp &b);
116 void add_use(
unsigned &byte_use, std::vector<Input> &a);
117 virtual int hash_num_columns(HashTable ht)
const {
return 52; }
118 virtual int group_max_index(Group::type_t t)
const;
119 virtual Group group_name(
bool ternary,
const value_t &value)
const;
120 virtual int group_size(Group::type_t t)
const;
121 const char *group_type(Group::type_t t)
const;
122 void parse_group(Table *t,
Group gr,
const value_t &value);
123 virtual bool parse_hash(Table *t,
const pair_t &kv) {
return false; }
124 void parse_hash_group(
HashGrp &hash_group,
const value_t &value);
125 void parse_hash_table(Table *t,
HashTable ht,
const value_t &value);
126 virtual bool parse_unit(Table *t,
const pair_t &kv) {
return false; }
127 void setup_hash(std::map<int, HashCol> &,
HashTable ht, gress_t,
int stage, value_t &,
128 int lineno,
int lo,
int hi);
130 std::map<int, std::pair<const Input &, int>> tcam_use;
131 std::set<InputXbar *> ixbars_added;
134 int tcam_input_use(
int out_byte,
int phv_byte,
int phv_size);
136 void gen_hash_column(std::pair<const int, HashCol> &col,
137 std::pair<
const HashTable, std::map<int, HashCol>> &hash);
141 const std::vector<InputXbar *> &use;
142 GroupSet(
const std::vector<InputXbar *> &u,
Group g) : group(g), use(u) {}
144 void dbprint(std::ostream &)
const;
146 std::vector<const Input *> find_all(
Phv::Slice sl)
const;
149 InputXbar() =
delete;
150 InputXbar(
const InputXbar &) =
delete;
151 void input(
Table *table,
bool ternary,
const VECTOR(
pair_t) & data);
152 InputXbar(
Table *table,
int lineno) : table(table), lineno(lineno) {}
156 int random_seed = -1;
157 static std::unique_ptr<InputXbar> create(
Table *table,
const value_t *key =
nullptr);
158 static std::unique_ptr<InputXbar> create(
Table *table,
bool tern,
const value_t &key,
159 const VECTOR(
pair_t) & data);
161 virtual void pass2();
162 template <
class REGS>
163 void write_regs(REGS ®s);
164 template <
class REGS>
165 void write_xmu_regs(REGS ®s);
166 template <
class REGS>
167 void write_galois_matrix(REGS ®s, HashTable
id,
const std::map<int, HashCol> &mat);
168 bool have_exact()
const {
169 for (
auto &grp : groups)
170 if (grp.first.type == Group::EXACT)
return true;
173 bool have_ternary()
const {
174 for (
auto &grp : groups)
175 if (grp.first.type != Group::EXACT)
return true;
178 int hash_group()
const {
180 if (hash_groups.size() != 1)
return -1;
181 return hash_groups.begin()->first;
183 bitvec hash_group_bituse(
int grp = -1)
const;
184 std::vector<const HashCol *> hash_column(
int col,
int grp = -1)
const;
187 if (groups.size() != 1 || groups.begin()->first.type != Group::EXACT)
return -1;
188 return groups.begin()->first.index;
192 unsigned tcam_width();
193 int tcam_byte_group(
int n);
194 int tcam_word_group(
int n);
195 std::map<HashTable, std::map<int, HashCol>> &get_hash_tables() {
return hash_tables; }
196 const std::map<int, HashCol> &get_hash_table(
HashTable id);
197 const std::map<int, HashCol> &get_hash_table(
unsigned id = 0) {
198 return get_hash_table(
HashTable(HashTable::EXACT,
id));
203 BUG_CHECK(ht.type == HashTable::EXACT,
"not an exact hash table");
204 return Group(Group::EXACT, ht.index / 2);
206 virtual Phv::Ref get_hashtable_bit(
HashTable id,
unsigned bit)
const {
207 BUG_CHECK(
id.type == HashTable::EXACT,
"not an exact hash table");
208 return get_group_bit(
Group(Group::EXACT,
id.index / 2), bit + 64 * (
id.index & 0x1));
210 Phv::Ref get_hashtable_bit(
unsigned id,
unsigned bit)
const {
211 return get_hashtable_bit(
HashTable(HashTable::EXACT,
id), bit);
213 Phv::Ref get_group_bit(
Group grp,
unsigned bit)
const {
214 if (groups.count(grp))
215 for (
auto &in : groups.at(grp))
216 if (bit >=
unsigned(in.lo) && bit <=
unsigned(in.hi))
217 return Phv::Ref(in.what, bit - in.lo, bit - in.lo);
220 std::string get_field_name(
int bit) {
221 for (
auto &g : groups) {
222 for (
auto &p : g.second) {
223 if (bit <= p.hi && bit >= p.lo)
return p.what.name();
228 bool is_p4_param_bit_in_hash(std::string p4_param_name,
unsigned bit) {
229 for (
auto &g : groups) {
230 for (
auto &p : g.second) {
231 std::string phv_field_name = p.what.name();
232 auto phv_field_lobit = remove_name_tail_range(phv_field_name);
233 phv_field_lobit += p.what.fieldlobit();
234 auto phv_field_hibit = phv_field_lobit + p.size() - 1;
235 if (p4_param_name == phv_field_name && bit <= phv_field_hibit &&
236 bit >= phv_field_lobit)
242 unsigned get_seed_bit(
unsigned group,
unsigned bit)
const {
243 if (hash_groups.count(group))
return ((hash_groups.at(group).seed >> bit) & 0x1);
246 HashGrp *get_hash_group(
unsigned group = -1) { return ::getref(hash_groups, group); }
247 HashGrp *get_hash_group_from_hash_table(
int hash_table) {
248 if (hash_table < 0 || hash_table >= Target::EXACT_HASH_TABLES())
return nullptr;
249 for (
auto &hg : hash_groups) {
250 if (hg.second.tables & (1U << hash_table))
return &hg.second;
254 bool log_hashes(std::ofstream &out)
const;
255 virtual unsigned exact_physical_ids()
const {
return -1; }
260 std::vector<Input>::const_iterator inner;
261 void mk_inner_valid() {
263 if (outer == outer_end)
return;
264 inner = outer->second.begin();
266 while (inner == outer->second.end()) {
267 if (++outer == outer_end)
return;
268 inner = outer->second.begin();
272 struct iter_deref :
public std::pair<Group, const Input &> {
273 explicit iter_deref(
const std::pair<Group, const Input &> &a)
274 : std::pair<Group, const Input &>(a) {}
275 iter_deref *operator->() {
return this; }
280 : outer(o), outer_end(oend), inner_valid(
false) {
283 bool operator==(
const all_iter &a)
const {
284 if (outer != a.outer)
return false;
285 if (inner_valid != a.inner_valid)
return false;
286 return inner_valid ? inner == a.inner :
true;
288 all_iter &operator++() {
289 if (inner_valid && ++inner == outer->second.end()) {
296 std::pair<Group, const Input &> operator*() {
297 return std::pair<Group, const Input &>(outer->first, *inner);
299 iter_deref operator->() {
return iter_deref(**
this); }
302 all_iter end()
const {
return all_iter(groups.end(), groups.end()); }
304 const Input *find(Phv::Slice sl,
Group grp,
Group *found =
nullptr)
const;
305 const Input *find_exact(Phv::Slice sl,
int group)
const {
306 return find(sl,
Group(Group::EXACT, group));
308 virtual int find_offset(
const MatchSource *,
Group grp,
int offset)
const;
309 int find_gateway_offset(
const MatchSource *ms,
int offset)
const {
310 return find_offset(ms,
Group(Group::GATEWAY, 0), offset);
312 int find_match_offset(
const MatchSource *ms,
int offset = -1)
const {
313 return find_offset(ms,
Group(Group::EXACT, -1), offset);
316 std::vector<const Input *> find_all(Phv::Slice sl,
Group grp)
const;
318 virtual int global_bit_position_adjust(
HashTable ht)
const {
319 BUG_CHECK(ht.type == HashTable::EXACT,
"not an exact hash table");
320 return (ht.index / 2) * 128;
322 virtual bitvec global_column0_extract(
323 HashTable ht,
const hash_column_t matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN])
const {
324 BUG_CHECK(ht.type == HashTable::EXACT,
"not an exact hash table");
325 return bitvec(matrix[ht.index][0].column_value);
327 virtual void setup_match_key_cfg(
const MatchSource *) {}