Skip to content

Commit

Permalink
Handle headers in structs; fixes #1642 (#1643)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihai Budiu authored Dec 26, 2018
1 parent cb8e3ee commit e4386b8
Show file tree
Hide file tree
Showing 7 changed files with 341 additions and 5 deletions.
14 changes: 9 additions & 5 deletions midend/flattenInterfaceStructs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void StructTypeReplacement::flatten(const P4::TypeMap* typeMap,
cstring fieldName = prefix.replace(".", "_") +
cstring::to_cstring(fieldNameRemap.size());
fieldNameRemap.emplace(prefix, fieldName);
fields->push_back(new IR::StructField(IR::ID(fieldName), type));
fields->push_back(new IR::StructField(IR::ID(fieldName), type->getP4Type()));
}

StructTypeReplacement::StructTypeReplacement(
Expand All @@ -45,7 +45,7 @@ const IR::StructInitializerExpression* StructTypeReplacement::explode(
const IR::Expression *root, cstring prefix) {
auto vec = new IR::IndexedVector<IR::NamedExpression>();
auto fieldType = ::get(structFieldMap, prefix);
CHECK_NULL(fieldType);
BUG_CHECK(fieldType, "No field for %1%", prefix);
for (auto f : fieldType->fields) {
cstring fieldName = prefix + "." + f->name.name;
auto newFieldname = ::get(fieldNameRemap, fieldName);
Expand Down Expand Up @@ -114,9 +114,6 @@ const IR::Node* ReplaceStructs::postorder(IR::Type_Struct* type) {

const IR::Node* ReplaceStructs::postorder(IR::Member* expression) {
// Find out if this applies to one of the parameters that are being replaced.
if (getParent<IR::Member>() != nullptr)
// We only want to process the outermost Member
return expression;
const IR::Expression* e = expression;
cstring prefix = "";
while (auto mem = e->to<IR::Member>()) {
Expand All @@ -138,6 +135,13 @@ const IR::Node* ReplaceStructs::postorder(IR::Member* expression) {
auto newFieldName = ::get(repl->fieldNameRemap, prefix);
const IR::Expression* result;
if (newFieldName.isNullOrEmpty()) {
auto type = replacementMap->typeMap->getType(getOriginal(), true);
// This could be, for example, a method like setValid.
if (!type->is<IR::Type_Struct>())
return expression;
if (getParent<IR::Member>() != nullptr)
// We only want to process the outermost Member
return expression;
// Prefix is a reference to a field of the original struct whose
// type is actually a struct itself. We need to replace the field
// with a struct initializer expression. (This won't work if the
Expand Down
66 changes: 66 additions & 0 deletions testdata/p4_16_samples/issue1642-bmv2.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <v1model.p4>

header short {
bit<32> f;
}

struct alt_t {
bit<1> valid;
bit<7> port;
};

struct row_t {
alt_t alt0;
alt_t alt1;
};

struct parsed_packet_t {};

struct local_metadata_t {
short s;
row_t row;
};

parser parse(packet_in pk, out parsed_packet_t hdr,
inout local_metadata_t local_metadata,
inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control ingress(inout parsed_packet_t hdr,
inout local_metadata_t local_metadata,
inout standard_metadata_t standard_metadata) {
apply {
local_metadata.s.setValid();
local_metadata.s.f = 0;
local_metadata.row.alt0 = local_metadata.row.alt1;
local_metadata.row.alt0.valid = 1;
local_metadata.row.alt1.port = local_metadata.row.alt1.port + 1;
clone3(CloneType.I2E, 0, local_metadata.row);
}
}

control egress(inout parsed_packet_t hdr,
inout local_metadata_t local_metadata,
inout standard_metadata_t standard_metadata) {
apply { }
}

control deparser(packet_out b, in parsed_packet_t hdr) {
apply { }
}

control verify_checksum(inout parsed_packet_t hdr,
inout local_metadata_t local_metadata) {
apply { }
}

control compute_checksum(inout parsed_packet_t hdr,
inout local_metadata_t local_metadata) {
apply { }
}

V1Switch(parse(), verify_checksum(), ingress(), egress(),
compute_checksum(), deparser()) main;
64 changes: 64 additions & 0 deletions testdata/p4_16_samples_outputs/issue1642-bmv2-first.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <core.p4>
#include <v1model.p4>

header short {
bit<32> f;
}

struct alt_t {
bit<1> valid;
bit<7> port;
}

struct row_t {
alt_t alt0;
alt_t alt1;
}

struct parsed_packet_t {
}

struct local_metadata_t {
short s;
row_t row;
}

parser parse(packet_in pk, out parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control ingress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
local_metadata.s.setValid();
local_metadata.s.f = 32w0;
local_metadata.row.alt0 = local_metadata.row.alt1;
local_metadata.row.alt0.valid = 1w1;
local_metadata.row.alt1.port = local_metadata.row.alt1.port + 7w1;
clone3<row_t>(CloneType.I2E, 32w0, local_metadata.row);
}
}

control egress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
}
}

control deparser(packet_out b, in parsed_packet_t hdr) {
apply {
}
}

control verify_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

control compute_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

V1Switch<parsed_packet_t, local_metadata_t>(parse(), verify_checksum(), ingress(), egress(), compute_checksum(), deparser()) main;

64 changes: 64 additions & 0 deletions testdata/p4_16_samples_outputs/issue1642-bmv2-frontend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <core.p4>
#include <v1model.p4>

header short {
bit<32> f;
}

struct alt_t {
bit<1> valid;
bit<7> port;
}

struct row_t {
alt_t alt0;
alt_t alt1;
}

struct parsed_packet_t {
}

struct local_metadata_t {
short s;
row_t row;
}

parser parse(packet_in pk, out parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control ingress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
local_metadata.s.setValid();
local_metadata.s.f = 32w0;
local_metadata.row.alt0 = local_metadata.row.alt1;
local_metadata.row.alt0.valid = 1w1;
local_metadata.row.alt1.port = local_metadata.row.alt1.port + 7w1;
clone3<row_t>(CloneType.I2E, 32w0, local_metadata.row);
}
}

control egress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
}
}

control deparser(packet_out b, in parsed_packet_t hdr) {
apply {
}
}

control verify_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

control compute_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

V1Switch<parsed_packet_t, local_metadata_t>(parse(), verify_checksum(), ingress(), egress(), compute_checksum(), deparser()) main;

74 changes: 74 additions & 0 deletions testdata/p4_16_samples_outputs/issue1642-bmv2-midend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <core.p4>
#include <v1model.p4>

header short {
bit<32> f;
}

struct alt_t {
bit<1> valid;
bit<7> port;
}

struct row_t {
alt_t alt0;
alt_t alt1;
}

struct parsed_packet_t {
}

struct local_metadata_t {
short s;
row_t row;
}

parser parse(packet_in pk, out parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control ingress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
@hidden action act() {
local_metadata.s.setValid();
local_metadata.s.f = 32w0;
local_metadata.row.alt0.valid = local_metadata.row.alt1.valid;
local_metadata.row.alt0.port = local_metadata.row.alt1.port;
local_metadata.row.alt0.valid = 1w1;
local_metadata.row.alt1.port = local_metadata.row.alt1.port + 7w1;
clone3<row_t>(CloneType.I2E, 32w0, local_metadata.row);
}
@hidden table tbl_act {
actions = {
act();
}
const default_action = act();
}
apply {
tbl_act.apply();
}
}

control egress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
}
}

control deparser(packet_out b, in parsed_packet_t hdr) {
apply {
}
}

control verify_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

control compute_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

V1Switch<parsed_packet_t, local_metadata_t>(parse(), verify_checksum(), ingress(), egress(), compute_checksum(), deparser()) main;

64 changes: 64 additions & 0 deletions testdata/p4_16_samples_outputs/issue1642-bmv2.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <core.p4>
#include <v1model.p4>

header short {
bit<32> f;
}

struct alt_t {
bit<1> valid;
bit<7> port;
}

struct row_t {
alt_t alt0;
alt_t alt1;
}

struct parsed_packet_t {
}

struct local_metadata_t {
short s;
row_t row;
}

parser parse(packet_in pk, out parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control ingress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
local_metadata.s.setValid();
local_metadata.s.f = 0;
local_metadata.row.alt0 = local_metadata.row.alt1;
local_metadata.row.alt0.valid = 1;
local_metadata.row.alt1.port = local_metadata.row.alt1.port + 1;
clone3(CloneType.I2E, 0, local_metadata.row);
}
}

control egress(inout parsed_packet_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) {
apply {
}
}

control deparser(packet_out b, in parsed_packet_t hdr) {
apply {
}
}

control verify_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

control compute_checksum(inout parsed_packet_t hdr, inout local_metadata_t local_metadata) {
apply {
}
}

V1Switch(parse(), verify_checksum(), ingress(), egress(), compute_checksum(), deparser()) main;

Empty file.

0 comments on commit e4386b8

Please sign in to comment.