89    std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
 
   92    template <
typename Func>
 
   93    void forAllPipeBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
 
   94        auto main = evaluatedProgram->getMain();
 
   95        if (!main) ::error(ErrorType::ERR_NOT_FOUND, 
"Program does not contain a `main` module");
 
   96        auto cparams = main->getConstructorParameters();
 
   98        for (
auto param : main->constantValue) {
 
  100            if (!param.second) 
continue;
 
  101            auto pipe = param.second;
 
  102            if (!pipe->is<IR::PackageBlock>()) 
continue;
 
  103            auto idxParam = cparams->getParameter(index);
 
  104            auto pipeName = idxParam->name;
 
  105            function(pipeName, pipe->to<IR::PackageBlock>());
 
  114    using Counter = p4configv1::Counter;
 
  115    using Meter = p4configv1::Meter;
 
  116    using CounterSpec = p4configv1::CounterSpec;
 
  117    using MeterSpec = p4configv1::MeterSpec;
 
  120                         const IR::ToplevelBlock *evaluatedProgram)
 
  127        forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName, 
const IR::PackageBlock *pkg) {
 
  129                auto decl = pkg->node->to<IR::Declaration_Instance>();
 
  130                cstring blockNamePrefix = pipeName;
 
  131                if (decl) blockNamePrefix = decl->controlPlaneName();
 
  132                blockNamePrefixMap[block] = blockNamePrefix;
 
  137    cstring getBlockNamePrefix(
const IR::Block *blk) {
 
  138        if (blockNamePrefixMap.count(blk) > 0) 
return blockNamePrefixMap[blk];
 
  143                                               p4configv1::P4Info *p4info) {
 
  144        for (
auto &externType : *p4info->mutable_externs()) {
 
  145            if (externType.extern_type_id() == 
static_cast<p4rt_id_t
>(typeId)) 
return &externType;
 
  147        auto *externType = p4info->add_externs();
 
  148        externType->set_extern_type_id(
static_cast<p4rt_id_t
>(typeId));
 
  149        externType->set_extern_type_name(typeName);
 
  155                                        const IR::IAnnotated *annotations,
 
  156                                        const ::google::protobuf::Message &message,
 
  157                                        p4configv1::P4Info *p4info,
 
  158                                        cstring pipeName = cstring::empty) {
 
  159        auto *externType = getP4InfoExtern(typeId, typeName, p4info);
 
  160        auto *externInstance = externType->add_instances();
 
  161        auto *pre = externInstance->mutable_preamble();
 
  162        pre->set_id(symbols.
getId(typeId, name));
 
  163        pre->set_name(prefix(pipeName, name));
 
  164        pre->set_alias(symbols.
getAlias(name));
 
  165        Helpers::addAnnotations(pre, annotations);
 
  167        externInstance->mutable_info()->PackFrom(message);
 
  170    std::optional<ActionSelector> getActionSelector(
const IR::ExternBlock *instance) {
 
  173        auto size = instance->getParameterValue(
"size"_cs);
 
  174        BUG_CHECK(size->
is<IR::Constant>(), 
"Non-constant size");
 
  175        return ActionSelector{actionSelDecl->controlPlaneName(), size->
to<IR::Constant>()->asInt(),
 
  176                              ActionSelector::defaultMaxGroupSize,
 
  177                              size->
to<IR::Constant>()->asInt(),
 
  178                              actionSelDecl->to<IR::IAnnotated>()};
 
  183                           cstring pipeName = cstring::empty) {
 
  184        ::dpdk::ActionSelector selector;
 
  185        selector.set_max_group_size(actionSelector.maxGroupSize);
 
  186        selector.set_num_groups(actionSelector.numGroups);
 
  187        p4configv1::ActionProfile profile;
 
  188        profile.set_size(actionSelector.size);
 
  189        auto tablesIt = this->actionProfilesRefs.find(actionSelector.name);
 
  190        if (tablesIt != this->actionProfilesRefs.end()) {
 
  191            for (
const auto &table : tablesIt->second) {
 
  192                profile.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
 
  193                selector.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
 
  198        cstring profileName = actionSelector.name;
 
  199        selector.set_action_profile_id(
 
  200            symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
 
  201        cstring selectorName = profileName + 
"_sel";
 
  202        addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(),
 
  203                                "ActionSelector"_cs, selectorName, actionSelector.annotations,
 
  204                                selector, p4Info, pipeName);
 
  208                               const IR::ExternBlock *externBlock)
 override {
 
  212        if (decl == 
nullptr) 
return;
 
  213        if (externBlock->type->name == 
"Digest") {
 
  214            symbols->
add(SymbolType::P4RT_DIGEST(), decl);
 
  216            auto selName = decl->controlPlaneName() + 
"_sel";
 
  217            auto profName = decl->controlPlaneName();
 
  218            symbols->
add(SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), selName);
 
  219            symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), profName);
 
 
  224                            p4configv1::Table *table, 
const IR::TableBlock *tableBlock)
 override {
 
  227        auto tableDeclaration = tableBlock->container;
 
  229        if (supportsTimeout) {
 
  230            table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
 
  232            table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
 
  236        auto pipeName = getBlockNamePrefix(tableBlock);
 
  237        auto *pre = table->mutable_preamble();
 
  238        if (pre->name() == tableDeclaration->controlPlaneName())
 
  239            pre->set_name(prefix(pipeName, pre->name()));
 
  242    void addExternInstance(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
 
  243                           const IR::ExternBlock *externBlock)
 override {
 
  244        P4RuntimeArchHandlerCommon<arch>::addExternInstance(symbols, p4info, externBlock);
 
  246        auto decl = externBlock->node->to<IR::Declaration_Instance>();
 
  247        if (decl == 
nullptr) 
return;
 
  251        cstring pipeName = getBlockNamePrefix(externBlock);
 
  253        auto p4RtTypeInfo = p4info->mutable_type_info();
 
  254        if (externBlock->type->name == 
"Digest") {
 
  255            auto digest = 
getDigest(decl, p4RtTypeInfo);
 
  256            if (digest) this->addDigest(symbols, p4info, *digest);
 
  257        } 
else if (externBlock->type->name == 
"ActionSelector") {
 
  258            auto actionSelector = getActionSelector(externBlock);
 
  259            if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
 
  260            for (
auto &extType : *p4info->mutable_action_profiles()) {
 
  261                auto *pre = extType.mutable_preamble();
 
  262                if (pre->name() == decl->controlPlaneName()) {
 
  263                    pre->set_name(prefix(pipeName, pre->name()));
 
  267        } 
else if (externBlock->type->name == 
"ActionProfile") {
 
  268            for (
auto &extType : *p4info->mutable_action_profiles()) {
 
  269                auto *pre = extType.mutable_preamble();
 
  270                if (pre->name() == decl->controlPlaneName()) {
 
  271                    pre->set_name(prefix(pipeName, pre->name()));
 
  275        } 
else if (externBlock->type->name == 
"Meter") {
 
  276            for (
auto &extType : *p4info->mutable_meters()) {
 
  277                auto *pre = extType.mutable_preamble();
 
  278                if (pre->name() == decl->controlPlaneName()) {
 
  279                    pre->set_name(prefix(pipeName, pre->name()));
 
  283        } 
else if (externBlock->type->name == 
"Counter") {
 
  284            for (
auto &extType : *p4info->mutable_counters()) {
 
  285                auto *pre = extType.mutable_preamble();
 
  286                if (pre->name() == decl->controlPlaneName()) {
 
  287                    pre->set_name(prefix(pipeName, pre->name()));
 
  291        } 
else if (externBlock->type->name == 
"Register") {
 
  292            for (
auto &extType : *p4info->mutable_registers()) {
 
  293                auto *pre = extType.mutable_preamble();
 
  294                if (pre->name() == decl->controlPlaneName()) {
 
  295                    pre->set_name(prefix(pipeName, pre->name()));
 
  303    std::optional<Digest> 
getDigest(
const IR::Declaration_Instance *decl,
 
  304                                    p4configv1::P4TypeInfo *p4RtTypeInfo) {
 
  305        BUG_CHECK(decl->type->is<IR::Type_Specialized>(), 
"%1%: expected Type_Specialized",
 
  307        auto type = decl->type->to<IR::Type_Specialized>();
 
  308        BUG_CHECK(type->arguments->size() == 1, 
"%1%: expected one type argument", decl);
 
  309        auto typeArg = type->arguments->at(0);
 
  312        BUG_CHECK(typeSpec != 
nullptr,
 
  313                  "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
 
  315        return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
 
 
  321        auto timeout = table->properties->getProperty(
"psa_idle_timeout");
 
  323        if (timeout == 
nullptr) 
return false;
 
  325        if (
auto exprValue = timeout->value->to<IR::ExpressionValue>()) {
 
  326            if (
auto expr = exprValue->expression) {
 
  327                if (
auto member = expr->to<IR::Member>()) {
 
  328                    if (member->member == 
"NOTIFY_CONTROL") {
 
  330                    } 
else if (member->member == 
"NO_TIMEOUT") {
 
  333                } 
else if (expr->is<IR::PathExpression>()) {
 
  334                    ::error(ErrorType::ERR_UNEXPECTED,
 
  335                            "Unresolved value %1% for psa_idle_timeout " 
  336                            "property on table %2%. Must be a constant and one of " 
  337                            "{ NOTIFY_CONTROL, NO_TIMEOUT }",
 
  344        ::error(ErrorType::ERR_UNEXPECTED,
 
  345                "Unexpected value %1% for psa_idle_timeout " 
  346                "property on table %2%. Supported values are " 
  347                "{ NOTIFY_CONTROL, NO_TIMEOUT }",