P4C
The P4 Compiler
Loading...
Searching...
No Matches
tcExterns.h
1/*
2Copyright (C) 2024 Intel Corporation
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6http://www.apache.org/licenses/LICENSE-2.0
7Unless required by applicable law or agreed to in writing,
8software distributed under the License is distributed on an "AS IS" BASIS,
9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10See the License for the specific language governing permissions
11and limitations under the License.
12*/
13
14#ifndef BACKENDS_TC_TCEXTERNS_H_
15#define BACKENDS_TC_TCEXTERNS_H_
16
17#include "backend.h"
18#include "ebpfCodeGen.h"
19
20namespace P4::TC {
21
22using namespace P4::literals;
23
26
27class EBPFCounterPNA : public EBPF::EBPFCounterPSA {
28 const IR::Declaration_Instance *di;
29 cstring tblname;
30
31 public:
32 EBPFCounterPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *di,
33 cstring name, EBPF::CodeGenInspector *codeGen, cstring tblname)
34 : EBPF::EBPFCounterPSA(program, di, name, codeGen) {
35 this->tblname = tblname;
36 this->di = di;
37 }
38 EBPFCounterPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *di,
39 cstring name, EBPF::CodeGenInspector *codeGen)
40 : EBPF::EBPFCounterPSA(program, di, name, codeGen) {
41 this->di = di;
42 }
43
44 void emitDirectMethodInvocation(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
45 const ConvertToBackendIR *tcIR);
46 void emitMethodInvocation(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
47 ControlBodyTranslatorPNA *translator);
48 virtual void emitCounterUpdate(EBPF::CodeBuilder *builder, const ConvertToBackendIR *tcIR);
49 virtual void emitCount(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
50 ControlBodyTranslatorPNA *translator);
51};
52
53class EBPFRegisterPNA : public EBPF::EBPFTableBase {
54 protected:
55 cstring instanceName;
56 const IR::Type *keyArg;
57 const IR::Type *valueArg;
58 EBPF::EBPFType *keyType;
59 EBPF::EBPFType *valueType;
60
61 public:
62 EBPFRegisterPNA(const EBPF::EBPFProgram *program, cstring instanceName,
63 const IR::Declaration_Instance *di, EBPF::CodeGenInspector *codeGen)
64 : EBPF::EBPFTableBase(program, instanceName, codeGen) {
65 CHECK_NULL(di);
66 this->instanceName = di->toString();
67 if (!di->type->is<IR::Type_Specialized>()) {
68 ::P4::error(ErrorType::ERR_MODEL, "Missing specialization: %1%", di);
69 return;
70 }
71 auto ts = di->type->to<IR::Type_Specialized>();
72
73 if (ts->arguments->size() != PARAM_INDEX_2) {
74 ::P4::error(ErrorType::ERR_MODEL, "Expected a type specialized with two arguments: %1%",
75 ts);
76 return;
77 }
78
79 this->valueArg = ts->arguments->at(0);
80 this->keyArg = ts->arguments->at(1);
81
82 this->keyType = EBPF::EBPFTypeFactory::instance->create(keyArg);
83 this->valueType = EBPF::EBPFTypeFactory::instance->create(valueArg);
84 }
85 void emitRegisterRead(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
86 ControlBodyTranslatorPNA *translator,
87 const IR::Expression *leftExpression);
88 void emitRegisterWrite(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
89 ControlBodyTranslatorPNA *translator);
90 void emitInitializer(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
91 ControlBodyTranslatorPNA *translator);
92};
93
94class EBPFTablePNADirectCounterPropertyVisitor : public EBPF::EBPFTablePsaPropertyVisitor {
95 public:
96 explicit EBPFTablePNADirectCounterPropertyVisitor(EBPF::EBPFTablePSA *table)
98
99 bool preorder(const IR::PathExpression *pe) override {
100 auto decl = table->program->refMap->getDeclaration(pe->path, true);
101 auto di = decl->to<IR::Declaration_Instance>();
102 CHECK_NULL(di);
103 if (EBPF::EBPFObject::getSpecializedTypeName(di) != "DirectCounter") {
104 ::P4::error(ErrorType::ERR_UNEXPECTED,
105 "%1%: not a DirectCounter, see declaration of %2%", pe, decl);
106 return false;
107 }
108 auto counterName = EBPF::EBPFObject::externalName(di);
109 auto tblname = table->table->container->name.originalName;
110 auto ctr = new EBPFCounterPNA(table->program, di, counterName, table->codeGen, tblname);
111 table->counters.emplace_back(std::make_pair(counterName, ctr));
112 return false;
113 }
114
115 void visitTableProperty() {
116 EBPF::EBPFTablePsaPropertyVisitor::visitTableProperty("pna_direct_counter"_cs);
117 }
118};
119
120class InternetChecksumAlgorithmPNA : public EBPF::EBPFHashAlgorithmPSA {
121 protected:
122 cstring stateVar;
123 cstring csumVar;
124
125 void updateChecksum(EBPF::CodeBuilder *builder, const ArgumentsList &arguments, bool addData);
126
127 public:
128 InternetChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name)
129 : EBPF::EBPFHashAlgorithmPSA(program, name) {}
130
131 void emitVariables(EBPF::CodeBuilder *builder, const IR::Declaration_Instance *decl) override;
132
133 void emitClear(EBPF::CodeBuilder *builder) override;
134 void emitAddData(EBPF::CodeBuilder *builder, const ArgumentsList &arguments) override;
135 void emitGet(EBPF::CodeBuilder *builder) override;
136
137 void emitSubtractData(EBPF::CodeBuilder *builder, const ArgumentsList &arguments) override;
138
139 void emitGetInternalState(EBPF::CodeBuilder *builder) override;
140 void emitSetInternalState(EBPF::CodeBuilder *builder,
141 const IR::MethodCallExpression *expr) override;
142 cstring getConvertByteOrderFunction(unsigned widthToEmit, cstring byte_order);
143};
144
145class EBPFChecksumPNA : public EBPF::EBPFChecksumPSA {
146 protected:
147 void init(const EBPF::EBPFProgram *program, cstring name, int type);
148
149 public:
150 EBPFChecksumPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *block,
151 cstring name)
152 : EBPF::EBPFChecksumPSA(program, block, name) {
153 auto di = block->to<IR::Declaration_Instance>();
154 if (di->arguments->size() != 1) {
155 ::P4::error(ErrorType::ERR_UNEXPECTED, "Expected exactly 1 argument %1%", block);
156 return;
157 }
158 int type = di->arguments->at(0)->expression->checkedTo<IR::Constant>()->asInt();
159 init(program, name, type);
160 }
161
162 EBPFChecksumPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *block,
163 cstring name, int type)
164 : EBPF::EBPFChecksumPSA(program, block, name, type) {
165 init(program, name, type);
166 }
167};
168
169class EBPFInternetChecksumPNA : public EBPFChecksumPNA {
170 public:
171 EBPFInternetChecksumPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *block,
172 cstring name)
173 : EBPFChecksumPNA(program, block, name,
174 EBPF::EBPFHashAlgorithmPSA::HashAlgorithm::ONES_COMPLEMENT16) {}
175
176 void processMethod(EBPF::CodeBuilder *builder, cstring method,
177 const IR::MethodCallExpression *expr, Visitor *visitor) override;
178};
179
180class EBPFHashPNA : public EBPFChecksumPNA {
181 public:
182 EBPFHashPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *block,
183 cstring name)
184 : EBPFChecksumPNA(program, block, name) {}
185 void processMethod(EBPF::CodeBuilder *builder, cstring method,
186 const IR::MethodCallExpression *expr, Visitor *visitor) override;
187 void calculateHash(EBPF::CodeBuilder *builder, const IR::MethodCallExpression *expr,
188 Visitor *visitor);
189 void emitVariables(EBPF::CodeBuilder *builder);
190};
191class CRCChecksumAlgorithmPNA : public EBPF::CRCChecksumAlgorithm {
192 public:
193 CRCChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name, int width)
194 : EBPF::CRCChecksumAlgorithm(program, name, width) {
195 BUG_CHECK(width == 16 || width == 32, "Must be 16 bits width or 32 bits width.");
196 initialValue = "0"_cs;
197 }
198 void emitGet(EBPF::CodeBuilder *builder) override;
199 void emitAddData(EBPF::CodeBuilder *builder, const ArgumentsList &arguments,
200 const IR::MethodCallExpression *expr);
201 void emitAddData(EBPF::CodeBuilder *builder, int dataPos,
202 const IR::MethodCallExpression *expr) override;
203};
204
205class EBPFDigestPNA : public EBPF::EBPFDigestPSA {
206 const ConvertToBackendIR *tcIR;
207 cstring externName;
208 cstring instanceName;
209
210 public:
211 EBPFDigestPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *di,
212 cstring externName, const ConvertToBackendIR *tcIR)
213 : EBPF::EBPFDigestPSA(program, di) {
214 this->tcIR = tcIR;
215 this->externName = externName;
216 this->instanceName = di->toString();
217 }
218 void emitInitializer(EBPF::CodeBuilder *builder) const;
219 void emitPushElement(EBPF::CodeBuilder *builder, const IR::Expression *elem,
220 Inspector *codegen) const;
221 void emitPushElement(EBPF::CodeBuilder *builder, cstring elem) const;
222};
223
224class EBPFMeterPNA : public EBPF::EBPFMeterPSA {
225 cstring tblname;
226 cstring instanceName;
227
228 public:
229 EBPFMeterPNA(const EBPF::EBPFProgram *program, cstring instanceName,
230 const IR::Declaration_Instance *di, EBPF::CodeGenInspector *codeGen)
231 : EBPF::EBPFMeterPSA(program, instanceName, di, codeGen) {
232 this->instanceName = di->toString();
233 }
234 EBPFMeterPNA(const EBPF::EBPFProgram *program, cstring instanceName, cstring tblname,
235 const IR::Declaration_Instance *di, EBPF::CodeGenInspector *codeGen)
236 : EBPF::EBPFMeterPSA(program, instanceName, di, codeGen) {
237 this->tblname = tblname;
238 this->instanceName = di->toString();
239 }
240 void emitExecute(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
241 ControlBodyTranslatorPNA *translator,
242 const IR::Expression *leftExpression) const;
243 void emitDirectMeterExecute(EBPF::CodeBuilder *builder, const P4::ExternMethod *method,
244 ControlBodyTranslatorPNA *translator,
245 const IR::Expression *leftExpression) const;
246 void emitInitializer(EBPF::CodeBuilder *builder, const ConvertToBackendIR *tcIR,
247 cstring externName) const;
248};
249
250class EBPFTablePNADirectMeterPropertyVisitor : public EBPF::EBPFTablePsaPropertyVisitor {
251 public:
252 explicit EBPFTablePNADirectMeterPropertyVisitor(EBPF::EBPFTablePSA *table)
254
255 bool preorder(const IR::PathExpression *pe) override {
256 auto decl = table->program->refMap->getDeclaration(pe->path, true);
257 auto di = decl->to<IR::Declaration_Instance>();
258 CHECK_NULL(di);
259 if (EBPF::EBPFObject::getTypeName(di) != "DirectMeter") {
260 ::P4::error(ErrorType::ERR_UNEXPECTED, "%1%: not a DirectMeter, see declaration of %2%",
261 pe, decl);
262 return false;
263 }
264
265 auto meterName = EBPF::EBPFObject::externalName(di);
266 auto tblname = table->table->container->name.originalName;
267 auto met = new EBPFMeterPNA(table->program, meterName, tblname, di, table->codeGen);
268 table->meters.emplace_back(std::make_pair(meterName, met));
269 return false;
270 }
271
272 void visitTableProperty() {
273 EBPF::EBPFTablePsaPropertyVisitor::visitTableProperty("pna_direct_meter"_cs);
274 }
275};
276
277} // namespace P4::TC
278
279#endif /* BACKENDS_TC_TCEXTERNS_H_ */
Definition ebpfPsaHashAlgorithm.h:74
Definition ebpf/codeGen.h:33
Definition ebpf/codeGen.h:41
Definition ebpfPsaChecksum.h:25
Definition ebpfPsaCounter.h:26
Definition ebpfPsaDigest.h:27
Definition ebpfPsaHashAlgorithm.h:26
Definition ebpfPsaMeter.h:23
Definition ebpfProgram.h:39
Also used to represent counters.
Definition ebpfTable.h:49
Definition ebpfPsaTable.h:29
Definition ebpfPsaTable.h:123
Base class for EBPF types.
Definition ebpfType.h:29
Definition methodInstance.h:168
Definition visitor.h:413
Definition ebpfCodeGen.h:386
Definition tc/backend.h:49
Definition tcExterns.h:27
Definition tcExterns.h:224
void emitVariables(EBPF::CodeBuilder *builder, const IR::Declaration_Instance *decl) override
decl might be a null pointer
Definition tcExterns.cpp:215
Definition visitor.h:75
Definition cstring.h:85
This file defines functions for the pass to generate the introspection file.
Definition tc/backend.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
T * to() noexcept
Definition rtti.h:226