17#ifndef BACKENDS_DPDK_DPDKARCH_H_ 
   18#define BACKENDS_DPDK_DPDKARCH_H_ 
   21#include "dpdkProgramStructure.h" 
   23#include "frontends/common/resolveReferences/resolveReferences.h" 
   24#include "frontends/p4/evaluator/evaluator.h" 
   25#include "frontends/p4/sideEffects.h" 
   26#include "frontends/p4/typeMap.h" 
   28#include "lib/ordered_map.h" 
   29#include "midend/flattenInterfaceStructs.h" 
   30#include "midend/removeLeftSlices.h" 
   37bool isSimpleExpression(
const IR::Expression *e);
 
   38bool isNonConstantSimpleExpression(
const IR::Expression *e);
 
   41using UserMeta = std::set<cstring>;
 
   43class CollectMetadataHeaderInfo;
 
   61    const IR::Type_Control *rewriteControlType(
const IR::Type_Control *, 
cstring);
 
   62    const IR::Type_Parser *rewriteParserType(
const IR::Type_Parser *, 
cstring);
 
   63    const IR::Type_Control *rewriteDeparserType(
const IR::Type_Control *, 
cstring);
 
   64    const IR::Node *postorder(IR::Type_Control *c) 
override;
 
   65    const IR::Node *postorder(IR::Type_Parser *p) 
override;
 
   66    const IR::Node *preorder(IR::Member *m) 
override;
 
   67    const IR::Node *preorder(IR::PathExpression *pe) 
override;
 
   71        : refMap(refMap), structure(structure) {
 
   72        CHECK_NULL(structure);
 
 
  110        std::unordered_map<const IR::P4Program *, IR::IndexedVector<IR::Node>> newHeaderMap;
 
  111        std::unordered_map<const IR::P4Parser *, IR::IndexedVector<IR::Declaration>> newLocalVarMap;
 
  112        std::unordered_map<const IR::AssignmentStatement *, IR::IndexedVector<IR::StatOrDecl>>
 
  116        void insertHeader(
const IR::P4Program *p, 
const IR::Type_Header *h) {
 
  117            if (newHeaderMap.count(p)) {
 
  118                newHeaderMap.at(p).push_back(h);
 
  122            LOG5(
"Program: " << dbp(p));
 
  123            LOG2(
"Adding new header:" << std::endl << 
" " << h);
 
  126            if (newHeaderMap.count(p)) {
 
  131        void insertVar(
const IR::P4Parser *p, 
const IR::Declaration_Variable *v) {
 
  132            if (newLocalVarMap.count(p)) {
 
  133                newLocalVarMap.at(p).push_back(v);
 
  137            LOG5(
"Parser: " << dbp(p));
 
  138            LOG2(
"Adding new local variable:" << std::endl << 
" " << v);
 
  141            if (newLocalVarMap.count(p)) {
 
  146        void insertStatements(
const IR::AssignmentStatement *as,
 
  148            BUG_CHECK(newStatMap.count(as) == 0,
 
  149                      "Unexpectedly converting statement %1% multiple times!", as);
 
  150            newStatMap.emplace(as, *vec);
 
  151            LOG5(
"AssignmentStatement: " << dbp(as));
 
  152            LOG2(
"Adding new statements:");
 
  153            for (
auto s : *vec) {
 
  158            if (newStatMap.count(as)) {
 
 
  174            : refMap(refMap), typeMap(typeMap), repl(repl) {}
 
  175        void postorder(
const IR::AssignmentStatement *statement) 
override;
 
 
  184            : structure(structure), repl(repl) {}
 
  185        const IR::Node *postorder(IR::AssignmentStatement *as) 
override;
 
  186        const IR::Node *postorder(IR::Type_Struct *s) 
override;
 
  187        const IR::Node *postorder(IR::P4Parser *parser) 
override;
 
 
  192        passes.push_back(
new Collect(refMap, typeMap, &repl));
 
  193        passes.push_back(
new Replace(s, &repl));
 
 
  205    void pushMetadata(
const IR::Parameter *p);
 
  206    void pushMetadata(
const IR::ParameterList *, std::list<int> indices);
 
  210    bool preorder(
const IR::P4Program *p) 
override;
 
  211    bool preorder(
const IR::Type_Struct *s) 
override;
 
 
  222    const IR::Node *preorder(IR::Type_Struct *s) 
override;
 
 
  234    const IR::Node *preorder(IR::Type_Struct *s) 
override;
 
 
  247        CHECK_NULL(structure);
 
  249    const IR::Node *preorder(IR::Type_StructLike *st) 
override;
 
  250    const IR::Node *preorder(IR::Member *m) 
override;
 
 
  260        : typeMap(typeMap), refMap(refMap), structure(structure) {
 
  261        CHECK_NULL(structure);
 
 
  289    std::map<const IR::Node *, IR::IndexedVector<IR::Declaration> *> decl_map;
 
  293    void collect(
const IR::P4Control *control, 
const IR::P4Parser *parser,
 
  294                 const IR::Declaration *decl) {
 
  297            auto res = decl_map.find(parser);
 
  298            if (res != decl_map.end()) {
 
  302                decl_map.emplace(parser, decls);
 
  304        } 
else if (control) {
 
  305            auto res = decl_map.find(control);
 
  306            if (res != decl_map.end()) {
 
  310                decl_map.emplace(control, decls);
 
  313        BUG_CHECK(decls != 
nullptr, 
"decls cannot be null");
 
  314        decls->push_back(decl);
 
  317        auto res = decl_map.find(orig);
 
  318        if (res == decl_map.end()) {
 
  321        control->controlLocals.prepend(*res->second);
 
  325        auto res = decl_map.find(orig);
 
  326        if (res == decl_map.end()) {
 
  329        parser->parserLocals.prepend(*res->second);
 
 
  348        : refMap(refMap), structure(structure) {}
 
  349    const IR::Node *preorder(IR::AssignmentStatement *a) 
override;
 
  350    const IR::Node *postorder(IR::P4Control *a) 
override;
 
  351    const IR::Node *postorder(IR::P4Parser *a) 
override;
 
 
  369    IR::PathExpression *root;
 
  371        setName(
"ExpressionUnroll");
 
  373    bool preorder(
const IR::Operation_Unary *a) 
override;
 
  374    bool preorder(
const IR::Operation_Binary *a) 
override;
 
  375    bool preorder(
const IR::MethodCallExpression *a) 
override;
 
  376    bool preorder(
const IR::Member *a) 
override;
 
  377    bool preorder(
const IR::PathExpression *a) 
override;
 
  378    bool preorder(
const IR::Constant *a) 
override;
 
  379    bool preorder(
const IR::BoolLiteral *a) 
override;
 
 
  392        setName(
"IfStatementUnroll");
 
  394    const IR::Node *postorder(IR::SwitchStatement *a) 
override;
 
  395    const IR::Node *postorder(IR::IfStatement *a) 
override;
 
  396    const IR::Node *postorder(IR::P4Control *a) 
override;
 
  397    const IR::Node *postorder(IR::P4Parser *a) 
override;
 
 
  410    IR::Expression *root;
 
  411    static bool is_logical(
const IR::Operation_Binary *bin) {
 
  412        if (bin->is<IR::LAnd>() || bin->is<IR::LOr>() || bin->is<IR::Leq>() || bin->is<IR::Equ>() ||
 
  413            bin->is<IR::Neq>() || bin->is<IR::Grt>() || bin->is<IR::Lss>() || bin->is<IR::Geq>() ||
 
  421        visitDagOnce = 
false;
 
  423    bool preorder(
const IR::Operation_Unary *a) 
override;
 
  424    bool preorder(
const IR::Operation_Binary *a) 
override;
 
  425    bool preorder(
const IR::MethodCallExpression *a) 
override;
 
  426    bool preorder(
const IR::Member *a) 
override;
 
  427    bool preorder(
const IR::PathExpression *a) 
override;
 
  428    bool preorder(
const IR::Constant *a) 
override;
 
  429    bool preorder(
const IR::BoolLiteral *a) 
override;
 
 
  441    const IR::Node *postorder(IR::AssignmentStatement *a) 
override;
 
  442    const IR::Node *postorder(IR::P4Control *a) 
override;
 
  443    const IR::Node *postorder(IR::P4Parser *a) 
override;
 
 
  458        for (
auto d : *locals) {
 
  459            if (
auto dv = d->to<IR::Declaration_Variable>()) {
 
  460                const cstring name = refMap->
newName(prefix + 
"_" + dv->name.name);
 
  461                localsMap.emplace(dv, name);
 
  462            } 
else if (!d->is<IR::P4Action>() && !d->is<IR::P4Table>() &&
 
  463                       !d->is<IR::Declaration_Instance>()) {
 
  464                BUG(
"%1%: Unhandled declaration type", d);
 
  472        : refMap(refMap), typeMap(typeMap), structure(structure) {}
 
  473    const IR::Node *preorder(IR::P4Program *p) 
override;
 
  474    const IR::Node *postorder(IR::Type_Struct *s) 
override;
 
  475    const IR::Node *postorder(IR::Member *m) 
override;
 
  476    const IR::Node *postorder(IR::PathExpression *path) 
override;
 
  477    const IR::Node *postorder(IR::P4Control *c) 
override;
 
  478    const IR::Node *postorder(IR::P4Parser *p) 
override;
 
 
  497        : typeMap(typeMap), refMap(refMap), structure(structure) {}
 
  498    const IR::Node *postorder(IR::P4Action *a) 
override;
 
  499    const IR::Node *postorder(IR::P4Program *s) 
override;
 
  500    const IR::Node *preorder(IR::PathExpression *path) 
override;
 
  501    const IR::Node *preorder(IR::MethodCallExpression *) 
override;
 
 
  517        : typeMap(typeMap), refMap(refMap), structure(structure) {}
 
  518    void postorder(
const IR::P4Table *t) 
override;
 
 
  530    cstring createTemporary(
const IR::Type *type);
 
  532                                        const IR::Expression *expression);
 
  536        : typeMap(typeMap), refMap(refMap) {}
 
  537    const IR::Node *preorder(IR::Mux *expression) 
override;
 
  538    const IR::Node *postorder(IR::P4Parser *parser) 
override;
 
  539    const IR::Node *postorder(IR::Function *function) 
override;
 
  540    const IR::Node *postorder(IR::P4Control *control) 
override;
 
  541    const IR::Node *postorder(IR::P4Action *action) 
override;
 
  542    const IR::Node *postorder(IR::AssignmentStatement *statement) 
override;
 
 
  555    std::vector<cstring> *csum_vec;
 
  560                                    std::vector<cstring> *csum_vec)
 
  561        : typeMap(typeMap), structure(structure), csum_vec(csum_vec) {}
 
  562    bool preorder(
const IR::Declaration_Instance *d)
 override {
 
  563        auto type = typeMap->getType(d, 
true);
 
  564        if (
auto extn = type->to<IR::Type_Extern>()) {
 
  565            if (extn->name == 
"InternetChecksum") {
 
  566                std::ostringstream s;
 
  567                s << 
"state_" << index++;
 
  568                csum_vec->push_back(s.str());
 
  569                structure->csum_map.emplace(d, s.str());
 
 
  581    std::vector<cstring> *csum_vec;
 
  585                                            std::vector<cstring> *csum_vec)
 
  586        : structure(structure), csum_vec(csum_vec) {}
 
  588    const IR::Node *postorder(IR::P4Program *p)
 override {
 
  590        bool inserted = 
false;
 
  591        for (
auto obj : p->objects) {
 
  592            if (obj->to<IR::Type_Header>() && !inserted) {
 
  594                if (csum_vec->size() > 0) {
 
  596                    for (
auto fld : *csum_vec) {
 
  598                            new IR::StructField(
IR::ID(fld), IR::Type::Bits::get(16, 
false)));
 
  600                    new_objs->push_back(
new IR::Type_Header(
IR::ID(
"cksum_state_t"), *fields));
 
  603            new_objs->push_back(obj);
 
  605        p->objects = *new_objs;
 
  609    const IR::Node *postorder(IR::Type_Struct *s)
 override {
 
  610        if (s->name.name == structure->header_type) {
 
  611            if (structure->csum_map.size() > 0)
 
  612                s->fields.push_back(
new IR::StructField(
 
  613                    IR::ID(
"cksum_state"), 
new IR::Type_Name(
IR::ID(
"cksum_state_t"))));
 
 
  620    std::vector<cstring> csum_vec;
 
 
  636    bool preorder(
const IR::Declaration_Instance *d)
 override {
 
  637        if (
auto type = d->type->to<IR::Type_Name>()) {
 
  638            auto externTypeName = type->path->name.name;
 
  639            if (externTypeName == 
"DirectMeter") {
 
  640                if (d->arguments->size() != 1) {
 
  641                    ::error(ErrorType::ERR_EXPECTED,
 
  642                            "%1%: expected type of meter as the only argument", d);
 
  645                    if (d->arguments->at(0)->expression->to<IR::Constant>()->asUnsigned() == 0)
 
  646                        warn(ErrorType::WARN_UNSUPPORTED,
 
  647                             "%1%: Packet metering is not supported." 
  648                             " Falling back to byte metering.",
 
  655            structure->externDecls.push_back(d);
 
  656        } 
else if (
auto type = d->type->to<IR::Type_Specialized>()) {
 
  657            auto externTypeName = type->baseType->path->name.name;
 
  658            if (externTypeName == 
"Meter") {
 
  659                if (d->arguments->size() != 2) {
 
  660                    ::error(ErrorType::ERR_EXPECTED,
 
  661                            "%1%: expected number of meters and type of meter as arguments", d);
 
  664                    if (d->arguments->at(1)->expression->to<IR::Constant>()->asUnsigned() == 0)
 
  665                        warn(ErrorType::WARN_UNSUPPORTED,
 
  666                             "%1%: Packet metering is not supported." 
  667                             " Falling back to byte metering.",
 
  670            } 
else if (externTypeName == 
"Counter") {
 
  671                if (d->arguments->size() != 2) {
 
  672                    ::error(ErrorType::ERR_EXPECTED,
 
  673                            "%1%: expected number of counters and type of counter as arguments", d);
 
  675            } 
else if (externTypeName == 
"DirectCounter") {
 
  676                if (d->arguments->size() != 1) {
 
  677                    ::error(ErrorType::ERR_EXPECTED,
 
  678                            "%1%: expected type of counter as the only argument", d);
 
  680            } 
else if (externTypeName == 
"Register") {
 
  681                if (d->arguments->size() != 1 && d->arguments->size() != 2) {
 
  682                    ::error(ErrorType::ERR_EXPECTED,
 
  683                            "%1%: expected size and optionally init_val as arguments", d);
 
  685            } 
else if (externTypeName == 
"Hash") {
 
  686                if (d->arguments->size() != 1) {
 
  687                    ::error(ErrorType::ERR_EXPECTED,
 
  688                            "%1%: expected hash algorithm as the only argument", d);
 
  694            structure->externDecls.push_back(d);
 
 
  706    const IR::Node *postorder(IR::LAnd *land) {
 
  707        if (
auto land2 = land->left->to<IR::LAnd>()) {
 
  708            auto sub = 
new IR::LAnd(land2->right, land->right);
 
  709            return new IR::LAnd(land2->left, sub);
 
  710        } 
else if (!land->left->is<IR::LOr>() && !land->left->is<IR::Equ>() &&
 
  711                   !land->left->is<IR::Neq>() && !land->left->is<IR::Leq>() &&
 
  712                   !land->left->is<IR::Geq>() && !land->left->is<IR::Lss>() &&
 
  713                   !land->left->is<IR::Grt>() && !land->left->is<IR::MethodCallExpression>() &&
 
  714                   !land->left->is<IR::PathExpression>() && !land->left->is<IR::Member>()) {
 
  715            BUG(
"Logical Expression Unroll pass failed");
 
  719    const IR::Node *postorder(IR::LOr *lor) {
 
  720        if (
auto lor2 = lor->left->to<IR::LOr>()) {
 
  721            auto sub = 
new IR::LOr(lor2->right, lor->right);
 
  722            return new IR::LOr(lor2->left, sub);
 
  723        } 
else if (!lor->left->is<IR::LAnd>() && !lor->left->is<IR::Equ>() &&
 
  724                   !lor->left->is<IR::Neq>() && !lor->left->is<IR::Lss>() &&
 
  725                   !lor->left->is<IR::Grt>() && !lor->left->is<IR::MethodCallExpression>() &&
 
  726                   !lor->left->is<IR::PathExpression>() && !lor->left->is<IR::Member>()) {
 
  727            BUG(
"Logical Expression Unroll pass failed");
 
 
  739        if (n->
is<IR::Equ>() || n->
is<IR::Neq>() || n->
is<IR::Lss>() || n->
is<IR::Grt>() ||
 
  740            n->
is<IR::Geq>() || n->
is<IR::Leq>() || n->
is<IR::MethodCallExpression>() ||
 
  741            n->
is<IR::PathExpression>() || n->
is<IR::Member>()) {
 
  743        } 
else if (!n->
is<IR::LAnd>() && !n->
is<IR::LOr>()) {
 
  744            BUG(
"Logical Expression Unroll pass failed");
 
  751    const IR::Node *postorder(IR::LAnd *land) {
 
  752        if (!is_simple(land->left) && is_simple(land->right)) {
 
  753            return new IR::LAnd(land->right, land->left);
 
  754        } 
else if (!is_simple(land->left)) {
 
  755            if (
auto land2 = land->right->to<IR::LAnd>()) {
 
  756                if (is_simple(land2->left)) {
 
  757                    auto sub = 
new IR::LAnd(land->left, land2->right);
 
  758                    return new IR::LAnd(land2->left, sub);
 
  764    const IR::Node *postorder(IR::LOr *lor) {
 
  765        if (!is_simple(lor->left) && is_simple(lor->right)) {
 
  766            return new IR::LOr(lor->right, lor->left);
 
  767        } 
else if (!is_simple(lor->left)) {
 
  768            if (
auto lor2 = lor->right->to<IR::LOr>()) {
 
  769                if (is_simple(lor2->left)) {
 
  770                    auto sub = 
new IR::LOr(lor->left, lor2->right);
 
  771                    return new IR::LOr(lor2->left, sub);
 
 
  802        setName(
"CollectTableInfo");
 
  804    bool preorder(
const IR::Key *key) 
override;
 
 
  815    int offsetInMetadata;
 
 
  821    int numExistingMetaFields;
 
  825    std::vector<struct keyElementInfo *> elements;
 
 
  831    bool metaCopyNeeded = 
false;
 
  837        setName(
"CopyMatchKeysToSingleStruct");
 
  840    const IR::Node *preorder(IR::Key *key) 
override;
 
  841    const IR::Node *postorder(IR::KeyElement *element) 
override;
 
  842    const IR::Node *doStatement(
const IR::Statement *statement, 
const IR::Expression *expression,
 
  844    struct keyInfo *getKeyInfo(IR::Key *keys);
 
  845    cstring getTableKeyName(
const IR::Expression *e);
 
  846    int getFieldSizeBits(
const IR::Type *field_type);
 
  847    bool isLearnerTable(
const IR::P4Table *t);
 
 
  854    std::map<cstring, std::vector<std::tuple<cstring, IR::Constant *>>> actionCaseMap;
 
  858    void addToSwitchMap(
cstring actionName, 
cstring switchExprTmp, IR::Constant *caseLabelValue) {
 
  859        actionCaseMap[actionName].push_back(std::make_tuple(switchExprTmp, caseLabelValue));
 
  862    const IR::Node *setSwitchVarInAction(IR::P4Action *action) {
 
  863        if (actionCaseMap.count(action->name.name)) {
 
  866            auto acm = actionCaseMap[action->name.name];
 
  867            auto body = 
new IR::BlockStatement(action->body->srcInfo);
 
  868            for (
auto pair : acm) {
 
  869                auto assn = 
new IR::AssignmentStatement(
 
  870                    new IR::PathExpression(
IR::ID(get<0>(pair))), get<1>(pair));
 
  871                body->push_back(assn);
 
  873            for (
auto s : action->body->components) body->push_back(s);
 
  875            actionCaseMap.erase(action->name.name);
 
 
  889    enum class TableImplementation { DEFAULT, ACTION_PROFILE, ACTION_SELECTOR };
 
  894    TableImplementation implementation;
 
  895    std::set<cstring> match_tables;
 
  896    std::map<cstring, cstring> group_tables;
 
  897    std::map<cstring, cstring> member_tables;
 
  898    std::map<cstring, cstring> member_ids;
 
  899    std::map<cstring, cstring> group_ids;
 
  903        : refMap(refMap), typeMap(typeMap), structure(structure), sw(sw) {
 
  904        implementation = TableImplementation::DEFAULT;
 
  907    const IR::Node *postorder(IR::MethodCallStatement *) 
override;
 
  908    const IR::Node *postorder(IR::IfStatement *) 
override;
 
  909    const IR::Node *postorder(IR::SwitchStatement *) 
override;
 
  910    const IR::Node *postorder(IR::P4Control *) 
override;
 
  912        const IR::P4Table * );
 
  914    const IR::P4Table *create_member_table(
const IR::P4Table *, 
cstring, 
cstring);
 
 
  932        implementation = TableImplementation::ACTION_SELECTOR;
 
  934    const IR::Node *postorder(IR::P4Table *tbl) 
override;
 
 
  947        implementation = TableImplementation::ACTION_PROFILE;
 
  949    const IR::Node *postorder(IR::P4Table *tbl) 
override;
 
 
  976    const IR::Node *postorder(IR::P4Action *action) { 
return sw.setSwitchVarInAction(action); }
 
 
 1011    bool methodCallFound;
 
 1012    int getTableSize(
const IR::P4Table *tbl);
 
 1013    bool ifMethodFound(
const IR::P4Action *a, 
cstring method,
 
 1014                       cstring instancename = cstring::empty);
 
 1021        : refMap(refMap), typeMap(typeMap), structure(structure) {
 
 1022        setName(
"CollectDirectCounterMeter");
 
 1023        visitDagOnce = 
false;
 
 1024        method = cstring::empty;
 
 1025        instancename = cstring::empty;
 
 1026        oneInstance = cstring::empty;
 
 1027        methodCallFound = 
false;
 
 1030    bool preorder(
const IR::MethodCallStatement *mcs) 
override;
 
 1031    bool preorder(
const IR::AssignmentStatement *assn) 
override;
 
 1032    bool preorder(
const IR::P4Action *a) 
override;
 
 1033    bool preorder(
const IR::P4Table *t) 
override;
 
 
 1045        : refMap(refMap), typeMap(typeMap), structure(structure) {}
 
 1047    void postorder(
const IR::AssignmentStatement *) 
override;
 
 1048    void postorder(
const IR::MethodCallStatement *) 
override;
 
 
 1059        : refMap(refMap), typeMap(typeMap), structure(structure) {}
 
 1061    void postorder(
const IR::P4Table *t) 
override;
 
 1062    void postorder(
const IR::MethodCallStatement *) 
override;
 
 
 1073        : refMap(refMap), typeMap(typeMap), structure(structure) {}
 
 1075    void postorder(
const IR::MethodCallStatement *) 
override;
 
 1076    cstring getDefActionName(
const IR::P4Table *t) {
 
 1077        auto act = t->getDefaultAction();
 
 1078        BUG_CHECK(act != 
nullptr, 
"%1%: default action does not exist", t);
 
 1079        if (
auto mc = act->to<IR::MethodCallExpression>()) {
 
 1080            auto method = mc->method->to<IR::PathExpression>();
 
 1081            return method->path->name;
 
 
 1092    void isValidOperandSize(
const IR::Expression *e) {
 
 1093        if (
auto t = e->type->to<IR::Type_Bits>()) {
 
 1094            if (t->width_bits() > dpdk_max_operand_size) {
 
 1095                ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, 
"Unsupported bitwidth %1% in %2%",
 
 1096                        t->width_bits(), e);
 
 1102    void postorder(
const IR::Operation_Binary *binop)
 override {
 
 1103        isValidOperandSize(binop->left);
 
 1104        isValidOperandSize(binop->right);
 
 1108    void postorder(
const IR::Operation_Unary *unop)
 override {
 
 1109        if (unop->is<IR::Cast>()) 
return;
 
 1110        isValidOperandSize(unop->expr);
 
 1113    void postorder(
const IR::Operation_Ternary *top)
 override {
 
 1114        isValidOperandSize(top->e0);
 
 1115        isValidOperandSize(top->e1);
 
 1116        isValidOperandSize(top->e2);
 
 
 1125        CHECK_NULL(structure);
 
 1127    void postorder(
const IR::Type_Error *error)
 override {
 
 1129        for (
auto err : error->members) {
 
 1130            if (structure->error_map.count(err->name.name) == 0) {
 
 1131                structure->error_map.emplace(err->name.name, 
id++);
 
 
 1175    bool isHeader(
const IR::Expression *e);
 
 1176    const IR::Node *preorder(IR::AssignmentStatement *as) 
override;
 
 1177    const IR::Node *preorder(IR::MethodCallStatement *mcs) 
override;
 
 1178    const IR::Node *postorder(IR::Member *m) 
override;
 
 
 1196    bool &is_all_arg_header_fields;
 
 1200        : is_all_arg_header_fields(is_all_arg_header_fields) {}
 
 1201    bool preorder(
const IR::AssignmentStatement *assn)
 override {
 
 1202        if (!is_all_arg_header_fields) 
return false;
 
 1203        if ((isLargeFieldOperand(assn->left) && !isLargeFieldOperand(assn->right) &&
 
 1204             !isInsideHeader(assn->right)) ||
 
 1205            (isLargeFieldOperand(assn->left) && assn->right->is<IR::Constant>()) ||
 
 1206            (!isLargeFieldOperand(assn->left) && isLargeFieldOperand(assn->right) &&
 
 1207             !isInsideHeader(assn->left))) {
 
 1208            is_all_arg_header_fields &= 
false;
 
 
 1219    bool &is_all_arg_header_fields;
 
 1223        : typeMap(typeMap), is_all_arg_header_fields(is_all_arg_header_fields) {}
 
 1224    bool preorder(
const IR::MethodCallExpression *mce)
 override {
 
 1225        if (!is_all_arg_header_fields) 
return false;
 
 1226        if (
auto *m = mce->method->to<IR::Member>()) {
 
 1227            if (
auto *type = typeMap->getType(m->expr)->to<IR::Type_Extern>()) {
 
 1228                if (type->name == 
"InternetChecksum") {
 
 1229                    if (m->member == 
"add" || m->member == 
"subtract") {
 
 1230                        for (
auto arg : *mce->arguments) {
 
 1231                            if (
auto se = arg->expression->to<IR::StructExpression>()) {
 
 1232                                for (
auto c : se->components) {
 
 1233                                    if (
auto m0 = c->expression->to<IR::Member>()) {
 
 1234                                        if (!typeMap->getType(m0->expr, 
true)
 
 1235                                                 ->is<IR::Type_Header>()) {
 
 1236                                            is_all_arg_header_fields = 
false;
 
 1240                                        is_all_arg_header_fields = 
false;
 
 1244                            } 
else if (arg->expression->to<IR::Constant>()) {
 
 1245                                is_all_arg_header_fields = 
false;
 
 1247                            } 
else if (
auto m = arg->expression->to<IR::Member>()) {
 
 1248                                if (!(typeMap->getType(m->expr, 
true)->is<IR::Type_Header>() ||
 
 1249                                      typeMap->getType(m, 
true)->is<IR::Type_Header>())) {
 
 1250                                    is_all_arg_header_fields = 
false;
 
 
 1272    bool &is_all_args_header;
 
 1276    static cstring pseudoHeaderInstanceName;
 
 1277    static cstring pseudoHeaderTypeName;
 
 1279                            bool &is_all_args_header)
 
 1280        : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header) {
 
 1281        pseudoHeaderInstanceName = refMap->
newName(
"dpdk_pseudo_header");
 
 1282        pseudoHeaderTypeName = refMap->
newName(
"dpdk_pseudo_header_t");
 
 1283        (void)this->typeMap;
 
 1287    const IR::Node *preorder(IR::P4Program *program) 
override;
 
 1288    const IR::Node *preorder(IR::Type_Struct *st) 
override;
 
 
 1309    bool &is_all_args_header;
 
 1313    static std::vector<std::pair<cstring, const IR::Type *>> pseudoFieldNameType;
 
 1315                                      bool &is_all_args_header)
 
 1316        : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header) {}
 
 1317    std::pair<IR::AssignmentStatement *, IR::Member *> addAssignmentStmt(
const IR::Expression *ne);
 
 1319    const IR::Node *postorder(IR::P4Program *p)
 override {
 
 1320        if (newStructTypes.size() > 0) {
 
 1322            allTypeDecls.append(newStructTypes);
 
 1323            allTypeDecls.append(p->objects);
 
 1324            p->objects = allTypeDecls;
 
 1328    const IR::Node *postorder(IR::MethodCallStatement *statement) 
override;
 
 1329    const IR::Node *postorder(IR::AssignmentStatement *statement) 
override;
 
 
 1337    bool &is_all_args_header;
 
 1341                            bool &is_all_args_header)
 
 1342        : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header) {
 
 1343        (void)this->typeMap;
 
 1346    const IR::Node *preorder(IR::Type_Header *h) 
override;
 
 
 1352    bool &is_all_args_header;
 
 1356                        bool &is_all_args_header_fields)
 
 1357        : refMap(refMap), typeMap(typeMap), is_all_args_header(is_all_args_header_fields) {
 
 
 1387        passes.push_back(evaluator);
 
 1388        passes.push_back(
new VisitFunctor([evaluator, parseDpdk]() {
 
 1389            auto toplevel = evaluator->getToplevelBlock();
 
 1390            auto main = toplevel->getMain();
 
 1391            if (main == 
nullptr) {
 
 1392                ::error(ErrorType::ERR_NOT_FOUND,
 
 1393                        "Could not locate top-level block; is there a %1% module?",
 
 1394                        IR::P4Program::main);
 
 1397            main->apply(*parseDpdk);
 
 
 1409    const IR::Node *preorder(IR::Type_Struct *s) 
override;
 
 1410    const IR::Node *postorder(IR::P4Control *c) 
override;
 
 1411    const IR::Node *postorder(IR::P4Program *p) 
override;
 
 1412    const IR::Node *postorder(IR::P4Parser *c) 
override;
 
 
 1422        : refMap(refMap), typeMap(typeMap) {}
 
 1423    const IR::Node *postorder(IR::P4Parser *c) 
override;
 
 1424    const IR::Node *preorder(IR::PathExpression *path) 
override;
 
 1425    static const IR::Type_Struct *metadataStrct;
 
 1426    static std::map<cstring, const IR::Type *> fieldNameType;
 
 
 1451    bool &is_ipsec_used;
 
 1460        : is_ipsec_used(is_ipsec_used),
 
 1461          sa_id_width(sa_id_width),
 
 1464          structure(structure) {}
 
 1465    bool preorder(
const IR::MethodCallStatement *mcs)
 override {
 
 1468            if (a->originalExternType->getName().name == 
"ipsec_accelerator") {
 
 1469                if (structure->
isPSA()) {
 
 1470                    ::error(ErrorType::ERR_MODEL, 
"%1% is not available for PSA programs",
 
 1471                            a->originalExternType->getName().name);
 
 1474                if (a->method->getName().name == 
"enable") {
 
 1475                    is_ipsec_used = 
true;
 
 1476                } 
else if (a->method->getName().name == 
"set_sa_index") {
 
 1477                    auto typeArgs = a->expr->typeArguments;
 
 1478                    if (typeArgs->size() != 1) {
 
 1479                        ::error(ErrorType::ERR_MODEL, 
"Unexpected number of type arguments for %1%",
 
 1483                    auto width = typeArgs->at(0);
 
 1484                    if (!width->is<IR::Type_Bits>()) {
 
 1485                        ::error(ErrorType::ERR_MODEL, 
"Unexpected width type %1% for sa_index",
 
 1489                    sa_id_width = width->to<IR::Type_Bits>()->width_bits();
 
 
 1505    bool &is_ipsec_used;
 
 1507    cstring newHeaderName = 
"platform_hdr_t"_cs;
 
 1508    IR::Type_Header *ipsecHeader = 
nullptr;
 
 1509    std::vector<cstring> registerInstanceNames = {
 
 1510        "ipsec_port_out_inbound"_cs, 
"ipsec_port_out_outbound"_cs, 
"ipsec_port_in_inbound"_cs,
 
 1511        "ipsec_port_in_outbound"_cs};
 
 1515                          bool &is_ipsec_used, 
int &sa_id_width)
 
 1517          structure(structure),
 
 1518          is_ipsec_used(is_ipsec_used),
 
 1519          sa_id_width(sa_id_width) {
 
 1520        setName(
"InsertReqDeclForIPSec");
 
 1523    const IR::Node *preorder(IR::P4Program *program) 
override;
 
 1524    const IR::Node *preorder(IR::Type_Struct *s) 
override;
 
 1525    const IR::Node *preorder(IR::P4Control *c) 
override;
 
 
 1533    bool is_ipsec_used = 
false;
 
 1534    int sa_id_width = 32;
 
 1538        : refMap(refMap), typeMap(typeMap), structure(structure) {
 
 1540            new CollectIPSecInfo(is_ipsec_used, sa_id_width, refMap, typeMap, structure));
 
 
Definition dpdkArch.h:704
 
Definition dpdkArch.h:1051
 
Definition dpdkArch.h:1001
 
Definition dpdkArch.h:1120
 
Definition dpdkArch.h:631
 
Definition dpdkArch.h:1450
 
Definition dpdkArch.h:552
 
Definition dpdkArch.h:1432
 
Definition dpdkArch.h:451
 
Definition dpdkArch.h:1381
 
Definition dpdkArch.h:1416
 
Definition dpdkArch.h:797
 
bool preorder(const IR::Key *key) override
Definition dpdkArch.cpp:647
 
Definition dpdkArch.h:980
 
Definition dpdkArch.h:435
 
Definition dpdkArch.h:619
 
Definition dpdkArch.h:784
 
Definition dpdkArch.h:167
 
Definition dpdkArch.h:178
 
Definition dpdkArch.h:109
 
Definition dpdkArch.h:828
 
Definition dpdkArch.h:288
 
Definition dpdkArch.h:510
 
void postorder(const IR::P4Table *t) override
Definition dpdkArch.cpp:1228
 
Definition dpdkArch.h:524
 
Definition dpdkArch.h:1371
 
Definition dpdkArch.h:1376
 
Definition dpdkArch.h:363
 
This pass checks whether an assignment statement has large operands (>64-bit).
Definition dpdkArch.h:1195
 
Definition dpdkArch.h:385
 
Definition dpdkArch.h:217
 
Definition dpdkArch.h:1502
 
IR::IndexedVector< IR::StatOrDecl > * addRegDeclInstance(std::vector< cstring > portRegs)
Create and add register declaration instance to program.
Definition dpdkArch.cpp:3221
 
Definition dpdkArch.h:404
 
bool preorder(const IR::Operation_Unary *a) override
Definition dpdkArch.cpp:910
 
Definition dpdkArch.h:489
 
Definition dpdkArch.h:942
 
Definition dpdkArch.h:927
 
Definition dpdkArch.h:884
 
std::tuple< const IR::P4Table *, cstring, cstring > create_match_table(const IR::P4Table *)
Definition dpdkArch.cpp:1785
 
IR::Expression * initializeMemberAndGroupId(cstring tableName, IR::IndexedVector< IR::StatOrDecl > *decls)
Definition dpdkArch.cpp:2134
 
Definition dpdkArch.h:340
 
Definition dpdkArch.h:737
 
Definition dpdkArch.h:850
 
Definition dpdkArch.h:971
 
Definition dpdkArch.h:1065
 
Definition dpdkArch.h:1036
 
Definition dpdkArch.h:1089
 
Definition typeChecker.h:32
 
Definition removeLeftSlices.h:35
 
Definition evaluator.h:114
 
Definition methodInstance.h:149
 
Definition flattenInterfaceStructs.h:253
 
Definition sideEffects.h:295
 
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
 
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
 
cstring newName(std::string_view base) override
Generate a name from base that fresh for the program.
Definition referenceMap.cpp:96
 
Definition resolveReferences.h:118
 
Definition typeChecker.h:55
 
Definition typeChecker.h:78
 
Definition dpdkProgramStructure.h:117
 
Definition pass_manager.h:38
 
Definition pass_manager.h:143
 
Definition source_file.h:123
 
Definition pass_manager.h:182
 
Definition ordered_map.h:30
 
Definition dpdk/backend.cpp:36
 
void expressionUnrollSanityCheck(const IR::Expression *e)
Definition dpdkArch.cpp:47
 
Definition dpdkArch.h:814
 
Definition dpdkArch.h:819
 
Definition dpdkArch.h:253
 
Definition dpdkArch.h:108
 
Definition dpdkArch.h:1529
 
Definition dpdkArch.h:278
 
Collect information related to P4 programs targeting dpdk.
Definition dpdkProgramStructure.h:14
 
bool isPSA(void)
Predicate that states whether architecture is PSA or not.
Definition dpdkProgramStructure.h:87
 
bool is() const noexcept
Definition rtti.h:216