Skip to content

Commit

Permalink
put back actionSelectorCheck in control.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
Han Wang committed May 10, 2017
1 parent 04bf207 commit 5bcf930
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 110 deletions.
4 changes: 3 additions & 1 deletion backends/bmv2/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ p4c_bm2_ss_UNIFIED = \
backends/bmv2/midend.cpp \
backends/bmv2/metermap.cpp \
backends/bmv2/parser.cpp \
backends/bmv2/sharedActionSelectorCheck.cpp \
backends/bmv2/v1model.cpp

noinst_HEADERS += \
Expand All @@ -55,7 +56,8 @@ noinst_HEADERS += \
backends/bmv2/lower.h \
backends/bmv2/midend.h \
backends/bmv2/metermap.h \
backends/bmv2/parser.h
backends/bmv2/parser.h \
backends/bmv2/sharedActionSelectorCheck.h

cpplint_FILES += $(p4c_bm2_ss_UNIFIED) $(p4c_bm2_ss_NONUNIFIED)

Expand Down
7 changes: 5 additions & 2 deletions backends/bmv2/control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,9 @@ bool Control::preorder(const IR::ControlBlock* block) {
auto action_profiles = mkArrayField(result, "action_profiles");
auto conditionals = mkArrayField(result, "conditionals");

SharedActionSelectorCheck selector_check(refMap, typeMap);
block->apply(selector_check);

// Tables are created prior to the other local declarations
for (auto node : cfg->allNodes) {
if (node->is<CFG::TableNode>()) {
Expand Down Expand Up @@ -751,11 +754,11 @@ bool Control::preorder(const IR::ControlBlock* block) {
continue;
if (bl->is<IR::ExternBlock>()) {
auto eb = bl->to<IR::ExternBlock>();
P4V1::V1Model::convertExternInstances(backend, c, eb, action_profiles);
P4V1::V1Model::convertExternInstances(backend, c, eb, action_profiles, selector_check);
continue;
}
}
BUG("%1%: not yet handled", c);
P4C_UNIMPLEMENTED("%1%: not yet handled", c);
}
#endif

Expand Down
96 changes: 1 addition & 95 deletions backends/bmv2/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,104 +27,10 @@ limitations under the License.
#include "midend/convertEnums.h"
#include "expression.h"
#include "helpers.h"
#include "sharedActionSelectorCheck.h"

namespace BMV2 {

// This pass makes sure that when several match tables share a selector, they use the same input for
// the selection algorithm. This is because bmv2 considers that the selection key is part of the
// action_selector while v1model.p4 considers that it belongs to the table match key definition.
class SharedActionSelectorCheck : public Inspector {
P4::ReferenceMap* refMap;
P4::TypeMap* typeMap;
using Input = std::vector<const IR::Expression *>;
std::map<const IR::Declaration_Instance *, Input> selector_input_map{};

static bool checkSameKeyExpr(const IR::Expression* expr0, const IR::Expression* expr1) {
if (expr0->node_type_name() != expr1->node_type_name())
return false;
if (auto pe0 = expr0->to<IR::PathExpression>()) {
auto pe1 = expr1->to<IR::PathExpression>();
return pe0->path->name == pe1->path->name &&
pe0->path->absolute == pe1->path->absolute;
} else if (auto mem0 = expr0->to<IR::Member>()) {
auto mem1 = expr1->to<IR::Member>();
return checkSameKeyExpr(mem0->expr, mem1->expr) && mem0->member == mem1->member;
} else if (auto l0 = expr0->to<IR::Literal>()) {
auto l1 = expr1->to<IR::Literal>();
return *l0 == *l1;
} else if (auto ai0 = expr0->to<IR::ArrayIndex>()) {
auto ai1 = expr1->to<IR::ArrayIndex>();
return checkSameKeyExpr(ai0->left, ai1->left) && checkSameKeyExpr(ai0->right, ai1->right);
}
return false;
}

public:
explicit SharedActionSelectorCheck(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) :
refMap(refMap), typeMap(typeMap) {}

const Input &get_selector_input(const IR::Declaration_Instance* selector) const {
return selector_input_map.at(selector);
}

bool preorder(const IR::P4Table* table) override {
auto implementation = table->properties->getProperty("implementation");
if (implementation == nullptr) return false;
if (!implementation->value->is<IR::ExpressionValue>()) {
::error("%1%: expected expression for property", implementation);
return false;
}
auto propv = implementation->value->to<IR::ExpressionValue>();
if (!propv->expression->is<IR::PathExpression>()) return false;
auto pathe = propv->expression->to<IR::PathExpression>();
auto decl = refMap->getDeclaration(pathe->path, true);
if (!decl->is<IR::Declaration_Instance>()) {
::error("%1%: expected a reference to an instance", pathe);
return false;
}
auto dcltype = typeMap->getType(pathe, true);
if (!dcltype->is<IR::Type_Extern>()) {
::error("%1%: unexpected type for implementation", dcltype);
return false;
}
auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
if (type_extern_name != BMV2::TableImplementation::actionSelectorName) return false;

auto key = table->getKey();
Input input;
for (auto ke : key->keyElements) {
auto mt = refMap->getDeclaration(ke->matchType->path, true)->to<IR::Declaration_ID>();
BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
if (mt->name.name != BMV2::MatchImplementation::selectorMatchTypeName) continue;
input.push_back(ke->expression);
}
auto decl_instance = decl->to<IR::Declaration_Instance>();
auto it = selector_input_map.find(decl_instance);
if (it == selector_input_map.end()) {
selector_input_map[decl_instance] = input;
return false;
}
// returns true if inputs are the same, false otherwise
auto cmp_inputs = [](const Input &i1, const Input &i2) {
for (auto e1 : i1) {
auto cmp_e = [e1](const IR::Expression *e2) {
return checkSameKeyExpr(e1, e2);
};
if (std::find_if(i2.begin(), i2.end(), cmp_e) == i2.end()) return false;
}
return true;
};

if (!cmp_inputs(it->second, input)) {
::error(
"Action selector '%1%' is used by multiple tables with different selector inputs",
decl);
}

return false;
}
};

class Control : public Inspector {
Backend* backend;
P4::ReferenceMap* refMap;
Expand Down
3 changes: 0 additions & 3 deletions backends/bmv2/metermap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ limitations under the License.

namespace BMV2 {

/**
*
*/
class DirectMeterMap final {
public:
struct DirectMeterInfo {
Expand Down
84 changes: 84 additions & 0 deletions backends/bmv2/sharedActionSelectorCheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Copyright 2013-present Barefoot Networks, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "sharedActionSelectorCheck.h"

namespace BMV2 {

const Input&
SharedActionSelectorCheck::get_selector_input(const IR::Declaration_Instance* selector) {
return selector_input_map.at(selector);
}

bool
SharedActionSelectorCheck::preorder(const IR::P4Table* table) {
auto implementation = table->properties->getProperty("implementation");
if (implementation == nullptr) return false;
if (!implementation->value->is<IR::ExpressionValue>()) {
::error("%1%: expected expression for property", implementation);
return false;
}
auto propv = implementation->value->to<IR::ExpressionValue>();
if (!propv->expression->is<IR::PathExpression>()) return false;
auto pathe = propv->expression->to<IR::PathExpression>();
auto decl = refMap->getDeclaration(pathe->path, true);
if (!decl->is<IR::Declaration_Instance>()) {
::error("%1%: expected a reference to an instance", pathe);
return false;
}
auto dcltype = typeMap->getType(pathe, true);
if (!dcltype->is<IR::Type_Extern>()) {
::error("%1%: unexpected type for implementation", dcltype);
return false;
}
auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
if (type_extern_name != BMV2::TableImplementation::actionSelectorName) return false;

auto key = table->getKey();
Input input;
for (auto ke : key->keyElements) {
auto mt = refMap->getDeclaration(ke->matchType->path, true)->to<IR::Declaration_ID>();
BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
if (mt->name.name != BMV2::MatchImplementation::selectorMatchTypeName) continue;
input.push_back(ke->expression);
}
auto decl_instance = decl->to<IR::Declaration_Instance>();
auto it = selector_input_map.find(decl_instance);
if (it == selector_input_map.end()) {
selector_input_map[decl_instance] = input;
return false;
}
// returns true if inputs are the same, false otherwise
auto cmp_inputs = [](const Input &i1, const Input &i2) {
for (auto e1 : i1) {
auto cmp_e = [e1](const IR::Expression *e2) {
return checkSameKeyExpr(e1, e2);
};
if (std::find_if(i2.begin(), i2.end(), cmp_e) == i2.end()) return false;
}
return true;
};

if (!cmp_inputs(it->second, input)) {
::error(
"Action selector '%1%' is used by multiple tables with different selector inputs",
decl);
}

return false;
}

} // namespace BMV2
71 changes: 71 additions & 0 deletions backends/bmv2/sharedActionSelectorCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright 2013-present Barefoot Networks, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef _BACKENDS_BMV2_SHAREDACTIONSELECTORCHECK_H_
#define _BACKENDS_BMV2_SHAREDACTIONSELECTORCHECK_H_

#include "ir/ir.h"
#include "lib/json.h"
#include "frontends/p4/coreLibrary.h"
#include "frontends/p4/frontend.h"
#include "frontends/p4/typeMap.h"
#include "frontends/p4/typeChecking/typeChecker.h"
#include "frontends/common/resolveReferences/referenceMap.h"
#include "helpers.h"

namespace BMV2 {

using Input = std::vector<const IR::Expression *>;

// This pass makes sure that when several match tables share a selector, they use the same input for
// the selection algorithm. This is because bmv2 considers that the selection key is part of the
// action_selector while v1model.p4 considers that it belongs to the table match key definition.
class SharedActionSelectorCheck : public Inspector {
P4::ReferenceMap* refMap;
P4::TypeMap* typeMap;
std::map<const IR::Declaration_Instance *, Input> selector_input_map{};

static bool checkSameKeyExpr(const IR::Expression* expr0, const IR::Expression* expr1) {
if (expr0->node_type_name() != expr1->node_type_name())
return false;
if (auto pe0 = expr0->to<IR::PathExpression>()) {
auto pe1 = expr1->to<IR::PathExpression>();
return pe0->path->name == pe1->path->name &&
pe0->path->absolute == pe1->path->absolute;
} else if (auto mem0 = expr0->to<IR::Member>()) {
auto mem1 = expr1->to<IR::Member>();
return checkSameKeyExpr(mem0->expr, mem1->expr) && mem0->member == mem1->member;
} else if (auto l0 = expr0->to<IR::Literal>()) {
auto l1 = expr1->to<IR::Literal>();
return *l0 == *l1;
} else if (auto ai0 = expr0->to<IR::ArrayIndex>()) {
auto ai1 = expr1->to<IR::ArrayIndex>();
return checkSameKeyExpr(ai0->left, ai1->left) && checkSameKeyExpr(ai0->right, ai1->right);
}
return false;
}

public:
explicit SharedActionSelectorCheck(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) :
refMap(refMap), typeMap(typeMap) {}

const Input &get_selector_input(const IR::Declaration_Instance* selector);
bool preorder(const IR::P4Table* table) override;
};

} // namespace BMV2

#endif /* _BACKENDS_BMV2_SHAREDACTIONSELECTORCHECK_H_ */
16 changes: 8 additions & 8 deletions backends/bmv2/v1model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ void V1Model::convertExternFunctions(Util::JsonArray *result, BMV2::Backend *bmv
void V1Model::convertExternInstances(BMV2::Backend *backend,
const IR::Declaration *c,
const IR::ExternBlock* eb,
Util::JsonArray* action_profiles) {
Util::JsonArray* action_profiles,
BMV2::SharedActionSelectorCheck& selector_check) {
auto inst = c->to<IR::Declaration_Instance>();
cstring name = extVisibleName(inst);
if (eb->type->name == instance.counter.name) {
Expand Down Expand Up @@ -467,13 +468,12 @@ void V1Model::convertExternInstances(BMV2::Backend *backend,
BUG_CHECK(hash->is<IR::Declaration_ID>(), "%1%: expected a member", hash);
auto algo = convertHashAlgorithm(hash->to<IR::Declaration_ID>()->name);
selector->emplace("algo", algo);
// FIXME selector_check pass
// const auto &input = selector_check.get_selector_input(inst);
// auto j_input = mkArrayField(selector, "input");
// for (auto expr : input) {
// auto jk = backend->getExpressionConverter()->convert(expr);
// j_input->append(jk);
// }
const auto &input = selector_check.get_selector_input(inst);
auto j_input = mkArrayField(selector, "input");
for (auto expr : input) {
auto jk = backend->getExpressionConverter()->convert(expr);
j_input->append(jk);
}
action_profile->emplace("selector", selector);
}

Expand Down
4 changes: 3 additions & 1 deletion frontends/p4/fromv1.0/v1model.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ limitations under the License.
#include "frontends/p4/methodInstance.h"
#include "ir/ir.h"
#include "lib/json.h"
#include "backends/bmv2/sharedActionSelectorCheck.h"

namespace BMV2 {
class Backend;
Expand Down Expand Up @@ -316,7 +317,8 @@ class V1Model : public ::Model::Model {
static void convertExternInstances(BMV2::Backend *bmv2,
const IR::Declaration *c,
const IR::ExternBlock* eb,
Util::JsonArray* action_profiles);
Util::JsonArray* action_profiles,
BMV2::SharedActionSelectorCheck& selector_check);

static V1Model instance;
};
Expand Down

0 comments on commit 5bcf930

Please sign in to comment.