79class BFRuntimeArchHandler :
public P4RuntimeArchHandlerCommon<arch> {
81 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
84 template <
typename Func>
85 void forAllPipeBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
86 auto main = evaluatedProgram->getMain();
88 ::P4::error(ErrorType::ERR_NOT_FOUND,
"Program does not contain a `main` module");
89 auto cparams = main->getConstructorParameters();
91 for (
auto param : main->constantValue) {
93 if (!param.second)
continue;
94 auto pipe = param.second;
95 if (!pipe->is<IR::PackageBlock>())
continue;
96 auto idxParam = cparams->getParameter(index);
97 auto pipeName = idxParam->name;
98 function(pipeName, pipe->to<IR::PackageBlock>());
107 using Counter = p4configv1::Counter;
108 using Meter = p4configv1::Meter;
109 using CounterSpec = p4configv1::CounterSpec;
110 using MeterSpec = p4configv1::MeterSpec;
113 const IR::ToplevelBlock *evaluatedProgram)
114 : P4RuntimeArchHandlerCommon<arch>(refMap, typeMap, evaluatedProgram) {
120 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
122 auto decl = pkg->node->to<IR::Declaration_Instance>();
123 cstring blockNamePrefix = pipeName;
124 if (decl) blockNamePrefix = decl->controlPlaneName();
125 blockNamePrefixMap[block] = blockNamePrefix;
130 cstring getBlockNamePrefix(
const IR::Block *blk) {
131 if (blockNamePrefixMap.count(blk) > 0)
return blockNamePrefixMap[blk];
136 p4configv1::P4Info *p4info) {
137 for (
auto &externType : *p4info->mutable_externs()) {
138 if (externType.extern_type_id() ==
static_cast<p4rt_id_t
>(typeId))
return &externType;
140 auto *externType = p4info->add_externs();
141 externType->set_extern_type_id(
static_cast<p4rt_id_t
>(typeId));
142 externType->set_extern_type_name(typeName);
148 const IR::IAnnotated *annotations,
149 const ::google::protobuf::Message &message,
150 p4configv1::P4Info *p4info,
151 cstring pipeName = cstring::empty) {
152 auto *externType = getP4InfoExtern(typeId, typeName, p4info);
153 auto *externInstance = externType->add_instances();
154 auto *pre = externInstance->mutable_preamble();
155 pre->set_id(symbols.
getId(typeId, name));
156 pre->set_name(prefix(pipeName, name));
157 pre->set_alias(symbols.
getAlias(name));
158 Helpers::addAnnotations(pre, annotations);
160 externInstance->mutable_info()->PackFrom(message);
163 std::optional<ActionSelector> getActionSelector(
const IR::ExternBlock *instance) {
166 auto size = instance->getParameterValue(
"size"_cs);
167 BUG_CHECK(size->
is<IR::Constant>(),
"Non-constant size");
168 return ActionSelector{actionSelDecl->controlPlaneName(), size->
to<IR::Constant>()->asInt(),
169 ActionSelector::defaultMaxGroupSize,
170 size->
to<IR::Constant>()->asInt(),
171 actionSelDecl->to<IR::IAnnotated>()};
176 cstring pipeName = cstring::empty) {
177 ::dpdk::ActionSelector selector;
178 selector.set_max_group_size(actionSelector.maxGroupSize);
179 selector.set_num_groups(actionSelector.numGroups);
180 p4configv1::ActionProfile profile;
181 profile.set_size(actionSelector.size);
182 auto tablesIt = this->actionProfilesRefs.find(actionSelector.name);
183 if (tablesIt != this->actionProfilesRefs.end()) {
184 for (
const auto &table : tablesIt->second) {
185 profile.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
186 selector.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
191 cstring profileName = actionSelector.name;
192 selector.set_action_profile_id(
193 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
194 cstring selectorName = profileName +
"_sel";
195 addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(),
196 "ActionSelector"_cs, selectorName, actionSelector.annotations,
197 selector, p4Info, pipeName);
201 const IR::ExternBlock *externBlock)
override {
205 if (decl ==
nullptr)
return;
206 if (externBlock->type->name ==
"Digest") {
207 symbols->
add(SymbolType::P4RT_DIGEST(), decl);
209 auto selName = decl->controlPlaneName() +
"_sel";
210 auto profName = decl->controlPlaneName();
211 symbols->
add(SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), selName);
212 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), profName);
217 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
218 P4RuntimeArchHandlerCommon<arch>::addTableProperties(symbols, p4info, table, tableBlock);
220 auto tableDeclaration = tableBlock->container;
222 if (supportsTimeout) {
223 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
225 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
229 auto pipeName = getBlockNamePrefix(tableBlock);
230 auto *pre = table->mutable_preamble();
231 if (pre->name() == tableDeclaration->controlPlaneName())
232 pre->set_name(
prefix(pipeName, pre->name()));
236 const IR::ExternBlock *externBlock)
override {
237 P4RuntimeArchHandlerCommon<arch>::addExternInstance(symbols, p4info, externBlock);
239 auto decl = externBlock->node->to<IR::Declaration_Instance>();
240 if (decl ==
nullptr)
return;
244 cstring pipeName = getBlockNamePrefix(externBlock);
246 auto p4RtTypeInfo = p4info->mutable_type_info();
247 if (externBlock->type->name ==
"Digest") {
248 auto digest =
getDigest(decl, p4RtTypeInfo);
249 if (digest) this->addDigest(symbols, p4info, *digest);
250 }
else if (externBlock->type->name ==
"ActionSelector") {
251 auto actionSelector = getActionSelector(externBlock);
252 if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
253 for (
auto &extType : *p4info->mutable_action_profiles()) {
254 auto *pre = extType.mutable_preamble();
255 if (pre->name() == decl->controlPlaneName()) {
256 pre->set_name(prefix(pipeName, pre->name()));
260 }
else if (externBlock->type->name ==
"ActionProfile") {
261 for (
auto &extType : *p4info->mutable_action_profiles()) {
262 auto *pre = extType.mutable_preamble();
263 if (pre->name() == decl->controlPlaneName()) {
264 pre->set_name(prefix(pipeName, pre->name()));
268 }
else if (externBlock->type->name ==
"Meter") {
269 for (
auto &extType : *p4info->mutable_meters()) {
270 auto *pre = extType.mutable_preamble();
271 if (pre->name() == decl->controlPlaneName()) {
272 pre->set_name(prefix(pipeName, pre->name()));
276 }
else if (externBlock->type->name ==
"Counter") {
277 for (
auto &extType : *p4info->mutable_counters()) {
278 auto *pre = extType.mutable_preamble();
279 if (pre->name() == decl->controlPlaneName()) {
280 pre->set_name(prefix(pipeName, pre->name()));
284 }
else if (externBlock->type->name ==
"Register") {
285 for (
auto &extType : *p4info->mutable_registers()) {
286 auto *pre = extType.mutable_preamble();
287 if (pre->name() == decl->controlPlaneName()) {
288 pre->set_name(prefix(pipeName, pre->name()));
296 std::optional<Digest>
getDigest(
const IR::Declaration_Instance *decl,
297 p4configv1::P4TypeInfo *p4RtTypeInfo) {
298 BUG_CHECK(decl->type->is<IR::Type_Specialized>(),
"%1%: expected Type_Specialized",
300 auto type = decl->type->to<IR::Type_Specialized>();
301 BUG_CHECK(type->arguments->size() == 1,
"%1%: expected one type argument", decl);
302 auto typeArg = type->arguments->at(0);
305 BUG_CHECK(typeSpec !=
nullptr,
306 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
308 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
314 auto timeout = table->properties->getProperty(
"psa_idle_timeout");
316 if (timeout ==
nullptr)
return false;
318 if (
auto exprValue = timeout->value->to<IR::ExpressionValue>()) {
319 if (
auto expr = exprValue->expression) {
320 if (
auto member = expr->to<IR::Member>()) {
321 if (member->member ==
"NOTIFY_CONTROL") {
323 }
else if (member->member ==
"NO_TIMEOUT") {
326 }
else if (expr->is<IR::PathExpression>()) {
328 "Unresolved value %1% for psa_idle_timeout "
329 "property on table %2%. Must be a constant and one of "
330 "{ NOTIFY_CONTROL, NO_TIMEOUT }",
338 "Unexpected value %1% for psa_idle_timeout "
339 "property on table %2%. Supported values are "
340 "{ NOTIFY_CONTROL, NO_TIMEOUT }",