diff --git a/.bazelrc b/.bazelrc index 6532c3cafd9..2b925ab17ac 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1 +1,6 @@ +# Remove once #5066 is resolved. +common --enable_workspace +# Enable once #5066 is resolved. +common --noenable_bzlmod + build --action_env=BAZEL_CXXOPTS="-std=c++17" diff --git a/.bazelversion b/.bazelversion index 19b860c1872..815da58b7a9 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -6.4.0 +7.4.1 diff --git a/.clang-format b/.clang-format index 49d5d1b0ad8..c9c143d72ed 100644 --- a/.clang-format +++ b/.clang-format @@ -1,14 +1,5 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# clang-format configuration file. Intended for clang-format >= 4. -# -# For more information, see: -# -# Documentation/process/clang-format.rst -# https://clang.llvm.org/docs/ClangFormat.html -# https://clang.llvm.org/docs/ClangFormatStyleOptions.html -# --- +Language: Cpp BasedOnStyle: Google IndentWidth: 4 FixNamespaceComments: true @@ -22,16 +13,18 @@ DerivePointerAlignment: false PointerAlignment: Right Standard: c++17 IncludeCategories: -# Matches common headers first and sorts them before project includes -- Regex: '^<.+/.*\.h>' - Priority: 2000 -- Regex: '^<.+/.*>' - Priority: 4000 -- Regex: '^<.*\.h>' - Priority: 1000 -- Regex: '^<.*>' - Priority: 3000 -- Regex: 'testgen/.*' - Priority: 6000 -- Regex: '.*' - Priority: 5000 + # Matches common headers first and sorts them before project includes + - Regex: '^<.+/.*\.h>' + Priority: 2000 + - Regex: "^<.+/.*>" + Priority: 4000 + - Regex: '^<.*\.h>' + Priority: 1000 + - Regex: "^<.*>" + Priority: 3000 + - Regex: "testgen/.*" + Priority: 6000 + - Regex: ".*" + Priority: 5000 +IncludeIsMainRegex: '(_test)?$' +... diff --git a/.clangd b/.clangd new file mode 100755 index 00000000000..e95990a8fb5 --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + CompilationDatabase: build/ diff --git a/.github/workflows/ci-lint.yaml b/.github/workflows/ci-lint.yaml index d0988cd90a1..c938f577185 100644 --- a/.github/workflows/ci-lint.yaml +++ b/.github/workflows/ci-lint.yaml @@ -14,6 +14,10 @@ jobs: env: IMAGE_TYPE: test CMAKE_ONLY: ON + CTEST_PARALLEL_LEVEL: 4 + ENABLE_GTESTS: ON + ENABLE_TOFINO: ON + ENABLE_TEST_TOOLS: ON steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 34ad0473aeb..c5906446c4f 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -17,8 +17,8 @@ jobs: build-and-deploy: runs-on: ubuntu-latest env: - DOXYGEN_VERSION: 1.12.0 - DOXYGEN_AWESOME_VERSION: 2.3.3 + DOXYGEN_VERSION: 1.13.0 + DOXYGEN_AWESOME_VERSION: 2.3.4 PR_PATH: pr-preview/${{ github.event.number }} DOMAIN: p4lang.github.io DEPLOYMENT: 'Rocket' diff --git a/CMakeLists.txt b/CMakeLists.txt index bc21ef31e76..f519916729a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,7 +240,6 @@ list (APPEND P4C_LIB_DEPS ${P4C_ABSL_LIBRARIES}) p4c_add_library (rt clock_gettime HAVE_CLOCK_GETTIME) # Check includes. -check_include_file(execinfo.h HAVE_EXECINFO_H) check_include_file(ucontext.h HAVE_UCONTEXT_H) check_include_file(backtrace-supported.h HAVE_LIBBACKTRACE) check_include_file_cxx(mm_malloc.h HAVE_MM_MALLOC_H) diff --git a/README.md b/README.md index 3974d029305..fabf0deddca 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,7 @@ use them, but YMMV. - Python 3 for scripting and running tests -- Optional: Documentation generation requires Doxygen (1.12.0) and Graphviz (2.38.0 or higher). +- Optional: Documentation generation requires Doxygen (1.13.0) and Graphviz (2.38.0 or higher). Backends may have additional dependencies. The dependencies for the backends included with `P4C` are documented here: @@ -311,14 +311,14 @@ pip3 install --user -r requirements.txt **For documentation building:** **Tools** -- Download the Doxygen 1.12.0 binary +- Download the Doxygen 1.13.0 binary ```bash -wget https://github.com/doxygen/doxygen/releases/download/Release_1_12_0/doxygen-1.12.0.linux.bin.tar.gz +wget https://github.com/doxygen/doxygen/releases/download/Release_1_13_0/doxygen-1.13.0.linux.bin.tar.gz ``` - Extract and install Doxygen ```bash -tar xzvf doxygen-1.12.0.linux.bin.tar.gz -cd doxygen-1.12.0 +tar xzvf doxygen-1.13.0.linux.bin.tar.gz +cd doxygen-1.13.0 sudo make install cd .. ``` @@ -328,7 +328,7 @@ sudo apt-get install -y graphviz ``` **Theme** ```bash -git clone --depth 1 -b v2.3.3 https://github.com/jothepro/doxygen-awesome-css ./docs/doxygen/awesome_css +git clone --depth 1 -b v2.3.4 https://github.com/jothepro/doxygen-awesome-css ./docs/doxygen/awesome_css ``` `P4C` also depends on Google Protocol Buffers (Protobuf). `P4C` requires version @@ -362,14 +362,14 @@ sudo pip3 install -r requirements.txt **For documentation building:** **Tools** -- Download the Doxygen 1.12.0 binary +- Download the Doxygen 1.13.0 binary ```bash -wget https://github.com/doxygen/doxygen/releases/download/Release_1_12_0/doxygen-1.12.0.linux.bin.tar.gz +wget https://github.com/doxygen/doxygen/releases/download/Release_1_13_0/doxygen-1.13.0.linux.bin.tar.gz ``` - Extract and install Doxygen ```bash -tar xzvf doxygen-1.12.0.linux.bin.tar.gz -cd doxygen-1.12.0 +tar xzvf doxygen-1.13.0.linux.bin.tar.gz +cd doxygen-1.13.0 sudo make install cd .. ``` @@ -379,7 +379,7 @@ sudo dnf install -y graphviz ``` **Theme** ```bash -git clone --depth 1 -b v2.3.3 https://github.com/jothepro/doxygen-awesome-css ./docs/doxygen/awesome_css +git clone --depth 1 -b v2.3.4 https://github.com/jothepro/doxygen-awesome-css ./docs/doxygen/awesome_css ``` You can also look at the [dependencies installation script](https://github.com/p4lang/p4c/blob/main/tools/install_fedora_deps.sh) @@ -421,14 +421,14 @@ Installing on macOS: ``` **Optional documentation building tools:** - - Download and install the Doxygen 1.12.0 DMG file from [here](https://github.com/doxygen/doxygen/releases/download/Release_1_12_0/Doxygen-1.12.0.dmg). + - Download and install the Doxygen 1.13.0 DMG file from [here](https://github.com/doxygen/doxygen/releases/download/Release_1_13_0/Doxygen-1.13.0.dmg). - Install Graphviz ``` brew install graphviz ``` **Optional Documentation theme:** ``` - git clone --depth 1 -b v2.3.3 https://github.com/jothepro/doxygen-awesome-css ./docs/doxygen/awesome_css + git clone --depth 1 -b v2.3.4 https://github.com/jothepro/doxygen-awesome-css ./docs/doxygen/awesome_css ``` Homebrew offers a `protobuf` formula. It installs version 3.2, which should diff --git a/Version.txt b/Version.txt index 58d8c37e093..3bada59d0ac 100644 --- a/Version.txt +++ b/Version.txt @@ -1 +1 @@ -1.2.5.1 +1.2.5.2 diff --git a/backends/bmv2/simple_switch/main.cpp b/backends/bmv2/simple_switch/main.cpp index 0458cc2caab..aaaa5aa0b44 100644 --- a/backends/bmv2/simple_switch/main.cpp +++ b/backends/bmv2/simple_switch/main.cpp @@ -32,6 +32,7 @@ limitations under the License. #include "ir/json_generator.h" #include "ir/json_loader.h" #include "lib/algorithm.h" +#include "lib/crash.h" #include "lib/error.h" #include "lib/exceptions.h" #include "lib/gc.h" @@ -42,6 +43,7 @@ using namespace P4; int main(int argc, char *const argv[]) { setup_gc_logging(); + setup_signals(); AutoCompileContext autoBMV2Context(new BMV2::SimpleSwitchContext); auto &options = BMV2::SimpleSwitchContext::get().options(); diff --git a/backends/dpdk/DpdkXfail.cmake b/backends/dpdk/DpdkXfail.cmake index 9df082cf9ee..8fc1f992463 100644 --- a/backends/dpdk/DpdkXfail.cmake +++ b/backends/dpdk/DpdkXfail.cmake @@ -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" diff --git a/backends/dpdk/dpdkArch.cpp b/backends/dpdk/dpdkArch.cpp index e6ca7e0a0c7..e540e919b11 100644 --- a/backends/dpdk/dpdkArch.cpp +++ b/backends/dpdk/dpdkArch.cpp @@ -2957,6 +2957,14 @@ 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(); + if (isLargeFieldOperand(assn->left) && assn->right->is()) { + auto leftType = assn->left->type->to()->width_bits(); + auto rightType = assn->right->type->to()->width_bits(); + if (leftType == SupportedBitWidth && rightType == leftType) { + auto cst = assn->right->to(); + if (!cst->fitsUint64()) return assn; + } + } if ((isLargeFieldOperand(assn->left) && !isLargeFieldOperand(assn->right) && !isInsideHeader(assn->right)) || (isLargeFieldOperand(assn->left) && assn->right->is())) { @@ -2964,10 +2972,11 @@ const IR::Node *MoveNonHeaderFieldsToPseudoHeader::postorder(IR::AssignmentState if (auto base = assn->right->to()) expr = base->expr; if (auto cst = assn->right->to()) { 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; } } diff --git a/backends/dpdk/dpdkHelpers.cpp b/backends/dpdk/dpdkHelpers.cpp index 3d623a8c8c5..7be732c77b9 100644 --- a/backends/dpdk/dpdkHelpers.cpp +++ b/backends/dpdk/dpdkHelpers.cpp @@ -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()->width_bits() == 128) { + if (n->expr->type->to()->width_bits() == SupportedBitWidth) { add128bitComplInstr(left, n->expr); } else { BUG_CHECK(metadataStruct, "Metadata structure missing unexpectedly!"); @@ -632,7 +632,12 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) { } } else if (right->is() || right->is() || right->is() || right->is()) { - i = new IR::DpdkMovStatement(a->left, a->right); + if (right->is() && + right->type->to()->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."); @@ -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()) { - if (src1Type->width_bits() == 128) { + if (src1Type->width_bits() == SupportedBitWidth) { if (auto src2Type = src2Op->type->to()) { - if (src2Type->width_bits() == 128) return true; + if (src2Type->width_bits() == SupportedBitWidth) return true; } } } @@ -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()) { + auto ConstVal = src2Op->to()->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 { @@ -1624,7 +1632,7 @@ void ConvertStatementToDpdk::createSandboxHeader() { void ConvertStatementToDpdk::createTmpVarForSandbox() { auto fields = new IR::IndexedVector; - 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); } @@ -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()) { - add_instr(new IR::DpdkXorStatement(src1OpUpper, src1OpUpper, src2Op)); - add_instr(new IR::DpdkXorStatement(src1OpLower, src1OpLower, src2Op)); + auto ConstVal = src2Op->to()->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()) { @@ -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()) { + leftHeaderName = left->to()->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()->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 diff --git a/backends/dpdk/dpdkHelpers.h b/backends/dpdk/dpdkHelpers.h index 7e9979179b3..6f76f912a23 100644 --- a/backends/dpdk/dpdkHelpers.h +++ b/backends/dpdk/dpdkHelpers.h @@ -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. @@ -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 { diff --git a/backends/dpdk/dpdkUtils.cpp b/backends/dpdk/dpdkUtils.cpp index 115ed5dc6ea..9f8bcc5f517 100644 --- a/backends/dpdk/dpdkUtils.cpp +++ b/backends/dpdk/dpdkUtils.cpp @@ -151,15 +151,13 @@ bool reservedNames(P4::ReferenceMap *refMap, const std::vector &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; } diff --git a/backends/dpdk/spec.cpp b/backends/dpdk/spec.cpp index bde9c0b56c9..6aee664891b 100644 --- a/backends/dpdk/spec.cpp +++ b/backends/dpdk/spec.cpp @@ -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; } diff --git a/backends/ebpf/codeGen.cpp b/backends/ebpf/codeGen.cpp index db05340e817..8dc1086123b 100644 --- a/backends/ebpf/codeGen.cpp +++ b/backends/ebpf/codeGen.cpp @@ -61,12 +61,13 @@ bool CodeGenInspector::preorder(const IR::Declaration_Variable *decl) { return false; } +// We count on the optimizer to get rid of 64-bit arithmetic when it's unnecessary static cstring getMask(P4::TypeMap *typeMap, const IR::Node *node) { auto type = typeMap->getType(node, true); cstring mask = cstring::empty; if (auto tb = type->to()) { if (tb->size != 8 && tb->size != 16 && tb->size != 32 && tb->size != 64) - mask = " & ((1 << " + Util::toString(tb->size) + ") - 1)"; + mask = " & ((1ULL << " + Util::toString(tb->size) + ") - 1)"; } return mask; } diff --git a/backends/p4test/midend.cpp b/backends/p4test/midend.cpp index 1ab5238f0e3..4c1da8b857e 100644 --- a/backends/p4test/midend.cpp +++ b/backends/p4test/midend.cpp @@ -43,6 +43,7 @@ limitations under the License. #include "midend/expandLookahead.h" #include "midend/flattenHeaders.h" #include "midend/flattenInterfaceStructs.h" +#include "midend/flattenLogMsg.h" #include "midend/flattenUnions.h" #include "midend/global_copyprop.h" #include "midend/hsIndexSimplify.h" @@ -101,6 +102,7 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::SimplifyParsers(), new P4::StrengthReduction(&typeMap), new P4::EliminateTuples(&typeMap), + new P4::FlattenLogMsg(&typeMap), new P4::SimplifyComparisons(&typeMap), new P4::CopyStructures(&typeMap, false), new P4::NestedStructs(&typeMap), diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index 7390f72a4dc..ac4bded08ff 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -18,6 +18,12 @@ and limitations under the License. namespace P4::TC { +DeparserBodyTranslatorPNA::DeparserBodyTranslatorPNA(const IngressDeparserPNA *deparser) + : CodeGenInspector(deparser->program->refMap, deparser->program->typeMap), + DeparserBodyTranslatorPSA(deparser) { + setName("DeparserBodyTranslatorPNA"); +} + // =====================PNAEbpfGenerator============================= void PNAEbpfGenerator::emitPNAIncludes(EBPF::CodeBuilder *builder) const { builder->appendLine("#include "); @@ -49,10 +55,14 @@ void PNAEbpfGenerator::emitCommonPreamble(EBPF::CodeBuilder *builder) const { void PNAEbpfGenerator::emitInternalStructures(EBPF::CodeBuilder *builder) const { builder->appendLine("struct p4tc_filter_fields p4tc_filter_fields;"); builder->newline(); - builder->appendLine( + builder->append( "struct internal_metadata {\n" " __u16 pkt_ether_type;\n" - "} __attribute__((aligned(4)));"); + "} __attribute__((aligned(4)));\n\n" + "struct skb_aggregate {\n" + " struct p4tc_skb_meta_get get;\n" + " struct p4tc_skb_meta_set set;\n" + "};\n"); builder->newline(); } @@ -266,9 +276,10 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { parser->headerType->as().kind, parser->headerType->as().name, parser->headers->name, compilerGlobalMetadata); - + if (func_name == "process") builder->append(", struct skb_aggregate *sa"); builder->append(")"); builder->newline(); + builder->blockStart(); emitCPUMAPHeadersInitializers(builder); @@ -365,6 +376,27 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { builder->blockStart(); + builder->emitIndent(); + + if ((dynamic_cast(control))->touched_skb_metadata || + (dynamic_cast(deparser))->touched_skb_metadata) { + builder->append("struct skb_aggregate skbstuff = {\n"); + builder->newline(); + builder->increaseIndent(); + builder->emitIndent(); + builder->appendFormat( + ".get = { .bitmask = P4TC_SKB_META_GET_AT_INGRESS_BIT | " + "P4TC_SKB_META_GET_FROM_INGRESS_BIT },"); + builder->newline(); + builder->emitIndent(); + builder->appendFormat(".set = { },"); + builder->newline(); + builder->decreaseIndent(); + builder->append("};\n"); + } else { + builder->append("struct skb_aggregate skbstuff;\n"); + } + emitGlobalMetadataInitializer(builder); emitHeaderInstances(builder); @@ -376,7 +408,7 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { builder->emitIndent(); builder->appendFormat("ret = %v(skb, ", func_name); - builder->appendFormat("(%v %v *) %v, %v);", + builder->appendFormat("(%v %v *) %v, %v, &skbstuff);", parser->headerType->as().kind, parser->headerType->as().name, parser->headers->name, compilerGlobalMetadata); @@ -446,14 +478,12 @@ void TCIngressPipelinePNA::emitGlobalMetadataInitializer(EBPF::CodeBuilder *buil compilerGlobalMetadata); builder->newline(); - // if Traffic Manager decided to pass packet to the kernel stack earlier, send it up immediately + // Make sure drop and recirculate start out false builder->emitIndent(); - builder->append("if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK;"); + builder->append("compiler_meta__->drop = false;"); builder->newline(); - - // Make sure drop starts out false builder->emitIndent(); - builder->append("compiler_meta__->drop = false;"); + builder->append("compiler_meta__->recirculate = false;"); builder->newline(); // workaround to make TC protocol-independent, DO NOT REMOVE @@ -482,24 +512,24 @@ void TCIngressPipelinePNA::emitGlobalMetadataInitializer(EBPF::CodeBuilder *buil void TCIngressPipelinePNA::emitTrafficManager(EBPF::CodeBuilder *builder) { builder->emitIndent(); - builder->appendFormat("if (!%v->drop && %v->egress_port == 0) ", compilerGlobalMetadata, + builder->appendFormat("if (!%v->drop && %v->recirculate) ", compilerGlobalMetadata, compilerGlobalMetadata); builder->blockStart(); - builder->target->emitTraceMessage(builder, "IngressTM: Sending packet up to the kernel stack"); - - // Since XDP helper re-writes EtherType for packets other than IPv4 (e.g., ARP) - // we cannot simply return TC_ACT_OK to pass the packet up to the kernel stack, - // because the kernel stack would receive a malformed packet (with invalid skb->protocol). - // The workaround is to send the packet back to the same interface. If we redirect, - // the packet will be re-written back to the original format. - // At the beginning of the pipeline we check if pass_to_kernel is true and, - // if so, the program returns TC_ACT_OK. builder->emitIndent(); - builder->appendLine("compiler_meta__->pass_to_kernel = true;"); + builder->appendFormat("%v->recirculated = true;", compilerGlobalMetadata); + builder->newline(); builder->emitIndent(); - builder->append("return bpf_redirect(skb->ifindex, BPF_F_INGRESS)"); - builder->endOfStatement(true); + builder->appendFormat("return TC_ACT_UNSPEC;"); + builder->newline(); builder->blockEnd(true); + builder->emitIndent(); + builder->appendFormat("if (!%v->drop && %v->egress_port == 0)", compilerGlobalMetadata, + compilerGlobalMetadata); + builder->newline(); + builder->increaseIndent(); + builder->emitIndent(); + builder->appendLine("return TC_ACT_OK;"); + builder->decreaseIndent(); cstring eg_port = absl::StrFormat("%v->egress_port", compilerGlobalMetadata); cstring cos = @@ -622,7 +652,7 @@ void PnaStateTranslationVisitor::compileExtractField(const IR::Expression *expr, std::string sInt = value.substr(2).c_str(); unsigned int width = std::stoi(sInt); if (widthToExtract != width) { - ::P4::error("Width of the field doesnt match the annotation width. '%1%'", field); + ::P4::error("Width of the field doesn't match the annotation width. '%1%'", field); } noEndiannessConversion = true; } @@ -1218,7 +1248,51 @@ void IngressDeparserPNA::emit(EBPF::CodeBuilder *builder) { prepareBufferTranslator->substitute(this->headers, this->parserHeaders); controlBlock->container->body->apply(*prepareBufferTranslator); + builder->newline(); + builder->emitIndent(); + builder->appendFormat("__u16 saved_proto = 0"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bool have_saved_proto = false"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendLine("// bpf_skb_adjust_room works only when protocol is IPv4 or IPv6"); + builder->emitIndent(); + builder->appendLine("// 0x0800 = IPv4, 0x86dd = IPv6"); + builder->emitIndent(); + builder->append("if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) "); + builder->blockStart(); + builder->emitIndent(); + builder->appendFormat("saved_proto = skb->protocol"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("have_saved_proto = true"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800)"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set))"); + builder->endOfStatement(true); + builder->blockEnd(true); + builder->emitIndent(); + builder->endOfStatement(true); + emitBufferAdjusts(builder); + + builder->newline(); + builder->emitIndent(); + builder->append("if (have_saved_proto) "); + builder->blockStart(); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto)"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set))"); + builder->endOfStatement(true); + builder->blockEnd(true); + builder->newline(); + builder->emitIndent(); builder->appendFormat("%v = %v;", program->packetStartVar, builder->target->dataOffset(program->model.CPacketName.toString())); @@ -1257,6 +1331,65 @@ void IngressDeparserPNA::emitDeclaration(EBPF::CodeBuilder *builder, const IR::D EBPFDeparser::emitDeclaration(builder, decl); } +static void gen_skb_call(EBPF::CodeBuilder *b, const P4::ExternMethod *m, + EBPF::CodeGenInspector *xlat) { + b->appendFormat("/* SKB metadata: call %s */", m->method->name.name.c_str()); + if (m->method->name.name == "get") { + if (!m->expr->arguments->empty()) { + ::P4::error("%1%: takes no arguments", m->method->name.name); + } + b->appendFormat("bpf_p4tc_skb_meta_get(skb,&sa->get,sizeof(sa->get))"); + } else if (m->method->name.name == "set") { + if (!m->expr->arguments->empty()) { + ::P4::error("%1%: takes no arguments", m->method->name.name); + } + b->appendFormat("bpf_p4tc_skb_meta_set(skb,&sa->set,sizeof(sa->set))"); + } +#define GETSET(n) \ + else if (m->method->name.name == ("get_" #n)) { \ + if (!m->expr->arguments->empty()) { \ + P4::error("%1%: takes no arguments", m->method->name.name); \ + } \ + b->append("bpf_p4tc_skb_get_" #n "(skb,&sa->get)"); \ + } \ + else if (m->method->name.name == ("set_" #n)) { \ + if (m->expr->arguments->size() != 1) { \ + P4::error("%1%: requires exactly one argument", m->method->name.name); \ + } \ + b->append("bpf_p4tc_skb_set_" #n "(skb,&sa->set,"); \ + xlat->visit(m->expr->arguments->at(0)->expression); \ + b->append(")"); \ + } + GETSET(tstamp) + GETSET(mark) + GETSET(tc_classid) + GETSET(tc_index) + GETSET(queue_mapping) + GETSET(protocol) + GETSET(tc_at_ingress) + GETSET(from_ingress) +#undef GETSET + else { + P4::error("Unsupported SKB metadata method call %1%", m->method->name.name); + } +} + +static bool is_skb_meta_func(const P4::cstring fname) { + return (fname == "skb_get_meta") || (fname == "skb_set_tstamp") || (fname == "skb_set_mark") || + (fname == "skb_set_queue_mapping") || (fname == "skb_set_protocol") || + (fname == "skb_set_tc_classid") || (fname == "skb_set_tc_index") || + (fname == "skb_set_meta"); +} + +void DeparserBodyTranslatorPNA::processFunction(const P4::ExternFunction *function) { + auto fname = function->expr->method->toString(); + + if (is_skb_meta_func(fname)) { + ::P4::error(ErrorType::ERR_UNEXPECTED, + "Unexpected call to extern function %s in the deparser", fname); + } +} + // =====================ConvertToEbpfPNA============================= const PNAEbpfGenerator *ConvertToEbpfPNA::build(const IR::ToplevelBlock *tlb) { /* @@ -1409,6 +1542,8 @@ bool ConvertToEBPFControlPNA::preorder(const IR::ControlBlock *ctrl) { ++it; control->outputStandardMetadata = *it; + control->touched_skb_metadata = false; + auto codegen = new ControlBodyTranslatorPNA(control, tcIR); codegen->substitute(control->headers, parserHeaders); @@ -1797,6 +1932,42 @@ void ControlBodyTranslatorPNA::processFunction(const P4::ExternFunction *functio "sizeof(key))"); return; } + + auto fname = function->expr->method->toString(); + + if (is_skb_meta_func(fname)) { + if (fname == "skb_get_meta") { + if (function->expr->arguments->size() != 0) { + ::P4::error("skb_get_meta takes no arguments"); + return; + } + builder->emitIndent(); + builder->append("bpf_p4tc_skb_meta_get(skb,&sa->get,sizeof(sa->get))"); + } else if ((fname == "skb_set_tstamp") || (fname == "skb_set_mark") || + (fname == "skb_set_tc_classid") || (fname == "skb_set_tc_index") || + (fname == "skb_set_queue_mapping") || (fname == "skb_set_protocol")) { + if (function->expr->arguments->size() != 1) { + ::P4::error("%1% takes exactly one argument", fname); + return; + } + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_%s(skb,&sa->set,", fname.c_str()); + visit(function->expr->arguments->at(0)); + builder->append(")"); + } else if (fname == "skb_set_meta") { + if (function->expr->arguments->size() != 0) { + ::P4::error("skb_set_meta takes no arguments"); + return; + } + builder->emitIndent(); + builder->append("bpf_p4tc_skb_meta_set(skb,&sa->set,sizeof(sa->set))"); + } else { + BUG_CHECK(0, "impossible method name in %1%", &__func__[0]); + return; + } + (dynamic_cast(control))->touched_skb_metadata = true; + return; + } processCustomExternFunction(function, EBPF::EBPFTypeFactory::instance); } @@ -1971,6 +2142,14 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { builder->target->emitTraceMessage(builder, msgStr.c_str()); } +static void gen_skb_call_ctrl(const EBPFControlPNA *c, EBPF::CodeBuilder *b, + const P4::ExternMethod *m, ControlBodyTranslatorPNA *xlat) { + EBPF::CodeGenInspector *inspector = xlat; + + c->touched_skb_metadata = true; + gen_skb_call(b, m, inspector); +} + void ControlBodyTranslatorPNA::processMethod(const P4::ExternMethod *method) { auto decl = method->object; auto declType = method->originalExternType; @@ -2002,16 +2181,19 @@ void ControlBodyTranslatorPNA::processMethod(const P4::ExternMethod *method) { auto hash = pnaControl->getHash(name); hash->processMethod(builder, method->method->name.name, method->expr, this); return; + } else if (declType->name.name == "tc_skb_metadata") { + gen_skb_call_ctrl(pnaControl, builder, method, this); + return; } else { - ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: Unexpected method call", - method->expr); + ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: [C] [%2%] Unexpected method call", + method->expr, declType->name.name); } } bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { if (auto methodCallExpr = a->right->to()) { - if (methodCallExpr->method->toString() == "is_net_port" || - methodCallExpr->method->toString() == "is_host_port") { + auto mname = methodCallExpr->method->toString(); + if (mname == "is_net_port" || mname == "is_host_port") { builder->emitIndent(); visit(a->left); builder->append(" = "); @@ -2023,6 +2205,17 @@ bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { assert(methodCallExpr->arguments->size() == 1); visit(methodCallExpr->arguments->at(0)); builder->append(");"); + } else if ((mname == "skb_get_tstamp") || (mname == "skb_get_mark") || + (mname == "skb_get_tc_classid") || (mname == "skb_get_tc_index") || + (mname == "skb_get_queue_mapping") || (mname == "skb_get_protocol") || + (mname == "skb_get_tc_at_ingress") || (mname == "skb_get_from_ingress")) { + if (methodCallExpr->arguments->size() != 0) { + ::P4::error("%1% takes no arguments", mname); + return (false); + } + visit(a->left); + builder->appendFormat(" = bpf_p4tc_%s(skb, &sa->get);", mname.c_str()); + return (false); } auto mi = P4::MethodInstance::resolve(methodCallExpr, control->program->refMap, control->program->typeMap); @@ -2055,6 +2248,8 @@ bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { auto pna_meter = dynamic_cast(meter); pna_meter->emitDirectMeterExecute(builder, ext, this, a->left); return false; + } else { + return (false); } } @@ -2114,9 +2309,9 @@ cstring ActionTranslationVisitorPNA::getParamName(const IR::PathExpression *expr void ActionTranslationVisitorPNA::processMethod(const P4::ExternMethod *method) { auto declType = method->originalExternType; auto decl = method->object; - BUG_CHECK(decl->is(), "Extern has not been declared: %1%", decl); - auto di = decl->to(); - auto instanceName = EBPF::EBPFObject::externalName(di); + BUG_CHECK(decl->is(), "Extern has not been declared [A]: %1% (is a %2%)", decl, + decl->node_type_name()); + auto instanceName = EBPF::EBPFObject::externalName(decl->to()); cstring name = EBPF::EBPFObject::externalName(decl); if (declType->name.name == "DirectCounter") { diff --git a/backends/tc/ebpfCodeGen.h b/backends/tc/ebpfCodeGen.h index 44b94629202..4c44b97532b 100644 --- a/backends/tc/ebpfCodeGen.h +++ b/backends/tc/ebpfCodeGen.h @@ -185,11 +185,25 @@ class EBPFTablePNA : public EBPF::EBPFTablePSA { DECLARE_TYPEINFO(EBPFTablePNA, EBPF::EBPFTablePSA); }; +class IngressDeparserPNA; + +class DeparserBodyTranslatorPNA : public EBPF::DeparserBodyTranslatorPSA { + public: + explicit DeparserBodyTranslatorPNA(const IngressDeparserPNA *deparser); + + void processFunction(const P4::ExternFunction *function) override; +}; + class IngressDeparserPNA : public EBPF::EBPFDeparserPSA { public: + mutable bool touched_skb_metadata; + IngressDeparserPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control, const IR::Parameter *parserHeaders, const IR::Parameter *istd) - : EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd) {} + : EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd), + touched_skb_metadata(false) { + codeGen = new DeparserBodyTranslatorPNA(this); + } bool addExternDeclaration = false; bool build() override; @@ -282,9 +296,11 @@ class EBPFControlPNA : public EBPF::EBPFControlPSA { std::map pna_registers; std::map pna_hashes; + mutable bool touched_skb_metadata; + EBPFControlPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control, const IR::Parameter *parserHeaders) - : EBPF::EBPFControlPSA(program, control, parserHeaders) {} + : EBPF::EBPFControlPSA(program, control, parserHeaders), touched_skb_metadata(false) {} EBPFRegisterPNA *getRegister(cstring name) const { auto result = ::P4::get(pna_registers, name); diff --git a/backends/tc/runtime/pna.h b/backends/tc/runtime/pna.h index ae87f545262..42b0714b4a2 100644 --- a/backends/tc/runtime/pna.h +++ b/backends/tc/runtime/pna.h @@ -75,6 +75,7 @@ struct pna_main_output_metadata_t { */ struct pna_global_metadata { bool recirculated; + bool recirculate; bool drop; // NOTE : no drop field in PNA metadata, so we keep drop state as internal metadata. PortId_t egress_port; enum MirrorType mirror_type; @@ -460,4 +461,152 @@ static inline u32 bpf_p4tc_extern_random(u32 min, u32 max) { return (min + bpf_get_prandom_u32()) % (max + 1); } + +#define BIT(x) (1 << x) + +#define P4TC_SKB_META_SET_TSTAMP BIT(0) +#define P4TC_SKB_META_SET_MARK BIT(1) +#define P4TC_SKB_META_SET_CLASSID BIT(2) +#define P4TC_SKB_META_SET_TC_INDEX BIT(3) +#define P4TC_SKB_META_SET_QMAP BIT(4) +#define P4TC_SKB_META_SET_PROTO BIT(5) + +struct p4tc_skb_meta_set { + __u64 tstamp; + __u32 mark; + __u16 tc_classid; + __u16 tc_index; + __u16 queue_mapping; + __be16 protocol; + __u32 bitmask; +}; + +static inline void +bpf_p4tc_skb_set_tstamp(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u64 tstamp) +{ + meta_set->tstamp = tstamp; + meta_set->bitmask |= P4TC_SKB_META_SET_TSTAMP; +} + +static inline void +bpf_p4tc_skb_set_mark(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u32 mark) +{ + meta_set->mark = mark; + meta_set->bitmask |= P4TC_SKB_META_SET_MARK; +} + +static inline void +bpf_p4tc_skb_set_tc_classid(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u32 tc_classid) +{ + meta_set->tc_classid = tc_classid; + meta_set->bitmask |= P4TC_SKB_META_SET_CLASSID; +} + +static inline void +bpf_p4tc_skb_set_tc_index(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u16 tc_index) +{ + meta_set->tc_index = tc_index; + meta_set->bitmask |= P4TC_SKB_META_SET_TC_INDEX; +} + +static inline void +bpf_p4tc_skb_set_queue_mapping(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, + __u16 queue_mapping) +{ + meta_set->queue_mapping = queue_mapping; + meta_set->bitmask |= P4TC_SKB_META_SET_QMAP; +} + +static inline void +bpf_p4tc_skb_set_protocol(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __be16 protocol) +{ + meta_set->protocol = protocol; + meta_set->bitmask |= P4TC_SKB_META_SET_PROTO; +} + +int bpf_p4tc_skb_meta_set(struct __sk_buff *skb, + struct p4tc_skb_meta_set *skb_meta_set, + u32 skb_meta_set__sz) __ksym; + +#define P4TC_SKB_META_GET_AT_INGRESS_BIT BIT(0) +#define P4TC_SKB_META_GET_FROM_INGRESS_BIT BIT(1) + +struct p4tc_skb_meta_get { + u8 tc_at_ingress:1, + from_ingress:1; + u8 bitmask; +}; + +static inline __u64 +bpf_p4tc_skb_get_tstamp(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->tstamp; +} + +static inline __u16 +bpf_p4tc_skb_get_tc_classid(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->tc_classid; +} + +static inline __u16 +bpf_p4tc_skb_get_tc_index(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->tc_index; +} + +static inline __u16 +bpf_p4tc_skb_get_queue_mapping(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->queue_mapping; +} + +static inline __be16 +bpf_p4tc_skb_get_protocol(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->protocol; +} + +static inline int +bpf_p4tc_skb_get_tc_at_ingress(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + if (meta_get->bitmask & P4TC_SKB_META_GET_AT_INGRESS_BIT) + return meta_get->tc_at_ingress; + + return -1; +} + +static inline int +bpf_p4tc_skb_get_from_ingress(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + if (meta_get->bitmask & P4TC_SKB_META_GET_FROM_INGRESS_BIT) + return meta_get->from_ingress; + + return -1; +} + +static inline __u32 +bpf_p4tc_skb_get_mark(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->mark; +} + +int bpf_p4tc_skb_meta_get(struct __sk_buff *skb, + struct p4tc_skb_meta_get *skb_meta_get, + u32 skb_meta_get__sz) __ksym; + #endif /* P4C_PNA_H */ diff --git a/backends/tofino/CMakeLists.txt b/backends/tofino/CMakeLists.txt index 65b933cb5db..8ceaf2e1eb2 100644 --- a/backends/tofino/CMakeLists.txt +++ b/backends/tofino/CMakeLists.txt @@ -1,4 +1,4 @@ -####### Barefoot Compilers Toolchain +# ###### Barefoot Compilers Toolchain MESSAGE("-- Adding p4c-barefoot") include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/spdlog.cmake) @@ -148,11 +148,6 @@ add_custom_target(ctags-all DEPENDS ctags-asm ctags COMMENT "Building ctags") -add_custom_target(cpplint-all - DEPENDS cpplint-asm cpplint - COMMENT "cpplint everything" - ) - if (ENABLE_DOXYGEN) find_package(Doxygen QUIET COMPONENTS dot) if(DOXYGEN_FOUND) @@ -212,7 +207,7 @@ set (BF_P4C_IR_DEF_FILES ${CMAKE_CURRENT_SOURCE_DIR}/bf-p4c/ir/parde.def ${CMAKE_CURRENT_SOURCE_DIR}/bf-p4c/ir/parde-lowered.def ) - + # publish IR_DEF_FILES upstream set (IR_DEF_FILES ${IR_DEF_FILES} ${BF_P4C_IR_DEF_FILES} PARENT_SCOPE) @@ -234,30 +229,9 @@ set (BF_P4C_IR_SRCS bf-p4c/parde/match_register.cpp bf-p4c/parde/clot/clot.cpp bf-p4c/phv/phv.cpp - bf-utils/src/dynamic_hash/dynamic_hash.cpp - bf-utils/src/dynamic_hash/bfn_hash_algorithm.cpp - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_IR_SRCS}") - -set (BF_P4C_IR_HDRS - bf-p4c/midend/path_linearizer.h - bf-p4c/ir/bitrange.h - bf-p4c/ir/control_flow_visitor.h - bf-p4c/ir/gateway_control_flow.h - bf-p4c/ir/gress.h - bf-p4c/ir/ir_enums.h - bf-p4c/ir/thread_visitor.h - bf-p4c/ir/tofino_write_context.h - bf-p4c/ir/unique_id.h - bf-p4c/mau/hash_function.h - bf-p4c/parde/marshal.h - bf-p4c/parde/match_register.h - bf-p4c/parde/clot/clot.h - bf-p4c/phv/phv.h - bf-utils/include/dynamic_hash/dynamic_hash.h - bf-utils/include/dynamic_hash/bfn_hash_algorithm.h + bf-utils/dynamic_hash/dynamic_hash.cpp + bf-utils/dynamic_hash/bfn_hash_algorithm.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_IR_HDRS}") set(QUAL_BF_P4C_IR_SRCS) foreach(src IN LISTS BF_P4C_IR_SRCS) diff --git a/backends/tofino/bf-p4c/CMakeLists.txt b/backends/tofino/bf-p4c/CMakeLists.txt index bd51223c5da..ef99d9d062d 100644 --- a/backends/tofino/bf-p4c/CMakeLists.txt +++ b/backends/tofino/bf-p4c/CMakeLists.txt @@ -1,18 +1,18 @@ # Copyright (C) 2024 Intel Corporation -# +# # 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. -# +# # SPDX-License-Identifier: Apache-2.0 -####### Barefoot back-end +# # # #### Barefoot back-end MESSAGE("-- Adding p4c-barefoot") @@ -44,10 +44,10 @@ endif() # interfaces tools. set (INTERFACES_DIR ${BFN_P4C_SOURCE_DIR}/compiler_interfaces) set(COMPILER_SCHEMA_TARGETS "${INTERFACES_DIR}/schemas/targets.py") - set(DEFAULT_SCHEMA_TARGETS "['tofino', 'tofino2', 'tofino2m', 'tofino2u', 'tofino2a0']") - set(DEFAULT_SCHEMA_P4ARCH "['tna', 't2na', 'psa', 'PISA', 'v1model']") -file(WRITE ${COMPILER_SCHEMA_TARGETS} "TARGETS=${DEFAULT_SCHEMA_TARGETS}\n") -file(APPEND ${COMPILER_SCHEMA_TARGETS} "P4ARCHITECTURES=${DEFAULT_SCHEMA_P4ARCH}\n") +set(DEFAULT_SCHEMA_TARGETS "['tofino', 'tofino2', 'tofino2m', 'tofino2u', 'tofino2a0']") +set(DEFAULT_SCHEMA_P4ARCH "['tna', 't2na', 'psa', 'PISA', 'v1model']") +file(WRITE ${COMPILER_SCHEMA_TARGETS} "TARGETS = ${DEFAULT_SCHEMA_TARGETS}\n") +file(APPEND ${COMPILER_SCHEMA_TARGETS} "P4ARCHITECTURES = ${DEFAULT_SCHEMA_P4ARCH}\n") get_schema_version(manifest_schema MANIFEST_SCHEMA_VERSION) MESSAGE(STATUS "Found manifest schema version ${MANIFEST_SCHEMA_VERSION}") @@ -85,7 +85,7 @@ add_definitions("-DRESOURCES_SCHEMA_VERSION=\"${RESOURCES_SCHEMA_VERSION}\"") set (HAVE_LIBBOOST_GRAPH 1) -set (P4C_LIB_DEPS "${P4C_LIB_DEPS};${Boost_GRAPH_LIBRARY};${LIBDYNHASH_LIBRARY};${Z3_LIB}") +set (P4C_LIB_DEPS "${P4C_LIB_DEPS};${Boost_GRAPH_LIBRARY};${Z3_LIB}") set (P4C_LIB_DEPS ${P4C_LIB_DEPS} PARENT_SCOPE) add_subdirectory(logging) @@ -124,46 +124,7 @@ set (BF_P4C_MIDEND_SRCS midend/type_categories.cpp midend/type_checker.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_MIDEND_SRCS}") - -set (BF_P4C_MIDEND_HDRS - midend/action_synthesis_policy.h - midend/annotate_with_in_hash.h - midend/blockmap.h - midend/check_design_pattern.h - midend/check_header_alignment.h - midend/check_register_actions.h - midend/check_unsupported.h - midend/copy_block_pragmas.h - midend/copy_header.h - midend/defuse.h - midend/drop_packet_with_mirror_engine.h - midend/elim_cast.h - midend/eliminate_tuples.h - midend/fold_constant_hashes.h - midend/desugar_varbit_extract.h - midend/initialize_mirror_io_select.h - midend/move_to_egress.h - midend/normalize_hash_list.h - midend/normalize_params.h - midend/param_binding.h - midend/parser_enforce_depth_req.h - midend/parser_graph.h - midend/register_read_write.h - midend/detect_multiple_pipelines.h - midend/ping_pong_generation.h - midend/rewrite_egress_intrinsic_metadata_header.h - midend/simplify_args.h - midend/simplifyIfStatement.h - midend/simplify_key_policy.h - midend/simplify_nested_if.h - midend/simplify_references.h - midend/alpm.h - midend/table_mutex.h - midend/type_categories.h - midend/type_checker.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_MIDEND_HDRS}") + set (BF_P4C_BACKEND_CONV_SRCS arch/fromv1.0/field_list.cpp @@ -175,17 +136,6 @@ set (BF_P4C_BACKEND_CONV_SRCS arch/fromv1.0/wred.cpp arch/tna/primitives.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_CONV_SRCS}") - -set (BF_P4C_BACKEND_CONV_HDRS - arch/fromv1.0/field_list.h - arch/fromv1.0/lpf.h - arch/fromv1.0/meter.h - arch/fromv1.0/programStructure.h - arch/fromv1.0/stateful_alu.h - arch/fromv1.0/wred.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_CONV_HDRS}") # IR sources that need to go into the frontend library set(QUAL_BF_P4C_IR_SRCS) @@ -220,39 +170,6 @@ set (BF_P4C_BACKEND_COMMON_SRCS common/size_of.cpp common/utils.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_COMMON_SRCS}") - -set (BF_P4C_BACKEND_COMMON_HDRS - common/alias.h - common/autoindent.h - common/check_field_corruption.h - common/check_for_unimplemented_features.h - common/check_header_refs.h - common/check_uninitialized_read.h - common/pragma/collect_global_pragma.h - common/debug_info.h - common/elim_unused.h - common/empty_tableseq.h - common/extract_maupipe.h - common/field_defuse.h - - common/front_end_policy.h - common/bridged_packing.h - common/header_stack.h - common/ir_utils.h - common/map_tables_to_actions.h - common/merge_pov_bits.h - common/multiple_apply.h - common/parse_annotations.h - common/pragma/all_pragmas.h - common/run_id.h - common/scc_toposort.h - common/slice.h - common/size_of.h - common/table_printer.h - common/utils.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_COMMON_HDRS}") set (BF_P4C_BACKEND_CONTROL_PLANE_SRCS control-plane/bfruntime_ext.cpp @@ -260,36 +177,10 @@ set (BF_P4C_BACKEND_CONTROL_PLANE_SRCS control-plane/bfruntime.cpp control-plane/runtime.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_CONTROL_PLANE_SRCS}") - -set (BF_P4C_BACKEND_CONTROL_PLANE_HDRS - control-plane/bfruntime_arch_handler.h - control-plane/bfruntime_ext.h - control-plane/bfruntime.h - control-plane/p4runtime_force_std.h - control-plane/runtime.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_CONTROL_PLANE_HDRS}") set (BF_P4C_BACKEND_LIB_SRCS lib/error_type.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_LIB_SRCS}") - -set (BF_P4C_BACKEND_LIB_HDRS - lib/autoclone.h - lib/boost_graph.h - lib/cmp.h - lib/dyn_vector.h - lib/error_macros.h - lib/error_type.h - lib/log_fixup.h - lib/pad_alignment.h - lib/pointer_wrapper.h - lib/safe_width.h - lib/union_find.hpp - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_LIB_HDRS}") set (BF_P4C_BACKEND_MAU_SRCS mau/action_analysis.cpp @@ -346,7 +237,6 @@ set (BF_P4C_BACKEND_MAU_SRCS mau/validate_actions.cpp mau/walk_power_graph.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_MAU_SRCS}") set (BF_P4C_BACKEND_MAU_TOFINO_SRCS mau/tofino/action_data_bus.cpp @@ -355,78 +245,6 @@ set (BF_P4C_BACKEND_MAU_TOFINO_SRCS mau/tofino/mau_spec.cpp mau/tofino/memories.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_MAU_TOFINO_SRCS}") - - -set (BF_P4C_BACKEND_MAU_HDRS - mau/action_analysis.h - mau/action_data_bus.h - mau/action_format.h - mau/action_mutex.h - mau/adjust_byte_count.h - mau/add_always_run.h - mau/asm_output.h - mau/asm_hash_output.h - mau/attached_entries.h - mau/attached_info.h - mau/attached_output.h - mau/build_power_graph.h - mau/default_next.h - mau/determine_power_usage.h - mau/dump_json_graph.h - mau/dynamic_dep_metrics.h - mau/dynhash.h - mau/field_use.h - mau/finalize_mau_pred_deps_power.h - mau/gateway.h - mau/gen_prim_json.h - mau/handle_assign.h - mau/input_xbar.h - mau/instruction_adjustment.h - mau/instruction_memory.h - mau/instruction_selection.h - mau/ixbar_expr.h - mau/ixbar_info.h - mau/ixbar_realign.h - mau/jbay_next_table.h - mau/mau_alloc.h - mau/mau_power.h - mau/memories.h - mau/next_table.h - mau/payload_gateway.h - mau/push_pop.h - mau/reduction_or.h - mau/remove_noop_gateway.h - mau/resource_estimate.h - mau/resource.h - mau/selector_update.h - mau/simple_power_graph.h - mau/split_gateways.h - mau/stateful_alu.h - mau/static_entries_const_prop.h - mau/table_control_deps.h - mau/table_dependency_graph.h - mau/table_flow_graph.h - mau/table_format.h - mau/table_layout.h - mau/table_mutex.h - mau/table_placement.h - mau/table_seqdeps.h - mau/table_summary.h - mau/table_injected_deps.h - mau/validate_actions.h - mau/walk_power_graph.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_MAU_HDRS}") - -set (BF_P4C_BACKEND_MAU_TOFINO_HDRS - mau/tofino/action_data_bus.h - mau/tofino/asm_output.h - mau/tofino/input_xbar.h - mau/tofino/memories.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_MAU_TOFINO_HDRS}") - set (BF_P4C_BACKEND_PARDE_SRCS parde/add_metadata_pov.cpp @@ -481,76 +299,6 @@ set (BF_P4C_BACKEND_PARDE_SRCS parde/lowered/split_greedy_parser_states.cpp parde/mirror/const_mirror_session_opt.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_PARDE_SRCS}") - -set (BF_P4C_BACKEND_PARDE_HDRS - parde/add_metadata_pov.h - parde/add_parde_metadata.h - parde/allocate_parser_checksum.h - parde/allocate_parser_match_register.h - parde/adjust_extract.h - parde/asm_output.h - parde/characterize_parser.h - parde/check_parser_multi_write.h - parde/coalesce_learning.h - parde/collect_parser_usedef.h - parde/count_strided_header_refs.h - parde/create_pov_encoder.h - parde/decaf.h - parde/deparser_checksum_update.h - parde/dump_parser.h - parde/extract_parser.h - parde/extract_deparser.h - parde/field_packing.h - - parde/infer_payload_offset.h - parde/lower_parser.h - parde/marshal.h - parde/match_register.h - parde/merge_parser_state.h - parde/parde_spec.h - parde/parser_dominator_builder.h - parde/parser_header_sequences.h - parde/parser_loops_info.h - parde/phase0.h - parde/parde_utils.h - parde/parser_info.h - parde/parser_query.h - parde/reset_invalidated_checksum_headers.h - parde/resolve_negative_extract.h - parde/rewrite_parser_locals.h - parde/split_parser_state.h - parde/update_parser_write_mode.h - parde/clot/allocate_clot.h - parde/clot/check_clot_groups.h - parde/clot/clot_candidate.h - parde/clot/clot_info.h - parde/clot/deparse_graph.h - parde/clot/field_slice_extract_info.h - parde/clot/field_slice_set.h - parde/clot/field_pov_analysis.h - parde/clot/header_validity_analysis.h - parde/clot/merge_desugared_varbit_valids.h - parde/clot/pseudoheader.h - parde/clot/pragma/do_not_use_clot.h - parde/common/allocators.h - parde/common/match_reducer.h - parde/lowered/compute_buffer_requirements.h - parde/lowered/compute_init_zero_containers.h - parde/lowered/compute_lowered_deparser_ir.h - parde/lowered/compute_lowered_parser_ir.h - parde/lowered/compute_multi_write_containers.h - parde/lowered/eliminate_empty_states.h - parde/lowered/extract_simplifier.h - parde/lowered/helpers.h - parde/lowered/hoist_common_match_operations.h - - parde/lowered/merge_lowered_parser_states.h - parde/lowered/rewrite_emit_clot.h - parde/lowered/split_greedy_parser_states.h - parde/mirror/const_mirror_session_opt.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_PARDE_HDRS}") set (BF_P4C_BACKEND_PHV_SRCS phv/check_unallocated.cpp @@ -641,110 +389,6 @@ set (BF_P4C_BACKEND_PHV_SRCS phv/v2/types.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_PHV_SRCS}") - -set (BF_P4C_BACKEND_PHV_HDRS - phv/dump_table_flow_graph.h - phv/constraints/constraints.h - phv/action_phv_constraints.h - phv/add_initialization.h - phv/add_special_constraints.h - phv/init_in_mau.h - phv/allocate_phv.h - phv/allocate_temps_and_finalize_liverange.h - phv/error.h - phv/asm_output.h - phv/auto_init_metadata.h - phv/check_unallocated.h - phv/cluster_phv_operations.h - phv/collect_strided_headers.h - phv/collect_table_keys.h - phv/create_thread_local_instances.h - phv/parser_extract_balance_score.h - phv/finalize_physical_liverange.h - phv/finalize_stage_allocation.h - phv/live_range_split.h - phv/make_clusters.h - phv/mau_backtracker.h - phv/optimize_phv.h - phv/action_packing_validator_interface.h - phv/parser_packing_validator_interface.h - phv/legacy_action_packing_validator.h - phv/parde_phv_constraints.h - phv/add_alias_allocation.h - phv/phv_analysis.h - phv/phv_fields.h - phv/phv_parde_mau_use.h - phv/phv_spec.h - phv/split_padding.h - phv/table_phv_constraints.h - phv/validate_allocation.h - phv/analysis/build_mutex.h - phv/analysis/critical_path_clusters.h - phv/analysis/dark_live_range.h - phv/analysis/deparser_zero.h - phv/analysis/dominator_tree.h - phv/analysis/header_mutex.h - phv/analysis/memoize_min_stage.h - phv/analysis/meta_live_range.h - phv/analysis/mutex_overlay.h - phv/analysis/non_mocha_dark_fields.h - phv/analysis/live_range_shrinking.h - phv/analysis/pack_conflicts.h - phv/analysis/parser_critical_path.h - phv/analysis/dark.h - phv/analysis/jbay_phv_analysis.h - phv/analysis/mocha.h - phv/pragma/pa_alias.h - phv/pragma/pa_atomic.h - phv/pragma/pa_byte_pack.h - phv/pragma/pa_container_size.h - phv/pragma/pa_container_type.h - phv/pragma/pa_deparser_zero.h - phv/pragma/pa_mutually_exclusive.h - phv/pragma/pa_no_init.h - phv/pragma/pa_no_overlay.h - phv/pragma/pa_no_pack.h - phv/pragma/pa_solitary.h - phv/pragma/phv_pragmas.h - phv/pragma/pretty_print.h - phv/action_source_tracker.h - phv/slicing/types.h - phv/slicing/phv_slicing_split.h - phv/slicing/phv_slicing_iterator.h - phv/slicing/phv_slicing_dfs_iterator.h - phv/solver/symbolic_bitvec.h - phv/solver/action_constraint_solver.h - phv/transforms/auto_alias.h - phv/utils/live_range_report.h - phv/utils/report.h - phv/utils/slice_alloc.h - phv/utils/tables_to_ids.h - phv/utils/utils.h - phv/utils/liverange_opti_utils.h - phv/fieldslice_live_range.h - phv/alloc_setting.h - phv/v2/phv_kit.h - phv/v2/allocator_base.h - phv/v2/allocator_metrics.h - phv/v2/copacker.h - phv/v2/phv_allocation_v2.h - phv/v2/parser_packing_validator.h - phv/v2/action_packing_validator.h - phv/v2/greedy_allocator.h - phv/v2/kind_size_indexed_map.h - phv/v2/table_replay_friendly_constraints.cpp - phv/v2/trivial_allocator.h - phv/v2/tx_score.h - phv/v2/greedy_tx_score.h - phv/v2/utils_v2.h - phv/v2/sort_macros.h - phv/v2/metadata_initialization.h - phv/v2/smart_packing.h - phv/v2/types.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_PHV_HDRS}") - set (BF_P4C_BACKEND_ARCH_SRCS arch/arch.cpp arch/arch_spec.cpp @@ -777,64 +421,7 @@ set (BF_P4C_BACKEND_ARCH_SRCS arch/fromv1.0/v1_converters.cpp arch/fromv1.0/v1_program_structure.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_ARCH_SRCS}") -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "arch/t2na.cpp") - - -set (BF_P4C_BACKEND_ARCH_HDRS - arch/arch.h - arch/arch_spec.h - arch/add_t2na_meta.h - arch/intrinsic_metadata.h - arch/bridge_metadata.h - arch/check_extern_invocation.h - arch/collect_bridged_fields.h - arch/collect_hardware_constrained_fields.h - arch/helpers.h - arch/program_structure.h - arch/psa/psa.h - arch/psa/psa_converters.h - arch/psa/psa_model.h - arch/psa/programStructure.h - arch/psa/rewrite_packet_path.h - arch/psa/rewrite_bridge_metadata.h - arch/remove_set_metadata.h - arch/rewrite_action_selector.h - arch/tna.h - arch/t2na.h - - - arch/v1model.h - arch/fromv1.0/add_metadata_parser_states.h - arch/fromv1.0/egress_packet_length.h - arch/fromv1.0/checksum.h - arch/fromv1.0/mirror.h - arch/fromv1.0/parser_counter.h - arch/fromv1.0/phase0.h - arch/fromv1.0/resubmit.h - arch/fromv1.0/v1_converters.h - arch/fromv1.0/v1_program_structure.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_ARCH_HDRS}") - -set (BF_P4C_BACKEND_LOGGING_HDRS - logging/bf_error_reporter.h - logging/collect_diagnostic_checks.h - logging/constrained_fields.h - logging/container_size_extractor.h - logging/event_logger.h - logging/filelog.h - logging/logging.h - logging/manifest.h - logging/group_constraint_extractor.h - logging/pass_manager.h - logging/phv_logging.h - logging/resources.h - logging/resources_parser.h - logging/resources_clot.h - logging/source_info_logging.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_LOGGING_HDRS}") + set (BF_P4C_BACKEND_LOGGING_SRCS logging/bf_error_reporter.cpp logging/collect_diagnostic_checks.cpp @@ -850,8 +437,7 @@ set (BF_P4C_BACKEND_LOGGING_SRCS logging/resources_parser.cpp logging/resources_clot.cpp logging/source_info_logging.cpp - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_LOGGING_SRCS}") +) set (BF_P4C_BACKEND_MAIN_SRCS asm.cpp @@ -860,16 +446,6 @@ set (BF_P4C_BACKEND_MAIN_SRCS device.cpp midend.cpp ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_MAIN_SRCS}") - -set (BF_P4C_BACKEND_MAIN_HDRS - asm.h - backend.h - bf-p4c-options.h - device.h - midend.h - ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${BF_P4C_BACKEND_MAIN_HDRS}") set (BF_P4C_IR_DEF_FILES ${CMAKE_CURRENT_SOURCE_DIR}/bf-p4c/ir/tofino.def @@ -882,13 +458,6 @@ set (BF_P4C_IR_DEF_FILES # publish IR_DEF_FILES upstream set (IR_DEF_FILES ${IR_DEF_FILES} ${BF_P4C_IR_DEF_FILES} PARENT_SCOPE) -# do not add to cpp lint. They are added as part of the p4c-graphs backend -set (BF_P4C_GRAPHS_HDRS - ${P4C_SOURCE_DIR}/backends/graphs/controls.h - ${P4C_SOURCE_DIR}/backends/graphs/graphs.h - ${P4C_SOURCE_DIR}/backends/graphs/parsers.h - ${P4C_SOURCE_DIR}/backends/graphs/graph_visitor.h - ) set (BF_P4C_GRAPHS_SRCS ${P4C_SOURCE_DIR}/backends/graphs/controls.cpp ${P4C_SOURCE_DIR}/backends/graphs/graphs.cpp @@ -954,12 +523,11 @@ set (P4C_BAREFOOT_SRCS ${BF_P4C_BACKEND_CONV_SRCS} ${BF_P4C_GRAPHS_SRCS} ) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${P4C_BAREFOOT_SRCS}") if(BUILD_STATIC_BFP4C_LIBS) - add_library(tofinobackend STATIC ${BF_P4C_SOURCES}) + add_library(tofinobackend STATIC ${BF_P4C_SOURCES}) else() - add_library(tofinobackend OBJECT ${BF_P4C_SOURCES}) + add_library(tofinobackend OBJECT ${BF_P4C_SOURCES}) endif() target_link_libraries(tofinobackend PRIVATE absl::prefetch ${P4C_LIB_DEPS} controlplane-gen ir) target_include_directories( @@ -973,11 +541,11 @@ target_include_directories( add_dependencies(tofinobackend frontend genLogging bfn_p4runtime) if(BUILD_STATIC_BFP4C_LIBS) - add_library(bfp4c STATIC ${P4C_BAREFOOT_SRCS}) + add_library(bfp4c STATIC ${P4C_BAREFOOT_SRCS}) else() - # For objlib there is no way (as far as I know) to encompass smaller libraries (namely adding - # $ $ to sources does not work) - add_library(bfp4c OBJECT ${P4C_BAREFOOT_SRCS}) + # For objlib there is no way (as far as I know) to encompass smaller libraries (namely adding + # $ $ to sources does not work) + add_library(bfp4c OBJECT ${P4C_BAREFOOT_SRCS}) endif() target_link_libraries (bfp4c tofinobackend bfn_p4runtime ${P4C_LIBRARIES} ${P4C_LIB_DEPS} ${CMAKE_THREAD_LIBS_INIT}) @@ -1000,31 +568,31 @@ if (ENABLE_BAREFOOT_INTERNAL) endif() if(BUILD_STATIC_BFP4C_LIBS) - add_executable(p4c-barefoot p4c-barefoot.cpp) - # --whole-archive prevents the linker from removing unused symbols - # - # This prevents an issue with non-unified builds and P4 primitives being - # undefined. The file "bf-p4c/arch/fromv1.0/primitives.cpp" defines a number - # of primitives (e.g., bypass_egress). This is done by subclassing - # PrimitiveConverter and creating a singleton instance, which registers - # itself with the PrimitiveConverter base class. These singleton instances are - # omitted during linking of the non-unified builds, and so the primitives are - # not registered. - # - # FIXME: Understand why the symbols are present in unified builds but not - # non-unified builds and remove the --whole-archive flag if possible. - target_link_libraries(p4c-barefoot + add_executable(p4c-barefoot p4c-barefoot.cpp) + # --whole-archive prevents the linker from removing unused symbols + # + # This prevents an issue with non-unified builds and P4 primitives being + # undefined. The file "bf-p4c/arch/fromv1.0/primitives.cpp" defines a number + # of primitives (e.g., bypass_egress). This is done by subclassing + # PrimitiveConverter and creating a singleton instance, which registers + # itself with the PrimitiveConverter base class. These singleton instances are + # omitted during linking of the non-unified builds, and so the primitives are + # not registered. + # + # FIXME: Understand why the symbols are present in unified builds but not + # non-unified builds and remove the --whole-archive flag if possible. + target_link_libraries(p4c-barefoot -Wl,--whole-archive bfp4c -Wl,--no-whole-archive) else() - # No transitive library dependencies for objlibs :-/, bring tofinobackend & bfn_p4runtime - # here explictly as well as their dependencies - add_executable(p4c-barefoot p4c-barefoot.cpp $ + # No transitive library dependencies for objlibs :-/, bring tofinobackend & bfn_p4runtime + # here explictly as well as their dependencies + add_executable(p4c-barefoot p4c-barefoot.cpp $ $ $) - target_link_libraries(p4c-barefoot ${P4C_LIBRARIES} ${P4C_LIB_DEPS} ${CMAKE_THREAD_LIBS_INIT}) - # FIXME: These includes should be exported by earlier libraries. - target_include_directories( + target_link_libraries(p4c-barefoot ${P4C_LIBRARIES} ${P4C_LIB_DEPS} ${CMAKE_THREAD_LIBS_INIT}) + # FIXME: These includes should be exported by earlier libraries. + target_include_directories( p4c-barefoot # We also export Z3's includes with the common library. # This is necessary because the z3 target itself does not export its includes. @@ -1238,7 +806,7 @@ endif() install (FILES ${P4C_BINARY_DIR}/p4c_src/main.py DESTINATION ${P4C_ARTIFACTS_OUTPUT_DIRECTORY}/p4c_src) -################ Proto +# # # ############# Proto set (BFN_P4RUNTIME_DIR ${CMAKE_CURRENT_SOURCE_DIR}/control-plane/proto) set (BFN_P4RUNTIME_INFO_PROTO ${BFN_P4RUNTIME_DIR}/barefoot/p4info.proto) set (BFN_P4RUNTIME_INFO_GEN_SRCS ${P4C_BINARY_DIR}/control-plane/barefoot/p4info.pb.cc) @@ -1264,15 +832,15 @@ add_custom_command( COMMENT "Generating protobuf files for p4info." ) if(BUILD_STATIC_BFP4C_LIBS) - add_library(bfn_p4runtime STATIC ${BFN_P4RUNTIME_INFO_GEN_SRCS}) + add_library(bfn_p4runtime STATIC ${BFN_P4RUNTIME_INFO_GEN_SRCS}) else() - add_library(bfn_p4runtime OBJECT ${BFN_P4RUNTIME_INFO_GEN_SRCS}) + add_library(bfn_p4runtime OBJECT ${BFN_P4RUNTIME_INFO_GEN_SRCS}) endif() target_link_libraries(bfn_p4runtime PUBLIC controlplane-gen PRIVATE absl::prefetch) set_source_files_properties(${BFN_P4RUNTIME_INFO_GEN_SRCS} PROPERTIES GENERATED TRUE) add_dependencies(bfn_p4runtime barefootdir controlplane) -################ Testing +# # # ############# Testing if (ENABLE_GTESTS) # # Tofino-specific GTests. @@ -1348,8 +916,8 @@ if (ENABLE_GTESTS) add_library (bf_gtest_support "${P4HEADERS_CPP}" "${CMAKE_CURRENT_SOURCE_DIR}/test/gtest/bf_gtest_helpers.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/test/gtest/tofino_gtest_utils.cpp") - # test_bf_gtest_helpers should be in its own testlib - & requies 'whole_archive' hack! - # Leave it in GTEST_BF_P4C_SOURCES for now. + # test_bf_gtest_helpers should be in its own testlib - & requies 'whole_archive' hack! + # Leave it in GTEST_BF_P4C_SOURCES for now. target_link_libraries (bf_gtest_support PRIVATE absl::flat_hash_map PRIVATE absl::flat_hash_set PRIVATE ir ${P4C_LIB_DEPS}) target_include_directories( bf_gtest_support @@ -1460,8 +1028,8 @@ if (ENABLE_GTESTS) ${BF_P4C_GRAPHS_SRCS} ) if (NOT BUILD_STATIC_BFP4C_LIBS) - # objlibs cannot be linked, need to add objects here explicitly - set (GTEST_BF_P4C_SOURCES ${GTEST_BF_P4C_SOURCES} + # objlibs cannot be linked, need to add objects here explicitly + set (GTEST_BF_P4C_SOURCES ${GTEST_BF_P4C_SOURCES} $ $) endif() @@ -1470,7 +1038,7 @@ if (ENABLE_GTESTS) set (GTEST_SOURCES ${GTEST_SOURCES} ${GTEST_BF_P4C_SOURCES} PARENT_SCOPE) set (GTEST_LDADD ${GTEST_LDADD} - "bf_gtest_support;tofinobackend;${LIBDYNHASH_LIBRARY};bfn_p4runtime" PARENT_SCOPE) + "bf_gtest_support;tofinobackend;bfn_p4runtime" PARENT_SCOPE) # TODO: re-enable this test once p4-test is added to the build system # add_test(NAME test_p4c_driver @@ -1481,5 +1049,3 @@ if (ENABLE_GTESTS) endif(ENABLE_GTESTS) -set(EVEN_MORE_FILES_TO_LINT p4c-barefoot.cpp) -add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${EVEN_MORE_FILES_TO_LINT}") diff --git a/backends/tofino/bf-p4c/bf-p4c-options.cpp b/backends/tofino/bf-p4c/bf-p4c-options.cpp index 5ad102b7eb5..c7d5efd2018 100644 --- a/backends/tofino/bf-p4c/bf-p4c-options.cpp +++ b/backends/tofino/bf-p4c/bf-p4c-options.cpp @@ -905,24 +905,24 @@ BFNOptionPragmaParser::parseCompilerOption(const IR::Annotation *annotation) { // Parsing of option pragmas is done early in the compiler, before P4₁₆ // annotations are parsed, so we are responsible for doing our own parsing // here. - auto args = &annotation->getExpr(); - if (args->empty()) { - auto parseResult = + const IR::Vector *args = nullptr; + if (annotation->needsParsing()) { + args = P4::P4ParserDriver::parseExpressionList(annotation->srcInfo, annotation->getUnparsed()); - if (parseResult != nullptr) { - args = parseResult; - } + } else { + args = &annotation->getExpr(); } + CHECK_NULL(args); bool first = true; - for (auto *arg : *args) { + for (const auto *arg : *args) { // Try to convert the parsed expression to a valid option string cstring optionString = ""_cs; - if (auto *argString = arg->to()) { + if (const auto *argString = arg->to()) { optionString = argString->value; } else { // The expression is not a IR::StringLiteral, but it can still be a valid integer - if (auto *argConstant = arg->to()) { + if (const auto *argConstant = arg->to()) { optionString = std::to_string(argConstant->asInt()); } else { // The expression is neither a IR::StringLiteral or IR::Constant and so is invalid @@ -932,7 +932,7 @@ BFNOptionPragmaParser::parseCompilerOption(const IR::Annotation *annotation) { } } - if (first && !cmdLinePragmas.count(optionString)) { + if (first && (cmdLinePragmas.count(optionString) == 0U)) { ::warning("Unknown @pragma command_line %1%", annotation); return std::nullopt; } diff --git a/backends/tofino/bf-p4c/control-plane/bfruntime_ext.h b/backends/tofino/bf-p4c/control-plane/bfruntime_ext.h index 82a4aee7c91..9dedb576bd8 100644 --- a/backends/tofino/bf-p4c/control-plane/bfruntime_ext.h +++ b/backends/tofino/bf-p4c/control-plane/bfruntime_ext.h @@ -25,7 +25,7 @@ #include "barefoot/p4info.pb.h" #pragma GCC diagnostic pop #include "backends/tofino/bf-p4c/device.h" -#include "backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h" +#include "backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.h" #include "bfruntime.h" namespace BFN { diff --git a/backends/tofino/bf-p4c/driver/barefoot.py b/backends/tofino/bf-p4c/driver/barefoot.py index b0fe5206e52..23233325fa5 100755 --- a/backends/tofino/bf-p4c/driver/barefoot.py +++ b/backends/tofino/bf-p4c/driver/barefoot.py @@ -76,16 +76,6 @@ def checkEnv(): return None -# Search the environment for assets -# if os.environ['P4C_BUILD_TYPE'] == "DEVELOPER": -# bfas = find_file('bf-asm', 'bfas') -# else: -# bfas = find_file(os.environ['P4C_BIN_DIR'], 'bfas') - -bfrt_schema = find_file(os.environ['P4C_BIN_DIR'], 'bfrt_schema.py') -p4c_gen_conf = find_file(os.environ['P4C_BIN_DIR'], 'p4c-gen-conf') - - class BarefootBackend(BackendDriver): """! Customized version of public driver to specify our options, @@ -112,9 +102,6 @@ def __init__(self, target, arch, argParser): self.add_command('preclean-runtime', 'rm') self.add_command('preprocessor', 'cc') self.add_command('compiler', os.path.join(os.environ['P4C_BIN_DIR'], 'p4c-barefoot')) - # self.add_command('assembler', bfas) - self.add_command('bf-rt-verifier', bfrt_schema) - self.add_command('p4c-gen-conf', p4c_gen_conf) self.add_command('cleaner', 'rm') self.runVerifiers = False @@ -192,6 +179,12 @@ def add_command_line_options(self): default=False, help="Add source outputs to the archive.", ) + self._argGroup.add_argument( + "--enable-bf-asm", + action="store_true", + default=False, + help="Use the assembler to generate a binary.", + ) self._argGroup.add_argument( "--bf-rt-schema", action="store", @@ -494,6 +487,20 @@ def process_command_line_options(self, opts): """! Main parsing or command line options @param opts Object holding set arguments """ + # Add assembler options if they are available. + if opts.enable_bf_asm or os.getenv("ENABLE_BF_ASM"): + if os.environ['P4C_BUILD_TYPE'] == "DEVELOPER": + bfas = find_file('bf-asm', 'bfas') + else: + bfas = find_file(os.environ['P4C_BIN_DIR'], 'bfas') + + bfrt_schema = find_file(os.environ['P4C_BIN_DIR'], 'bfrt_schema.py') + p4c_gen_conf = find_file(os.environ['P4C_BIN_DIR'], 'p4c-gen-conf') + self.add_command('assembler', bfas) + self.add_command('bf-rt-verifier', bfrt_schema) + self.add_command('p4c-gen-conf', p4c_gen_conf) + self._commandsEnabled.append('assembler') + BackendDriver.process_command_line_options(self, opts) # P4 program name is by default derived from the source file name, diff --git a/backends/tofino/bf-p4c/driver/p4c.tofino.cfg b/backends/tofino/bf-p4c/driver/p4c.tofino.cfg index b188df3953c..09fbd5bfc24 100644 --- a/backends/tofino/bf-p4c/driver/p4c.tofino.cfg +++ b/backends/tofino/bf-p4c/driver/p4c.tofino.cfg @@ -18,7 +18,6 @@ from p4c_src.driver import BackendDriver import p4c_src.barefoot as bfn - class TofinoBackend(bfn.BarefootBackend): def __init__(self, target, arch, argParser): bfn.BarefootBackend.__init__(self, target, arch, argParser) @@ -26,7 +25,12 @@ class TofinoBackend(bfn.BarefootBackend): # command options self.config_preprocessor("__TARGET_TOFINO__=1") self.config_compiler("__TARGET_TOFINO__=1") - # self.config_assembler("tofino") + + def process_command_line_options(self, opts): + if opts.enable_bf_asm or os.getenv("ENABLE_BF_ASM"): + self.config_assembler("tofino") + bfn.BarefootBackend.process_command_line_options(self, opts) + # Tofino Native Architecture tna_target = TofinoBackend('tofino', 'tna', argParser) diff --git a/backends/tofino/bf-p4c/driver/p4c.tofino2.cfg b/backends/tofino/bf-p4c/driver/p4c.tofino2.cfg index a4788a6e04c..1a8852ffc41 100644 --- a/backends/tofino/bf-p4c/driver/p4c.tofino2.cfg +++ b/backends/tofino/bf-p4c/driver/p4c.tofino2.cfg @@ -35,7 +35,11 @@ class Tofino2Backend(bfn.BarefootBackend): self.config_preprocessor("__TOFINO2_VARIANT__={}".format(Tofino2Variants[target])) self.config_compiler("__TARGET_TOFINO__=2") self.config_compiler("__TOFINO2_VARIANT__={}".format(Tofino2Variants[target])) - # self.config_assembler(target) + + def process_command_line_options(self, opts): + if opts.enable_bf_asm or os.getenv("ENABLE_BF_ASM"): + self.config_assembler(self.target) + bfn.BarefootBackend.process_command_line_options(self, opts) for t in Tofino2Variants.keys(): config.target.append(Tofino2Backend(t, 't2na', argParser)) diff --git a/backends/tofino/bf-p4c/mau/hash_function.cpp b/backends/tofino/bf-p4c/mau/hash_function.cpp index 19f47daa839..1a611c6ec92 100644 --- a/backends/tofino/bf-p4c/mau/hash_function.cpp +++ b/backends/tofino/bf-p4c/mau/hash_function.cpp @@ -23,7 +23,7 @@ #include "lib/hex.h" #include "lib/big_int_util.h" #include "backends/tofino/bf-p4c/mau/hash_function.h" -#include "backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h" +#include "backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h" using namespace P4::literals; diff --git a/backends/tofino/bf-p4c/mau/input_xbar.cpp b/backends/tofino/bf-p4c/mau/input_xbar.cpp index a5372cde485..eb45cad34d3 100644 --- a/backends/tofino/bf-p4c/mau/input_xbar.cpp +++ b/backends/tofino/bf-p4c/mau/input_xbar.cpp @@ -26,7 +26,7 @@ #include "backends/tofino/bf-p4c/mau/resource_estimate.h" #include "backends/tofino/bf-p4c/mau/tofino/input_xbar.h" #include "backends/tofino/bf-p4c/phv/phv_fields.h" -#include "backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h" +#include "backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h" #include "lib/algorithm.h" #include "lib/bitops.h" #include "lib/bitrange.h" diff --git a/backends/tofino/bf-p4c/mau/tofino/input_xbar.cpp b/backends/tofino/bf-p4c/mau/tofino/input_xbar.cpp index 24f4d78d7b7..1c6f00b2b5d 100644 --- a/backends/tofino/bf-p4c/mau/tofino/input_xbar.cpp +++ b/backends/tofino/bf-p4c/mau/tofino/input_xbar.cpp @@ -27,7 +27,7 @@ #include "backends/tofino/bf-p4c/mau/resource.h" #include "backends/tofino/bf-p4c/mau/resource_estimate.h" #include "backends/tofino/bf-p4c/phv/phv_fields.h" -#include "backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h" +#include "backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h" #include "lib/algorithm.h" #include "lib/bitvec.h" #include "lib/bitops.h" diff --git a/backends/tofino/bf-p4c/midend/fold_constant_hashes.h b/backends/tofino/bf-p4c/midend/fold_constant_hashes.h index 1ae433826e7..5504025a4ab 100644 --- a/backends/tofino/bf-p4c/midend/fold_constant_hashes.h +++ b/backends/tofino/bf-p4c/midend/fold_constant_hashes.h @@ -23,7 +23,7 @@ #include "ir/ir.h" #include "backends/tofino/bf-p4c/midend/type_checker.h" #include "backends/tofino/bf-p4c/mau/hash_function.h" -#include "backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h" +#include "backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h" namespace BFN { diff --git a/backends/tofino/bf-utils/dynamic_hash/CMakeLists.txt b/backends/tofino/bf-utils/dynamic_hash/CMakeLists.txt new file mode 100644 index 00000000000..c239cab88ed --- /dev/null +++ b/backends/tofino/bf-utils/dynamic_hash/CMakeLists.txt @@ -0,0 +1,13 @@ +project(libdynhash VERSION 0.1 LANGUAGES C) +add_library(dynhash_o OBJECT + dynamic_hash.cpp + bfn_hash_algorithm.cpp +) + +add_library(dynhash SHARED EXCLUDE_FROM_ALL $) + +# static lib for compiler with no syslibs +add_library(tofino_dynhash STATIC dynamic_hash.cpp bfn_hash_algorithm.cpp) +set_target_properties(tofino_dynhash PROPERTIES OUTPUT_NAME dynhash) +target_compile_definitions(tofino_dynhash PUBLIC NO_BFSYSLIBS) + diff --git a/backends/tofino/bf-utils/src/dynamic_hash/bfn_hash_algorithm.cpp b/backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.cpp similarity index 99% rename from backends/tofino/bf-utils/src/dynamic_hash/bfn_hash_algorithm.cpp rename to backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.cpp index 2439b2c5404..5420ba7b9d4 100644 --- a/backends/tofino/bf-utils/src/dynamic_hash/bfn_hash_algorithm.cpp +++ b/backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.cpp @@ -1,4 +1,4 @@ -#include "backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h" +#include "backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.h" #include #include @@ -6,6 +6,8 @@ #include #include +#include + /** * These values are based on the crc calculations provided at this url: * http://reveng.sourceforge.net/crc-catalogue/all.htm diff --git a/backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h b/backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.h similarity index 98% rename from backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h rename to backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.h index 63ee35a97f2..3d2058e4903 100644 --- a/backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h +++ b/backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.h @@ -1,5 +1,5 @@ -#ifndef BACKENDS_TOFINO_BF_UTILS_INCLUDE_DYNAMIC_HASH_BFN_HASH_ALGORITHM_H_ -#define BACKENDS_TOFINO_BF_UTILS_INCLUDE_DYNAMIC_HASH_BFN_HASH_ALGORITHM_H_ +#ifndef BACKENDS_TOFINO_BF_UTILS_DYNAMIC_HASH_BFN_HASH_ALGORITHM_H_ +#define BACKENDS_TOFINO_BF_UTILS_DYNAMIC_HASH_BFN_HASH_ALGORITHM_H_ #ifndef __KERNEL__ #include @@ -419,4 +419,4 @@ void initialize_crc_matrix(bfn_hash_algorithm_t *alg); void calculate_crc(bfn_hash_algorithm_t *alg, uint32_t hash_output_bits, uint8_t *stream, uint32_t stream_len, uint8_t *crc); -#endif /* BACKENDS_TOFINO_BF_UTILS_INCLUDE_DYNAMIC_HASH_BFN_HASH_ALGORITHM_H_ */ +#endif /* BACKENDS_TOFINO_BF_UTILS_DYNAMIC_HASH_BFN_HASH_ALGORITHM_H_ */ diff --git a/backends/tofino/bf-utils/src/dynamic_hash/dynamic_hash.cpp b/backends/tofino/bf-utils/dynamic_hash/dynamic_hash.cpp similarity index 99% rename from backends/tofino/bf-utils/src/dynamic_hash/dynamic_hash.cpp rename to backends/tofino/bf-utils/dynamic_hash/dynamic_hash.cpp index 23567dec6fa..2cb1479c8ea 100644 --- a/backends/tofino/bf-utils/src/dynamic_hash/dynamic_hash.cpp +++ b/backends/tofino/bf-utils/dynamic_hash/dynamic_hash.cpp @@ -1,4 +1,4 @@ -#include "backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h" +#include "backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h" #include #include diff --git a/backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h b/backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h similarity index 96% rename from backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h rename to backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h index d42e6db9e16..3564c612d0c 100644 --- a/backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h +++ b/backends/tofino/bf-utils/dynamic_hash/dynamic_hash.h @@ -1,10 +1,10 @@ -#ifndef BACKENDS_TOFINO_BF_UTILS_INCLUDE_DYNAMIC_HASH_DYNAMIC_HASH_H_ -#define BACKENDS_TOFINO_BF_UTILS_INCLUDE_DYNAMIC_HASH_DYNAMIC_HASH_H_ +#ifndef BACKENDS_TOFINO_BF_UTILS_DYNAMIC_HASH_DYNAMIC_HASH_H_ +#define BACKENDS_TOFINO_BF_UTILS_DYNAMIC_HASH_DYNAMIC_HASH_H_ #include #include -#include "backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h" +#include "backends/tofino/bf-utils/dynamic_hash/bfn_hash_algorithm.h" #ifdef __cplusplus extern "C" { @@ -213,4 +213,4 @@ void determine_tofino_regs(const ixbar_init_t *ixbar_init, const ixbar_input_t * } #endif -#endif /* BACKENDS_TOFINO_BF_UTILS_INCLUDE_DYNAMIC_HASH_DYNAMIC_HASH_H_ */ +#endif /* BACKENDS_TOFINO_BF_UTILS_DYNAMIC_HASH_DYNAMIC_HASH_H_ */ diff --git a/backends/tofino/bf-utils/src/dynamic_hash/CMakeLists.txt b/backends/tofino/bf-utils/src/dynamic_hash/CMakeLists.txt deleted file mode 100644 index c22d0a2fb1e..00000000000 --- a/backends/tofino/bf-utils/src/dynamic_hash/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -project(libdynhash VERSION 0.1 LANGUAGES C) -add_library(dynhash_o OBJECT - dynamic_hash.c - bfn_hash_algorithm.c) -add_library(dynhash SHARED EXCLUDE_FROM_ALL $) - -# static lib for compiler with no syslibs -add_library(dynhashStatic STATIC dynamic_hash.c bfn_hash_algorithm.c) -set_target_properties(dynhashStatic PROPERTIES OUTPUT_NAME dynhash) -target_compile_definitions(dynhashStatic PUBLIC NO_BFSYSLIBS) diff --git a/backends/tofino/bf-utils/src/dynamic_hash/bfn_hash_algorithm.c b/backends/tofino/bf-utils/src/dynamic_hash/bfn_hash_algorithm.c deleted file mode 100644 index 4207819a3d4..00000000000 --- a/backends/tofino/bf-utils/src/dynamic_hash/bfn_hash_algorithm.c +++ /dev/null @@ -1,281 +0,0 @@ -#include "backends/tofino/bf-utils/include/dynamic_hash/bfn_hash_algorithm.h" - -#include -#include -#include -#include -#include - -/** - * These values are based on the crc calculations provided at this url: - * http://reveng.sourceforge.net/crc-catalogue/all.htm - * - * It is understood that the top bit of the the polynomial is known to be == 1, - * but any polynomial over 64 bits would not fit. Thus the strings do not have - * this value - */ -static crc_alg_info_t standard_crc_algs[CRC_INVALID] = { - {"crc_8", 0x07, false, 0, 0}, - {"crc_8_darc", 0x39, true, 0, 0}, - {"crc_8_i_code", 0x1d, false, 0xfd, 0}, - {"crc_8_itu", 0x07, false, 0x55, 0x55}, - {"crc_8_maxim", 0x31, true, 0, 0}, - {"crc_8_rohc", 0x07, true, 0xff, 0}, - {"crc_8_wcdma", 0x9b, true, 0, 0}, - {"crc_16", 0x8005, true, 0, 0}, - {"crc_16_bypass", 0x8005, false, 0, 0}, - {"crc_16_dds_110", 0x8005, false, 0x800d, 0}, - // This one doesn't appear on the website, but kept to not break - // regressions - {"crc_16_dect", 0x0589, false, 1, 1}, - {"crc_16_dect_r", 0x0589, false, 0, 1}, - {"crc_16_dect_x", 0x0589, false, 0, 0}, - {"crc_16_dnp", 0x3d65, true, 0, 0xffff}, - {"crc_16_en_13757", 0x3d65, false, 0, 0xffff}, - {"crc_16_genibus", 0x1021, false, 0xffff, 0xffff}, - {"crc_16_maxim", 0x8005, true, 0, 0xffff}, - {"crc_16_mcrf4xx", 0x1021, true, 0xffff, 0}, - {"crc_16_riello", 0x1021, true, 0xb2aa, 0}, - {"crc_16_t10_dif", 0x8bb7, false, 0, 0}, - {"crc_16_teledisk", 0xa097, false, 0, 0}, - {"crc_16_usb", 0x8005, true, 0xffff, 0xffff}, - {"x_25", 0x1021, true, 0xffff, 0xffff}, - {"xmodem", 0x1021, false, 0, 0}, - {"modbus", 0x8005, true, 0xffff, 0}, - {"kermit", 0x1021, true, 0, 0}, - {"crc_ccitt_false", 0x1021, false, 0xffff, 0}, - {"crc_aug_ccitt", 0x1021, false, 0x1d0f, 0}, - {"crc_32", 0x04c11db7, true, 0xffffffff, 0xffffffff}, - {"crc_32_bzip2", 0x04c11db7, false, 0xffffffff, 0xffffffff}, - {"crc_32c", 0x1edc6f41, true, 0xffffffff, 0xffffffff}, - {"crc_32d", 0xa833982b, true, 0xffffffff, 0xffffffff}, - {"crc_32_mpeg", 0x04c11db7, false, 0xffffffff, 0}, - {"posix", 0x04c11db7, false, 0, 0xffffffff}, - {"crc_32q", 0x814141ab, false, 0, 0}, - {"jamcrc", 0x04c11db7, true, 0xffffffff, 0}, - {"xfer", 0x000000af, false, 0, 0}, - {"crc_64", 0x42f0e1eba9ea3693, false, 0, 0}, - {"crc_64_go_iso", 0x000000000000001b, true, 0xffffffffffffffff, 0xffffffffffffffff}, - {"crc_64_we", 0x42f0e1eba9ea3693, false, 0xffffffffffffffff, 0xffffffffffffffff}, - // This one doesn't appear on the website, but kept to not break - // regressions - {"crc_64_jones", 0xad93d23594c935a9, true, 0xffffffffffffffff, 0}}; - -int determine_msb(uint64_t value) { - int rv = -1; -#if defined(__GNUC__) || defined(__clang__) - if (value) rv = 63 - __builtin_clzl(value); -#else - for (int i = 63; i >= 0; i--) { - if (((1ULL << i) & value) != 0ULL) return i; - } -#endif - return rv; -} - -#define BUILD_CRC_ERRORS - -static char *bfn_crc_errors[BUILD_CRC_ERRORS] = { - "Polynomial is not odd", - "Init value is larger than the polynomial", - "Final xor value is larger than the polynomial", -}; - -bool verify_algorithm(bfn_hash_algorithm_t *alg, char **error_message) { - if ((alg->poly & 1) == 0) { - if (error_message) *error_message = bfn_crc_errors[0]; - return false; - } - if (alg->init && determine_msb(alg->init) + 1 > alg->hash_bit_width) { - if (error_message) *error_message = bfn_crc_errors[1]; - return false; - } - if (alg->final_xor && determine_msb(alg->final_xor) + 1 > alg->hash_bit_width) { - if (error_message) *error_message = bfn_crc_errors[2]; - return false; - } - return true; -} - -/** - * Builds the algorithm from the standard crc algorithm position - */ -void build_standard_crc_algorithm(bfn_hash_algorithm_t *alg, bfn_crc_alg_t crc_alg) { - if (crc_alg >= CRC_8 && crc_alg <= CRC_8_WCDMA) - alg->hash_bit_width = 8; - else if (crc_alg >= CRC_16 && crc_alg <= CRC_AUG_CCITT) - alg->hash_bit_width = 16; - else if (crc_alg >= CRC_32 && crc_alg <= XFER) - alg->hash_bit_width = 32; - else if (crc_alg >= CRC_64 && crc_alg <= CRC_64_JONES) - alg->hash_bit_width = 64; - - crc_alg_info_t crc_alg_info = standard_crc_algs[(int)crc_alg]; - alg->poly = crc_alg_info.poly; - alg->reverse = crc_alg_info.reverse; - alg->init = crc_alg_info.init; - alg->final_xor = crc_alg_info.final_xor; - alg->crc_type = crc_alg_str_to_type(crc_alg_info.crc_name); -} - -void initialize_algorithm(bfn_hash_algorithm_t *alg, bfn_hash_alg_type_t hash_alg, bool msb, - bool extend, bfn_crc_alg_t crc_alg) { - alg->hash_alg = hash_alg; - alg->msb = msb; - alg->extend = extend; - if (crc_alg != CRC_INVALID) build_standard_crc_algorithm(alg, crc_alg); -} - -static uint64_t invert_poly(uint64_t poly, int bit_width) { - uint64_t ret = 0, i = 0; - while (poly > 0) { - ret |= ((poly & 0x1) << (bit_width - i - 1)); - i++; - poly >>= 1; - } - return ret; -} - -static void construct_stream(bfn_hash_algorithm_t *alg, uint64_t val, uint8_t *stream) { - uint8_t width = (alg->hash_bit_width + 7) / 8; - for (uint8_t i = 0; i < width; i++) { - stream[width - i - 1] = (val >> (i * 8)); - } - return; -} - -static void shift_right(uint8_t *stream, uint8_t bit_width) { - uint8_t width = (bit_width + 7) / 8; - for (int i = width - 1; i >= 0; i--) { - stream[i] >>= 1; - if (i > 0) { - stream[i] |= (stream[i - 1] & 0x1) << 7; - } - } -} - -static void shift_left(uint8_t *stream, uint8_t bit_width) { - uint8_t width = (bit_width + 7) / 8; - for (uint8_t i = 0; i < width; i++) { - stream[i] <<= 1; - if (i < width - 1) { - stream[i] |= (stream[i + 1] >> 7) & 0x1; - } - } -} - -void initialize_crc_matrix(bfn_hash_algorithm_t *alg) { - if (alg->hash_alg != CRC_DYN) { - return; - } - - uint32_t width = (alg->hash_bit_width + 7) / 8, i = 0; - uint8_t poly[width], rem[width]; - memset(poly, 0, width * sizeof(uint8_t)); - memset(rem, 0, width * sizeof(uint8_t)); - - uint64_t poly_val = alg->poly; - if (alg->reverse) { - poly_val = invert_poly(poly_val, alg->hash_bit_width); - } - construct_stream(alg, poly_val, poly); - uint32_t byte = 0, bit = 0; - bool xor = false; - if (alg->reverse) { - for (byte = 0; byte < 256; byte++) { - memset(rem, 0, width * sizeof(uint8_t)); - rem[width - 1] = byte; - for (bit = 0; bit < 8; bit++) { - xor = rem[width - 1] & 0x1; - shift_right(rem, alg->hash_bit_width); - if (xor) { - for (i = 0; i < width; i++) { - rem[i] ^= poly[i]; - } - } - } - memcpy(alg->crc_matrix[byte], rem, width); - } - } else { - uint8_t offset = alg->hash_bit_width % 8; - uint8_t top_bit = offset == 0 ? 0x80 : 1 << ((offset - 1) % 8); - uint8_t top_mask = top_bit == 0x80 ? 0xff : (top_bit << 1) - 1; - for (byte = 0; byte < 256; byte++) { - memset(rem, 0, width * sizeof(uint8_t)); - if (offset == 0) { - rem[0] = byte; - } else { - rem[0] = byte >> (8 - offset); - rem[1] = byte << offset; - } - for (bit = 0; bit < 8; bit++) { - xor = rem[0] & top_bit; - shift_left(rem, alg->hash_bit_width); - if (xor) { - for (i = 0; i < width; i++) { - rem[i] ^= poly[i]; - } - } - rem[0] &= top_mask; - } - memcpy(alg->crc_matrix[byte], rem, width); - } - } - - return; -} - -static uint8_t get_byte(uint8_t *stream, uint8_t index, uint8_t offset) { - if (offset == 0) { - return stream[index]; - } - return ((stream[index] << (8 - offset)) | (stream[index + 1] >> offset)); -} - -void calculate_crc(bfn_hash_algorithm_t *alg, uint32_t hash_output_bits, uint8_t *stream, - uint32_t stream_len, uint8_t *crc) { - uint32_t i = 0; - uint8_t idx = 0; - uint8_t width = (alg->hash_bit_width + 7) / 8; - uint8_t hash_output_bytes = (hash_output_bits + 7) / 8; - uint8_t final_xor[width]; - memset(crc, 0, hash_output_bytes * sizeof(uint8_t)); - memset(final_xor, 0, width * sizeof(uint8_t)); - construct_stream(alg, alg->init, crc); - construct_stream(alg, alg->final_xor, final_xor); - uint8_t *crc_str = crc + hash_output_bytes - width; - - for (i = 0; i < stream_len; i++) { - if (alg->reverse) { - idx = crc_str[width - 1] ^ stream[i]; - for (int j = width - 1; j > 0; j--) { - crc_str[j] = crc_str[j - 1] ^ alg->crc_matrix[idx][j]; - } - crc_str[0] = alg->crc_matrix[idx][0]; - } else { - uint8_t offset = alg->hash_bit_width % 8; - uint8_t mask = offset == 0 ? 0xff : (1 << offset) - 1; - idx = get_byte(crc_str, 0, offset) ^ stream[i]; - for (uint8_t j = 0; j < width - 1; j++) { - crc_str[j] = (crc_str[j + 1] ^ alg->crc_matrix[idx][j]) & mask; - mask = 0xff; - } - crc_str[width - 1] = alg->crc_matrix[idx][width - 1]; - } - } - - for (i = 0; i < width; i++) { - crc_str[i] ^= final_xor[i]; - } - - if (alg->extend) { - for (i = 0; i < (uint32_t)(hash_output_bytes - width); i++) { - *(crc_str - i - 1) = crc_str[width - i % width - 1]; - } - if (hash_output_bits % 8) { - crc[0] &= (1 << (hash_output_bits % 8)) - 1; - } - } - - return; -} diff --git a/backends/tofino/bf-utils/src/dynamic_hash/dynamic_hash.c b/backends/tofino/bf-utils/src/dynamic_hash/dynamic_hash.c deleted file mode 100644 index 5f76c8ea729..00000000000 --- a/backends/tofino/bf-utils/src/dynamic_hash/dynamic_hash.c +++ /dev/null @@ -1,831 +0,0 @@ -#include "backends/tofino/bf-utils/include/dynamic_hash/dynamic_hash.h" - -#include -#include -#include -#include -#include -#include - -#define assert_macro assert -#define calloc_macro calloc -#define free_macro free - -#define ALLOC_CHECK(ptr, str) \ - do { \ - if (ptr == NULL) { \ - printf("%s\n", str); \ - assert_macro(0); \ - return; \ - } \ - } while (0) - -bool determine_identity_gfm(uint32_t input_bit, uint32_t p4_hash_output_bit) { - return input_bit == p4_hash_output_bit; -} - -bool determine_random_gfm() { return random() & 1; } - -static bool determine_xor_gfm(uint32_t input_bit, uint32_t p4_hash_output_bit, uint32_t width, - uint32_t total_input_bits) { - /* -- The message (input registers) is handled as a big integer - the - * highest bit of the integer is the beginning of the message. Zero-th - * bit is the end of the message. If the message is not aligned with - * the algorithm's width, zero bits must be appended after the end - * of the message - that's the reason of shifting the input bit - * by total_input_bits. */ - return (p4_hash_output_bit < width) && - ((input_bit + width * width - total_input_bits) % width) == p4_hash_output_bit; -} - -/** - * The point of this funciton is to get up to a 64 bit value from the - * bitvector. - * - * This is potientially broken up into two separate lookups, if the boundary - * of the write crosses a 64 bit section. The bitvec is an array of 64 bit - * values. Thus if the algorithm wanted to get a 16 bit value at position - * 56, the value returned would be the upper 8 bits of bitvec[0] starting at - * bit 0, ORed with the lower 8 bits of bitvec[1] starting at bit 8. - * - * The lower_* values in the previous example would deal with any reads - * to bitvec[0], while all upper_* values deal with any reads to bitvec[1] - */ -uint64_t get_from_bitvec(const uint64_t *val, uint32_t bitvec_sz, uint32_t start_bit, - uint32_t size) { - uint64_t current_value = 0ULL; - uint32_t mod_pos = start_bit % 64; - uint32_t bitvec_pos = start_bit / 64; - uint64_t upper_mask = (1ULL << mod_pos) - 1; - uint64_t lower_mask = ULLONG_MAX & ~upper_mask; - - uint64_t upper_value = 0ULL; - if (mod_pos && bitvec_pos + 1 < bitvec_sz) { - upper_value = upper_mask & *(val + bitvec_pos + 1); - upper_value <<= 64 - mod_pos; - } - - uint64_t lower_value = lower_mask & *(val + bitvec_pos); - lower_value >>= mod_pos; - current_value = lower_value | upper_value; - - uint64_t mask = 0ULL; - if (size >= 64ULL) { - mask = ULLONG_MAX; - } else { - mask = (1ULL << size) - 1; - } - - return current_value & mask; -} - -/** - * The point of this function is to write up to a 64 bit value into a position - * of the bitvector. - * - * This is potentially broken up into two separate assignment, if the boundary - * of the write crosses a 64 bit section. The bitvec is an array of 64 bit - * values. Thus if the algorithm wanted to write a 16 bit value into the - * bitvec at position 56, bitvec[0] upper 8 bits would be written and - * bitvec[1] lower 8 bits would be written. - * - * The lower_* values in the previous example would deal with any writes - * to bitvec[0], while all upper_* values deal with any writes to bitvec[1] - */ -void set_into_bitvec(uint64_t *val, uint32_t bitvec_sz, uint64_t current_value, uint32_t start_bit, - uint32_t size) { - uint64_t mask = 0ULL; - if (size >= 64ULL) { - mask = ULLONG_MAX; - } else { - mask = (1ULL << size) - 1; - } - uint32_t mod_pos = start_bit % 64; - uint32_t bitvec_pos = start_bit / 64; - - // Bits of the current_value headed to the lower bitvec position - uint64_t lower_mask = ULLONG_MAX; - if (mod_pos != 0) lower_mask = (1ULL << (64 - mod_pos)) - 1; - // Bits of the current_value headed to the upper bitvec position - uint64_t upper_mask = ULLONG_MAX & ~lower_mask; - uint64_t upper_value = upper_mask & current_value & mask; - if (mod_pos) - upper_value >>= 64 - mod_pos; - else - upper_value = 0; - - // Bits of the upper bitvecs that will be written into - uint64_t upper_set_mask = ULLONG_MAX; - if (mod_pos != 0) upper_set_mask = ~(mask >> (64 - mod_pos)) & ULLONG_MAX; - - uint64_t lower_value = lower_mask & current_value & mask; - lower_value <<= mod_pos; - // Bits of the lower bitvecs that will be written into - uint64_t lower_set_mask = ~(mask << mod_pos) & ULLONG_MAX; - - if (bitvec_pos + 1 < bitvec_sz) { - *(val + bitvec_pos + 1) = upper_value | (upper_set_mask & *(val + bitvec_pos + 1)); - } - *(val + bitvec_pos) = lower_value | (lower_set_mask & *(val + bitvec_pos)); -} - -uint32_t compute_bitvec_sz(const bfn_hash_algorithm_t *alg, uint32_t total_input_bits) { - uint32_t total_msb = (((total_input_bits - 1) + 7) / 8) * 8; - if (alg->hash_alg == CRC_DYN) total_msb += alg->hash_bit_width; - return (total_msb + 63) / 64; -} - -/** - * The constants from the hash field inputs need to be correctly added to - * the initial bit vector. This function writes these constants into - * the bit vector at the correct location. - * - * The purpose of this library is to determine each relevant hash matrix bit - * which has a corresponding input and output bit. All input bits correspond - * to a PHV bit, as that is the input to the hash matrix. For constant inputs, - * these constants have no single input xbar bit, and thus have no single row - * in the hash matrix that they coordinate to. However, in order to calculate - * each individual row's matrix, the constants must be included in every - * calculation of that data. - */ -void initialize_input_data_stream(const bfn_hash_algorithm_t *alg, uint64_t *val, - uint32_t bitvec_sz, const ixbar_input_t *inputs, - uint32_t inputs_sz) { - int start_bit = 0; - if (alg->hash_alg == CRC_DYN) start_bit += alg->hash_bit_width; - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - if (input->type == tCONST) { - // For reverse algorithms, the inputs are byte reversed. This is - // true for any constant input as well. - if (alg->hash_alg == CRC_DYN && alg->reverse) { - for (uint32_t j = 0; j < input->bit_size; j++) { - uint32_t val_bit_pos = start_bit + j; - val_bit_pos -= alg->hash_bit_width; - val_bit_pos ^= 7; - val_bit_pos += alg->hash_bit_width; - uint64_t val_bit_val = (input->u.constant >> j) & 1ULL; - set_into_bitvec(val, bitvec_sz, val_bit_val, val_bit_pos, 1); - } - - // All other algorithms have the constants in order, so we add them - // in order - } else { - uint32_t val_bit_pos = start_bit; - uint32_t val_bit_len = input->bit_size; - uint64_t val_bit_val = input->u.constant; - set_into_bitvec(val, bitvec_sz, val_bit_val, val_bit_pos, val_bit_len); - } - } - start_bit += input->bit_size; - } -} - -/** - * The matrix position i, j where: - * - * i - the input bit of the data stream - * j - the output bit of the hash function - * - * will be equal to whether: - * (1 << output_bit) & crc(alg, data_stream)) == (1 << output), - * - * where the data stream is an all 0 bitstream except for a single bit at the - * input_bit position. - * - * The output of the crc is the remainder of a polynomial division modulo two - * of a data stream with a polynomial. From msb to lsb, the polynomial is - * XORed with the value in the data stream until each bit in the data stream - * has been XORed. The general details of the CRC algorithm are publicly - * available. - * - * The bfn_hash_algorithm_t holds certain parameters that impact the crc - * calculation: - * - * poly - The polynomial to XOR with the data stream. Currently assumed - * that the upper bit is always 1, and is not stored directly in the - * polynomial. This is done to hold all possible polynomials for a - * 64 bit crc. - * init - The initial value of the crc. THIS IS XORed with the first - * portion of the data stream. (Note: not appended to the msb of the - * data stream) - * reverse - This indicates two values. First, the byte ordering, remains - * the same, but each byte of the crc is msb to lsb, rather than the - * standard lsb to msb. Secondly, the output of the crc is - * bit-reversed as well. - * final_xor - This is a value that is XORed at the end of the calculation. - * This doesn't apply to the hash_matrix, but the seed, as isn't - * necessary for this function - * - * In order to fully convert this to a Galois Matrix, a couple extra steps - * are required. If the crc has an init value, then the all 0 input to the - * matrix will have a non all 0 result before the final xor. However, in - * a matrix multiplication, no matter what, the all zero input will be an all - * zero output. - * - * Thus in order to capture the all 0 input, the seed register per hash - * function must represent the result of the all 0 input of the crc function, - * as it must capture this init value. This seed value must then be xored - * out of each matrix row calculation - */ -bool determine_crc_gfm(const bfn_hash_algorithm_t *alg, uint64_t *init_data, uint32_t bitvec_sz, - uint32_t input_bit, bool use_input_bit, uint32_t p4_hash_output_bit, - uint32_t total_input_bits) { - // The input stream is 0 extended to the byte. Always start with highest - // bit, as constants could be included in the calculation - uint32_t total_msb = alg->hash_bit_width - 1; - total_msb += ((total_input_bits + 7) / 8) * 8; - - uint32_t val_bit = input_bit; - // Reverse the input bytes - if (alg->reverse) { - val_bit ^= 7; - } - - // This is the data stream, and is saved as a bit vector - uint64_t val[bitvec_sz]; - memset(val, 0, sizeof(val)); - for (uint32_t i = 0; i < bitvec_sz; i++) val[i] = init_data[i]; - - if (use_input_bit) { - int val_bit_pos = val_bit + alg->hash_bit_width; - set_into_bitvec(val, bitvec_sz, 1ULL, val_bit_pos, 1); - } - - ///> XOR the initial value into the data stream - if (alg->init != 0ULL) { - int init_lsb = total_msb - (alg->hash_bit_width - 1); - uint64_t current_value = get_from_bitvec(val, bitvec_sz, init_lsb, alg->hash_bit_width); - current_value ^= alg->init; - set_into_bitvec(val, bitvec_sz, current_value, init_lsb, alg->hash_bit_width); - } - - ///> Calculate crc at each bit position - for (int i = total_msb - alg->hash_bit_width; i >= 0; i--) { - int upper_bit_position = (i + alg->hash_bit_width); - uint64_t upper_value = get_from_bitvec(val, bitvec_sz, upper_bit_position, 1); - upper_value &= 1ULL; - if (upper_value == 1ULL) { - set_into_bitvec(val, bitvec_sz, 0ULL, upper_bit_position, 1); - uint64_t current_value = get_from_bitvec(val, bitvec_sz, i, alg->hash_bit_width); - current_value ^= alg->poly; - set_into_bitvec(val, bitvec_sz, current_value, i, alg->hash_bit_width); - } - } - - ///> Xor the final xor - uint64_t hash_calc = get_from_bitvec(val, bitvec_sz, 0, alg->hash_bit_width) ^ alg->final_xor; - - ///> Reverse the output bits - uint64_t mask = (1ULL << p4_hash_output_bit); - if (alg->reverse) { - mask = (1ULL << ((alg->hash_bit_width - 1) - p4_hash_output_bit)); - } - - return (mask & hash_calc) != 0ULL; -} - -bool get_matrix_bit(hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN], - uint32_t ixbar_input_bit, uint32_t galois_bit) { - uint32_t matrix_index0 = ixbar_input_bit / 64; - uint32_t matrix_index1 = galois_bit; - - uint32_t bit_offset = ixbar_input_bit % 64; - return (hash_matrix[matrix_index0][matrix_index1].column_value & (1ULL << bit_offset)) != 0ULL; -} - -void initialize_matrix_bit(hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN], - uint32_t ixbar_input_bit, uint32_t galois_bit, bool set_bit) { - uint32_t matrix_index0 = ixbar_input_bit / 64; - uint32_t matrix_index1 = galois_bit; - - uint32_t bit_offset = ixbar_input_bit % 64; - uint32_t byte_offset = bit_offset / 8; - if (set_bit) hash_matrix[matrix_index0][matrix_index1].column_value |= (1ULL << bit_offset); - hash_matrix[matrix_index0][matrix_index1].byte_used |= (1ULL << byte_offset); -} - -/** - * The purpose of this function is to determine the bit for hash matrix - * position input_bit x output_bit is set to 1 or 0. The parameters - * for the function are the following: - * - * Note that the hash_matrix[ixbar_input_bit][galois_bit] is always the - * bit which is modified. So it doesn't depend upon the logical input_bit - * or logical p4_hash_output_bit. The content of this bit, however, - * depends upon the logical input/output. - * - * ixbar_input_bit - The bit on the 1024 bit input xbar array. - * input_bit - the logical input bit on the total list of field bits. - * total_input_bits - the size of the input stream for the hash - * calculation. This is required for crc algorithms. - * p4_hash_output_bit - The logical hash bit output - * galois_bit - the output bit of the 52 bits hash calculation - * total_output_bits - the total size of the hash calculation. Required - * for msb/extensions of hash calculations. - */ -void determine_matrix_bit(hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN], - const bfn_hash_algorithm_t *alg, const ixbar_input_t *inputs, - uint32_t inputs_sz, uint32_t ixbar_input_bit, uint32_t input_bit, - uint32_t total_input_bits, uint32_t p4_hash_output_bit, - uint32_t galois_bit) { - bool set_bit = false; - - uint32_t virtual_p4_hash_output_bit = p4_hash_output_bit; - if (alg->extend) { - virtual_p4_hash_output_bit = virtual_p4_hash_output_bit % alg->hash_bit_width; - } - - ///> Initialize the input bitvec with the constant inputs - if (alg->hash_alg == IDENTITY_DYN) { - set_bit = determine_identity_gfm(input_bit, virtual_p4_hash_output_bit); - } else if (alg->hash_alg == RANDOM_DYN) { - set_bit = determine_random_gfm(); - } else if (alg->hash_alg == XOR_DYN) { - set_bit = determine_xor_gfm(input_bit, virtual_p4_hash_output_bit, alg->hash_bit_width, - total_input_bits); - } else if (alg->hash_alg == CRC_DYN) { - uint32_t bitvec_sz = compute_bitvec_sz(alg, total_input_bits); - uint64_t val[bitvec_sz]; - memset(val, 0, sizeof(val)); - initialize_input_data_stream(alg, val, bitvec_sz, inputs, inputs_sz); - // See comments above the dete - set_bit = determine_crc_gfm(alg, val, bitvec_sz, input_bit, true, - virtual_p4_hash_output_bit, total_input_bits) ^ - determine_crc_gfm(alg, val, bitvec_sz, 0, /* input_bit */ - false, virtual_p4_hash_output_bit, total_input_bits); - } - - initialize_matrix_bit(hash_matrix, ixbar_input_bit, galois_bit, set_bit); -} - -/** - * This function is used to determine the seed. For CRC functions, this - * coordinates to the all 0 input result as described in the determine_crc_gfm - * comments. For random functions, this will provide a random number as - * the seed. - */ -void determine_seed_bit(hash_seed_t *hash_seed, uint64_t *init_data, /* bit vec */ - uint32_t init_data_sz, const bfn_hash_algorithm_t *alg, - uint32_t p4_hash_output_bit, uint32_t total_input_bits, - uint32_t galois_bit) { - bool set_bit = false; - if (alg->hash_alg == RANDOM_DYN) { - set_bit = random() & 1; - } else if (alg->hash_alg == CRC_DYN && total_input_bits != 0) { - if (alg->extend) { - p4_hash_output_bit = p4_hash_output_bit % alg->hash_bit_width; - } - set_bit = determine_crc_gfm(alg, init_data, init_data_sz, 0, false, p4_hash_output_bit, - total_input_bits); - } else if (alg->hash_alg == IDENTITY_DYN) { - set_bit = get_from_bitvec(init_data, init_data_sz, p4_hash_output_bit, 1) == 1ULL; - } else if (alg->hash_alg == XOR_DYN) { - if (p4_hash_output_bit < ((uint32_t)alg->hash_bit_width)) { - uint64_t acc = 0; - int32_t i = - p4_hash_output_bit - alg->hash_bit_width + total_input_bits % alg->hash_bit_width; - if (i < 0) i += alg->hash_bit_width; - for (; i < ((int32_t)total_input_bits); i += alg->hash_bit_width) { - acc ^= get_from_bitvec(init_data, init_data_sz, i, 1); - } - set_bit = acc == 1ULL; - } else { - set_bit = false; - } - } - hash_seed->hash_seed_used |= (1ULL << galois_bit); - - if (set_bit) hash_seed->hash_seed_value |= (1ULL << galois_bit); -} - -void print_hash_matrix(hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]) { - printf("Hash matrix ---> \n"); - uint32_t n_nibbles = 16; - for (uint32_t i = 0; i < PARITY_GROUPS_DYN; i++) { - for (uint32_t j = 0; j < n_nibbles; j++) { - for (uint32_t k = 0; k < HASH_MATRIX_WIDTH_DYN; k++) { - printf("%" PRIx64 " ", ((hash_matrix[i][k].column_value >> (j * 4)) & 0xf)); - } - printf("\n"); - } - } -} - -void print_hash_matrix_used(hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]) { - printf("Hash matrix Used bytes ---> \n"); - for (uint32_t i = 0; i < PARITY_GROUPS_DYN; i++) { - for (uint32_t j = 0; j < HASH_MATRIX_WIDTH_DYN; j++) { - printf("%x ", hash_matrix[i][j].byte_used); - } - printf("\n"); - } -} - -static void rotate_seed(hash_calc_rotate_info_t *rot_info, hash_seed_t *hash_seed) { - uint32_t bit_posn = 0, idx = 0; - bool hash_seed_value[HASH_SEED_LENGTH] = {0}; - bool hash_seed_used[HASH_SEED_LENGTH] = {0}; - bool rotate_temp_value[HASH_SEED_LENGTH] = {0}; - bool rotate_temp_used[HASH_SEED_LENGTH] = {0}; - uint64_t rotate = rot_info->rotate; - uint32_t num_tot_hash_bits = rot_info->num_hash_bits; - /* Dissect into an array */ - while (bit_posn < num_tot_hash_bits) { - idx = rot_info->p4_hash_output_bit_posn[bit_posn]; - hash_seed_value[idx] = hash_seed->hash_seed_value & (1ULL << idx); - hash_seed_used[idx] = hash_seed->hash_seed_used & (1ULL << idx); - bit_posn++; - } - - /* Safeguard the rotated bits. */ - bit_posn = 0; - while (bit_posn < rotate) { - idx = rot_info->p4_hash_output_bit_posn[(num_tot_hash_bits - 1) - (rotate - 1) + bit_posn]; - rotate_temp_value[bit_posn] = hash_seed_value[idx]; - rotate_temp_used[bit_posn] = hash_seed_used[idx]; - bit_posn++; - } - - /* Right shift as per rotation. */ - for (int rot_idx = num_tot_hash_bits - (rotate + 1); rot_idx >= 0; rot_idx--) { - idx = rot_info->p4_hash_output_bit_posn[rot_idx]; - hash_seed_value[(idx + rotate) % HASH_SEED_LENGTH] = hash_seed_value[idx]; - hash_seed_used[(idx + rotate) % HASH_SEED_LENGTH] = hash_seed_used[idx]; - } - - /* Get rotated bits to position. */ - for (bit_posn = 0; bit_posn < rotate; bit_posn++) { - idx = rot_info->p4_hash_output_bit_posn[bit_posn]; - hash_seed_value[idx] = rotate_temp_value[bit_posn]; - hash_seed_used[idx] = rotate_temp_used[bit_posn]; - } - bit_posn = 0; - /* Reform the seed. */ - while (bit_posn < num_tot_hash_bits) { - idx = rot_info->p4_hash_output_bit_posn[bit_posn]; - /* Reset the original bit posn value. */ - hash_seed->hash_seed_value &= ~(1ULL << idx); - hash_seed->hash_seed_used &= ~(1ULL << idx); - if (hash_seed_value[idx]) { - hash_seed->hash_seed_value |= (1ULL << idx); - } - if (hash_seed_used[idx]) { - hash_seed->hash_seed_used |= (1ULL << idx); - } - bit_posn++; - } -} - -static void rotate_matrix(hash_calc_rotate_info_t *rot_info, - hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]) { - uint32_t p4_hash_bit_idx = 0, idx = 0; - hash_column_t temp_col[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]; - uint64_t rotate = rot_info->rotate; - uint32_t num_tot_hash_bits = rot_info->num_hash_bits; - /* Safeguard the rotated coloumn. */ - for (uint32_t i = 0; i < rotate; i++) { - for (uint32_t k = 0; k < PARITY_GROUPS_DYN; k++) { - p4_hash_bit_idx = - rot_info->p4_hash_output_bit_posn[(num_tot_hash_bits - 1) - (rotate - 1) + i]; - idx = rot_info->gfm_bit_posn[p4_hash_bit_idx]; - temp_col[k][i].column_value = hash_matrix[k][idx].column_value; - temp_col[k][i].byte_used = hash_matrix[k][idx].byte_used; - } - } - - /* Right shift as per rotation. */ - for (int i = num_tot_hash_bits - (rotate + 1); i >= 0; i--) { - for (uint32_t k = 0; k < PARITY_GROUPS_DYN; k++) { - p4_hash_bit_idx = rot_info->p4_hash_output_bit_posn[i]; - idx = rot_info->gfm_bit_posn[p4_hash_bit_idx]; - hash_matrix[k][(idx + rotate) % num_tot_hash_bits].column_value = - hash_matrix[k][idx].column_value; - hash_matrix[k][(idx + rotate) % num_tot_hash_bits].byte_used = - hash_matrix[k][idx].byte_used; - } - } - - /* Get rotated bits to position. */ - for (uint32_t i = 0; i < rotate; i++) { - for (uint32_t k = 0; k < PARITY_GROUPS_DYN; k++) { - p4_hash_bit_idx = rot_info->p4_hash_output_bit_posn[i]; - idx = rot_info->gfm_bit_posn[p4_hash_bit_idx]; - hash_matrix[k][idx].column_value = temp_col[k][i].column_value; - hash_matrix[k][idx].byte_used = temp_col[k][i].byte_used; - } - } -} - -/** - * Updates the hash matrix for symmetric fields. - * Every field taking part in symmetric hashing has a sym_group and - * a sib_sym_group. For example if (src_ip, dst_ip) are symmetrically - * hashed, src_ip bits can have group as 1 and sib_sym_group as 2. - * The reverse for dst_ip. Use these groups to figure out which field - * inputs need to be XOR'ed. - * The following property is used if (f2,f3) are symmetric and - * (f4,f5) are symmetric. - * - * symmetric(f1,f2,f3,f4,f5) = crc(f1,f2,f3,f4,f5) ^ crc(f1,f3,f2,f5,f4) - * == crc(f1, f2^f3, f3^f2, f4^f5, f5^f4) - * - */ -void update_symmetric_bits(const ixbar_init_t *ixbar_init, const ixbar_input_t *inputs, - uint32_t inputs_sz, - hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]) { - uint32_t n_groups = 0; - uint32_t *groups = NULL; - uint32_t *sibling_groups = NULL; - bool symmetric_present = false; - hash_column_t hash_matrix_old[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]; - - // Check the input first. If there are no symmetric fields present, - // return - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - if (input->type == tPHV && !input->u.valid) continue; - if (input->type == tCONST) continue; - if (input->symmetric_info.is_symmetric == false) continue; - symmetric_present = true; - } - if (!symmetric_present) return; - - memcpy(hash_matrix_old, hash_matrix, - sizeof(hash_column_t) * PARITY_GROUPS_DYN * HASH_MATRIX_WIDTH_DYN); - - groups = calloc_macro(inputs_sz, sizeof(uint32_t)); - ALLOC_CHECK(groups, "failed to allocate groups"); - - sibling_groups = calloc_macro(inputs_sz, sizeof(uint32_t)); - ALLOC_CHECK(sibling_groups, "failed to allocate sibling_groups"); - - // preprocess the input and record all the groups and sibling groups - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - if (input->type == tPHV && !input->u.valid) continue; - if (input->type == tCONST) continue; - if (input->symmetric_info.is_symmetric == false) continue; - - groups[n_groups] = input->symmetric_info.sym_group; - sibling_groups[n_groups] = input->symmetric_info.sib_sym_group; - n_groups++; - } - - for (uint32_t g = 0; g < n_groups; g++) { - uint32_t cur_sym_count = 0; - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - if (input->type == tPHV && !input->u.valid) continue; - if (input->type == tCONST) continue; - if (input->symmetric_info.is_symmetric == false) continue; - // Process each group at a time - if (input->symmetric_info.sym_group != groups[g]) continue; - - uint32_t sib_sym_count = 0; - const ixbar_input_t *sib_input = NULL; - bool sib_found = false; - // Find the corresponding sibling bit - for (uint32_t a = 0; a < inputs_sz; a++) { - sib_input = inputs + a; - // Check if the prospective sibling's sym_group is the same as - // the sibling group we are trying to find - if (sib_input->symmetric_info.sym_group == sibling_groups[g]) { - if (cur_sym_count == sib_sym_count) { - sib_found = true; - break; - } - sib_sym_count++; - if (sib_sym_count > cur_sym_count) break; - } - } - // If sibling wasn't found, just continue - if (!sib_found) continue; - // Sibling was found. A few sanity checks like comparing bit_size - if (input->bit_size != sib_input->bit_size) continue; - - cur_sym_count++; - - // modify hash_matrix for input with xor of sib_input - - for (uint32_t j = 0; j < input->bit_size; j++) { - uint32_t ixbar_input_bit = input->ixbar_bit_position + j; - uint32_t sib_ixbar_input_bit = sib_input->ixbar_bit_position + j; - - for (uint32_t k = 0; k < ixbar_init->outputs_sz; k++) { - hash_matrix_output_t *output = ixbar_init->hash_matrix_outputs + k; - for (uint32_t l = 0; l < output->bit_size; l++) { - uint32_t galois_bit = output->gfm_start_bit + l; - bool set_bit = - get_matrix_bit(hash_matrix_old, sib_ixbar_input_bit, galois_bit) ^ - get_matrix_bit(hash_matrix_old, ixbar_input_bit, galois_bit); - initialize_matrix_bit(hash_matrix, ixbar_input_bit, galois_bit, set_bit); - } - } - } - } - } - if (groups) free_macro(groups); - if (sibling_groups) free_macro(sibling_groups); -} - -void determine_hash_matrix(const ixbar_init_t *ixbar_init, const ixbar_input_t *inputs, - uint32_t inputs_sz, const bfn_hash_algorithm_t *alg, - hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]) { - uint32_t total_input_bits = 0; - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - total_input_bits += input->bit_size; - } - - ///> Initialize the GFM matrix with the corresponding inputs - int input_bit = 0; - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - ///> Potential holes in inputs during partial crc calculations during the - /// compiler require valid inputs - if (input->type == tPHV && !input->u.valid) { - input_bit += input->bit_size; - continue; - } else if (input->type == tCONST) { - input_bit += input->bit_size; - continue; - } - - ///> Iterate through all inputs and all outputs bit by bit to calculate the - /// bit positions - for (uint32_t j = 0; j < input->bit_size; j++) { - uint32_t ixbar_input_bit = input->ixbar_bit_position + j; - for (uint32_t k = 0; k < ixbar_init->outputs_sz; k++) { - const hash_matrix_output_t *output = ixbar_init->hash_matrix_outputs + k; - for (uint32_t l = 0; l < output->bit_size; l++) { - uint32_t p4_hash_output_bit = output->p4_hash_output_bit + l; - uint32_t galois_bit = output->gfm_start_bit + l; - determine_matrix_bit(hash_matrix, alg, inputs, inputs_sz, ixbar_input_bit, - input_bit, total_input_bits, p4_hash_output_bit, - galois_bit); - } - } - input_bit++; - } - } - - ///> Mark all fields not included in the inputs as used and marked as 0 - for (uint32_t i = 0; i < ixbar_init->inputs_sz; i++) { - ixbar_input_t *input = ixbar_init->ixbar_inputs + i; - if (input->type == tPHV && !input->u.valid) { - continue; - } - if (input->type == tCONST) continue; - for (uint32_t j = 0; j < input->bit_size; j++) { - uint32_t ixbar_input_bit = input->ixbar_bit_position + j; - for (uint32_t k = 0; k < ixbar_init->outputs_sz; k++) { - hash_matrix_output_t *output = ixbar_init->hash_matrix_outputs + k; - for (uint32_t l = 0; l < output->bit_size; l++) { - uint32_t galois_bit = output->gfm_start_bit + l; - initialize_matrix_bit(hash_matrix, ixbar_input_bit, galois_bit, false); - } - } - } - } -} - -void determine_seed(const hash_matrix_output_t *hash_matrix_outputs, uint32_t outputs_sz, - const ixbar_input_t *inputs, uint32_t inputs_sz, uint32_t total_input_bits, - const bfn_hash_algorithm_t *alg, hash_seed_t *hash_seed) { - ///> Initialize the input bitvec with the constant inputs - uint32_t bitvec_sz = compute_bitvec_sz(alg, total_input_bits); - // This is the data stream, and is saved as a bit vector - uint64_t val[bitvec_sz]; - memset(val, 0, sizeof(val)); - initialize_input_data_stream(alg, val, bitvec_sz, inputs, inputs_sz); - - for (uint32_t i = 0; i < outputs_sz; i++) { - const hash_matrix_output_t *output = hash_matrix_outputs + i; - for (uint32_t j = 0; j < output->bit_size; j++) { - uint32_t p4_hash_output_bit = output->p4_hash_output_bit + j; - uint32_t galois_bit = output->gfm_start_bit + j; - determine_seed_bit(hash_seed, val, bitvec_sz, alg, p4_hash_output_bit, total_input_bits, - galois_bit); - } - } -} - -/** - * This builds the changes to the galois field matrix for this particular hash - * function. - */ -void determine_tofino_gfm_delta(hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN], - hash_regs_t *regs) { - int galois_delta_count = 0; - ///> Determine the number of registers that require a change - for (int i = 0; i < PARITY_GROUPS_DYN; i++) { - for (int j = 0; j < HASH_MATRIX_WIDTH_DYN; j++) { - for (int k = 0; k < 8; k += 2) { - if (((1 << k) & hash_matrix[i][j].byte_used) != 0 || - ((1 << (k + 1)) & hash_matrix[i][j].byte_used) != 0) { - galois_delta_count++; - } - } - } - } - - regs->galois_field_matrix_regs = - calloc_macro(galois_delta_count, sizeof(galois_field_matrix_delta_t)); - if (!regs->galois_field_matrix_regs) { - assert_macro(0); - return; - } - - regs->gfm_sz = galois_delta_count; - - ///> Build the array of registers that require the change. - uint32_t gfm_index = 0; - for (int i = 0; i < PARITY_GROUPS_DYN; i++) { - for (int j = 0; j < HASH_MATRIX_WIDTH_DYN; j++) { - for (int k = 0; k < 8; k += 2) { - int byte0_shift = k * 8; - int byte1_shift = (k + 1) * 8; - - if (((1 << k) & hash_matrix[i][j].byte_used) == 0 && - ((1 << (k + 1)) & hash_matrix[i][j].byte_used) == 0) - continue; - - // NOTE: Must be freed after use outside of this - galois_field_matrix_delta_t *gfm_delta = regs->galois_field_matrix_regs + gfm_index; - gfm_delta->byte_pair_index = i * BYTE_PAIRS_PER_PARITY_GROUP + k / 2; - gfm_delta->hash_bit = j; - gfm_delta->byte0 = (hash_matrix[i][j].column_value >> byte0_shift) & 0xffUL; - gfm_delta->byte1 = (hash_matrix[i][j].column_value >> byte1_shift) & 0xffUL; - gfm_delta->valid0 = 0; - gfm_delta->valid1 = 0; - gfm_index++; - } - } - } -} - -void determine_seed_delta(const hash_seed_t *hash_seed, hash_regs_t *regs, uint32_t parity_group) { - int seed_delta_count = 0; - - ///> Determine the number of registers that require a change - for (int i = 0; i < HASH_MATRIX_WIDTH_DYN; i++) { - if (((1ULL << i) & hash_seed->hash_seed_used) != 0ULL) seed_delta_count++; - } - - // NOTE: Must be freed after use outside of this - regs->hash_seed_regs = calloc_macro(seed_delta_count, sizeof(hash_seed_delta_t)); - if (!regs->hash_seed_regs) { - assert_macro(0); - return; - } - - regs->hs_sz = seed_delta_count; - - ///> Build the array of registers that require the change - uint32_t seed_index = 0; - for (int i = 0; i < HASH_MATRIX_WIDTH_DYN; i++) { - uint64_t mask = (1ULL << i); - if ((mask & hash_seed->hash_seed_used) == 0ULL) continue; - uint64_t seed_value = (mask & hash_seed->hash_seed_value) >> i; - hash_seed_delta_t *hs_delta = regs->hash_seed_regs + seed_index; - - hs_delta->hash_bit = i; - hs_delta->hash_seed_and_value = 0xff & ~(1 << parity_group); - hs_delta->hash_seed_or_value = (seed_value << parity_group); - seed_index++; - } -} - -void determine_tofino_regs(const ixbar_init_t *ixbar_init, const ixbar_input_t *inputs, - uint32_t inputs_sz, const bfn_hash_algorithm_t *alg, - hash_calc_rotate_info_t *rot_info, hash_regs_t *regs) { - hash_column_t hash_matrix[PARITY_GROUPS_DYN][HASH_MATRIX_WIDTH_DYN]; - memset(hash_matrix, 0, sizeof(hash_column_t) * PARITY_GROUPS_DYN * HASH_MATRIX_WIDTH_DYN); - - hash_seed_t hash_seed; - memset(&hash_seed, 0, sizeof(hash_seed_t)); - - uint32_t total_input_bits = 0; - for (uint32_t i = 0; i < inputs_sz; i++) { - const ixbar_input_t *input = inputs + i; - total_input_bits += input->bit_size; - } - determine_hash_matrix(ixbar_init, inputs, inputs_sz, alg, hash_matrix); - update_symmetric_bits(ixbar_init, inputs, inputs_sz, hash_matrix); - if (rot_info->rotate) { - rotate_matrix(rot_info, hash_matrix); - } -#ifdef HASH_DEBUG - print_hash_matrix(hash_matrix); - print_hash_matrix_used(hash_matrix); -#endif - determine_seed(ixbar_init->hash_matrix_outputs, ixbar_init->outputs_sz, inputs, inputs_sz, - total_input_bits, alg, &hash_seed); - if (rot_info->rotate) { - rotate_seed(rot_info, &hash_seed); - } - - determine_tofino_gfm_delta(hash_matrix, regs); - determine_seed_delta(&hash_seed, regs, ixbar_init->parity_group); -} diff --git a/bazel/example/.bazelrc b/bazel/example/.bazelrc index 6532c3cafd9..2b925ab17ac 100644 --- a/bazel/example/.bazelrc +++ b/bazel/example/.bazelrc @@ -1 +1,6 @@ +# Remove once #5066 is resolved. +common --enable_workspace +# Enable once #5066 is resolved. +common --noenable_bzlmod + build --action_env=BAZEL_CXXOPTS="-std=c++17" diff --git a/bazel/example/.bazelversion b/bazel/example/.bazelversion index 19b860c1872..815da58b7a9 100644 --- a/bazel/example/.bazelversion +++ b/bazel/example/.bazelversion @@ -1 +1 @@ -6.4.0 +7.4.1 diff --git a/bazel/example/WORKSPACE.bazel b/bazel/example/WORKSPACE.bazel index 4be9dfe7230..0ea8a56e92d 100644 --- a/bazel/example/WORKSPACE.bazel +++ b/bazel/example/WORKSPACE.bazel @@ -7,7 +7,8 @@ local_repository( # This part is optional: only needed for custom backends with IR extensions. repo_mapping = { # Tells p4c where to look for `:ir_extension` target: in this project. - "@com_github_p4lang_p4c_extension": "@example_p4_project", + # The main repo has no name, so a bare `@` means this repository. + "@com_github_p4lang_p4c_extension": "@", }, ) diff --git a/bazel/p4_library.bzl b/bazel/p4_library.bzl index 07e38eb62a7..4882cdd8149 100644 --- a/bazel/p4_library.bzl +++ b/bazel/p4_library.bzl @@ -170,7 +170,6 @@ p4_library = rule( default = Label("@com_github_p4lang_p4c//:p4include"), allow_files = [".p4", ".h"], ), - "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), }, toolchains = use_cpp_toolchain(), ) @@ -250,7 +249,6 @@ p4_graphs = rule( default = Label("@com_github_p4lang_p4c//:p4include"), allow_files = [".p4", ".h"], ), - "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), }, toolchains = use_cpp_toolchain(), ) diff --git a/cmake/Linters.cmake b/cmake/Linters.cmake index 459bed4da24..ecab52b80e5 100644 --- a/cmake/Linters.cmake +++ b/cmake/Linters.cmake @@ -137,6 +137,7 @@ file( ) list(FILTER P4C_PYTHON_LINT_LIST EXCLUDE REGEX "backends/p4tools/submodules") list(FILTER P4C_PYTHON_LINT_LIST EXCLUDE REGEX "backends/ebpf/runtime/contrib/libbpf") +list(FILTER P4C_PYTHON_LINT_LIST EXCLUDE REGEX "backends/tofino/third_party") list(FILTER P4C_PYTHON_LINT_LIST EXCLUDE REGEX "tools/cpplint.py") add_black_files(${P4C_SOURCE_DIR} "${P4C_PYTHON_LINT_LIST}") diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake index 11de85d8eae..661a54576aa 100644 --- a/cmake/config.h.cmake +++ b/cmake/config.h.cmake @@ -4,9 +4,6 @@ /* Define to 1 if you have the boost graph headers */ #cmakedefine HAVE_LIBBOOST_GRAPH 1 -/* Define to 1 if you have the execinfo.h header */ -#cmakedefine HAVE_EXECINFO_H 1 - /* Define to 1 if you have libbacktrace */ #cmakedefine HAVE_LIBBACKTRACE 1 diff --git a/docs/README.md b/docs/README.md index afdd34f2224..322a98dcffc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -175,7 +175,7 @@ overview of the compiler goals and architecture. ### Doxygen Comments Style Guide - Comment Markup and Documentation Commands - `` is used for adding documentation inclusion notes. This content is hidden from both the rendered Markdown and Doxygen, but visible in the raw view on GitHub. - - `````` hides commands from GitHub’s Markdown rendering but provides instructions to Doxygen. For example: + - Use HTML comments with an exclamation mark to add instructions for Doxygen. These comments are hidden in GitHub's Markdown but processed by Doxygen. For example: ``` +