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 EBPF::Target *target;
273 void insert_wr(WidthRec &);
274 void add_width(int);
275 void add_concat(int, int);
276 void add_arith(WrType, int);
277 void add_sarith(WrType, int, bool);
278 void add_bxsmul(int, unsigned int);
279 void add_cast(unsigned int, unsigned int);
280 bool bigXSmallMul(const IR::Expression *, const IR::Constant *);
281 void add_shift_c(WrType, unsigned int, unsigned int);
282 void add_shift_x(WrType, unsigned int, unsigned int);
283 void add_cmp(unsigned int, unsigned char);
284 void add_assign(unsigned int);
285
286 public:
287 explicit ScanWidths(P4::TypeMap *tm, EBPF::Target *tgt)
288 : nwr(0), wrv(0), typemap(tm), target(tgt) {}
289 ~ScanWidths(void) { std::free(wrv); }
290 void expr_common(const IR::Expression *);
291 bool preorder(const IR::Expression *) override;
292 bool preorder(const IR::Concat *) override;
293 bool preorder(const IR::Add *) override;
294 bool preorder(const IR::Sub *) override;
295 bool preorder(const IR::Mul *) override;
296 bool preorder(const IR::Cast *) override;
297 bool preorder(const IR::Neg *) override;
298 bool preorder(const IR::Cmpl *) override;
299 bool preorder(const IR::Shl *) override;
300 bool preorder(const IR::Shr *) override;
301 bool preorder(const IR::Equ *) override;
302 bool preorder(const IR::Neq *) override;
303 bool preorder(const IR::Lss *) override;
304 bool preorder(const IR::Leq *) override;
305 bool preorder(const IR::Grt *) override;
306 bool preorder(const IR::Geq *) override;
307 bool preorder(const IR::BAnd *) override;
308 bool preorder(const IR::BOr *) override;
309 bool preorder(const IR::BXor *) override;
310 bool preorder(const IR::AddSat *) override;
311 bool preorder(const IR::SubSat *) override;
312 bool preorder(const IR::AssignmentStatement *) override;
313 bool arith_common_2(const IR::Operation_Binary *, WrType, bool = true);
314 bool arith_common_1(const IR::Operation_Unary *, WrType, bool = true);
315 bool sarith_common_2(const IR::Operation_Binary *, WrType, bool = true);
316 profile_t init_apply(const IR::Node *) override;
317 void end_apply(const IR::Node *) override;
318 void revisit_visited();
319 void dump() const;
320 void gen_h(EBPF::CodeBuilder *) const;
321 void gen_c(EBPF::CodeBuilder *) const;
322};
323
327class ConvertToBackendIR : public Inspector {
328 public:
330 cstring instance_name;
331 unsigned instance_id;
332 bool is_num_elements;
333 int num_elements;
334 };
335 struct ExternBlock {
336 cstring externId;
337 cstring control_name;
338 unsigned no_of_instances;
339 cstring permissions;
341 };
342 enum CounterType { PACKETS, BYTES, PACKETS_AND_BYTES };
343 const IR::ToplevelBlock *tlb;
344 IR::TCPipeline *tcPipeline;
345 P4::ReferenceMap *refMap;
346 P4::TypeMap *typeMap;
347 TCOptions &options;
348 unsigned int tableCount = 0;
349 unsigned int actionCount = 0;
350 unsigned int metadataCount = 0;
351 unsigned int labelCount = 0;
352 unsigned int externCount = 0;
353 cstring pipelineName = nullptr;
354 cstring mainParserName = nullptr;
358 ordered_map<unsigned, unsigned> tableKeysizeList;
359 safe_vector<const IR::P4Table *> add_on_miss_tables;
363
364 public:
365 ConvertToBackendIR(const IR::ToplevelBlock *tlb, IR::TCPipeline *pipe, P4::ReferenceMap *refMap,
366 P4::TypeMap *typeMap, TCOptions &options)
367 : tlb(tlb), tcPipeline(pipe), refMap(refMap), typeMap(typeMap), options(options) {}
368 void setPipelineName();
369 cstring getPipelineName() { return pipelineName; };
370 bool preorder(const IR::P4Program *p) override;
371 void postorder(const IR::P4Action *a) override;
372 void postorder(const IR::P4Table *t) override;
373 void postorder(const IR::P4Program *p) override;
374 void postorder(const IR::Declaration_Instance *d) override;
375 void postorder(const IR::Type_Struct *ts) override;
376 safe_vector<const IR::TCKey *> processExternConstructor(const IR::Type_Extern *extn,
377 const IR::Declaration_Instance *decl,
378 struct ExternInstance *instance);
379 safe_vector<const IR::TCKey *> processExternControlPath(const IR::Type_Extern *extn,
380 const IR::Declaration_Instance *decl,
381 cstring eName);
382 cstring getControlPathKeyAnnotation(const IR::StructField *field);
383 unsigned GetAccessNumericValue(std::string_view access);
384 bool isDuplicateAction(const IR::P4Action *action);
385 bool isDuplicateOrNoAction(const IR::P4Action *action);
386 void updateDefaultHitAction(const IR::P4Table *t, IR::TCTable *tdef);
387 void updateDefaultMissAction(const IR::P4Table *t, IR::TCTable *tdef);
388 void updateConstEntries(const IR::P4Table *t, IR::TCTable *tdef);
389 void updateMatchType(const IR::P4Table *t, IR::TCTable *tabledef);
390 void updateTimerProfiles(IR::TCTable *tabledef);
391 void updatePnaDirectCounter(const IR::P4Table *t, IR::TCTable *tabledef, unsigned tentries);
392 void updatePnaDirectMeter(const IR::P4Table *t, IR::TCTable *tabledef, unsigned tentries);
393 bool isPnaParserMeta(const IR::Member *mem);
394 bool isPnaMainInputMeta(const IR::Member *mem);
395 bool isPnaMainOutputMeta(const IR::Member *mem);
396 unsigned int findMappedKernelMeta(const IR::Member *mem);
397 const IR::Expression *ExtractExpFromCast(const IR::Expression *exp);
398 unsigned getTcType(const IR::StringLiteral *sl);
399 unsigned getTableId(cstring tableName) const;
400 unsigned getActionId(cstring actionName) const;
401 cstring getExternId(cstring externName) const;
402 unsigned getExternInstanceId(cstring externName, cstring instanceName) const;
403 cstring processExternPermission(const IR::Type_Extern *ext);
404 unsigned getTableKeysize(unsigned tableId) const;
405 cstring externalName(const IR::IDeclaration *declaration) const;
406 cstring HandleTableAccessPermission(const IR::P4Table *t);
407 std::pair<cstring, cstring> *GetAnnotatedAccessPath(const IR::Annotation *anno);
408 void updateAddOnMissTable(const IR::P4Table *t);
409 bool checkParameterDirection(const IR::TCAction *tcAction);
410 bool hasExecuteMethod(const IR::Type_Extern *extn);
411 void addExternTypeInstance(const IR::Declaration_Instance *decl,
412 IR::TCExternInstance *tcExternInstance, cstring eName);
413 safe_vector<const IR::TCKey *> HandleTypeNameStructField(const IR::StructField *field,
414 const IR::Type_Extern *extn,
415 const IR::Declaration_Instance *decl,
416 int &kId, cstring annoName);
417 safe_vector<const IR::TCKey *> processCounterControlPathKeys(
418 const IR::Type_Struct *extern_control_path, const IR::Type_Extern *extn,
419 const IR::Declaration_Instance *decl);
420 CounterType toCounterType(const int type);
421};
422
423class Extern {
424 public:
425 static const cstring dropPacket;
426 static const cstring sendToPort;
427};
428
429class Backend : public PassManager {
430 public:
431 IR::ToplevelBlock *toplevel;
432 P4::ReferenceMap *refMap;
433 P4::TypeMap *typeMap;
434 TCOptions &options;
435 IR::TCPipeline *pipeline = new IR::TCPipeline();
438 TC::ParseTCAnnotations *parseTCAnno;
439 const IR::ToplevelBlock *top = nullptr;
440 EbpfOptions ebpfOption;
441 EBPF::Target *target;
442 const PNAEbpfGenerator *ebpf_program;
443 const ScanWidths *widths;
444
445 public:
446 explicit Backend(IR::ToplevelBlock *toplevel, P4::ReferenceMap *refMap, P4::TypeMap *typeMap,
447 TCOptions &options)
448 : toplevel(toplevel), refMap(refMap), typeMap(typeMap), options(options), widths(0) {
449 setName("BackEnd");
450 }
451 bool process();
452 bool ebpfCodeGen(P4::ReferenceMap *refMap, P4::TypeMap *typeMap, const IR::P4Program *);
453 void serialize() const;
454 bool serializeIntrospectionJson(std::ostream &out) const;
455 bool emitCFile();
456};
457
458} // namespace P4::TC
459
460#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:327
bool isPnaParserMeta(const IR::Member *mem)
Definition tc/backend.cpp:2950
Definition tc/backend.h:335
Definition tc/backend.h:423
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