P4C
The P4 Compiler
Loading...
Searching...
No Matches
sharedActionSelectorCheck.h
1/*
2 * SPDX-FileCopyrightText: 2013 Barefoot Networks, Inc.
3 * Copyright 2013-present Barefoot Networks, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_
9#define BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_
10
11#include <algorithm>
12
13#include "frontends/common/resolveReferences/referenceMap.h"
14#include "frontends/p4/coreLibrary.h"
15#include "frontends/p4/frontend.h"
16#include "frontends/p4/typeChecking/typeChecker.h"
17#include "frontends/p4/typeMap.h"
18#include "helpers.h"
19#include "ir/ir.h"
20#include "lib/error.h"
21#include "lib/json.h"
22
23namespace P4::BMV2 {
24
25using SelectorInput = std::vector<const IR::Expression *>;
26
31template <Standard::Arch arch>
32class SharedActionSelectorCheck : public Inspector {
34 P4::ReferenceMap *refMap;
35 P4::TypeMap *typeMap;
36
37 static bool checkSameKeyExpr(const IR::Expression *expr0, const IR::Expression *expr1) {
38 if (expr0->node_type_name() != expr1->node_type_name()) return false;
39 if (auto pe0 = expr0->to<IR::PathExpression>()) {
40 auto pe1 = expr1->to<IR::PathExpression>();
41 return pe0->path->name == pe1->path->name && pe0->path->absolute == pe1->path->absolute;
42 } else if (auto mem0 = expr0->to<IR::Member>()) {
43 auto mem1 = expr1->to<IR::Member>();
44 return checkSameKeyExpr(mem0->expr, mem1->expr) && mem0->member == mem1->member;
45 } else if (auto l0 = expr0->to<IR::Literal>()) {
46 auto l1 = expr1->to<IR::Literal>();
47 return *l0 == *l1;
48 } else if (auto ai0 = expr0->to<IR::ArrayIndex>()) {
49 auto ai1 = expr1->to<IR::ArrayIndex>();
50 return checkSameKeyExpr(ai0->left, ai1->left) &&
51 checkSameKeyExpr(ai0->right, ai1->right);
52 }
53 return false;
54 }
55
56 public:
57 explicit SharedActionSelectorCheck(BMV2::ConversionContext *ctxt) : ctxt(ctxt) {
58 refMap = ctxt->refMap;
59 typeMap = ctxt->typeMap;
60 }
61
62 bool preorder(const IR::P4Table *table) override {
63 auto implementation = table->properties->getProperty("implementation");
64 if (implementation == nullptr) return false;
65 if (!implementation->value->is<IR::ExpressionValue>()) {
66 ::P4::error(ErrorType::ERR_EXPECTED, "%1%: expected expression for property",
67 implementation);
68 return false;
69 }
70 auto propv = implementation->value->to<IR::ExpressionValue>();
71 if (!propv->expression->is<IR::PathExpression>()) return false;
72 auto pathe = propv->expression->to<IR::PathExpression>();
73 auto decl = refMap->getDeclaration(pathe->path, true);
74 if (!decl->is<IR::Declaration_Instance>()) {
75 ::P4::error(ErrorType::ERR_EXPECTED, "%1%: expected a reference to an instance", pathe);
76 return false;
77 }
78 auto dcltype = typeMap->getType(pathe, true);
79 if (!dcltype->is<IR::Type_Extern>()) {
80 ::P4::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type for implementation",
81 dcltype);
82 return false;
83 }
84 auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
85 auto actionSelectorName = Standard::ActionSelectorTraits<arch>::typeName();
86 if (type_extern_name != actionSelectorName) return false;
87
88 auto key = table->getKey();
89 SelectorInput input;
90 for (auto ke : key->keyElements) {
91 auto mt = refMap->getDeclaration(ke->matchType->path, true)->to<IR::Declaration_ID>();
92 BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
93 if (mt->name.name != BMV2::MatchImplementation::selectorMatchTypeName) continue;
94 input.push_back(ke->expression);
95 }
96 auto decl_instance = decl->to<IR::Declaration_Instance>();
97 auto it = ctxt->selector_input_map.find(decl_instance);
98 if (it == ctxt->selector_input_map.end()) {
99 ctxt->selector_input_map[decl_instance] = input;
100 return false;
101 }
102 // returns true if inputs are the same, false otherwise
103 auto cmp_inputs = [](const SelectorInput &i1, const SelectorInput &i2) {
104 if (i1.size() != i2.size()) return false;
105 return std::equal(i1.begin(), i1.end(), i2.begin(), checkSameKeyExpr);
106 };
107
108 if (!cmp_inputs(it->second, input)) {
110 ErrorType::ERR_INVALID,
111 "Action selector %1% is used by multiple tables with different selector inputs",
112 decl);
113 }
114
115 return false;
116 }
117};
118
119} // namespace P4::BMV2
120
121#endif /* BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_ */
static const cstring selectorMatchTypeName
constant definition for bmv2
Definition bmv2/common/helpers.h:32
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition typeMap.h:32
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition action.cpp:9
std::vector< const IR::Expression * > SelectorInput
Definition bmv2/common/helpers.h:286
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
Definition bmv2/common/helpers.h:288
Definition bmv2/common/helpers.h:107