677 const IR::ToplevelBlock *evaluatedProgram)
678 : refMap(refMap), typeMap(typeMap), evaluatedProgram(evaluatedProgram) {}
690 auto declName = decl ? decl->controlPlaneName() : cstring::empty;
691 return getFullyQualifiedName(block, declName);
709 cstring getFullyQualifiedName(
const IR::Block *block,
const cstring name,
710 bool skip_control_plane_name =
false) {
711 cstring block_name = cstring::empty;
712 cstring control_plane_name = cstring::empty;
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,
850 cstring blockPrefix = cstring::empty) {
851 CHECK_NULL(tableBlock);
852 auto tableDeclaration = tableBlock->container;
856 auto p4RtTypeInfo = p4info->mutable_type_info();
864 auto directRegister =
getDirectRegister(tableDeclaration, refMap, typeMap, p4RtTypeInfo);
868 auto id = actionProfile->getId(symbols, blockPrefix);
869 table->set_implementation_id(
id);
870 if (isExternPropertyConstructedInPlace(tableDeclaration, implementationString)) {
871 addActionProfile(symbols, p4info, *actionProfile, blockPrefix);
875 if (actionSelector) {
876 auto id = actionSelector->getId(symbols, blockPrefix);
877 table->set_implementation_id(
id);
879 addActionSelector(symbols, p4info, *actionSelector, blockPrefix);
889 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_COUNTER(),
890 prefix(blockPrefix, directCounter->name));
891 table->add_direct_resource_ids(
id);
892 addCounter(symbols, p4info, *directCounter, blockPrefix);
896 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_METER(),
897 prefix(blockPrefix, directMeter->name));
898 table->add_direct_resource_ids(
id);
899 addMeter(symbols, p4info, *directMeter, blockPrefix);
902 if (directRegister) {
903 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_REGISTER(),
904 prefix(blockPrefix, directRegister->name));
905 table->add_direct_resource_ids(
id);
906 addRegister(symbols, p4info, *directRegister, blockPrefix);
911 if (supportsTimeout) {
912 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
914 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
921 auto timeout = table->properties->getProperty(
"idle_timeout"_cs);
922 if (timeout ==
nullptr)
return false;
923 if (!timeout->value->is<IR::ExpressionValue>()) {
924 error(
"Unexpected value %1% for idle_timeout on table %2%", timeout, table);
928 auto expr = timeout->value->to<IR::ExpressionValue>()->expression;
929 if (!expr->is<IR::BoolLiteral>()) {
931 "Unexpected non-boolean value %1% for idle_timeout "
932 "property on table %2%",
937 return expr->to<IR::BoolLiteral>()->value;
944 p4configv1::P4TypeInfo *p4RtTypeInfo) {
945 auto directRegisterInstance =
947 if (!directRegisterInstance)
return std::nullopt;
952 const IR::ExternBlock *)
override {}
955 p4configv1::P4Info *p4info,
const IR::ExternBlock *externBlock,
956 cstring pipeName = cstring::empty) {
957 Log::TempIndent indent;
958 LOG1(
"Adding Extern Instances for pipe " << pipeName << indent);
959 auto decl = externBlock->node->
to<IR::Declaration_Instance>();
962 if (decl ==
nullptr)
return;
966 auto p4RtTypeInfo = p4info->mutable_type_info();
968 if (externBlock->type->name ==
"ActionProfile") {
970 if (actionProfile) addActionProfile(symbols, p4info, *actionProfile, pipeName);
971 }
else if (externBlock->type->name ==
"ActionSelector") {
973 if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
974 }
else if (externBlock->type->name ==
"Counter") {
976 Counterlike<ArchCounterExtern>::from(externBlock, refMap, typeMap, p4RtTypeInfo);
977 if (counter) addCounter(symbols, p4info, *counter, pipeName);
978 }
else if (externBlock->type->name ==
"Meter") {
980 Counterlike<ArchMeterExtern>::from(externBlock, refMap, typeMap, p4RtTypeInfo);
981 if (meter) addMeter(symbols, p4info, *meter, pipeName);
982 }
else if (externBlock->type->name ==
"Digest") {
983 auto digest = getDigest(decl, p4RtTypeInfo);
984 if (digest) addDigest(symbols, p4info, *digest, pipeName);
985 }
else if (externBlock->type->name ==
"Register") {
986 auto register_ =
Register::from(externBlock, refMap, typeMap, p4RtTypeInfo);
987 if (register_) addRegister(symbols, p4info, *register_, pipeName);
988 }
else if (externBlock->type->name ==
"Hash") {
989 auto dynHash = getDynHash(decl, p4RtTypeInfo);
990 if (dynHash) addDynHash(symbols, p4info, *dynHash, pipeName);
998 const ValueSet &valueSetInstance) {
999 ::barefoot::ValueSet valueSet;
1000 valueSet.set_size(valueSetInstance.size);
1001 valueSet.mutable_type_spec()->CopyFrom(*valueSetInstance.typeSpec);
1002 addP4InfoExternInstance(symbols, SymbolType::P4RT_VALUE_SET(),
"ValueSet"_cs,
1003 valueSetInstance.name, valueSetInstance.annotations, valueSet,
1005 LOG2(
"Added Instance - Value Set " << valueSetInstance.name);
1009 const IR::ParserBlock *parserBlock) {
1010 CHECK_NULL(parserBlock);
1011 auto parser = parserBlock->container;
1014 for (
auto s : parser->parserLocals) {
1015 if (
auto inst = s->to<IR::P4ValueSet>()) {
1016 auto valueSet = ValueSet::from(inst->controlPlaneName(), inst, refMap, typeMap,
1017 p4info->mutable_type_info());
1018 if (valueSet) addValueSet(symbols, p4info, *valueSet);
1024 ::p4::config::v1::P4Info *p4info)
override {
1030 if (!block->is<IR::ParserBlock>())
return;
1031 analyzeParser(symbols, p4info, block->to<IR::ParserBlock>());
1036 const IR::ExternBlock *)
override {}
1040 std::optional<Digest> getDigest(
const IR::Declaration_Instance *decl,
1041 p4configv1::P4TypeInfo *p4RtTypeInfo) {
1042 std::vector<const P4::ExternMethod *> packCalls;
1050 decl, [&](
const P4::ExternMethod *method) { packCalls.push_back(method); });
1051 if (packCalls.size() == 0)
return std::nullopt;
1052 if (packCalls.size() > 1) {
1053 error(
"Expected single call to pack for digest instance '%1%'", decl);
1054 return std::nullopt;
1056 LOG4(
"Found 'pack' method call for digest instance " << decl->controlPlaneName());
1058 BUG_CHECK(decl->type->is<IR::Type_Specialized>(),
"%1%: expected Type_Specialized",
1060 auto type = decl->type->to<IR::Type_Specialized>();
1061 BUG_CHECK(type->arguments->size() == 1,
"%1%: expected one type argument", decl);
1062 auto typeArg = type->arguments->at(0);
1065 BUG_CHECK(typeSpec !=
nullptr,
1066 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
1067 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
1070 std::optional<DynHash> getDynHash(
const IR::Declaration_Instance *decl,
1071 p4configv1::P4TypeInfo *p4RtTypeInfo) {
1072 std::vector<const P4::ExternMethod *> hashCalls;
1075 decl, [&](
const P4::ExternMethod *method) { hashCalls.push_back(method); });
1076 if (hashCalls.size() == 0)
return std::nullopt;
1077 if (hashCalls.size() > 1) {
1079 "Expected single call to get for hash instance '%1%'."
1080 "Control plane API is not generated for this hash call",
1082 return std::nullopt;
1084 LOG4(
"Found 'get' method call for hash instance " << decl->controlPlaneName());
1088 if (
auto *call = hashCalls[0]->expr->to<IR::MethodCallExpression>()) {
1090 if (
auto t = call->type->to<IR::Type_Bits>()) {
1091 hashWidth = t->width_bits();
1094 auto fieldListArg = call->arguments->at(0);
1095 LOG4(
"FieldList for Hash: " << fieldListArg);
1097 std::vector<DynHash::hashField> hashFieldInfo;
1098 if (fieldListArg->expression->is<IR::ListExpression>() ||
1099 fieldListArg->expression->is<IR::StructExpression>()) {
1100 for (
auto f : *getListExprComponents(*fieldListArg->expression)) {
1101 if (
auto c = f->to<IR::Concat>()) {
1102 for (
auto e : convertConcatToList(c)) {
1103 hashFieldInfo.push_back({e->toString(), e->is<IR::Constant>()});
1104 typeArgs->push_back(e->type);
1108 hashFieldInfo.push_back({f->toString(), f->is<IR::Constant>()});
1109 auto t = f->type->is<IR::Type_SerEnum>() ? f->type->to<IR::Type_SerEnum>()->type
1111 typeArgs->push_back(t);
1114 auto *typeList =
new IR::Type_List(*typeArgs);
1116 typeList, p4RtTypeInfo);
1117 BUG_CHECK(typeSpec !=
nullptr,
1118 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
1119 return DynHash{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>(),
1120 hashFieldInfo, hashWidth};
1122 return std::nullopt;
1131 if (!instance)
return std::nullopt;
1132 if (instance->type->name !=
"ActionProfile")
return std::nullopt;
1133 auto size = instance->substitution.lookupByName(
"size"_cs)->expression;
1135 BUG_CHECK(size->template is<IR::Constant>(),
"Non-constant size");
1136 return ActionProfile{*instance->name, size->template to<IR::Constant>()->asInt(),
1137 getTableImplementationAnnotations(table, refMap)};
1143 auto size = instance->getParameterValue(
"size"_cs);
1144 BUG_CHECK(size->
is<IR::Constant>(),
"Non-constant size");
1145 return ActionProfile{decl->controlPlaneName(), size->
to<IR::Constant>()->asInt(),
1146 decl->to<IR::IAnnotated>()};
1155 table, implementationString,
"ActionSelector"_cs, refMap, typeMap);
1156 if (!action_selector)
return std::nullopt;
1159 if (action_selector->substitution.lookupByName(
"size"_cs)) {
1160 auto size = action_selector->substitution.lookupByName(
"size"_cs)->expression;
1161 BUG_CHECK(size->template is<IR::Constant>(),
"Non-constant size");
1164 size->template to<IR::Constant>()->asInt(),
1165 defaultMaxGroupSize,
1166 size->template to<IR::Constant>()->asInt(),
1167 getTableImplementationAnnotations(table, refMap),
1171 action_selector->substitution.lookupByName(
"max_group_size"_cs)->expression;
1172 auto numGroups = action_selector->substitution.lookupByName(
"num_groups"_cs)->expression;
1174 BUG_CHECK(maxGroupSize->template is<IR::Constant>(),
"Non-constant max group size");
1175 BUG_CHECK(numGroups->template is<IR::Constant>(),
"Non-constant num groups");
1177 *action_selector->name,
1179 maxGroupSize->template to<IR::Constant>()->asInt(),
1180 numGroups->template to<IR::Constant>()->asInt(),
1181 getTableImplementationAnnotations(table, refMap),
1185 std::optional<ActionSelector>
getActionSelector(
const IR::ExternBlock *instance) {
1188 if (instance->findParameterValue(
"size"_cs)) {
1189 auto size = instance->getParameterValue(
"size"_cs);
1190 BUG_CHECK(size->is<IR::Constant>(),
"Non-constant size");
1193 size->to<IR::Constant>()->asInt(),
1194 defaultMaxGroupSize,
1195 size->to<IR::Constant>()->asInt(),
1196 actionSelDecl->to<IR::IAnnotated>(),
1199 auto maxGroupSize = instance->getParameterValue(
"max_group_size"_cs);
1200 auto numGroups = instance->getParameterValue(
"num_groups"_cs);
1201 BUG_CHECK(maxGroupSize->is<IR::Constant>(),
"Non-constant max group size");
1202 BUG_CHECK(numGroups->is<IR::Constant>(),
"Non-constant num groups");
1203 auto action_profile = instance->getParameterValue(
"action_profile"_cs);
1204 auto action_profile_decl =
1206 return ActionSelector{actionSelDecl->controlPlaneName(),
1207 cstring::to_cstring(action_profile_decl->controlPlaneName()),
1209 maxGroupSize->to<IR::Constant>()->asInt(),
1210 numGroups->to<IR::Constant>()->asInt(),
1211 actionSelDecl->to<IR::IAnnotated>(),
1216 cstring typeName, p4configv1::P4Info *p4info) {
1217 for (
auto &externType : *p4info->mutable_externs()) {
1218 if (externType.extern_type_id() ==
static_cast<p4rt_id_t
>(typeId))
return &externType;
1220 auto *externType = p4info->add_externs();
1221 externType->set_extern_type_id(
static_cast<p4rt_id_t
>(typeId));
1222 externType->set_extern_type_name(typeName);
1229 const IR::IAnnotated *annotations,
1230 const ::google::protobuf::Message &message,
1231 p4configv1::P4Info *p4info) {
1232 auto *externType = getP4InfoExtern(typeId, typeName, p4info);
1233 auto *externInstance = externType->add_instances();
1234 auto *pre = externInstance->mutable_preamble();
1235 pre->set_id(symbols.
getId(typeId, name));
1236 pre->set_name(name);
1237 pre->set_alias(symbols.
getAlias(name));
1238 Helpers::addAnnotations(pre, annotations);
1240 externInstance->mutable_info()->PackFrom(message);
1244 const Digest &digestInstance,
cstring pipeName = cstring::empty) {
1245 ::barefoot::Digest digest;
1246 digest.mutable_type_spec()->CopyFrom(*digestInstance.typeSpec);
1247 auto digestName = prefix(pipeName, digestInstance.name);
1248 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIGEST(),
"Digest"_cs, digestName,
1249 digestInstance.annotations, digest, p4Info);
1250 LOG2(
"Added Instance - Digest " << digestName);
1254 const DynHash &dynHashInstance,
cstring pipeName = cstring::empty) {
1255 ::barefoot::DynHash dynHash;
1256 dynHash.set_hash_width(dynHashInstance.hashWidth);
1257 dynHash.mutable_type_spec()->CopyFrom(*dynHashInstance.typeSpec);
1258 auto dynHashName = prefix(pipeName, dynHashInstance.name);
1259 for (
const auto &f : dynHashInstance.hashFieldInfo) {
1260 auto newF = dynHash.add_field_infos();
1261 newF->set_field_name(f.hashFieldName);
1262 newF->set_is_constant(f.isConstant);
1264 addP4InfoExternInstance(symbols, SymbolType::P4RT_HASH(),
"DynHash"_cs, dynHashName,
1265 dynHashInstance.annotations, dynHash, p4Info);
1266 LOG2(
"Added Instance - DynHash " << dynHashName);
1272 const Register ®isterInstance,
cstring pipeName = cstring::empty) {
1273 auto registerName = prefix(pipeName, registerInstance.name);
1274 if (registerInstance.size == 0) {
1275 ::barefoot::DirectRegister register_;
1276 register_.mutable_type_spec()->CopyFrom(*registerInstance.typeSpec);
1277 register_.set_data_field_name(registerInstance.name);
1278 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_REGISTER(),
1279 "DirectRegister"_cs, registerName, registerInstance.annotations,
1281 LOG2(
"Added Instance - DirectRegister " << registerName);
1283 ::barefoot::Register register_;
1284 register_.set_size(registerInstance.size);
1285 register_.mutable_type_spec()->CopyFrom(*registerInstance.typeSpec);
1286 register_.set_data_field_name(registerInstance.name);
1287 addP4InfoExternInstance(symbols, SymbolType::P4RT_REGISTER(),
"Register"_cs,
1288 registerName, registerInstance.annotations, register_, p4Info);
1289 LOG2(
"Added Instance - Register " << registerName);
1294 template <
typename Kind>
1297 auto counter_spec = counter->mutable_spec();
1298 counter_spec->set_unit(CounterTraits::mapUnitName(counterInstance.
unit));
1303 const cstring blockPrefix = cstring::empty) {
1304 if (counterInstance.
table) {
1305 ::barefoot::DirectCounter counter;
1307 auto tableName = prefix(blockPrefix, *counterInstance.
table);
1308 auto counterName = prefix(blockPrefix, counterInstance.
name);
1310 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
1311 counter.set_direct_table_id(tableId);
1312 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_COUNTER(),
1314 counterName, counterInstance.
annotations, counter, p4Info);
1315 LOG2(
"Added Instance - DirectCounter " << counterName);
1317 ::barefoot::Counter counter;
1319 counter.set_size(counterInstance.
size);
1320 auto counterName = prefix(blockPrefix, counterInstance.
name);
1321 addP4InfoExternInstance(symbols, SymbolType::P4RT_COUNTER(),
1323 counterName, counterInstance.
annotations, counter, p4Info);
1324 LOG2(
"Added Instance - Counter " << counterName);
1329 template <
typename Kind>
1331 using ::barefoot::MeterSpec;
1333 auto meter_spec = meter->mutable_spec();
1335 meter_spec->set_type(MeterSpec::COLOR_AWARE);
1337 meter_spec->set_type(MeterSpec::COLOR_UNAWARE);
1339 meter_spec->set_unit(CounterlikeTraits<ArchMeterExtern>::mapUnitName(meterInstance.
unit));
1344 const cstring blockPrefix = cstring::empty) {
1345 auto meterName = prefix(blockPrefix, meterInstance.
name);
1346 if (meterInstance.
table) {
1347 ::barefoot::DirectMeter meter;
1349 auto tableName = prefix(blockPrefix, *meterInstance.
table);
1351 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
1352 meter.set_direct_table_id(tableId);
1353 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_METER(),
1355 meterName, meterInstance.
annotations, meter, p4Info);
1356 LOG2(
"Added Instance - DirectMeter " << meterName);
1358 ::barefoot::Meter meter;
1360 meter.set_size(meterInstance.
size);
1361 addP4InfoExternInstance(symbols, SymbolType::P4RT_METER(),
1363 meterName, meterInstance.
annotations, meter, p4Info);
1364 LOG2(
"Added Instance - Meter " << meterName);
1369 const ActionProfile &actionProfile,
cstring pipeName = cstring::empty) {
1370 ::barefoot::ActionProfile profile;
1371 profile.set_size(actionProfile.size);
1372 auto actionProfileName = prefix(pipeName, actionProfile.name);
1375 for (
const auto &table : tablesIt->second) {
1377 if (!pipeName.isNullOrEmpty()) tableName = prefix(pipeName, tableName);
1378 profile.add_table_ids(symbols.
getId(
1379 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1382 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_PROFILE(),
"ActionProfile"_cs,
1383 actionProfileName, actionProfile.annotations, profile, p4Info);
1384 LOG2(
"Added Extern Instance - Action Profile " << actionProfileName);
1388 p4configv1::P4Info *p4Info,
const ActionSelector &actionSelector,
1389 cstring blockPrefix = cstring::empty) {
1390 ::barefoot::ActionSelector selector;
1391 selector.set_max_group_size(actionSelector.maxGroupSize);
1392 selector.set_num_groups(actionSelector.numGroups);
1393 cstring actionSelectorName = prefix(blockPrefix, actionSelector.name);
1394 if (actionSelector.actionProfileName) {
1395 selector.set_action_profile_id(
1396 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(),
1397 prefix(blockPrefix, *actionSelector.actionProfileName)));
1400 for (
const auto &table : tablesIt->second) {
1401 cstring tableName = prefix(blockPrefix, table);
1402 selector.add_table_ids(symbols.
getId(
1403 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1406 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_SELECTOR(),
1407 "ActionSelector"_cs, actionSelectorName,
1408 actionSelector.annotations, selector, p4Info);
1409 LOG2(
"Added Extern Instance - Action Selector " << actionSelectorName);
1411 ::barefoot::ActionProfile profile;
1412 profile.set_size(actionSelector.size);
1415 for (
const auto &table : tablesIt->second) {
1416 cstring tableName = prefix(blockPrefix, table);
1417 profile.add_table_ids(symbols.
getId(
1418 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1419 selector.add_table_ids(symbols.
getId(
1420 P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName));
1426 cstring profileName = actionSelectorName;
1427 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_PROFILE(),
"ActionProfile"_cs,
1428 profileName, actionSelector.annotations, profile, p4Info);
1429 selector.set_action_profile_id(
1430 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
1431 cstring selectorName = profileName +
"_sel";
1432 addP4InfoExternInstance(symbols, SymbolType::P4RT_ACTION_SELECTOR(),
1433 "ActionSelector"_cs, selectorName, actionSelector.annotations,
1435 LOG2(
"Added Extern Instance - Action Selector " << selectorName);
1443 template <
typename Func>
1446 evaluatedProgram->getProgram(), [&](
const IR::MethodCallExpression *call) {
1447 auto instance = P4::MethodInstance::resolve(call, refMap, typeMap);
1448 if (instance->is<P4::ExternMethod>() && instance->object == object) {
1449 function(instance->to<P4::ExternMethod>());
1457 return table->properties->getProperty(implementationString);
1460 const IR::IAnnotated *getTableImplementationAnnotations(
const IR::P4Table *table,
1462 auto impl = getTableImplementationProperty(table);
1463 if (impl ==
nullptr)
return nullptr;
1464 if (!impl->value->template is<IR::ExpressionValue>())
return nullptr;
1465 auto expr = impl->value->template to<IR::ExpressionValue>()->expression;
1466 if (expr->template is<IR::ConstructorCallExpression>())
1467 return impl->template to<IR::IAnnotated>();
1468 if (expr->template is<IR::PathExpression>()) {
1469 auto decl = refMap->
getDeclaration(expr->template to<IR::PathExpression>()->path,
true);
1470 return decl->template to<IR::IAnnotated>();
1475 std::optional<cstring> getTableImplementationName(
const IR::P4Table *table,
1477 auto impl = getTableImplementationProperty(table);
1478 if (impl ==
nullptr)
return std::nullopt;
1479 if (!impl->value->template is<IR::ExpressionValue>()) {
1480 error(
"Expected %1% property value for table %2% to be an expression: %2%",
1481 implementationString, table->controlPlaneName(), impl);
1482 return std::nullopt;
1484 auto expr = impl->value->template to<IR::ExpressionValue>()->expression;
1485 if (expr->template is<IR::ConstructorCallExpression>())
return impl->controlPlaneName();
1486 if (expr->template is<IR::PathExpression>()) {
1487 auto decl = refMap->
getDeclaration(expr->template to<IR::PathExpression>()->path,
true);
1488 return decl->controlPlaneName();
1490 return std::nullopt;
1495 const IR::ToplevelBlock *evaluatedProgram;
1503 cstring defaultPipeName =
"pipe"_cs;
1505 static constexpr int64_t defaultMaxGroupSize = 120;
1508 google::protobuf::util::JsonPrintOptions jsonPrintOptions;
1512 return jsonPrintOptions;
1521 template <
typename Func>
1522 void forAllPipeBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
1523 auto main = evaluatedProgram->getMain();
1524 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1525 auto cparams = main->getConstructorParameters();
1527 for (
auto param : main->constantValue) {
1529 if (!param.second)
continue;
1530 auto pipe = param.second;
1531 if (!pipe->is<IR::PackageBlock>()) {
1532 error(ErrorType::ERR_INVALID,
1533 "%1% package block. You are compiling for the %2% "
1534 "P4 architecture.\n"
1535 "Please verify that you included the correct architecture file.",
1536 pipe, BackendOptions().arch);
1539 auto idxParam = cparams->getParameter(index);
1540 auto pipeName = idxParam->name;
1541 function(pipeName, pipe->to<IR::PackageBlock>());
1545 template <
typename Func>
1546 void forAllPortMetadataBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
1547 auto main = evaluatedProgram->getMain();
1548 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1549 if (main->type->name ==
"MultiParserSwitch") {
1550 int numParsersPerPipe = Device::numParsersPerPipe();
1551 auto parsersName =
"ig_prsr"_cs;
1552 forAllPipeBlocks(evaluatedProgram, [&](
cstring,
const IR::PackageBlock *pkg) {
1553 auto parsers = pkg->findParameterValue(parsersName);
1554 BUG_CHECK(parsers,
"Expected Block");
1555 if (!parsers->is<IR::PackageBlock>()) {
1556 error(ErrorType::ERR_INVALID,
1557 "%1% package block. "
1558 "You are compiling for the %2% P4 architecture.\n"
1559 "Please verify that you included the correct architecture file.",
1560 parsers, BackendOptions().arch);
1563 auto parsersBlock = parsers->to<IR::PackageBlock>();
1564 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1565 auto mpParserName =
"prsr" + std::to_string(idx);
1566 auto parser = parsersBlock->findParameterValue(mpParserName);
1568 auto parserBlock = parser->to<IR::ParserBlock>();
1569 if (hasUserPortMetadata.count(parserBlock) == 0) {
1570 auto portMetadataFullName =
1571 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
1572 function(portMetadataFullName, parserBlock);
1577 auto parserName =
"ingress_parser"_cs;
1578 forAllPipeBlocks(evaluatedProgram, [&](
cstring,
const IR::PackageBlock *pkg) {
1579 auto *block = pkg->findParameterValue(parserName);
1581 if (!block->is<IR::ParserBlock>())
return;
1582 auto parserBlock = block->to<IR::ParserBlock>();
1583 if (hasUserPortMetadata.count(parserBlock) == 0) {
1584 auto portMetadataFullName =
1585 getFullyQualifiedName(parserBlock, PortMetadata::name());
1586 function(portMetadataFullName, parserBlock);
1593 const IR::ToplevelBlock *evaluatedProgram)
1595 Log::TempIndent indent;
1596 LOG1(
"BFRuntimeArchHandlerTofino" << indent);
1597 implementationString =
"implementation"_cs;
1599 std::set<cstring> pipes;
1600 LOG2(
"Populating blockNamePrefixMap" << Log::indent);
1606 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1608 auto decl = pkg->node->to<IR::Declaration_Instance>();
1609 cstring blockNamePrefix = pipeName;
1610 if (decl) blockNamePrefix = decl->controlPlaneName();
1611 blockNamePrefixMap[block] = blockNamePrefix;
1612 LOG4(
"Updating blockNamePrefixMap with " << &*block << block->toString() <<
" : "
1613 << blockNamePrefixMap[block]);
1614 pipes.insert(pipeName);
1620 static std::vector<cstring> gressNames = {
"ig"_cs,
"eg"_cs};
1621 int numParsersPerPipe = Device::numParsersPerPipe();
1623 auto main = evaluatedProgram->getMain();
1624 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1626 isMultiParser =
false;
1627 if (main->type->name ==
"MultiParserSwitch") {
1628 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1630 pkg->type->name ==
"MultiParserPipeline",
1631 "Only MultiParserPipeline pipes can be used with a MultiParserSwitch switch");
1632 for (
auto gressName : gressNames) {
1633 auto parsersName = gressName +
"_prsr";
1634 auto parsers = pkg->findParameterValue(parsersName);
1635 BUG_CHECK(parsers && parsers->is<IR::PackageBlock>(),
"Expected PackageBlock");
1636 auto parsersBlock = parsers->to<IR::PackageBlock>();
1637 auto decl = parsersBlock->node->to<IR::Declaration_Instance>();
1638 if (decl) parsersName = decl->controlPlaneName();
1639 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1640 auto parserName =
"prsr" + std::to_string(idx);
1641 auto parser = parsersBlock->findParameterValue(parserName);
1643 BUG_CHECK(parser->is<IR::ParserBlock>(),
"Expected ParserBlock");
1644 auto parserBlock = parser->to<IR::ParserBlock>();
1647 auto parserFullName = pipeName +
"." + parsersName +
"." + parserName;
1648 blockNamePrefixMap[parserBlock] = parserFullName;
1650 isMultiParser =
true;
1656 cstring getBlockNamePrefix(
const IR::Block *blk)
override {
1657 if (blockNamePrefixMap.count(blk) > 0)
return blockNamePrefixMap[blk];
1658 return cstring::empty;
1662 const IR::ExternBlock *externBlock)
override {
1663 collectExternInstanceCommon(symbols, externBlock);
1665 CHECK_NULL(externBlock);
1671 if (decl ==
nullptr)
return;
1673 auto symName = getControlPlaneName(externBlock, decl);
1674 if (externBlock->type->name ==
"Lpf") {
1675 symbols->
add(SymbolType::P4RT_LPF(), symName);
1676 }
else if (externBlock->type->name ==
"DirectLpf") {
1677 symbols->
add(SymbolType::P4RT_DIRECT_LPF(), symName);
1678 }
else if (externBlock->type->name ==
"Wred") {
1679 symbols->
add(SymbolType::P4RT_WRED(), symName);
1680 }
else if (externBlock->type->name ==
"DirectWred") {
1681 symbols->
add(SymbolType::P4RT_DIRECT_WRED(), symName);
1682 }
else if (externBlock->type->name ==
"RegisterParam") {
1683 symbols->
add(SymbolType::P4RT_REGISTER_PARAM(), symName);
1691 const IR::ParserBlock *parserBlock) {
1692 auto portMetadata = getPortMetadataExtract(externFunction, refMap, typeMap,
nullptr);
1694 if (hasUserPortMetadata.count(parserBlock)) {
1695 error(
"Cannot have multiple extern calls for %1%",
1696 BFN::ExternPortMetadataUnpackString);
1699 hasUserPortMetadata.insert(parserBlock);
1700 auto portMetadataFullName =
1701 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
1702 symbols->
add(SymbolType::P4RT_PORT_METADATA(), portMetadataFullName);
1707 const IR::ParserBlock *parserBlock) {
1708 CHECK_NULL(parserBlock);
1709 auto parser = parserBlock->container;
1713 for (
auto state : parser->states) {
1715 state, [&](
const IR::MethodCallExpression *call) {
1718 collectPortMetadataExternFunction(
1723 for (
auto s : parser->parserLocals) {
1724 if (
auto inst = s->to<IR::P4ValueSet>()) {
1725 auto name = getFullyQualifiedName(parserBlock, inst->controlPlaneName(),
true);
1726 symbols->
add(SymbolType::P4RT_VALUE_SET(), name);
1735 auto *params = parser->getApplyParameters();
1736 for (
auto p : *params) {
1737 if (p->type->toString() ==
"ingress_intrinsic_metadata_t") {
1739 ingressIntrinsicMdParamName.count(parserBlock) == 0 ||
1740 strcmp(ingressIntrinsicMdParamName[parserBlock], p->name.toString()) == 0,
1741 "%1%: Multiple names of intrinsic metadata found in this parser block",
1743 ingressIntrinsicMdParamName[parserBlock] = p->name;
1767 static std::vector<cstring> gressNames = {
"ingress"_cs,
"egress"_cs};
1768 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1769 for (
auto gressName : gressNames) {
1770 auto gress = pkg->findParameterValue(gressName);
1771 BUG_CHECK(gress->is<IR::ControlBlock>(),
"Expected control");
1772 auto control = gress->to<IR::ControlBlock>();
1773 if (blockNamePrefixMap.count(control) > 0) pipeName = blockNamePrefixMap[control];
1774 snapshotInfo.emplace(control,
1775 SnapshotInfo{pipeName, gressName, 0u, cstring::empty, {}});
1776 LOG3(
"Adding SnapshotInfo for " << control->getName() <<
" " << gressName
1777 <<
" on pipe " << pipeName);
1790 CHECK_NULL(controlBlock);
1791 auto control = controlBlock->container;
1792 CHECK_NULL(control);
1793 Log::TempIndent indent;
1794 auto sinfoIt = snapshotInfo.find(controlBlock);
1797 if (sinfoIt == snapshotInfo.end())
return;
1798 auto snapshot_name = getFullyQualifiedName(controlBlock, control->externalName());
1799 LOG1(
"Collecting Snapshot for control " << snapshot_name << indent);
1804 if (snapshots.count(snapshot_name)) {
1805 snapshotInfo.erase(sinfoIt);
1808 snapshots.insert(snapshot_name);
1809 sinfoIt->second.name = snapshot_name;
1810 auto snapshotFields = &sinfoIt->second.fields;
1811 auto params = control->getApplyParameters();
1812 for (
size_t idx = 0; idx < params->size(); idx++) {
1813 auto p = params->getParameter(idx);
1816 auto includeValid = (idx == sinfoIt->second.userHdrParamIdx);
1817 SnapshotFieldFinder::find(typeMap, p->type, p->name, includeValid, snapshotFields,
1820 LOG3(
"Adding snaphot to bfrt info for control: " << snapshot_name);
1821 symbols->
add(SymbolType::P4RT_SNAPSHOT(), snapshot_name);
1830 static std::vector<cstring> gressNames = {
"ig"_cs,
"eg"_cs};
1831 int numParsersPerPipe = Device::numParsersPerPipe();
1833 auto main = evaluatedProgram->getMain();
1834 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1835 if (main->type->name !=
"MultiParserSwitch")
return;
1837 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1838 BUG_CHECK(pkg->type->name ==
"MultiParserPipeline",
1839 "Only MultiParserPipeline pipes can be used with a MultiParserSwitch switch");
1840 for (
auto gressName : gressNames) {
1841 ::barefoot::ParserChoices parserChoices;
1843 if (
auto decl = pkg->node->to<IR::Declaration_Instance>()) pipeName = decl->Name();
1845 parserChoices.set_pipe(pipeName);
1846 if (gressName ==
"ig")
1847 parserChoices.set_direction(::barefoot::DIRECTION_INGRESS);
1849 parserChoices.set_direction(::barefoot::DIRECTION_EGRESS);
1851 auto parsersName = gressName +
"_prsr";
1852 auto parsers = pkg->findParameterValue(parsersName);
1853 BUG_CHECK(parsers && parsers->is<IR::PackageBlock>(),
"Expected PackageBlock");
1854 auto parsersBlock = parsers->to<IR::PackageBlock>();
1855 auto decl = parsersBlock->node->to<IR::Declaration_Instance>();
1856 if (decl) parsersName = decl->controlPlaneName();
1857 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1858 auto parserName =
"prsr" + std::to_string(idx);
1859 auto parser = parsersBlock->findParameterValue(parserName);
1861 BUG_CHECK(parser->is<IR::ParserBlock>(),
"Expected ParserBlock");
1862 auto parserBlock = parser->to<IR::ParserBlock>();
1863 auto decl = parserBlock->node->to<IR::Declaration_Instance>();
1864 auto userName = (decl ==
nullptr) ?
"" : decl->controlPlaneName();
1866 auto choice = parserChoices.add_choices();
1867 auto parserFullName = prefix(parsersName, parserName);
1868 parserFullName = prefix(pipeName, parserFullName);
1869 choice->set_arch_name(parserFullName);
1870 choice->set_type_name(parserBlock->getName().name);
1871 choice->set_user_name(userName);
1873 auto parsersFullName = prefix(pipeName, parsersName);
1874 symbols->
add(SymbolType::P4RT_PARSER_CHOICES(), parsersFullName);
1875 parserConfiguration.emplace(parsersFullName, parserChoices);
1881 Log::TempIndent indent;
1882 LOG1(
"BFRuntimeArchHandlerTofino::collectExtra" << indent);
1883 LOG2(
"Collecting Parser Symbols" << Log::indent);
1889 if (!block->is<IR::ParserBlock>())
return;
1890 collectParserSymbols(symbols, block->to<IR::ParserBlock>());
1894 LOG2(
"Collecting Snapshot Fields" << Log::indent);
1897 getSnapshotControls();
1900 if (!block->is<IR::ControlBlock>())
return;
1901 collectSnapshot(symbols, block->to<IR::ControlBlock>(), &snapshotFieldIds);
1905 LOG2(
"Collecting Parser Choices" << Log::indent);
1906 collectParserChoices(symbols);
1909 LOG2(
"Collecting PortMetadata" << Log::indent);
1912 forAllPortMetadataBlocks(
1913 evaluatedProgram, [&](
cstring portMetadataFullName,
const IR::ParserBlock *) {
1914 symbols->
add(SymbolType::P4RT_PORT_METADATA(), portMetadataFullName);
1915 LOG3(
"Adding PortMetadata symbol: " << portMetadataFullName);
1921 Log::TempIndent indent;
1922 LOG1(
"BFRuntimeArchHandlerTofino::postCollect" << indent);
1927 if (!block->is<IR::TableBlock>())
return;
1928 auto table = block->to<IR::TableBlock>()->container;
1929 auto implementation = getTableImplementationName(table, refMap);
1930 if (implementation) {
1931 auto pipeName = blockNamePrefixMap[block];
1932 auto implName = prefix(pipeName, *implementation);
1933 actionProfilesRefs[implName].insert(table->controlPlaneName());
1934 LOG5(
"Adding action profile : " << implName <<
" for table "
1935 << table->controlPlaneName());
1942 if (!block->is<IR::ExternBlock>())
return;
1943 auto selectorExternBlock = block->to<IR::ExternBlock>();
1944 if (selectorExternBlock->type->name !=
"ActionSelector")
return;
1945 auto selectorDecl = selectorExternBlock->node->to<IR::Declaration_Instance>();
1946 CHECK_NULL(selectorDecl);
1947 auto profile = selectorExternBlock->getParameterValue(
"action_profile"_cs);
1949 auto profileExternBlock = profile->to<IR::ExternBlock>();
1950 auto profileDecl = profileExternBlock->node->to<IR::Declaration_Instance>();
1951 CHECK_NULL(profileDecl);
1952 auto pipeName = blockNamePrefixMap[selectorExternBlock];
1953 auto profileDeclName = prefix(pipeName, profileDecl->controlPlaneName());
1954 auto selectorDeclName = prefix(pipeName, selectorDecl->controlPlaneName());
1955 actionProfilesRefs[profileDeclName].insert(
1956 actionProfilesRefs[selectorDeclName].begin(),
1957 actionProfilesRefs[selectorDeclName].end());
1958 LOG5(
"Adding action profile : " << profileDeclName <<
" for tables "
1959 << actionProfilesRefs[profileDeclName]);
1968 if (!block->is<IR::ExternBlock>())
return;
1969 auto externBlock = block->to<IR::ExternBlock>();
1970 if (externBlock->type->name !=
"Meter" && externBlock->type->name !=
"DirectMeter")
1972 auto decl = externBlock->node->to<IR::Declaration_Instance>();
1977 auto call = method->expr;
1978 if (call->arguments->size() == 2) {
1979 LOG3(
"Meter " << decl->controlPlaneName() <<
" is color-aware "
1980 <<
"because of 2-argument call to execute()");
1981 colorAwareMeters.insert(decl->controlPlaneName());
1986 class RegisterParamFinder :
public Inspector {
1989 bool checkExtern(
const IR::Declaration_Instance *decl,
cstring name) {
1990 if (
auto *specialized = decl->type->to<IR::Type_Specialized>())
1991 if (
auto *name_type = specialized->baseType->to<IR::Type_Name>())
1992 return name_type->path->name == name;
1998 bool preorder(
const IR::MethodCallExpression *mce)
override {
2001 if (method->
object ==
nullptr)
2003 auto *reg_param = method->
object->
to<IR::Declaration_Instance>();
2004 if (reg_param ==
nullptr)
2006 if (!checkExtern(reg_param,
"RegisterParam"_cs))
return true;
2008 auto *reg_action = findContext<IR::Declaration_Instance>();
2009 if (reg_action ==
nullptr)
return true;
2010 if (!checkExtern(reg_action,
"DirectRegisterAction"_cs) &&
2011 !checkExtern(reg_action,
"RegisterAction"_cs))
2013 BUG_CHECK(reg_action->arguments->size() > 0,
"%1%: Missing argument", reg_action);
2014 auto *rap = reg_action->arguments->at(0)->expression->to<IR::PathExpression>();
2015 if (rap ==
nullptr)
return true;
2018 if (rap_decl ==
nullptr)
return true;
2019 if (checkExtern(rap_decl,
"Register"_cs))
2020 self.registerParam2register[reg_param->controlPlaneName()] =
2021 rap_decl->controlPlaneName();
2022 if (checkExtern(rap_decl,
"DirectRegister"_cs))
2023 self.registerParam2table[reg_param->controlPlaneName()] =
2024 rap_decl->controlPlaneName();
2027 void postorder(
const IR::P4Table *table)
override {
2029 auto *registers = table->properties->getProperty(
"registers"_cs);
2030 if (registers ==
nullptr)
return;
2031 auto *registers_value = registers->value->to<IR::ExpressionValue>();
2032 CHECK_NULL(registers_value);
2033 auto *registers_path = registers_value->expression->to<IR::PathExpression>();
2034 CHECK_NULL(registers_path);
2035 auto *registers_decl =
getDeclInst(self.refMap, registers_path);
2036 CHECK_NULL(registers_decl);
2038 for (
auto r : self.registerParam2table)
2039 if (r.second == registers_decl->controlPlaneName())
2040 self.registerParam2table[r.first] = table->controlPlaneName();
2044 evaluatedProgram->getProgram()->apply(RegisterParamFinder(*
this));
2048 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
2049 CHECK_NULL(tableBlock);
2050 auto tableDeclaration = tableBlock->container;
2051 auto blockPrefix = blockNamePrefixMap[tableBlock];
2053 addTablePropertiesCommon(symbols, p4info, table, tableBlock, blockPrefix);
2055 auto directLpf = getDirectLpf(tableDeclaration, refMap, typeMap);
2058 symbols.
getId(SymbolType::P4RT_DIRECT_LPF(), prefix(blockPrefix, directLpf->name));
2059 table->add_direct_resource_ids(
id);
2060 addLpf(symbols, p4info, *directLpf, blockPrefix);
2063 auto directWred = getDirectWred(tableDeclaration, refMap, typeMap);
2065 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_WRED(),
2066 prefix(blockPrefix, directWred->name));
2067 table->add_direct_resource_ids(
id);
2068 addWred(symbols, p4info, *directWred, blockPrefix);
2075 template <
typename T>
2078 auto directFilterInstance =
2080 if (!directFilterInstance)
return std::nullopt;
2081 CHECK_NULL(directFilterInstance->type);
2082 if (directFilterInstance->type->name != filterType)
return std::nullopt;
2083 return T::fromDirect(*directFilterInstance, table);
2090 return getDirectFilter<Lpf>(table, refMap, typeMap,
"DirectLpf"_cs);
2097 return getDirectFilter<Wred>(table, refMap, typeMap,
"DirectWred"_cs);
2101 const IR::ExternBlock *externBlock)
override {
2102 auto decl = externBlock->node->to<IR::Declaration_Instance>();
2105 if (decl ==
nullptr)
return;
2110 auto pipeName = blockNamePrefixMap[externBlock];
2112 addExternInstanceCommon(symbols, p4info, externBlock, pipeName);
2114 auto p4RtTypeInfo = p4info->mutable_type_info();
2116 if (externBlock->type->name ==
"Lpf") {
2117 auto lpf = Lpf::from(externBlock);
2118 if (lpf) addLpf(symbols, p4info, *lpf, pipeName);
2119 }
else if (externBlock->type->name ==
"Wred") {
2120 auto wred = Wred::from(externBlock);
2121 if (wred) addWred(symbols, p4info, *wred, pipeName);
2122 }
else if (externBlock->type->name ==
"RegisterParam") {
2123 auto register_param_ = RegisterParam::from(externBlock, refMap, typeMap, p4RtTypeInfo);
2124 if (register_param_) addRegisterParam(symbols, p4info, *register_param_, pipeName);
2132 p4configv1::P4Info *p4info,
2134 const IR::ParserBlock *parserBlock) {
2135 auto p4RtTypeInfo = p4info->mutable_type_info();
2136 auto portMetadata = getPortMetadataExtract(externFunction, refMap, typeMap, p4RtTypeInfo);
2138 if (blockNamePrefixMap.count(parserBlock)) {
2139 auto portMetadataFullName =
2140 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
2141 addPortMetadata(symbols, p4info, *portMetadata, portMetadataFullName, parserBlock);
2147 const IR::ParserBlock *parserBlock) {
2148 CHECK_NULL(parserBlock);
2149 auto parser = parserBlock->container;
2152 for (
auto s : parser->parserLocals) {
2153 if (
auto inst = s->to<IR::P4ValueSet>()) {
2155 getFullyQualifiedName(parserBlock, inst->controlPlaneName(),
true);
2157 ValueSet::from(namePrefix, inst, refMap, typeMap, p4info->mutable_type_info());
2158 if (valueSet) addValueSet(symbols, p4info, *valueSet);
2163 for (
auto state : parser->states) {
2165 state, [&](
const IR::MethodCallExpression *call) {
2168 addPortMetadataExternFunction(
2175 ::p4::config::v1::P4Info *p4info)
override {
2183 p4info->clear_value_sets();
2186 if (!block->is<IR::ParserBlock>())
return;
2187 analyzeParser(symbols, p4info, block->to<IR::ParserBlock>());
2192 forAllPortMetadataBlocks(evaluatedProgram, [&](
cstring portMetadataFullName,
2193 const IR::ParserBlock *parserBlock) {
2194 addPortMetadataDefault(symbols, p4info, portMetadataFullName, parserBlock);
2197 for (
const auto &snapshot : snapshotInfo) addSnapshot(symbols, p4info, snapshot.second);
2199 for (
const auto &parser : parserConfiguration)
2200 addParserChoices(symbols, p4info, parser.first, parser.second);
2207 p4configv1::P4TypeInfo *p4RtTypeInfo) {
2208 if (function->method->name != BFN::ExternPortMetadataUnpackString)
return std::nullopt;
2210 if (
auto *call = function->expr->to<IR::MethodCallExpression>()) {
2211 auto *typeArg = call->typeArguments->at(0);
2213 typeArg, p4RtTypeInfo);
2216 return std::nullopt;
2221 const IR::ParserBlock *parserBlock) {
2222 ::barefoot::PortMetadata portMetadata;
2223 portMetadata.mutable_type_spec()->CopyFrom(*portMetadataExtract.typeSpec);
2224 CHECK_NULL(parserBlock);
2225 auto parser = parserBlock->container;
2227 BUG_CHECK(ingressIntrinsicMdParamName.count(parserBlock),
2228 "%1%: Name of the intrinsic metadata not found for this parser block",
2230 portMetadata.set_key_name(ingressIntrinsicMdParamName[parserBlock]);
2231 addP4InfoExternInstance(symbols, SymbolType::P4RT_PORT_METADATA(),
"PortMetadata"_cs, name,
2232 nullptr, portMetadata, p4Info);
2236 p4configv1::P4Info *p4Info,
const cstring &name,
2237 const IR::ParserBlock *parserBlock) {
2238 ::barefoot::PortMetadata portMetadata;
2239 CHECK_NULL(parserBlock);
2240 auto parser = parserBlock->container;
2243 if (ingressIntrinsicMdParamName.count(parserBlock)) {
2244 portMetadata.set_key_name(ingressIntrinsicMdParamName[parserBlock]);
2247 auto const DP0TKN = BFN::getDefaultPhase0TableKeyName();
2248 portMetadata.set_key_name(DP0TKN);
2251 addP4InfoExternInstance(symbols, SymbolType::P4RT_PORT_METADATA(),
"PortMetadata"_cs, name,
2252 nullptr, portMetadata, p4Info);
2256 const SnapshotInfo &snapshotInstance) {
2257 ::barefoot::Snapshot snapshot;
2258 snapshot.set_pipe(snapshotInstance.pipe);
2259 if (snapshotInstance.gress ==
"ingress")
2260 snapshot.set_direction(::barefoot::DIRECTION_INGRESS);
2261 else if (snapshotInstance.gress ==
"egress")
2262 snapshot.set_direction(::barefoot::DIRECTION_EGRESS);
2264 BUG(
"Invalid gress '%1%'", snapshotInstance.gress);
2265 for (
const auto &f : snapshotInstance.fields) {
2266 auto newF = snapshot.add_fields();
2268 newF->set_name(f.name);
2269 newF->set_bitwidth(f.bitwidth);
2271 addP4InfoExternInstance(symbols, SymbolType::P4RT_SNAPSHOT(),
"Snapshot"_cs,
2272 snapshotInstance.name,
nullptr, snapshot, p4Info);
2276 cstring name, const ::barefoot::ParserChoices &parserChoices) {
2277 addP4InfoExternInstance(symbols, SymbolType::P4RT_PARSER_CHOICES(),
"ParserChoices"_cs,
2278 name,
nullptr, parserChoices, p4Info);
2282 const Lpf &lpfInstance,
const cstring pipeName) {
2283 auto lpfName = prefix(pipeName, lpfInstance.name);
2284 if (lpfInstance.table) {
2285 ::barefoot::DirectLpf lpf;
2286 auto tableName = prefix(pipeName, *lpfInstance.table);
2288 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
2289 lpf.set_direct_table_id(tableId);
2290 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_LPF(),
"DirectLpf"_cs, lpfName,
2291 lpfInstance.annotations, lpf, p4Info);
2292 LOG2(
"Added Instance - Direct LPF " << lpfName);
2294 ::barefoot::Lpf lpf;
2295 lpf.set_size(lpfInstance.size);
2296 addP4InfoExternInstance(symbols, SymbolType::P4RT_LPF(),
"Lpf"_cs, lpfName,
2297 lpfInstance.annotations, lpf, p4Info);
2298 LOG2(
"Added Instance - LPF " << lpfName);
2303 template <
typename Kind>
2305 using ::barefoot::WredSpec;
2306 auto wred_spec = wred->mutable_spec();
2307 wred_spec->set_drop_value(wredInstance.dropValue);
2308 wred_spec->set_no_drop_value(wredInstance.noDropValue);
2312 const Wred &wredInstance,
const cstring pipeName) {
2313 auto wredName = prefix(pipeName, wredInstance.name);
2314 if (wredInstance.
table) {
2315 ::barefoot::DirectWred wred;
2316 setWredCommon(&wred, wredInstance);
2317 auto tableName = prefix(pipeName, *wredInstance.
table);
2319 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
2320 wred.set_direct_table_id(tableId);
2321 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_WRED(),
"DirectWred"_cs,
2322 wredName, wredInstance.annotations, wred, p4Info);
2323 LOG2(
"Added Instance - Direct WRED " << wredName);
2325 ::barefoot::Wred wred;
2326 setWredCommon(&wred, wredInstance);
2327 wred.set_size(wredInstance.size);
2328 addP4InfoExternInstance(symbols, SymbolType::P4RT_WRED(),
"Wred"_cs, wredName,
2329 wredInstance.annotations, wred, p4Info);
2330 LOG2(
"Added Instance - WRED " << wredName);
2337 const RegisterParam ®isterParamInstance,
2338 cstring pipeName = cstring::empty) {
2339 p4rt_id_t tableId = 0;
2340 if (registerParam2register.count(registerParamInstance.name) > 0)
2342 symbols.
getId(SymbolType::P4RT_REGISTER(),
2343 prefix(pipeName, registerParam2register[registerParamInstance.name]));
2344 else if (registerParam2table.count(registerParamInstance.name) > 0)
2346 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(),
2347 prefix(pipeName, registerParam2table[registerParamInstance.name]));
2349 ::barefoot::RegisterParam register_param_;
2350 register_param_.mutable_type_spec()->CopyFrom(*registerParamInstance.typeSpec);
2351 register_param_.set_table_id(tableId);
2352 register_param_.set_initial_value(registerParamInstance.initial_value);
2353 register_param_.set_data_field_name(registerParamInstance.name);
2354 auto registerParamName = prefix(pipeName, registerParamInstance.name);
2355 addP4InfoExternInstance(symbols, SymbolType::P4RT_REGISTER_PARAM(),
"RegisterParam"_cs,
2356 registerParamName, registerParamInstance.annotations,
2357 register_param_, p4Info);
2358 LOG2(
"Added Instance - RegisterParam " << registerParamName);
2363 std::unordered_set<cstring> snapshots;
2365 std::unordered_set<const IR::Block *> hasUserPortMetadata;
2369 std::unordered_map<const IR::ParserBlock *, cstring> ingressIntrinsicMdParamName;
2371 using SnapshotInfoMap = std::map<const IR::ControlBlock *, SnapshotInfo>;
2372 SnapshotInfoMap snapshotInfo;
2374 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
2376 std::map<cstring, ::barefoot::ParserChoices> parserConfiguration;
2381 std::unordered_map<cstring, cstring> registerParam2register;
2383 std::unordered_map<cstring, cstring> registerParam2table;