Skip to content

Commit

Permalink
Added support for 128 bit constants usage in dpdk backend (#5074)
Browse files Browse the repository at this point in the history
Signed-off-by: Maheswari Subramanian <[email protected]>
  • Loading branch information
maheswari-s authored Dec 23, 2024
1 parent d8c1d1b commit 4005380
Show file tree
Hide file tree
Showing 79 changed files with 4,432 additions and 1,427 deletions.
1 change: 0 additions & 1 deletion backends/dpdk/DpdkXfail.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ p4c_add_xfail_reason("dpdk"
testdata/p4_16_samples/pna-dpdk-invalid-hdr-warnings5.p4
testdata/p4_16_samples/pna-dpdk-invalid-hdr-warnings6.p4
testdata/p4_16_samples/pna-dpdk-header-union-stack2.p4
testdata/p4_16_samples/dash/dash-pipeline-pna-dpdk.p4
)

p4c_add_xfail_reason("dpdk"
Expand Down
17 changes: 13 additions & 4 deletions backends/dpdk/dpdkArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2957,17 +2957,26 @@ MoveNonHeaderFieldsToPseudoHeader::addAssignmentStmt(const IR::Expression *e) {
const IR::Node *MoveNonHeaderFieldsToPseudoHeader::postorder(IR::AssignmentStatement *assn) {
if (is_all_args_header) return assn;
auto result = new IR::IndexedVector<IR::StatOrDecl>();
if (isLargeFieldOperand(assn->left) && assn->right->is<IR::Constant>()) {
auto leftType = assn->left->type->to<IR::Type_Bits>()->width_bits();
auto rightType = assn->right->type->to<IR::Type_Bits>()->width_bits();
if (leftType == SupportedBitWidth && rightType == leftType) {
auto cst = assn->right->to<IR::Constant>();
if (!cst->fitsUint64()) return assn;
}
}
if ((isLargeFieldOperand(assn->left) && !isLargeFieldOperand(assn->right) &&
!isInsideHeader(assn->right)) ||
(isLargeFieldOperand(assn->left) && assn->right->is<IR::Constant>())) {
auto expr = assn->right;
if (auto base = assn->right->to<IR::Cast>()) expr = base->expr;
if (auto cst = assn->right->to<IR::Constant>()) {
if (!cst->fitsUint64()) {
::P4::error(
ErrorType::ERR_OVERLIMIT,
"DPDK target supports up-to 64-bit immediate values, %1% exceeds the limit",
cst);
::P4::error(ErrorType::ERR_OVERLIMIT,
"DPDK target supports constant values "
"that are up to 64-bits, and also exactly 128-bits, but no other "
"sizes. %1% is not a supported size",
cst);
return assn;
}
}
Expand Down
73 changes: 60 additions & 13 deletions backends/dpdk/dpdkHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) {
"Negate operation is only supported on BIT types");
return false;
}
if (n->expr->type->to<IR::Type_Bits>()->width_bits() == 128) {
if (n->expr->type->to<IR::Type_Bits>()->width_bits() == SupportedBitWidth) {
add128bitComplInstr(left, n->expr);
} else {
BUG_CHECK(metadataStruct, "Metadata structure missing unexpectedly!");
Expand Down Expand Up @@ -632,7 +632,12 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) {
}
} else if (right->is<IR::PathExpression>() || right->is<IR::Member>() ||
right->is<IR::BoolLiteral>() || right->is<IR::Constant>()) {
i = new IR::DpdkMovStatement(a->left, a->right);
if (right->is<IR::Constant>() &&
right->type->to<IR::Type_Bits>()->width_bits() == SupportedBitWidth) {
add128bitMovInstr(left, right);
} else {
i = new IR::DpdkMovStatement(left, right);
}
} else {
std::cerr << right->node_type_name() << std::endl;
BUG("Not implemented.");
Expand Down Expand Up @@ -1506,9 +1511,9 @@ bool ConvertStatementToDpdk::preorder(const IR::SwitchStatement *s) {
bool ConvertStatementToDpdk::checkIf128bitOp(const IR::Expression *src1Op,
const IR::Expression *src2Op) {
if (auto src1Type = src1Op->type->to<IR::Type_Bits>()) {
if (src1Type->width_bits() == 128) {
if (src1Type->width_bits() == SupportedBitWidth) {
if (auto src2Type = src2Op->type->to<IR::Type_Bits>()) {
if (src2Type->width_bits() == 128) return true;
if (src2Type->width_bits() == SupportedBitWidth) return true;
}
}
}
Expand Down Expand Up @@ -1559,22 +1564,25 @@ void ConvertStatementToDpdk::add128bitwiseInstr(const IR::Expression *src1Op,
add_instr(new IR::DpdkMovhStatement(src1OpUpper, src1Op));
add_instr(new IR::DpdkMovStatement(src1OpLower, src1Op));
if (src2Op->is<IR::Constant>()) {
auto ConstVal = src2Op->to<IR::Constant>()->value;
auto upperConst = new IR::Constant(ConstVal >> 64);
auto lowerConst = new IR::Constant(ConstVal & 0xFFFFFFFFFFFFFFFF);
add_instr(new IR::DpdkMovStatement(tmp, src1OpLower));
if (strcmp(op, "xor") == 0) {
add_instr(new IR::DpdkXorStatement(tmp, tmp, src2Op));
add_instr(new IR::DpdkXorStatement(tmp, tmp, lowerConst));
} else if (strcmp(op, "or") == 0) {
add_instr(new IR::DpdkOrStatement(tmp, tmp, src2Op));
add_instr(new IR::DpdkOrStatement(tmp, tmp, lowerConst));
} else if (strcmp(op, "and") == 0) {
add_instr(new IR::DpdkAndStatement(tmp, tmp, src2Op));
add_instr(new IR::DpdkAndStatement(tmp, tmp, lowerConst));
}
add_instr(new IR::DpdkMovStatement(src1Op, tmp));
add_instr(new IR::DpdkMovStatement(tmp, src1OpUpper));
if (strcmp(op, "xor") == 0) {
add_instr(new IR::DpdkXorStatement(tmp, tmp, src2Op));
add_instr(new IR::DpdkXorStatement(tmp, tmp, upperConst));
} else if (strcmp(op, "or") == 0) {
add_instr(new IR::DpdkOrStatement(tmp, tmp, src2Op));
add_instr(new IR::DpdkOrStatement(tmp, tmp, upperConst));
} else if (strcmp(op, "and") == 0) {
add_instr(new IR::DpdkAndStatement(tmp, tmp, src2Op));
add_instr(new IR::DpdkAndStatement(tmp, tmp, upperConst));
}
add_instr(new IR::DpdkMovhStatement(src1Op, tmp));
} else {
Expand Down Expand Up @@ -1624,7 +1632,7 @@ void ConvertStatementToDpdk::createSandboxHeader() {

void ConvertStatementToDpdk::createTmpVarForSandbox() {
auto fields = new IR::IndexedVector<IR::StructField>;
fields->push_back(new IR::StructField("tmp", IR::Type_Bits::get(64)));
fields->push_back(new IR::StructField("inter", IR::Type_Bits::get(64)));
const IR::Type_Header *headerStruct = new IR::Type_Header(IR::ID("_p4c_tmp128_t"), *fields);
structure->header_types.emplace(cstring("_p4c_tmp128_t"), headerStruct);
}
Expand Down Expand Up @@ -1659,8 +1667,11 @@ void ConvertStatementToDpdk::add128ComparisonInstr(cstring true_label, const IR:
add_instr(new IR::DpdkMovhStatement(src1OpUpper, src1Op));
add_instr(new IR::DpdkMovStatement(src1OpLower, src1Op));
if (src2Op->is<IR::Constant>()) {
add_instr(new IR::DpdkXorStatement(src1OpUpper, src1OpUpper, src2Op));
add_instr(new IR::DpdkXorStatement(src1OpLower, src1OpLower, src2Op));
auto ConstVal = src2Op->to<IR::Constant>()->value;
auto upperConst = new IR::Constant(ConstVal >> 64);
auto lowerConst = new IR::Constant(ConstVal & 0xFFFFFFFFFFFFFFFF);
add_instr(new IR::DpdkXorStatement(src1OpUpper, src1OpUpper, upperConst));
add_instr(new IR::DpdkXorStatement(src1OpLower, src1OpLower, lowerConst));
} else {
auto src2OpHeaderName = src2Op->toString();
if (src2Op->is<IR::Member>()) {
Expand Down Expand Up @@ -1734,4 +1745,40 @@ void ConvertStatementToDpdk::add128bitComplInstr(const IR::Expression *dst,
add_instr(new IR::DpdkMovStatement(dst, src1OpLower));
add_instr(new IR::DpdkMovhStatement(dst, src1OpUpper));
}

void ConvertStatementToDpdk::add128bitMovInstr(const IR::Expression *left,
const IR::Expression *right) {
if (!createSandboxHeaderType) {
createSandboxHeaderType = true;
createSandboxHeader();
}
const IR::Type_Header *Type_Header = nullptr;
for (auto header : structure->header_types) {
if (header.first == "_p4c_sandbox_header_t") {
Type_Header = header.second;
}
}
if (Type_Header == nullptr) {
BUG("Header type not found");
}
auto leftHeaderName = left->toString();
if (left->is<IR::Member>()) {
leftHeaderName = left->to<IR::Member>()->member.name;
}
leftHeaderName = leftHeaderName + "_128";
auto leftHeader = new IR::Declaration_Variable(leftHeaderName, Type_Header);
auto leftHeaderInstance = new IR::DpdkHeaderInstance(leftHeader, Type_Header);
structure->addHeaderInstances(leftHeaderInstance);
auto leftUpper =
new IR::Member(new IR::PathExpression("h." + leftHeader->name), IR::ID("upper_half"));
auto leftLower =
new IR::Member(new IR::PathExpression("h." + leftHeader->name), IR::ID("lower_half"));
auto ConstVal = right->to<IR::Constant>()->value;
auto upperConst = new IR::Constant(ConstVal >> 64);
auto lowerConst = new IR::Constant(ConstVal & 0xFFFFFFFFFFFFFFFF);
add_instr(new IR::DpdkMovStatement(leftUpper, upperConst));
add_instr(new IR::DpdkMovStatement(leftLower, lowerConst));
add_instr(new IR::DpdkMovStatement(left, leftLower));
add_instr(new IR::DpdkMovhStatement(left, leftUpper));
}
} // namespace P4::DPDK
3 changes: 3 additions & 0 deletions backends/dpdk/dpdkHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ limitations under the License.

namespace P4::DPDK {

static const int SupportedBitWidth = 128;

class ConvertStatementToDpdk;

/// @brief Name of the metadata used as output port.
Expand Down Expand Up @@ -199,6 +201,7 @@ class ConvertStatementToDpdk : public Inspector {
void add128ComparisonInstr(cstring true_label, const IR::Expression *src1Op,
const IR::Expression *src2Op, const char *op);
void add128bitComplInstr(const IR::Expression *, const IR::Expression *);
void add128bitMovInstr(const IR::Expression *left, const IR::Expression *right);
};
/// Only simplify complex expression in ingress/egress.
class ProcessControls : public P4::RemoveComplexExpressionsPolicy {
Expand Down
14 changes: 6 additions & 8 deletions backends/dpdk/dpdkUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,13 @@ bool reservedNames(P4::ReferenceMap *refMap, const std::vector<cstring> &names,
return true;
}

/// Update bitwidth of Metadata fields to 32 or 64 bits if it 8-bit aligned.
/// The DPDK pipeline requirement is all header/metadata fields to be multiple of 8bits.
/// There is no limitation on total bit width. This function allows any bit width but
/// if the width is odd size, then nearest multiple of 8bit value is returned.
int getMetadataFieldWidth(int width) {
if (width % 8 != 0) {
BUG_CHECK(width <= 64, "Metadata bit-width expected to be within 64-bits, found %1%",
width);
if (width < 32)
return 32;
else
return 64;
if ((width & 0x7) != 0) {
auto resize = (width + 7) & 0xFFFFFFF8;
return resize;
}
return width;
}
Expand Down
2 changes: 1 addition & 1 deletion backends/dpdk/spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ std::ostream &IR::DpdkHeaderType::toSpec(std::ostream &out) const {
}

std::ostream &IR::DpdkHeaderInstance::toSpec(std::ostream &out) const {
out << "header " << name->toString() << " instanceof " << headerType->toString();
out << "header " << name->toString() << " instanceof " << headerType->name.name;
return out;
}

Expand Down
Loading

0 comments on commit 4005380

Please sign in to comment.