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 "frontends/p4/evaluator/evaluator.h"
25#include "frontends/p4/parseAnnotations.h"
26#include "frontends/p4/parserCallGraph.h"
27#include "introspection.h"
28#include "ir/ir.h"
29#include "lib/error.h"
30#include "lib/nullstream.h"
31#include "lib/stringify.h"
32#include "options.h"
33#include "pnaProgramStructure.h"
34#include "tcAnnotations.h"
35#include "tc_defines.h"
36
37namespace P4::TC {
38
39extern cstring PnaMainParserInputMetaFields[TC::MAX_PNA_PARSER_META];
40extern cstring PnaMainInputMetaFields[TC::MAX_PNA_INPUT_META];
41extern cstring PnaMainOutputMetaFields[TC::MAX_PNA_OUTPUT_META];
42
44
45typedef struct decllist DECLLIST;
46struct decllist {
47 DECLLIST *link;
48 IR::Declaration *decl;
49};
50
51typedef struct stmtlist STMTLIST;
52struct stmtlist {
53 STMTLIST *link;
54 IR::Statement *stmt;
55};
56
57typedef struct container CONTAINER;
58struct container {
59 CONTAINER *link;
60 DECLLIST *temps;
61 STMTLIST *stmts;
62 IR::Statement *s;
63};
64
65enum WrType {
66 WR_VALUE = 1,
67 WR_CONCAT,
68 WR_ADD,
69 WR_SUB,
70 WR_MUL,
71 WR_BXSMUL,
72 WR_CAST,
73 WR_NEG,
74 WR_NOT,
75 WR_SHL_X,
76 WR_SHL_C,
77 WR_SHRA_X,
78 WR_SHRA_C,
79 WR_SHRL_X,
80 WR_SHRL_C,
81 WR_CMP,
82 WR_BITAND,
83 WR_BITOR,
84 WR_BITXOR,
85 WR_ADDSAT,
86 WR_SUBSAT,
87 WR_ASSIGN,
88};
89
90class WidthRec {
91 public:
92 WrType type;
93 union {
94 // if WR_VALUE
95 int value;
96 // if WR_CONCAT
97 struct {
98 int lhsw;
99 int rhsw;
100 // result width is implicit: is lhsw + rhsw
101 } concat;
102 // if WR_ADD, WR_SUB, WR_MUL, WR_NEG, WR_NOT, WR_BITAND,
103 // WR_BITOR, WR_BITXOR
104 struct {
105 int w;
106 } arith;
107 // if WR_BXSMUL
108 struct {
109 int bw;
110 unsigned int sv;
111 } bxsmul;
112 // if WR_CAST
113 struct {
114 int fw;
115 int tw;
116 } cast;
117 // if WR_SHL_X, WR_SHRA_X, WR_SHRL_X
118 struct {
119 int lw;
120 int rw;
121 } shift_x;
122 // if WR_SHL_C, WR_SHRA_C, WR_SRL_C
123 struct {
124 int lw;
125 unsigned int sv;
126 } shift_c;
127 // if WR_CMP
128 struct {
129 int w;
130 unsigned char cmp;
131#define CMP_EQ 0x01
132#define CMP_NE 0x02
133#define CMP_LT 0x03
134#define CMP_GE 0x04
135#define CMP_GT 0x05
136#define CMP_LE 0x06
137#define CMP_BASE 0x07
138#define CMP_SIGNED 0x08
139 } cmp;
140 // if WR_ADDSAT, WR_SUBSAT
141 struct {
142 int w;
143 bool issigned;
144 } sarith;
145 // if WR_ASSIGN
146 struct {
147 int w;
148 } assign;
149 // Naming union to avoid c++ warnings
150 } u;
151
152 public:
153 friend bool operator<(const WidthRec &l, const WidthRec &r) {
154 if (l.type != r.type) return (l.type < r.type);
155 switch (l.type) {
156 case WR_VALUE:
157 return (l.u.value < r.u.value);
158 break;
159 case WR_CONCAT:
160 return (
161 (l.u.concat.lhsw < r.u.concat.lhsw) ||
162 ((l.u.concat.lhsw == r.u.concat.lhsw) && (l.u.concat.rhsw < r.u.concat.rhsw)));
163 break;
164 case WR_ADD:
165 case WR_SUB:
166 case WR_MUL:
167 case WR_NEG:
168 case WR_NOT:
169 case WR_BITAND:
170 case WR_BITOR:
171 case WR_BITXOR:
172 return (l.u.arith.w < r.u.arith.w);
173 break;
174 case WR_BXSMUL:
175 return ((l.u.bxsmul.bw < r.u.bxsmul.bw) ||
176 ((l.u.bxsmul.bw == r.u.bxsmul.bw) && (l.u.bxsmul.sv < r.u.bxsmul.sv)));
177 break;
178 case WR_CAST:
179 return ((l.u.cast.fw < r.u.cast.fw) ||
180 ((l.u.cast.fw == r.u.cast.fw) && (l.u.cast.tw < r.u.cast.tw)));
181 break;
182 case WR_SHL_X:
183 case WR_SHRA_X:
184 case WR_SHRL_X:
185 return ((l.u.shift_x.lw < r.u.shift_x.lw) || ((l.u.shift_x.lw == r.u.shift_x.lw) &&
186 ((l.u.shift_x.rw < r.u.shift_x.rw))));
187 break;
188 case WR_SHL_C:
189 case WR_SHRA_C:
190 case WR_SHRL_C:
191 return ((l.u.shift_c.lw < r.u.shift_c.lw) || ((l.u.shift_c.lw == r.u.shift_c.lw) &&
192 ((l.u.shift_c.sv < r.u.shift_c.sv))));
193 break;
194 case WR_CMP:
195 return ((l.u.cmp.w < r.u.cmp.w) ||
196 ((l.u.cmp.w == r.u.cmp.w) && (l.u.cmp.cmp < r.u.cmp.cmp)));
197 break;
198 case WR_ADDSAT:
199 case WR_SUBSAT:
200 return ((l.u.sarith.w < r.u.sarith.w) ||
201 ((l.u.sarith.w == r.u.sarith.w) &&
202 (!l.u.sarith.issigned && r.u.sarith.issigned)));
203 break;
204 case WR_ASSIGN:
205 return (l.u.assign.w < r.u.assign.w);
206 break;
207 }
208 return (0);
209 }
210 friend bool operator==(const WidthRec &l, const WidthRec &r) {
211 if (l.type != r.type) return (0);
212 switch (l.type) {
213 case WR_VALUE:
214 return (l.u.value == r.u.value);
215 break;
216 case WR_CONCAT:
217 return ((l.u.concat.lhsw == r.u.concat.lhsw) &&
218 (l.u.concat.rhsw) == (r.u.concat.rhsw));
219 break;
220 case WR_ADD:
221 case WR_SUB:
222 case WR_MUL:
223 case WR_NEG:
224 case WR_NOT:
225 case WR_BITAND:
226 case WR_BITOR:
227 case WR_BITXOR:
228 return (l.u.arith.w == r.u.arith.w);
229 break;
230 case WR_BXSMUL:
231 return ((l.u.bxsmul.bw == r.u.bxsmul.bw) && (l.u.bxsmul.sv == r.u.bxsmul.sv));
232 break;
233 case WR_CAST:
234 return ((l.u.cast.fw == r.u.cast.fw) && (l.u.cast.tw == r.u.cast.tw));
235 break;
236 case WR_SHL_X:
237 case WR_SHRA_X:
238 case WR_SHRL_X:
239 return ((l.u.shift_x.lw == r.u.shift_x.lw) && (l.u.shift_x.rw == r.u.shift_x.rw));
240 break;
241 case WR_SHL_C:
242 case WR_SHRA_C:
243 case WR_SHRL_C:
244 return ((l.u.shift_c.lw == r.u.shift_c.lw) && (l.u.shift_c.sv == r.u.shift_c.sv));
245 break;
246 case WR_CMP:
247 return ((l.u.cmp.w == r.u.cmp.w) && (l.u.cmp.cmp == r.u.cmp.cmp));
248 break;
249 case WR_ADDSAT:
250 case WR_SUBSAT:
251 return ((l.u.sarith.w == r.u.sarith.w) &&
252 (l.u.sarith.issigned == r.u.sarith.issigned));
253 break;
254 case WR_ASSIGN:
255 return (l.u.assign.w == r.u.assign.w);
256 break;
257 }
258 return (1);
259 }
260 friend bool operator>(const WidthRec &l, const WidthRec &r) { return (r < l); }
261 friend bool operator>=(const WidthRec &l, const WidthRec &r) { return (!(l < r)); }
262 friend bool operator<=(const WidthRec &l, const WidthRec &r) { return (!(r < l)); }
263 friend bool operator!=(const WidthRec &l, const WidthRec &r) { return (!(l == r)); }
264};
265
266class ScanWidths : public Inspector {
267 private:
268 int nwr;
269 WidthRec *wrv;
270 P4::TypeMap *typemap;
271 P4::ReferenceMap *refmap;
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, P4::ReferenceMap *rm, EBPF::Target *tgt)
288 : nwr(0), wrv(0), typemap(tm), refmap(rm), 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 preorder(const IR::MethodCallExpression *) override;
314 bool arith_common_2(const IR::Operation_Binary *, WrType, bool = true);
315 bool arith_common_1(const IR::Operation_Unary *, WrType, bool = true);
316 bool sarith_common_2(const IR::Operation_Binary *, WrType, bool = true);
317 profile_t init_apply(const IR::Node *) override;
318 void end_apply(const IR::Node *) override;
319 void revisit_visited();
320 void dump() const;
321 void gen_h(EBPF::CodeBuilder *) const;
322 void gen_c(EBPF::CodeBuilder *) const;
323};
324
328class ConvertToBackendIR : public Inspector {
329 public:
331 cstring instance_name;
332 unsigned instance_id;
333 bool is_num_elements;
334 int num_elements;
335 };
336 struct ExternBlock {
337 cstring externId;
338 cstring control_name;
339 unsigned no_of_instances;
340 cstring permissions;
342 };
343 enum CounterType { PACKETS, BYTES, PACKETS_AND_BYTES };
344 const IR::ToplevelBlock *tlb;
345 IR::TCPipeline *tcPipeline;
346 P4::ReferenceMap *refMap;
347 P4::TypeMap *typeMap;
348 TCOptions &options;
349 unsigned int tableCount = 0;
350 unsigned int actionCount = 0;
351 unsigned int metadataCount = 0;
352 unsigned int labelCount = 0;
353 unsigned int externCount = 0;
354 cstring pipelineName = nullptr;
355 cstring mainParserName = nullptr;
359 ordered_map<unsigned, unsigned> tableKeysizeList;
360 safe_vector<const IR::P4Table *> add_on_miss_tables;
364
365 public:
366 ConvertToBackendIR(const IR::ToplevelBlock *tlb, IR::TCPipeline *pipe, P4::ReferenceMap *refMap,
367 P4::TypeMap *typeMap, TCOptions &options)
368 : tlb(tlb), tcPipeline(pipe), refMap(refMap), typeMap(typeMap), options(options) {}
369 void setPipelineName();
370 cstring getPipelineName() { return pipelineName; };
371 bool preorder(const IR::P4Program *p) override;
372 void postorder(const IR::P4Action *a) override;
373 void postorder(const IR::P4Table *t) override;
374 void postorder(const IR::P4Program *p) override;
375 void postorder(const IR::Declaration_Instance *d) override;
376 void postorder(const IR::Type_Struct *ts) override;
377 safe_vector<const IR::TCKey *> processExternConstructor(const IR::Type_Extern *extn,
378 const IR::Declaration_Instance *decl,
379 struct ExternInstance *instance);
380 safe_vector<const IR::TCKey *> processExternControlPath(const IR::Type_Extern *extn,
381 const IR::Declaration_Instance *decl,
382 cstring eName);
383 cstring getControlPathKeyAnnotation(const IR::StructField *field);
384 unsigned GetAccessNumericValue(std::string_view access);
385 bool isDuplicateAction(const IR::P4Action *action);
386 bool isDuplicateOrNoAction(const IR::P4Action *action);
387 void updateDefaultHitAction(const IR::P4Table *t, IR::TCTable *tdef);
388 void updateDefaultMissAction(const IR::P4Table *t, IR::TCTable *tdef);
389 void updateConstEntries(const IR::P4Table *t, IR::TCTable *tdef);
390 void updateMatchType(const IR::P4Table *t, IR::TCTable *tabledef);
391 void updateTimerProfiles(IR::TCTable *tabledef);
392 void updatePnaDirectCounter(const IR::P4Table *t, IR::TCTable *tabledef, unsigned tentries);
393 void updatePnaDirectMeter(const IR::P4Table *t, IR::TCTable *tabledef, unsigned tentries);
394 bool isPnaParserMeta(const IR::Member *mem);
395 bool isPnaMainInputMeta(const IR::Member *mem);
396 bool isPnaMainOutputMeta(const IR::Member *mem);
397 unsigned int findMappedKernelMeta(const IR::Member *mem);
398 const IR::Expression *ExtractExpFromCast(const IR::Expression *exp);
399 unsigned getTcType(const IR::StringLiteral *sl);
400 unsigned getTableId(cstring tableName) const;
401 unsigned getActionId(cstring actionName) const;
402 cstring getExternId(cstring externName) const;
403 unsigned getExternInstanceId(cstring externName, cstring instanceName) const;
404 cstring processExternPermission(const IR::Type_Extern *ext);
405 unsigned getTableKeysize(unsigned tableId) const;
406 cstring externalName(const IR::IDeclaration *declaration) const;
407 cstring HandleTableAccessPermission(const IR::P4Table *t);
408 std::pair<cstring, cstring> *GetAnnotatedAccessPath(const IR::Annotation *anno);
409 void updateAddOnMissTable(const IR::P4Table *t);
410 bool checkParameterDirection(const IR::TCAction *tcAction);
411 bool hasExecuteMethod(const IR::Type_Extern *extn);
412 void addExternTypeInstance(const IR::Declaration_Instance *decl,
413 IR::TCExternInstance *tcExternInstance, cstring eName);
414 safe_vector<const IR::TCKey *> HandleTypeNameStructField(const IR::StructField *field,
415 const IR::Type_Extern *extn,
416 const IR::Declaration_Instance *decl,
417 int &kId, cstring annoName);
418 safe_vector<const IR::TCKey *> processCounterControlPathKeys(
419 const IR::Type_Struct *extern_control_path, const IR::Type_Extern *extn,
420 const IR::Declaration_Instance *decl);
421 CounterType toCounterType(const int type);
422};
423
424class Extern {
425 public:
426 static const cstring dropPacket;
427 static const cstring sendToPort;
428};
429
430class Backend : public PassManager {
431 public:
432 IR::ToplevelBlock *toplevel;
433 P4::ReferenceMap *refMap;
434 P4::TypeMap *typeMap;
435 TCOptions &options;
436 IR::TCPipeline *pipeline = new IR::TCPipeline();
439 TC::ParseTCAnnotations *parseTCAnno;
440 const IR::ToplevelBlock *top = nullptr;
441 EbpfOptions ebpfOption;
442 EBPF::Target *target;
443 const PNAEbpfGenerator *ebpf_program;
444 const ScanWidths *widths;
445
446 public:
447 explicit Backend(IR::ToplevelBlock *toplevel, P4::ReferenceMap *refMap, P4::TypeMap *typeMap,
448 TCOptions &options)
449 : toplevel(toplevel), refMap(refMap), typeMap(typeMap), options(options), widths(0) {
450 setName("BackEnd");
451 }
452 bool process();
453 bool ebpfCodeGen(P4::ReferenceMap *refMap, P4::TypeMap *typeMap, const IR::P4Program *);
454 void serialize() const;
455 bool serializeIntrospectionJson(std::ostream &out) const;
456 bool emitCFile();
457};
458
459} // namespace P4::TC
460
461#endif /* BACKENDS_TC_BACKEND_H_ */
Definition ebpf/codeGen.h:33
Definition ebpf/target.h:44
Definition ebpfOptions.h:26
Definition node.h:53
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition tc/backend.h:328
bool isPnaParserMeta(const IR::Member *mem)
Definition tc/backend.cpp:2969
Definition tc/backend.h:336
Definition tc/backend.h:424
This pass generates introspection JSON into user specified file.
Definition introspection.h:148
Definition ebpfCodeGen.h:29
Definition tcAnnotations.h:25
Definition tc/backend.h:266
Definition backends/tc/options.h:25
Definition tc/backend.h:90
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:28
Definition tc/backend.h:58
Definition tc/backend.h:46
Definition tc/backend.h:52