677 const IR::ToplevelBlock *evaluatedProgram)
678 : refMap(refMap), typeMap(typeMap), evaluatedProgram(evaluatedProgram) {}
690 auto declName = decl ? decl->controlPlaneName() :
""_cs;
691 return getFullyQualifiedName(block, declName);
709 cstring getFullyQualifiedName(
const IR::Block *block,
const cstring name,
710 bool skip_control_plane_name =
false) {
712 cstring control_plane_name =
""_cs;
713 cstring full_name = getBlockNamePrefix(block);
714 if (!skip_control_plane_name) {
715 if (
auto cont = block->getContainer()) {
716 block_name = cont->getName();
717 control_plane_name = cont->controlPlaneName();
718 full_name = prefix(full_name, control_plane_name);
722 if (!name.isNullOrEmpty()) full_name = prefix(full_name, name);
723 LOG5(
"Block : " << block <<
", block_name: " << block_name
724 <<
", block_name_prefix: " << getBlockNamePrefix(block)
725 <<
", control_plane_name: " << control_plane_name <<
", name: " << name
726 <<
", fqname: " << full_name);
730 virtual cstring getBlockNamePrefix(
const IR::Block *) {
return defaultPipeName; }
733 const IR::TableBlock *tableBlock)
override {
734 CHECK_NULL(tableBlock);
735 bool isConstructedInPlace =
false;
743 auto table = tableBlock->container;
744 LOG2(
"Collecting Table Properties on block " << table->name);
746 table, implementationString,
"ActionProfile"_cs, refMap, typeMap,
747 &isConstructedInPlace);
748 if (action_profile) {
749 cstring tableName = *action_profile->name;
750 tableName = prefix(getBlockNamePrefix(tableBlock), tableName);
751 if (isConstructedInPlace)
752 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), tableName);
755 table, implementationString,
"ActionSelector"_cs, refMap, typeMap,
756 &isConstructedInPlace);
757 if (action_selector) {
758 cstring tableName = *action_selector->name;
759 tableName = prefix(getBlockNamePrefix(tableBlock), tableName);
760 if (action_selector->substitution.lookupByName(
"size"_cs)) {
761 std::string selectorName(tableName +
"_sel");
762 symbols->
add(SymbolType::P4RT_ACTION_SELECTOR(), selectorName);
763 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), tableName);
765 symbols->
add(SymbolType::P4RT_ACTION_SELECTOR(), tableName);
775 const IR::ExternBlock *externBlock) {
776 CHECK_NULL(externBlock);
782 if (decl ==
nullptr)
return;
785 if (externBlock->type->name ==
"Counter") {
786 symbols->
add(SymbolType::P4RT_COUNTER(), symName);
787 }
else if (externBlock->type->name ==
"DirectCounter") {
788 symbols->
add(SymbolType::P4RT_DIRECT_COUNTER(), symName);
789 }
else if (externBlock->type->name ==
"Meter") {
790 symbols->
add(SymbolType::P4RT_METER(), symName);
791 }
else if (externBlock->type->name ==
"DirectMeter") {
792 symbols->
add(SymbolType::P4RT_DIRECT_METER(), symName);
793 }
else if (externBlock->type->name ==
"ActionProfile") {
794 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), symName);
795 }
else if (externBlock->type->name ==
"ActionSelector") {
796 if (externBlock->findParameterValue(
"size"_cs)) {
797 std::string selectorName(symName +
"_sel");
798 symbols->
add(SymbolType::P4RT_ACTION_SELECTOR(), selectorName);
799 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), symName);
801 symbols->
add(SymbolType::P4RT_ACTION_SELECTOR(), symName);
803 }
else if (externBlock->type->name ==
"Digest") {
804 symbols->
add(SymbolType::P4RT_DIGEST(), symName);
805 }
else if (externBlock->type->name ==
"Register") {
806 symbols->
add(SymbolType::P4RT_REGISTER(), symName);
807 }
else if (externBlock->type->name ==
"DirectRegister") {
808 symbols->
add(SymbolType::P4RT_DIRECT_REGISTER(), symName);
809 }
else if (externBlock->type->name ==
"Hash") {
810 symbols->
add(SymbolType::P4RT_HASH(), symName);
815 const IR::AssignmentStatement *)
override {}
822 const IR::ParserBlock *parserBlock) {
823 CHECK_NULL(parserBlock);
824 auto parser = parserBlock->container;
829 for (
auto s : parser->parserLocals) {
830 if (
auto inst = s->to<IR::P4ValueSet>()) {
831 symbols->
add(SymbolType::P4RT_VALUE_SET(), inst->controlPlaneName());
842 if (!block->is<IR::ParserBlock>())
return;
843 collectParserSymbols(symbols, block->to<IR::ParserBlock>());
848 p4configv1::P4Info *p4info, p4configv1::Table *table,
849 const IR::TableBlock *tableBlock,
cstring blockPrefix =
"") {
850 CHECK_NULL(tableBlock);
851 auto tableDeclaration = tableBlock->container;
855 auto p4RtTypeInfo = p4info->mutable_type_info();
863 auto directRegister =
getDirectRegister(tableDeclaration, refMap, typeMap, p4RtTypeInfo);
867 auto id = actionProfile->getId(symbols, blockPrefix);
868 table->set_implementation_id(
id);
869 if (isExternPropertyConstructedInPlace(tableDeclaration, implementationString)) {
870 addActionProfile(symbols, p4info, *actionProfile, blockPrefix);
874 if (actionSelector) {
875 auto id = actionSelector->getId(symbols, blockPrefix);
876 table->set_implementation_id(
id);
878 addActionSelector(symbols, p4info, *actionSelector, blockPrefix);
888 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_COUNTER(),
889 prefix(blockPrefix, directCounter->name));
890 table->add_direct_resource_ids(
id);
891 addCounter(symbols, p4info, *directCounter, blockPrefix);
895 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_METER(),
896 prefix(blockPrefix, directMeter->name));
897 table->add_direct_resource_ids(
id);
898 addMeter(symbols, p4info, *directMeter, blockPrefix);
901 if (directRegister) {
902 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_REGISTER(),
903 prefix(blockPrefix, directRegister->name));
904 table->add_direct_resource_ids(
id);
905 addRegister(symbols, p4info, *directRegister, blockPrefix);
910 if (supportsTimeout) {
911 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
913 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
920 auto timeout = table->properties->getProperty(
"idle_timeout"_cs);
921 if (timeout ==
nullptr)
return false;
922 if (!timeout->value->is<IR::ExpressionValue>()) {
923 error(
"Unexpected value %1% for idle_timeout on table %2%", timeout, table);
927 auto expr = timeout->value->to<IR::ExpressionValue>()->expression;
928 if (!expr->is<IR::BoolLiteral>()) {
930 "Unexpected non-boolean value %1% for idle_timeout "
931 "property on table %2%",
936 return expr->to<IR::BoolLiteral>()->value;
943 p4configv1::P4TypeInfo *p4RtTypeInfo) {
944 auto directRegisterInstance =
946 if (!directRegisterInstance)
return std::nullopt;
951 const IR::ExternBlock *)
override {}
954 p4configv1::P4Info *p4info,
const IR::ExternBlock *externBlock,
956 Log::TempIndent indent;
957 LOG1(
"Adding Extern Instances for pipe " << pipeName << indent);
958 auto decl = externBlock->node->
to<IR::Declaration_Instance>();
961 if (decl ==
nullptr)
return;
965 auto p4RtTypeInfo = p4info->mutable_type_info();
967 if (externBlock->type->name ==
"ActionProfile") {
969 if (actionProfile) addActionProfile(symbols, p4info, *actionProfile, pipeName);
970 }
else if (externBlock->type->name ==
"ActionSelector") {
972 if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
973 }
else if (externBlock->type->name ==
"Counter") {
975 Counterlike<ArchCounterExtern>::from(externBlock, refMap, typeMap, p4RtTypeInfo);
976 if (counter) addCounter(symbols, p4info, *counter, pipeName);
977 }
else if (externBlock->type->name ==
"Meter") {
979 Counterlike<ArchMeterExtern>::from(externBlock, refMap, typeMap, p4RtTypeInfo);
980 if (meter) addMeter(symbols, p4info, *meter, pipeName);
981 }
else if (externBlock->type->name ==
"Digest") {
982 auto digest = getDigest(decl, p4RtTypeInfo);
983 if (digest) addDigest(symbols, p4info, *digest, pipeName);
984 }
else if (externBlock->type->name ==
"Register") {
985 auto register_ =
Register::from(externBlock, refMap, typeMap, p4RtTypeInfo);
986 if (register_) addRegister(symbols, p4info, *register_, pipeName);
987 }
else if (externBlock->type->name ==
"Hash") {
988 auto dynHash = getDynHash(decl, p4RtTypeInfo);
989 if (dynHash) addDynHash(symbols, p4info, *dynHash, pipeName);
997 const ValueSet &valueSetInstance) {
998 ::barefoot::ValueSet valueSet;
999 valueSet.set_size(valueSetInstance.size);
1000 valueSet.mutable_type_spec()->CopyFrom(*valueSetInstance.typeSpec);
1001 addP4InfoExternInstance(symbols, SymbolType::P4RT_VALUE_SET(),
"ValueSet"_cs,
1002 valueSetInstance.name, valueSetInstance.annotations, valueSet,
1004 LOG2(
"Added Instance - Value Set " << valueSetInstance.name);
1008 const IR::ParserBlock *parserBlock) {
1009 CHECK_NULL(parserBlock);
1010 auto parser = parserBlock->container;
1013 for (
auto s : parser->parserLocals) {
1014 if (
auto inst = s->to<IR::P4ValueSet>()) {
1015 auto valueSet = ValueSet::from(inst->controlPlaneName(), inst, refMap, typeMap,
1016 p4info->mutable_type_info());
1017 if (valueSet) addValueSet(symbols, p4info, *valueSet);
1023 ::p4::config::v1::P4Info *p4info)
override {
1029 if (!block->is<IR::ParserBlock>())
return;
1030 analyzeParser(symbols, p4info, block->to<IR::ParserBlock>());
1035 const IR::ExternBlock *)
override {}
1039 std::optional<Digest> getDigest(
const IR::Declaration_Instance *decl,
1040 p4configv1::P4TypeInfo *p4RtTypeInfo) {
1041 std::vector<const P4::ExternMethod *> packCalls;
1049 decl, [&](
const P4::ExternMethod *method) { packCalls.push_back(method); });
1050 if (packCalls.size() == 0)
return std::nullopt;
1051 if (packCalls.size() > 1) {
1052 error(
"Expected single call to pack for digest instance '%1%'", decl);
1053 return std::nullopt;
1055 LOG4(
"Found 'pack' method call for digest instance " << decl->controlPlaneName());
1057 BUG_CHECK(decl->type->is<IR::Type_Specialized>(),
"%1%: expected Type_Specialized",
1059 auto type = decl->type->to<IR::Type_Specialized>();
1060 BUG_CHECK(type->arguments->size() == 1,
"%1%: expected one type argument", decl);
1061 auto typeArg = type->arguments->at(0);
1064 BUG_CHECK(typeSpec !=
nullptr,
1065 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
1066 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
1069 std::optional<DynHash> getDynHash(
const IR::Declaration_Instance *decl,
1070 p4configv1::P4TypeInfo *p4RtTypeInfo) {
1071 std::vector<const P4::ExternMethod *> hashCalls;
1074 decl, [&](
const P4::ExternMethod *method) { hashCalls.push_back(method); });
1075 if (hashCalls.size() == 0)
return std::nullopt;
1076 if (hashCalls.size() > 1) {
1078 "Expected single call to get for hash instance '%1%'."
1079 "Control plane API is not generated for this hash call",
1081 return std::nullopt;
1083 LOG4(
"Found 'get' method call for hash instance " << decl->controlPlaneName());
1087 if (
auto *call = hashCalls[0]->expr->to<IR::MethodCallExpression>()) {
1089 if (
auto t = call->type->to<IR::Type_Bits>()) {
1090 hashWidth = t->width_bits();
1093 auto fieldListArg = call->arguments->at(0);
1094 LOG4(
"FieldList for Hash: " << fieldListArg);
1096 std::vector<DynHash::hashField> hashFieldInfo;
1097 if (fieldListArg->expression->is<IR::ListExpression>() ||
1098 fieldListArg->expression->is<IR::StructExpression>()) {
1099 for (
auto f : *getListExprComponents(*fieldListArg->expression)) {
1100 if (
auto c = f->to<IR::Concat>()) {
1101 for (
auto e : convertConcatToList(c)) {
1102 hashFieldInfo.push_back({e->toString(), e->is<IR::Constant>()});
1103 typeArgs->push_back(e->type);
1107 hashFieldInfo.push_back({f->toString(), f->is<IR::Constant>()});
1108 auto t = f->type->is<IR::Type_SerEnum>() ? f->type->to<IR::Type_SerEnum>()->type
1110 typeArgs->push_back(t);
1113 auto *typeList =
new IR::Type_List(*typeArgs);
1115 typeList, p4RtTypeInfo);
1116 BUG_CHECK(typeSpec !=
nullptr,
1117 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
1118 return DynHash{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>(),
1119 hashFieldInfo, hashWidth};
1121 return std::nullopt;
1130 if (!instance)
return std::nullopt;
1131 if (instance->type->name !=
"ActionProfile")
return std::nullopt;
1132 auto size = instance->substitution.lookupByName(
"size"_cs)->expression;
1134 BUG_CHECK(size->template is<IR::Constant>(),
"Non-constant size");
1135 return ActionProfile{*instance->name, size->template to<IR::Constant>()->asInt(),
1136 getTableImplementationAnnotations(table, refMap)};
1142 auto size = instance->getParameterValue(
"size"_cs);
1143 BUG_CHECK(size->
is<IR::Constant>(),
"Non-constant size");
1144 return ActionProfile{decl->controlPlaneName(), size->
to<IR::Constant>()->asInt(),
1145 decl->to<IR::IAnnotated>()};
1154 table, implementationString,
"ActionSelector"_cs, refMap, typeMap);
1155 if (!action_selector)
return std::nullopt;
1158 if (action_selector->substitution.lookupByName(
"size"_cs)) {
1159 auto size = action_selector->substitution.lookupByName(
"size"_cs)->expression;
1160 BUG_CHECK(size->template is<IR::Constant>(),
"Non-constant size");
1163 size->template to<IR::Constant>()->asInt(),
1164 defaultMaxGroupSize,
1165 size->template to<IR::Constant>()->asInt(),
1166 getTableImplementationAnnotations(table, refMap),
1170 action_selector->substitution.lookupByName(
"max_group_size"_cs)->expression;
1171 auto numGroups = action_selector->substitution.lookupByName(
"num_groups"_cs)->expression;
1173 BUG_CHECK(maxGroupSize->template is<IR::Constant>(),
"Non-constant max group size");
1174 BUG_CHECK(numGroups->template is<IR::Constant>(),
"Non-constant num groups");
1176 *action_selector->name,
1178 maxGroupSize->template to<IR::Constant>()->asInt(),
1179 numGroups->template to<IR::Constant>()->asInt(),
1180 getTableImplementationAnnotations(table, refMap),
1184 std::optional<ActionSelector>
getActionSelector(
const IR::ExternBlock *instance) {
1187 if (instance->findParameterValue(
"size"_cs)) {
1188 auto size = instance->getParameterValue(
"size"_cs);
1189 BUG_CHECK(size->is<IR::Constant>(),
"Non-constant size");
1192 size->to<IR::Constant>()->asInt(),
1193 defaultMaxGroupSize,
1194 size->to<IR::Constant>()->asInt(),
1195 actionSelDecl->to<IR::IAnnotated>(),
1198 auto maxGroupSize = instance->getParameterValue(
"max_group_size"_cs);
1199 auto numGroups = instance->getParameterValue(
"num_groups"_cs);
1200 BUG_CHECK(maxGroupSize->is<IR::Constant>(),
"Non-constant max group size");
1201 BUG_CHECK(numGroups->is<IR::Constant>(),
"Non-constant num groups");
1202 auto action_profile = instance->getParameterValue(
"action_profile"_cs);
1203 auto action_profile_decl =
1205 return ActionSelector{actionSelDecl->controlPlaneName(),
1206 cstring::to_cstring(action_profile_decl->controlPlaneName()),
1208 maxGroupSize->to<IR::Constant>()->asInt(),
1209 numGroups->to<IR::Constant>()->asInt(),
1210 actionSelDecl->to<IR::IAnnotated>(),
1215 cstring typeName, p4configv1::P4Info *p4info) {
1216 for (
auto &externType : *p4info->mutable_externs()) {
1217 if (externType.extern_type_id() ==
static_cast<p4rt_id_t
>(typeId))
return &externType;
1219 auto *externType = p4info->add_externs();
1220 externType->set_extern_type_id(
static_cast<p4rt_id_t
>(typeId));
1221 externType->set_extern_type_name(typeName);
1228 const IR::IAnnotated *annotations,
1229 const ::google::protobuf::Message &message,
1230 p4configv1::P4Info *p4info) {
1231 auto *externType = getP4InfoExtern(typeId, typeName, p4info);
1232 auto *externInstance = externType->add_instances();
1233 auto *pre = externInstance->mutable_preamble();
1234 pre->set_id(symbols.
getId(typeId, name));
1235 pre->set_name(name);
1236 pre->set_alias(symbols.
getAlias(name));
1237 Helpers::addAnnotations(pre, annotations);
1239 externInstance->mutable_info()->PackFrom(message);
1243 const Digest &digestInstance,
cstring pipeName =
"") {
1244 ::barefoot::Digest digest;
1245 digest.mutable_type_spec()->CopyFrom(*digestInstance.typeSpec);
1246 auto digestName = prefix(pipeName, digestInstance.name);
1247 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIGEST(),
"Digest"_cs, digestName,
1248 digestInstance.annotations, digest, p4Info);
1249 LOG2(
"Added Instance - Digest " << digestName);
1253 const DynHash &dynHashInstance,
cstring pipeName =
"") {
1254 ::barefoot::DynHash dynHash;
1255 dynHash.set_hash_width(dynHashInstance.hashWidth);
1256 dynHash.mutable_type_spec()->CopyFrom(*dynHashInstance.typeSpec);
1257 auto dynHashName = prefix(pipeName, dynHashInstance.name);
1258 for (
const auto &f : dynHashInstance.hashFieldInfo) {
1259 auto newF = dynHash.add_field_infos();
1260 newF->set_field_name(f.hashFieldName);
1261 newF->set_is_constant(f.isConstant);
1263 addP4InfoExternInstance(symbols, SymbolType::P4RT_HASH(),
"DynHash"_cs, dynHashName,
1264 dynHashInstance.annotations, dynHash, p4Info);
1265 LOG2(
"Added Instance - DynHash " << dynHashName);
1271 const Register ®isterInstance,
cstring pipeName =
"") {
1272 auto registerName = prefix(pipeName, registerInstance.name);
1273 if (registerInstance.size == 0) {
1274 ::barefoot::DirectRegister register_;
1275 register_.mutable_type_spec()->CopyFrom(*registerInstance.typeSpec);
1276 register_.set_data_field_name(registerInstance.name);
1277 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_REGISTER(),
1278 "DirectRegister"_cs, registerName, registerInstance.annotations,
1280 LOG2(
"Added Instance - DirectRegister " << registerName);
1282 ::barefoot::Register register_;
1283 register_.set_size(registerInstance.size);
1284 register_.mutable_type_spec()->CopyFrom(*registerInstance.typeSpec);
1285 register_.set_data_field_name(registerInstance.name);
1286 addP4InfoExternInstance(symbols, SymbolType::P4RT_REGISTER(),
"Register"_cs,
1287 registerName, registerInstance.annotations, register_, p4Info);
1288 LOG2(
"Added Instance - Register " << registerName);
1293 template <
typename Kind>
1296 auto counter_spec = counter->mutable_spec();
1297 counter_spec->set_unit(CounterTraits::mapUnitName(counterInstance.
unit));
1302 const cstring blockPrefix =
"") {
1303 if (counterInstance.
table) {
1304 ::barefoot::DirectCounter counter;
1306 auto tableName = prefix(blockPrefix, *counterInstance.
table);
1307 auto counterName = prefix(blockPrefix, counterInstance.
name);
1309 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
1310 counter.set_direct_table_id(tableId);
1311 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_COUNTER(),
1313 counterName, counterInstance.
annotations, counter, p4Info);
1314 LOG2(
"Added Instance - DirectCounter " << counterName);
1316 ::barefoot::Counter counter;
1318 counter.set_size(counterInstance.
size);
1319 auto counterName = prefix(blockPrefix, counterInstance.
name);
1320 addP4InfoExternInstance(symbols, SymbolType::P4RT_COUNTER(),
1322 counterName, counterInstance.
annotations, counter, p4Info);
1323 LOG2(
"Added Instance - Counter " << counterName);
1328 template <
typename Kind>
1330 using ::barefoot::MeterSpec;
1332 auto meter_spec = meter->mutable_spec();
1334 meter_spec->set_type(MeterSpec::COLOR_AWARE);
1336 meter_spec->set_type(MeterSpec::COLOR_UNAWARE);
1338 meter_spec->set_unit(CounterlikeTraits<ArchMeterExtern>::mapUnitName(meterInstance.
unit));
1343 const cstring blockPrefix =
"") {
1344 auto meterName = prefix(blockPrefix, meterInstance.
name);
1345 if (meterInstance.
table) {
1346 ::barefoot::DirectMeter meter;
1348 auto tableName = prefix(blockPrefix, *meterInstance.
table);
1350 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
1351 meter.set_direct_table_id(tableId);
1352 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_METER(),
1354 meterName, meterInstance.
annotations, meter, p4Info);
1355 LOG2(
"Added Instance - DirectMeter " << meterName);
1357 ::barefoot::Meter meter;
1359 meter.set_size(meterInstance.
size);
1360 addP4InfoExternInstance(symbols, SymbolType::P4RT_METER(),
1362 meterName, meterInstance.
annotations, meter, p4Info);
1363 LOG2(
"Added Instance - Meter " << meterName);
1368 const ActionProfile &actionProfile,
cstring pipeName =
"") {
1369 ::barefoot::ActionProfile profile;
1370 profile.set_size(actionProfile.size);
1371 auto actionProfileName = prefix(pipeName, actionProfile.name);
1374 for (
const auto &table : tablesIt->second) {
1376 if (!pipeName.isNullOrEmpty()) tableName = prefix(pipeName, tableName);
1377 profile.add_table_ids(symbols.
getId(
1378 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1381 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_PROFILE(),
"ActionProfile"_cs,
1382 actionProfileName, actionProfile.annotations, profile, p4Info);
1383 LOG2(
"Added Extern Instance - Action Profile " << actionProfileName);
1387 p4configv1::P4Info *p4Info,
const ActionSelector &actionSelector,
1389 ::barefoot::ActionSelector selector;
1390 selector.set_max_group_size(actionSelector.maxGroupSize);
1391 selector.set_num_groups(actionSelector.numGroups);
1392 cstring actionSelectorName = prefix(blockPrefix, actionSelector.name);
1393 if (actionSelector.actionProfileName) {
1394 selector.set_action_profile_id(
1395 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(),
1396 prefix(blockPrefix, *actionSelector.actionProfileName)));
1399 for (
const auto &table : tablesIt->second) {
1400 cstring tableName = prefix(blockPrefix, table);
1401 selector.add_table_ids(symbols.
getId(
1402 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1405 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_SELECTOR(),
1406 "ActionSelector"_cs, actionSelectorName,
1407 actionSelector.annotations, selector, p4Info);
1408 LOG2(
"Added Extern Instance - Action Selector " << actionSelectorName);
1410 ::barefoot::ActionProfile profile;
1411 profile.set_size(actionSelector.size);
1414 for (
const auto &table : tablesIt->second) {
1415 cstring tableName = prefix(blockPrefix, table);
1416 profile.add_table_ids(symbols.
getId(
1417 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1418 selector.add_table_ids(symbols.
getId(
1419 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1425 cstring profileName = actionSelectorName;
1426 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_PROFILE(),
"ActionProfile"_cs,
1427 profileName, actionSelector.annotations, profile, p4Info);
1428 selector.set_action_profile_id(
1429 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
1430 cstring selectorName = profileName +
"_sel";
1431 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_SELECTOR(),
1432 "ActionSelector"_cs, selectorName, actionSelector.annotations,
1434 LOG2(
"Added Extern Instance - Action Selector " << selectorName);
1442 template <
typename Func>
1445 evaluatedProgram->getProgram(), [&](
const IR::MethodCallExpression *call) {
1446 auto instance = P4::MethodInstance::resolve(call, refMap, typeMap);
1447 if (instance->is<P4::ExternMethod>() && instance->object == object) {
1448 function(instance->to<P4::ExternMethod>());
1456 return table->properties->getProperty(implementationString);
1459 const IR::IAnnotated *getTableImplementationAnnotations(
const IR::P4Table *table,
1461 auto impl = getTableImplementationProperty(table);
1462 if (impl ==
nullptr)
return nullptr;
1463 if (!impl->value->template is<IR::ExpressionValue>())
return nullptr;
1464 auto expr = impl->value->template to<IR::ExpressionValue>()->expression;
1465 if (expr->template is<IR::ConstructorCallExpression>())
1466 return impl->template to<IR::IAnnotated>();
1467 if (expr->template is<IR::PathExpression>()) {
1468 auto decl = refMap->
getDeclaration(expr->template to<IR::PathExpression>()->path,
true);
1469 return decl->template to<IR::IAnnotated>();
1474 std::optional<cstring> getTableImplementationName(
const IR::P4Table *table,
1476 auto impl = getTableImplementationProperty(table);
1477 if (impl ==
nullptr)
return std::nullopt;
1478 if (!impl->value->template is<IR::ExpressionValue>()) {
1479 error(
"Expected %1% property value for table %2% to be an expression: %2%",
1480 implementationString, table->controlPlaneName(), impl);
1481 return std::nullopt;
1483 auto expr = impl->value->template to<IR::ExpressionValue>()->expression;
1484 if (expr->template is<IR::ConstructorCallExpression>())
return impl->controlPlaneName();
1485 if (expr->template is<IR::PathExpression>()) {
1486 auto decl = refMap->
getDeclaration(expr->template to<IR::PathExpression>()->path,
true);
1487 return decl->controlPlaneName();
1489 return std::nullopt;
1494 const IR::ToplevelBlock *evaluatedProgram;
1502 cstring defaultPipeName =
"pipe"_cs;
1504 static constexpr int64_t defaultMaxGroupSize = 120;
1507 google::protobuf::util::JsonPrintOptions jsonPrintOptions;
1511 return jsonPrintOptions;
1520 template <
typename Func>
1521 void forAllPipeBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
1522 auto main = evaluatedProgram->getMain();
1523 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1524 auto cparams = main->getConstructorParameters();
1526 for (
auto param : main->constantValue) {
1528 if (!param.second)
continue;
1529 auto pipe = param.second;
1530 if (!pipe->is<IR::PackageBlock>()) {
1531 error(ErrorType::ERR_INVALID,
1532 "%1% package block. You are compiling for the %2% "
1533 "P4 architecture.\n"
1534 "Please verify that you included the correct architecture file.",
1535 pipe, BackendOptions().arch);
1538 auto idxParam = cparams->getParameter(index);
1539 auto pipeName = idxParam->name;
1540 function(pipeName, pipe->to<IR::PackageBlock>());
1544 template <
typename Func>
1545 void forAllPortMetadataBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
1546 auto main = evaluatedProgram->getMain();
1547 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1548 if (main->type->name ==
"MultiParserSwitch") {
1549 int numParsersPerPipe = Device::numParsersPerPipe();
1550 auto parsersName =
"ig_prsr"_cs;
1551 forAllPipeBlocks(evaluatedProgram, [&](
cstring,
const IR::PackageBlock *pkg) {
1552 auto parsers = pkg->findParameterValue(parsersName);
1553 BUG_CHECK(parsers,
"Expected Block");
1554 if (!parsers->is<IR::PackageBlock>()) {
1555 error(ErrorType::ERR_INVALID,
1556 "%1% package block. "
1557 "You are compiling for the %2% P4 architecture.\n"
1558 "Please verify that you included the correct architecture file.",
1559 parsers, BackendOptions().arch);
1562 auto parsersBlock = parsers->to<IR::PackageBlock>();
1563 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1564 auto mpParserName =
"prsr" + std::to_string(idx);
1565 auto parser = parsersBlock->findParameterValue(mpParserName);
1567 auto parserBlock = parser->to<IR::ParserBlock>();
1568 if (hasUserPortMetadata.count(parserBlock) == 0) {
1569 auto portMetadataFullName =
1570 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
1571 function(portMetadataFullName, parserBlock);
1576 auto parserName =
"ingress_parser"_cs;
1577 forAllPipeBlocks(evaluatedProgram, [&](
cstring,
const IR::PackageBlock *pkg) {
1578 auto *block = pkg->findParameterValue(parserName);
1580 if (!block->is<IR::ParserBlock>())
return;
1581 auto parserBlock = block->to<IR::ParserBlock>();
1582 if (hasUserPortMetadata.count(parserBlock) == 0) {
1583 auto portMetadataFullName =
1584 getFullyQualifiedName(parserBlock, PortMetadata::name());
1585 function(portMetadataFullName, parserBlock);
1592 const IR::ToplevelBlock *evaluatedProgram)
1594 Log::TempIndent indent;
1595 LOG1(
"BFRuntimeArchHandlerTofino" << indent);
1596 implementationString =
"implementation"_cs;
1598 std::set<cstring> pipes;
1599 LOG2(
"Populating blockNamePrefixMap" << Log::indent);
1605 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1607 auto decl = pkg->node->to<IR::Declaration_Instance>();
1608 cstring blockNamePrefix = pipeName;
1609 if (decl) blockNamePrefix = decl->controlPlaneName();
1610 blockNamePrefixMap[block] = blockNamePrefix;
1611 LOG4(
"Updating blockNamePrefixMap with " << &*block << block->toString() <<
" : "
1612 << blockNamePrefixMap[block]);
1613 pipes.insert(pipeName);
1619 static std::vector<cstring> gressNames = {
"ig"_cs,
"eg"_cs};
1620 int numParsersPerPipe = Device::numParsersPerPipe();
1622 auto main = evaluatedProgram->getMain();
1623 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1625 isMultiParser =
false;
1626 if (main->type->name ==
"MultiParserSwitch") {
1627 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1629 pkg->type->name ==
"MultiParserPipeline",
1630 "Only MultiParserPipeline pipes can be used with a MultiParserSwitch switch");
1631 for (
auto gressName : gressNames) {
1632 auto parsersName = gressName +
"_prsr";
1633 auto parsers = pkg->findParameterValue(parsersName);
1634 BUG_CHECK(parsers && parsers->is<IR::PackageBlock>(),
"Expected PackageBlock");
1635 auto parsersBlock = parsers->to<IR::PackageBlock>();
1636 auto decl = parsersBlock->node->to<IR::Declaration_Instance>();
1637 if (decl) parsersName = decl->controlPlaneName();
1638 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1639 auto parserName =
"prsr" + std::to_string(idx);
1640 auto parser = parsersBlock->findParameterValue(parserName);
1642 BUG_CHECK(parser->is<IR::ParserBlock>(),
"Expected ParserBlock");
1643 auto parserBlock = parser->to<IR::ParserBlock>();
1646 auto parserFullName = pipeName +
"." + parsersName +
"." + parserName;
1647 blockNamePrefixMap[parserBlock] = parserFullName;
1649 isMultiParser =
true;
1655 cstring getBlockNamePrefix(
const IR::Block *blk)
override {
1656 if (blockNamePrefixMap.count(blk) > 0)
return blockNamePrefixMap[blk];
1661 const IR::ExternBlock *externBlock)
override {
1662 collectExternInstanceCommon(symbols, externBlock);
1664 CHECK_NULL(externBlock);
1670 if (decl ==
nullptr)
return;
1672 auto symName = getControlPlaneName(externBlock, decl);
1673 if (externBlock->type->name ==
"Lpf") {
1674 symbols->
add(SymbolType::P4RT_LPF(), symName);
1675 }
else if (externBlock->type->name ==
"DirectLpf") {
1676 symbols->
add(SymbolType::P4RT_DIRECT_LPF(), symName);
1677 }
else if (externBlock->type->name ==
"Wred") {
1678 symbols->
add(SymbolType::P4RT_WRED(), symName);
1679 }
else if (externBlock->type->name ==
"DirectWred") {
1680 symbols->
add(SymbolType::P4RT_DIRECT_WRED(), symName);
1681 }
else if (externBlock->type->name ==
"RegisterParam") {
1682 symbols->
add(SymbolType::P4RT_REGISTER_PARAM(), symName);
1690 const IR::ParserBlock *parserBlock) {
1691 auto portMetadata = getPortMetadataExtract(externFunction, refMap, typeMap,
nullptr);
1693 if (hasUserPortMetadata.count(parserBlock)) {
1694 error(
"Cannot have multiple extern calls for %1%",
1695 BFN::ExternPortMetadataUnpackString);
1698 hasUserPortMetadata.insert(parserBlock);
1699 auto portMetadataFullName =
1700 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
1701 symbols->
add(SymbolType::P4RT_PORT_METADATA(), portMetadataFullName);
1706 const IR::ParserBlock *parserBlock) {
1707 CHECK_NULL(parserBlock);
1708 auto parser = parserBlock->container;
1712 for (
auto state : parser->states) {
1714 state, [&](
const IR::MethodCallExpression *call) {
1717 collectPortMetadataExternFunction(
1722 for (
auto s : parser->parserLocals) {
1723 if (
auto inst = s->to<IR::P4ValueSet>()) {
1724 auto name = getFullyQualifiedName(parserBlock, inst->controlPlaneName(),
true);
1725 symbols->
add(SymbolType::P4RT_VALUE_SET(), name);
1734 auto *params = parser->getApplyParameters();
1735 for (
auto p : *params) {
1736 if (p->type->toString() ==
"ingress_intrinsic_metadata_t") {
1738 ingressIntrinsicMdParamName.count(parserBlock) == 0 ||
1739 strcmp(ingressIntrinsicMdParamName[parserBlock], p->name.toString()) == 0,
1740 "%1%: Multiple names of intrinsic metadata found in this parser block",
1742 ingressIntrinsicMdParamName[parserBlock] = p->name;
1766 static std::vector<cstring> gressNames = {
"ingress"_cs,
"egress"_cs};
1767 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1768 for (
auto gressName : gressNames) {
1769 auto gress = pkg->findParameterValue(gressName);
1770 BUG_CHECK(gress->is<IR::ControlBlock>(),
"Expected control");
1771 auto control = gress->to<IR::ControlBlock>();
1772 if (blockNamePrefixMap.count(control) > 0) pipeName = blockNamePrefixMap[control];
1773 snapshotInfo.emplace(control,
SnapshotInfo{pipeName, gressName, 0u,
""_cs, {}});
1774 LOG3(
"Adding SnapshotInfo for " << control->getName() <<
" " << gressName
1775 <<
" on pipe " << pipeName);
1788 CHECK_NULL(controlBlock);
1789 auto control = controlBlock->container;
1790 CHECK_NULL(control);
1791 Log::TempIndent indent;
1792 auto sinfoIt = snapshotInfo.find(controlBlock);
1795 if (sinfoIt == snapshotInfo.end())
return;
1796 auto snapshot_name = getFullyQualifiedName(controlBlock, control->externalName());
1797 LOG1(
"Collecting Snapshot for control " << snapshot_name << indent);
1802 if (snapshots.count(snapshot_name)) {
1803 snapshotInfo.erase(sinfoIt);
1806 snapshots.insert(snapshot_name);
1807 sinfoIt->second.name = snapshot_name;
1808 auto snapshotFields = &sinfoIt->second.fields;
1809 auto params = control->getApplyParameters();
1810 for (
size_t idx = 0; idx < params->size(); idx++) {
1811 auto p = params->getParameter(idx);
1814 auto includeValid = (idx == sinfoIt->second.userHdrParamIdx);
1815 SnapshotFieldFinder::find(typeMap, p->type, p->name, includeValid, snapshotFields,
1818 LOG3(
"Adding snaphot to bfrt info for control: " << snapshot_name);
1819 symbols->
add(SymbolType::P4RT_SNAPSHOT(), snapshot_name);
1828 static std::vector<cstring> gressNames = {
"ig"_cs,
"eg"_cs};
1829 int numParsersPerPipe = Device::numParsersPerPipe();
1831 auto main = evaluatedProgram->getMain();
1832 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1833 if (main->type->name !=
"MultiParserSwitch")
return;
1835 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1836 BUG_CHECK(pkg->type->name ==
"MultiParserPipeline",
1837 "Only MultiParserPipeline pipes can be used with a MultiParserSwitch switch");
1838 for (
auto gressName : gressNames) {
1839 ::barefoot::ParserChoices parserChoices;
1841 if (
auto decl = pkg->node->to<IR::Declaration_Instance>()) pipeName = decl->Name();
1843 parserChoices.set_pipe(pipeName);
1844 if (gressName ==
"ig")
1845 parserChoices.set_direction(::barefoot::DIRECTION_INGRESS);
1847 parserChoices.set_direction(::barefoot::DIRECTION_EGRESS);
1849 auto parsersName = gressName +
"_prsr";
1850 auto parsers = pkg->findParameterValue(parsersName);
1851 BUG_CHECK(parsers && parsers->is<IR::PackageBlock>(),
"Expected PackageBlock");
1852 auto parsersBlock = parsers->to<IR::PackageBlock>();
1853 auto decl = parsersBlock->node->to<IR::Declaration_Instance>();
1854 if (decl) parsersName = decl->controlPlaneName();
1855 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1856 auto parserName =
"prsr" + std::to_string(idx);
1857 auto parser = parsersBlock->findParameterValue(parserName);
1859 BUG_CHECK(parser->is<IR::ParserBlock>(),
"Expected ParserBlock");
1860 auto parserBlock = parser->to<IR::ParserBlock>();
1861 auto decl = parserBlock->node->to<IR::Declaration_Instance>();
1862 auto userName = (decl ==
nullptr) ?
"" : decl->controlPlaneName();
1864 auto choice = parserChoices.add_choices();
1865 auto parserFullName = prefix(parsersName, parserName);
1866 parserFullName = prefix(pipeName, parserFullName);
1867 choice->set_arch_name(parserFullName);
1868 choice->set_type_name(parserBlock->getName().name);
1869 choice->set_user_name(userName);
1871 auto parsersFullName = prefix(pipeName, parsersName);
1872 symbols->
add(SymbolType::P4RT_PARSER_CHOICES(), parsersFullName);
1873 parserConfiguration.emplace(parsersFullName, parserChoices);
1879 Log::TempIndent indent;
1880 LOG1(
"BFRuntimeArchHandlerTofino::collectExtra" << indent);
1881 LOG2(
"Collecting Parser Symbols" << Log::indent);
1887 if (!block->is<IR::ParserBlock>())
return;
1888 collectParserSymbols(symbols, block->to<IR::ParserBlock>());
1892 LOG2(
"Collecting Snapshot Fields" << Log::indent);
1895 getSnapshotControls();
1898 if (!block->is<IR::ControlBlock>())
return;
1899 collectSnapshot(symbols, block->to<IR::ControlBlock>(), &snapshotFieldIds);
1903 LOG2(
"Collecting Parser Choices" << Log::indent);
1904 collectParserChoices(symbols);
1907 LOG2(
"Collecting PortMetadata" << Log::indent);
1910 forAllPortMetadataBlocks(
1911 evaluatedProgram, [&](
cstring portMetadataFullName,
const IR::ParserBlock *) {
1912 symbols->
add(SymbolType::P4RT_PORT_METADATA(), portMetadataFullName);
1913 LOG3(
"Adding PortMetadata symbol: " << portMetadataFullName);
1919 Log::TempIndent indent;
1920 LOG1(
"BFRuntimeArchHandlerTofino::postCollect" << indent);
1925 if (!block->is<IR::TableBlock>())
return;
1926 auto table = block->to<IR::TableBlock>()->container;
1927 auto implementation = getTableImplementationName(table, refMap);
1928 if (implementation) {
1929 auto pipeName = blockNamePrefixMap[block];
1930 auto implName = prefix(pipeName, *implementation);
1931 actionProfilesRefs[implName].insert(table->controlPlaneName());
1932 LOG5(
"Adding action profile : " << implName <<
" for table "
1933 << table->controlPlaneName());
1940 if (!block->is<IR::ExternBlock>())
return;
1941 auto selectorExternBlock = block->to<IR::ExternBlock>();
1942 if (selectorExternBlock->type->name !=
"ActionSelector")
return;
1943 auto selectorDecl = selectorExternBlock->node->to<IR::Declaration_Instance>();
1944 CHECK_NULL(selectorDecl);
1945 auto profile = selectorExternBlock->getParameterValue(
"action_profile"_cs);
1947 auto profileExternBlock = profile->to<IR::ExternBlock>();
1948 auto profileDecl = profileExternBlock->node->to<IR::Declaration_Instance>();
1949 CHECK_NULL(profileDecl);
1950 auto pipeName = blockNamePrefixMap[selectorExternBlock];
1951 auto profileDeclName = prefix(pipeName, profileDecl->controlPlaneName());
1952 auto selectorDeclName = prefix(pipeName, selectorDecl->controlPlaneName());
1953 actionProfilesRefs[profileDeclName].insert(
1954 actionProfilesRefs[selectorDeclName].begin(),
1955 actionProfilesRefs[selectorDeclName].end());
1956 LOG5(
"Adding action profile : " << profileDeclName <<
" for tables "
1957 << actionProfilesRefs[profileDeclName]);
1966 if (!block->is<IR::ExternBlock>())
return;
1967 auto externBlock = block->to<IR::ExternBlock>();
1968 if (externBlock->type->name !=
"Meter" && externBlock->type->name !=
"DirectMeter")
1970 auto decl = externBlock->node->to<IR::Declaration_Instance>();
1975 auto call = method->expr;
1976 if (call->arguments->size() == 2) {
1977 LOG3(
"Meter " << decl->controlPlaneName() <<
" is color-aware "
1978 <<
"because of 2-argument call to execute()");
1979 colorAwareMeters.insert(decl->controlPlaneName());
1984 class RegisterParamFinder :
public Inspector {
1987 bool checkExtern(
const IR::Declaration_Instance *decl,
cstring name) {
1988 if (
auto *specialized = decl->type->to<IR::Type_Specialized>())
1989 if (
auto *name_type = specialized->baseType->to<IR::Type_Name>())
1990 return name_type->path->name == name;
1996 bool preorder(
const IR::MethodCallExpression *mce)
override {
1999 if (method->
object ==
nullptr)
2001 auto *reg_param = method->
object->
to<IR::Declaration_Instance>();
2002 if (reg_param ==
nullptr)
2004 if (!checkExtern(reg_param,
"RegisterParam"_cs))
return true;
2006 auto *reg_action = findContext<IR::Declaration_Instance>();
2007 if (reg_action ==
nullptr)
return true;
2008 if (!checkExtern(reg_action,
"DirectRegisterAction"_cs) &&
2009 !checkExtern(reg_action,
"RegisterAction"_cs))
2011 BUG_CHECK(reg_action->arguments->size() > 0,
"%1%: Missing argument", reg_action);
2012 auto *rap = reg_action->arguments->at(0)->expression->to<IR::PathExpression>();
2013 if (rap ==
nullptr)
return true;
2016 if (rap_decl ==
nullptr)
return true;
2017 if (checkExtern(rap_decl,
"Register"_cs))
2018 self.registerParam2register[reg_param->controlPlaneName()] =
2019 rap_decl->controlPlaneName();
2020 if (checkExtern(rap_decl,
"DirectRegister"_cs))
2021 self.registerParam2table[reg_param->controlPlaneName()] =
2022 rap_decl->controlPlaneName();
2025 void postorder(
const IR::P4Table *table)
override {
2027 auto *registers = table->properties->getProperty(
"registers"_cs);
2028 if (registers ==
nullptr)
return;
2029 auto *registers_value = registers->value->to<IR::ExpressionValue>();
2030 CHECK_NULL(registers_value);
2031 auto *registers_path = registers_value->expression->to<IR::PathExpression>();
2032 CHECK_NULL(registers_path);
2033 auto *registers_decl =
getDeclInst(self.refMap, registers_path);
2034 CHECK_NULL(registers_decl);
2036 for (
auto r : self.registerParam2table)
2037 if (r.second == registers_decl->controlPlaneName())
2038 self.registerParam2table[r.first] = table->controlPlaneName();
2042 evaluatedProgram->getProgram()->apply(RegisterParamFinder(*
this));
2046 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
2047 CHECK_NULL(tableBlock);
2048 auto tableDeclaration = tableBlock->container;
2049 auto blockPrefix = blockNamePrefixMap[tableBlock];
2051 addTablePropertiesCommon(symbols, p4info, table, tableBlock, blockPrefix);
2053 auto directLpf = getDirectLpf(tableDeclaration, refMap, typeMap);
2056 symbols.
getId(SymbolType::P4RT_DIRECT_LPF(), prefix(blockPrefix, directLpf->name));
2057 table->add_direct_resource_ids(
id);
2058 addLpf(symbols, p4info, *directLpf, blockPrefix);
2061 auto directWred = getDirectWred(tableDeclaration, refMap, typeMap);
2063 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_WRED(),
2064 prefix(blockPrefix, directWred->name));
2065 table->add_direct_resource_ids(
id);
2066 addWred(symbols, p4info, *directWred, blockPrefix);
2073 template <
typename T>
2076 auto directFilterInstance =
2078 if (!directFilterInstance)
return std::nullopt;
2079 CHECK_NULL(directFilterInstance->type);
2080 if (directFilterInstance->type->name != filterType)
return std::nullopt;
2081 return T::fromDirect(*directFilterInstance, table);
2088 return getDirectFilter<Lpf>(table, refMap, typeMap,
"DirectLpf"_cs);
2095 return getDirectFilter<Wred>(table, refMap, typeMap,
"DirectWred"_cs);
2099 const IR::ExternBlock *externBlock)
override {
2100 auto decl = externBlock->node->to<IR::Declaration_Instance>();
2103 if (decl ==
nullptr)
return;
2108 auto pipeName = blockNamePrefixMap[externBlock];
2110 addExternInstanceCommon(symbols, p4info, externBlock, pipeName);
2112 auto p4RtTypeInfo = p4info->mutable_type_info();
2114 if (externBlock->type->name ==
"Lpf") {
2115 auto lpf = Lpf::from(externBlock);
2116 if (lpf) addLpf(symbols, p4info, *lpf, pipeName);
2117 }
else if (externBlock->type->name ==
"Wred") {
2118 auto wred = Wred::from(externBlock);
2119 if (wred) addWred(symbols, p4info, *wred, pipeName);
2120 }
else if (externBlock->type->name ==
"RegisterParam") {
2121 auto register_param_ = RegisterParam::from(externBlock, refMap, typeMap, p4RtTypeInfo);
2122 if (register_param_) addRegisterParam(symbols, p4info, *register_param_, pipeName);
2130 p4configv1::P4Info *p4info,
2132 const IR::ParserBlock *parserBlock) {
2133 auto p4RtTypeInfo = p4info->mutable_type_info();
2134 auto portMetadata = getPortMetadataExtract(externFunction, refMap, typeMap, p4RtTypeInfo);
2136 if (blockNamePrefixMap.count(parserBlock)) {
2137 auto portMetadataFullName =
2138 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
2139 addPortMetadata(symbols, p4info, *portMetadata, portMetadataFullName, parserBlock);
2145 const IR::ParserBlock *parserBlock) {
2146 CHECK_NULL(parserBlock);
2147 auto parser = parserBlock->container;
2150 for (
auto s : parser->parserLocals) {
2151 if (
auto inst = s->to<IR::P4ValueSet>()) {
2153 getFullyQualifiedName(parserBlock, inst->controlPlaneName(),
true);
2155 ValueSet::from(namePrefix, inst, refMap, typeMap, p4info->mutable_type_info());
2156 if (valueSet) addValueSet(symbols, p4info, *valueSet);
2161 for (
auto state : parser->states) {
2163 state, [&](
const IR::MethodCallExpression *call) {
2166 addPortMetadataExternFunction(
2173 ::p4::config::v1::P4Info *p4info)
override {
2181 p4info->clear_value_sets();
2184 if (!block->is<IR::ParserBlock>())
return;
2185 analyzeParser(symbols, p4info, block->to<IR::ParserBlock>());
2190 forAllPortMetadataBlocks(evaluatedProgram, [&](
cstring portMetadataFullName,
2191 const IR::ParserBlock *parserBlock) {
2192 addPortMetadataDefault(symbols, p4info, portMetadataFullName, parserBlock);
2195 for (
const auto &snapshot : snapshotInfo) addSnapshot(symbols, p4info, snapshot.second);
2197 for (
const auto &parser : parserConfiguration)
2198 addParserChoices(symbols, p4info, parser.first, parser.second);
2205 p4configv1::P4TypeInfo *p4RtTypeInfo) {
2206 if (function->method->name != BFN::ExternPortMetadataUnpackString)
return std::nullopt;
2208 if (
auto *call = function->expr->to<IR::MethodCallExpression>()) {
2209 auto *typeArg = call->typeArguments->at(0);
2211 typeArg, p4RtTypeInfo);
2214 return std::nullopt;
2219 const IR::ParserBlock *parserBlock) {
2220 ::barefoot::PortMetadata portMetadata;
2221 portMetadata.mutable_type_spec()->CopyFrom(*portMetadataExtract.typeSpec);
2222 CHECK_NULL(parserBlock);
2223 auto parser = parserBlock->container;
2225 BUG_CHECK(ingressIntrinsicMdParamName.count(parserBlock),
2226 "%1%: Name of the intrinsic metadata not found for this parser block",
2228 portMetadata.set_key_name(ingressIntrinsicMdParamName[parserBlock]);
2229 addP4InfoExternInstance(symbols, SymbolType::P4RT_PORT_METADATA(),
"PortMetadata"_cs, name,
2230 nullptr, portMetadata, p4Info);
2234 p4configv1::P4Info *p4Info,
const cstring &name,
2235 const IR::ParserBlock *parserBlock) {
2236 ::barefoot::PortMetadata portMetadata;
2237 CHECK_NULL(parserBlock);
2238 auto parser = parserBlock->container;
2241 if (ingressIntrinsicMdParamName.count(parserBlock)) {
2242 portMetadata.set_key_name(ingressIntrinsicMdParamName[parserBlock]);
2245 auto const DP0TKN = BFN::getDefaultPhase0TableKeyName();
2246 portMetadata.set_key_name(DP0TKN);
2249 addP4InfoExternInstance(symbols, SymbolType::P4RT_PORT_METADATA(),
"PortMetadata"_cs, name,
2250 nullptr, portMetadata, p4Info);
2254 const SnapshotInfo &snapshotInstance) {
2255 ::barefoot::Snapshot snapshot;
2256 snapshot.set_pipe(snapshotInstance.pipe);
2257 if (snapshotInstance.gress ==
"ingress")
2258 snapshot.set_direction(::barefoot::DIRECTION_INGRESS);
2259 else if (snapshotInstance.gress ==
"egress")
2260 snapshot.set_direction(::barefoot::DIRECTION_EGRESS);
2262 BUG(
"Invalid gress '%1%'", snapshotInstance.gress);
2263 for (
const auto &f : snapshotInstance.fields) {
2264 auto newF = snapshot.add_fields();
2266 newF->set_name(f.name);
2267 newF->set_bitwidth(f.bitwidth);
2269 addP4InfoExternInstance(symbols, SymbolType::P4RT_SNAPSHOT(),
"Snapshot"_cs,
2270 snapshotInstance.name,
nullptr, snapshot, p4Info);
2274 cstring name, const ::barefoot::ParserChoices &parserChoices) {
2275 addP4InfoExternInstance(symbols, SymbolType::P4RT_PARSER_CHOICES(),
"ParserChoices"_cs,
2276 name,
nullptr, parserChoices, p4Info);
2280 const Lpf &lpfInstance,
const cstring pipeName) {
2281 auto lpfName = prefix(pipeName, lpfInstance.name);
2282 if (lpfInstance.table) {
2283 ::barefoot::DirectLpf lpf;
2284 auto tableName = prefix(pipeName, *lpfInstance.table);
2286 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
2287 lpf.set_direct_table_id(tableId);
2288 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_LPF(),
"DirectLpf"_cs, lpfName,
2289 lpfInstance.annotations, lpf, p4Info);
2290 LOG2(
"Added Instance - Direct LPF " << lpfName);
2292 ::barefoot::Lpf lpf;
2293 lpf.set_size(lpfInstance.size);
2294 addP4InfoExternInstance(symbols, SymbolType::P4RT_LPF(),
"Lpf"_cs, lpfName,
2295 lpfInstance.annotations, lpf, p4Info);
2296 LOG2(
"Added Instance - LPF " << lpfName);
2301 template <
typename Kind>
2303 using ::barefoot::WredSpec;
2304 auto wred_spec = wred->mutable_spec();
2305 wred_spec->set_drop_value(wredInstance.dropValue);
2306 wred_spec->set_no_drop_value(wredInstance.noDropValue);
2310 const Wred &wredInstance,
const cstring pipeName) {
2311 auto wredName = prefix(pipeName, wredInstance.name);
2312 if (wredInstance.
table) {
2313 ::barefoot::DirectWred wred;
2314 setWredCommon(&wred, wredInstance);
2315 auto tableName = prefix(pipeName, *wredInstance.
table);
2317 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
2318 wred.set_direct_table_id(tableId);
2319 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_WRED(),
"DirectWred"_cs,
2320 wredName, wredInstance.annotations, wred, p4Info);
2321 LOG2(
"Added Instance - Direct WRED " << wredName);
2323 ::barefoot::Wred wred;
2324 setWredCommon(&wred, wredInstance);
2325 wred.set_size(wredInstance.size);
2326 addP4InfoExternInstance(symbols, SymbolType::P4RT_WRED(),
"Wred"_cs, wredName,
2327 wredInstance.annotations, wred, p4Info);
2328 LOG2(
"Added Instance - WRED " << wredName);
2335 const RegisterParam ®isterParamInstance,
cstring pipeName =
""_cs) {
2336 p4rt_id_t tableId = 0;
2337 if (registerParam2register.count(registerParamInstance.name) > 0)
2339 symbols.
getId(SymbolType::P4RT_REGISTER(),
2340 prefix(pipeName, registerParam2register[registerParamInstance.name]));
2341 else if (registerParam2table.count(registerParamInstance.name) > 0)
2343 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(),
2344 prefix(pipeName, registerParam2table[registerParamInstance.name]));
2346 ::barefoot::RegisterParam register_param_;
2347 register_param_.mutable_type_spec()->CopyFrom(*registerParamInstance.typeSpec);
2348 register_param_.set_table_id(tableId);
2349 register_param_.set_initial_value(registerParamInstance.initial_value);
2350 register_param_.set_data_field_name(registerParamInstance.name);
2351 auto registerParamName = prefix(pipeName, registerParamInstance.name);
2352 addP4InfoExternInstance(symbols, SymbolType::P4RT_REGISTER_PARAM(),
"RegisterParam"_cs,
2353 registerParamName, registerParamInstance.annotations,
2354 register_param_, p4Info);
2355 LOG2(
"Added Instance - RegisterParam " << registerParamName);
2360 std::unordered_set<cstring> snapshots;
2362 std::unordered_set<const IR::Block *> hasUserPortMetadata;
2366 std::unordered_map<const IR::ParserBlock *, cstring> ingressIntrinsicMdParamName;
2368 using SnapshotInfoMap = std::map<const IR::ControlBlock *, SnapshotInfo>;
2369 SnapshotInfoMap snapshotInfo;
2371 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
2373 std::map<cstring, ::barefoot::ParserChoices> parserConfiguration;
2378 std::unordered_map<cstring, cstring> registerParam2register;
2380 std::unordered_map<cstring, cstring> registerParam2table;