P4C
The P4 Compiler
Loading...
Searching...
No Matches
dpdkHelpers.h
1/*
2 * Copyright 2020 Intel Corp.
3 * SPDX-FileCopyrightText: 2020 Intel Corp.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef BACKENDS_DPDK_DPDKHELPERS_H_
9#define BACKENDS_DPDK_DPDKHELPERS_H_
10
11#include "constants.h"
12#include "dpdkProgramStructure.h"
13#include "frontends/common/constantFolding.h"
14#include "frontends/common/resolveReferences/referenceMap.h"
15#include "frontends/p4/coreLibrary.h"
16#include "frontends/p4/enumInstance.h"
17#include "frontends/p4/evaluator/evaluator.h"
18#include "frontends/p4/methodInstance.h"
19#include "frontends/p4/simplify.h"
20#include "frontends/p4/typeMap.h"
21#include "frontends/p4/unusedDeclarations.h"
22#include "ir/ir.h"
23#include "lib/big_int_util.h"
24#include "lib/json.h"
25#include "midend/removeComplexExpressions.h"
26
27#define TOSTR_DECLA(NAME) std::ostream &toStr(std::ostream &, IR::NAME *)
28
29namespace P4::DPDK {
30
31static const int SupportedBitWidth = 128;
32
34
43const char PnaMainOutputMetadataOutputPortName[] = "pna_main_output_metadata_output_port";
44const char DirectResourceTableEntryIndex[] = "table_entry_index";
45
46/* This class will generate a optimized jmp and label control flow.
47 * Couple of examples here
48 *
49 * Example 1:
50 * If(a && b){
51 *
52 * }
53 * Else{
54 *
55 * }
56 *
57 * Will be translated to(in an optimal form):
58 * cmp a 1
59 * jneq false
60 * cmp b 1
61 * jneq false
62 * true:
63 * // if true statements go here
64 * jmp end
65 * false:
66 * // if false statements go here
67 * end:
68 *
69 * In this case, in order to use fewer jmp, I use jneq instead of jeq to let the
70 * true condition fall through the jmp statement and short-circuit the false
71 * condition.
72 *
73 * Example 2:
74 * (a && b) || c
75 * cmp a 1
76 * jneq half_false
77 * cmp b 1
78 * jneq half_false
79 * jmp true
80 * half_false:
81 * cmp c 1
82 * jeq true
83 * false:
84 *
85 * jmp end
86 * true:
87 *
88 * end:
89 *
90 * In this case, it is not in an optimal form. To make it optimal, I need to
91 * change (a && b) || c to c ||(a && b) and assembly code looks like this:
92 * cmp c 1
93 * jeq true
94 * cmp a 1
95 * jneq false
96 * cmp b 1
97 * jneq false
98 * false:
99 *
100 * jmp end
101 * true:
102 *
103 * end:
104 *
105 * It is very important to generate as fewer jmp and label instructions as
106 * possible, because the performance of DPDK is directly related to the number
107 * of instructions.
108 *
109 * This class uses a recursive function to generate the control flow and is
110 * optmized.
111 */
112class BranchingInstructionGeneration {
113 ConvertStatementToDpdk *convert;
114 P4::ReferenceMap *refMap;
115 P4::TypeMap *typeMap;
116 bool nested(const IR::Node *n) {
117 if (n->is<IR::LAnd>() || n->is<IR::LOr>()) {
118 return true;
119 } else {
120 return false;
121 }
122 }
123
124 public:
125 BranchingInstructionGeneration(ConvertStatementToDpdk *convert, P4::ReferenceMap *refMap,
126 P4::TypeMap *typeMap)
127 : convert(convert), refMap(refMap), typeMap(typeMap) {}
128 bool generate(const IR::Expression *, cstring, cstring, bool);
129};
130
131class TypeWidthValidator : public Inspector {
132 void postorder(const IR::Type_Varbits *type) override {
133 LOG3("Validating Type_Varbits: " << type);
134 if (type->size % 8 != 0) {
135 ::P4::error(ErrorType::ERR_UNSUPPORTED, "%1% varbit width (%2%) not aligned to 8 bits",
136 type->srcInfo, type->size);
137 }
138 }
139};
140
141class ConvertStatementToDpdk : public Inspector {
143 P4::TypeMap *typemap;
144 P4::ReferenceMap *refmap;
145 DpdkProgramStructure *structure;
146 const IR::P4Parser *parser = nullptr;
147 const IR::Node *parent = nullptr;
148 IR::Type_Struct *metadataStruct = nullptr;
149 bool createSandboxHeaderType = false;
150 bool createTmpVar = false;
151
152 private:
153 void processHashParams(const IR::Argument *field, IR::Vector<IR::Expression> &components);
154 bool checkIfBelongToSameHdrMdStructure(const IR::Argument *field);
155 void updateMdStrAndGenInstr(const IR::Argument *field, IR::Vector<IR::Expression> &components);
156 cstring getHdrMdStrName(const IR::Member *mem);
157 bool checkIfConsecutiveHdrMdfields(const IR::Argument *field);
158 void createSandboxHeader();
159 void createTmpVarForSandbox();
160 friend class BranchingInstructionGeneration;
161
162 public:
163 ConvertStatementToDpdk(P4::ReferenceMap *refmap, P4::TypeMap *typemap,
164 DpdkProgramStructure *structure)
165 : typemap(typemap), refmap(refmap), structure(structure) {
166 visitDagOnce = false;
167 }
168 ConvertStatementToDpdk(P4::ReferenceMap *refmap, P4::TypeMap *typemap,
169 DpdkProgramStructure *structure, IR::Type_Struct *metadataStruct)
170 : typemap(typemap), refmap(refmap), structure(structure), metadataStruct(metadataStruct) {
171 visitDagOnce = false;
172 }
173 IR::IndexedVector<IR::DpdkAsmStatement> getInstructions() { return instructions; }
174 void branchingInstructionGeneration(cstring true_label, cstring false_label,
175 const IR::Expression *expr);
176 bool preorder(const IR::AssignmentStatement *a) override;
177 bool preorder(const IR::IfStatement *a) override;
178 bool preorder(const IR::MethodCallStatement *a) override;
179 bool preorder(const IR::SwitchStatement *a) override;
180
181 void add_instr(const IR::DpdkAsmStatement *s) { instructions.push_back(s); }
182 IR::IndexedVector<IR::DpdkAsmStatement> &get_instr() { return instructions; }
183 void process_logical_operation(const IR::Expression *, const IR::Operation_Binary *);
184 void process_relation_operation(const IR::Expression *, const IR::Operation_Relation *);
185 cstring append_parser_name(const IR::P4Parser *p, cstring);
186 void set_parser(const IR::P4Parser *p) { parser = p; }
187 void set_parent(const IR::Node *p) { parent = p; }
188 bool handleConstSwitch(const IR::SwitchStatement *a);
189 bool checkIf128bitOp(const IR::Expression *, const IR::Expression *);
190 void add128bitwiseInstr(const IR::Expression *src1Op, const IR::Expression *src2Op,
191 const char *op);
192 void add128ComparisonInstr(cstring true_label, const IR::Expression *src1Op,
193 const IR::Expression *src2Op, const char *op);
194 void add128bitComplInstr(const IR::Expression *, const IR::Expression *);
195 void add128bitMovInstr(const IR::Expression *left, const IR::Expression *right);
196};
197
198class ProcessControls : public P4::RemoveComplexExpressionsPolicy {
199 const std::set<cstring> *process;
200
201 public:
202 explicit ProcessControls(const std::set<cstring> *process) : process(process) {
203 CHECK_NULL(process);
204 }
205 bool convert(const IR::P4Control *control) const {
206 if (process->find(control->name) != process->end()) return true;
207 return false;
208 }
209};
210
211} // namespace P4::DPDK
212#endif /* BACKENDS_DPDK_DPDKHELPERS_H_ */
bool generate(const IR::Expression *, cstring, cstring, bool)
Definition dpdkHelpers.cpp:809
Definition dpdkHelpers.h:141
void process_relation_operation(const IR::Expression *, const IR::Operation_Relation *)
Definition dpdkHelpers.cpp:20
bool preorder(const IR::AssignmentStatement *a) override
Definition dpdkHelpers.cpp:113
bool convert(const IR::P4Control *control) const
Definition dpdkHelpers.h:205
Definition dpdkHelpers.h:131
Definition indexed_vector.h:31
Definition node.h:53
Definition ir/vector.h:59
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition removeComplexExpressions.h:21
Definition typeMap.h:32
Definition cstring.h:85
Definition dpdk/backend.cpp:26
const char PnaMainOutputMetadataOutputPortName[]
Name of the metadata used as output port.
Definition dpdkHelpers.h:43
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
Collect information related to P4 programs targeting dpdk.
Definition dpdkProgramStructure.h:22
bool is() const noexcept
Definition rtti.h:216