47 auto table = node->table;
48 LOG3(
"Processing " << dbp(table));
50 cstring name = table->controlPlaneName();
51 result->emplace(
"name", name);
52 result->emplace(
"id", nextId(
"tables"_cs));
53 result->emplace_non_null(
"source_info"_cs, table->sourceInfoJsonObj());
54 cstring table_match_type = corelib.exactMatch.name;
55 auto key = table->getKey();
56 auto tkey = mkArrayField(result,
"key"_cs);
61 for (
auto ke : key->keyElements) {
62 auto expr = ke->expression;
63 auto ket = ctxt->typeMap->getType(expr,
true);
64 if (!ket->is<IR::Type_Bits>() && !ket->is<IR::Type_Boolean>() &&
65 !ket->is<IR::Type_Error>())
67 "%1%: unsupporded key type %2%. "
68 "Supported key types are be bit<> or boolean, or error.",
71 auto match_type = getKeyMatchType(ke);
79 if (match_type == corelib.lpmMatch.name) count_lpm++;
82 "multiple LPM keys in table %1% not supported", table);
83 if (match_type != table_match_type) {
84 if (match_type == BMV2::MatchImplementation::rangeMatchTypeName)
85 table_match_type = BMV2::MatchImplementation::rangeMatchTypeName;
86 if ((match_type == corelib.ternaryMatch.name ||
87 match_type == BMV2::MatchImplementation::optionalMatchTypeName) &&
88 table_match_type != BMV2::MatchImplementation::rangeMatchTypeName)
89 table_match_type = corelib.ternaryMatch.name;
90 if (match_type == corelib.lpmMatch.name &&
91 table_match_type == corelib.exactMatch.name)
92 table_match_type = corelib.lpmMatch.name;
96 if (
auto mexp = expr->to<IR::BAnd>()) {
97 if (mexp->right->is<IR::Constant>()) {
98 mask = mexp->right->to<IR::Constant>()->value;
100 }
else if (mexp->left->is<IR::Constant>()) {
101 mask = mexp->left->to<IR::Constant>()->value;
104 ::P4::error(ErrorType::ERR_EXPECTED,
"%1% must be a constant", expr);
106 }
else if (
auto slice = expr->to<IR::Slice>()) {
108 int h = slice->getH();
109 int l = slice->getL();
110 mask = Util::maskFromSlice(h, l);
117 if (match_type == BMV2::MatchImplementation::optionalMatchTypeName) {
118 keyelement->emplace(
"match_type", corelib.ternaryMatch.name);
120 keyelement->emplace(
"match_type", match_type);
122 if (
auto na = ke->getAnnotation(IR::Annotation::nameAnnotation)) {
123 BUG_CHECK(na->expr.size() == 1,
"%1%: expected 1 name", na);
124 auto name = na->expr[0]->to<IR::StringLiteral>();
125 BUG_CHECK(name !=
nullptr,
"%1%: expected a string", na);
128 keyelement->emplace(
"name", name->value);
134 keyelement->emplace(
"mask",
135 stringRepr(mask, ROUNDUP(expr->type->width_bits(), 8)));
137 keyelement->emplace(
"mask", Util::JsonValue::null);
138 tkey->append(keyelement);
141 LOG3(
"table_match_type: " << table_match_type);
142 result->emplace(
"match_type", table_match_type);
146 auto impl = table->properties->getProperty(propertyName);
150 auto sz = table->properties->getProperty(
"size");
152 if (sz->value->is<IR::ExpressionValue>()) {
153 auto expr = sz->value->to<IR::ExpressionValue>()->expression;
154 if (!expr->is<IR::Constant>()) {
155 ::P4::error(ErrorType::ERR_EXPECTED,
"%1% must be a constant", sz);
158 size = expr->to<IR::Constant>()->asInt();
161 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected a number", sz);
164 if (
auto entries = table->getEntries()) {
165 size = entries->entries.size();
167 if (size == 0) size = BMV2::TableAttributes::defaultTableSize;
169 result->emplace(
"max_size", size);
170 auto ctrs = table->properties->getProperty(
"counters");
171 if (ctrs !=
nullptr) {
175 if (ctrs->value->is<IR::ExpressionValue>()) {
176 auto expr = ctrs->value->to<IR::ExpressionValue>()->expression;
177 if (expr->is<IR::ConstructorCallExpression>()) {
178 auto type = ctxt->typeMap->getType(expr,
true);
179 if (type ==
nullptr)
return result;
180 if (!type->is<IR::Type_Extern>()) {
182 "%1%: Unexpected type %2% for property. "
187 auto te = type->to<IR::Type_Extern>();
188 if (te->name !=
"direct_counter" && te->name !=
"counter") {
190 "%1%: Unexpected type %2% for property. "
191 "Must be 'counter' or 'direct_counter'.",
196 cstring ctrname = ctrs->controlPlaneName(
"counter"_cs);
197 jctr->emplace(
"name", ctrname);
198 jctr->emplace(
"id", nextId(
"counter_arrays"_cs));
199 jctr->emplace_non_null(
"source_info"_cs, ctrs->sourceInfoJsonObj());
202 bool direct = te->name ==
"direct_counter";
203 jctr->emplace(
"is_direct", direct);
204 jctr->emplace(
"binding", table->controlPlaneName());
205 ctxt->
json->counters->append(jctr);
206 }
else if (expr->is<IR::PathExpression>()) {
207 auto pe = expr->to<IR::PathExpression>();
209 if (!decl->is<IR::Declaration_Instance>()) {
210 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected an instance",
214 cstring ctrname = decl->controlPlaneName();
216 LOG3(
"Looking up " << ctrname);
219 "%1%: Direct counters cannot be attached to multiple tables"
221 decl, it->second, table);
226 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected a counter", ctrs);
229 result->emplace(
"with_counters",
true);
231 result->emplace(
"with_counters",
false);
235 auto timeout = table->properties->getProperty(
"support_timeout");
236 if (timeout !=
nullptr) {
237 if (timeout->value->is<IR::ExpressionValue>()) {
238 auto expr = timeout->value->to<IR::ExpressionValue>()->expression;
239 if (!expr->is<IR::BoolLiteral>()) {
240 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: must true/false", timeout);
242 sup_to = expr->to<IR::BoolLiteral>()->value;
245 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected a Boolean", timeout);
248 result->emplace(
"support_timeout", sup_to);
250 auto dm = table->properties->getProperty(
"meters");
252 if (dm->value->is<IR::ExpressionValue>()) {
253 auto expr = dm->value->to<IR::ExpressionValue>()->expression;
254 if (!expr->is<IR::PathExpression>()) {
256 "%1%: expected a reference to a meter declaration", expr);
258 auto pe = expr->to<IR::PathExpression>();
260 auto type = ctxt->typeMap->getType(expr,
true);
261 if (type ==
nullptr)
return result;
262 if (type->is<IR::Type_SpecializedCanonical>())
263 type = type->to<IR::Type_SpecializedCanonical>()->baseType;
264 if (!type->is<IR::Type_Extern>()) {
266 "%1%: Unexpected type %2% for property", dm, type);
269 auto te = type->to<IR::Type_Extern>();
270 if (te->name !=
"direct_meter") {
272 "%1%: Unexpected type %2% for property", dm, type);
275 if (!decl->is<IR::Declaration_Instance>()) {
276 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected an instance",
282 BUG_CHECK(decl->is<IR::Declaration_Instance>(),
"%1%: expected an instance",
284 cstring name = decl->controlPlaneName();
285 result->emplace(
"direct_meters", name);
288 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected a meter", dm);
291 result->emplace(
"direct_meters", Util::JsonValue::null);
294 auto action_ids = mkArrayField(result,
"action_ids"_cs);
295 auto actions = mkArrayField(result,
"actions"_cs);
296 auto al = table->getActionList();
298 std::map<cstring, cstring> useActionName;
299 for (
auto a : al->actionList) {
300 if (a->expression->is<IR::MethodCallExpression>()) {
301 auto mce = a->expression->to<IR::MethodCallExpression>();
302 if (mce->arguments->size() > 0)
304 "%1%: actions in action list with arguments not supported", a);
307 BUG_CHECK(decl->is<IR::P4Action>(),
"%1%: should be an action name", a);
308 auto action = decl->to<IR::P4Action>();
309 unsigned id = get(ctxt->
structure->
ids, action, INVALID_ACTION_ID);
310 LOG3(
"look up id " << action <<
" " <<
id);
311 BUG_CHECK(
id != INVALID_ACTION_ID,
"Could not find id for %1%", action);
312 action_ids->append(
id);
313 auto name = action->controlPlaneName();
314 actions->append(name);
315 useActionName.emplace(action->name, name);
321 CFG::Node *defaultLabelDestination =
nullptr;
323 bool hitMiss =
false;
324 for (
auto s : node->successors.edges) {
325 if (s->isUnconditional()) {
326 nextDestination = s->endpoint;
327 LOG3(
"nextDestination " << s->endpoint);
328 }
else if (s->isBool()) {
331 }
else if (s->label ==
"default") {
332 defaultLabelDestination = s->endpoint;
333 LOG3(
"default " << s->endpoint);
339 BUG_CHECK(nextDestination,
"Could not find default destination for %1%",
341 nextLabel = nodeName(nextDestination);
342 result->emplace(
"base_default_next", nextLabel);
345 if (defaultLabelDestination !=
nullptr) nextLabel = nodeName(defaultLabelDestination);
347 result->emplace(
"base_default_next", Util::JsonValue::null);
350 std::set<cstring> labelsDone;
351 for (
auto s : node->successors.edges) {
354 label = s->getBool() ?
"__HIT__"_cs :
"__MISS__"_cs;
355 }
else if (s->isUnconditional()) {
359 if (label ==
"default")
continue;
360 label = ::P4::get(useActionName, label);
362 next_tables->emplace(label, nodeName(s->endpoint));
363 labelsDone.emplace(label);
369 for (
auto a : al->actionList) {
370 cstring name = a->getName().name;
371 cstring label = ::P4::get(useActionName, name);
372 if (labelsDone.find(label) == labelsDone.end())
373 next_tables->emplace(label, nextLabel);
377 result->emplace(
"next_tables", next_tables);
379 table->properties->getProperty(IR::TableProperties::defaultActionPropertyName);
380 if (defact !=
nullptr) {
383 ErrorType::WARN_UNSUPPORTED,
384 "Target does not support default_action for %1% (due to action profiles)",
389 if (!defact->value->is<IR::ExpressionValue>()) {
390 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected an action", defact);
393 auto expr = defact->value->to<IR::ExpressionValue>()->expression;
394 const IR::P4Action *action =
nullptr;
397 if (expr->is<IR::PathExpression>()) {
398 auto path = expr->to<IR::PathExpression>()->path;
400 BUG_CHECK(decl->is<IR::P4Action>(),
"%1%: should be an action name", expr);
401 action = decl->to<IR::P4Action>();
402 }
else if (expr->is<IR::MethodCallExpression>()) {
403 auto mce = expr->to<IR::MethodCallExpression>();
405 BUG_CHECK(mi->is<
P4::ActionCall>(),
"%1%: expected an action", expr);
407 args = mce->arguments;
409 BUG(
"%1%: unexpected expression", expr);
412 unsigned actionid = get(ctxt->
structure->
ids, action, INVALID_ACTION_ID);
413 BUG_CHECK(actionid != INVALID_ACTION_ID,
"Could not find id for %1%", action);
415 entry->emplace(
"action_id", actionid);
416 entry->emplace(
"action_const", defact->isConstant);
417 auto fields = mkArrayField(entry,
"action_data"_cs);
418 if (args !=
nullptr) {
420 for (
auto a : *args) {
421 if (a->expression->is<IR::Constant>()) {
422 cstring repr = stringRepr(a->expression->to<IR::Constant>()->value);
423 fields->append(repr);
426 "%1%: argument must evaluate to a constant integer", a);
431 entry->emplace(
"action_entry_const", defact->isConstant);
432 result->emplace(
"default_entry", entry);
434 convertTableEntries(table, result);
437 void convertTableEntries(
const IR::P4Table *table,
Util::JsonObject *jsonTable) {
438 auto entriesList = table->getEntries();
439 if (entriesList ==
nullptr)
return;
441 auto entries = mkArrayField(jsonTable,
"entries"_cs);
442 int entryPriority = 1;
443 for (
auto e : entriesList->entries) {
445 entry->emplace_non_null(
"source_info"_cs, e->sourceInfoJsonObj());
447 auto keyset = e->getKeys();
448 auto matchKeys = mkArrayField(entry,
"match_key"_cs);
450 for (
auto k : keyset->components) {
452 auto tableKey = table->getKey()->keyElements.at(keyIndex);
454 if (tableKey->expression->type->is<IR::Type_Error>()) {
458 keyWidth = tableKey->expression->type->width_bits();
460 auto k8 = ROUNDUP(keyWidth, 8);
461 auto matchType = getKeyMatchType(tableKey);
465 if (matchType ==
"optional") {
466 key->emplace(
"match_type",
"ternary");
468 key->emplace(
"match_type", matchType);
470 if (matchType == corelib.exactMatch.name) {
471 if (k->is<IR::Constant>())
472 key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
473 else if (k->is<IR::BoolLiteral>())
476 stringRepr(k->to<IR::BoolLiteral>()->value ? 1 : 0, k8));
478 ::P4::error(ErrorType::ERR_UNSUPPORTED,
479 "%1%: unsupported exact key expression", k);
480 }
else if (matchType == corelib.ternaryMatch.name) {
481 if (k->is<IR::Mask>()) {
482 auto km = k->to<IR::Mask>();
483 key->emplace(
"key", stringRepr(km->left->to<IR::Constant>()->value, k8));
484 key->emplace(
"mask", stringRepr(km->right->to<IR::Constant>()->value, k8));
485 }
else if (k->is<IR::Constant>()) {
486 key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
487 key->emplace(
"mask", stringRepr(Util::mask(keyWidth), k8));
488 }
else if (k->is<IR::DefaultExpression>()) {
489 key->emplace(
"key", stringRepr(0, k8));
490 key->emplace(
"mask", stringRepr(0, k8));
493 "%1%: unsupported ternary key expression", k);
495 }
else if (matchType == corelib.lpmMatch.name) {
496 if (k->is<IR::Mask>()) {
497 auto km = k->to<IR::Mask>();
498 key->emplace(
"key", stringRepr(km->left->to<IR::Constant>()->value, k8));
499 auto trailing_zeros = [](
unsigned long n,
unsigned long keyWidth) {
500 return n ? __builtin_ctzl(n) :
static_cast<int>(keyWidth);
502 auto count_ones = [](
unsigned long n) {
503 return n ? __builtin_popcountl(n) : 0;
506 static_cast<unsigned long>(km->right->to<IR::Constant>()->value);
507 auto len = trailing_zeros(mask, keyWidth);
508 if (len + count_ones(mask) != keyWidth)
509 ::P4::error(ErrorType::ERR_INVALID,
"%1%: invalid mask for LPM key", k);
511 key->emplace(
"prefix_length", keyWidth - len);
512 }
else if (k->is<IR::Constant>()) {
513 key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
514 key->emplace(
"prefix_length", keyWidth);
515 }
else if (k->is<IR::DefaultExpression>()) {
516 key->emplace(
"key", stringRepr(0, k8));
517 key->emplace(
"prefix_length", 0);
520 "%1%: unsupported LPM key expression", k);
522 }
else if (matchType ==
"range") {
523 if (k->is<IR::Range>()) {
524 auto kr = k->to<IR::Range>();
525 key->emplace(
"start", stringRepr(kr->left->to<IR::Constant>()->value, k8));
526 key->emplace(
"end", stringRepr(kr->right->to<IR::Constant>()->value, k8));
527 }
else if (k->is<IR::Constant>()) {
528 key->emplace(
"start", stringRepr(k->to<IR::Constant>()->value, k8));
529 key->emplace(
"end", stringRepr(k->to<IR::Constant>()->value, k8));
530 }
else if (k->is<IR::DefaultExpression>()) {
531 key->emplace(
"start", stringRepr(0, k8));
532 key->emplace(
"end", stringRepr((1 << keyWidth) - 1, k8));
535 "%1% unsupported range key expression", k);
537 }
else if (matchType ==
"optional") {
545 if (k->is<IR::Constant>()) {
546 key->emplace(
"key", stringRepr(k->to<IR::Constant>()->value, k8));
547 key->emplace(
"mask", stringRepr(Util::mask(keyWidth), k8));
548 }
else if (k->is<IR::DefaultExpression>()) {
549 key->emplace(
"key", stringRepr(0, k8));
550 key->emplace(
"mask", stringRepr(0, k8));
553 "%1%: unsupported optional key expression", k);
556 ::P4::error(ErrorType::ERR_UNKNOWN,
"unknown key match type '%2%' for key %1%",
559 matchKeys->append(key);
564 auto actionRef = e->getAction();
565 if (!actionRef->is<IR::MethodCallExpression>())
566 ::P4::error(ErrorType::ERR_INVALID,
"Invalid action '%1%' in entries list.",
568 auto actionCall = actionRef->to<IR::MethodCallExpression>();
569 auto method = actionCall->method->to<IR::PathExpression>()->path;
571 auto actionDecl = decl->
to<IR::P4Action>();
572 unsigned id = get(ctxt->
structure->
ids, actionDecl, INVALID_ACTION_ID);
573 BUG_CHECK(
id != INVALID_ACTION_ID,
"Could not find id for %1%", actionDecl);
574 action->emplace(
"action_id",
id);
575 auto actionData = mkArrayField(action,
"action_data"_cs);
576 for (
auto arg : *actionCall->arguments) {
577 actionData->append(stringRepr(arg->expression->to<IR::Constant>()->value, 0));
579 entry->emplace(
"action_entry", action);
581 auto priorityAnnotation = e->getAnnotation(
"priority"_cs);
582 if (priorityAnnotation !=
nullptr) {
583 if (priorityAnnotation->expr.size() > 1)
584 ::P4::error(ErrorType::ERR_INVALID,
"Invalid priority value %1%",
585 priorityAnnotation->expr);
586 auto priValue = priorityAnnotation->expr.front();
587 if (!priValue->is<IR::Constant>())
589 "Invalid priority value %1%; must be constant.",
590 priorityAnnotation->expr);
591 entry->emplace(
"priority", priValue->to<IR::Constant>()->value);
593 entry->emplace(
"priority", entryPriority);
597 entries->append(entry);
600 cstring getKeyMatchType(
const IR::KeyElement *ke) {
601 auto path = ke->matchType->path;
603 BUG_CHECK(mt !=
nullptr,
"%1%: could not find declaration", ke->matchType);
605 if (mt->name.name == corelib.exactMatch.name ||
606 mt->name.name == corelib.ternaryMatch.name || mt->name.name == corelib.lpmMatch.name ||
608 return mt->name.name;
611 ::P4::error(ErrorType::ERR_UNSUPPORTED,
"%1%: match type not supported on this target", mt);
618 if (implementation ==
nullptr) {
619 table->emplace(
"type",
"simple");
623 if (!implementation->value->is<IR::ExpressionValue>()) {
624 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected expression for property",
628 auto propv = implementation->value->to<IR::ExpressionValue>();
630 bool isSimpleTable =
true;
634 if (propv->expression->is<IR::ConstructorCallExpression>()) {
636 P4::ConstructorCall::resolve(propv->expression->to<IR::ConstructorCallExpression>(),
637 ctxt->
refMap, ctxt->typeMap);
639 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected extern object for property",
644 auto implementationType = ecc->type;
645 auto arguments = ecc->cce->arguments;
646 apname = implementation->controlPlaneName(ctxt->
refMap->
newName(
"action_profile"));
648 action_profiles->append(action_profile);
649 action_profile->emplace(
"name", apname);
650 action_profile->emplace(
"id", nextId(
"action_profiles"_cs));
651 action_profile->emplace_non_null(
"source_info"_cs,
652 propv->expression->sourceInfoJsonObj());
656 auto add_size = [&action_profile, &arguments](
size_t arg_index) {
657 auto size_expr = arguments->at(arg_index)->expression;
659 if (!size_expr->is<IR::Constant>()) {
660 ::P4::error(ErrorType::ERR_EXPECTED,
"%1% must be a constant", size_expr);
663 size = size_expr->to<IR::Constant>()->asInt();
665 action_profile->emplace(
"max_size", size);
669 if (implementationType->name == actionSelectorName) {
670 BUG_CHECK(arguments->size() == 3,
"%1%: expected 3 arguments", arguments);
671 isSimpleTable =
false;
673 table->emplace(
"type",
"indirect_ws");
674 action_profile->emplace(
"selector"_cs, selector);
676 auto hash = arguments->at(0)->expression;
680 "%1%: hash must be a constant on this target", hash);
683 selector->emplace(
"algo", algo);
685 auto input = mkArrayField(selector,
"input"_cs);
686 for (
auto ke : key->keyElements) {
688 ->
to<IR::Declaration_ID>();
689 BUG_CHECK(mt !=
nullptr,
"%1%: could not find declaration", ke->matchType);
692 auto expr = ke->expression;
696 }
else if (implementationType->name ==
698 isSimpleTable =
false;
699 table->emplace(
"type",
"indirect");
702 ::P4::error(ErrorType::ERR_UNEXPECTED,
"%1%: expected value for property", propv);
704 }
else if (propv->expression->is<IR::PathExpression>()) {
705 auto pathe = propv->expression->to<IR::PathExpression>();
707 if (!decl->is<IR::Declaration_Instance>()) {
708 ::P4::error(ErrorType::ERR_EXPECTED,
"%1%: expected a reference to an instance",
712 apname = decl->controlPlaneName();
713 auto dcltype = ctxt->typeMap->getType(pathe,
true);
714 if (!dcltype->is<IR::Type_Extern>()) {
715 ::P4::error(ErrorType::ERR_UNEXPECTED,
"%1%: unexpected type for implementation",
719 auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
722 if (type_extern_name == actionProfileName) {
723 table->emplace(
"type",
"indirect");
724 }
else if (type_extern_name == actionSelectorName) {
725 table->emplace(
"type",
"indirect_ws");
727 ::P4::error(ErrorType::ERR_UNEXPECTED,
"%1%: unexpected type for implementation",
731 isSimpleTable =
false;
732 if (ctxt->toplevel->hasValue(decl->getNode())) {
733 auto eb = ctxt->toplevel->getValue(decl->getNode());
734 BUG_CHECK(eb->is<IR::ExternBlock>(),
"Not an extern block?");
735 ExternConverter::cvtExternInstance(ctxt, decl->to<IR::Declaration>(),
736 eb->to<IR::ExternBlock>(), emitExterns);
739 ::P4::error(ErrorType::ERR_UNEXPECTED,
"%1%: unexpected value for property", propv);
742 table->emplace(
"action_profile", apname);
743 return isSimpleTable;
749 result->emplace(
"name", node->name);
750 result->emplace(
"id", nextId(
"conditionals"_cs));
751 result->emplace_non_null(
"source_info"_cs, node->statement->condition->sourceInfoJsonObj());
752 auto j = ctxt->
conv->
convert(node->statement->condition,
true,
false);
754 result->emplace(
"expression"_cs, j);
755 for (
auto e : node->successors.edges) {
757 cstring label = Util::toString(e->getBool());
759 result->emplace(label, dest);
765 const bool emitExterns;
766 bool preorder(
const IR::P4Control *cont)
override {
767 auto result =
new Util::JsonObject();
769 result->emplace(
"name", name);
770 result->emplace(
"id", nextId(
"control"_cs));
771 result->emplace_non_null(
"source_info"_cs, cont->sourceInfoJsonObj());
773 auto cfg =
new CFG();
774 cfg->build(cont, ctxt->
refMap, ctxt->typeMap);
775 bool success = cfg->checkImplementable();
776 if (!success)
return false;
778 if (cfg->entryPoint->successors.size() == 0) {
779 result->emplace(
"init_table", Util::JsonValue::null);
781 BUG_CHECK(cfg->entryPoint->successors.size() == 1,
"Expected 1 start node for %1%",
783 auto start = (*(cfg->entryPoint->successors.edges.begin()))->endpoint;
784 result->emplace(
"init_table", nodeName(start));
787 auto tables = mkArrayField(result,
"tables"_cs);
788 auto action_profiles = mkArrayField(result,
"action_profiles"_cs);
789 auto conditionals = mkArrayField(result,
"conditionals"_cs);
792 auto selector_check =
new BMV2::SharedActionSelectorCheck<arch>(ctxt);
793 cont->apply(*selector_check);
795 std::set<const IR::P4Table *> done;
798 for (
auto node : cfg->allNodes) {
799 auto tn = node->
to<CFG::TableNode>();
801 if (done.find(tn->table) != done.end())
806 done.emplace(tn->table);
807 auto j = convertTable(tn, action_profiles, selector_check);
810 }
else if (node->
is<CFG::IfNode>()) {
811 auto j = convertIf(node->
to<CFG::IfNode>(), cont->name);
813 conditionals->append(j);
817 for (
auto c : cont->controlLocals) {
818 if (c->is<IR::Declaration_Constant>() || c->is<IR::Declaration_Variable>() ||
819 c->is<IR::P4Action>() || c->is<IR::P4Table>())
821 if (c->is<IR::Declaration_Instance>()) {
824 if (bl->is<IR::ControlBlock>() || bl->is<IR::ParserBlock>())
828 if (bl->is<IR::ExternBlock>()) {
829 auto eb = bl->to<IR::ExternBlock>();
830 ExternConverter::cvtExternInstance(ctxt, c, eb, emitExterns);
834 P4C_UNIMPLEMENTED(
"%1%: not yet handled", c);
837 ctxt->
json->pipelines->append(result);
841 explicit ControlConverter(ConversionContext *ctxt, cstring name,
const bool &emitExterns_)
844 corelib(
P4::P4CoreLibrary::instance()),
845 emitExterns(emitExterns_) {
846 setName(
"ControlConverter");