8#ifndef BACKENDS_DPDK_DPDKARCH_H_
9#define BACKENDS_DPDK_DPDKARCH_H_
12#include "dpdkProgramStructure.h"
14#include "frontends/common/resolveReferences/resolveReferences.h"
15#include "frontends/p4/evaluator/evaluator.h"
16#include "frontends/p4/sideEffects.h"
17#include "frontends/p4/typeMap.h"
19#include "lib/ordered_map.h"
20#include "midend/flattenInterfaceStructs.h"
21#include "midend/removeLeftSlices.h"
25using namespace P4::literals;
27cstring TypeStruct2Name(
const cstring *s);
28bool isSimpleExpression(
const IR::Expression *e);
29bool isNonConstantSimpleExpression(
const IR::Expression *e);
32using UserMeta = std::set<cstring>;
48class ConvertToDpdkArch :
public Transform {
52 const IR::Type_Control *rewriteControlType(
const IR::Type_Control *,
cstring);
53 const IR::Type_Parser *rewriteParserType(
const IR::Type_Parser *,
cstring);
54 const IR::Type_Control *rewriteDeparserType(
const IR::Type_Control *,
cstring);
55 const IR::Node *postorder(IR::Type_Control *c)
override;
56 const IR::Node *postorder(IR::Type_Parser *p)
override;
57 const IR::Node *preorder(IR::Member *m)
override;
58 const IR::Node *preorder(IR::PathExpression *pe)
override;
62 : refMap(refMap), structure(structure) {
63 CHECK_NULL(structure);
99struct ConvertLookahead :
public PassManager {
101 std::unordered_map<const IR::P4Program *, IR::IndexedVector<IR::Node>> newHeaderMap;
102 std::unordered_map<const IR::P4Parser *, IR::IndexedVector<IR::Declaration>> newLocalVarMap;
103 std::unordered_map<const IR::AssignmentStatement *, IR::IndexedVector<IR::StatOrDecl>>
107 void insertHeader(
const IR::P4Program *p,
const IR::Type_Header *h) {
108 if (newHeaderMap.count(p)) {
109 newHeaderMap.at(p).push_back(h);
113 LOG5(
"Program: " << dbp(p));
114 LOG2(
"Adding new header:" << std::endl <<
" " << h);
117 if (newHeaderMap.count(p)) {
122 void insertVar(
const IR::P4Parser *p,
const IR::Declaration_Variable *v) {
123 if (newLocalVarMap.count(p)) {
124 newLocalVarMap.at(p).push_back(v);
128 LOG5(
"Parser: " << dbp(p));
129 LOG2(
"Adding new local variable:" << std::endl <<
" " << v);
132 if (newLocalVarMap.count(p)) {
137 void insertStatements(
const IR::AssignmentStatement *as,
139 BUG_CHECK(newStatMap.count(as) == 0,
140 "Unexpectedly converting statement %1% multiple times!", as);
141 newStatMap.emplace(as, *vec);
142 LOG5(
"AssignmentStatement: " << dbp(as));
143 LOG2(
"Adding new statements:");
144 for (
auto s : *vec) {
149 if (newStatMap.count(as)) {
158 class Collect :
public Inspector {
165 : refMap(refMap), typeMap(typeMap), repl(repl) {}
166 void postorder(
const IR::AssignmentStatement *statement)
override;
169 class Replace :
public Transform {
175 : structure(structure), repl(repl) {}
176 const IR::Node *postorder(IR::AssignmentStatement *as)
override;
177 const IR::Node *postorder(IR::Type_Struct *s)
override;
178 const IR::Node *postorder(IR::P4Parser *parser)
override;
183 passes.push_back(
new Collect(refMap, typeMap, &repl));
184 passes.push_back(
new Replace(s, &repl));
193class CollectMetadataHeaderInfo :
public Inspector {
196 void pushMetadata(
const IR::Parameter *p);
197 void pushMetadata(
const IR::ParameterList *, std::list<int> indices);
201 bool preorder(
const IR::P4Program *p)
override;
202 bool preorder(
const IR::Type_Struct *s)
override;
208class InjectJumboStruct :
public Transform {
213 const IR::Node *preorder(IR::Type_Struct *s)
override;
220class InjectFixedMetadataField :
public Transform {
225 const IR::Node *preorder(IR::Type_Struct *s)
override;
231class AlignHdrMetaField :
public Transform {
238 CHECK_NULL(structure);
240 const IR::Node *preorder(IR::Type_StructLike *st)
override;
241 const IR::Node *preorder(IR::Member *m)
override;
244struct ByteAlignment :
public PassManager {
251 : typeMap(typeMap), refMap(refMap), structure(structure) {
252 CHECK_NULL(structure);
271 fieldInfo() { fieldWidth = 0; }
280 std::map<const IR::Node *, IR::IndexedVector<IR::Declaration> *> decl_map;
284 void collect(
const IR::P4Control *control,
const IR::P4Parser *parser,
285 const IR::Declaration *decl) {
288 auto res = decl_map.find(parser);
289 if (res != decl_map.end()) {
293 decl_map.emplace(parser, decls);
295 }
else if (control) {
296 auto res = decl_map.find(control);
297 if (res != decl_map.end()) {
301 decl_map.emplace(control, decls);
304 BUG_CHECK(decls !=
nullptr,
"decls cannot be null");
305 decls->push_back(decl);
308 auto res = decl_map.find(orig);
309 if (res == decl_map.end()) {
312 control->controlLocals.prepend(*res->second);
316 auto res = decl_map.find(orig);
317 if (res == decl_map.end()) {
320 parser->parserLocals.prepend(*res->second);
331class StatementUnroll :
public Transform {
339 : refMap(refMap), structure(structure) {}
340 const IR::Node *preorder(IR::AssignmentStatement *a)
override;
341 const IR::Node *postorder(IR::P4Control *a)
override;
342 const IR::Node *postorder(IR::P4Parser *a)
override;
354class ExpressionUnroll :
public Inspector {
360 IR::PathExpression *root;
362 setName(
"ExpressionUnroll");
364 bool preorder(
const IR::Operation_Unary *a)
override;
365 bool preorder(
const IR::Operation_Binary *a)
override;
366 bool preorder(
const IR::MethodCallExpression *a)
override;
367 bool preorder(
const IR::Member *a)
override;
368 bool preorder(
const IR::PathExpression *a)
override;
369 bool preorder(
const IR::Constant *a)
override;
370 bool preorder(
const IR::BoolLiteral *a)
override;
376class IfStatementUnroll :
public Transform {
383 setName(
"IfStatementUnroll");
385 const IR::Node *postorder(IR::SwitchStatement *a)
override;
386 const IR::Node *postorder(IR::IfStatement *a)
override;
387 const IR::Node *postorder(IR::P4Control *a)
override;
388 const IR::Node *postorder(IR::P4Parser *a)
override;
395class LogicalExpressionUnroll :
public Inspector {
401 IR::Expression *root;
402 static bool is_logical(
const IR::Operation_Binary *bin) {
403 if (bin->is<IR::LAnd>() || bin->is<IR::LOr>() || bin->is<IR::Leq>() || bin->is<IR::Equ>() ||
404 bin->is<IR::Neq>() || bin->is<IR::Grt>() || bin->is<IR::Lss>() || bin->is<IR::Geq>() ||
411 explicit LogicalExpressionUnroll(
P4::ReferenceMap *refMap) : refMap(refMap) {
412 visitDagOnce =
false;
414 bool preorder(
const IR::Operation_Unary *a)
override;
415 bool preorder(
const IR::Operation_Binary *a)
override;
416 bool preorder(
const IR::MethodCallExpression *a)
override;
417 bool preorder(
const IR::Member *a)
override;
418 bool preorder(
const IR::PathExpression *a)
override;
419 bool preorder(
const IR::Constant *a)
override;
420 bool preorder(
const IR::BoolLiteral *a)
override;
426class ConvertBinaryOperationTo2Params :
public Transform {
431 explicit ConvertBinaryOperationTo2Params(
P4::ReferenceMap *refMap) : refMap(refMap) {}
432 const IR::Node *postorder(IR::AssignmentStatement *a)
override;
433 const IR::Node *postorder(IR::P4Control *a)
override;
434 const IR::Node *postorder(IR::P4Parser *a)
override;
442class CollectLocalVariables :
public Transform {
449 for (
auto d : *locals) {
450 if (
auto dv = d->to<IR::Declaration_Variable>()) {
451 const cstring name = refMap->newName(
prefix +
"_" + dv->name.name);
452 localsMap.emplace(dv, name);
453 }
else if (!d->is<IR::P4Action>() && !d->is<IR::P4Table>() &&
454 !d->is<IR::Declaration_Instance>()) {
455 BUG(
"%1%: Unhandled declaration type", d);
463 : refMap(refMap), typeMap(typeMap), structure(structure) {}
464 const IR::Node *preorder(IR::P4Program *p)
override;
465 const IR::Node *postorder(IR::Type_Struct *s)
override;
466 const IR::Node *postorder(IR::Member *m)
override;
467 const IR::Node *postorder(IR::PathExpression *path)
override;
468 const IR::Node *postorder(IR::P4Control *c)
override;
469 const IR::Node *postorder(IR::P4Parser *p)
override;
480class PrependPDotToActionArgs :
public Transform {
488 : typeMap(typeMap), refMap(refMap), structure(structure) {}
489 const IR::Node *postorder(IR::P4Action *a)
override;
490 const IR::Node *postorder(IR::P4Program *s)
override;
491 const IR::Node *preorder(IR::PathExpression *path)
override;
492 const IR::Node *preorder(IR::MethodCallExpression *)
override;
501class DefActionValue :
public Inspector {
508 : typeMap(typeMap), refMap(refMap), structure(structure) {}
509 void postorder(
const IR::P4Table *t)
override;
515class DismantleMuxExpressions :
public Transform {
521 cstring createTemporary(
const IR::Type *type);
523 const IR::Expression *expression);
527 : typeMap(typeMap), refMap(refMap) {}
528 const IR::Node *preorder(IR::Mux *expression)
override;
529 const IR::Node *postorder(IR::P4Parser *parser)
override;
530 const IR::Node *postorder(IR::Function *function)
override;
531 const IR::Node *postorder(IR::P4Control *control)
override;
532 const IR::Node *postorder(IR::P4Action *action)
override;
533 const IR::Node *postorder(IR::AssignmentStatement *statement)
override;
543class CollectInternetChecksumInstance :
public Inspector {
546 std::vector<cstring> *csum_vec;
551 std::vector<cstring> *csum_vec)
552 : typeMap(typeMap), structure(structure), csum_vec(csum_vec) {}
553 bool preorder(
const IR::Declaration_Instance *d)
override {
554 auto type = typeMap->getType(d,
true);
555 if (
auto extn = type->to<IR::Type_Extern>()) {
556 if (extn->name ==
"InternetChecksum") {
557 std::ostringstream s;
558 s <<
"state_" << index++;
559 csum_vec->push_back(s.str());
560 structure->csum_map.emplace(d, s.str());
570class InjectInternetChecksumIntermediateValue :
public Transform {
572 std::vector<cstring> *csum_vec;
576 std::vector<cstring> *csum_vec)
577 : structure(structure), csum_vec(csum_vec) {}
579 const IR::Node *postorder(IR::P4Program *p)
override {
581 bool inserted =
false;
582 for (
auto obj : p->objects) {
583 if (obj->to<IR::Type_Header>() && !inserted) {
585 if (csum_vec->size() > 0) {
587 for (
auto fld : *csum_vec) {
589 new IR::StructField(
IR::ID(fld), IR::Type::Bits::get(16,
false)));
591 new_objs->push_back(
new IR::Type_Header(
IR::ID(
"cksum_state_t"), *fields));
594 new_objs->push_back(obj);
596 p->objects = *new_objs;
600 const IR::Node *postorder(IR::Type_Struct *s)
override {
601 if (s->name.name == structure->header_type) {
602 if (structure->csum_map.size() > 0)
603 s->fields.push_back(
new IR::StructField(
604 IR::ID(
"cksum_state"),
new IR::Type_Name(
IR::ID(
"cksum_state_t"))));
610class ConvertInternetChecksum :
public PassManager {
611 std::vector<cstring> csum_vec;
622class CollectExternDeclaration :
public Inspector {
627 bool preorder(
const IR::Declaration_Instance *d)
override {
628 if (
auto type = d->type->to<IR::Type_Name>()) {
629 auto externTypeName = type->path->name.name;
630 if (externTypeName ==
"DirectMeter") {
631 if (d->arguments->size() != 1) {
633 "%1%: expected type of meter as the only argument", d);
636 if (d->arguments->at(0)->expression->to<IR::Constant>()->asUnsigned() == 0)
637 warn(ErrorType::WARN_UNSUPPORTED,
638 "%1%: Packet metering is not supported."
639 " Falling back to byte metering.",
646 structure->externDecls.push_back(d);
647 }
else if (
auto type = d->type->to<IR::Type_Specialized>()) {
648 auto externTypeName = type->baseType->path->name.name;
649 if (externTypeName ==
"Meter") {
650 if (d->arguments->size() != 2) {
652 "%1%: expected number of meters and type of meter as arguments", d);
655 if (d->arguments->at(1)->expression->to<IR::Constant>()->asUnsigned() == 0)
656 warn(ErrorType::WARN_UNSUPPORTED,
657 "%1%: Packet metering is not supported."
658 " Falling back to byte metering.",
661 }
else if (externTypeName ==
"Counter") {
662 if (d->arguments->size() != 2) {
664 "%1%: expected number of counters and type of counter as arguments",
667 }
else if (externTypeName ==
"DirectCounter") {
668 if (d->arguments->size() != 1) {
670 "%1%: expected type of counter as the only argument", d);
672 }
else if (externTypeName ==
"Register") {
673 if (d->arguments->size() != 1 && d->arguments->size() != 2) {
675 "%1%: expected size and optionally init_val as arguments", d);
677 }
else if (externTypeName ==
"Hash") {
678 if (d->arguments->size() != 1) {
680 "%1%: expected hash algorithm as the only argument", d);
686 structure->externDecls.push_back(d);
698 const IR::Node *postorder(IR::LAnd *land) {
699 if (
auto land2 = land->left->to<IR::LAnd>()) {
700 auto sub =
new IR::LAnd(land2->right, land->right);
701 return new IR::LAnd(land2->left, sub);
702 }
else if (!land->left->is<IR::LOr>() && !land->left->is<IR::Equ>() &&
703 !land->left->is<IR::Neq>() && !land->left->is<IR::Leq>() &&
704 !land->left->is<IR::Geq>() && !land->left->is<IR::Lss>() &&
705 !land->left->is<IR::Grt>() && !land->left->is<IR::MethodCallExpression>() &&
706 !land->left->is<IR::PathExpression>() && !land->left->is<IR::Member>()) {
707 BUG(
"Logical Expression Unroll pass failed");
711 const IR::Node *postorder(IR::LOr *lor) {
712 if (
auto lor2 = lor->left->to<IR::LOr>()) {
713 auto sub =
new IR::LOr(lor2->right, lor->right);
714 return new IR::LOr(lor2->left, sub);
715 }
else if (!lor->left->is<IR::LAnd>() && !lor->left->is<IR::Equ>() &&
716 !lor->left->is<IR::Neq>() && !lor->left->is<IR::Lss>() &&
717 !lor->left->is<IR::Grt>() && !lor->left->is<IR::MethodCallExpression>() &&
718 !lor->left->is<IR::PathExpression>() && !lor->left->is<IR::Member>()) {
719 BUG(
"Logical Expression Unroll pass failed");
731 if (n->
is<IR::Equ>() || n->
is<IR::Neq>() || n->
is<IR::Lss>() || n->
is<IR::Grt>() ||
732 n->
is<IR::Geq>() || n->
is<IR::Leq>() || n->
is<IR::MethodCallExpression>() ||
733 n->
is<IR::PathExpression>() || n->
is<IR::Member>()) {
735 }
else if (!n->
is<IR::LAnd>() && !n->
is<IR::LOr>()) {
736 BUG(
"Logical Expression Unroll pass failed");
743 const IR::Node *postorder(IR::LAnd *land) {
744 if (!is_simple(land->left) && is_simple(land->right)) {
745 return new IR::LAnd(land->right, land->left);
746 }
else if (!is_simple(land->left)) {
747 if (
auto land2 = land->right->to<IR::LAnd>()) {
748 if (is_simple(land2->left)) {
749 auto sub =
new IR::LAnd(land->left, land2->right);
750 return new IR::LAnd(land2->left, sub);
756 const IR::Node *postorder(IR::LOr *lor) {
757 if (!is_simple(lor->left) && is_simple(lor->right)) {
758 return new IR::LOr(lor->right, lor->left);
759 }
else if (!is_simple(lor->left)) {
760 if (
auto lor2 = lor->right->to<IR::LOr>()) {
761 if (is_simple(lor2->left)) {
762 auto sub =
new IR::LOr(lor->left, lor2->right);
763 return new IR::LOr(lor2->left, sub);
776class ConvertLogicalExpression :
public PassManager {
778 ConvertLogicalExpression() {
789class CollectTableInfo :
public Inspector {
794 setName(
"CollectTableInfo");
796 bool preorder(
const IR::Key *key)
override;
807 int offsetInMetadata;
813 int numExistingMetaFields;
817 std::vector<struct keyElementInfo *> elements;
823 bool metaCopyNeeded =
false;
826 CopyMatchKeysToSingleStruct(
P4::TypeMap *typeMap, std::set<const IR::P4Table *> *invokedInKey,
829 setName(
"CopyMatchKeysToSingleStruct");
832 const IR::Node *preorder(IR::Key *key)
override;
833 const IR::Node *postorder(IR::KeyElement *element)
override;
834 const IR::Node *doStatement(
const IR::Statement *statement,
const IR::Expression *expression,
835 const Visitor::Context *ctxt)
override;
836 struct keyInfo *getKeyInfo(IR::Key *keys);
837 cstring getTableKeyName(
const IR::Expression *e);
838 int getFieldSizeBits(
const IR::Type *field_type);
839 bool isLearnerTable(
const IR::P4Table *t);
846 std::map<cstring, std::vector<std::tuple<cstring, IR::Constant *>>> actionCaseMap;
850 void addToSwitchMap(
cstring actionName,
cstring switchExprTmp, IR::Constant *caseLabelValue) {
851 actionCaseMap[actionName].push_back(std::make_tuple(switchExprTmp, caseLabelValue));
854 const IR::Node *setSwitchVarInAction(IR::P4Action *action) {
855 if (actionCaseMap.count(action->name.name)) {
858 auto acm = actionCaseMap[action->name.name];
859 auto body =
new IR::BlockStatement(action->body->srcInfo);
860 for (
auto pair : acm) {
861 auto assn =
new IR::AssignmentStatement(
862 new IR::PathExpression(
IR::ID(get<0>(pair))), get<1>(pair));
863 body->push_back(assn);
865 for (
auto s : action->body->components) body->push_back(s);
867 actionCaseMap.erase(action->name.name);
876class SplitP4TableCommon :
public Transform {
881 enum class TableImplementation { DEFAULT, ACTION_PROFILE, ACTION_SELECTOR };
886 TableImplementation implementation;
887 std::set<cstring> match_tables;
888 std::map<cstring, cstring> group_tables;
889 std::map<cstring, cstring> member_tables;
890 std::map<cstring, cstring> member_ids;
891 std::map<cstring, cstring> group_ids;
895 : refMap(refMap), typeMap(typeMap), structure(structure), sw(sw) {
896 implementation = TableImplementation::DEFAULT;
899 const IR::Node *postorder(IR::MethodCallStatement *)
override;
900 const IR::Node *postorder(IR::IfStatement *)
override;
901 const IR::Node *postorder(IR::SwitchStatement *)
override;
902 const IR::Node *postorder(IR::P4Control *)
override;
904 const IR::P4Table * );
906 const IR::P4Table *create_member_table(
const IR::P4Table *,
cstring,
cstring);
919class SplitActionSelectorTable :
public SplitP4TableCommon {
923 : SplitP4TableCommon(refMap, typeMap, structure, sw) {
924 implementation = TableImplementation::ACTION_SELECTOR;
926 const IR::Node *postorder(IR::P4Table *tbl)
override;
934class SplitActionProfileTable :
public SplitP4TableCommon {
938 : SplitP4TableCommon(refMap, typeMap, structure, sw) {
939 implementation = TableImplementation::ACTION_PROFILE;
941 const IR::Node *postorder(IR::P4Table *tbl)
override;
963class UpdateActionForSwitch :
public Transform {
967 explicit UpdateActionForSwitch(
SwitchHandler &sw) : sw(sw) { setName(
"UpdateActionForSwitch"); }
968 const IR::Node *postorder(IR::P4Action *action) {
return sw.setSwitchVarInAction(action); }
972class ConvertActionSelectorAndProfile :
public PassManager {
993class CollectDirectCounterMeter :
public Inspector {
1003 bool methodCallFound;
1004 int getTableSize(
const IR::P4Table *tbl);
1005 bool ifMethodFound(
const IR::P4Action *a,
cstring method,
1006 cstring instancename = cstring::empty);
1013 : refMap(refMap), typeMap(typeMap), structure(structure) {
1014 setName(
"CollectDirectCounterMeter");
1015 visitDagOnce =
false;
1016 method = cstring::empty;
1017 instancename = cstring::empty;
1018 oneInstance = cstring::empty;
1019 methodCallFound =
false;
1022 bool preorder(
const IR::MethodCallStatement *mcs)
override;
1023 bool preorder(
const IR::AssignmentStatement *assn)
override;
1024 bool preorder(
const IR::P4Action *a)
override;
1025 bool preorder(
const IR::P4Table *t)
override;
1028class ValidateDirectCounterMeter :
public Inspector {
1037 : refMap(refMap), typeMap(typeMap), structure(structure) {}
1039 void postorder(
const IR::AssignmentStatement *)
override;
1040 void postorder(
const IR::MethodCallStatement *)
override;
1043class CollectAddOnMissTable :
public Inspector {
1051 : refMap(refMap), typeMap(typeMap), structure(structure) {}
1053 void postorder(
const IR::P4Table *t)
override;
1054 void postorder(
const IR::MethodCallStatement *)
override;
1057class ValidateAddOnMissExterns :
public Inspector {
1065 : refMap(refMap), typeMap(typeMap), structure(structure) {}
1067 void postorder(
const IR::MethodCallStatement *)
override;
1068 cstring getDefActionName(
const IR::P4Table *t) {
1069 auto act = t->getDefaultAction();
1070 BUG_CHECK(act !=
nullptr,
"%1%: default action does not exist", t);
1071 if (
auto mc = act->to<IR::MethodCallExpression>()) {
1072 auto method = mc->method->to<IR::PathExpression>();
1073 return method->path->name;
1081class ValidateOperandSize :
public Inspector {
1083 ValidateOperandSize() { setName(
"ValidateOperandSize"); }
1084 void isValidOperandSize(
const IR::Expression *e) {
1085 if (
auto t = e->type->to<IR::Type_Bits>()) {
1087 ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
"Unsupported bitwidth %1% in %2%",
1088 t->width_bits(), e);
1094 void postorder(
const IR::Operation_Binary *binop)
override {
1095 if (binop->is<IR::BOr>() || binop->is<IR::BAnd>() || binop->is<IR::BXor>() ||
1096 binop->is<IR::Equ>() || binop->is<IR::Neq>()) {
1097 if (
auto src1Type = binop->left->type->to<IR::Type_Bits>()) {
1098 if (src1Type->width_bits() == 128)
return;
1101 isValidOperandSize(binop->left);
1102 isValidOperandSize(binop->right);
1106 void postorder(
const IR::Operation_Unary *unop)
override {
1107 if (unop->is<IR::Cast>())
return;
1108 if (unop->is<IR::Cmpl>()) {
1109 if (
auto src1Type = unop->expr->type->to<IR::Type_Bits>()) {
1110 if (src1Type->width_bits() == 128)
return;
1113 isValidOperandSize(unop->expr);
1116 void postorder(
const IR::Operation_Ternary *top)
override {
1117 isValidOperandSize(top->e0);
1118 isValidOperandSize(top->e1);
1119 isValidOperandSize(top->e2);
1123class CollectErrors :
public Inspector {
1128 CHECK_NULL(structure);
1130 void postorder(
const IR::Type_Error *
error)
override {
1132 for (
auto err :
error->members) {
1133 if (structure->error_map.count(err->name.name) == 0) {
1134 structure->error_map.emplace(err->name.name,
id++);
1164class ElimHeaderCopy :
public Transform {
1177 explicit ElimHeaderCopy(
P4::TypeMap *typeMap) : typeMap{typeMap} {}
1178 bool isHeader(
const IR::Expression *e);
1179 const IR::Node *preorder(IR::AssignmentStatement *as)
override;
1180 const IR::Node *preorder(IR::MethodCallStatement *mcs)
override;
1181 const IR::Node *postorder(IR::Member *m)
override;
1184class EliminateHeaderCopy :
public PassManager {
1198class HaveNonHeaderLargeOperandAssignment :
public Inspector {
1199 bool &is_all_arg_header_fields;
1202 explicit HaveNonHeaderLargeOperandAssignment(
bool &is_all_arg_header_fields)
1203 : is_all_arg_header_fields(is_all_arg_header_fields) {}
1204 bool preorder(
const IR::AssignmentStatement *assn)
override {
1205 if (!is_all_arg_header_fields)
return false;
1206 if ((isLargeFieldOperand(assn->left) && !isLargeFieldOperand(assn->right) &&
1207 !isInsideHeader(assn->right)) ||
1208 (isLargeFieldOperand(assn->left) && assn->right->is<IR::Constant>()) ||
1209 (!isLargeFieldOperand(assn->left) && isLargeFieldOperand(assn->right) &&
1210 !isInsideHeader(assn->left))) {
1211 is_all_arg_header_fields &=
false;
1220class HaveNonHeaderChecksumArgs :
public Inspector {
1222 bool &is_all_arg_header_fields;
1225 HaveNonHeaderChecksumArgs(
P4::TypeMap *typeMap,
bool &is_all_arg_header_fields)
1226 : typeMap(typeMap), is_all_arg_header_fields(is_all_arg_header_fields) {}
1227 bool preorder(
const IR::MethodCallExpression *mce)
override {
1228 if (!is_all_arg_header_fields)
return false;
1229 if (
auto *m = mce->method->to<IR::Member>()) {
1230 if (
auto *type = typeMap->getType(m->expr)->to<IR::Type_Extern>()) {
1231 if (type->name ==
"InternetChecksum") {
1232 if (m->member ==
"add" || m->member ==
"subtract") {
1233 for (
auto arg : *mce->arguments) {
1234 if (
auto se = arg->expression->to<IR::StructExpression>()) {
1235 for (
auto c : se->components) {
1236 if (
auto m0 = c->expression->to<IR::Member>()) {
1237 if (!typeMap->getType(m0->expr,
true)
1238 ->is<IR::Type_Header>()) {
1239 is_all_arg_header_fields =
false;
1243 is_all_arg_header_fields =
false;
1247 }
else if (arg->expression->to<IR::Constant>()) {
1248 is_all_arg_header_fields =
false;
1250 }
else if (
auto m = arg->expression->to<IR::Member>()) {
1251 if (!(typeMap->getType(m->expr,
true)->is<IR::Type_Header>() ||
1252 typeMap->getType(m,
true)->is<IR::Type_Header>())) {
1253 is_all_arg_header_fields =
false;
1272class DpdkAddPseudoHeaderDecl :
public Transform {
1275 bool &is_all_args_header;
1279 static cstring pseudoHeaderInstanceName;
1280 static cstring pseudoHeaderTypeName;
1282 bool &is_all_args_header)
1283 : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header) {
1284 pseudoHeaderInstanceName = refMap->newName(
"dpdk_pseudo_header");
1285 pseudoHeaderTypeName = refMap->newName(
"dpdk_pseudo_header_t");
1286 (void)this->typeMap;
1290 const IR::Node *preorder(IR::P4Program *program)
override;
1291 const IR::Node *preorder(IR::Type_Struct *st)
override;
1309class MoveNonHeaderFieldsToPseudoHeader :
public Transform {
1312 bool &is_all_args_header;
1316 static std::vector<std::pair<cstring, const IR::Type *>> pseudoFieldNameType;
1318 bool &is_all_args_header)
1319 : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header) {}
1320 std::pair<IR::AssignmentStatement *, IR::Member *> addAssignmentStmt(
const IR::Expression *ne);
1322 const IR::Node *postorder(IR::P4Program *p)
override {
1323 if (newStructTypes.size() > 0) {
1325 allTypeDecls.append(newStructTypes);
1326 allTypeDecls.append(p->objects);
1327 p->objects = allTypeDecls;
1331 const IR::Node *postorder(IR::MethodCallStatement *statement)
override;
1332 const IR::Node *postorder(IR::AssignmentStatement *statement)
override;
1337class AddFieldsToPseudoHeader :
public Transform {
1340 bool &is_all_args_header;
1344 bool &is_all_args_header)
1345 : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header) {
1346 (void)this->typeMap;
1349 const IR::Node *preorder(IR::Type_Header *h)
override;
1352struct DpdkAddPseudoHeader :
public PassManager {
1355 bool &is_all_args_header;
1359 bool &is_all_args_header_fields)
1360 : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header_fields) {
1374class DpdkArchFirst :
public PassManager {
1376 DpdkArchFirst() { setName(
"DpdkArchFirst"); }
1379class DpdkArchLast :
public PassManager {
1381 DpdkArchLast() { setName(
"DpdkArchLast"); }
1384class CollectProgramStructure :
public PassManager {
1390 passes.push_back(evaluator);
1391 passes.push_back(
new VisitFunctor([evaluator, parseDpdk]() {
1392 auto toplevel = evaluator->getToplevelBlock();
1393 auto main = toplevel->getMain();
1394 if (main ==
nullptr) {
1396 "Could not locate top-level block; is there a %1% module?",
1397 IR::P4Program::main);
1400 main->apply(*parseDpdk);
1407class MoveCollectedStructLocalVariableToMetadata :
public Transform {
1411 explicit MoveCollectedStructLocalVariableToMetadata(
P4::TypeMap *typeMap) : typeMap(typeMap) {}
1412 const IR::Node *preorder(IR::Type_Struct *s)
override;
1413 const IR::Node *postorder(IR::P4Control *c)
override;
1414 const IR::Node *postorder(IR::P4Program *p)
override;
1415 const IR::Node *postorder(IR::P4Parser *c)
override;
1419class CollectStructLocalVariables :
public Transform {
1425 : refMap(refMap), typeMap(typeMap) {}
1426 const IR::Node *postorder(IR::P4Parser *c)
override;
1427 const IR::Node *preorder(IR::PathExpression *path)
override;
1428 static const IR::Type_Struct *metadataStrct;
1429 static std::map<cstring, const IR::Type *> fieldNameType;
1435class CollectLocalStructAndFlatten :
public PassManager {
1453class CollectIPSecInfo :
public Inspector {
1454 bool &is_ipsec_used;
1461 CollectIPSecInfo(
bool &is_ipsec_used,
int &sa_id_width,
P4::ReferenceMap *refMap,
1463 : is_ipsec_used(is_ipsec_used),
1464 sa_id_width(sa_id_width),
1467 structure(structure) {}
1468 bool preorder(
const IR::MethodCallStatement *mcs)
override {
1471 if (a->originalExternType->getName().name ==
"ipsec_accelerator") {
1472 if (structure->isPSA()) {
1473 ::P4::error(ErrorType::ERR_MODEL,
"%1% is not available for PSA programs",
1474 a->originalExternType->getName().name);
1477 if (a->method->getName().name ==
"enable") {
1478 is_ipsec_used =
true;
1479 }
else if (a->method->getName().name ==
"set_sa_index") {
1480 auto typeArgs = a->expr->typeArguments;
1481 if (typeArgs->size() != 1) {
1483 "Unexpected number of type arguments for %1%", a->method->name);
1486 auto width = typeArgs->at(0);
1487 if (!width->is<IR::Type_Bits>()) {
1488 ::P4::error(ErrorType::ERR_MODEL,
"Unexpected width type %1% for sa_index",
1492 sa_id_width = width->to<IR::Type_Bits>()->width_bits();
1505class InsertReqDeclForIPSec :
public Transform {
1508 bool &is_ipsec_used;
1510 cstring newHeaderName =
"platform_hdr_t"_cs;
1511 IR::Type_Header *ipsecHeader =
nullptr;
1512 std::vector<cstring> registerInstanceNames = {
1513 "ipsec_port_out_inbound"_cs,
"ipsec_port_out_outbound"_cs,
"ipsec_port_in_inbound"_cs,
1514 "ipsec_port_in_outbound"_cs};
1518 bool &is_ipsec_used,
int &sa_id_width)
1520 structure(structure),
1521 is_ipsec_used(is_ipsec_used),
1522 sa_id_width(sa_id_width) {
1523 setName(
"InsertReqDeclForIPSec");
1526 const IR::Node *preorder(IR::P4Program *program)
override;
1527 const IR::Node *preorder(IR::Type_Struct *s)
override;
1528 const IR::Node *preorder(IR::P4Control *c)
override;
1532struct DpdkHandleIPSec :
public PassManager {
1536 bool is_ipsec_used =
false;
1537 int sa_id_width = 32;
1541 : refMap(refMap), typeMap(typeMap), structure(structure) {
1543 new CollectIPSecInfo(is_ipsec_used, sa_id_width, refMap, typeMap, structure));
Definition typeChecker.h:32
Definition dpdkArch.h:696
Definition dpdkArch.h:1453
Definition dpdkArch.h:543
Definition dpdkArch.h:1419
bool preorder(const IR::Key *key) override
Definition dpdkArch.cpp:636
Definition dpdkArch.h:158
Definition dpdkArch.h:169
Definition dpdkArch.h:100
Definition dpdkArch.h:279
void postorder(const IR::P4Table *t) override
Definition dpdkArch.cpp:1216
This pass checks whether an assignment statement has large operands (>64-bit).
Definition dpdkArch.h:1198
Definition dpdkArch.h:1505
IR::IndexedVector< IR::StatOrDecl > * addRegDeclInstance(std::vector< cstring > portRegs)
Create and add register declaration instance to program.
Definition dpdkArch.cpp:3215
bool preorder(const IR::Operation_Unary *a) override
Definition dpdkArch.cpp:898
Definition dpdkArch.h:934
Definition dpdkArch.h:919
IR::Expression * initializeMemberAndGroupId(cstring tableName, IR::IndexedVector< IR::StatOrDecl > *decls)
Definition dpdkArch.cpp:2118
std::tuple< const IR::P4Table *, cstring, cstring > create_match_table(const IR::P4Table *)
Definition dpdkArch.cpp:1773
Definition dpdkArch.h:729
Definition dpdkArch.h:842
Definition dpdkArch.h:963
Definition removeLeftSlices.h:35
Definition evaluator.h:115
Definition methodInstance.h:168
Definition flattenInterfaceStructs.h:238
Definition indexed_vector.h:31
Definition ir/vector.h:59
Definition sideEffects.h:253
static MethodInstance * resolve(const IR::MethodCallExpression *mce, const DeclarationLookup *refMap, TypeMap *typeMap, bool useExpressionType=false, const Visitor::Context *ctxt=nullptr, bool incomplete=false)
Definition methodInstance.cpp:27
Definition dpdkProgramStructure.h:132
Definition ir/pass_manager.h:146
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition resolveReferences.h:124
Definition typeChecker.h:55
Definition typeChecker.h:491
Definition source_file.h:132
Definition ir/pass_manager.h:185
Definition ordered_map.h:32
Definition dpdk/backend.cpp:26
void expressionUnrollSanityCheck(const IR::Expression *e)
Definition dpdkArch.cpp:36
Definition dpdkArch.h:806
Definition dpdkArch.h:811
const int dpdk_max_operand_size
Maximum operand size for unary, binary and ternary operations.
Definition dpdk/constants.h:56
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
Definition register_reference.h:28