530 using Counter = p4configv1::Counter;
531 using Meter = p4configv1::Meter;
532 using CounterSpec = p4configv1::CounterSpec;
533 using MeterSpec = p4configv1::MeterSpec;
536 const IR::ToplevelBlock *evaluatedProgram)
537 : refMap(refMap), typeMap(typeMap), evaluatedProgram(evaluatedProgram) {
538 jsonPrintOptions.add_whitespace =
true;
542 const IR::TableBlock *tableBlock)
override {
543 CHECK_NULL(tableBlock);
544 auto table = tableBlock->container;
545 bool isConstructedInPlace =
false;
550 refMap, typeMap, &isConstructedInPlace);
555 "Expected an action profile or action selector: %1%",
556 instance->expression);
557 }
else if (isConstructedInPlace) {
558 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), *instance->name);
563 auto instance = getExternInstanceFromProperty(
564 table, CounterTraits::directPropertyName(), refMap, typeMap, &isConstructedInPlace);
566 if (instance->type->name != CounterTraits::directTypeName()) {
567 ::P4::error(ErrorType::ERR_EXPECTED,
"Expected a direct counter: %1%",
568 instance->expression);
569 }
else if (isConstructedInPlace) {
570 symbols->
add(SymbolType::P4RT_DIRECT_COUNTER(), *instance->name);
575 auto instance = getExternInstanceFromProperty(table, MeterTraits::directPropertyName(),
576 refMap, typeMap, &isConstructedInPlace);
578 if (instance->type->name != MeterTraits::directTypeName()) {
579 ::P4::error(ErrorType::ERR_EXPECTED,
"Expected a direct meter: %1%",
580 instance->expression);
581 }
else if (isConstructedInPlace) {
582 symbols->
add(SymbolType::P4RT_DIRECT_METER(), *instance->name);
589 const IR::AssignmentStatement *)
override {}
594 const IR::ExternBlock *externBlock)
override {
595 CHECK_NULL(externBlock);
601 if (decl ==
nullptr)
return;
603 if (externBlock->type->name == CounterTraits::typeName()) {
604 symbols->
add(SymbolType::P4RT_COUNTER(), decl);
605 }
else if (externBlock->type->name == CounterTraits::directTypeName()) {
606 symbols->
add(SymbolType::P4RT_DIRECT_COUNTER(), decl);
607 }
else if (externBlock->type->name == MeterTraits::typeName()) {
608 symbols->
add(SymbolType::P4RT_METER(), decl);
609 }
else if (externBlock->type->name == MeterTraits::directTypeName()) {
610 symbols->
add(SymbolType::P4RT_DIRECT_METER(), decl);
613 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), decl);
615 symbols->
add(SymbolType::P4RT_REGISTER(), decl);
623 (void)externFunction;
636 if (!block->is<IR::TableBlock>())
return;
637 auto table = block->to<IR::TableBlock>()->container;
638 auto implementation = getTableImplementationName(table, refMap);
640 actionProfilesRefs[*implementation].insert(table->controlPlaneName());
645 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
646 CHECK_NULL(tableBlock);
647 auto tableDeclaration = tableBlock->container;
651 auto implementation = getActionProfile(tableDeclaration, refMap, typeMap);
657 if (implementation) {
658 auto id = symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), implementation->name);
659 table->set_implementation_id(
id);
661 if (isExternPropertyConstructedInPlace(tableDeclaration, propertyName))
662 addActionProfile(symbols, p4info, *implementation);
666 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_COUNTER(), directCounter->name);
667 table->add_direct_resource_ids(
id);
669 addCounter(symbols, p4info, *directCounter);
673 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_METER(), directMeter->name);
674 table->add_direct_resource_ids(
id);
676 addMeter(symbols, p4info, *directMeter);
680 void addExternInstance(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
681 const IR::ExternBlock *externBlock)
override {
682 auto decl = externBlock->node->to<IR::Declaration_Instance>();
683 if (decl ==
nullptr)
return;
685 auto p4RtTypeInfo = p4info->mutable_type_info();
686 if (externBlock->type->name == CounterTraits::typeName()) {
688 typeMap, p4RtTypeInfo);
689 if (counter) addCounter(symbols, p4info, *counter);
690 }
else if (externBlock->type->name == MeterTraits::typeName()) {
693 if (meter) addMeter(symbols, p4info, *meter);
694 }
else if (externBlock->type->name == RegisterTraits<arch>::typeName()) {
696 if (register_) addRegister(symbols, p4info, *register_);
697 }
else if (externBlock->type->name == ActionProfileTraits<arch>::typeName() ||
698 externBlock->type->name == ActionSelectorTraits<arch>::typeName()) {
699 auto actionProfile = getActionProfile(externBlock);
700 if (actionProfile) addActionProfile(symbols, p4info, *actionProfile);
704 void addExternFunction(
const P4RuntimeSymbolTableIface &, p4configv1::P4Info *,
710 const IR::ExternBlock *)
override {}
714 return jsonPrintOptions;
717 static std::optional<ActionProfile> getActionProfile(
cstring name,
const IR::Type_Extern *type,
719 const IR::IAnnotated *annotations) {
722 actionProfileType = ActionProfileType::INDIRECT_WITH_SELECTOR;
723 }
else if (type->name == ActionProfileTraits<arch>::typeName()) {
724 actionProfileType = ActionProfileType::INDIRECT;
729 return ActionProfile{name, actionProfileType, size, annotations};
737 auto instance = getExternInstanceFromProperty(table, propertyName, refMap, typeMap);
738 if (!instance)
return std::nullopt;
741 if (!size->template is<IR::Constant>()) {
742 ::P4::error(ErrorType::ERR_INVALID,
"Action profile '%1%' has non-constant size '%2%'",
743 *instance->name, size);
746 return getActionProfile(*instance->name, instance->type,
747 size->template to<IR::Constant>()->asInt(),
748 getTableImplementationAnnotations(table, refMap));
755 if (!size->template is<IR::Constant>()) {
756 ::P4::error(ErrorType::ERR_INVALID,
"Action profile '%1%' has non-constant size '%2%'",
757 decl->controlPlaneName(), size);
760 return getActionProfile(decl->controlPlaneName(), instance->type,
761 size->template to<IR::Constant>()->asInt(),
762 decl->
to<IR::IAnnotated>());
767 auto profile = p4Info->add_action_profiles();
768 auto id = symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), actionProfile.name);
769 setPreamble(profile->mutable_preamble(),
id, actionProfile.name,
770 symbols.
getAlias(actionProfile.name), actionProfile.annotations,
774 return name ==
"max_group_size" || name ==
"selector_size_semantics" ||
775 name ==
"max_member_weight";
777 profile->set_with_selector(actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR);
778 profile->set_size(actionProfile.size);
779 auto maxGroupSizeAnnotation = actionProfile.annotations->getAnnotation(
"max_group_size"_cs);
780 if (maxGroupSizeAnnotation) {
781 if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) {
782 auto maxGroupSizeConstant =
783 maxGroupSizeAnnotation->getExpr(0)->checkedTo<IR::Constant>();
784 CHECK_NULL(maxGroupSizeConstant);
785 profile->set_max_group_size(maxGroupSizeConstant->asInt());
788 "Ignoring annotation @max_group_size on action profile '%1%', "
789 "which does not have a selector",
790 actionProfile.annotations);
795 auto selectorSizeSemanticsAnnotation =
796 actionProfile.annotations->getAnnotation(
"selector_size_semantics"_cs);
797 if (selectorSizeSemanticsAnnotation) {
798 if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) {
799 auto selectorSizeSemantics =
800 selectorSizeSemanticsAnnotation->getExpr(0)->checkedTo<IR::StringLiteral>();
801 CHECK_NULL(selectorSizeSemantics);
804 if (selectorSizeSemantics->value.toUpper() ==
"SUM_OF_WEIGHTS") {
805 profile->mutable_sum_of_weights();
806 }
else if (selectorSizeSemantics->value.toUpper() ==
"SUM_OF_MEMBERS") {
807 profile->mutable_sum_of_members();
810 "Expected selector_size_semantics value \"sum_of_weights\" or "
811 "\"sum_of_members\", but got '%1%'",
812 selectorSizeSemantics);
816 "Ignoring annotation @selector_size_semantics on action "
817 "profile '%1%', which does not have a selector ",
818 actionProfile.annotations);
823 auto maxMemberWeightAnnotation =
824 actionProfile.annotations->getAnnotation(
"max_member_weight"_cs);
825 if (maxMemberWeightAnnotation) {
826 if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR &&
827 profile->has_sum_of_members()) {
828 auto maxMemberWeightConstant =
829 maxMemberWeightAnnotation->getExpr(0)->checkedTo<IR::Constant>();
830 CHECK_NULL(maxMemberWeightConstant);
831 profile->mutable_sum_of_members()->set_max_member_weight(
832 maxMemberWeightConstant->asInt());
833 }
else if (actionProfile.type != ActionProfileType::INDIRECT_WITH_SELECTOR) {
835 "Ignoring annotation @max_member_weight on action profile "
836 "'%1%', which does not have a selector",
837 actionProfile.annotations);
840 "Ignoring annotation @max_member_weight on action profile '%1%', "
841 "which does not use 'sum_of_members' as its SelectorSizeSemantics",
842 actionProfile.annotations);
846 auto tablesIt = actionProfilesRefs.find(actionProfile.name);
847 if (tablesIt != actionProfilesRefs.end()) {
848 for (
const auto &table : tablesIt->second)
849 profile->add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
854 template <
typename Kind>
857 setPreamble(counter->mutable_preamble(),
id, counterInstance.
name,
859 auto counter_spec = counter->mutable_spec();
860 counter_spec->set_unit(CounterTraits::mapUnitName(counterInstance.
unit));
865 if (counterInstance.
table) {
866 auto counter = p4Info->add_direct_counters();
867 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_COUNTER(), counterInstance.
name);
869 auto tableId = symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), *counterInstance.
table);
870 counter->set_direct_table_id(tableId);
872 auto counter = p4Info->add_counters();
873 auto id = symbols.
getId(SymbolType::P4RT_COUNTER(), counterInstance.
name);
875 counter->set_size(counterInstance.
size);
877 counter->mutable_index_type_name()->set_name(counterInstance.
index_type_name);
883 template <
typename Kind>
886 setPreamble(meter->mutable_preamble(),
id, meterInstance.
name,
888 auto meter_spec = meter->mutable_spec();
889 meter_spec->set_unit(MeterTraits::mapUnitName(meterInstance.
unit));
894 if (meterInstance.
table) {
895 auto meter = p4Info->add_direct_meters();
896 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_METER(), meterInstance.
name);
898 auto tableId = symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), *meterInstance.
table);
899 meter->set_direct_table_id(tableId);
901 auto meter = p4Info->add_meters();
902 auto id = symbols.
getId(SymbolType::P4RT_METER(), meterInstance.
name);
904 meter->set_size(meterInstance.
size);
906 meter->mutable_index_type_name()->set_name(meterInstance.
index_type_name);
911 void addRegister(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4Info,
912 const Register ®isterInstance) {
913 auto register_ = p4Info->add_registers();
914 auto id = symbols.getId(SymbolType::P4RT_REGISTER(), registerInstance.name);
915 setPreamble(register_->mutable_preamble(),
id, registerInstance.name,
916 symbols.getAlias(registerInstance.name), registerInstance.annotations);
917 register_->set_size(registerInstance.size);
918 register_->mutable_type_spec()->CopyFrom(*registerInstance.typeSpec);
919 if (registerInstance.index_type_name) {
920 register_->mutable_index_type_name()->set_name(registerInstance.index_type_name);
924 void addDigest(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4Info,
925 const Digest &digest) {
930 auto id = symbols.getId(SymbolType::P4RT_DIGEST(), digest.name);
934 auto *digestInstance = p4Info->add_digests();
935 setPreamble(digestInstance->mutable_preamble(),
id, digest.name,
936 symbols.getAlias(digest.name), digest.annotations);
937 digestInstance->mutable_type_spec()->CopyFrom(*digest.typeSpec);
946 static const IR::IAnnotated *getTableImplementationAnnotations(
const IR::P4Table *table,
952 if (impl ==
nullptr)
return nullptr;
953 if (!impl->value->is<IR::ExpressionValue>())
return nullptr;
954 auto expr = impl->value->to<IR::ExpressionValue>()->expression;
955 if (expr->is<IR::ConstructorCallExpression>())
return impl->to<IR::IAnnotated>();
956 if (expr->is<IR::PathExpression>()) {
957 auto decl = refMap->
getDeclaration(expr->to<IR::PathExpression>()->path,
true);
958 return decl->
to<IR::IAnnotated>();
963 static std::optional<cstring> getTableImplementationName(
const IR::P4Table *table,
966 if (impl ==
nullptr)
return std::nullopt;
967 if (!impl->value->is<IR::ExpressionValue>()) {
969 ErrorType::ERR_EXPECTED,
970 "Expected implementation property value for table %1% to be an expression: %2%",
971 table->controlPlaneName(), impl);
974 auto expr = impl->value->to<IR::ExpressionValue>()->expression;
975 if (expr->is<IR::ConstructorCallExpression>())
return impl->controlPlaneName();
976 if (expr->is<IR::PathExpression>()) {
977 auto decl = refMap->
getDeclaration(expr->to<IR::PathExpression>()->path,
true);
978 return decl->controlPlaneName();
983 ReferenceMap *refMap;
985 const IR::ToplevelBlock *evaluatedProgram;
987 std::unordered_map<cstring, std::set<cstring>> actionProfilesRefs;
993 google::protobuf::util::JsonPrintOptions jsonPrintOptions;