P4C
The P4 Compiler
Loading...
Searching...
No Matches
sharedActionSelectorCheck.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_
18#define BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_
19
20#include <algorithm>
21
22#include "frontends/common/resolveReferences/referenceMap.h"
23#include "frontends/p4/coreLibrary.h"
24#include "frontends/p4/frontend.h"
25#include "frontends/p4/typeChecking/typeChecker.h"
26#include "frontends/p4/typeMap.h"
27#include "helpers.h"
28#include "ir/ir.h"
29#include "lib/error.h"
30#include "lib/json.h"
31
32namespace P4::BMV2 {
33
34using SelectorInput = std::vector<const IR::Expression *>;
35
40template <Standard::Arch arch>
43 P4::ReferenceMap *refMap;
44 P4::TypeMap *typeMap;
45
46 static bool checkSameKeyExpr(const IR::Expression *expr0, const IR::Expression *expr1) {
47 if (expr0->node_type_name() != expr1->node_type_name()) return false;
48 if (auto pe0 = expr0->to<IR::PathExpression>()) {
49 auto pe1 = expr1->to<IR::PathExpression>();
50 return pe0->path->name == pe1->path->name && pe0->path->absolute == pe1->path->absolute;
51 } else if (auto mem0 = expr0->to<IR::Member>()) {
52 auto mem1 = expr1->to<IR::Member>();
53 return checkSameKeyExpr(mem0->expr, mem1->expr) && mem0->member == mem1->member;
54 } else if (auto l0 = expr0->to<IR::Literal>()) {
55 auto l1 = expr1->to<IR::Literal>();
56 return *l0 == *l1;
57 } else if (auto ai0 = expr0->to<IR::ArrayIndex>()) {
58 auto ai1 = expr1->to<IR::ArrayIndex>();
59 return checkSameKeyExpr(ai0->left, ai1->left) &&
60 checkSameKeyExpr(ai0->right, ai1->right);
61 }
62 return false;
63 }
64
65 public:
66 explicit SharedActionSelectorCheck(BMV2::ConversionContext *ctxt) : ctxt(ctxt) {
67 refMap = ctxt->refMap;
68 typeMap = ctxt->typeMap;
69 }
70
71 bool preorder(const IR::P4Table *table) override {
72 auto implementation = table->properties->getProperty("implementation");
73 if (implementation == nullptr) return false;
74 if (!implementation->value->is<IR::ExpressionValue>()) {
75 ::P4::error(ErrorType::ERR_EXPECTED, "%1%: expected expression for property",
76 implementation);
77 return false;
78 }
79 auto propv = implementation->value->to<IR::ExpressionValue>();
80 if (!propv->expression->is<IR::PathExpression>()) return false;
81 auto pathe = propv->expression->to<IR::PathExpression>();
82 auto decl = refMap->getDeclaration(pathe->path, true);
83 if (!decl->is<IR::Declaration_Instance>()) {
84 ::P4::error(ErrorType::ERR_EXPECTED, "%1%: expected a reference to an instance", pathe);
85 return false;
86 }
87 auto dcltype = typeMap->getType(pathe, true);
88 if (!dcltype->is<IR::Type_Extern>()) {
89 ::P4::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type for implementation",
90 dcltype);
91 return false;
92 }
93 auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
94 auto actionSelectorName = Standard::ActionSelectorTraits<arch>::typeName();
95 if (type_extern_name != actionSelectorName) return false;
96
97 auto key = table->getKey();
98 SelectorInput input;
99 for (auto ke : key->keyElements) {
100 auto mt = refMap->getDeclaration(ke->matchType->path, true)->to<IR::Declaration_ID>();
101 BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
102 if (mt->name.name != BMV2::MatchImplementation::selectorMatchTypeName) continue;
103 input.push_back(ke->expression);
104 }
105 auto decl_instance = decl->to<IR::Declaration_Instance>();
106 auto it = ctxt->selector_input_map.find(decl_instance);
107 if (it == ctxt->selector_input_map.end()) {
108 ctxt->selector_input_map[decl_instance] = input;
109 return false;
110 }
111 // returns true if inputs are the same, false otherwise
112 auto cmp_inputs = [](const SelectorInput &i1, const SelectorInput &i2) {
113 if (i1.size() != i2.size()) return false;
114 return std::equal(i1.begin(), i1.end(), i2.begin(), checkSameKeyExpr);
115 };
116
117 if (!cmp_inputs(it->second, input)) {
119 ErrorType::ERR_INVALID,
120 "Action selector %1% is used by multiple tables with different selector inputs",
121 decl);
122 }
123
124 return false;
125 }
126};
127
128} // namespace P4::BMV2
129
130#endif /* BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_ */
static const cstring selectorMatchTypeName
constant definition for bmv2
Definition bmv2/common/helpers.h:41
Definition sharedActionSelectorCheck.h:41
Definition visitor.h:400
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
const IR::IDeclaration * getDeclaration(const IR::Path *path, bool notNull=false) const override
Definition referenceMap.cpp:78
Definition typeMap.h:41
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition action.cpp:21
std::vector< const IR::Expression * > SelectorInput
Definition bmv2/common/helpers.h:295
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51
Definition bmv2/common/helpers.h:297
P4::ReferenceMap * refMap
context
Definition bmv2/common/helpers.h:299
Definition bmv2/common/helpers.h:116
T * to() noexcept
Definition rtti.h:226