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") {
1738 BUG_CHECK(ingressIntrinsicMdParamName.count(parserBlock) == 0 ||
1739 ingressIntrinsicMdParamName[parserBlock] == p->name.toString(),
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,
1774 SnapshotInfo{pipeName, gressName, 0u, cstring::empty, {}});
1775 LOG3(
"Adding SnapshotInfo for " << control->getName() <<
" " << gressName
1776 <<
" on pipe " << pipeName);
1789 CHECK_NULL(controlBlock);
1790 auto control = controlBlock->container;
1791 CHECK_NULL(control);
1792 Log::TempIndent indent;
1793 auto sinfoIt = snapshotInfo.find(controlBlock);
1796 if (sinfoIt == snapshotInfo.end())
return;
1797 auto snapshot_name = getFullyQualifiedName(controlBlock, control->externalName());
1798 LOG1(
"Collecting Snapshot for control " << snapshot_name << indent);
1803 if (snapshots.count(snapshot_name)) {
1804 snapshotInfo.erase(sinfoIt);
1807 snapshots.insert(snapshot_name);
1808 sinfoIt->second.name = snapshot_name;
1809 auto snapshotFields = &sinfoIt->second.fields;
1810 auto params = control->getApplyParameters();
1811 for (
size_t idx = 0; idx < params->size(); idx++) {
1812 auto p = params->getParameter(idx);
1815 auto includeValid = (idx == sinfoIt->second.userHdrParamIdx);
1816 SnapshotFieldFinder::find(typeMap, p->type, p->name, includeValid, snapshotFields,
1819 LOG3(
"Adding snaphot to bfrt info for control: " << snapshot_name);
1820 symbols->
add(SymbolType::P4RT_SNAPSHOT(), snapshot_name);
1829 static std::vector<cstring> gressNames = {
"ig"_cs,
"eg"_cs};
1830 int numParsersPerPipe = Device::numParsersPerPipe();
1832 auto main = evaluatedProgram->getMain();
1833 if (!main) ::fatal_error(
"Program does not contain a `main` module");
1834 if (main->type->name !=
"MultiParserSwitch")
return;
1836 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
1837 BUG_CHECK(pkg->type->name ==
"MultiParserPipeline",
1838 "Only MultiParserPipeline pipes can be used with a MultiParserSwitch switch");
1839 for (
auto gressName : gressNames) {
1840 ::barefoot::ParserChoices parserChoices;
1842 if (
auto decl = pkg->node->to<IR::Declaration_Instance>()) pipeName = decl->Name();
1844 parserChoices.set_pipe(pipeName);
1845 if (gressName ==
"ig")
1846 parserChoices.set_direction(::barefoot::DIRECTION_INGRESS);
1848 parserChoices.set_direction(::barefoot::DIRECTION_EGRESS);
1850 auto parsersName = gressName +
"_prsr";
1851 auto parsers = pkg->findParameterValue(parsersName);
1852 BUG_CHECK(parsers && parsers->is<IR::PackageBlock>(),
"Expected PackageBlock");
1853 auto parsersBlock = parsers->to<IR::PackageBlock>();
1854 auto decl = parsersBlock->node->to<IR::Declaration_Instance>();
1855 if (decl) parsersName = decl->controlPlaneName();
1856 for (
int idx = 0; idx < numParsersPerPipe; idx++) {
1857 auto parserName =
"prsr" + std::to_string(idx);
1858 auto parser = parsersBlock->findParameterValue(parserName);
1860 BUG_CHECK(parser->is<IR::ParserBlock>(),
"Expected ParserBlock");
1861 auto parserBlock = parser->to<IR::ParserBlock>();
1862 auto decl = parserBlock->node->to<IR::Declaration_Instance>();
1863 auto userName = (decl ==
nullptr) ? cstring::empty : decl->controlPlaneName();
1865 auto choice = parserChoices.add_choices();
1866 auto parserFullName = prefix(parsersName, parserName);
1867 parserFullName = prefix(pipeName, parserFullName);
1868 choice->set_arch_name(parserFullName);
1869 choice->set_type_name(parserBlock->getName().name);
1870 choice->set_user_name(userName);
1872 auto parsersFullName = prefix(pipeName, parsersName);
1873 symbols->
add(SymbolType::P4RT_PARSER_CHOICES(), parsersFullName);
1874 parserConfiguration.emplace(parsersFullName, parserChoices);
1880 Log::TempIndent indent;
1881 LOG1(
"BFRuntimeArchHandlerTofino::collectExtra" << indent);
1882 LOG2(
"Collecting Parser Symbols" << Log::indent);
1888 if (!block->is<IR::ParserBlock>())
return;
1889 collectParserSymbols(symbols, block->to<IR::ParserBlock>());
1893 LOG2(
"Collecting Snapshot Fields" << Log::indent);
1896 getSnapshotControls();
1899 if (!block->is<IR::ControlBlock>())
return;
1900 collectSnapshot(symbols, block->to<IR::ControlBlock>(), &snapshotFieldIds);
1904 LOG2(
"Collecting Parser Choices" << Log::indent);
1905 collectParserChoices(symbols);
1908 LOG2(
"Collecting PortMetadata" << Log::indent);
1911 forAllPortMetadataBlocks(
1912 evaluatedProgram, [&](
cstring portMetadataFullName,
const IR::ParserBlock *) {
1913 symbols->
add(SymbolType::P4RT_PORT_METADATA(), portMetadataFullName);
1914 LOG3(
"Adding PortMetadata symbol: " << portMetadataFullName);
1920 Log::TempIndent indent;
1921 LOG1(
"BFRuntimeArchHandlerTofino::postCollect" << indent);
1926 if (!block->is<IR::TableBlock>())
return;
1927 auto table = block->to<IR::TableBlock>()->container;
1928 auto implementation = getTableImplementationName(table, refMap);
1929 if (implementation) {
1930 auto pipeName = blockNamePrefixMap[block];
1931 auto implName = prefix(pipeName, *implementation);
1932 actionProfilesRefs[implName].insert(table->controlPlaneName());
1933 LOG5(
"Adding action profile : " << implName <<
" for table "
1934 << table->controlPlaneName());
1941 if (!block->is<IR::ExternBlock>())
return;
1942 auto selectorExternBlock = block->to<IR::ExternBlock>();
1943 if (selectorExternBlock->type->name !=
"ActionSelector")
return;
1944 auto selectorDecl = selectorExternBlock->node->to<IR::Declaration_Instance>();
1945 CHECK_NULL(selectorDecl);
1946 auto profile = selectorExternBlock->getParameterValue(
"action_profile"_cs);
1948 auto profileExternBlock = profile->to<IR::ExternBlock>();
1949 auto profileDecl = profileExternBlock->node->to<IR::Declaration_Instance>();
1950 CHECK_NULL(profileDecl);
1951 auto pipeName = blockNamePrefixMap[selectorExternBlock];
1952 auto profileDeclName = prefix(pipeName, profileDecl->controlPlaneName());
1953 auto selectorDeclName = prefix(pipeName, selectorDecl->controlPlaneName());
1954 actionProfilesRefs[profileDeclName].insert(
1955 actionProfilesRefs[selectorDeclName].begin(),
1956 actionProfilesRefs[selectorDeclName].end());
1957 LOG5(
"Adding action profile : " << profileDeclName <<
" for tables "
1958 << actionProfilesRefs[profileDeclName]);
1967 if (!block->is<IR::ExternBlock>())
return;
1968 auto externBlock = block->to<IR::ExternBlock>();
1969 if (externBlock->type->name !=
"Meter" && externBlock->type->name !=
"DirectMeter")
1971 auto decl = externBlock->node->to<IR::Declaration_Instance>();
1976 auto call = method->expr;
1977 if (call->arguments->size() == 2) {
1978 LOG3(
"Meter " << decl->controlPlaneName() <<
" is color-aware "
1979 <<
"because of 2-argument call to execute()");
1980 colorAwareMeters.insert(decl->controlPlaneName());
1985 class RegisterParamFinder :
public Inspector {
1988 bool checkExtern(
const IR::Declaration_Instance *decl,
cstring name) {
1989 if (
auto *specialized = decl->type->to<IR::Type_Specialized>())
1990 if (
auto *name_type = specialized->baseType->to<IR::Type_Name>())
1991 return name_type->path->name == name;
1997 bool preorder(
const IR::MethodCallExpression *mce)
override {
2000 if (method->
object ==
nullptr)
2002 auto *reg_param = method->
object->
to<IR::Declaration_Instance>();
2003 if (reg_param ==
nullptr)
2005 if (!checkExtern(reg_param,
"RegisterParam"_cs))
return true;
2007 auto *reg_action = findContext<IR::Declaration_Instance>();
2008 if (reg_action ==
nullptr)
return true;
2009 if (!checkExtern(reg_action,
"DirectRegisterAction"_cs) &&
2010 !checkExtern(reg_action,
"RegisterAction"_cs))
2012 BUG_CHECK(reg_action->arguments->size() > 0,
"%1%: Missing argument", reg_action);
2013 auto *rap = reg_action->arguments->at(0)->expression->to<IR::PathExpression>();
2014 if (rap ==
nullptr)
return true;
2017 if (rap_decl ==
nullptr)
return true;
2018 if (checkExtern(rap_decl,
"Register"_cs))
2019 self.registerParam2register[reg_param->controlPlaneName()] =
2020 rap_decl->controlPlaneName();
2021 if (checkExtern(rap_decl,
"DirectRegister"_cs))
2022 self.registerParam2table[reg_param->controlPlaneName()] =
2023 rap_decl->controlPlaneName();
2026 void postorder(
const IR::P4Table *table)
override {
2028 auto *registers = table->properties->getProperty(
"registers"_cs);
2029 if (registers ==
nullptr)
return;
2030 auto *registers_value = registers->value->to<IR::ExpressionValue>();
2031 CHECK_NULL(registers_value);
2032 auto *registers_path = registers_value->expression->to<IR::PathExpression>();
2033 CHECK_NULL(registers_path);
2034 auto *registers_decl =
getDeclInst(self.refMap, registers_path);
2035 CHECK_NULL(registers_decl);
2037 for (
auto r : self.registerParam2table)
2038 if (r.second == registers_decl->controlPlaneName())
2039 self.registerParam2table[r.first] = table->controlPlaneName();
2043 evaluatedProgram->getProgram()->apply(RegisterParamFinder(*
this));
2047 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
2048 CHECK_NULL(tableBlock);
2049 auto tableDeclaration = tableBlock->container;
2050 auto blockPrefix = blockNamePrefixMap[tableBlock];
2052 addTablePropertiesCommon(symbols, p4info, table, tableBlock, blockPrefix);
2054 auto directLpf = getDirectLpf(tableDeclaration, refMap, typeMap);
2057 symbols.
getId(SymbolType::P4RT_DIRECT_LPF(), prefix(blockPrefix, directLpf->name));
2058 table->add_direct_resource_ids(
id);
2059 addLpf(symbols, p4info, *directLpf, blockPrefix);
2062 auto directWred = getDirectWred(tableDeclaration, refMap, typeMap);
2064 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_WRED(),
2065 prefix(blockPrefix, directWred->name));
2066 table->add_direct_resource_ids(
id);
2067 addWred(symbols, p4info, *directWred, blockPrefix);
2074 template <
typename T>
2077 auto directFilterInstance =
2079 if (!directFilterInstance)
return std::nullopt;
2080 CHECK_NULL(directFilterInstance->type);
2081 if (directFilterInstance->type->name != filterType)
return std::nullopt;
2082 return T::fromDirect(*directFilterInstance, table);
2089 return getDirectFilter<Lpf>(table, refMap, typeMap,
"DirectLpf"_cs);
2096 return getDirectFilter<Wred>(table, refMap, typeMap,
"DirectWred"_cs);
2100 const IR::ExternBlock *externBlock)
override {
2101 auto decl = externBlock->node->to<IR::Declaration_Instance>();
2104 if (decl ==
nullptr)
return;
2109 auto pipeName = blockNamePrefixMap[externBlock];
2111 addExternInstanceCommon(symbols, p4info, externBlock, pipeName);
2113 auto p4RtTypeInfo = p4info->mutable_type_info();
2115 if (externBlock->type->name ==
"Lpf") {
2116 auto lpf = Lpf::from(externBlock);
2117 if (lpf) addLpf(symbols, p4info, *lpf, pipeName);
2118 }
else if (externBlock->type->name ==
"Wred") {
2119 auto wred = Wred::from(externBlock);
2120 if (wred) addWred(symbols, p4info, *wred, pipeName);
2121 }
else if (externBlock->type->name ==
"RegisterParam") {
2122 auto register_param_ = RegisterParam::from(externBlock, refMap, typeMap, p4RtTypeInfo);
2123 if (register_param_) addRegisterParam(symbols, p4info, *register_param_, pipeName);
2131 p4configv1::P4Info *p4info,
2133 const IR::ParserBlock *parserBlock) {
2134 auto p4RtTypeInfo = p4info->mutable_type_info();
2135 auto portMetadata = getPortMetadataExtract(externFunction, refMap, typeMap, p4RtTypeInfo);
2137 if (blockNamePrefixMap.count(parserBlock)) {
2138 auto portMetadataFullName =
2139 getFullyQualifiedName(parserBlock, PortMetadata::name(), isMultiParser);
2140 addPortMetadata(symbols, p4info, *portMetadata, portMetadataFullName, parserBlock);
2146 const IR::ParserBlock *parserBlock) {
2147 CHECK_NULL(parserBlock);
2148 auto parser = parserBlock->container;
2151 for (
auto s : parser->parserLocals) {
2152 if (
auto inst = s->to<IR::P4ValueSet>()) {
2154 getFullyQualifiedName(parserBlock, inst->controlPlaneName(),
true);
2156 ValueSet::from(namePrefix, inst, refMap, typeMap, p4info->mutable_type_info());
2157 if (valueSet) addValueSet(symbols, p4info, *valueSet);
2162 for (
auto state : parser->states) {
2164 state, [&](
const IR::MethodCallExpression *call) {
2167 addPortMetadataExternFunction(
2174 ::p4::config::v1::P4Info *p4info)
override {
2182 p4info->clear_value_sets();
2185 if (!block->is<IR::ParserBlock>())
return;
2186 analyzeParser(symbols, p4info, block->to<IR::ParserBlock>());
2191 forAllPortMetadataBlocks(evaluatedProgram, [&](
cstring portMetadataFullName,
2192 const IR::ParserBlock *parserBlock) {
2193 addPortMetadataDefault(symbols, p4info, portMetadataFullName, parserBlock);
2196 for (
const auto &snapshot : snapshotInfo) addSnapshot(symbols, p4info, snapshot.second);
2198 for (
const auto &parser : parserConfiguration)
2199 addParserChoices(symbols, p4info, parser.first, parser.second);
2206 p4configv1::P4TypeInfo *p4RtTypeInfo) {
2207 if (function->method->name != BFN::ExternPortMetadataUnpackString)
return std::nullopt;
2209 if (
auto *call = function->expr->to<IR::MethodCallExpression>()) {
2210 auto *typeArg = call->typeArguments->at(0);
2212 typeArg, p4RtTypeInfo);
2215 return std::nullopt;
2220 const IR::ParserBlock *parserBlock) {
2221 ::barefoot::PortMetadata portMetadata;
2222 portMetadata.mutable_type_spec()->CopyFrom(*portMetadataExtract.typeSpec);
2223 CHECK_NULL(parserBlock);
2224 auto parser = parserBlock->container;
2226 BUG_CHECK(ingressIntrinsicMdParamName.count(parserBlock),
2227 "%1%: Name of the intrinsic metadata not found for this parser block",
2229 portMetadata.set_key_name(ingressIntrinsicMdParamName[parserBlock]);
2230 addP4InfoExternInstance(symbols, SymbolType::P4RT_PORT_METADATA(),
"PortMetadata"_cs, name,
2231 nullptr, portMetadata, p4Info);
2235 p4configv1::P4Info *p4Info,
const cstring &name,
2236 const IR::ParserBlock *parserBlock) {
2237 ::barefoot::PortMetadata portMetadata;
2238 CHECK_NULL(parserBlock);
2239 auto parser = parserBlock->container;
2242 if (ingressIntrinsicMdParamName.count(parserBlock)) {
2243 portMetadata.set_key_name(ingressIntrinsicMdParamName[parserBlock]);
2246 auto const DP0TKN = BFN::getDefaultPhase0TableKeyName();
2247 portMetadata.set_key_name(DP0TKN);
2250 addP4InfoExternInstance(symbols, SymbolType::P4RT_PORT_METADATA(),
"PortMetadata"_cs, name,
2251 nullptr, portMetadata, p4Info);
2255 const SnapshotInfo &snapshotInstance) {
2256 ::barefoot::Snapshot snapshot;
2257 snapshot.set_pipe(snapshotInstance.pipe);
2258 if (snapshotInstance.gress ==
"ingress")
2259 snapshot.set_direction(::barefoot::DIRECTION_INGRESS);
2260 else if (snapshotInstance.gress ==
"egress")
2261 snapshot.set_direction(::barefoot::DIRECTION_EGRESS);
2263 BUG(
"Invalid gress '%1%'", snapshotInstance.gress);
2264 for (
const auto &f : snapshotInstance.fields) {
2265 auto newF = snapshot.add_fields();
2267 newF->set_name(f.name);
2268 newF->set_bitwidth(f.bitwidth);
2270 addP4InfoExternInstance(symbols, SymbolType::P4RT_SNAPSHOT(),
"Snapshot"_cs,
2271 snapshotInstance.name,
nullptr, snapshot, p4Info);
2275 cstring name, const ::barefoot::ParserChoices &parserChoices) {
2276 addP4InfoExternInstance(symbols, SymbolType::P4RT_PARSER_CHOICES(),
"ParserChoices"_cs,
2277 name,
nullptr, parserChoices, p4Info);
2281 const Lpf &lpfInstance,
const cstring pipeName) {
2282 auto lpfName = prefix(pipeName, lpfInstance.name);
2283 if (lpfInstance.table) {
2284 ::barefoot::DirectLpf lpf;
2285 auto tableName = prefix(pipeName, *lpfInstance.table);
2287 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
2288 lpf.set_direct_table_id(tableId);
2289 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_LPF(),
"DirectLpf"_cs, lpfName,
2290 lpfInstance.annotations, lpf, p4Info);
2291 LOG2(
"Added Instance - Direct LPF " << lpfName);
2293 ::barefoot::Lpf lpf;
2294 lpf.set_size(lpfInstance.size);
2295 addP4InfoExternInstance(symbols, SymbolType::P4RT_LPF(),
"Lpf"_cs, lpfName,
2296 lpfInstance.annotations, lpf, p4Info);
2297 LOG2(
"Added Instance - LPF " << lpfName);
2302 template <
typename Kind>
2304 using ::barefoot::WredSpec;
2305 auto wred_spec = wred->mutable_spec();
2306 wred_spec->set_drop_value(wredInstance.dropValue);
2307 wred_spec->set_no_drop_value(wredInstance.noDropValue);
2311 const Wred &wredInstance,
const cstring pipeName) {
2312 auto wredName = prefix(pipeName, wredInstance.name);
2313 if (wredInstance.
table) {
2314 ::barefoot::DirectWred wred;
2315 setWredCommon(&wred, wredInstance);
2316 auto tableName = prefix(pipeName, *wredInstance.
table);
2318 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), tableName);
2319 wred.set_direct_table_id(tableId);
2320 addP4InfoExternInstance(symbols, SymbolType::P4RT_DIRECT_WRED(),
"DirectWred"_cs,
2321 wredName, wredInstance.annotations, wred, p4Info);
2322 LOG2(
"Added Instance - Direct WRED " << wredName);
2324 ::barefoot::Wred wred;
2325 setWredCommon(&wred, wredInstance);
2326 wred.set_size(wredInstance.size);
2327 addP4InfoExternInstance(symbols, SymbolType::P4RT_WRED(),
"Wred"_cs, wredName,
2328 wredInstance.annotations, wred, p4Info);
2329 LOG2(
"Added Instance - WRED " << wredName);
2336 const RegisterParam ®isterParamInstance,
2337 cstring pipeName = cstring::empty) {
2338 p4rt_id_t tableId = 0;
2339 if (registerParam2register.count(registerParamInstance.name) > 0)
2341 symbols.
getId(SymbolType::P4RT_REGISTER(),
2342 prefix(pipeName, registerParam2register[registerParamInstance.name]));
2343 else if (registerParam2table.count(registerParamInstance.name) > 0)
2345 symbols.
getId(P4::ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(),
2346 prefix(pipeName, registerParam2table[registerParamInstance.name]));
2348 ::barefoot::RegisterParam register_param_;
2349 register_param_.mutable_type_spec()->CopyFrom(*registerParamInstance.typeSpec);
2350 register_param_.set_table_id(tableId);
2351 register_param_.set_initial_value(registerParamInstance.initial_value);
2352 register_param_.set_data_field_name(registerParamInstance.name);
2353 auto registerParamName = prefix(pipeName, registerParamInstance.name);
2354 addP4InfoExternInstance(symbols, SymbolType::P4RT_REGISTER_PARAM(),
"RegisterParam"_cs,
2355 registerParamName, registerParamInstance.annotations,
2356 register_param_, p4Info);
2357 LOG2(
"Added Instance - RegisterParam " << registerParamName);
2362 std::unordered_set<cstring> snapshots;
2364 std::unordered_set<const IR::Block *> hasUserPortMetadata;
2368 std::unordered_map<const IR::ParserBlock *, cstring> ingressIntrinsicMdParamName;
2370 using SnapshotInfoMap = std::map<const IR::ControlBlock *, SnapshotInfo>;
2371 SnapshotInfoMap snapshotInfo;
2373 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
2375 std::map<cstring, ::barefoot::ParserChoices> parserConfiguration;
2380 std::unordered_map<cstring, cstring> registerParam2register;
2382 std::unordered_map<cstring, cstring> registerParam2table;