P4C
The P4 Compiler
Loading...
Searching...
No Matches
tc/backend.h
1/*
2Copyright (C) 2023 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing,
11software distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions
14and limitations under the License.
15*/
16
17#ifndef BACKENDS_TC_BACKEND_H_
18#define BACKENDS_TC_BACKEND_H_
19
20#include <deque>
21
22#include "backends/ebpf/psa/ebpfPsaGen.h"
23#include "control-plane/p4RuntimeArchHandler.h"
24#include "ebpfCodeGen.h"
25#include "frontends/p4/evaluator/evaluator.h"
26#include "frontends/p4/parseAnnotations.h"
27#include "frontends/p4/parserCallGraph.h"
28#include "introspection.h"
29#include "ir/ir.h"
30#include "lib/error.h"
31#include "lib/nullstream.h"
32#include "lib/stringify.h"
33#include "options.h"
34#include "pnaProgramStructure.h"
35#include "tcAnnotations.h"
36#include "tc_defines.h"
37
38namespace P4::TC {
39
40extern cstring PnaMainParserInputMetaFields[TC::MAX_PNA_PARSER_META];
41extern cstring PnaMainInputMetaFields[TC::MAX_PNA_INPUT_META];
42extern cstring PnaMainOutputMetaFields[TC::MAX_PNA_OUTPUT_META];
43
45
46typedef struct decllist DECLLIST;
47struct decllist {
48 DECLLIST *link;
49 IR::Declaration *decl;
50};
51
52typedef struct stmtlist STMTLIST;
53struct stmtlist {
54 STMTLIST *link;
55 IR::Statement *stmt;
56};
57
58typedef struct container CONTAINER;
59struct container {
60 CONTAINER *link;
61 DECLLIST *temps;
62 STMTLIST *stmts;
63 IR::Statement *s;
64};
65
66enum WrType {
67 WR_VALUE = 1,
68 WR_CONCAT,
69 WR_ADD,
70 WR_SUB,
71 WR_MUL,
72 WR_BXSMUL,
73 WR_CAST,
74 WR_NEG,
75 WR_NOT,
76 WR_SHL_X,
77 WR_SHL_C,
78 WR_SHRA_X,
79 WR_SHRA_C,
80 WR_SHRL_X,
81 WR_SHRL_C,
82 WR_CMP,
83 WR_BITAND,
84 WR_BITOR,
85 WR_BITXOR,
86 WR_ADDSAT,
87 WR_SUBSAT,
88 WR_ASSIGN,
89};
90
91class WidthRec {
92 public:
93 WrType type;
94 union {
95 // if WR_VALUE
96 int value;
97 // if WR_CONCAT
98 struct {
99 int lhsw;
100 int rhsw;
101 // result width is implicit: is lhsw + rhsw
102 } concat;
103 // if WR_ADD, WR_SUB, WR_MUL, WR_NEG, WR_NOT, WR_BITAND,
104 // WR_BITOR, WR_BITXOR
105 struct {
106 int w;
107 } arith;
108 // if WR_BXSMUL
109 struct {
110 int bw;
111 unsigned int sv;
112 } bxsmul;
113 // if WR_CAST
114 struct {
115 int fw;
116 int tw;
117 } cast;
118 // if WR_SHL_X, WR_SHRA_X, WR_SHRL_X
119 struct {
120 int lw;
121 int rw;
122 } shift_x;
123 // if WR_SHL_C, WR_SHRA_C, WR_SRL_C
124 struct {
125 int lw;
126 unsigned int sv;
127 } shift_c;
128 // if WR_CMP
129 struct {
130 int w;
131 unsigned char cmp;
132#define CMP_EQ 0x01
133#define CMP_NE 0x02
134#define CMP_LT 0x03
135#define CMP_GE 0x04
136#define CMP_GT 0x05
137#define CMP_LE 0x06
138#define CMP_BASE 0x07
139#define CMP_SIGNED 0x08
140 } cmp;
141 // if WR_ADDSAT, WR_SUBSAT
142 struct {
143 int w;
144 bool issigned;
145 } sarith;
146 // if WR_ASSIGN
147 struct {
148 int w;
149 } assign;
150 // Naming union to avoid c++ warnings
151 } u;
152
153 public:
154 friend bool operator<(const WidthRec &l, const WidthRec &r) {
155 if (l.type != r.type) return (l.type < r.type);
156 switch (l.type) {
157 case WR_VALUE:
158 return (l.u.value < r.u.value);
159 break;
160 case WR_CONCAT:
161 return (
162 (l.u.concat.lhsw < r.u.concat.lhsw) ||
163 ((l.u.concat.lhsw == r.u.concat.lhsw) && (l.u.concat.rhsw < r.u.concat.rhsw)));
164 break;
165 case WR_ADD:
166 case WR_SUB:
167 case WR_MUL:
168 case WR_NEG:
169 case WR_NOT:
170 case WR_BITAND:
171 case WR_BITOR:
172 case WR_BITXOR:
173 return (l.u.arith.w < r.u.arith.w);
174 break;
175 case WR_BXSMUL:
176 return ((l.u.bxsmul.bw < r.u.bxsmul.bw) ||
177 ((l.u.bxsmul.bw == r.u.bxsmul.bw) && (l.u.bxsmul.sv < r.u.bxsmul.sv)));
178 break;
179 case WR_CAST:
180 return ((l.u.cast.fw < r.u.cast.fw) ||
181 ((l.u.cast.fw == r.u.cast.fw) && (l.u.cast.tw < r.u.cast.tw)));
182 break;
183 case WR_SHL_X:
184 case WR_SHRA_X:
185 case WR_SHRL_X:
186 return ((l.u.shift_x.lw < r.u.shift_x.lw) || ((l.u.shift_x.lw == r.u.shift_x.lw) &&
187 ((l.u.shift_x.rw < r.u.shift_x.rw))));
188 break;
189 case WR_SHL_C:
190 case WR_SHRA_C:
191 case WR_SHRL_C:
192 return ((l.u.shift_c.lw < r.u.shift_c.lw) || ((l.u.shift_c.lw == r.u.shift_c.lw) &&
193 ((l.u.shift_c.sv < r.u.shift_c.sv))));
194 break;
195 case WR_CMP:
196 return ((l.u.cmp.w < r.u.cmp.w) ||
197 ((l.u.cmp.w == r.u.cmp.w) && (l.u.cmp.cmp < r.u.cmp.cmp)));
198 break;
199 case WR_ADDSAT:
200 case WR_SUBSAT:
201 return ((l.u.sarith.w < r.u.sarith.w) ||
202 ((l.u.sarith.w == r.u.sarith.w) &&
203 (!l.u.sarith.issigned && r.u.sarith.issigned)));
204 break;
205 case WR_ASSIGN:
206 return (l.u.assign.w < r.u.assign.w);
207 break;
208 }
209 return (0);
210 }
211 friend bool operator==(const WidthRec &l, const WidthRec &r) {
212 if (l.type != r.type) return (0);
213 switch (l.type) {
214 case WR_VALUE:
215 return (l.u.value == r.u.value);
216 break;
217 case WR_CONCAT:
218 return ((l.u.concat.lhsw == r.u.concat.lhsw) &&
219 (l.u.concat.rhsw) == (r.u.concat.rhsw));
220 break;
221 case WR_ADD:
222 case WR_SUB:
223 case WR_MUL:
224 case WR_NEG:
225 case WR_NOT:
226 case WR_BITAND:
227 case WR_BITOR:
228 case WR_BITXOR:
229 return (l.u.arith.w == r.u.arith.w);
230 break;
231 case WR_BXSMUL:
232 return ((l.u.bxsmul.bw == r.u.bxsmul.bw) && (l.u.bxsmul.sv == r.u.bxsmul.sv));
233 break;
234 case WR_CAST:
235 return ((l.u.cast.fw == r.u.cast.fw) && (l.u.cast.tw == r.u.cast.tw));
236 break;
237 case WR_SHL_X:
238 case WR_SHRA_X:
239 case WR_SHRL_X:
240 return ((l.u.shift_x.lw == r.u.shift_x.lw) && (l.u.shift_x.rw == r.u.shift_x.rw));
241 break;
242 case WR_SHL_C:
243 case WR_SHRA_C:
244 case WR_SHRL_C:
245 return ((l.u.shift_c.lw == r.u.shift_c.lw) && (l.u.shift_c.sv == r.u.shift_c.sv));
246 break;
247 case WR_CMP:
248 return ((l.u.cmp.w == r.u.cmp.w) && (l.u.cmp.cmp == r.u.cmp.cmp));
249 break;
250 case WR_ADDSAT:
251 case WR_SUBSAT:
252 return ((l.u.sarith.w == r.u.sarith.w) &&
253 (l.u.sarith.issigned == r.u.sarith.issigned));
254 break;
255 case WR_ASSIGN:
256 return (l.u.assign.w == r.u.assign.w);
257 break;
258 }
259 return (1);
260 }
261 friend bool operator>(const WidthRec &l, const WidthRec &r) { return (r < l); }
262 friend bool operator>=(const WidthRec &l, const WidthRec &r) { return (!(l < r)); }
263 friend bool operator<=(const WidthRec &l, const WidthRec &r) { return (!(r < l)); }
264 friend bool operator!=(const WidthRec &l, const WidthRec &r) { return (!(l == r)); }
265};
266
267class ScanWidths : public Inspector {
268 private:
269 int nwr;
270 WidthRec *wrv;
271 P4::TypeMap *typemap;
272 P4::ReferenceMap *refmap;
273 EBPF::Target *target;
274 void insert_wr(WidthRec &);
275 void add_width(int);
276 void add_concat(int, int);
277 void add_arith(WrType, int);
278 void add_sarith(WrType, int, bool);
279 void add_bxsmul(int, unsigned int);
280 void add_cast(unsigned int, unsigned int);
281 bool bigXSmallMul(const IR::Expression *, const IR::Constant *);
282 void add_shift_c(WrType, unsigned int, unsigned int);
283 void add_shift_x(WrType, unsigned int, unsigned int);
284 void add_cmp(unsigned int, unsigned char);
285 void add_assign(unsigned int);
286
287 public:
288 explicit ScanWidths(P4::TypeMap *tm, P4::ReferenceMap *rm, EBPF::Target *tgt)
289 : nwr(0), wrv(0), typemap(tm), refmap(rm), target(tgt) {}
290 ~ScanWidths(void) { std::free(wrv); }
291 void expr_common(const IR::Expression *);
292 bool preorder(const IR::Expression *) override;
293 bool preorder(const IR::Concat *) override;
294 bool preorder(const IR::Add *) override;
295 bool preorder(const IR::Sub *) override;
296 bool preorder(const IR::Mul *) override;
297 bool preorder(const IR::Cast *) override;
298 bool preorder(const IR::Neg *) override;
299 bool preorder(const IR::Cmpl *) override;
300 bool preorder(const IR::Shl *) override;
301 bool preorder(const IR::Shr *) override;
302 bool preorder(const IR::Equ *) override;
303 bool preorder(const IR::Neq *) override;
304 bool preorder(const IR::Lss *) override;
305 bool preorder(const IR::Leq *) override;
306 bool preorder(const IR::Grt *) override;
307 bool preorder(const IR::Geq *) override;
308 bool preorder(const IR::BAnd *) override;
309 bool preorder(const IR::BOr *) override;
310 bool preorder(const IR::BXor *) override;
311 bool preorder(const IR::AddSat *) override;
312 bool preorder(const IR::SubSat *) override;
313 bool preorder(const IR::AssignmentStatement *) override;
314 bool preorder(const IR::MethodCallExpression *) override;
315 bool arith_common_2(const IR::Operation_Binary *, WrType, bool = true);
316 bool arith_common_1(const IR::Operation_Unary *, WrType, bool = true);
317 bool sarith_common_2(const IR::Operation_Binary *, WrType, bool = true);
318 profile_t init_apply(const IR::Node *) override;
319 void end_apply(const IR::Node *) override;
320 void revisit_visited();
321 void dump() const;
322 void gen_h(EBPF::CodeBuilder *) const;
323 void gen_c(EBPF::CodeBuilder *) const;
324};
325
329class ConvertToBackendIR : public Inspector {
330 public:
332 cstring instance_name;
333 unsigned instance_id;
334 bool is_num_elements;
335 int num_elements;
336 };
337 struct ExternBlock {
338 cstring externId;
339 cstring control_name;
340 unsigned no_of_instances;
341 cstring permissions;
343 };
344 enum CounterType { PACKETS, BYTES, PACKETS_AND_BYTES };
345 const IR::ToplevelBlock *tlb;
346 IR::TCPipeline *tcPipeline;
347 P4::ReferenceMap *refMap;
348 P4::TypeMap *typeMap;
349 TCOptions &options;
350 unsigned int tableCount = 0;
351 unsigned int actionCount = 0;
352 unsigned int metadataCount = 0;
353 unsigned int labelCount = 0;
354 unsigned int externCount = 0;
355 cstring pipelineName = nullptr;
356 cstring mainParserName = nullptr;
360 ordered_map<unsigned, unsigned> tableKeysizeList;
361 safe_vector<const IR::P4Table *> add_on_miss_tables;
365
366 public:
367 ConvertToBackendIR(const IR::ToplevelBlock *tlb, IR::TCPipeline *pipe, P4::ReferenceMap *refMap,
368 P4::TypeMap *typeMap, TCOptions &options)
369 : tlb(tlb), tcPipeline(pipe), refMap(refMap), typeMap(typeMap), options(options) {}
370 void setPipelineName();
371 cstring getPipelineName() { return pipelineName; };
372 bool preorder(const IR::P4Program *p) override;
373 void postorder(const IR::P4Action *a) override;
374 void postorder(const IR::P4Table *t) override;
375 void postorder(const IR::P4Program *p) override;
376 void postorder(const IR::Declaration_Instance *d) override;
377 void postorder(const IR::Type_Struct *ts) override;
378 safe_vector<const IR::TCKey *> processExternConstructor(const IR::Type_Extern *extn,
379 const IR::Declaration_Instance *decl,
380 struct ExternInstance *instance);
381 safe_vector<const IR::TCKey *> processExternControlPath(const IR::Type_Extern *extn,
382 const IR::Declaration_Instance *decl,
383 cstring eName);
384 cstring getControlPathKeyAnnotation(const IR::StructField *field);
385 unsigned GetAccessNumericValue(std::string_view access);
386 bool isDuplicateAction(const IR::P4Action *action);
387 bool isDuplicateOrNoAction(const IR::P4Action *action);
388 void updateDefaultHitAction(const IR::P4Table *t, IR::TCTable *tdef);
389 void updateDefaultMissAction(const IR::P4Table *t, IR::TCTable *tdef);
390 void updateConstEntries(const IR::P4Table *t, IR::TCTable *tdef);
391 void updateMatchType(const IR::P4Table *t, IR::TCTable *tabledef);
392 void updateTimerProfiles(IR::TCTable *tabledef);
393 void updatePnaDirectCounter(const IR::P4Table *t, IR::TCTable *tabledef, unsigned tentries);
394 void updatePnaDirectMeter(const IR::P4Table *t, IR::TCTable *tabledef, unsigned tentries);
395 bool isPnaParserMeta(const IR::Member *mem);
396 bool isPnaMainInputMeta(const IR::Member *mem);
397 bool isPnaMainOutputMeta(const IR::Member *mem);
398 unsigned int findMappedKernelMeta(const IR::Member *mem);
399 const IR::Expression *ExtractExpFromCast(const IR::Expression *exp);
400 unsigned getTcType(const IR::StringLiteral *sl);
401 unsigned getTableId(cstring tableName) const;
402 unsigned getActionId(cstring actionName) const;
403 cstring getExternId(cstring externName) const;
404 unsigned getExternInstanceId(cstring externName, cstring instanceName) const;
405 cstring processExternPermission(const IR::Type_Extern *ext);
406 unsigned getTableKeysize(unsigned tableId) const;
407 cstring externalName(const IR::IDeclaration *declaration) const;
408 cstring HandleTableAccessPermission(const IR::P4Table *t);
409 std::pair<cstring, cstring> *GetAnnotatedAccessPath(const IR::Annotation *anno);
410 void updateAddOnMissTable(const IR::P4Table *t);
411 bool checkParameterDirection(const IR::TCAction *tcAction);
412 bool hasExecuteMethod(const IR::Type_Extern *extn);
413 void addExternTypeInstance(const IR::Declaration_Instance *decl,
414 IR::TCExternInstance *tcExternInstance, cstring eName);
415 safe_vector<const IR::TCKey *> HandleTypeNameStructField(const IR::StructField *field,
416 const IR::Type_Extern *extn,
417 const IR::Declaration_Instance *decl,
418 int &kId, cstring annoName);
419 safe_vector<const IR::TCKey *> processCounterControlPathKeys(
420 const IR::Type_Struct *extern_control_path, const IR::Type_Extern *extn,
421 const IR::Declaration_Instance *decl);
422 CounterType toCounterType(const int type);
423};
424
425class Extern {
426 public:
427 static const cstring dropPacket;
428 static const cstring sendToPort;
429};
430
431class Backend : public PassManager {
432 public:
433 IR::ToplevelBlock *toplevel;
434 P4::ReferenceMap *refMap;
435 P4::TypeMap *typeMap;
436 TCOptions &options;
437 IR::TCPipeline *pipeline = new IR::TCPipeline();
440 TC::ParseTCAnnotations *parseTCAnno;
441 const IR::ToplevelBlock *top = nullptr;
442 EbpfOptions ebpfOption;
443 EBPF::Target *target;
444 const PNAEbpfGenerator *ebpf_program;
445 const ScanWidths *widths;
446
447 public:
448 explicit Backend(IR::ToplevelBlock *toplevel, P4::ReferenceMap *refMap, P4::TypeMap *typeMap,
449 TCOptions &options)
450 : toplevel(toplevel), refMap(refMap), typeMap(typeMap), options(options), widths(0) {
451 setName("BackEnd");
452 }
453 bool process();
454 bool ebpfCodeGen(P4::ReferenceMap *refMap, P4::TypeMap *typeMap, const IR::P4Program *);
455 void serialize() const;
456 bool serializeIntrospectionJson(std::ostream &out) const;
457 bool emitCFile();
458};
459
460} // namespace P4::TC
461
462#endif /* BACKENDS_TC_BACKEND_H_ */
Definition ebpf/codeGen.h:33
Definition ebpf/target.h:44
Definition ebpfOptions.h:26
Definition node.h:94
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition tc/backend.h:329
bool isPnaParserMeta(const IR::Member *mem)
Definition tc/backend.cpp:2969
Definition tc/backend.h:337
Definition tc/backend.h:425
This pass generates introspection JSON into user specified file.
Definition introspection.h:148
Definition ebpfCodeGen.h:36
Definition tcAnnotations.h:25
Definition tc/backend.h:267
Definition backends/tc/options.h:25
Definition tc/backend.h:91
Definition typeMap.h:41
Definition visitor.h:78
Definition cstring.h:85
Definition ordered_map.h:32
Definition safe_vector.h:27
This file defines functions for the pass to generate the introspection file.
Definition tc/backend.cpp:27
Definition tc/backend.h:59
Definition tc/backend.h:47
Definition tc/backend.h:53