Skip to content

Commit

Permalink
Support for 128 bit bitwise operation
Browse files Browse the repository at this point in the history
* Added movh statement definition
* Added support for 128 bitwise operation
  • Loading branch information
Sosutha committed Oct 1, 2024
1 parent 6b5e688 commit 06eb13a
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 7 deletions.
4 changes: 4 additions & 0 deletions backends/dpdk/dbprint-dpdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ void IR::DpdkMovStatement::dbprint(std::ostream &out) const {
out << "mov " << dst << " " << src << std::endl;
}

void IR::DpdkMovhStatement::dbprint(std::ostream &out) const {
out << "movh " << dst << " " << src << std::endl;
}

} // namespace P4
6 changes: 6 additions & 0 deletions backends/dpdk/dpdk.def
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ class DpdkMovStatement : DpdkUnaryStatement {
#noconstructor
}

class DpdkMovhStatement : DpdkUnaryStatement {
DpdkMovhStatement(Expression dst, Expression src) :
DpdkUnaryStatement("movh"_cs, dst, src) { }
#noconstructor
}

abstract DpdkBinaryStatement : DpdkAssignmentStatement {
Expression src1;
Expression src2;
Expand Down
13 changes: 13 additions & 0 deletions backends/dpdk/dpdkArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1101,10 +1101,23 @@ class ValidateOperandSize : public Inspector {
}

void postorder(const IR::Operation_Binary *binop) override {
if (binop->is<IR::BOr>() || binop->is<IR::BAnd>() || binop->is<IR::BXor>())
if (checkIf128bitOp(binop->left, binop->right)) return;
isValidOperandSize(binop->left);
isValidOperandSize(binop->right);
}

bool checkIf128bitOp(const IR::Expression *src1Op, const IR::Expression *src2Op) {
if (auto src1Type = src1Op->type->to<IR::Type_Bits>()) {
if (src1Type->width_bits() == 128) {
if (auto src2Type = src2Op->type->to<IR::Type_Bits>()) {
if (src2Type->width_bits() == 128) return true;
}
}
}
return false;
}

// Reject all operations except typecast if the operand size is beyond the supported limit
void postorder(const IR::Operation_Unary *unop) override {
if (unop->is<IR::Cast>()) return;
Expand Down
112 changes: 109 additions & 3 deletions backends/dpdk/dpdkHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,20 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) {
} else if (right->is<IR::LOr>() || right->is<IR::LAnd>()) {
process_logical_operation(left, r);
} else if (right->is<IR::BOr>()) {
add_instr(new IR::DpdkOrStatement(left, src1Op, src2Op));
if (checkIf128bitOp(left, src1Op, src2Op))
add128bitInstr(src1Op, src2Op, "or");
else
add_instr(new IR::DpdkOrStatement(left, src1Op, src2Op));
} else if (right->is<IR::BAnd>()) {
add_instr(new IR::DpdkAndStatement(left, src1Op, src2Op));
if (checkIf128bitOp(left, src1Op, src2Op))
add128bitInstr(src1Op, src2Op, "and");
else
add_instr(new IR::DpdkAndStatement(left, src1Op, src2Op));
} else if (right->is<IR::BXor>()) {
add_instr(new IR::DpdkXorStatement(left, src1Op, src2Op));
if (checkIf128bitOp(left, src1Op, src2Op))
add128bitInstr(src1Op, src2Op, "xor");
else
add_instr(new IR::DpdkXorStatement(left, src1Op, src2Op));
} else if (right->is<IR::ArrayIndex>()) {
add_instr(new IR::DpdkMovStatement(a->left, a->right));
} else {
Expand Down Expand Up @@ -1460,4 +1469,101 @@ bool ConvertStatementToDpdk::preorder(const IR::SwitchStatement *s) {
return false;
}

bool ConvertStatementToDpdk::checkIf128bitOp(const IR::Expression *left,
const IR::Expression *src1Op,
const IR::Expression *src2Op) {
if (auto t = left->type->to<IR::Type_Bits>()) {
auto leftWidth = t->width_bits();
if (leftWidth == 128) {
if (auto src1Type = src1Op->type->to<IR::Type_Bits>()) {
if (src1Type->width_bits() == 128) {
if (auto src2Type = src2Op->type->to<IR::Type_Bits>()) {
if (src2Type->width_bits() == 128) return true;
}
}
}
}
}
return false;
}

void ConvertStatementToDpdk::add128bitInstr(const IR::Expression *src1Op,
const IR::Expression *src2Op, const char *op) {
// check bool variable to check and create sandbox struct
// sandbox tmp variable creation
if (!createTmpVar) {
createTmpVar = true;
createTmpVarForSandbox();
}
if (!createSandboxHeaderType) {
createSandboxHeaderType = true;
createSandboxHeader();
}
const IR::Type_Header *Type_Header = nullptr;
const IR::Type_Header *Type_Tmp = nullptr;
for (auto &header : structure->header_types) {
if (header.first == "sandbox_header_h") {
Type_Header = header.second;
} else if (header.first == "tmpVarOp_h") {
Type_Tmp = header.second;
}
}
auto src1OpHeaderInstance =
new IR::Declaration_Variable(src1Op->toString() + "_128", Type_Header);
auto src2OpHeaderInstance =
new IR::Declaration_Variable(src2Op->toString() + "_128", Type_Header);
auto tmpVarOpInstance = new IR::Declaration_Variable(src1Op->toString() + "_tmp", Type_Tmp);
structure->headers.emplace(src1OpHeaderInstance->name, src1OpHeaderInstance);
structure->headers.emplace(src2OpHeaderInstance->name, src2OpHeaderInstance);
structure->headers.emplace(tmpVarOpInstance->name, tmpVarOpInstance);
auto src1OpUpper =
new IR::Member(new IR::PathExpression(src1OpHeaderInstance->name), IR::ID("upper_half"));
auto src1OpLower =
new IR::Member(new IR::PathExpression(src1OpHeaderInstance->name), IR::ID("lower_half"));
auto src2OpUpper =
new IR::Member(new IR::PathExpression(src2OpHeaderInstance->name), IR::ID("upper_half"));
auto src2OpLower =
new IR::Member(new IR::PathExpression(src2OpHeaderInstance->name), IR::ID("lower_half"));
auto tmp = new IR::Member(new IR::PathExpression(tmpVarOpInstance->name), IR::ID("tmp"));
add_instr(new IR::DpdkMovhStatement(src1OpUpper, src1Op));
add_instr(new IR::DpdkMovStatement(src1OpLower, src1Op));
add_instr(new IR::DpdkMovhStatement(src2OpUpper, src2Op));
add_instr(new IR::DpdkMovStatement(src2OpLower, src2Op));
add_instr(new IR::DpdkMovStatement(tmp, src1OpUpper));
if (strcmp(op, "xor") == 0) {
add_instr(new IR::DpdkXorStatement(tmp, tmp, src2OpUpper));
} else if (strcmp(op, "or") == 0) {
add_instr(new IR::DpdkOrStatement(tmp, tmp, src2OpUpper));
} else if (strcmp(op, "and") == 0) {
add_instr(new IR::DpdkAndStatement(tmp, tmp, src2OpUpper));
}
add_instr(new IR::DpdkMovhStatement(src1OpUpper, tmp));
add_instr(new IR::DpdkMovStatement(tmp, src1OpLower));
if (strcmp(op, "xor") == 0) {
add_instr(new IR::DpdkXorStatement(tmp, tmp, src2OpLower));
} else if (strcmp(op, "or") == 0) {
add_instr(new IR::DpdkOrStatement(tmp, tmp, src2OpLower));
} else if (strcmp(op, "and") == 0) {
add_instr(new IR::DpdkAndStatement(tmp, tmp, src2OpLower));
}
add_instr(new IR::DpdkMovStatement(src1OpLower, tmp));
}

void ConvertStatementToDpdk::createSandboxHeader() {
auto fields = new IR::IndexedVector<IR::StructField>;
fields->push_back(new IR::StructField("upper_half", IR::Type_Bits::get(64)));
fields->push_back(new IR::StructField("lower_half", IR::Type_Bits::get(64)));
const IR::Type_Header *headerStruct = new IR::Type_Header(IR::ID("sandbox_header_h"), *fields);
auto name = new cstring("sandbox_header_h");
structure->header_types.emplace(*name, headerStruct);
}

void ConvertStatementToDpdk::createTmpVarForSandbox() {
auto fields = new IR::IndexedVector<IR::StructField>;
fields->push_back(new IR::StructField("tmp", IR::Type_Bits::get(64)));
const IR::Type_Header *headerStruct = new IR::Type_Header(IR::ID("tmpVarOp_h"), *fields);
auto name = new cstring("tmpVarOp_h");
structure->header_types.emplace(*name, headerStruct);
}

} // namespace P4::DPDK
7 changes: 6 additions & 1 deletion backends/dpdk/dpdkHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,17 @@ class ConvertStatementToDpdk : public Inspector {
const IR::P4Parser *parser = nullptr;
const IR::Node *parent = nullptr;
IR::Type_Struct *metadataStruct = nullptr;
bool createSandboxHeaderType = false;
bool createTmpVar = false;

private:
void processHashParams(const IR::Argument *field, IR::Vector<IR::Expression> &components);
bool checkIfBelongToSameHdrMdStructure(const IR::Argument *field);
void updateMdStrAndGenInstr(const IR::Argument *field, IR::Vector<IR::Expression> &components);
cstring getHdrMdStrName(const IR::Member *mem);
bool checkIfConsecutiveHdrMdfields(const IR::Argument *field);
void createSandboxHeader();
void createTmpVarForSandbox();

public:
ConvertStatementToDpdk(P4::ReferenceMap *refmap, P4::TypeMap *typemap,
Expand Down Expand Up @@ -185,8 +189,9 @@ class ConvertStatementToDpdk : public Inspector {
void set_parser(const IR::P4Parser *p) { parser = p; }
void set_parent(const IR::Node *p) { parent = p; }
bool handleConstSwitch(const IR::SwitchStatement *a);
bool checkIf128bitOp(const IR::Expression *, const IR::Expression *, const IR::Expression *);
void add128bitInstr(const IR::Expression *src1Op, const IR::Expression *src2Op, const char *op);
};

/// Only simplify complex expression in ingress/egress.
class ProcessControls : public P4::RemoveComplexExpressionsPolicy {
const std::set<cstring> *process;
Expand Down
42 changes: 39 additions & 3 deletions testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ struct dpdk_pseudo_header_t {
bit<64> pseudo
}

struct tmpVarOp_h {
bit<64> tmp
}

struct sandbox_header_h {
bit<64> upper_half
bit<64> lower_half
}

struct psa_ingress_output_metadata_t {
bit<8> class_of_service
bit<8> clone
Expand Down Expand Up @@ -50,11 +59,38 @@ action NoAction args none {

action macswp args none {
mov m.Ingress_tmp m.Ingress_flg
and m.Ingress_tmp 0xFFFFFFFFFFFFFFFF
movh m.Ingress_tmp_128.upper_half m.Ingress_tmp
mov m.Ingress_tmp_128.lower_half m.Ingress_tmp
movh 128w18446744073709551615_128.upper_half 0xFFFFFFFFFFFFFFFF
mov 128w18446744073709551615_128.lower_half 0xFFFFFFFFFFFFFFFF
mov m.Ingress_tmp_tmp.tmp m.Ingress_tmp_128.upper_half
and m.Ingress_tmp_tmp.tmp 128w18446744073709551615_128.upper_half
movh m.Ingress_tmp_128.upper_half m.Ingress_tmp_tmp.tmp
mov m.Ingress_tmp_tmp.tmp m.Ingress_tmp_128.lower_half
and m.Ingress_tmp_tmp.tmp 128w18446744073709551615_128.lower_half
mov m.Ingress_tmp_128.lower_half m.Ingress_tmp_tmp.tmp
mov m.Ingress_tmp_0 m.Ingress_tmp
and m.Ingress_tmp_0 0xFFFFFFFFFFFFFFFF
movh m.Ingress_tmp_0_128.upper_half m.Ingress_tmp_0
mov m.Ingress_tmp_0_128.lower_half m.Ingress_tmp_0
movh 128w18446744073709551615_128.upper_half 0xFFFFFFFFFFFFFFFF
mov 128w18446744073709551615_128.lower_half 0xFFFFFFFFFFFFFFFF
mov m.Ingress_tmp_0_tmp.tmp m.Ingress_tmp_0_128.upper_half
and m.Ingress_tmp_0_tmp.tmp 128w18446744073709551615_128.upper_half
movh m.Ingress_tmp_0_128.upper_half m.Ingress_tmp_0_tmp.tmp
mov m.Ingress_tmp_0_tmp.tmp m.Ingress_tmp_0_128.lower_half
and m.Ingress_tmp_0_tmp.tmp 128w18446744073709551615_128.lower_half
mov m.Ingress_tmp_0_128.lower_half m.Ingress_tmp_0_tmp.tmp
mov m.Ingress_tmp_1 m.Ingress_tmp_0
and m.Ingress_tmp_1 0xFFFFFFFFFFFFFFFF
movh m.Ingress_tmp_1_128.upper_half m.Ingress_tmp_1
mov m.Ingress_tmp_1_128.lower_half m.Ingress_tmp_1
movh 128w18446744073709551615_128.upper_half 0xFFFFFFFFFFFFFFFF
mov 128w18446744073709551615_128.lower_half 0xFFFFFFFFFFFFFFFF
mov m.Ingress_tmp_1_tmp.tmp m.Ingress_tmp_1_128.upper_half
and m.Ingress_tmp_1_tmp.tmp 128w18446744073709551615_128.upper_half
movh m.Ingress_tmp_1_128.upper_half m.Ingress_tmp_1_tmp.tmp
mov m.Ingress_tmp_1_tmp.tmp m.Ingress_tmp_1_128.lower_half
and m.Ingress_tmp_1_tmp.tmp 128w18446744073709551615_128.lower_half
mov m.Ingress_tmp_1_128.lower_half m.Ingress_tmp_1_tmp.tmp
mov h.dpdk_pseudo_header.pseudo m.Ingress_tmp_1
jmpneq LABEL_END h.dpdk_pseudo_header.pseudo 0x2
mov m.local_metadata_addr h.ethernet.dst_addr
Expand Down

0 comments on commit 06eb13a

Please sign in to comment.