Skip to content

Commit bae6a84

Browse files
authored
dpdk: make unique names for header and metadata struct fields (#3080)
* dpdk: inject local header variables into header struct instead of metadata struct Instructions extract and lookahead in DPDK target assembler support only operand which is a header, metadata fields are not supported as operands. Until now, all local variables were injected into main metadata structure. As a result, if there was an extract or lookahead call which parsed the data from a packet into a header, there was generated an instruction with metadata operand producing invalid spec file. This commit makes a header from every local variable which is of header type instead of adding it to main metadata structure. * ExpandLookahead: add parameter for disabling expansion of headers Some targets (f.e. DPDK target) may support lookahead with header type argument directly without the need to expand the header, but they might still require expansion of structures. ExpandLookahead pass can be utilized for such targets when a new parameter which allows to disable expansion of headers is added. This change is backwards compatible as a default behavior remains the same and a new parameter for constructor is optional. * dpdk: transform base or structure type lookahead into header lookahead Lookahead implementation in DPDK target supports only header instance as an operand. Variables or metadata structure fields of other than header types need to be either rejected or transformed so that there is used lookahead with header instance operand. This commit implements a transformation which converts all usages of lookahead with other than header type argument to lookahead with header type argument. After P4::ExpandLookahead pass lookahead method may occur only as an assignment to a header or base bit type as follows: T var_name; state state_name { var_name = pkt.lookahead<T>(); } Lookahead with header types arguments are unchanged by newly added pass ConvertLookahead. Lookahead with other than header type argument is transformed to following: header var_name_header { T var_name; } T var_name; var_name_header var_name_tmp_h; state state_name { var_name_tmp_h = pkt.lookahead<var_name_header>(); var_name = var_name_tmp_h.var_name; } Note (limitation): Current maximum supported width of header fields in DPDK target is 64 bits. As ExpandLookahead pass expands structures used as type arguments of lookahead method into bit type of the same width as the width of the whole structure and there is created a temporary variable of the given width which is than part of metadata structure, maximum supported width of the structure used as a type argument for lookahead is also 64 bits. * dpdk: update extract and lookahead tests * dpdk: package ConvertLookahead pass into PassManager * dpdk: fix year in new test license * ExpandLookahead: add more comments for new policy flag * dpdk: change comment format * dpdk: update psa test to not fail with bmv2 * dpdk: simplify naming of newly synthesized variables and headers * dpdk: insert new headers before main headers structure * dpdk: use base type instead of header with lookahead in psa test * dpdk: make unique names for header and metadata struct fields
1 parent aeca7f3 commit bae6a84

File tree

73 files changed

+1795
-509
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1795
-509
lines changed

backends/dpdk/backend.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ void DpdkBackend::convert(const IR::ToplevelBlock *tlb) {
6464
new P4::MoveDeclarations(), // Move all local declarations to the beginning
6565
new CollectProgramStructure(refMap, typeMap, &structure),
6666
new CollectMetadataHeaderInfo(&structure),
67+
new ConvertLookahead(refMap, typeMap, &structure),
68+
new P4::TypeChecking(refMap, typeMap),
6769
new ConvertToDpdkArch(refMap, &structure),
6870
new InjectJumboStruct(&structure),
6971
new InjectOutputPortMetadataField(&structure),
@@ -77,7 +79,7 @@ void DpdkBackend::convert(const IR::ToplevelBlock *tlb) {
7779
new P4::TypeChecking(refMap, typeMap, true),
7880
new ConvertBinaryOperationTo2Params(),
7981
new CollectProgramStructure(refMap, typeMap, &structure),
80-
new CollectLocalVariableToMetadata(refMap, &structure),
82+
new CollectLocalVariables(refMap, typeMap, &structure),
8183
new CollectErrors(&structure),
8284
new ConvertInternetChecksum(typeMap, &structure),
8385
new PrependPDotToActionArgs(typeMap, refMap, &structure),

backends/dpdk/dpdkArch.cpp

+201-35
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,16 @@ const IR::Node *ConvertToDpdkArch::preorder(IR::PathExpression *pe) {
195195
auto declaration = refMap->getDeclaration(pe->path);
196196
if (auto decl = declaration->to<IR::Parameter>()) {
197197
if (auto type = decl->type->to<IR::Type_Name>()) {
198+
LOG3("Expression: " << pe << std::endl <<
199+
" declaration: " << declaration);
198200
if (type->path->name == structure->header_type) {
199-
return new IR::PathExpression(IR::ID("h"));
201+
auto expr = new IR::PathExpression(IR::ID("h"));
202+
LOG3(" replaced by: " << expr);
203+
return expr;
200204
} else if (type->path->name == structure->local_metadata_type) {
201-
return new IR::PathExpression(IR::ID("m"));
205+
auto expr = new IR::PathExpression(IR::ID("m"));
206+
LOG3(" replaced by: " << expr);
207+
return expr;
202208
}
203209
}
204210
}
@@ -216,18 +222,26 @@ const IR::Node *ConvertToDpdkArch::preorder(IR::Member *m) {
216222
auto declaration = refMap->getDeclaration(p->path);
217223
if (auto decl = declaration->to<IR::Parameter>()) {
218224
if (auto type = decl->type->to<IR::Type_Name>()) {
225+
LOG3("Member: " << m << std::endl <<
226+
" declaration: " << declaration);
219227
if (isStandardMetadata(type->path->name)) {
220-
return new IR::Member(
228+
auto nm = new IR::Member(
221229
new IR::PathExpression(IR::ID("m")),
222230
IR::ID(TypeStruct2Name(type->path->name.name) + "_" +
223231
m->member.name));
232+
LOG3(" replaced by new member: " << nm);
233+
return nm;
224234
} else if (type->path->name == structure->header_type) {
225-
return new IR::Member(new IR::PathExpression(IR::ID("h")),
235+
auto nm = new IR::Member(new IR::PathExpression(IR::ID("h")),
226236
IR::ID(m->member.name));
237+
LOG3(" replaced by new member: " << nm);
238+
return nm;
227239
} else if (type->path->name == structure->local_metadata_type) {
228-
return new IR::Member(
240+
auto nm = new IR::Member(
229241
new IR::PathExpression(IR::ID("m")),
230242
IR::ID("local_metadata_" + m->member.name));
243+
LOG3(" replaced by new member: " << nm);
244+
return nm;
231245
}
232246
}
233247
}
@@ -237,6 +251,129 @@ const IR::Node *ConvertToDpdkArch::preorder(IR::Member *m) {
237251

238252

239253

254+
void ConvertLookahead::Collect::postorder(const IR::AssignmentStatement *statement) {
255+
if (!statement->right->is<IR::MethodCallExpression>())
256+
return;
257+
auto mce = statement->right->to<IR::MethodCallExpression>();
258+
259+
if (mce->type->is<IR::Type_Header>())
260+
return;
261+
262+
auto mi = P4::MethodInstance::resolve(mce, refMap, typeMap);
263+
if (!mi->is<P4::ExternMethod>())
264+
return;
265+
auto em = mi->to<P4::ExternMethod>();
266+
if (em->originalExternType->name != P4::P4CoreLibrary::instance.packetIn.name ||
267+
em->method->name != P4::P4CoreLibrary::instance.packetIn.lookahead.name)
268+
return;
269+
270+
LOG2("Collecting lookahead in statement:" << std::endl << " " << statement);
271+
272+
/**
273+
* Store new header in following format in the map:
274+
*
275+
* header lookahead_tmp_hdr {
276+
* T f;
277+
* }
278+
*/
279+
IR::ID newHeaderFieldName("f");
280+
auto program = findOrigCtxt<IR::P4Program>();
281+
IR::IndexedVector<IR::StructField> newHeaderFields;
282+
newHeaderFields.push_back(new IR::StructField(newHeaderFieldName, statement->left->type));
283+
IR::ID newHeaderName(refMap->newName("lookahead_tmp_hdr"));
284+
auto newHeader = new IR::Type_Header(newHeaderName, newHeaderFields);
285+
286+
repl->insertHeader(program, newHeader);
287+
288+
/**
289+
* Store following declaration of new local variable which is of
290+
* new header type in the map:
291+
*
292+
* lookahead_tmp_hdr lookahead_tmp;
293+
*/
294+
auto parser = findOrigCtxt<IR::P4Parser>();
295+
IR::ID newLocalVarName(refMap->newName("lookahead_tmp"));
296+
auto newLocalVarType = new IR::Type_Name(newHeaderName);
297+
auto newLocalVar = new IR::Declaration_Variable(newLocalVarName, newLocalVarType);
298+
299+
repl->insertVar(parser, newLocalVar);
300+
301+
/**
302+
* Replace current statement with 2 new statements:
303+
* - assignment statement with lookahead method using
304+
* newly created header definiton
305+
* - assignment statement which assigns the field from
306+
* newly created header into the original variable
307+
*
308+
* lookahead_tmp = pkt.lookahead<lookahead_tmp_hdr>();
309+
* var_name = lookahead_tmp.f;
310+
*/
311+
auto newStatements = new IR::IndexedVector<IR::StatOrDecl>;
312+
const IR::Expression *newLeft;
313+
const IR::Expression *newRight;
314+
const IR::AssignmentStatement *newStat;
315+
316+
newLeft = new IR::PathExpression(newHeader, new IR::Path(newLocalVarName));
317+
newRight = new IR::MethodCallExpression(newHeader, mce->method,
318+
new IR::Vector<IR::Type>(newLocalVarType));
319+
newStat = new IR::AssignmentStatement(newLeft, newRight);
320+
newStatements->push_back(newStat);
321+
322+
newLeft = statement->left;
323+
newRight = new IR::Member(new IR::PathExpression(newLocalVarName), newHeaderFieldName);
324+
newStat = new IR::AssignmentStatement(newLeft, newRight);
325+
newStatements->push_back(newStat);
326+
327+
repl->insertStatements(statement, newStatements);
328+
}
329+
330+
const IR::Node *ConvertLookahead::Replace::postorder(IR::AssignmentStatement *as) {
331+
auto result = repl->getStatements(getOriginal()->to<IR::AssignmentStatement>());
332+
if (result == nullptr)
333+
return as;
334+
335+
LOG2("Statement:" << std::endl << " " << as);
336+
LOG2("replaced by statements:");
337+
for (auto s : *result) {
338+
LOG2(" " << s);
339+
}
340+
341+
return result;
342+
}
343+
344+
const IR::Node *ConvertLookahead::Replace::postorder(IR::Type_Struct *s) {
345+
auto program = findOrigCtxt<IR::P4Program>();
346+
347+
if (s->name != structure->header_type || program == nullptr)
348+
return s;
349+
350+
auto result = repl->getHeaders(program);
351+
if (result == nullptr)
352+
return s;
353+
354+
LOG2("Following new headers inserted into program " << dbp(program) << ":");
355+
for (auto h : *result) {
356+
LOG2(" " << h);
357+
}
358+
359+
result->push_back(s);
360+
return result;
361+
}
362+
363+
const IR::Node *ConvertLookahead::Replace::postorder(IR::P4Parser *parser) {
364+
auto result = repl->getVars(getOriginal()->to<IR::P4Parser>());
365+
if (result != nullptr) {
366+
parser->parserLocals.append(*result);
367+
LOG2("Following new declarations inserted into parser " << dbp(parser) << ":");
368+
for (auto decl : *result) {
369+
LOG2(" " << decl);
370+
}
371+
}
372+
return parser;
373+
}
374+
375+
376+
240377
void CollectMetadataHeaderInfo::pushMetadata(const IR::ParameterList* params,
241378
std::list<int> indices) {
242379
for (auto idx : indices) {
@@ -318,9 +455,11 @@ bool CollectMetadataHeaderInfo::preorder(const IR::Type_Struct *s) {
318455
for (auto m : structure->used_metadata) {
319456
if (m->to<IR::Type_Name>()->path->name.name == s->name.name) {
320457
for (auto field : s->fields) {
321-
structure->compiler_added_fields.push_back(new IR::StructField(
458+
auto sf = new IR::StructField(
322459
IR::ID(TypeStruct2Name(s->name.name) + "_" + field->name),
323-
field->type));
460+
field->type);
461+
LOG4("Adding metadata field: " << sf);
462+
structure->compiler_added_fields.push_back(sf);
324463
}
325464
return true;
326465
}
@@ -770,55 +909,82 @@ const IR::Node *ConvertBinaryOperationTo2Params::postorder(IR::P4Parser *a) {
770909
return injector.inject_parser(parser, a);
771910
}
772911

773-
const IR::Node *CollectLocalVariableToMetadata::preorder(IR::P4Program *p) {
912+
const IR::Node *CollectLocalVariables::preorder(IR::P4Program *p) {
774913
for (auto kv : structure->parsers) {
775-
locals_map.emplace(kv.first+"_parser", kv.second->parserLocals);
914+
insert(kv.first + "_parser", &kv.second->parserLocals);
776915
}
777916
for (auto kv : structure->pipelines) {
778-
locals_map.emplace(kv.first, kv.second->controlLocals);
917+
insert(kv.first, &kv.second->controlLocals);
779918
}
780919
for (auto kv : structure->deparsers) {
781-
locals_map.emplace(kv.first+"_deprser", kv.second->controlLocals);
920+
insert(kv.first + "_deparser", &kv.second->controlLocals);
782921
}
922+
LOG4("Collecting local variables, localsMap:");
923+
for (auto kv : localsMap) {
924+
LOG4(" " << dbp(kv.first) << ": " << kv.second);
925+
}
926+
783927
return p;
784928
}
785929

786-
const IR::Node *CollectLocalVariableToMetadata::postorder(IR::Type_Struct *s) {
930+
const IR::Node *CollectLocalVariables::postorder(IR::Type_Struct *s) {
787931
if (s->name.name == structure->local_metadata_type) {
788-
for (auto kv : locals_map) {
789-
for (auto d : kv.second) {
790-
if (auto dv = d->to<IR::Declaration_Variable>()) {
791-
s->fields.push_back(new IR::StructField(
792-
IR::ID(kv.first + "_" + dv->name.name), dv->type));
793-
} else if (!d->is<IR::P4Action>() && !d->is<IR::P4Table>() &&
794-
!d->is<IR::Declaration_Instance>()) {
795-
BUG("%1%: Unhandled declaration type", s);
796-
}
932+
for (auto kv : localsMap) {
933+
auto dv = kv.first;
934+
auto type = typeMap->getType(dv, true);
935+
if (type->is<IR::Type_Header>()) {
936+
LOG3("Variable: " << dv << std::endl <<
937+
" type: " << type << std::endl <<
938+
" already added to: " << structure->header_type);
939+
} else {
940+
auto sf = new IR::StructField(IR::ID(kv.second), dv->type);
941+
LOG2("New field: " << sf << std::endl <<
942+
" type: " << type << std::endl <<
943+
" added to: " << s->name.name);
944+
s->fields.push_back(sf);
945+
}
946+
}
947+
} else if (s->name.name == structure->header_type) {
948+
for (auto kv : localsMap) {
949+
auto dv = kv.first;
950+
auto type = typeMap->getType(dv, true);
951+
if (type->is<IR::Type_Header>()) {
952+
auto sf = new IR::StructField(IR::ID(kv.second), dv->type);
953+
LOG2("New field: " << sf << std::endl <<
954+
" type: " << type << std::endl <<
955+
" added to: " << s->name.name);
956+
s->fields.push_back(sf);
957+
} else {
958+
LOG3("Variable: " << dv << std::endl <<
959+
" type: " << type << std::endl <<
960+
" already added to: " << structure->local_metadata_type);
797961
}
798962
}
799963
}
800964
return s;
801965
}
802966

803967
const IR::Node *
804-
CollectLocalVariableToMetadata::postorder(IR::PathExpression *p) {
805-
if (auto decl =
806-
refMap->getDeclaration(p->path)->to<IR::Declaration_Variable>()) {
807-
for (auto kv : locals_map) {
808-
for (auto d : kv.second) {
809-
if (d->equiv(*decl)) {
810-
return new IR::Member(
811-
new IR::PathExpression(IR::ID("m")),
812-
IR::ID(kv.first + "_" + decl->name.name));
813-
}
968+
CollectLocalVariables::postorder(IR::PathExpression *p) {
969+
if (auto decl = refMap->getDeclaration(p->path)->to<IR::Declaration_Variable>()) {
970+
if (localsMap.count(decl)) {
971+
IR::ID name(localsMap.at(decl));
972+
IR::Member *member;
973+
if (typeMap->getType(decl, true)->is<IR::Type_Header>()) {
974+
member = new IR::Member(new IR::PathExpression(IR::ID("h")), name);
975+
} else {
976+
member = new IR::Member(new IR::PathExpression(IR::ID("m")), name);
814977
}
978+
LOG2("Expression: " << p << " replaced by: " << member);
979+
return member;
980+
} else {
981+
BUG("%1%: variable is not included in a control or parser block", p);
815982
}
816-
BUG("%1%: variable is not included in a control or parser block", p);
817983
}
818984
return p;
819985
}
820986

821-
const IR::Node *CollectLocalVariableToMetadata::postorder(IR::P4Control *c) {
987+
const IR::Node *CollectLocalVariables::postorder(IR::P4Control *c) {
822988
IR::IndexedVector<IR::Declaration> decls;
823989
for (auto d : c->controlLocals) {
824990
if (d->is<IR::Declaration_Instance>() || d->is<IR::P4Action>() ||
@@ -832,7 +998,7 @@ const IR::Node *CollectLocalVariableToMetadata::postorder(IR::P4Control *c) {
832998
return c;
833999
}
8341000

835-
const IR::Node *CollectLocalVariableToMetadata::postorder(IR::P4Parser *p) {
1001+
const IR::Node *CollectLocalVariables::postorder(IR::P4Parser *p) {
8361002
IR::IndexedVector<IR::Declaration> decls;
8371003
for (auto d : p->parserLocals) {
8381004
if (d->is<IR::Declaration_Instance>()) {
@@ -951,7 +1117,7 @@ const IR::Node* PrependPDotToActionArgs::preorder(IR::MethodCallExpression* mce)
9511117
gets translated to
9521118
control ingress(inout headers h, inout metadata m) {
9531119
bit<48> tbl_ethernet_srcAddr; // These declarations are later copied to metadata struct
954-
bit<16> tbl_ipv4_totalLen; // in CollectLocalVariableToMetadata pass.
1120+
bit<16> tbl_ipv4_totalLen; // in CollectLocalVariables pass.
9551121
...
9561122
table tbl {
9571123
key = {

0 commit comments

Comments
 (0)