P4C
The P4 Compiler
Loading...
Searching...
No Matches
tofino/bf-asm/deparser.h
1
17
18#ifndef BACKENDS_TOFINO_BF_ASM_DEPARSER_H_
19#define BACKENDS_TOFINO_BF_ASM_DEPARSER_H_
20
21#include <vector>
22
23#include <boost/optional.hpp>
24
25#include "constants.h"
26#include "lib/bitops.h"
27#include "lib/ordered_set.h"
28#include "phv.h"
29#include "sections.h"
30
31enum {
32 // limits over all targets
33 MAX_DEPARSER_CHECKSUM_UNITS = 8,
34 DEPARSER_STAGE = INT_MAX, // greater than the number of stages
35};
36
40class Deparser : public Section {
41 static Deparser singleton_object;
42
43 public:
44 struct Val {
45 /* a phv or clot reference with optional associated POV phv reference */
46 Phv::Ref val;
47 int tag = -1;
49 std::reference_wrapper<int> lineno = val.lineno;
50 Val() = default;
51 Val(const Val &) = default;
52 Val(Val &&) = default;
53 Val &operator=(Val &&) = default;
54 virtual ~Val() {}
55 Val(gress_t gr, const value_t &v) : val(gr, DEPARSER_STAGE, v) {}
56 Val(gress_t gr, const value_t &v, const value_t &p) : val(gr, DEPARSER_STAGE, v) {
57 pov.emplace(gr, DEPARSER_STAGE, p);
58 }
59 Val(gress_t gr, int tag, const value_t &p) : tag(tag) {
60 pov.emplace(gr, DEPARSER_STAGE, p);
61 }
62 Val &operator=(const Val &a) {
63 val = a.val;
64 tag = a.tag;
65 pov = a.pov;
66 return *this;
67 }
68 explicit operator bool() const { return is_phv() || is_clot(); }
69 Phv::Slice operator*() const { return *val; }
70 Phv::Slice operator->() const { return *val; }
71 bool is_phv() const { return bool(val); }
72 bool is_clot() const { return tag >= 0; }
73 virtual bool check() const {
74 if (is_phv() && is_clot()) {
75 error(lineno, "Reference cannot be phv and clot at the same time");
76 return false;
77 }
78 if (is_phv()) {
79 return val.check();
80 } else if (is_clot()) {
81 if (pov.empty()) {
82 error(lineno, "Clot requires a pov bit");
83 return false;
84 }
85 } else {
86 error(lineno, "Unknown val");
87 return false;
88 }
89 return true;
90 }
91 };
92
93 struct ChecksumVal : public Val {
94 int mask = 0;
95 int swap = 0;
96 ChecksumVal(gress_t gr, const value_t &v, const value_t &m) : Val(gr, v) {
97 if ((val->lo % 8 != 0) || (val->hi % 8 != 7))
98 error(lineno, "Can only do checksums on byte-aligned container slices");
99 mask = ((1 << (val->hi + 1) / 8) - 1) ^ ((1 << val->lo / 8) - 1);
100
101 if (CHECKTYPE(m, tMAP)) {
102 for (auto &kv : m.map) {
103 if (kv.key == "pov") {
104 if (!pov.empty()) error(kv.value.lineno, "Duplicate POV");
105 pov.emplace_back(gr, DEPARSER_STAGE, kv.value);
106 } else if (kv.key == "swap" && CHECKTYPE(kv.value, tINT)) {
107 swap = kv.value.i;
108 } else {
109 error(m.lineno, "Unknown key for checksum: %s", value_desc(kv.key));
110 }
111 }
112 }
113 }
114 ChecksumVal(gress_t gr, int tag, const value_t &p) : Val(gr, tag, p) {}
115 ChecksumVal &operator=(const ChecksumVal &a) {
116 Val::operator=(a);
117 mask = a.mask;
118 swap = a.swap;
119 return *this;
120 }
121 ChecksumVal(const ChecksumVal &a) : Val(a) {
122 mask = a.mask;
123 swap = a.swap;
124 };
125 ChecksumVal() : Val() {}
126 ChecksumVal(ChecksumVal &&) = default;
127 ChecksumVal &operator=(ChecksumVal &&) = default;
128 bool check() const override {
129 if (is_phv()) {
130 if (mask == 0) error(lineno, "mask is 0 for phv checkum value?");
131 if (swap < 0 || swap > 3) error(lineno, "Invalid swap for phv checksum");
132 }
133 return Val::check();
134 }
135 };
136
138 std::map<int, std::vector<ChecksumVal>> entries;
139 std::map<int, Phv::Ref> pov;
140 std::set<int> checksum_unit_invert;
141 std::set<int> clot_tag_invert;
142 std::vector<ChecksumVal> clot_entries;
143 bool zeros_as_ones_en = false;
144 };
145
146 struct FDEntry;
147 std::vector<ChecksumVal> checksum_entries[2][MAX_DEPARSER_CHECKSUM_UNITS];
148 FullChecksumUnit full_checksum_unit[2][MAX_DEPARSER_CHECKSUM_UNITS];
149 int lineno[2];
150 std::vector<FDEntry> dictionary[2];
151 std::vector<Phv::Ref> pov_order[2];
153 bitvec phv_use[2];
154 std::set<int> constants[2];
155
156 struct Intrinsic {
157 struct Type;
158 Type *type;
159 int lineno;
160 std::vector<Val> vals;
161 Intrinsic(Type *t, int l) : type(t), lineno(l) {}
162 };
163 std::vector<Intrinsic> intrinsics;
164 struct Digest {
165 struct Type {
166 target_t target;
167 gress_t gress;
168 std::string name;
169 int count;
170 bool can_shift = false;
171 static std::map<std::string, Type *> all[TARGET_INDEX_LIMIT][2];
172
173 protected:
174 Type(target_t t, gress_t gr, const char *n, int cnt)
175 : target(t), gress(gr), name(n), count(cnt) {
176 BUG_CHECK(!all[target][gress].count(name), "Duplicate name %s", name.c_str());
177 all[target][gress][name] = this;
178 }
179 ~Type() { all[target][gress].erase(name); }
180
181 public:
182#define VIRTUAL_TARGET_METHODS(TARGET) \
183 virtual void setregs(Target::TARGET::deparser_regs &regs, Deparser &deparser, \
184 Deparser::Digest &data) { \
185 BUG("target mismatch"); \
186 }
187 FOR_ALL_REGISTER_SETS(VIRTUAL_TARGET_METHODS)
188#undef VIRTUAL_TARGET_METHODS
189 };
190
191 Type *type;
192 int lineno;
193 Val select;
194 int shift = 0;
195 std::map<int, std::vector<Phv::Ref>> layout;
196 std::unique_ptr<json::map> context_json;
197 Digest(Type *t, int lineno, VECTOR(pair_t) & data);
198 };
199 std::vector<Digest> digests;
200 Deparser();
201 ~Deparser();
202 void start(int lineno, VECTOR(value_t) args);
203 void input(VECTOR(value_t) args, value_t data);
204 void process();
205 std::vector<ChecksumVal> merge_csum_entries(const std::vector<ChecksumVal> &, int);
206 template <class TARGET>
207 void process(TARGET *);
208 void output(json::map &);
209 template <class REGS>
210 void gen_learn_quanta(REGS &, json::vector &);
211 template <class REGS>
212 void write_config(REGS &);
213
214 static const bitvec &PhvUse(gress_t gr) { return singleton_object.phv_use[gr]; }
215
216 static bool add_constant(gress_t gr, int c) {
217 if (!singleton_object.constants[gr].count(c)) {
218 singleton_object.constants[gr].insert(c);
219 if (int(singleton_object.constants[gr].size()) > Target::DEPARSER_CONSTANTS())
220 return false;
221 }
222 return true;
223 }
224
225 static int constant_idx(gress_t gr, int c) {
226 if (singleton_object.constants[gr].count(c))
227 return std::distance(singleton_object.constants[gr].begin(),
228 singleton_object.constants[gr].find(c));
229 return -1;
230 }
231
232 // @return constant value that will be deparsed
233 static int get_constant(gress_t gr, int phv_idx) {
234 int i = 0;
235 for (auto constant : singleton_object.constants[gr]) {
236 if ((phv_idx - 224) == i) {
237 return constant;
238 } else {
239 i++;
240 }
241 }
242 return -1;
243 }
244
245 // Writes POV information in json used for field dictionary logging
246 // and deparser resources
247 static void write_pov_in_json(json::map &fd, json::map &fd_entry, const Phv::Register *phv,
248 int bit, int offset) {
249 auto povName = Phv::get_pov_name(phv->uid, offset);
250 // Field dictionary logging
251 fd["POV PHV"] = phv->uid;
252 fd["POV Field bit"] = bit;
253 fd["POV Field Name"] = povName;
254 // Deparser resources
255 fd_entry["pov_bit"] = bit;
256 fd_entry["pov_name"] = povName;
257 return;
258 }
259
260 // Digest Handle Setup
261 // ------------------------------------------------------
262 // | Pipe ID | Field Type | Field List Handle |
263 // 31 ... 28 24 0
264 // Field List Handle = 24 bits
265 // Field List Type = 4 bits (Field list is 0x9)
266 // Pipe ID = 4 bits
268 static unsigned next_handle() {
269 return unique_table_offset << PIPE_ID_SHIFT | FIELD_HANDLE_START |
271 }
272
273 // gtest methods
274
276 static Deparser *gtest_get_deparser() { return &singleton_object; }
277
279 void gtest_clear();
280
281 private:
282 // Report deparser resources to JSON file
283 void report_resources_deparser_json(json::vector &fde_entries_i, json::vector &fde_entries_e);
284};
285
286#endif /* BACKENDS_TOFINO_BF_ASM_DEPARSER_H_ */
Definition bitvec.h:120
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition bf-asm/phv.h:186
Definition bf-asm/phv.h:83
Definition backends/tofino/bf-asm/json.h:300
Definition backends/tofino/bf-asm/json.h:222
static Deparser * gtest_get_deparser()
Get the singleton object for use in gtest.
Definition tofino/bf-asm/deparser.h:276
void process()
optionally process the data if not done during parsing
Definition tofino/bf-asm/deparser.cpp:654
void gtest_clear()
Clear/reset the deparser object.
Definition tofino/bf-asm/deparser.cpp:810
void input(VECTOR(value_t) args, value_t data)
Definition tofino/bf-asm/deparser.cpp:295
static unsigned unique_field_list_handle
Definition tofino/bf-asm/deparser.h:267
void start(int lineno, VECTOR(value_t) args)
process the arguments on the same line as the heading
Definition tofino/bf-asm/deparser.cpp:284
Definition tofino/bf-asm/deparser.h:137
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
Definition tofino/bf-asm/deparser.h:165
Definition tofino/bf-asm/deparser.cpp:33
Definition tofino/bf-asm/deparser.cpp:205
Definition tofino/bf-asm/deparser.h:44
Definition asm-types.h:150
Definition asm-types.h:114