P4C
The P4 Compiler
Loading...
Searching...
No Matches
bf-asm/input_xbar.h
1
17
18#ifndef BACKENDS_TOFINO_BF_ASM_INPUT_XBAR_H_
19#define BACKENDS_TOFINO_BF_ASM_INPUT_XBAR_H_
20
21#include <fstream>
22
23#include "backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h"
24#include "constants.h"
25#include "lib/ordered_map.h"
26#include "phv.h"
27
28class Table;
29class HashExpr;
30
31struct HashCol {
32 int lineno = -1;
33 HashExpr *fn = 0;
34 int bit = 0;
35 bitvec data;
36 unsigned valid = 0; // Used only in Tofino
37 void dbprint(std::ostream &out) const;
38};
39
40inline std::ostream &operator<<(std::ostream &out, HashCol &col) {
41 col.dbprint(out);
42 return out;
43}
44
45struct DynamicIXbar {
46 int bit = -1;
47 std::vector<std::pair<Phv::Ref, match_t>> match_phv;
48 match_t match;
49
50 DynamicIXbar() = default;
51 DynamicIXbar(const DynamicIXbar &) = default;
52 DynamicIXbar(DynamicIXbar &&) = default;
53 DynamicIXbar &operator=(const DynamicIXbar &) = default;
54 DynamicIXbar &operator=(DynamicIXbar &&) = default;
55 DynamicIXbar(const Table *, const pair_t &);
56};
57
58class InputXbar {
59 public:
60 struct Group {
61 short index;
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;
69 }
70 };
71 struct HashTable {
72 short 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;
80 }
81 std::string toString() const;
82 unsigned uid() const;
83 };
84
85 protected:
86 struct Input {
87 Phv::Ref what;
88 int lo, hi;
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; }
93 };
94 struct HashGrp {
95 int lineno = -1;
96 unsigned tables = 0; // Bit set for table index
97 uint64_t seed = 0;
98 bool seed_parity = false; // Parity to be set on the seed value
99 };
100 Table *table;
102 std::map<HashTable, std::map<int, HashCol>> hash_tables;
103 // Map of hash table index to parity bit set on the table
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);
108 static bool conflict(const HashGrp &a, const HashGrp &b);
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));
114 }
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;
132 };
133 virtual void check_input(Group group, Input &input, TcamUseCache &tcam_use);
134 int tcam_input_use(int out_byte, int phv_byte, int phv_size);
135 void tcam_update_use(TcamUseCache &use);
136 void gen_hash_column(std::pair<const int, HashCol> &col,
137 std::pair<const HashTable, std::map<int, HashCol>> &hash);
138
139 struct GroupSet : public IHasDbPrint {
140 Group group;
141 const std::vector<InputXbar *> &use;
142 GroupSet(const std::vector<InputXbar *> &u, Group g) : group(g), use(u) {}
143 GroupSet(ordered_map<Group, std::vector<InputXbar *>> &u, Group g) : group(g), use(u[g]) {}
144 void dbprint(std::ostream &) const;
145 const Input *find(Phv::Slice sl) const;
146 std::vector<const Input *> find_all(Phv::Slice sl) const;
147 };
148
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) {}
153
154 public:
155 const int 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);
160 void pass1();
161 virtual void pass2();
162 template <class REGS>
163 void write_regs(REGS &regs);
164 template <class REGS>
165 void write_xmu_regs(REGS &regs);
166 template <class REGS>
167 void write_galois_matrix(REGS &regs, 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;
171 return false;
172 }
173 bool have_ternary() const {
174 for (auto &grp : groups)
175 if (grp.first.type != Group::EXACT) return true;
176 return false;
177 }
178 int hash_group() const {
179 /* used by gateways to get the associated hash group */
180 if (hash_groups.size() != 1) return -1;
181 return hash_groups.begin()->first;
182 }
183 bitvec hash_group_bituse(int grp = -1) const;
184 std::vector<const HashCol *> hash_column(int col, int grp = -1) const;
185 int match_group() {
186 /* used by gateways and stateful to get the associated match group */
187 if (groups.size() != 1 || groups.begin()->first.type != Group::EXACT) return -1;
188 return groups.begin()->first.index;
189 }
190 bitvec bytemask();
191 /* functions for tcam ixbar that take into account funny byte/word group stuff */
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));
199 }
200
201 // which Group provides the input for a given HashTable
202 virtual Group hashtable_input_group(HashTable ht) const {
203 BUG_CHECK(ht.type == HashTable::EXACT, "not an exact hash table");
204 return Group(Group::EXACT, ht.index / 2);
205 }
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));
209 }
210 Phv::Ref get_hashtable_bit(unsigned id, unsigned bit) const {
211 return get_hashtable_bit(HashTable(HashTable::EXACT, id), bit);
212 }
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);
218 return Phv::Ref();
219 }
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();
224 }
225 }
226 return "";
227 }
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)
237 return true;
238 }
239 }
240 return false;
241 }
242 unsigned get_seed_bit(unsigned group, unsigned bit) const {
243 if (hash_groups.count(group)) return ((hash_groups.at(group).seed >> bit) & 0x1);
244 return 0;
245 }
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;
251 }
252 return nullptr;
253 }
254 bool log_hashes(std::ofstream &out) const;
255 virtual unsigned exact_physical_ids() const { return -1; }
256
257 class all_iter {
258 decltype(groups)::const_iterator outer, outer_end;
259 bool inner_valid;
260 std::vector<Input>::const_iterator inner;
261 void mk_inner_valid() {
262 if (!inner_valid) {
263 if (outer == outer_end) return;
264 inner = outer->second.begin();
265 }
266 while (inner == outer->second.end()) {
267 if (++outer == outer_end) return;
268 inner = outer->second.begin();
269 }
270 inner_valid = true;
271 }
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; }
276 };
277
278 public:
279 all_iter(decltype(groups)::const_iterator o, decltype(groups)::const_iterator oend)
280 : outer(o), outer_end(oend), inner_valid(false) {
281 mk_inner_valid();
282 }
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;
287 }
288 all_iter &operator++() {
289 if (inner_valid && ++inner == outer->second.end()) {
290 ++outer;
291 inner_valid = false;
292 mk_inner_valid();
293 }
294 return *this;
295 }
296 std::pair<Group, const Input &> operator*() {
297 return std::pair<Group, const Input &>(outer->first, *inner);
298 }
299 iter_deref operator->() { return iter_deref(**this); }
300 };
301 all_iter begin() const { return all_iter(groups.begin(), groups.end()); }
302 all_iter end() const { return all_iter(groups.end(), groups.end()); }
303
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));
307 }
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);
311 }
312 int find_match_offset(const MatchSource *ms, int offset = -1) const {
313 return find_offset(ms, Group(Group::EXACT, -1), offset);
314 }
315
316 std::vector<const Input *> find_all(Phv::Slice sl, Group grp) const;
317 virtual std::vector<const Input *> find_hash_inputs(Phv::Slice sl, HashTable ht) 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;
321 }
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);
326 }
327 virtual void setup_match_key_cfg(const MatchSource *) {} // noop for tofino1/2
328};
329
330inline std::ostream &operator<<(std::ostream &out, InputXbar::Group gr) {
331 switch (gr.type) {
332 case InputXbar::Group::EXACT:
333 out << "exact";
334 break;
335 case InputXbar::Group::TERNARY:
336 out << "ternary";
337 break;
338 case InputXbar::Group::BYTE:
339 out << "byte";
340 break;
341 case InputXbar::Group::GATEWAY:
342 out << "gateway";
343 break;
344 case InputXbar::Group::XCMP:
345 out << "xcmp";
346 break;
347 default:
348 out << "<type=" << static_cast<int>(gr.type) << ">";
349 }
350 return out << " ixbar group " << gr.index;
351}
352
353inline std::ostream &operator<<(std::ostream &out, InputXbar::HashTable ht) {
354 switch (ht.type) {
355 case InputXbar::HashTable::EXACT:
356 out << "exact";
357 break;
358 case InputXbar::HashTable::XCMP:
359 out << "xcmp";
360 break;
361 default:
362 out << "<type=" << static_cast<int>(ht.type) << ">";
363 }
364 return out << " hashtable " << ht.index;
365}
366
367#endif /* BACKENDS_TOFINO_BF_ASM_INPUT_XBAR_H_ */
Definition hashexpr.h:25
Definition bf-asm/input_xbar.h:257
virtual std::vector< const Input * > find_hash_inputs(Phv::Slice sl, HashTable ht) const
Definition bf-asm/input_xbar.cpp:1020
Definition bf-asm/input_xbar.h:94
Definition bf-asm/input_xbar.h:129
Definition stringify.h:33
Definition bitvec.h:120
Definition ordered_map.h:32
Definition bf-asm/phv.h:186
Definition bf-asm/phv.h:83
Definition tables.h:98
Definition bf-asm/input_xbar.h:31
void dbprint(std::ostream &out) const
Definition bf-asm/input_xbar.cpp:37
Definition bf-asm/input_xbar.h:60
Definition bf-asm/input_xbar.h:71
Definition bf-asm/input_xbar.h:86
Definition match.h:36
Definition asm-types.h:150
Definition asm-types.h:114