Skip to content

Commit

Permalink
Merge branch 'master' into issue386
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisDodd authored Mar 29, 2017
2 parents 5910398 + f1543a2 commit d0671ce
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 23 deletions.
17 changes: 12 additions & 5 deletions backends/bmv2/jsonconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1374,13 +1374,20 @@ JsonConverter::convertTable(const CFG::TableNode* node,
BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
auto expr = ke->expression;
mpz_class mask;
if (expr->is<IR::Slice>()) {
auto slice = expr->to<IR::Slice>();
if (auto mexp = expr->to<IR::BAnd>()) {
if (mexp->right->is<IR::Constant>()) {
mask = mexp->right->to<IR::Constant>()->value;
expr = mexp->left;
} else if (mexp->left->is<IR::Constant>()) {
mask = mexp->left->to<IR::Constant>()->value;
expr = mexp->right;
} else {
::error("%1%: key mask must be a constant", expr); }
} else if (auto slice = expr->to<IR::Slice>()) {
expr = slice->e0;
int h = slice->getH();
int l = slice->getL();
mask = Util::maskFromSlice(h, l);
}
mask = Util::maskFromSlice(h, l); }

cstring match_type = mt->name.name;
if (mt->name.name == corelib.exactMatch.name) {
Expand Down Expand Up @@ -1426,7 +1433,7 @@ JsonConverter::convertTable(const CFG::TableNode* node,
auto jk = conv->convert(expr);
keyelement->emplace("target", jk->to<Util::JsonObject>()->get("value"));
if (mask != 0)
keyelement->emplace("mask", stringRepr(mask));
keyelement->emplace("mask", stringRepr(mask, (expr->type->width_bits() + 7) / 8));
else
keyelement->emplace("mask", Util::JsonValue::null);
tkey->append(keyelement);
Expand Down
2 changes: 1 addition & 1 deletion backends/bmv2/midend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ MidEnd::MidEnd(CompilerOptions& options) {
new P4::SimplifyControlFlow(&refMap, &typeMap),
new P4::RemoveActionParameters(&refMap, &typeMap),
new P4::SimplifyKey(&refMap, &typeMap,
new P4::NonLeftValue(&refMap, &typeMap)),
new P4::NonMaskLeftValue(&refMap, &typeMap)),
new P4::ConstantFolding(&refMap, &typeMap),
new P4::StrengthReduction(),
new P4::SimplifySelectCases(&refMap, &typeMap, true), // require constant keysets
Expand Down
19 changes: 9 additions & 10 deletions frontends/p4/fromv1.0/converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ const IR::Node* ExpressionConverter::postorder(IR::Mask* expression) {
auto exp = expression->left;
auto cst = expression->right->to<IR::Constant>();
mpz_class value = cst->value;
while (value != 0) {
auto range = Util::findOnes(value);
value = value - range.value;
exp = new IR::Slice(Util::SourceInfo(), exp,
new IR::Constant(range.highIndex), new IR::Constant(range.lowIndex));
}
return exp;
auto range = Util::findOnes(value);
if (range.lowIndex == 0 && range.highIndex >= exp->type->width_bits() - 1U)
return exp;
if (value != range.value)
return new IR::BAnd(expression->srcInfo, exp, cst);
return new IR::Slice(Util::SourceInfo(), exp,
new IR::Constant(range.highIndex), new IR::Constant(range.lowIndex));
}

const IR::Node* ExpressionConverter::postorder(IR::Constant* expression) {
Expand Down Expand Up @@ -111,9 +111,8 @@ const IR::Node* ExpressionConverter::postorder(IR::Primitive* primitive) {
BUG_CHECK(primitive->operands.size() == 1, "Expected 1 operand for %1%", primitive);
auto base = primitive->operands.at(0);
auto method = new IR::Member(primitive->srcInfo, base, IR::ID(IR::Type_Header::isValid));
auto result = new IR::MethodCallExpression(
primitive->srcInfo, method, new IR::Vector<IR::Type>(),
new IR::Vector<IR::Expression>());
auto result = new IR::MethodCallExpression(primitive->srcInfo, IR::Type::Boolean::get(),
method, new IR::Vector<IR::Type>(), new IR::Vector<IR::Expression>());
return result;
}
BUG("Unexpected primitive %1%", primitive);
Expand Down
11 changes: 11 additions & 0 deletions frontends/p4/tableKeyNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ class KeyNameGenerator : public Inspector {
name.emplace(expression, l + "[" + r + "]");
}

void postorder(const IR::BAnd *expression) override {
if (expression->right->is<IR::Constant>()) {
if (cstring l = getName(expression->left))
name.emplace(expression, l);
} else if (expression->left->is<IR::Constant>()) {
if (cstring r = getName(expression->right))
name.emplace(expression, r);
} else {
error(expression); }
}

void postorder(const IR::Constant* expression) override {
name.emplace(expression, expression->toString());
}
Expand Down
17 changes: 17 additions & 0 deletions ir/dbprint-stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,20 @@ void IR::Function::dbprint(std::ostream &out) const {
out << endl << s;
out << unindent << " }";
}

void IR::SwitchStatement::dbprint(std::ostream &out) const {
int prec = getprec(out);
out << Prec_Low << "switch (" << expression << ") {" << indent;
bool fallthrough = false;
for (auto c : cases) {
if (!fallthrough) out << endl;
out << Prec_Low << c->label << ": " << setprec(0);
if (c->statement) {
out << c->statement;
fallthrough = false;
} else {
fallthrough = true;
}
}
out << unindent << " }" << setprec(prec);
}
4 changes: 4 additions & 0 deletions ir/expression.def
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,15 @@ class ArrayIndex : Operation_Binary {
class Range : Operation_Binary {
stringOp = "..";
precedence = DBPrint::Prec_Low;
Range { if (left && type == left->type && !left->type->is<Type::Unknown>())
type = new Type_Set(left->type); }
}

class Mask : Operation_Binary {
stringOp = "&&&";
precedence = DBPrint::Prec_Low;
Mask { if (left && type == left->type && !left->type->is<Type::Unknown>())
type = new Type_Set(left->type); }
}

class Mux : Operation_Ternary {
Expand Down
1 change: 0 additions & 1 deletion ir/ir.def
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,6 @@ class SwitchCase {
class SwitchStatement : Statement {
Expression expression;
inline Vector<SwitchCase> cases;
#nodbprint
visit_children {
v.visit(expression, "expression");
cases.parallel_visit_children(v); }
Expand Down
18 changes: 12 additions & 6 deletions midend/local_copyprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class DoLocalCopyPropagation::RewriteTableKeys : public Transform {
IR::P4Table *preorder(IR::P4Table *tbl) {
BUG_CHECK(table == nullptr, "corrupt internal state");
table = &self.tables[tbl->name];
LOG3("RewriteTableKeys for table " << tbl->name);
return tbl; }
IR::P4Table *postorder(IR::P4Table *tbl) {
BUG_CHECK(table == &self.tables[tbl->name], "corrupt internal state");
Expand All @@ -96,9 +97,11 @@ class DoLocalCopyPropagation::RewriteTableKeys : public Transform {
const IR::Expression *preorder(IR::PathExpression *path) {
if (table) {
const Visitor::Context *ctxt = nullptr;
if (findContext<IR::KeyElement>(ctxt) && ctxt->child_index == 1)
if (table->key_remap.count(path->path->name))
return table->key_remap.at(path->path->name); }
if (findContext<IR::KeyElement>(ctxt) && ctxt->child_index == 1) {
if (table->key_remap.count(path->path->name)) {
LOG4(" rewriting key " << path->path->name << " : " <<
table->key_remap.at(path->path->name));
return table->key_remap.at(path->path->name); } } }
return path; }

public:
Expand All @@ -116,17 +119,20 @@ void DoLocalCopyPropagation::flow_merge(Visitor &a_) {
var.second.live = true;
} else {
var.second.val = nullptr; } }
need_key_rewrite |= a.need_key_rewrite;
}

void DoLocalCopyPropagation::dropValuesUsing(cstring name) {
LOG6("dropValuesUsing(" << name << ")");
for (auto &var : available) {
LOG7(" checking " << var.first << " = " << var.second.val);
if (var.first == name) {
LOG4(" dropping " << name << " as it is being assigned to");
LOG4(" dropping " << (var.second.val ? "" : "(nop) ") << name <<
" as it is being assigned to");
var.second.val = nullptr;
} else if (var.second.val && exprUses(var.second.val, name)) {
LOG4(" dropping " << var.first << " as it uses " << name);
LOG4(" dropping " << (var.second.val ? "" : "(nop) ") << var.first <<
" as it uses " << name);
var.second.val = nullptr; } }
}

Expand Down Expand Up @@ -350,7 +356,7 @@ void DoLocalCopyPropagation::apply_table(DoLocalCopyPropagation::TableInfo *tbl)
tbl->key_remap.erase(key);
var->live = true;
} else {
LOG3(" propagating value into table key " << key << ": " << var->val);
LOG3(" will propagate value into table key " << key << ": " << var->val);
tbl->key_remap.emplace(key, var->val);
need_key_rewrite = true; }
} else {
Expand Down
13 changes: 13 additions & 0 deletions midend/simplifyKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ class NonLeftValue : public KeyIsComplex {
bool isTooComplex(const IR::Expression* expression) const;
};

// Policy that allows masked lvalues as well as simple lvalues or isValid()
class NonMaskLeftValue : public NonLeftValue {
public:
NonMaskLeftValue(ReferenceMap* refMap, TypeMap* typeMap) : NonLeftValue(refMap, typeMap) {}
bool isTooComplex(const IR::Expression* expression) const {
if (auto mask = expression->to<IR::BAnd>()) {
if (mask->right->is<IR::Constant>())
expression = mask->left;
else if (mask->left->is<IR::Constant>())
expression = mask->right; }
return NonLeftValue::isTooComplex(expression); }
};

class TableInsertions {
public:
std::vector<const IR::Declaration_Variable*> declarations;
Expand Down
51 changes: 51 additions & 0 deletions testdata/p4_14_samples/exact_match_mask1.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
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.
*/

header_type data_t {
fields {
f1 : 32;
f2 : 32;
h1 : 16;
b1 : 8;
b2 : 8;
}
}
header data_t data;

parser start {
extract(data);
return ingress;
}

action noop() { }
action setb1(val, port) {
modify_field(data.b1, val);
modify_field(standard_metadata.egress_spec, port);
}

table test1 {
reads {
data.f1 mask 0xff00ff : exact;
}
actions {
setb1;
noop;
}
}

control ingress {
apply(test1);
}
8 changes: 8 additions & 0 deletions testdata/p4_14_samples/exact_match_mask1.stf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

add test1 data.f1:0x010001 setb1(val:0x7f, port:2)
add test1 data.f1:0x020002 setb1(val:7, port:3)

expect 2 01010101 ******** **** 7f 66
packet 0 01010101 00000202 0303 55 66 77 88
expect 3 02020202 ******** **** 07 66
packet 2 02020202 00000303 0404 55 66 77 88
71 changes: 71 additions & 0 deletions testdata/p4_14_samples_outputs/exact_match_mask1-first.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <core.p4>
#include <v1model.p4>

header data_t {
bit<32> f1;
bit<32> f2;
bit<16> h1;
bit<8> b1;
bit<8> b2;
}

struct metadata {
}

struct headers {
@name("data")
data_t data;
}

parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
@name("start") state start {
packet.extract<data_t>(hdr.data);
transition accept;
}
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
@name("setb1") action setb1(bit<8> val, bit<9> port) {
hdr.data.b1 = val;
standard_metadata.egress_spec = port;
}
@name("noop") action noop() {
}
@name("test1") table test1 {
actions = {
setb1();
noop();
@default_only NoAction();
}
key = {
hdr.data.f1 & 32w0xff00ff: exact @name("hdr.data.f1") ;
}
default_action = NoAction();
}
apply {
test1.apply();
}
}

control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
apply {
}
}

control DeparserImpl(packet_out packet, in headers hdr) {
apply {
packet.emit<data_t>(hdr.data);
}
}

control verifyChecksum(in headers hdr, inout metadata meta) {
apply {
}
}

control computeChecksum(inout headers hdr, inout metadata meta) {
apply {
}
}

V1Switch<headers, metadata>(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;
Loading

0 comments on commit d0671ce

Please sign in to comment.