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 BMV2 {
33
34using SelectorInput = std::vector<const IR::Expression *>;
35
36// This pass makes sure that when several match tables share a selector, they use the same input for
37// the selection algorithm. This is because bmv2 considers that the selection key is part of the
38// action_selector while v1model.p4 considers that it belongs to the table match key definition.
39template <Standard::Arch arch>
40class SharedActionSelectorCheck : public Inspector {
42 P4::ReferenceMap *refMap;
43 P4::TypeMap *typeMap;
44
45 static bool checkSameKeyExpr(const IR::Expression *expr0, const IR::Expression *expr1) {
46 if (expr0->node_type_name() != expr1->node_type_name()) return false;
47 if (auto pe0 = expr0->to<IR::PathExpression>()) {
48 auto pe1 = expr1->to<IR::PathExpression>();
49 return pe0->path->name == pe1->path->name && pe0->path->absolute == pe1->path->absolute;
50 } else if (auto mem0 = expr0->to<IR::Member>()) {
51 auto mem1 = expr1->to<IR::Member>();
52 return checkSameKeyExpr(mem0->expr, mem1->expr) && mem0->member == mem1->member;
53 } else if (auto l0 = expr0->to<IR::Literal>()) {
54 auto l1 = expr1->to<IR::Literal>();
55 return *l0 == *l1;
56 } else if (auto ai0 = expr0->to<IR::ArrayIndex>()) {
57 auto ai1 = expr1->to<IR::ArrayIndex>();
58 return checkSameKeyExpr(ai0->left, ai1->left) &&
59 checkSameKeyExpr(ai0->right, ai1->right);
60 }
61 return false;
62 }
63
64 public:
65 explicit SharedActionSelectorCheck(BMV2::ConversionContext *ctxt) : ctxt(ctxt) {
66 refMap = ctxt->refMap;
67 typeMap = ctxt->typeMap;
68 }
69
70 bool preorder(const IR::P4Table *table) override {
71 auto implementation = table->properties->getProperty("implementation");
72 if (implementation == nullptr) return false;
73 if (!implementation->value->is<IR::ExpressionValue>()) {
74 ::error(ErrorType::ERR_EXPECTED, "%1%: expected expression for property",
75 implementation);
76 return false;
77 }
78 auto propv = implementation->value->to<IR::ExpressionValue>();
79 if (!propv->expression->is<IR::PathExpression>()) return false;
80 auto pathe = propv->expression->to<IR::PathExpression>();
81 auto decl = refMap->getDeclaration(pathe->path, true);
82 if (!decl->is<IR::Declaration_Instance>()) {
83 ::error(ErrorType::ERR_EXPECTED, "%1%: expected a reference to an instance", pathe);
84 return false;
85 }
86 auto dcltype = typeMap->getType(pathe, true);
87 if (!dcltype->is<IR::Type_Extern>()) {
88 ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type for implementation", dcltype);
89 return false;
90 }
91 auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
93 if (type_extern_name != actionSelectorName) return false;
94
95 auto key = table->getKey();
96 SelectorInput input;
97 for (auto ke : key->keyElements) {
98 auto mt = refMap->getDeclaration(ke->matchType->path, true)->to<IR::Declaration_ID>();
99 BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
100 if (mt->name.name != BMV2::MatchImplementation::selectorMatchTypeName) continue;
101 input.push_back(ke->expression);
102 }
103 auto decl_instance = decl->to<IR::Declaration_Instance>();
104 auto it = ctxt->selector_input_map.find(decl_instance);
105 if (it == ctxt->selector_input_map.end()) {
106 ctxt->selector_input_map[decl_instance] = input;
107 return false;
108 }
109 // returns true if inputs are the same, false otherwise
110 auto cmp_inputs = [](const SelectorInput &i1, const SelectorInput &i2) {
111 if (i1.size() != i2.size()) return false;
112 return std::equal(i1.begin(), i1.end(), i2.begin(), checkSameKeyExpr);
113 };
114
115 if (!cmp_inputs(it->second, input)) {
116 ::error(ErrorType::ERR_INVALID,
117 "Action selector %1% is used by multiple tables with different selector inputs",
118 decl);
119 }
120
121 return false;
122 }
123};
124
125} // namespace BMV2
126
127#endif /* BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_ */
static const cstring selectorMatchTypeName
constant definition for bmv2
Definition helpers.h:39
Definition sharedActionSelectorCheck.h:40
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:42
Definition helpers.h:261
Definition helpers.h:100