diff --git a/backends/p4tools/common/lib/format_int.cpp b/backends/p4tools/common/lib/format_int.cpp index a135ab4c00..236342a171 100644 --- a/backends/p4tools/common/lib/format_int.cpp +++ b/backends/p4tools/common/lib/format_int.cpp @@ -269,7 +269,8 @@ std::string insertHexSeparators(const std::string &dataStr) { return insertSeparators(dataStr, "\\x", 2, false); } -std::vector convertBigIntToBytes(const big_int &dataInt, int targetWidthBits) { +std::vector convertBigIntToBytes(const big_int &dataInt, int targetWidthBits, + bool padLeft) { /// Chunk size is 8 bits, i.e., a byte. constexpr uint8_t chunkSize = 8U; @@ -282,7 +283,11 @@ std::vector convertBigIntToBytes(const big_int &dataInt, int targetWidt auto diff = targetWidthBytes - bytes.size(); if (targetWidthBytes > bytes.size() && diff > 0UL) { for (size_t i = 0; i < diff; ++i) { - bytes.push_back(0); + if (padLeft) { + bytes.insert(bytes.begin(), 0); + } else { + bytes.push_back(0); + } } } return bytes; diff --git a/backends/p4tools/common/lib/format_int.h b/backends/p4tools/common/lib/format_int.h index 1e3e0288ac..ead545cfa2 100644 --- a/backends/p4tools/common/lib/format_int.h +++ b/backends/p4tools/common/lib/format_int.h @@ -78,9 +78,11 @@ std::string insertOctalSeparators(const std::string &dataStr); std::string insertHexSeparators(const std::string &dataStr); /// Converts a big integer input into a vector of bytes with the size targetWidthBits /8. -/// If the integer value is smaller than the request bit size, padding is added on the right-hand -/// side of the vector (the "least-significant" side). -std::vector convertBigIntToBytes(const big_int &dataInt, int targetWidthBits); +/// If the integer value is smaller than the request bit size and @param padLeft is false, padding +/// is added on the right-hand side of the vector (the "least-significant" side). Otherwise, padding +/// is added on the left-hand side, (the "most-significant side") +std::vector convertBigIntToBytes(const big_int &dataInt, int targetWidthBits, + bool padLeft = false); /// Convert a byte array into a IPv4 string of the form "x.x.x.x". /// @returns std::nullopt if the conversion fails. diff --git a/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp b/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp index bba6e35300..d6b6f17487 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp @@ -13,12 +13,12 @@ #include #include +#include "backends/p4tools/common/lib/format_int.h" #include "backends/p4tools/common/lib/model.h" #include "ir/irutils.h" #include "ir/vector.h" #include "lib/cstring.h" #include "lib/exceptions.h" -#include "lib/log.h" #include "backends/p4tools/modules/testgen/lib/concolic.h" #include "backends/p4tools/modules/testgen/lib/exceptions.h" @@ -28,23 +28,6 @@ namespace P4Tools::P4Testgen::Bmv2 { -std::vector Bmv2Concolic::convertBigIntToBytes(big_int &dataInt, int targetWidthBits) { - std::vector bytes; - // Convert the input bit width to bytes and round up. - size_t targetWidthBytes = (targetWidthBits + CHUNK_SIZE - 1) / CHUNK_SIZE; - boost::multiprecision::export_bits(dataInt, std::back_inserter(bytes), CHUNK_SIZE); - // If the number of bytes produced by the export is lower than the desired width pad the byte - // array with zeroes. - auto diff = targetWidthBytes - bytes.size(); - if (targetWidthBytes > bytes.size() && diff > 0UL) { - for (size_t i = 0; i < diff; ++i) { - bytes.insert(bytes.begin(), 0); - } - } - - return bytes; -} - big_int Bmv2Concolic::computeChecksum(const std::vector &exprList, const Model &finalModel, int algo, Model::ExpressionMap *resolvedExpressions) { @@ -80,7 +63,7 @@ big_int Bmv2Concolic::computeChecksum(const std::vector TESTGEN_UNIMPLEMENTED("Algorithm %1% not implemented for hash.", algo); } - std::vector bytes; + std::vector bytes; if (!exprList.empty()) { const auto *concatExpr = exprList.at(0); for (size_t idx = 1; idx < exprList.size(); idx++) { @@ -102,7 +85,7 @@ big_int Bmv2Concolic::computeChecksum(const std::vector } auto dataInt = IR::getBigIntFromLiteral(finalModel.evaluate(concatExpr, true, resolvedExpressions)); - bytes = convertBigIntToBytes(dataInt, concatWidth); + bytes = convertBigIntToBytes(dataInt, concatWidth, true); } return checksumFun(bytes.data(), bytes.size()); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/concolic.h b/backends/p4tools/modules/testgen/targets/bmv2/concolic.h index e98a85d482..127599f18f 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/concolic.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/concolic.h @@ -16,7 +16,7 @@ namespace P4Tools::P4Testgen::Bmv2 { class Bmv2Concolic : public Concolic { private: /// In the behavioral model, checksum functions have the following signature. - using ChecksumFunction = std::function; + using ChecksumFunction = std::function; /// Chunk size is 8 bits, i.e., a byte. static constexpr int CHUNK_SIZE = 8; @@ -53,11 +53,6 @@ class Bmv2Concolic : public Concolic { static const IR::Expression *setAndComputePayload( const Model &finalModel, ConcolicVariableMap *resolvedConcolicVariables, int payloadSize); - /// Converts a big integer input into a vector of bytes. This byte vector is fed into the - /// hash function. - /// This function mimics the conversion of data structures to bytes in the behavioral model. - static std::vector convertBigIntToBytes(big_int &dataInt, int targetWidthBits); - public: /// @returns the concolic functions that are implemented for this particular target. static const ConcolicMethodImpls::ImplList *getBmv2ConcolicMethodImpls(); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.cpp b/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.cpp index 5f9303ff30..ad8b516f14 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.cpp @@ -91,7 +91,7 @@ static uint32_t table_crc32[256] = { 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4}; -uint16_t BMv2Hash::crc16(const char *buf, size_t len) { +uint16_t BMv2Hash::crc16(const uint8_t *buf, size_t len) { uint16_t remainder = 0x0000; uint16_t final_xor_value = 0x0000; for (unsigned int byte = 0; byte < len; byte++) { @@ -101,7 +101,7 @@ uint16_t BMv2Hash::crc16(const char *buf, size_t len) { return reflect(remainder, 16) ^ final_xor_value; } -uint32_t BMv2Hash::crc32(const char *buf, size_t len) { +uint32_t BMv2Hash::crc32(const uint8_t *buf, size_t len) { uint32_t remainder = 0xFFFFFFFF; uint32_t final_xor_value = 0xFFFFFFFF; for (unsigned int byte = 0; byte < len; byte++) { @@ -111,17 +111,17 @@ uint32_t BMv2Hash::crc32(const char *buf, size_t len) { return reflect(remainder, 32) ^ final_xor_value; } -uint16_t BMv2Hash::crcCCITT(const char *buf, size_t len) { +uint16_t BMv2Hash::crcCCITT(const uint8_t *buf, size_t len) { uint16_t remainder = 0xFFFF; uint16_t final_xor_value = 0x0000; for (unsigned int byte = 0; byte < len; byte++) { - int data = static_cast(buf[byte]) ^ (remainder >> 8); + int data = static_cast(buf[byte]) ^ (remainder >> 8); remainder = table_crcCCITT[data] ^ (remainder << 8); } return remainder ^ final_xor_value; } -uint16_t BMv2Hash::csum16(const char *buf, size_t len) { +uint16_t BMv2Hash::csum16(const uint8_t *buf, size_t len) { uint64_t sum = 0; const uint64_t *b = reinterpret_cast(buf); uint32_t t1, t2; @@ -165,7 +165,7 @@ uint16_t BMv2Hash::csum16(const char *buf, size_t len) { return ntohs(~t3); } -uint16_t BMv2Hash::xor16(const char *buf, size_t len) { +uint16_t BMv2Hash::xor16(const uint8_t *buf, size_t len) { uint16_t mask = 0x00ff; uint16_t final_xor_value = 0x0000; unsigned int byte = 0; @@ -185,7 +185,7 @@ uint16_t BMv2Hash::xor16(const char *buf, size_t len) { return final_xor_value; } -uint64_t BMv2Hash::identity(const char *buf, size_t len) { +uint64_t BMv2Hash::identity(const uint8_t *buf, size_t len) { uint64_t res = 0ULL; for (size_t i = 0; i < std::min(sizeof(res), len); i++) { if (i > 0) res <<= 8; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.h b/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.h index 87575b2f96..3218dfe8bc 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.h @@ -48,17 +48,17 @@ class BMv2Hash { } public: - static uint16_t crc16(const char *buf, size_t len); + static uint16_t crc16(const uint8_t *buf, size_t len); - static uint32_t crc32(const char *buf, size_t len); + static uint32_t crc32(const uint8_t *buf, size_t len); - static uint16_t crcCCITT(const char *buf, size_t len); + static uint16_t crcCCITT(const uint8_t *buf, size_t len); - static uint16_t csum16(const char *buf, size_t len); + static uint16_t csum16(const uint8_t *buf, size_t len); - static uint16_t xor16(const char *buf, size_t len); + static uint16_t xor16(const uint8_t *buf, size_t len); - static uint64_t identity(const char *buf, size_t len); + static uint64_t identity(const uint8_t *buf, size_t len); }; } // namespace P4Tools::P4Testgen::Bmv2