521 using Counter = p4configv1::Counter;
522 using Meter = p4configv1::Meter;
523 using CounterSpec = p4configv1::CounterSpec;
524 using MeterSpec = p4configv1::MeterSpec;
527 const IR::ToplevelBlock *evaluatedProgram)
528 : refMap(refMap), typeMap(typeMap), evaluatedProgram(evaluatedProgram) {
529 jsonPrintOptions.add_whitespace =
true;
533 const IR::TableBlock *tableBlock)
override {
534 CHECK_NULL(tableBlock);
535 auto table = tableBlock->container;
536 bool isConstructedInPlace =
false;
541 refMap, typeMap, &isConstructedInPlace);
546 "Expected an action profile or action selector: %1%",
547 instance->expression);
548 }
else if (isConstructedInPlace) {
549 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), *instance->name);
554 auto instance = getExternInstanceFromProperty(
555 table, CounterTraits::directPropertyName(), refMap, typeMap, &isConstructedInPlace);
557 if (instance->type->name != CounterTraits::directTypeName()) {
558 ::P4::error(ErrorType::ERR_EXPECTED,
"Expected a direct counter: %1%",
559 instance->expression);
560 }
else if (isConstructedInPlace) {
561 symbols->
add(SymbolType::P4RT_DIRECT_COUNTER(), *instance->name);
566 auto instance = getExternInstanceFromProperty(table, MeterTraits::directPropertyName(),
567 refMap, typeMap, &isConstructedInPlace);
569 if (instance->type->name != MeterTraits::directTypeName()) {
570 ::P4::error(ErrorType::ERR_EXPECTED,
"Expected a direct meter: %1%",
571 instance->expression);
572 }
else if (isConstructedInPlace) {
573 symbols->
add(SymbolType::P4RT_DIRECT_METER(), *instance->name);
580 const IR::BaseAssignmentStatement *)
override {}
585 const IR::ExternBlock *externBlock)
override {
586 CHECK_NULL(externBlock);
592 if (decl ==
nullptr)
return;
594 if (externBlock->type->name == CounterTraits::typeName()) {
595 symbols->
add(SymbolType::P4RT_COUNTER(), decl);
596 }
else if (externBlock->type->name == CounterTraits::directTypeName()) {
597 symbols->
add(SymbolType::P4RT_DIRECT_COUNTER(), decl);
598 }
else if (externBlock->type->name == MeterTraits::typeName()) {
599 symbols->
add(SymbolType::P4RT_METER(), decl);
600 }
else if (externBlock->type->name == MeterTraits::directTypeName()) {
601 symbols->
add(SymbolType::P4RT_DIRECT_METER(), decl);
604 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), decl);
606 symbols->
add(SymbolType::P4RT_REGISTER(), decl);
614 (void)externFunction;
627 if (!block->is<IR::TableBlock>())
return;
628 auto table = block->to<IR::TableBlock>()->container;
629 auto implementation = getTableImplementationName(table, refMap);
631 actionProfilesRefs[*implementation].insert(table->controlPlaneName());
636 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
637 CHECK_NULL(tableBlock);
638 auto tableDeclaration = tableBlock->container;
642 auto implementation = getActionProfile(tableDeclaration, refMap, typeMap);
648 if (implementation) {
649 auto id = symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), implementation->name);
650 table->set_implementation_id(
id);
652 if (isExternPropertyConstructedInPlace(tableDeclaration, propertyName))
653 addActionProfile(symbols, p4info, *implementation);
657 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_COUNTER(), directCounter->name);
658 table->add_direct_resource_ids(
id);
660 addCounter(symbols, p4info, *directCounter);
664 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_METER(), directMeter->name);
665 table->add_direct_resource_ids(
id);
667 addMeter(symbols, p4info, *directMeter);
671 void addExternInstance(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
672 const IR::ExternBlock *externBlock)
override {
673 auto decl = externBlock->node->to<IR::Declaration_Instance>();
674 if (decl ==
nullptr)
return;
676 auto p4RtTypeInfo = p4info->mutable_type_info();
677 if (externBlock->type->name == CounterTraits::typeName()) {
679 typeMap, p4RtTypeInfo);
680 if (counter) addCounter(symbols, p4info, *counter);
681 }
else if (externBlock->type->name == MeterTraits::typeName()) {
684 if (meter) addMeter(symbols, p4info, *meter);
685 }
else if (externBlock->type->name == RegisterTraits<arch>::typeName()) {
687 if (register_) addRegister(symbols, p4info, *register_);
688 }
else if (externBlock->type->name == ActionProfileTraits<arch>::typeName() ||
689 externBlock->type->name == ActionSelectorTraits<arch>::typeName()) {
690 auto actionProfile = getActionProfile(externBlock);
691 if (actionProfile) addActionProfile(symbols, p4info, *actionProfile);
695 void addExternFunction(
const P4RuntimeSymbolTableIface &, p4configv1::P4Info *,
696 const P4::ExternFunction *)
override {}
701 const IR::ExternBlock *)
override {}
705 return jsonPrintOptions;
708 static std::optional<ActionProfile> getActionProfile(
cstring name,
const IR::Type_Extern *type,
710 const IR::IAnnotated *annotations) {
713 actionProfileType = ActionProfileType::INDIRECT_WITH_SELECTOR;
714 }
else if (type->name == ActionProfileTraits<arch>::typeName()) {
715 actionProfileType = ActionProfileType::INDIRECT;
720 return ActionProfile{name, actionProfileType, size, annotations};
728 auto instance = getExternInstanceFromProperty(table, propertyName, refMap, typeMap);
729 if (!instance)
return std::nullopt;
732 if (!size->template is<IR::Constant>()) {
733 ::P4::error(ErrorType::ERR_INVALID,
"Action profile '%1%' has non-constant size '%2%'",
734 *instance->name, size);
737 return getActionProfile(*instance->name, instance->type,
738 size->template to<IR::Constant>()->asInt(),
739 getTableImplementationAnnotations(table, refMap));
746 if (!size->template is<IR::Constant>()) {
747 ::P4::error(ErrorType::ERR_INVALID,
"Action profile '%1%' has non-constant size '%2%'",
748 decl->controlPlaneName(), size);
751 return getActionProfile(decl->controlPlaneName(), instance->type,
752 size->template to<IR::Constant>()->asInt(),
753 decl->
to<IR::IAnnotated>());
758 auto profile = p4Info->add_action_profiles();
759 auto id = symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), actionProfile.name);
760 setPreamble(profile->mutable_preamble(),
id, actionProfile.name,
761 symbols.
getAlias(actionProfile.name), actionProfile.annotations,
765 return name ==
"max_group_size" || name ==
"selector_size_semantics" ||
766 name ==
"max_member_weight";
768 profile->set_with_selector(actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR);
769 profile->set_size(actionProfile.size);
770 auto maxGroupSizeAnnotation = actionProfile.annotations->getAnnotation(
"max_group_size"_cs);
771 if (maxGroupSizeAnnotation) {
772 if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) {
773 auto maxGroupSizeConstant =
774 maxGroupSizeAnnotation->getExpr(0)->checkedTo<IR::Constant>();
775 CHECK_NULL(maxGroupSizeConstant);
776 profile->set_max_group_size(maxGroupSizeConstant->asInt());
779 "Ignoring annotation @max_group_size on action profile '%1%', "
780 "which does not have a selector",
781 actionProfile.annotations);
786 auto selectorSizeSemanticsAnnotation =
787 actionProfile.annotations->getAnnotation(
"selector_size_semantics"_cs);
788 if (selectorSizeSemanticsAnnotation) {
789 if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) {
790 auto selectorSizeSemantics =
791 selectorSizeSemanticsAnnotation->getExpr(0)->checkedTo<IR::StringLiteral>();
792 CHECK_NULL(selectorSizeSemantics);
795 if (selectorSizeSemantics->value.toUpper() ==
"SUM_OF_WEIGHTS") {
796 profile->mutable_sum_of_weights();
797 }
else if (selectorSizeSemantics->value.toUpper() ==
"SUM_OF_MEMBERS") {
798 profile->mutable_sum_of_members();
801 "Expected selector_size_semantics value \"sum_of_weights\" or "
802 "\"sum_of_members\", but got '%1%'",
803 selectorSizeSemantics);
807 "Ignoring annotation @selector_size_semantics on action "
808 "profile '%1%', which does not have a selector ",
809 actionProfile.annotations);
814 auto maxMemberWeightAnnotation =
815 actionProfile.annotations->getAnnotation(
"max_member_weight"_cs);
816 if (maxMemberWeightAnnotation) {
817 if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR &&
818 profile->has_sum_of_members()) {
819 auto maxMemberWeightConstant =
820 maxMemberWeightAnnotation->getExpr(0)->checkedTo<IR::Constant>();
821 CHECK_NULL(maxMemberWeightConstant);
822 profile->mutable_sum_of_members()->set_max_member_weight(
823 maxMemberWeightConstant->asInt());
824 }
else if (actionProfile.type != ActionProfileType::INDIRECT_WITH_SELECTOR) {
826 "Ignoring annotation @max_member_weight on action profile "
827 "'%1%', which does not have a selector",
828 actionProfile.annotations);
831 "Ignoring annotation @max_member_weight on action profile '%1%', "
832 "which does not use 'sum_of_members' as its SelectorSizeSemantics",
833 actionProfile.annotations);
837 auto tablesIt = actionProfilesRefs.find(actionProfile.name);
838 if (tablesIt != actionProfilesRefs.end()) {
839 for (
const auto &table : tablesIt->second)
840 profile->add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
845 template <
typename Kind>
848 setPreamble(counter->mutable_preamble(),
id, counterInstance.
name,
850 auto counter_spec = counter->mutable_spec();
851 counter_spec->set_unit(CounterTraits::mapUnitName(counterInstance.
unit));
856 if (counterInstance.
table) {
857 auto counter = p4Info->add_direct_counters();
858 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_COUNTER(), counterInstance.
name);
860 auto tableId = symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), *counterInstance.
table);
861 counter->set_direct_table_id(tableId);
863 auto counter = p4Info->add_counters();
864 auto id = symbols.
getId(SymbolType::P4RT_COUNTER(), counterInstance.
name);
866 counter->set_size(counterInstance.
size);
868 counter->mutable_index_type_name()->set_name(counterInstance.
index_type_name);
874 template <
typename Kind>
877 setPreamble(meter->mutable_preamble(),
id, meterInstance.
name,
879 auto meter_spec = meter->mutable_spec();
880 meter_spec->set_unit(MeterTraits::mapUnitName(meterInstance.
unit));
885 if (meterInstance.
table) {
886 auto meter = p4Info->add_direct_meters();
887 auto id = symbols.
getId(SymbolType::P4RT_DIRECT_METER(), meterInstance.
name);
889 auto tableId = symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), *meterInstance.
table);
890 meter->set_direct_table_id(tableId);
892 auto meter = p4Info->add_meters();
893 auto id = symbols.
getId(SymbolType::P4RT_METER(), meterInstance.
name);
895 meter->set_size(meterInstance.
size);
897 meter->mutable_index_type_name()->set_name(meterInstance.
index_type_name);
902 void addRegister(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4Info,
903 const Register ®isterInstance) {
904 auto register_ = p4Info->add_registers();
905 auto id = symbols.
getId(SymbolType::P4RT_REGISTER(), registerInstance.name);
906 setPreamble(register_->mutable_preamble(),
id, registerInstance.name,
907 symbols.
getAlias(registerInstance.name), registerInstance.annotations);
908 register_->set_size(registerInstance.size);
909 register_->mutable_type_spec()->CopyFrom(*registerInstance.typeSpec);
910 if (registerInstance.index_type_name) {
911 register_->mutable_index_type_name()->set_name(registerInstance.index_type_name);
915 void addDigest(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4Info,
916 const Digest &digest) {
921 auto id = symbols.
getId(SymbolType::P4RT_DIGEST(), digest.name);
925 auto *digestInstance = p4Info->add_digests();
926 setPreamble(digestInstance->mutable_preamble(),
id, digest.name,
927 symbols.
getAlias(digest.name), digest.annotations);
928 digestInstance->mutable_type_spec()->CopyFrom(*digest.typeSpec);
937 static const IR::IAnnotated *getTableImplementationAnnotations(
const IR::P4Table *table,
943 if (impl ==
nullptr)
return nullptr;
944 if (!impl->value->is<IR::ExpressionValue>())
return nullptr;
945 auto expr = impl->value->to<IR::ExpressionValue>()->expression;
946 if (expr->is<IR::ConstructorCallExpression>())
return impl->to<IR::IAnnotated>();
947 if (expr->is<IR::PathExpression>()) {
948 auto decl = refMap->
getDeclaration(expr->to<IR::PathExpression>()->path,
true);
949 return decl->
to<IR::IAnnotated>();
954 static std::optional<cstring> getTableImplementationName(
const IR::P4Table *table,
957 if (impl ==
nullptr)
return std::nullopt;
958 if (!impl->value->is<IR::ExpressionValue>()) {
960 ErrorType::ERR_EXPECTED,
961 "Expected implementation property value for table %1% to be an expression: %2%",
962 table->controlPlaneName(), impl);
965 auto expr = impl->value->to<IR::ExpressionValue>()->expression;
966 if (expr->is<IR::ConstructorCallExpression>())
return impl->controlPlaneName();
967 if (expr->is<IR::PathExpression>()) {
968 auto decl = refMap->
getDeclaration(expr->to<IR::PathExpression>()->path,
true);
969 return decl->controlPlaneName();
974 ReferenceMap *refMap;
976 const IR::ToplevelBlock *evaluatedProgram;
978 std::unordered_map<cstring, std::set<cstring>> actionProfilesRefs;
984 google::protobuf::util::JsonPrintOptions jsonPrintOptions;