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