Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backends/p4test/midend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ MidEnd::MidEnd(P4TestOptions &options, std::ostream *outStream) {
new P4::HandleNoMatch(),
new P4::SimplifyParsers(),
new P4::StrengthReduction(&typeMap),
new P4::EliminateTuples(&typeMap),
options.keepTuples ? nullptr : new P4::EliminateTuples(&typeMap),
new P4::FlattenLogMsg(&typeMap),
new P4::SimplifyComparisons(&typeMap),
new P4::CopyStructures(&typeMap, false),
new P4::CopyStructures(&typeMap, false, false, options.keepTuples),
new P4::NestedStructs(&typeMap),
new P4::StrengthReduction(&typeMap),
new P4::SimplifySelectList(&typeMap),
Expand Down
3 changes: 3 additions & 0 deletions backends/p4test/p4test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ P4TestOptions::P4TestOptions() {
return true;
},
"use passes that use general switch instead of action_run");
registerOption(
"--keepTuples", nullptr, [this](const char *) { return keepTuples = true; },
"keep tuple type, but flatten assignments of them");
}

class P4TestPragmas : public P4::P4COptionPragmaParser {
Expand Down
1 change: 1 addition & 0 deletions backends/p4test/p4test.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class P4TestOptions : public CompilerOptions {
bool validateOnly = false;
bool loadIRFromJson = false;
bool preferSwitch = false;
bool keepTuples = false; // keep tuples but flatten assignments of them
P4TestOptions();
};

Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/common/compiler/midend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void MidEnd::addDefaultPasses() {
new P4::SimplifyComparisons(&typeMap),
// Expand header and struct assignments into sequences of field assignments.
new PassRepeated({
new P4::CopyStructures(&typeMap, false, true, nullptr),
new P4::CopyStructures(&typeMap, false, true, false, nullptr),
}),
new P4::RemoveParserControlFlow(&typeMap),
// Flatten nested list expressions.
Expand Down
15 changes: 13 additions & 2 deletions midend/copyStructures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
#include "copyStructures.h"

#include "frontends/p4/alias.h"
#include "ir/irutils.h"

namespace P4 {

Expand Down Expand Up @@ -66,7 +67,8 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
const auto *ltype = typeMap->getType(statement->left, true);

// If the left type is not a struct like or a header stack, return.
if (!(ltype->is<IR::Type_StructLike>() || ltype->is<IR::Type_Array>())) {
if (!ltype->is<IR::Type_StructLike>() && !ltype->is<IR::Type_Array>() &&
!ltype->is<IR::Type_Tuple>()) {
return statement;
}
/*
Expand Down Expand Up @@ -153,6 +155,15 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
new IR::ArrayIndex(stack->elementType, statement->right, new IR::Constant(i));
retval.push_back(new IR::AssignmentStatement(srcInfo, left, right));
}
} else if (auto *tup = ltype->to<IR::Type_Tuple>()) {
if (!copyTuples) return statement;
int idx = 0;
for (auto *el : tup->components) {
const auto *left = new IR::ArrayIndex(el, statement->left, new IR::Constant(idx));
const auto *right = new IR::ArrayIndex(el, statement->right, new IR::Constant(idx));
retval.push_back(new IR::AssignmentStatement(srcInfo, left, right));
++idx;
}
} else {
if (ltype->is<IR::Type_Header>() || ltype->is<IR::Type_Array>()) {
// Leave headers as they are -- copy_header will also copy the valid bit
Expand All @@ -168,7 +179,7 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
retval.push_back(new IR::AssignmentStatement(statement->srcInfo, left, right));
}
}
return new IR::BlockStatement(statement->srcInfo, std::move(retval));
return IR::inlineBlock(*this, std::move(retval));
}

} // namespace P4
25 changes: 17 additions & 8 deletions midend/copyStructures.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ namespace P4 {
*
* Further, struct initialization is converted to assignment on struct fields
*
* Note, header assignments are not converted in this pass.
* header assignments and tuple assignments are optionally converted in this pass, based
* on constructor argument
*
* @pre none
* @post
Expand All @@ -62,13 +63,22 @@ class DoCopyStructures : public Transform {

/// Do not only copy normal structures but also perform copy assignments for headers.
bool copyHeaders;
/// Also split up assignments of tuples
bool copyTuples;

public:
explicit DoCopyStructures(TypeMap *typeMap, bool errorOnMethodCall, bool copyHeaders = false)
: typeMap(typeMap), errorOnMethodCall(errorOnMethodCall), copyHeaders(copyHeaders) {
explicit DoCopyStructures(TypeMap *typeMap, bool errorOnMethodCall, bool copyHeaders = false,
bool copyTuples = true)
: typeMap(typeMap),
errorOnMethodCall(errorOnMethodCall),
copyHeaders(copyHeaders),
copyTuples(copyTuples) {
CHECK_NULL(typeMap);
setName("DoCopyStructures");
}
// FIXME -- this should be a preorder so we can deal with nested structs directly,
// but that fails because we depend on the typeMap which will be out of date after
// expanding outer copies. So we need to repeat this pass in a loop
const IR::Node *postorder(IR::AssignmentStatement *statement) override;
};

Expand Down Expand Up @@ -117,14 +127,13 @@ class RemoveAliases : public Transform {
class CopyStructures : public PassRepeated {
public:
explicit CopyStructures(TypeMap *typeMap, bool errorOnMethodCall = true,
bool copyHeaders = false, TypeChecking *typeChecking = nullptr) {
bool copyHeaders = false, bool copyTuples = false,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would consider converting this into an option struct. Now that we have C++20 we can also use designated initializers

TypeChecking *typeChecking = nullptr) {
CHECK_NULL(typeMap);
setName("CopyStructures");
if (typeChecking == nullptr) typeChecking = new TypeChecking(nullptr, typeMap);
passes.emplace_back(typeChecking);
passes.emplace_back(new RemoveAliases(typeMap));
passes.emplace_back(typeChecking);
passes.emplace_back(new DoCopyStructures(typeMap, errorOnMethodCall, copyHeaders));
addPasses({typeChecking, new RemoveAliases(typeMap), typeChecking,
new DoCopyStructures(typeMap, errorOnMethodCall, copyHeaders, copyTuples)});
}
};

Expand Down
26 changes: 26 additions & 0 deletions testdata/p4_16_samples/tuple5a.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <core.p4>
@command_line("--keepTuples")
control generic<M>(inout M m);
package top<M>(generic<M> c);

struct t1 {
tuple<bit<8>, bit<16>> a;
bit<32> b;
}

struct t2 {
tuple<bit<32>, t1> x;
tuple<t1, bit<32>> y;
}

control c(inout t2 t) {
apply {
t1 tmp = t.x[1];
t.x[0] += t.y[0].b;
t.x[1].a[0] = t.y[1][7:0];
t.x[1].a[1] = t.y[1][tmp.a[0]+:16];
t.y[0] = tmp;
}
}

top(c()) main;
25 changes: 25 additions & 0 deletions testdata/p4_16_samples_outputs/tuple5a-first.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <core.p4>

@command_line("--keepTuples") control generic<M>(inout M m);
package top<M>(generic<M> c);
struct t1 {
tuple<bit<8>, bit<16>> a;
bit<32> b;
}

struct t2 {
tuple<bit<32>, t1> x;
tuple<t1, bit<32>> y;
}

control c(inout t2 t) {
apply {
t1 tmp = t.x[1];
t.x[0] += t.y[0].b;
t.x[1].a[0] = t.y[1][7:0];
t.x[1].a[1] = t.y[1][tmp.a[0]+:16];
t.y[0] = tmp;
}
}

top<t2>(c()) main;
26 changes: 26 additions & 0 deletions testdata/p4_16_samples_outputs/tuple5a-frontend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <core.p4>

@command_line("--keepTuples") control generic<M>(inout M m);
package top<M>(generic<M> c);
struct t1 {
tuple<bit<8>, bit<16>> a;
bit<32> b;
}

struct t2 {
tuple<bit<32>, t1> x;
tuple<t1, bit<32>> y;
}

control c(inout t2 t) {
@name("c.tmp") t1 tmp_0;
apply {
tmp_0 = t.x[1];
t.x[0] = t.x[0] + t.y[0].b;
t.x[1].a[0] = t.y[1][7:0];
t.x[1].a[1] = t.y[1][tmp_0.a[0]+:16];
t.y[0] = tmp_0;
}
}

top<t2>(c()) main;
38 changes: 38 additions & 0 deletions testdata/p4_16_samples_outputs/tuple5a-midend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <core.p4>

@command_line("--keepTuples") control generic<M>(inout M m);
package top<M>(generic<M> c);
struct t1 {
tuple<bit<8>, bit<16>> a;
bit<32> b;
}

struct t2 {
tuple<bit<32>, t1> x;
tuple<t1, bit<32>> y;
}

control c(inout t2 t) {
tuple<bit<8>, bit<16>> tmp_0_a;
@hidden action tuple5a18() {
tmp_0_a[0] = t.x[1].a[0];
tmp_0_a[1] = t.x[1].a[1];
t.x[0] = t.x[0] + t.y[0].b;
t.x[1].a[0] = t.y[1][7:0];
t.x[1].a[1] = t.y[1][tmp_0_a[0]+:16];
t.y[0].a[0] = tmp_0_a[0];
t.y[0].a[1] = tmp_0_a[1];
t.y[0].b = t.x[1].b;
}
@hidden table tbl_tuple5a18 {
actions = {
tuple5a18();
}
const default_action = tuple5a18();
}
apply {
tbl_tuple5a18.apply();
}
}

top<t2>(c()) main;
25 changes: 25 additions & 0 deletions testdata/p4_16_samples_outputs/tuple5a.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <core.p4>

@command_line("--keepTuples") control generic<M>(inout M m);
package top<M>(generic<M> c);
struct t1 {
tuple<bit<8>, bit<16>> a;
bit<32> b;
}

struct t2 {
tuple<bit<32>, t1> x;
tuple<t1, bit<32>> y;
}

control c(inout t2 t) {
apply {
t1 tmp = t.x[1];
t.x[0] += t.y[0].b;
t.x[1].a[0] = t.y[1][7:0];
t.x[1].a[1] = t.y[1][tmp.a[0]+:16];
t.y[0] = tmp;
}
}

top(c()) main;
Empty file.
Loading