18#ifndef BACKENDS_TOFINO_BF_ASM_TABLES_H_
19#define BACKENDS_TOFINO_BF_ASM_TABLES_H_
24#include <unordered_map>
27#include "backends/tofino/bf-asm/alloc.h"
28#include "backends/tofino/bf-asm/asm-types.h"
29#include "backends/tofino/bf-asm/config.h"
30#include "backends/tofino/bf-asm/json.h"
31#include "backends/tofino/bf-asm/map.h"
32#include "backends/tofino/bf-asm/p4_table.h"
33#include "backends/tofino/bf-asm/phv.h"
34#include "backends/tofino/bf-asm/slist.h"
35#include "backends/tofino/bf-asm/target.h"
38#include "input_xbar.h"
39#include "lib/algorithm.h"
40#include "lib/bitops.h"
41#include "lib/bitvec.h"
42#include "lib/ordered_map.h"
61struct RandomNumberGen {
63 explicit RandomNumberGen(
int u) : unit(u) {}
64 bool operator==(
const RandomNumberGen &a)
const {
return unit == a.unit; }
67enum class TableOutputModifier { NONE, Color, Address };
68std::ostream &operator<<(std::ostream &, TableOutputModifier);
77 MemUnit(
const MemUnit &) =
default;
78 MemUnit(MemUnit &&) =
default;
79 MemUnit &operator=(
const MemUnit &) =
default;
80 MemUnit &operator=(MemUnit &&) =
default;
82 explicit MemUnit(
int unit) : col(unit) {}
83 MemUnit(
int r,
int c) : row(r), col(c) {}
84 MemUnit(
int s,
int r,
int c) : stage(s), row(r), col(c) {}
85 bool operator==(
const MemUnit &a)
const {
86 return std::tie(stage, row, col) == std::tie(a.stage, a.row, a.col);
88 bool operator!=(
const MemUnit &a)
const {
89 return std::tie(stage, row, col) != std::tie(a.stage, a.row, a.col);
91 bool operator<(
const MemUnit &a)
const {
92 return std::tie(stage, row, col) < std::tie(a.stage, a.row, a.col);
94 virtual const char *
desc()
const;
95 friend std::ostream &operator<<(std::ostream &out,
const MemUnit &m) {
return out << m.
desc(); }
111 enum bus_type_t { SEARCH_BUS, RESULT_BUS, TIND_BUS, IDLE_BUS, L2R_BUS, R2L_BUS };
112 std::map<bus_type_t, int> bus;
115 bool home_row =
false;
116 std::vector<MemUnit> memunits;
117 std::vector<int> vpns, maprams;
119 Layout(
int l,
int r) : lineno(l), row(r) {}
120 friend std::ostream &operator<<(std::ostream &,
const Layout &);
122 bool word_initialized()
const {
return word >= 0; }
123 bool operator==(
const Layout &)
const;
124 bool operator!=(
const Layout &a)
const {
return !(*
this == a); }
128 Table(
int line, std::string &&n, gress_t gr,
Stage *s,
131 Table(
const Table &) =
delete;
132 Table(Table &&) =
delete;
133 virtual void setup(VECTOR(
pair_t) & data) = 0;
134 virtual void common_init_setup(
const VECTOR(
pair_t) &,
bool, P4Table::type);
135 virtual bool common_setup(
pair_t &,
const VECTOR(
pair_t) &, P4Table::type);
136 void setup_context_json(
value_t &);
137 void setup_layout(std::vector<Layout> &,
const VECTOR(
pair_t) & data,
const char *subname =
"");
138 int setup_layout_bus_attrib(std::vector<Layout> &,
const value_t &data,
const char *what,
139 Layout::bus_type_t type);
140 int setup_layout_attrib(std::vector<Layout> &,
const value_t &data,
const char *what,
142 void setup_logical_id();
145 void setup_vpns(std::vector<Layout> &, VECTOR(
value_t) *,
bool allow_holes =
false);
146 virtual void vpn_params(
int &width,
int &depth,
int &period,
const char *&period_name)
const {
149 virtual int get_start_vpn() {
return 0; }
150 void alloc_rams(
bool logical, BFN::Alloc2Dbase<Table *> &use,
151 BFN::Alloc2Dbase<Table *> *bus_use = 0,
152 Layout::bus_type_t bus_type = Layout::SEARCH_BUS);
153 void alloc_global_bus(
Layout &, Layout::bus_type_t,
int,
int,
int,
int);
154 virtual void alloc_global_busses();
155 void alloc_global_srams();
156 void alloc_global_tcams();
157 void alloc_busses(BFN::Alloc2Dbase<Table *> &bus_use, Layout::bus_type_t bus_type);
158 void alloc_id(
const char *idname,
int &
id,
int &next_id,
int max_id,
bool order,
159 BFN::Alloc1Dbase<Table *> &use);
160 void alloc_maprams();
161 virtual void alloc_vpns();
162 virtual Layout::bus_type_t default_bus_type()
const {
return Layout::SEARCH_BUS; }
163 void need_bus(
int lineno, BFN::Alloc1Dbase<Table *> &use,
int idx,
const char *name);
168 static std::map<std::string, Type *> *all;
169 std::map<std::string, Type *>::iterator self;
172 explicit Type(std::string &&);
173 explicit Type(
const char *name) : Type(std::string(name)) {}
177 static Type *get(
const char *name) { return ::get(all, name); }
178 static Type *get(
const std::string &name) { return ::get(all, name); }
179 virtual Table *create(
int lineno,
const char *name, gress_t gress,
Stage *stage,
int lid,
180 VECTOR(
pair_t) & data) = 0;
186 Ref() : lineno(-1) {}
187 Ref(
const Ref &) =
default;
188 Ref(Ref &&) =
default;
189 Ref &operator=(
const Ref &a) & {
191 if (lineno < 0) lineno = a.lineno;
194 Ref &operator=(Ref &&a) & {
196 if (lineno < 0) lineno = a.lineno;
199 Ref &operator=(
const value_t &a) & {
200 BUG_CHECK(a.type == tSTR,
"expected string");
205 Ref(
const std::string &n) : lineno(-1), name(n) {}
206 Ref(
const char *n) : lineno(-1), name(n) {}
207 Ref(
const value_t &a) : lineno(a.lineno) {
208 if (CHECKTYPE(a, tSTR)) name = a.s;
210 Ref &operator=(
const std::string &n) {
214 operator bool()
const {
return all && all->count(name) > 0; }
215 operator Table *()
const { return ::get(all, name); }
216 Table *operator->()
const { return ::get(all, name); }
217 [[nodiscard]]
bool set()
const {
return lineno >= 0; }
218 bool operator==(
const Table &t)
const {
return name == t.name_; }
219 bool operator!=(
const Table &t)
const {
return name != t.name_; }
220 bool operator==(
const Ref &a)
const {
return name == a.name; }
221 bool operator!=(
const Ref &a)
const {
return name != a.name; }
222 bool operator<(
const Ref &a)
const {
return name < a.name; }
224 if (set() && !*
this)
error(lineno,
"No table named %s", name.c_str());
231 unsigned lb_tags = 0;
232 const Table *next_table_ =
nullptr;
233 bool resolved =
false;
234 bool can_use_lb(
int stage,
const NextTables &);
238 NextTables() =
default;
239 NextTables(
const NextTables &) =
default;
240 NextTables(NextTables &&) =
default;
241 NextTables &operator=(
const NextTables &a) =
default;
242 NextTables &operator=(NextTables &&) =
default;
245 std::set<Ref>::iterator begin()
const {
return next.begin(); }
246 std::set<Ref>::iterator end()
const {
return next.end(); }
247 int size()
const {
return next.size(); }
248 bool operator==(
const NextTables &a)
const {
return next == a.next; }
249 bool subset_of(
const NextTables &a)
const {
251 if (!a.next.count(n))
return false;
254 void resolve_long_branch(
const Table *tbl,
const std::map<int, NextTables> &lbrch);
255 bool set()
const {
return lineno >= 0; }
256 int next_table_id()
const {
257 BUG_CHECK(resolved,
"next table not resolved");
258 return next_table_ ? next_table_->table_id() : Target::END_OF_PIPE();
260 std::string next_table_name()
const {
261 BUG_CHECK(resolved,
"next table not resolved");
263 if (
auto nxt_p4_name = next_table_->p4_name())
return nxt_p4_name;
267 const Table *next_table()
const {
return next_table_; }
268 unsigned long_branch_tags()
const {
return lb_tags; }
269 unsigned next_in_stage(
int stage)
const;
270 bool need_next_map_lut()
const;
271 void force_single_next_table();
278 bitrange_t(
unsigned l,
unsigned h) : lo(l), hi(h) {}
279 bool operator==(
const bitrange_t &a)
const {
return lo == a.lo && hi == a.hi; }
280 bool disjoint(
const bitrange_t &a)
const {
return lo > a.hi || a.lo > hi; }
281 bitrange_t overlap(
const bitrange_t &a)
const {
283 return bitrange_t(std::max(lo, a.lo), std::min(hi, a.hi));
285 int size()
const {
return hi - lo + 1; }
288 unsigned size = 0, group = 0, flags = 0;
289 std::vector<bitrange_t> bits;
290 Field **by_group = 0;
292 bool operator==(
const Field &a)
const {
return size == a.size; }
294 unsigned bit(
unsigned i) {
296 for (
auto &chunk : bits) {
297 if (i < (
unsigned)chunk.size())
return chunk.lo + i;
301 if (i == 0)
return last;
307 unsigned immed_bit(
unsigned i) {
309 if (fmt && fmt->immed) rv -= fmt->immed->by_group[group]->bit(0);
312 unsigned hi(
unsigned bit) {
313 for (
auto &chunk : bits)
314 if (bit >= chunk.lo && bit <= chunk.hi)
return chunk.hi;
318 enum flags_t { NONE = 0, USED_IMMED = 1, ZERO = 3 };
319 bool conditional_value =
false;
320 std::string condition;
321 explicit Field(Format *f) : fmt(f) {}
322 Field(Format *f,
unsigned size,
unsigned lo = 0,
enum flags_t fl = NONE)
323 : size(size), flags(fl), fmt(f) {
324 if (size) bits.push_back({lo, lo + size - 1});
326 Field(
const Field &f, Format *fmt)
327 : size(f.size), flags(f.flags), bits(f.bits), fmt(fmt) {}
331 for (
auto &b : bits) bitset.setrange(b.lo, b.size());
334 friend std::ostream &operator<<(std::ostream &,
const Field &);
335 explicit Format(Table *t) : tbl(t) { fmt.resize(1); }
336 Format(
Table *,
const VECTOR(
pair_t) & data,
bool may_overlap =
false);
338 void pass1(
Table *tbl);
339 void pass2(
Table *tbl);
342 std::vector<ordered_map<std::string, Field>> fmt;
343 std::map<unsigned, ordered_map<std::string, Field>::iterator> byindex;
350 unsigned size = 0, immed_size = 0;
352 unsigned log2size = 0;
353 unsigned overhead_start = 0, overhead_size = 0;
354 int overhead_word = -1;
356 unsigned groups()
const {
return fmt.size(); }
357 const ordered_map<std::string, Field> &group(
int g)
const {
return fmt.at(g); }
358 Field *field(
const std::string &n,
int group = 0) {
359 BUG_CHECK(group >= 0 && (
size_t)group < fmt.size(),
"invalid group %d", group);
360 auto it = fmt[group].find(n);
361 if (it != fmt[group].end())
return &it->second;
364 void apply_to_field(
const std::string &n, std::function<
void(
Field *)> fn) {
365 for (
auto &m : fmt) {
367 if (it != m.end()) fn(&it->second);
370 std::string find_field(
Field *field) {
373 if (field == &f.second)
return f.first;
376 int find_field_lineno(
Field *field) {
379 if (field == &f.second)
return lineno;
382 void add_field(
Field &f, std::string name =
"dummy",
int grp = 0) {
383 fmt[grp].emplace(name,
Field(f,
this));
385 decltype(fmt[0].begin()) begin(
int grp = 0) {
return fmt[grp].begin(); }
386 decltype(fmt[0].end()) end(
int grp = 0) {
return fmt[grp].end(); }
387 decltype(fmt[0].cbegin()) begin(
int grp = 0)
const {
return fmt[grp].begin(); }
388 decltype(fmt[0].cend()) end(
int grp = 0)
const {
return fmt[grp].end(); }
389 bool is_wide_format()
const {
return (log2size >= 7 || groups() > 1) ? true :
false; }
390 int get_entries_per_table_word()
const {
392 if (tbl->table_type() == PHASE0)
return 1;
393 if (is_wide_format())
return groups();
394 return log2size ? (1U << (ceil_log2(tbl->ram_word_width()) - log2size)) : 0;
396 int get_mem_units_per_table_word()
const {
397 return is_wide_format() ? ((size - 1) / tbl->ram_word_width()) + 1 : 1;
399 int get_table_word_width()
const {
400 return is_wide_format() ? tbl->ram_word_width() * get_mem_units_per_table_word()
401 : tbl->ram_word_width();
403 int get_padding_format_width()
const {
404 return is_wide_format() ? get_mem_units_per_table_word() * tbl->ram_word_width()
411 enum { Field, HashDist, Counter, Const, Name } type;
421 void set(
const Arg &a) {
444 if (type == Name) str = strdup(str);
450 Arg &operator=(
const Arg &a) {
451 if (&a ==
this)
return *
this;
452 if (a == *
this)
return *
this;
453 if (type == Name) free(str);
455 if (type == Name) str = strdup(a.str);
458 Arg &operator=(Arg &&a) {
459 std::swap(type, a.type);
460 std::swap(val, a.val);
467 Arg(
int v) : type(Const) { val = v; }
468 Arg(
const char *n) : type(Name) { str = strdup(n); }
469 Arg(
decltype(Counter) ctr,
int mode) : type(Counter) {
471 BUG_CHECK(ctr == Counter,
"invalid counter type");
474 if (type == Name) free(str);
476 bool operator==(
const Arg &a)
const {
477 if (type != a.type)
return false;
487 return !strcmp(str, a.str);
489 BUG(
"unknown argument type");
493 bool operator!=(
const Arg &a)
const {
return !operator==(a); }
494 Format::Field *field()
const {
return type == Field ? fld :
nullptr; }
495 HashDistribution *hash_dist()
const {
return type == HashDist ? hd :
nullptr; }
496 const char *name()
const {
return type == Name ? str :
nullptr; }
497 int count_mode()
const {
return type == Counter ? val : 0; }
498 int value()
const {
return type == Const ? val : 0; }
499 operator bool()
const {
return fld !=
nullptr; }
500 unsigned size()
const;
502 std::vector<Arg> args;
503 void setup(
const value_t &v, Table *tbl);
505 Call(
const value_t &v, Table *tbl) { setup(v, tbl); }
506 bool operator==(
const Call &a)
const {
return Ref::operator==(a) && args == a.args; }
507 bool operator!=(
const Call &a)
const {
return !(*
this == a); }
508 bool is_direct_call()
const {
509 if (args.size() == 0)
return false;
511 if (a ==
"$DIRECT")
return true;
519 std::string key_name;
520 unsigned start_bit = 0;
521 unsigned position = 0;
522 unsigned bit_width = 0;
523 unsigned bit_width_full = 0;
525 std::string default_value;
526 bool defaulted =
false;
527 bool is_valid =
false;
529 std::unique_ptr<json::map> context_json;
530 explicit p4_param(std::string n =
"",
unsigned p = 0,
unsigned bw = 0)
531 : name(n), position(p), bit_width(bw) {}
533 friend std::ostream &operator<<(std::ostream &,
const p4_param &);
534 typedef std::vector<p4_param> p4_params;
541 int lineno = -1, lo = -1, hi = -1;
542 bool is_constant =
false;
545 unsigned size()
const {
546 if (hi != -1 && lo != -1)
551 std::string to_string()
const {
552 if (hi >= 0 && lo >= 0)
553 return name +
'(' + std::to_string(lo) +
".." + std::to_string(hi) +
')';
558 std::string rng_param_name =
"";
559 int lineno = -1, addr = -1, code = -1;
560 std::multimap<std::string, alias_t> alias;
561 std::vector<std::unique_ptr<Instruction>> instr;
564 p4_params p4_params_list;
565 bool hit_allowed =
true;
566 bool default_allowed =
false;
567 bool default_only =
false;
568 bool is_constant =
false;
569 std::string hit_disallowed_reason =
"";
570 std::string default_disallowed_reason =
"";
571 std::vector<Call> attached;
572 int next_table_encode = -1;
575 std::map<std::string, std::vector<bitvec>> mod_cond_values;
580 int position_in_assembly = -1;
581 bool minmax_use =
false;
586 int pred_comb_sel = -1;
587 std::unique_ptr<json::map> context_json;
588 Action(Table *, Actions *,
pair_t &,
int);
589 enum mod_cond_loc_t { MC_ADT, MC_IMMED };
591 Action(
const char *n,
int l);
596 bool equivVLIW(
Action *a);
597 typedef const decltype(alias)::value_type alias_value_t;
598 std::map<std::string, std::vector<alias_value_t *>> reverse_alias()
const;
599 std::string alias_lookup(
int lineno, std::string name,
int &lo,
int &hi)
const;
600 bool has_rng() {
return !rng_param_name.empty(); }
601 const p4_param *has_param(std::string param)
const {
602 for (
auto &e : p4_params_list)
603 if (e.name == param)
return &e;
606 void pass1(
Table *tbl);
607 void check_next(
Table *tbl);
609 void add_direct_resources(
json::vector &direct_resources,
const Call &att)
const;
610 void add_indirect_resources(
json::vector &indirect_resources,
const Call &att)
const;
612 bool is_color_aware()
const;
614 void add_p4_params(
json::vector &,
bool include_default =
true)
const;
617 friend std::ostream &operator<<(std::ostream &,
const alias_t &);
618 friend std::ostream &operator<<(std::ostream &,
const Action &);
622 typedef ordered_map<std::string, Action> map_t;
625 std::map<int, Action *> by_code;
631 Actions(Table *tbl, VECTOR(pair_t) &);
632 typedef map_t::value_type value_type;
633 typedef IterValues<map_t::iterator>::iterator iterator;
634 typedef IterValues<map_t::const_iterator>::iterator const_iterator;
635 iterator begin() {
return iterator(actions.begin()); }
636 const_iterator begin()
const {
return const_iterator(actions.begin()); }
637 iterator end() {
return iterator(actions.end()); }
638 const_iterator end()
const {
return const_iterator(actions.end()); }
639 int count() {
return actions.size(); }
640 int hit_actions_count()
const;
641 int default_actions_count()
const;
642 Action *action(
const std::string &n) {
643 auto it = actions.find(n);
644 return it == actions.end() ? nullptr : &it->second;
646 bool exists(
const std::string &n) {
return actions.count(n) > 0; }
649 void stateful_pass2(Table *);
650 template <
class REGS>
651 void write_regs(REGS &, Table *);
652 void add_p4_params(
const Action &, json::vector &)
const;
653 void gen_tbl_cfg(json::vector &)
const;
654 void add_immediate_mapping(json::map &);
656 bool has_hash_dist() {
return (table->table_type() == HASH_ACTION); }
657 size_t size() {
return actions.size(); }
661 const char *name()
const {
return name_.c_str(); }
662 const char *p4_name()
const {
664 return p4_table->p4_name();
668 unsigned p4_size()
const {
670 return p4_table->p4_size();
674 unsigned handle()
const {
676 return p4_table->get_handle();
680 std::string action_profile()
const {
682 return p4_table->action_profile;
686 std::string how_referenced()
const {
688 return p4_table->how_referenced;
692 int table_id()
const;
693 virtual bool is_always_run()
const {
return false; }
694 virtual void pass0() {}
695 virtual void pass1();
696 virtual void pass2() = 0;
697 virtual void pass3() = 0;
700 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
virtual void write_action_regs,
702 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
virtual void write_merge_regs,
703 (mau_regs &,
int type,
int bus), { assert(0); })
704 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
virtual void write_merge_regs,
705 (mau_regs &, MatchTable *match,
int type,
int bus,
706 const std::vector<Call::Arg> &args),
708 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
virtual void write_regs, (mau_regs &), = 0)
710 virtual
void gen_tbl_cfg(json::vector &out) const = 0;
711 virtual json::map *base_tbl_cfg(json::vector &out, const
char *type,
int size) const;
712 virtual json::map *add_stage_tbl_cfg(json::map &tbl, const
char *type,
int size) const;
713 virtual std::unique_ptr<json::map> gen_memory_resource_allocation_tbl_cfg(
714 const
char *type, const std::vector<
Layout> &layout,
bool skip_spare_bank = false) const;
715 virtual std::vector<
int> determine_spare_bank_memory_units()
const {
return {}; }
716 virtual void common_tbl_cfg(json::map &tbl)
const;
717 void add_match_key_cfg(json::map &tbl)
const;
718 bool add_json_node_to_table(json::map &tbl,
const char *name,
bool append =
false)
const;
719 void allocate_physical_ids(
unsigned usable = ~0U);
720 template <
typename T>
721 void init_json_node(json::map &tbl,
const char *name)
const;
739 virtual table_type_t table_type()
const {
return OTHER; }
740 virtual int instruction_set() {
return 0; }
741 virtual table_type_t set_match_table(MatchTable *m,
bool indirect) {
745 virtual const MatchTable *get_match_table()
const {
749 virtual MatchTable *get_match_table() {
753 virtual std::set<MatchTable *> get_match_tables() {
return std::set<MatchTable *>(); }
754 virtual const AttachedTables *get_attached()
const {
return 0; }
755 virtual AttachedTables *get_attached() {
return 0; }
756 virtual const GatewayTable *get_gateway()
const {
return 0; }
757 virtual SelectionTable *get_selector()
const {
return 0; }
758 virtual MeterTable *get_meter()
const {
return 0; }
759 virtual void set_stateful(StatefulTable *s) { BUG(
"unsupported"); }
760 virtual StatefulTable *get_stateful()
const {
return 0; }
761 virtual void set_address_used() {
764 "Tofino does not support extracting the address used on "
765 "a non-stateful table %s",
768 virtual void set_color_used() {
769 error(lineno,
"Cannot extract color on a non-meter table %s", name());
771 virtual void set_output_used() {
772 error(lineno,
"Cannot extract output on a non-stateful table %s", name());
774 virtual const Call &get_action()
const {
return action; }
775 virtual std::vector<Call> get_calls()
const;
776 virtual bool is_attached(
const Table *)
const {
780 virtual Format::Field *find_address_field(
const AttachedTable *)
const {
784 virtual Format::Field *get_per_flow_enable_param(MatchTable *)
const {
788 virtual Format::Field *get_meter_address_param(MatchTable *)
const {
792 virtual Format::Field *get_meter_type_param(MatchTable *)
const {
796 virtual int direct_shiftcount()
const {
800 virtual int indirect_shiftcount()
const {
804 virtual int address_shift()
const {
808 virtual int home_row()
const {
813 virtual int json_memunit(
const MemUnit &u)
const;
814 virtual int ram_word_width()
const {
return MEM_WORD_WIDTH; }
815 virtual int unitram_type() {
819 virtual bool uses_colormaprams()
const {
return false; }
820 virtual int color_shiftcount(Table::Call &call,
int group,
int tcam_shift)
const {
824 virtual bool adr_mux_select_stats() {
return false; }
825 virtual bool run_at_eop() {
return false; }
826 virtual Format *get_format()
const {
return format.get(); }
827 virtual unsigned determine_shiftcount(Table::Call &call,
int group,
unsigned word,
828 int tcam_shift)
const {
832 template <
class REGS>
833 void write_mapram_regs(REGS ®s,
int row,
int col,
int vpn,
int type);
836 return dynamic_cast<T *
>(
this);
839 const T *to()
const {
840 return dynamic_cast<const T *
>(
this);
842 virtual void determine_word_and_result_bus() { BUG(
"unsupported"); }
843 virtual int stm_vbus_column()
const { BUG(
"unsupported"); }
847 P4Table *p4_table = 0;
853 std::vector<DynamicIXbar> dynamic_config;
854 std::vector<std::unique_ptr<InputXbar>> input_xbar;
855 std::vector<Layout> layout;
856 bool no_vpns =
false;
858 std::unique_ptr<Format> format;
859 int action_enable = -1;
860 bool enable_action_data_enable =
false;
861 bool enable_action_instruction_enable =
false;
864 std::unique_ptr<Actions> actions;
865 std::unique_ptr<ActionBus> action_bus;
866 std::string default_action;
867 unsigned default_action_handle = 0;
868 int default_action_lineno = -1;
869 typedef std::map<std::string, std::string> default_action_params;
870 default_action_params default_action_parameters;
871 bool default_only_action =
false;
872 std::vector<NextTables> hit_next;
873 std::vector<NextTables> extra_next_lut;
879 std::map<int, NextTables> long_branch;
880 int long_branch_input = -1;
881 std::map<Table *, std::set<Actions::Action *>> pred;
883 std::vector<HashDistribution> hash_dist;
884 p4_params p4_params_list;
885 std::unique_ptr<json::map> context_json;
887 unsigned next_table_adr_mask = 0U;
888 bitvec reachable_tables_;
890 static std::map<std::string, Table *> *all;
891 static std::vector<Table *> *by_uid;
893 unsigned layout_size()
const {
895 for (
auto &row : layout) rv += row.memunits.size();
898 unsigned layout_get_vpn(
const MemUnit &m)
const {
899 for (
auto &row : layout) {
900 if (row.row != m.row)
continue;
901 auto u = find(row.memunits.begin(), row.memunits.end(), m);
902 if (u == row.memunits.end())
continue;
903 return row.vpns.at(u - row.memunits.begin());
908 void layout_vpn_bounds(
int &min,
int &max,
bool spare =
false)
const {
911 for (
const Layout &row : layout)
912 for (
const auto v : row.vpns) {
913 if (v < min) min = v;
914 if (v > max) max = v;
916 if (spare && max > min) --max;
918 virtual Format::Field *lookup_field(
const std::string &n,
const std::string &act =
"")
const {
919 return format ? format->field(n) : 0;
922 return format ? format->find_field(field) :
"<unknown>";
925 return format ? format->find_field_lineno(field) : -1;
927 virtual void apply_to_field(
const std::string &n, std::function<
void(
Format::Field *)> fn) {
928 if (format) format->apply_to_field(n, fn);
930 int find_on_ixbar(Phv::Slice sl, InputXbar::Group group, InputXbar::Group *found =
nullptr);
931 int find_on_ixbar(Phv::Slice sl,
int group) {
932 return find_on_ixbar(sl, InputXbar::Group(InputXbar::Group::EXACT, group));
934 virtual HashDistribution *find_hash_dist(
int unit);
935 virtual int find_on_actionbus(
const ActionBusSource &src,
int lo,
int hi,
int size,
937 virtual void need_on_actionbus(
const ActionBusSource &src,
int lo,
int hi,
int size);
938 virtual int find_on_actionbus(
const char *n, TableOutputModifier mod,
int lo,
int hi,
int size,
940 int find_on_actionbus(
const char *n,
int lo,
int hi,
int size,
int *len = 0) {
941 return find_on_actionbus(n, TableOutputModifier::NONE, lo, hi, size, len);
943 int find_on_actionbus(
const std::string &n, TableOutputModifier mod,
int lo,
int hi,
int size,
945 return find_on_actionbus(n.c_str(), mod, lo, hi, size, len);
947 int find_on_actionbus(
const std::string &n,
int lo,
int hi,
int size,
int *len = 0) {
948 return find_on_actionbus(n.c_str(), TableOutputModifier::NONE, lo, hi, size, len);
950 virtual void need_on_actionbus(Table *att, TableOutputModifier mod,
int lo,
int hi,
int size);
952 virtual Call &action_call() {
return action; }
953 virtual Call &instruction_call() {
return instruction; }
954 virtual Actions *get_actions()
const {
return actions.get(); }
955 virtual const std::vector<NextTables> &get_hit_next()
const {
return hit_next; }
956 virtual const NextTables &get_miss_next()
const {
return miss_next; }
957 virtual bool is_directly_referenced(
const Table::Call &c)
const;
959 json::map &add_pack_format(json::map &stage_tbl,
int memword,
int words,
960 int entries = -1)
const;
961 json::map &add_pack_format(json::map &stage_tbl, Table::Format *format,
bool pad_zeros =
true,
962 bool print_fields =
true,
963 Table::Actions::Action *act =
nullptr)
const;
965 std::string name,
const Table::Format::Field &field,
966 const Table::Actions::Action *act)
const;
967 virtual bool validate_call(Table::Call &call, MatchTable *self,
size_t required_args,
968 int hash_dist_type, Table::Call &first_call) {
977 void output_field_to_pack_format(json::vector &field_list,
unsigned basebit, std::string name,
978 std::string source,
unsigned start_bit,
979 const Table::Format::Field &field,
unsigned value = 0)
const;
980 void add_zero_padding_fields(Table::Format *format, Table::Actions::Action *act =
nullptr,
981 unsigned format_width = 64)
const;
982 void get_cjson_source(
const std::string &field_name, std::string &source,
int &start_bit)
const;
985 virtual void add_result_physical_buses(json::map &stage_tbl)
const;
986 virtual void merge_context_json(json::map &tbl, json::map &stage_tbl)
const;
987 void canon_field_list(json::vector &field_list)
const;
988 void for_all_next(std::function<
void(
const Ref &)> fn);
989 void check_next(
const Ref &next);
992 virtual void set_pred();
996 std::map<Table *, std::set<Actions::Action *>> find_pred_in_stage(
997 int stageno,
const std::set<Actions::Action *> &acts = std::set<Actions::Action *>());
999 bool choose_logical_id(
const slist<Table *> *work =
nullptr);
1000 virtual int hit_next_size()
const {
return hit_next.size(); }
1001 virtual int get_tcam_id()
const { BUG(
"%s not a TCAM table", name()); }
1003 const std::vector<const p4_param *> find_p4_params(std::string s, std::string t =
"",
1004 int start_bit = -1,
int width = -1)
const {
1005 remove_name_tail_range(s);
1006 std::vector<const p4_param *> params;
1007 if (start_bit <= -1)
return params;
1008 if (width <= -1)
return params;
1009 int end_bit = start_bit + width;
1010 for (
auto &p : p4_params_list) {
1011 if ((p.name == s) || (p.alias == s)) {
1012 int p_end_bit = p.start_bit + p.bit_width;
1013 if (!t.empty() && (p.type != t))
continue;
1014 if (p.start_bit >
static_cast<unsigned>(start_bit))
continue;
1015 if (p_end_bit < end_bit)
continue;
1016 params.push_back(&p);
1022 const p4_param *find_p4_param(std::string s, std::string t =
"",
int start_bit = -1,
1023 int width = -1)
const {
1024 remove_name_tail_range(s);
1025 std::vector<p4_param *> params;
1026 for (
auto &p : p4_params_list) {
1027 if ((p.name == s) || (p.alias == s)) {
1028 if (!t.empty() && (p.type != t))
continue;
1029 if ((start_bit > -1) && (
static_cast<unsigned>(start_bit) < p.start_bit))
continue;
1030 if ((width > -1) && (p.start_bit + p.bit_width < start_bit + width))
continue;
1037 const p4_param *find_p4_param_type(std::string &s)
const {
1038 for (
auto &p : p4_params_list)
1039 if (p.type == s)
return &p;
1042 virtual std::string get_default_action() {
1043 return (!default_action.empty()) ? default_action : action ? action->default_action :
"";
1045 virtual default_action_params *get_default_action_parameters() {
1046 return (!default_action_parameters.empty()) ? &default_action_parameters
1047 : action ? &action->default_action_parameters
1050 virtual unsigned get_default_action_handle()
const {
1051 return default_action_handle > 0 ? default_action_handle
1052 : action ? action->default_action_handle
1055 int get_format_field_size(std::string s)
const {
1056 if (
auto field = lookup_field(s))
return field->size;
1059 virtual bool needs_handle()
const {
return false; }
1060 virtual bool needs_next()
const {
return false; }
1061 virtual bitvec compute_reachable_tables();
1062 bitvec reachable_tables() {
1063 if (!reachable_tables_) reachable_tables_ = compute_reachable_tables();
1064 return reachable_tables_;
1066 std::string loc()
const;
1069std::ostream &operator<<(std::ostream &,
const Table::Layout &);
1070std::ostream &operator<<(std::ostream &,
const Table::Layout::bus_type_t);
1072class FakeTable :
public Table {
1074 explicit FakeTable(
const char *name) : Table(-1, name, INGRESS, 0, -1) {}
1075 void setup(VECTOR(
pair_t) & data)
override { assert(0); }
1076 void pass1()
override { assert(0); }
1077 void pass2()
override { assert(0); }
1078 void pass3()
override { assert(0); }
1079 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_regs, (mau_regs &),
override { assert(0); })
1080 void gen_tbl_cfg(
json::vector &out)
const override { assert(0); }
1083class AlwaysRunTable :
public Table {
1086 AlwaysRunTable(gress_t gress,
Stage *stage,
pair_t &init);
1087 void setup(VECTOR(
pair_t) & data)
override { assert(0); }
1088 void pass1()
override { actions->pass1(
this); }
1089 void pass2()
override { actions->pass2(
this); }
1090 void pass3()
override {}
1091 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_regs, (mau_regs & regs),
override)
1098 std::vector<Table::Call> stats, meters, statefuls;
1100 SelectionTable *get_selector()
const;
1101 MeterTable *get_meter(std::string name =
"")
const;
1102 StatefulTable *get_stateful(std::string name =
"")
const;
1105 bool is_attached(
const Table *tbl)
const {
return get_call(tbl) !=
nullptr; }
1106 void pass0(MatchTable *self);
1107 void pass1(MatchTable *self);
1108 template <
class REGS>
1109 void write_merge_regs(REGS ®s, MatchTable *self,
int type,
int bus);
1110 template <
class REGS>
1111 void write_tcam_merge_regs(REGS ®s, MatchTable *self,
int bus,
int tcam_shift);
1113 bitvec compute_reachable_tables()
const;
1116#define DECLARE_ABSTRACT_TABLE_TYPE(TYPE, PARENT, ...) \
1117 class TYPE : public PARENT { \
1119 TYPE(int l, const char *n, gress_t g, Stage *s, int lid) : PARENT(l, n, g, s, lid) {} \
1124DECLARE_ABSTRACT_TABLE_TYPE(
1127 enum {NONE = 0, TABLE_MISS = 1, TABLE_HIT = 2, DISABLED = 3, GATEWAY_MISS = 4, GATEWAY_HIT = 5,
1128 GATEWAY_INHIBIT = 6} table_counter = NONE;
1130 using Table::pass1;
using Table::write_regs;
1131 template <
class TARGET>
void write_common_regs(
typename TARGET::mau_regs &,
int,
Table *);
1132 template <
class REGS>
void write_regs(REGS &,
int type,
Table *result);
1133 template <
class REGS>
void write_next_table_regs(REGS &,
Table *);
1134 void common_init_setup(
const VECTOR(
pair_t) &,
bool, P4Table::type)
override;
1135 bool common_setup(
pair_t &,
const VECTOR(
pair_t) &, P4Table::type)
override;
1136 int get_address_mau_actiondata_adr_default(
unsigned log2size,
bool per_flow_enable); public
1137 :
bool is_always_run()
const override {
return always_run; }
void pass0()
override;
1138 void pass1()
override;
void pass3()
override;
bool is_alpm()
const {
1140 return p4_table->is_alpm();
1143 }
bool is_attached(
const Table *tbl)
const override;
1145 return get_attached()->get_call(tbl);
1146 }
const AttachedTables *get_attached()
const override {
return &attached; } std::vector<Call>
1147 get_calls()
const override;
1148 AttachedTables * get_attached()
override {
return &attached; } Format *
1149 get_format()
const override;
1150 const GatewayTable *get_gateway()
1151 const override {
return gateway; }
const MatchTable *get_match_table()
const override {
1153 } MatchTable *get_match_table()
override {
return this; } std::set<MatchTable *>
1154 get_match_tables()
override {
1155 std::set<MatchTable *> rv;
1158 } Format::Field *find_address_field(
const AttachedTable *tbl)
const override {
1159 return attached.find_address_field(tbl);
1160 } Format::Field *lookup_field(
const std::string &n,
const std::string &act =
"")
1162 bool run_at_eop()
override {
return attached.run_at_eop(); }
1163 virtual bool is_ternary() {
return false; }
1164 void gen_idletime_tbl_cfg(
json::map &stage_tbl)
const;
1165 int direct_shiftcount()
const override {
1170 virtual void add_hash_functions(
json::map &stage_tbl)
const;
1171 void add_all_reference_tables(
json::map &tbl,
Table *math_table =
nullptr)
const;
1172 METER_ACCESS_TYPE default_meter_access_type(
bool for_stateful);
1173 bool needs_handle()
const override {
return true; }
1174 bool needs_next()
const override {
return true; }
1175 bitvec compute_reachable_tables()
override;
1179#define DECLARE_TABLE_TYPE(TYPE, PARENT, NAME, ...) \
1180 class TYPE :
public PARENT { \
1181 static struct Type :
public Table::Type { \
1182 Type() : Table::Type(NAME) {} \
1183 TYPE *create(
int lineno,
const char *name, gress_t gress, Stage *stage,
int lid, \
1184 VECTOR(pair_t) & data); \
1185 } table_type_singleton; \
1186 friend struct Type; \
1189 TYPE(
int l,
const char *n, gress_t g, Stage *s,
int lid) : PARENT(l, n, g, s, lid) {} \
1190 void setup(VECTOR(pair_t) & data)
override; \
1193 void pass1()
override; \
1194 void pass2()
override; \
1195 void pass3()
override; \
1199 template <
class REGS> \
1200 void write_regs_vt(REGS ®s); \
1201 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_regs, (mau_regs & regs),
override) \
1202 void gen_tbl_cfg(json::vector &out)
const override; \
1208#define DEFINE_TABLE_TYPE(TYPE) \
1209 TYPE::Type TYPE::table_type_singleton; \
1210 TYPE *TYPE::Type::create(int lineno, const char *name, gress_t gress, Stage *stage, int lid, \
1211 VECTOR(pair_t) & data) { \
1212 TYPE *rv = new TYPE(lineno, name, gress, stage, lid); \
1216 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD, void TYPE::write_regs, (mau_regs & regs), \
1217 { write_regs_vt(regs); })
1220#define DEFINE_TABLE_TYPE_WITH_SPECIALIZATION(TYPE, KIND) \
1221 TYPE::Type TYPE::table_type_singleton; \
1222 TYPE *TYPE::Type::create(int lineno, const char *name, gress_t gress, Stage *stage, int lid, \
1223 VECTOR(pair_t) & data) { \
1224 SWITCH_FOREACH_##KIND(options.target, \
1225 auto *rv = new TARGET::TYPE(lineno, name, gress, stage, lid); \
1226 rv->setup(data); return rv;) \
1228 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD, void TYPE::write_regs, (mau_regs & regs), \
1229 { write_regs_vt(regs); })
1232DECLARE_ABSTRACT_TABLE_TYPE(SRamMatchTable, MatchTable,
1236 struct Ram :
public MemUnit {
1237 using MemUnit::MemUnit;
1238 Ram(
const MemUnit &m) : MemUnit(m) {}
1239 Ram(MemUnit &&m) : MemUnit(
std::move(m)) {}
1240 bool isLamb()
const {
return stage == INT_MIN && row == -1; }
1241 const char *desc()
const;
1250 std::vector<Ram> rams;
1251 bool isLamb()
const {
1252 BUG_CHECK(!rams.empty(),
"no rams in way");
1253 return rams.at(0).isLamb(); }
1254 bitvec select_bits()
const {
1256 rv.setrange(index, (isLamb() ? LAMB_DEPTH_BITS : SRAM_DEPTH_BITS) + subword_bits);
1263 std::vector<Way> ways;
1264 struct WayRam {
int way, index, word, bank; };
1265 std::map<Ram, WayRam> way_map;
1266 std::vector<MatchSource *> match;
1267 std::map<unsigned, MatchSource *> match_by_bit;
1268 std::vector<std::vector<MatchSource *>> match_in_word;
1269 std::vector<int> word_ixbar_group;
1276 int result_bus_word;
1277 std::map<int, int> match_group;
1278 std::vector<unsigned> tofino_mask;
1280 GroupInfo() : overhead_word(-1), overhead_bit(-1), result_bus_word(-1), vpn_offset(-1) {}
1282 int result_bus_word_group()
const {
return match_group.at(result_bus_word); }
1284 std::vector<GroupInfo> group_info;
1285 std::vector<std::vector<int>> word_info;
1287 int mgm_lineno = -1;
1288 friend class GatewayTable;
1289 friend class Target::Tofino::GatewayTable;
1290 bitvec version_nibble_mask;
1293 std::map<unsigned, unsigned> hash_fn_ids;
1296 template<
class REGS>
1297 void write_attached_merge_regs(REGS ®s,
int bus,
int word,
int word_group);
1299 bool parse_ram(
const value_t &, std::vector<Ram> &);
1300 bool parse_way(
const value_t &);
1301 void common_sram_setup(
pair_t &,
const VECTOR(
pair_t) &);
1302 void common_sram_checks();
1303 void alloc_global_busses()
override;
1304 void alloc_vpns()
override;
1305 int find_problematic_vpn_offset()
const;
1306 virtual void setup_ways();
1307 void setup_hash_function_ids();
1308 void pass1()
override;
1309 template<
class REGS>
void write_regs_vt(REGS ®s);
1310 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
1311 void write_regs, (mau_regs ®s),
override )
1312 virtual
std::
string get_match_mode(const
Phv::Ref &pref,
int offset) const;
1313 json::map* add_common_sram_tbl_cfgs(
json::map &tbl,
1314 std::
string match_type,
std::
string stage_table_type) const;
1315 void add_action_cfgs(
json::map &tbl,
json::map &stage_tbl) const;
1316 virtual
unsigned entry_ram_depth()
const {
return 1024; }
1317 unsigned get_number_entries()
const;
1318 unsigned get_format_width()
const;
1319 virtual int determine_pre_byteswizzle_loc(
MatchSource *ms,
int lo,
int hi,
int word);
1320 void add_field_to_pack_format(
json::vector &field_list,
unsigned basebit, std::string name,
1323 std::unique_ptr<json::map> gen_memory_resource_allocation_tbl_cfg_with_way(
const Way &)
const;
1324 Actions *get_actions()
const override {
1325 return actions ? actions.get() : (action ? action->actions.get() :
nullptr);
1327 void add_hash_functions(
json::map &stage_tbl)
const override;
1328 virtual void gen_ghost_bits(
int hash_function_number,
json::vector &ghost_bits_to_hash_bits,
1330 virtual void no_overhead_determine_result_bus_usage();
1334 Format::Field *lookup_field(
const std::string &n,
const std::string &act =
"")
const override;
1335 OVERLOAD_FUNC_FOREACH(TARGET_CLASS,
virtual void, setup_word_ixbar_group, (), ())
1336 OVERLOAD_FUNC_FOREACH(TARGET_CLASS, virtual
void, verify_format, (), ())
1337 OVERLOAD_FUNC_FOREACH(TARGET_CLASS, virtual
void, verify_format_pass2, (), ())
1338 virtual
bool verify_match_key();
1339 void verify_match(
unsigned fmt_width);
1340 void vpn_params(
int &width,
int &depth,
int &period, const
char *&period_name)
const override {
1341 width = (format->size-1)/128 + 1;
1342 period = format->groups();
1343 depth = period * layout_size() / width;
1344 period_name =
"match group size"; }
1345 template<
class REGS>
void write_merge_regs_vt(REGS ®s,
int type,
int bus) {
1346 attached.write_merge_regs(regs,
this, type, bus); }
1347 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
1348 void write_merge_regs, (mau_regs ®s,
int type,
int bus),
override {
1349 write_merge_regs_vt(regs, type, bus); })
1350 bool is_match_bit(
const std::string name,
const int bit)
const {
1351 for (
auto *m : match) {
1352 std::string m_name = m->name();
1353 int m_lo = remove_name_tail_range(m_name) + m->fieldlobit();
1354 int m_hi = m_lo + m->size() -1;
1355 if (m_name == name) {
1363 void determine_word_and_result_bus()
override;
1364 SelectionTable *get_selector()
const override {
return attached.get_selector(); }
1365 StatefulTable *get_stateful()
const override {
return attached.get_stateful(); }
1366 MeterTable* get_meter()
const override {
return attached.get_meter(); }
1367 const Way *way_for_ram(
Ram r)
const {
1368 return way_map.count(r) ? &ways[way_map.at(r).way] :
nullptr; }
1369 const Way *way_for_xme(
int xme)
const {
1370 for (
auto &way : ways)
if (way.group_xme == xme)
return &way;
1377 ExactMatchTable, SRamMatchTable,
"exact_match",
bool dynamic_key_masks =
false;
1382 using GhostBitPositions = std::map<std::pair<std::string, int>,
bitvec>;
1383 std::map<int, GhostBitPositions> ghost_bit_positions; std::unique_ptr<Format> stash_format;
1384 std::vector<int> stash_rows; std::vector<int> stash_cols; std::vector<int> stash_units;
1385 std::vector<int> stash_overhead_rows;
1389 :
int unitram_type()
override {
return UnitRam::MATCH; } table_type_t table_type()
1390 const override {
return EXACT; }
bool has_group(
int grp) {
1391 for (
auto &way : ways)
1392 if (way.group_xme == grp)
return true;
1394 }
void determine_ghost_bits();
1395 void gen_ghost_bits(
int hash_function_number,
json::vector &ghost_bits_to_hash_bits,
1397 void generate_stash_overhead_rows();)
1400 AlgTcamMatchTable, SRamMatchTable,
"atcam_match",
1402 std::map<int, int> col_priority_way;
1403 int number_partitions = 0;
int max_subtrees_per_partition = 0;
int bins_per_partition = 0;
1404 int atcam_subset_width = 0;
int shift_granularity = 0; std::string partition_field_name =
"";
1405 std::vector<int> ixbar_subgroup, ixbar_mask;
struct match_element {
1407 unsigned offset, width;
1409 bitvec s0q1_nibbles, s1q0_nibbles; std::vector<Phv::Ref *> s0q1_prefs, s1q0_prefs;
1410 std::map<int, match_element> s0q1, s1q0; table_type_t table_type()
1411 const override {
return ATCAM; };
1412 void verify_format(Target::Tofino)
override;
1413 void verify_entry_priority();
void setup_column_priority();
void find_tcam_match();
1414 void gen_unit_cfg(
json::vector &units,
int size)
const;
1415 std::unique_ptr<json::vector> gen_memory_resource_allocation_tbl_cfg_no_input()
const;
1417 std::map<int, match_element> &elems,
bitvec &mask);
1418 std::string get_match_mode(
const Phv::Ref &pref,
int offset)
const override;
1419 void base_alpm_atcam_tbl_cfg(
json::map &atcam_tbl,
const char *type,
int size)
const {
1420 if (p4_table) p4_table->base_alpm_tbl_cfg(atcam_tbl, size,
this, P4Table::Atcam);
1425 void add_hash_functions(
json::map &stage_tbl)
1426 const override {}
bool has_directly_attached_synth2port()
const;
1427 std::string get_lpm_field_name()
const {
1428 std::string lpm =
"lpm";
1429 if (
auto *p = find_p4_param_type(lpm))
1430 return p->key_name.empty() ? p->name : p->key_name;
1432 error(lineno,
"'lpm' type field not found in alpm atcam '%s-%s' p4 param order", name(),
1435 } std::set<unsigned>
1436 get_partition_action_handle()
const {
1437 if (p4_table)
return p4_table->get_partition_action_handle();
1439 }
void no_overhead_determine_result_bus_usage()
override;
1440 std::string get_partition_field_name()
const {
1441 if (!p4_table)
return "";
1442 auto name = p4_table->get_partition_field_name();
1443 if (
auto *p = find_p4_param(name))
1444 if (!p->key_name.empty())
return p->key_name;
1446 }
unsigned entry_ram_depth()
const override {
1447 return std::min(number_partitions, 1024);
1454 ProxyHashMatchTable, SRamMatchTable,
"proxy_hash",
bool dynamic_key_masks =
false;
1455 void setup_ways()
override;
int proxy_hash_group = -1; std::string proxy_hash_alg =
"<invalid>";
1456 bool verify_match_key()
override; table_type_t table_type()
1457 const override {
return PROXY_HASH; }
void setup_word_ixbar_group()
override;
1458 int determine_pre_byteswizzle_loc(
MatchSource *ms,
int lo,
int hi,
int word)
override;
1459 void add_proxy_hash_function(
json::map &stage_tbl)
const;
1463DECLARE_TABLE_TYPE(TernaryMatchTable, MatchTable,
"ternary_match",
1467 void vpn_params(int &width, int &depth, int &period, const char *&period_name) const override;
1469 int lineno = -1, word_group = -1, byte_group = -1, byte_config = 0, dirtcam = 0;
1471 explicit Match(
const value_t &);
1473 enum range_match_t { TCAM_NORMAL = 0, DIRTCAM_2B = 1, DIRTCAM_4B_LO = 2,
1474 DIRTCAM_4B_HI = 3, NONE = 4 };
1475 enum byte_config_t { MIDBYTE_NIBBLE_LO = 0, MIDBYTE_NIBBLE_HI = 1 };
1476 std::vector<Match> match;
1477 int match_word(
int word_group)
const {
1478 for (
unsigned i = 0; i < match.size(); i++)
1479 if (match[i].word_group == word_group)
1482 unsigned chain_rows[TCAM_UNITS_PER_ROW];
1483 enum { ALWAYS_ENABLE_ROW = (1<<2) | (1<<5) | (1<<9) };
1484 friend class TernaryIndirectTable;
1486 virtual void check_tcam_match_bus(
const std::vector<Table::Layout> &) = 0;
1490 void pass0()
override;
1493 int indirect_bus = -1;
1494 void alloc_vpns()
override;
1495 range_match_t get_dirtcam_mode(
int group,
int byte)
const {
1496 BUG_CHECK(group >= 0,
"group must be >= 0");
1497 BUG_CHECK(
byte >= 0,
"byte must be >= 0");
1498 range_match_t dirtcam_mode = NONE;
1499 for (
auto &m : match) {
1500 if (m.word_group == group) {
1501 dirtcam_mode = (range_match_t) ((m.dirtcam >> 2*
byte) & 0x3); } }
1502 return dirtcam_mode; }
1503 Format::Field *lookup_field(
const std::string &name,
const std::string &action)
const override;
1505 return indirect ? indirect->find_hash_dist(unit) : Table::find_hash_dist(unit); }
1506 int find_on_actionbus(
const ActionBusSource &src,
int lo,
int hi,
int size,
1507 int pos = -1)
override {
1508 return indirect ? indirect->find_on_actionbus(src, lo, hi, size, pos)
1509 : Table::find_on_actionbus(src, lo, hi, size, pos); }
1510 void need_on_actionbus(
const ActionBusSource &src,
int lo,
int hi,
int size)
override {
1511 indirect ? indirect->need_on_actionbus(src, lo, hi, size)
1512 : Table::need_on_actionbus(src, lo, hi, size); }
1513 int find_on_actionbus(
const char *n, TableOutputModifier mod,
int lo,
int hi,
1514 int size,
int *len = 0)
override {
1515 return indirect ? indirect->find_on_actionbus(n, mod, lo, hi, size, len)
1516 : Table::find_on_actionbus(n, mod, lo, hi, size, len); }
1517 void need_on_actionbus(
Table *att, TableOutputModifier mod,
int lo,
int hi,
int size)
override {
1518 indirect ? indirect->need_on_actionbus(att, mod, lo, hi, size)
1519 : Table::need_on_actionbus(att, mod, lo, hi, size); }
1520 const Call &get_action()
const override {
return indirect ? indirect->get_action() : action; }
1521 Actions *get_actions()
const override {
return actions ? actions.get() :
1522 (action ? action->actions.get() : indirect ? indirect->actions ? indirect->actions.get() :
1523 indirect->action ? indirect->action->actions.get() : 0 : 0); }
1525 return indirect ? indirect->get_attached() : &attached; }
1527 return indirect ? indirect->get_attached() : &attached; }
1528 SelectionTable *get_selector()
const override {
1529 return indirect ? indirect->get_selector() : 0; }
1530 StatefulTable *get_stateful()
const override {
1531 return indirect ? indirect->get_stateful() : 0; }
1532 MeterTable* get_meter()
const override {
1533 return indirect ? indirect->get_meter() : 0; }
1534 bool is_attached(
const Table *tbl)
const override {
1535 return indirect ? indirect->is_attached(tbl) : MatchTable::is_attached(tbl); }
1536 Format::Field *find_address_field(
const AttachedTable *tbl)
const override {
1537 return indirect ? indirect->find_address_field(tbl) : attached.find_address_field(tbl); }
1538 std::unique_ptr<json::map> gen_memory_resource_allocation_tbl_cfg(
1539 const char *type,
const std::vector<Layout> &layout,
1540 bool skip_spare_bank =
false)
const override;
1542 Call &action_call()
override {
return indirect ? indirect->action : action; }
1543 Call &instruction_call()
override {
return indirect ? indirect->instruction: instruction; }
1544 int json_memunit(
const MemUnit &u)
const override {
1545 return u.row + u.col*12; }
1546 bool is_ternary()
override {
return true; }
1547 bool has_indirect() {
return indirect; }
1548 int hit_next_size()
const override {
1549 if (indirect && indirect->hit_next.size() > 0)
1550 return indirect->hit_next.size();
1551 return hit_next.size(); }
1552 table_type_t table_type()
const override {
return TERNARY; }
1553 void gen_entry_cfg(
json::vector &out, std::string name,
1554 unsigned lsb_offset,
unsigned lsb_idx,
unsigned msb_idx,
1555 std::string source,
unsigned start_bit,
unsigned field_width,
1556 unsigned index,
bitvec &tcam_bits,
unsigned byte_offset)
const;
1557 void gen_entry_cfg2(
json::vector &out, std::string field_name, std::string global_name,
1558 unsigned lsb_offset,
unsigned lsb_idx,
unsigned msb_idx, std::string source,
1559 unsigned start_bit,
unsigned field_width,
bitvec &tcam_bits)
const;
1560 void gen_entry_range_cfg(
json::map &entry,
bool duplicate,
unsigned nibble_offset)
const;
1561 void set_partition_action_handle(
unsigned handle) {
1562 if (p4_table) p4_table->set_partition_action_handle(handle); }
1563 void set_partition_field_name(std::string name) {
1564 if (p4_table) p4_table->set_partition_field_name(name); }
1565 void base_alpm_pre_classifier_tbl_cfg(
json::map &pre_classifier_tbl,
1566 const char *type,
int size)
const {
1568 p4_table->base_alpm_tbl_cfg(pre_classifier_tbl, size,
this, P4Table::PreClassifier);
1570 virtual void gen_match_fields_pvp(
json::vector &match_field_list,
unsigned word,
1571 bool uses_versioning,
unsigned version_word_group,
bitvec &tcam_bits)
const;
1572 virtual void gen_match_fields(
json::vector &match_field_list,
1573 std::vector<bitvec> &tcam_bits)
const;
1574 unsigned get_default_action_handle()
const override {
1575 unsigned def_act_handle = Table::get_default_action_handle();
1576 return def_act_handle > 0 ? def_act_handle :
1577 indirect ? indirect->get_default_action_handle() ?
1578 indirect->get_default_action_handle() : action ?
1579 action->default_action_handle : 0 : 0;
1581 std::string get_default_action()
override {
1582 std::string def_act = Table::get_default_action();
1583 return !def_act.empty() ? def_act : indirect ? indirect->default_action :
""; }
1584 Format* get_format()
const override {
1585 return indirect ? indirect->get_format() : MatchTable::get_format(); }
1586 template<
class REGS>
void write_merge_regs_vt(REGS ®s,
int type,
int bus) {
1587 attached.write_merge_regs(regs,
this, type, bus); }
1588 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
1589 void write_merge_regs, (mau_regs ®s,
int type,
int bus),
override {
1590 write_merge_regs_vt(regs, type, bus); })
1591 void add_result_physical_buses(
json::map &stage_tbl)
const override;
1592 default_action_params* get_default_action_parameters()
override {
1593 if (!default_action_parameters.empty())
return &default_action_parameters;
1594 auto def_action_params = indirect ? indirect->get_default_action_parameters() :
nullptr;
1595 return def_action_params; }
1596 bitvec compute_reachable_tables()
override;
1597 int get_tcam_id()
const override {
return tcam_id; }
1598 virtual void setup_indirect(
const value_t &v) {
1599 if (CHECKTYPE(v, tSTR))
1604 template<
class REGS>
void tcam_table_map(REGS ®s,
int row,
int col);
1608 Phase0MatchTable, MatchTable,
"phase0_match",
int size = MAX_PORTS;
int width = 1;
1609 int constant_value = 0; table_type_t table_type()
const override {
return PHASE0; }
1613 void pass0()
override {}
void set_pred()
override {
return; }
bool needs_next()
const override {
1615 }
int ram_word_width()
const override {
return Target::PHASE0_FORMAT_WIDTH(); })
1617 HashActionTable, MatchTable,
"hash_action",
public
1620 table_type_t table_type() const override { return HASH_ACTION; }
template <
class REGS>
1621 void write_merge_regs_vt(REGS ®s,
int type,
int bus);
1622 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_merge_regs,
1623 (mau_regs & regs,
int type,
int bus),
override) Format::Field *
1624 lookup_field(const
std::
string &n, const
std::
string &act =
"") const override;
1625 void add_hash_functions(
json::map &stage_tbl) const override;
1626 void determine_word_and_result_bus() override;
1627 Layout::bus_type_t default_bus_type()
const override {
return Layout::RESULT_BUS; })
1629DECLARE_TABLE_TYPE(TernaryIndirectTable,
Table,
"ternary_indirect",
1633 TernaryMatchTable *match_table =
nullptr;
1635 table_type_t table_type()
const override {
return TERNARY_INDIRECT; }
1636 table_type_t set_match_table(MatchTable *m,
bool indirect)
override;
1637 void vpn_params(
int &width,
int &depth,
int &period,
const char *&period_name)
const override {
1638 width = (format->size-1)/128 + 1;
1639 depth = layout_size() / width;
1642 Actions *get_actions()
const override {
1643 return actions ? actions.get() : (match_table ? match_table->actions.get() :
nullptr);
1645 const AttachedTables *get_attached()
const override {
return &attached; }
1647 const GatewayTable *get_gateway()
const override {
return match_table->get_gateway(); }
1648 const MatchTable *get_match_table()
const override {
return match_table; }
1649 std::set<MatchTable *> get_match_tables()
override {
1650 std::set<MatchTable *> rv;
1651 if (match_table) rv.insert(match_table);
1653 SelectionTable *get_selector()
const override {
return attached.get_selector(); }
1654 StatefulTable *get_stateful()
const override {
return attached.get_stateful(); }
1655 MeterTable* get_meter()
const override {
return attached.get_meter(); }
1656 bool is_attached(
const Table *tbl)
const override {
return attached.is_attached(tbl); }
1657 Format::Field *find_address_field(
const AttachedTable *tbl)
const override {
1658 return attached.find_address_field(tbl); }
1659 template<
class REGS>
void write_merge_regs_vt(REGS ®s,
int type,
int bus) {
1660 attached.write_merge_regs(regs, match_table, type, bus); }
1661 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
1662 void write_merge_regs, (mau_regs ®s,
int type,
int bus),
override {
1663 write_merge_regs_vt(regs, type, bus); })
1664 int unitram_type()
override {
return UnitRam::TERNARY_INDIRECTION; }
1668 Format::Field *lookup_field(
const std::string &n,
1669 const std::string &act =
"")
const override;
1670 MatchTable *get_match_table()
override {
return match_table; }
1671 const std::vector<NextTables> &get_hit_next()
const override {
1672 if (hit_next.empty() && match_table)
1673 return match_table->get_hit_next();
1674 return Table::get_hit_next(); }
1675 const NextTables &get_miss_next()
const override {
1676 if (!miss_next.set() && match_table)
1677 return match_table->get_miss_next();
1678 return Table::get_miss_next(); }
1679 int address_shift()
const override {
return std::min(5U, format->log2size - 2); }
1680 unsigned get_default_action_handle()
const override {
1681 unsigned def_act_handle = Table::get_default_action_handle();
1682 return def_act_handle ? def_act_handle : action ? action->default_action_handle : 0; }
1683 bool needs_handle()
const override {
return true; }
1684 bool needs_next()
const override {
return true; }
1685 void determine_word_and_result_bus()
override;
1686 bitvec compute_reachable_tables()
override;
1687 int get_tcam_id()
const override {
return match_table->tcam_id; }
1688 Layout::bus_type_t default_bus_type()
const override {
return Layout::TIND_BUS; }
1692DECLARE_ABSTRACT_TABLE_TYPE(
1693 AttachedTable,
Table,
1695 std::set<MatchTable *> match_tables;
1696 bool direct =
false, indirect =
false;
bool per_flow_enable =
false;
1697 std::string per_flow_enable_param =
"";
1698 virtual unsigned per_flow_enable_bit(MatchTable *m =
nullptr)
const;
1699 table_type_t set_match_table(MatchTable * m,
bool indirect)
override {
1700 if ((indirect && direct) || (!indirect && this->indirect))
1701 error(lineno,
"Table %s is accessed with direct and indirect indices", name());
1702 this->indirect = indirect;
1704 match_tables.insert(m);
1705 if ((
unsigned)m->logical_id < (
unsigned)logical_id) logical_id = m->logical_id;
1706 return table_type();
1707 }
const GatewayTable *get_gateway()
const override {
1708 return match_tables.size() == 1 ? (*match_tables.begin())->get_gateway() : 0;
1709 } SelectionTable *get_selector()
const override;
1710 StatefulTable * get_stateful()
const override; MeterTable * get_meter()
const override;
1712 action_call()
override {
1713 return match_tables.size() == 1 ? (*match_tables.begin())->action_call() : action;
1715 int json_memunit(
const MemUnit &u)
const override;
1716 void pass1()
override;
1717 virtual unsigned get_alu_index()
const {
1718 if (layout.size() > 0)
return layout[0].row / 4U;
1719 error(lineno,
"Cannot determine ALU Index for table %s", name());
1721 }
unsigned determine_meter_shiftcount(
Table::Call &call,
int group,
int word,
int tcam_shift)
1723 void determine_meter_merge_regs(MatchTable *match,
int type,
int bus,
1724 const std::vector<Call::Arg> &arg,
1725 METER_ACCESS_TYPE default_type,
unsigned &adr_mask,
1726 unsigned &per_entry_mux_ctl,
unsigned &adr_default,
1727 unsigned &meter_type_position);
1734 void add_alu_index(
json::map &stage_tbl, std::string alu_index)
const;
1739 const MatchTable *get_match_table()
1740 const override {
return match_tables.size() == 1 ? *match_tables.begin() : 0; }
1741 MatchTable *get_match_table()
1742 override {
return match_tables.size() == 1 ? *match_tables.begin() : 0; }
1743 std::set<MatchTable *>
1744 get_match_tables()
override {
return match_tables; }
bool has_per_flow_enable()
1745 const {
return per_flow_enable; } std::string get_per_flow_enable_param() {
1746 return per_flow_enable_param;
1747 } Format::Field *get_per_flow_enable_param(MatchTable *m)
const override {
1748 return per_flow_enable ? m->lookup_field(per_flow_enable_param) :
nullptr;
1749 } Format::Field *get_meter_address_param(MatchTable *m)
const override {
1750 std::string pfe_name =
1751 per_flow_enable_param.substr(0, per_flow_enable_param.find(
"_pfe"));
1752 return per_flow_enable ? m->lookup_field(pfe_name +
"_addr") :
nullptr;
1753 } Format::Field *get_meter_type_param(MatchTable *m)
const override {
1754 std::string pfe_name =
1755 per_flow_enable_param.substr(0, per_flow_enable_param.find(
"_pfe"));
1756 return per_flow_enable ? m->lookup_field(pfe_name +
"_type") :
nullptr;
1758 bool get_per_flow_enable() {
return per_flow_enable; }
bool is_direct()
const {
return direct; }
1759 virtual int default_pfe_adjust()
const {
return 0; }
1760 std::string get_default_action()
override {
1761 if (!default_action.empty())
return default_action;
1762 for (
auto m : match_tables) {
1763 std::string def_action = m->get_default_action();
1764 if (!def_action.empty())
return def_action;
1768 default_action_params *get_default_action_parameters()
override {
1769 if (!default_action_parameters.empty())
return &default_action_parameters;
1770 for (
auto m : match_tables) {
1771 if (
auto def_action_params = m->get_default_action_parameters())
1772 if (!def_action_params->empty())
return def_action_params;
1775 }
bool validate_call(
Table::Call &call, MatchTable *self,
size_t required_args,
1776 int hash_dist_type,
Table::Call &first_call)
override;
1778 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
int meter_alu_fifo_enable_from_mask,
1779 (mau_regs &,
unsigned bytemask))
1785 ActionTable, AttachedTable,
"action",
protected
1786 : int action_id = -1;
1787 std::map<int, bitvec> home_rows_per_word;
int home_lineno = -1;
1788 std::map<std::string, std::unique_ptr<Format>> action_formats;
1789 std::map<std::string, Actions::Action *> pack_actions;
1790 static const std::map<unsigned, std::vector<std::string>> action_data_address_huffman_encoding;
1791 void vpn_params(
int &width,
int &depth,
int &period,
const char *&period_name)
const override;
1792 int get_start_vpn()
override; std::string find_field(Format::Field * field)
override;
1793 int find_field_lineno(Format::Field *field)
override;
1794 Format::Field * lookup_field(
const std::string &name,
const std::string &action)
const override;
1795 void apply_to_field(
const std::string &n, std::function<
void(Format::Field *)> fn)
override;
1796 int find_on_actionbus(
const char *n, TableOutputModifier mod,
int lo,
int hi,
int size,
1798 int find_on_actionbus(
const ActionBusSource &src,
int lo,
int hi,
int size,
int pos = -1)
1800 void need_on_actionbus(
const ActionBusSource &src,
int lo,
int hi,
int size)
override;
1801 void need_on_actionbus(
Table *att, TableOutputModifier mod,
int lo,
int hi,
int size)
override;
1802 table_type_t table_type()
const override {
return ACTION; }
int unitram_type()
1803 override {
return UnitRam::ACTION; }
void pad_format_fields();
1804 unsigned get_do_care_count(std::string bstring);
1805 unsigned get_lower_huffman_encoding_bits(
unsigned width); public
1806 :
const std::map<std::string, std::unique_ptr<Format>> &get_action_formats()
1807 const {
return action_formats; }
unsigned get_size()
const {
1809 if (format) size = format->size;
1810 for (
auto &f : get_action_formats()) {
1811 unsigned fsize = f.second->size;
1812 if (fsize > size) size = fsize;
1815 }
unsigned get_log2size()
const {
1816 unsigned size = get_size();
1817 return ceil_log2(size);
1818 }
unsigned determine_shiftcount(
Table::Call &call,
int group,
unsigned word,
int tcam_shift)
1820 unsigned determine_default(
Table::Call &call)
const;
1822 unsigned determine_vpn_shiftcount(
Table::Call &call)
const;
bool needs_handle()
1823 const override {
return true; }
bool needs_next()
const override {
return true; }
1828DECLARE_TABLE_TYPE(GatewayTable,
Table,
"gateway",
1832 MatchTable *match_table = 0;
1833 uint64_t payload = -1;
1834 int have_payload = -1;
1835 std::vector<int> payload_map;
1836 int match_address = -1;
1838 int payload_unit = -1;
1839 enum range_match_t { NONE, DC_2BIT, DC_4BIT }
1841 std::string gateway_name;
1842 std::string gateway_cond;
1843 bool always_run =
false;
1851 MatchKey(gress_t gr,
int stg, value_t &v) :
1852 offset(-1), val(gr, stg, v), valid(false) {}
1853 MatchKey(
int off, gress_t gr,
int stg, value_t &v) :
1854 offset(off), val(gr, stg, v), valid(false) {}
1857 MatchKey(
int off, gress_t gr,
int stg, value_t &v,
bool vld) :
1858 offset(off), val(gr, stg, v), valid(vld) {}
1859 bool operator<(
const MatchKey &a)
const {
return offset < a.offset; }
1864 std::vector<MatchKey> match, xor_match;
1867 uint16_t range[6] = { 0, 0, 0, 0, 0, 0 };
1869 bool run_table =
false;
1872 int next_map_lut = -1;
1874 Match(value_t *v, value_t &data, range_match_t range_match);
1875 } miss, cond_true, cond_false;
1876 std::vector<Match> table;
1877 bool need_next_map_lut =
false;
1878 template<
class REGS>
void payload_write_regs(REGS &,
int row,
int type,
int bus);
1879 template<
class REGS>
void standalone_write_regs(REGS ®s);
1880 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
1881 virtual void write_next_table_regs, (mau_regs &), { BUG(
"unsupported"); })
1882 bool gateway_needs_ixbar_group() {
1883 for (
auto& m : match)
1886 return !xor_match.empty(); }
1890 table_type_t table_type()
const override {
return GATEWAY; }
1891 virtual int find_next_lut_entry(
Table *tbl,
const Match &match);
1892 const MatchTable *get_match_table()
const override {
return match_table; }
1893 MatchTable *get_match_table()
override {
return match_table; }
1894 std::set<MatchTable *> get_match_tables()
override {
1895 std::set<MatchTable *> rv;
1896 if (match_table) rv.insert(match_table);
1898 table_type_t set_match_table(MatchTable *m,
bool indirect)
override {
1900 if ((
unsigned)m->logical_id < (
unsigned)logical_id) logical_id = m->logical_id;
1902 virtual void setup_map_indexing(
Table *tbl) {
return; }
1903 static GatewayTable *create(
int lineno,
const std::string &name, gress_t gress,
1905 {
return table_type_singleton.create(lineno, name.c_str(), gress, stage, lid, data); }
1906 const GatewayTable *get_gateway()
const override {
return this; }
1908 return match_table ? match_table->get_attached() : 0; }
1909 SelectionTable *get_selector()
const override {
1910 return match_table ? match_table->get_selector() : 0; }
1911 StatefulTable *get_stateful()
const override {
1912 return match_table ? match_table->get_stateful() : 0; }
1913 MeterTable *get_meter()
const override {
1914 return match_table ? match_table->get_meter() : 0; }
1915 bool empty_match()
const {
return match.empty() && xor_match.empty(); }
1916 unsigned input_use()
const;
1917 bool needs_handle()
const override {
return true; }
1918 bool needs_next()
const override {
return true; }
1919 bool is_branch()
const;
1920 void verify_format();
1921 bool is_always_run()
const override {
return always_run; }
1922 virtual bool check_match_key(MatchKey &,
const std::vector<MatchKey> &,
bool);
1923 virtual int gw_memory_unit()
const = 0;
1929 SelectionTable, AttachedTable,
"selection",
1930 bool non_linear_hash =
false,
1931 resilient_hash =
false;
1932 int mode_lineno = -1, param = -1; std::vector<int> pool_sizes;
1933 int min_words = -1, max_words = -1;
int selection_hash = -1; public
1934 : StatefulTable *bound_stateful =
nullptr;
1935 table_type_t table_type()
1936 const override {
return SELECTION; }
void vpn_params(
int &width,
int &depth,
int &period,
1937 const char *&period_name)
1940 depth = layout_size();
1944 template <
class REGS>
1945 void write_merge_regs_vt(REGS ®s, MatchTable *match,
int type,
int bus,
1946 const std::vector<Call::Arg> &args);
1947 template <
class REGS>
void setup_logical_alu_map(REGS ®s,
int logical_id,
int alu);
1948 template <
class REGS>
void setup_physical_alu_map(REGS ®s,
int type,
int bus,
int alu);
1949 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_merge_regs,
1950 (mau_regs & regs, MatchTable *match,
int type,
int bus,
1951 const std::vector<Call::Arg> &args),
1952 override) int address_shift()
1953 const override {
return 7; }
1954 std::vector<int> determine_spare_bank_memory_units()
const override;
1955 unsigned meter_group()
const {
return layout.at(0).row / 4U; }
int home_row()
const override {
1956 return layout.at(0).row | 3;
1957 }
int unitram_type()
override {
return UnitRam::SELECTOR; } StatefulTable *get_stateful()
1959 return bound_stateful;
1960 }
unsigned determine_shiftcount(
Table::Call &call,
int group,
unsigned word,
int tcam_shift)
1962 void set_stateful(StatefulTable *s)
override {
1964 }
unsigned per_flow_enable_bit(MatchTable *m =
nullptr)
const override;
1965 int indirect_shiftcount()
const override;
1966 unsigned determine_length_shiftcount(
const Table::Call &call,
int group,
int word)
const;
1967 unsigned determine_length_mask(
const Table::Call &call)
const;
1968 unsigned determine_length_default(
const Table::Call &call)
const;
1971class IdletimeTable : public Table {
1972 MatchTable *match_table = 0;
1973 int sweep_interval = 7, precision = 3;
1974 bool disable_notification =
false;
1975 bool two_way_notification =
false;
1976 bool per_flow_enable =
false;
1978 IdletimeTable(
int lineno,
const char *name, gress_t gress,
Stage *stage,
int lid)
1979 : Table(lineno, name, gress, stage, lid) {}
1980 void setup(VECTOR(
pair_t) & data)
override;
1983 table_type_t table_type()
const override {
return IDLETIME; }
1984 table_type_t set_match_table(MatchTable *m,
bool indirect)
override {
1986 if ((
unsigned)m->logical_id < (
unsigned)logical_id) logical_id = m->logical_id;
1989 void vpn_params(
int &width,
int &depth,
int &period,
const char *&period_name)
const override {
1991 depth = layout_size();
1994 int json_memunit(
const MemUnit &u)
const override;
1995 int precision_shift()
const;
1996 int direct_shiftcount()
const override;
1997 void pass1()
override;
1998 void pass2()
override;
1999 void pass3()
override;
2000 template <
class REGS>
2001 void write_merge_regs_vt(REGS ®s,
int type,
int bus);
2002 template <
class REGS>
2003 void write_regs_vt(REGS ®s);
2004 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_regs, (mau_regs & regs),
override)
2005 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_merge_regs,
2006 (mau_regs & regs,
int type,
int bus), override)
2007 void gen_tbl_cfg(
json::vector &out)
const override { }
2008 void gen_stage_tbl_cfg(
json::map &out)
const;
2009 static IdletimeTable *create(
int lineno,
const std::string &name, gress_t gress,
Stage *stage,
2010 int lid, VECTOR(
pair_t) & data) {
2015 bool needs_handle()
const override {
return true; }
2016 bool needs_next()
const override {
return true; }
2017 Layout::bus_type_t default_bus_type()
const override {
return Layout::IDLE_BUS; }
2022DECLARE_ABSTRACT_TABLE_TYPE(
2023 Synth2Port, AttachedTable,
2024 void vpn_params(
int &width,
int &depth,
int &period,
const char *&period_name)
const override {
2026 depth = layout_size();
2028 }
bool global_binding =
false;
2029 bool output_used =
false;
int home_lineno = -1; std::set<int, std::greater<int>> home_rows;
2030 json::map * add_stage_tbl_cfg(
json::map & tbl,
const char *type,
int size)
const override;
2032 int get_home_row_for_row(
int row)
const;
2033 void add_alu_indexes(
json::map &stage_tbl, std::string alu_indexes)
const;
2034 OVERLOAD_FUNC_FOREACH(TARGET_CLASS, std::vector<int>, determine_spare_bank_memory_units,
2035 ()
const, (),
override)
2036 OVERLOAD_FUNC_FOREACH(TARGET_CLASS,
void, alloc_vpns, (), (), override)
2037 template <class REGS>
void write_regs_vt(REGS ®s);
2038 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_regs, (mau_regs & regs), override)
2039 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_merge_regs,
2040 (mau_regs & regs, MatchTable *match,
int type,
int bus,
2041 const
std::vector<Call::Arg> &args),
2043 void common_init_setup(const VECTOR(
pair_t) &,
bool,
P4Table::type) override;
2045 void pass1() override;
void pass2() override;
void pass3() override;
2049 CounterTable, Synth2Port,
"counter",
2050 enum {NONE = 0, PACKETS = 1, BYTES = 2, BOTH = 3} type = NONE;
2051 int teop = -1;
bool teop_initialized =
false;
int bytecount_adjust = 0;
2052 table_type_t table_type()
const override {
return COUNTER; }
2053 template <
class REGS>
2054 void write_merge_regs_vt(REGS ®s, MatchTable *match,
int type,
int bus,
2055 const std::vector<Call::Arg> &args);
2056 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_merge_regs,
2057 (mau_regs & regs, MatchTable *match,
int type,
int bus,
2058 const std::vector<Call::Arg> &args),
2061 template <class REGS>
2062 void setup_teop_regs(REGS ®s,
int stats_group_index);
2063 template <class REGS>
void write_alu_vpn_range(REGS ®s);
2064 template <class REGS>
void setup_teop_regs_2(REGS ®s,
int stats_group_index);
2065 template <class REGS>
void write_alu_vpn_range_2(REGS ®s);
2071 lrt_params(
int l, int64_t t,
int i) : lineno(l), threshold(t), interval(i) {}
2072 explicit lrt_params(
const value_t &);
2074 std::vector<lrt_params> lrt; public
2075 :
int home_row()
const override {
return layout.at(0).row; }
int direct_shiftcount()
2077 int indirect_shiftcount()
const override;
2078 unsigned determine_shiftcount(
Table::Call &call,
int group,
unsigned word,
int tcam_shift)
2080 int address_shift()
const override;
2081 bool run_at_eop()
override {
return (type & BYTES) != 0; }
bool adr_mux_select_stats()
2082 override {
return true; }
int unitram_type()
override {
return UnitRam::STATISTICS; }
2088 MeterTable, Synth2Port,
"meter",
int red_nodrop_value = -1;
int red_drop_value = -1;
2089 int green_value = 0;
int yellow_value = 1;
int red_value = 3;
int profile = 0;
int teop = -1;
2090 bool teop_initialized =
false;
int bytecount_adjust = 0;
2091 enum {NONE = 0, STANDARD = 1, LPF = 2, RED = 3} type = NONE;
2092 enum {NONE_ = 0, PACKETS = 1, BYTES = 2} count = NONE_; std::vector<Layout> color_maprams;
2093 table_type_t table_type()
const override {
return METER; }
template <
class REGS>
2094 void write_merge_regs_vt(REGS ®s, MatchTable *match,
int type,
int bus,
2095 const std::vector<Call::Arg> &args);
2096 template <
class REGS>
void meter_color_logical_to_phys(REGS ®s,
int logical_id,
int alu);
2097 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
void write_merge_regs,
2098 (mau_regs & regs, MatchTable *match,
int type,
int bus,
2099 const std::vector<Call::Arg> &args),
2102 template <class REGS>
2103 void setup_teop_regs(REGS ®s,
int meter_group_index);
2104 template <class REGS>
void write_alu_vpn_range(REGS ®s);
2105 template <class REGS>
void write_regs_home_row(REGS ®s,
unsigned row);
2106 template <class REGS>
void write_mapram_color_regs(REGS ®s,
bool &push_on_overflow);
2108 template <class REGS>
void setup_teop_regs_2(REGS ®s,
int stats_group_index);
2109 template <class REGS>
void write_alu_vpn_range_2(REGS ®s);
2111 int sweep_interval = 2; public
2112 : enum {NO_COLOR_MAP, IDLE_MAP_ADDR, STATS_MAP_ADDR} color_mapram_addr = NO_COLOR_MAP;
2113 int direct_shiftcount()
const override;
int indirect_shiftcount()
const override;
2114 int address_shift()
const override;
bool color_aware =
false;
2115 bool color_aware_per_flow_enable =
false;
bool color_used =
false;
2116 int pre_color_hash_dist_unit = -1;
int pre_color_bit_lo = -1;
2117 bool run_at_eop()
override {
return type == STANDARD; }
int unitram_type()
override {
2118 return UnitRam::METER;
2119 }
int home_row()
const override {
return layout.at(0).row | 3; }
unsigned meter_group()
2120 const {
return layout.at(0).row / 4U; }
bool uses_colormaprams()
const override {
2121 return !color_maprams.empty();
2122 }
unsigned determine_shiftcount(
Table::Call &call,
int group,
unsigned word,
int tcam_shift)
2124 void add_cfg_reg(
json::vector &cfg_cache, std::string full_name, std::string name,
unsigned val,
2126 Layout::bus_type_t default_bus_type()
const override;
int default_pfe_adjust()
const override {
2127 return color_aware ? -METER_TYPE_BITS : 0;
2128 }
void set_color_used()
override { color_used =
true; }
void set_output_used()
override {
2130 }
int color_shiftcount(
Table::Call &call,
int group,
int tcam_shift)
const override;
2131 template <
class REGS>
2132 void setup_exact_shift(REGS &merge,
int bus,
int group,
int word,
int word_group,
2133 Call &meter_call, Call &color_call);
2134 template <
class REGS>
2135 void setup_tcam_shift(REGS &merge,
int bus,
int tcam_shift, Call &meter_call, Call &color_call);
2136 template <
class REGS>
void write_color_regs(REGS ®s, MatchTable *match,
int type,
int bus,
2137 const std::vector<Call::Arg> &args);
2144 const Table::Actions::Action *act;
2152DECLARE_TABLE_TYPE(StatefulTable, Synth2Port,
"stateful",
2153 table_type_t table_type()
const override {
return STATEFUL; }
2154 bool setup_jbay(
const pair_t &kv);
2155 template<
class REGS>
void write_action_regs_vt(REGS ®s,
const Actions::Action *);
2156 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
2157 void write_action_regs, (mau_regs ®s,
const Actions::Action *act),
override)
2158 template<class REGS>
void write_merge_regs_vt(REGS ®s, MatchTable *match,
int type,
int bus,
2159 const
std::vector<Call::Arg> &args);
2160 template<class REGS>
void write_logging_regs(REGS ®s);
2161 FOR_ALL_REGISTER_SETS(TARGET_OVERLOAD,
2162 void write_merge_regs, (mau_regs ®s, MatchTable *match,
int type,
2163 int bus, const
std::vector<Call::Arg> &args), override)
2164 template<class REGS>
void write_tofino2_common_regs(REGS ®s);
2165 struct const_info_t {
2169 std::string param_name;
2170 unsigned param_handle;
2171 static unsigned unique_register_param_handle;
2172 const_info_t() =
default;
2173 const_info_t(
int lineno,
2175 bool is_param =
false,
2176 std::string param_name =
"",
2177 unsigned param_handle = 0)
2178 : lineno(lineno), value(value), is_param(is_param),
2179 param_name(param_name), param_handle(param_handle) {
2180 if (is_param) this->param_handle = unique_register_param_handle++;
2183 std::vector<const_info_t> const_vals;
2186 std::vector<int> data;
2187 bool invert =
false;
2188 int shift = 0, scale = 0;
2189 explicit operator bool() {
return lineno >= 0; }
2192 bool dual_mode =
false;
2193 bool offset_vpn =
false;
2194 bool address_used =
false;
2195 int meter_adr_shift = 0;
2196 int stateful_counter_mode = 0;
2197 int watermark_level = 0;
2198 int watermark_pop_not_push = 0;
2199 uint64_t initial_value_lo = 0;
2200 uint64_t initial_value_hi = 0;
2201 unsigned data_bytemask = 0;
2202 unsigned hash_bytemask = 0;
2203 int logvpn_lineno = -1;
2204 int logvpn_min = -1, logvpn_max = -1;
2205 int pred_shift = 0, pred_comb_shift = 0;
2206 int stage_alu_id = -1;
2207 Ref underflow_action, overflow_action;
2212 unsigned phv_byte_mask = 0;
2213 std::vector<Ref> sbus_learn, sbus_match;
2214 enum { SBUS_OR = 0, SBUS_AND = 1 } sbus_comb = SBUS_OR;
2215 int phv_hash_shift = 0;
2219 uint32_t busy_value = 0;
2220 bool divmod_used =
false;
2221 int instruction_set()
override {
return 1; }
2222 int direct_shiftcount()
const override;
2223 int indirect_shiftcount()
const override;
2224 int address_shift()
const override;
2225 int unitram_type()
override {
return UnitRam::STATEFUL; }
2226 int get_const(
int lineno, int64_t v);
2227 bool is_dual_mode()
const {
return dual_mode; }
2228 int alu_size()
const {
return 1 << std::min(5U, format->log2size - is_dual_mode()); }
2229 int home_row()
const override {
return layout.at(0).row | 3; }
2230 unsigned meter_group()
const {
return layout.at(0).row/4U; }
2231 unsigned determine_shiftcount(
Table::Call &call,
int group,
unsigned word,
2232 int tcam_shift)
const override;
2233 unsigned per_flow_enable_bit(MatchTable *m =
nullptr)
const override;
2234 void set_address_used()
override { address_used =
true; }
2235 void set_output_used()
override { output_used =
true; }
2236 void parse_register_params(
int idx,
const value_t &val);
2237 int64_t get_const_val(
int index)
const {
return const_vals.at(index).value; }
2238 Actions::Action *action_for_table_action(
const MatchTable *tbl,
const Actions::Action *)
const;
2239 OVERLOAD_FUNC_FOREACH(REGISTER_SET,
static int, parse_counter_mode, (
const value_t &v), (v))
2240 OVERLOAD_FUNC_FOREACH(REGISTER_SET,
void, set_counter_mode, (
int mode), (mode))
2241 OVERLOAD_FUNC_FOREACH(REGISTER_SET,
2245 bool p4c_5192_workaround(
const Actions::Action *)
const;
Definition action_bus.h:147
Definition bf-asm/alloc.h:48
Definition match_source.h:32
Definition ordered_map.h:32
Definition bf-asm/phv.h:186
Definition bf-asm/phv.h:32
void add_action_format(const Table *, json::map &) const
Definition tables.cpp:2476
bool validate_instruction(Table::Call &call) const
Definition tables.cpp:593
virtual void add_reference_table(json::vector &table_refs, const Table::Call &c) const
Definition tables.cpp:2881
void get_cjson_source(const std::string &field_name, std::string &source, int &start_bit) const
Definition tables.cpp:2955
static bool allow_bus_sharing(Table *t1, Table *t2)
Definition tables.cpp:887
static bool allow_ram_sharing(const Table *t1, const Table *t2)
Definition tables.cpp:873
virtual void add_field_to_pack_format(json::vector &field_list, unsigned basebit, std::string name, const Table::Format::Field &field, const Table::Actions::Action *act) const
Definition tables.cpp:3030
Definition backends/tofino/bf-asm/json.h:300
Definition backends/tofino/bf-asm/json.h:222
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
Definition salu_inst.cpp:29
Definition action_bus.h:28
Definition bf-asm/input_xbar.h:31
Definition hash_dist.h:32
Definition instruction.h:26
virtual const char * desc() const
Definition tables.cpp:34
bool immediate_conditional(int lo, int sz, std::string &condition) const
Definition tables.cpp:1968
void setup_mod_cond_values(value_t &map)
Definition tables.cpp:1523
void check_conditional(Table::Format::Field &field) const
Definition tables.cpp:1939
void gen_simple_tbl_cfg(json::vector &) const
Definition tables.cpp:2434
Definition asm-types.h:150
Definition asm-types.h:114