diff --git a/bench/UpperPHY/LDPC/Decoding/main.cpp b/bench/UpperPHY/LDPC/Decoding/main.cpp index 16486d73dd9338814d6fe6bc920ad4c1909b7601..91560616a3221a127be316d0bfd4345e52090e03 100755 --- a/bench/UpperPHY/LDPC/Decoding/main.cpp +++ b/bench/UpperPHY/LDPC/Decoding/main.cpp @@ -28,6 +28,7 @@ void run_ldpc_decoding_perf(uint32_t n, armral_ldpc_graph_t bg, uint32_t z, std::vector data_out((num_llrs + 7) / 8); const auto *llr_ptr = llrs.data(); auto *out_ptr = data_out.data(); + uint32_t its_out = 0; #ifdef ARMRAL_BENCH_NOALLOC auto buffer_size = @@ -42,9 +43,9 @@ void run_ldpc_decoding_perf(uint32_t n, armral_ldpc_graph_t bg, uint32_t z, #else for (uint32_t r = 0; r < num_reps; ++r) { heap_allocator allocator{}; - armral::ldpc::decode_block(n, llr_ptr, bg, z, - len_filler_bits, out_ptr, - num_its, options, allocator); + armral::ldpc::decode_block( + n, llr_ptr, bg, z, len_filler_bits, out_ptr, num_its, &its_out, options, + allocator); } #endif } diff --git a/include/armral.h b/include/armral.h index f05fea3f7599932e6483e9709ec008b98ec78a45..ff3c30d5c1e8528af22f716181c5b7ef28e4e9f9 100644 --- a/include/armral.h +++ b/include/armral.h @@ -3564,7 +3564,12 @@ typedef struct { * * Option used by \ref armral_ldpc_decode_block. * - * Not currently supported. + * If set, a CRC check will be performed during the decoding. The frequency of + * how often the CRC check is done is determined by \ref + * ARMRAL_LDPC_CRC_EVERY_ITER and \ref ARMRAL_LDPC_CRC_END_ITER. If the CRC + * check succeeds, \ref armral_ldpc_decode_block will return `ARMRAL_SUCCESS`. + * If the CRC check fails on the last iteration, \ref armral_ldpc_decode_block + * will return `ARMRAL_FAIL`. */ #define ARMRAL_LDPC_CRC_16 (1 << 2) @@ -3573,7 +3578,12 @@ typedef struct { * * Option used by \ref armral_ldpc_decode_block. * - * Not currently supported. + * If set, a CRC check will be performed during the decoding. The frequency of + * how often the CRC check is done is determined by \ref + * ARMRAL_LDPC_CRC_EVERY_ITER and \ref ARMRAL_LDPC_CRC_END_ITER. If the CRC + * check succeeds, \ref armral_ldpc_decode_block will return `ARMRAL_SUCCESS`. + * If the CRC check fails on the last iteration, \ref armral_ldpc_decode_block + * will return `ARMRAL_FAIL`. */ #define ARMRAL_LDPC_CRC_24A (1 << 3) @@ -3795,8 +3805,8 @@ uint32_t armral_ldpc_encode_block_noalloc_buffer_size(armral_ldpc_graph_t bg, * * CRC Type: * - \ref ARMRAL_LDPC_CRC_NO (default) - * - \ref ARMRAL_LDPC_CRC_16 (not implemented) - * - \ref ARMRAL_LDPC_CRC_24A (not implemented) + * - \ref ARMRAL_LDPC_CRC_16 + * - \ref ARMRAL_LDPC_CRC_24A * - \ref ARMRAL_LDPC_CRC_24B * * CRC Mode: @@ -3812,8 +3822,13 @@ uint32_t armral_ldpc_encode_block_noalloc_buffer_size(armral_ldpc_graph_t bg, * `armral_ldpc_decode_block` returns `ARMRAL_ARGUMENT_ERROR`. * * If \ref ARMRAL_LDPC_CRC_NO (default) is set in `options`, no CRC check is - * performed. If \ref ARMRAL_LDPC_CRC_24B is set in `options`, a CRC check will - * be performed using \ref armral_crc24_b_be. The frequency of how often the + * performed. If \ref ARMRAL_LDPC_CRC_16 is set in `options`, a CRC check will + * be performed using \ref armral_crc16_be. + * If \ref ARMRAL_LDPC_CRC_24A is set in `options`, a CRC check will + * be performed using \ref armral_crc24_a_be. + * If \ref ARMRAL_LDPC_CRC_24B is set in `options`, a CRC check will + * be performed using \ref armral_crc24_b_be. + * The frequency of how often the * CRC check is done is determined by \ref ARMRAL_LDPC_CRC_EVERY_ITER (default) * and \ref ARMRAL_LDPC_CRC_END_ITER. If the CRC check succeeds, * `armral_ldpc_decode_block` returns `ARMRAL_SUCCESS`. If the CRC check fails @@ -3855,10 +3870,11 @@ uint32_t armral_ldpc_encode_block_noalloc_buffer_size(armral_ldpc_graph_t bg, * graph 1 and `10 * z` for base graph 2. It is assumed * that the array `data_out` is able to store this many * bits. - * @param[in] max_its The maximum number of iterations of the LDPC decoder. + * @param[in] its_max The maximum number of iterations of the LDPC decoder. * The algorithm may terminate after fewer iterations if * the current candidate codeword passes all the parity * checks, or if it satisfies the CRC check. + * @param[out] its_out Number of Iterations taken to complete LDPC Decoding. * @param[in] options See the documentation above for a summary of available * `options`. If you want to use the default options, set * the options parameter to either `0` or @@ -3870,8 +3886,8 @@ uint32_t armral_ldpc_encode_block_noalloc_buffer_size(armral_ldpc_graph_t bg, armral_status armral_ldpc_decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, uint32_t len_filler_bits, - uint8_t *data_out, uint32_t max_its, - uint32_t options); + uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options); /** * Non-allocating variant of \link armral_ldpc_decode_block \endlink. @@ -3891,8 +3907,8 @@ armral_status armral_ldpc_decode_block(uint32_t n, const int8_t *llrs, * * CRC Type: * - \ref ARMRAL_LDPC_CRC_NO (default) - * - \ref ARMRAL_LDPC_CRC_16 (not implemented) - * - \ref ARMRAL_LDPC_CRC_24A (not implemented) + * - \ref ARMRAL_LDPC_CRC_16 + * - \ref ARMRAL_LDPC_CRC_24A * - \ref ARMRAL_LDPC_CRC_24B * * CRC Mode: @@ -3908,8 +3924,13 @@ armral_status armral_ldpc_decode_block(uint32_t n, const int8_t *llrs, * `armral_ldpc_decode_block` returns `ARMRAL_ARGUMENT_ERROR`. * * If \ref ARMRAL_LDPC_CRC_NO (default) is set in `options`, no CRC check is - * performed. If \ref ARMRAL_LDPC_CRC_24B is set in `options`, a CRC check will - * be performed using \ref armral_crc24_b_be. The frequency of how often the + * performed. If \ref ARMRAL_LDPC_CRC_16 is set in `options`, a CRC check will + * be performed using \ref armral_crc16_be. + * If \ref ARMRAL_LDPC_CRC_24A is set in `options`, a CRC check will + * be performed using \ref armral_crc24_a_be. + * If \ref ARMRAL_LDPC_CRC_24B is set in `options`, a CRC check will + * be performed using \ref armral_crc24_b_be. + * The frequency of how often the * CRC check is done is determined by \ref ARMRAL_LDPC_CRC_EVERY_ITER (default) * and \ref ARMRAL_LDPC_CRC_END_ITER. If the CRC check succeeds, * `armral_ldpc_decode_block` returns `ARMRAL_SUCCESS`. If the CRC check fails @@ -3951,10 +3972,11 @@ armral_status armral_ldpc_decode_block(uint32_t n, const int8_t *llrs, * graph 1 and `10 * z` for base graph 2. It is assumed * that the array `data_out` is able to store this many * bits. - * @param[in] max_its The maximum number of iterations of the LDPC decoder. + * @param[in] its_max The maximum number of iterations of the LDPC decoder. * The algorithm may terminate after fewer iterations if * the current candidate codeword passes all the parity * checks, or if it satisfies the CRC check. + * @param[out] its_out Number of Iterations taken to complete LDPC Decoding. * @param[in] options See the documentation above for a summary of available * `options`. If you want to use the default options, set * the options parameter to either `0` or @@ -3966,8 +3988,8 @@ armral_status armral_ldpc_decode_block(uint32_t n, const int8_t *llrs, */ armral_status armral_ldpc_decode_block_noalloc( uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options, void *buffer); + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options, void *buffer); /** * Calculates the required buffer size in bytes needed to perform LDPC decoding @@ -3976,7 +3998,7 @@ armral_status armral_ldpc_decode_block_noalloc( * @param[in] bg The type of base graph to use for the decoding. * @param[in] z The lifting size. Valid values of the lifting size are * described in table 5.3.2-1 in TS 38.212. - * @param[in] max_its The maximum number of iterations of the LDPC decoder. + * @param[in] its_max The maximum number of iterations of the LDPC decoder. * The algorithm may terminate after fewer iterations if * the current candidate codeword passes all the parity * checks, or if it satisfies the CRC check. @@ -3984,7 +4006,7 @@ armral_status armral_ldpc_decode_block_noalloc( */ uint32_t armral_ldpc_decode_block_noalloc_buffer_size(armral_ldpc_graph_t bg, uint32_t z, - uint32_t max_its); + uint32_t its_max); /** * Matches the rate of the code block encoded with LDPC code to the rate of the diff --git a/simulation/ldpc_awgn/ldpc_awgn.cpp b/simulation/ldpc_awgn/ldpc_awgn.cpp index 0a3827afc2f668dfc6088f765e721f562a454b34..e9611b4f6871806145c09a13a0dc1bba7b91d8b2 100644 --- a/simulation/ldpc_awgn/ldpc_awgn.cpp +++ b/simulation/ldpc_awgn/ldpc_awgn.cpp @@ -223,9 +223,10 @@ int run_check(armral::utils::random_state *state, uint32_t z, data->data_recovered); // Run LDPC decoding for a single block + uint32_t its_out = 0; armral_ldpc_decode_block(data->len_encoded, data->data_recovered, bg, z, data->len_filler_bits, data->data_decoded, 10, - ARMRAL_LDPC_CRC_NO); + &its_out, ARMRAL_LDPC_CRC_NO); // To make it easier to compare the values, convert the bit array to a byte // array diff --git a/src/UpperPHY/LDPC/arm_ldpc_decoder.cpp b/src/UpperPHY/LDPC/arm_ldpc_decoder.cpp index eabb719a4f620ef386dbbb9a7ec883f9b6f56573..1dfe24e4b847d8f4668f3b6100f21a69a923109f 100644 --- a/src/UpperPHY/LDPC/arm_ldpc_decoder.cpp +++ b/src/UpperPHY/LDPC/arm_ldpc_decoder.cpp @@ -19,6 +19,8 @@ namespace armral::ldpc { +enum class crc_options { CRC16, CRC24A, CRC24B, NONE }; + // compute number of half words supported inline uint32_t get_num_lanes() { #if ARMRAL_ARCH_SVE >= 2 @@ -1293,7 +1295,7 @@ void compute_l_r_and_mins(int16_t *__restrict__ l, int16_t *__restrict__ r, } bool hard_decision(int16_t *ptr_l, uint8_t *crc_buff, uint8_t *ptr_data, - uint32_t k, uint32_t crc_flag) { + uint32_t k, uint32_t crc_flag, crc_options crc_type) { uint32_t num_lanes = get_num_lanes(); uint32_t k_prime = k; @@ -1408,8 +1410,27 @@ bool hard_decision(int16_t *ptr_l, uint8_t *crc_buff, uint8_t *ptr_data, // Generate the CRC parity bits uint64_t crc = 0; if (crc_flag != 0U) { - armral_crc24_b_be((k_prime >> 3) + pad_bytes, (const uint64_t *)crc_buff, + switch (crc_type) { + case crc_options::CRC16: + armral_crc16_be((k_prime >> 3) + pad_bytes, (const uint64_t *)crc_buff, &crc); + break; + + case crc_options::CRC24A: + armral_crc24_a_be((k_prime >> 3) + pad_bytes, (const uint64_t *)crc_buff, + &crc); + break; + + case crc_options::CRC24B: + armral_crc24_b_be((k_prime >> 3) + pad_bytes, (const uint64_t *)crc_buff, + &crc); + break; + + case crc_options::NONE: + default: + break; + } + // Removing the Zero padding if (pad_bytes != 0U) { for (uint32_t i = 0; i < (k_prime >> 3); i++) { @@ -1637,8 +1658,6 @@ inline void load_ptr_l(int16_t *ptr_l, const int8_t *llrs_ptr, uint32_t len_in, } } -enum class crc_options { CRC16, CRC24A, CRC24B, NONE }; - std::optional parse_crc_option(uint32_t options) { uint32_t mask = ARMRAL_LDPC_CRC_NO | ARMRAL_LDPC_CRC_16 | ARMRAL_LDPC_CRC_24A | ARMRAL_LDPC_CRC_24B; @@ -1646,9 +1665,9 @@ std::optional parse_crc_option(uint32_t options) { switch (option) { case ARMRAL_LDPC_CRC_16: - return std::nullopt; // Not supported + return crc_options::CRC16; case ARMRAL_LDPC_CRC_24A: - return std::nullopt; // Not supported + return crc_options::CRC24A; case ARMRAL_LDPC_CRC_24B: return crc_options::CRC24B; case ARMRAL_LDPC_CRC_NO: @@ -1695,10 +1714,11 @@ std::optional parse_implicit_bits_option(uint32_t options) { template armral_status decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options, Allocator &allocator) { + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options, Allocator &allocator) { bool crc_passed = false; + *its_out = its_max; // Get the base graph and the lifting size const auto *graph = armral_ldpc_get_base_graph(bg); @@ -1775,7 +1795,7 @@ decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, uint32_t full_blk = z_len / num_lanes; - for (uint32_t it = 0; it < max_its; ++it) { + for (uint32_t it = 0; it < its_max; ++it) { r_index = 0; for (uint32_t layer = 0; layer < no_of_rows; layer++) { @@ -1820,10 +1840,11 @@ decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, // decision and CRC at the iteration if (iter_option == iter_options::EVERY) { - crc_passed = - hard_decision(l.get(), crc_buff.get(), &data_out[0], - graph->nmessage_bits * z - len_filler_bits, true); + crc_passed = hard_decision(l.get(), crc_buff.get(), &data_out[0], + graph->nmessage_bits * z - len_filler_bits, + true, crc_option); if (crc_passed) { + *its_out = it + 1; break; } } @@ -1832,17 +1853,17 @@ decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, // do decision and CRC if (iter_option == iter_options::END) { // ignore filler bits - crc_passed = - hard_decision(l.get(), crc_buff.get(), &data_out[0], - graph->nmessage_bits * z - len_filler_bits, true); + crc_passed = hard_decision(l.get(), crc_buff.get(), &data_out[0], + graph->nmessage_bits * z - len_filler_bits, true, + crc_option); } // do only decisions if (iter_option == iter_options::NEVER) { // ignore filler bits - crc_passed = - hard_decision(l.get(), crc_buff.get(), &data_out[0], - graph->nmessage_bits * z - len_filler_bits, false); + crc_passed = hard_decision(l.get(), crc_buff.get(), &data_out[0], + graph->nmessage_bits * z - len_filler_bits, + false, crc_option); } return crc_passed ? ARMRAL_SUCCESS : ARMRAL_FAIL; } @@ -1851,40 +1872,41 @@ decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, template armral_status armral::ldpc::decode_block( uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options, heap_allocator &); + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options, heap_allocator &); template armral_status armral::ldpc::decode_block( uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options, buffer_bump_allocator &); + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options, buffer_bump_allocator &); armral_status armral_ldpc_decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, uint32_t len_filler_bits, - uint8_t *data_out, uint32_t max_its, - uint32_t options) { + uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options) { heap_allocator allocator{}; return armral::ldpc::decode_block(n, llrs, bg, z, len_filler_bits, data_out, - max_its, options, allocator); + its_max, its_out, options, allocator); } armral_status armral_ldpc_decode_block_noalloc( uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options, void *buffer) { + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options, void *buffer) { buffer_bump_allocator allocator{buffer}; return armral::ldpc::decode_block(n, llrs, bg, z, len_filler_bits, data_out, - max_its, options, allocator); + its_max, its_out, options, allocator); } uint32_t armral_ldpc_decode_block_noalloc_buffer_size(armral_ldpc_graph_t bg, uint32_t z, - uint32_t max_its) { + uint32_t its_max) { + uint32_t its_out; counting_allocator allocator{}; - armral::ldpc::decode_block(0, nullptr, bg, z, 0, nullptr, max_its, + armral::ldpc::decode_block(0, nullptr, bg, z, 0, nullptr, its_max, &its_out, ARMRAL_LDPC_CRC_NO, allocator); return allocator.required_bytes(); } diff --git a/src/UpperPHY/LDPC/ldpc_coding.hpp b/src/UpperPHY/LDPC/ldpc_coding.hpp index 03794659ae2e3d409f33faff18e722030e1260e0..fa8340d284cee640392c3b1b724a02aafb9d0a9f 100644 --- a/src/UpperPHY/LDPC/ldpc_coding.hpp +++ b/src/UpperPHY/LDPC/ldpc_coding.hpp @@ -17,7 +17,7 @@ uint32_t get_lifting_index(uint32_t lifting_size); template armral_status decode_block(uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options, Allocator &allocator); + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options, Allocator &allocator); } // namespace armral::ldpc diff --git a/test/UpperPHY/LDPC/Decoding/main.cpp b/test/UpperPHY/LDPC/Decoding/main.cpp index b1164e030fc42a6f52e874bcd2fbdfac11327e51..55052924e98833b6e7ee921077fe60d124700da0 100644 --- a/test/UpperPHY/LDPC/Decoding/main.cpp +++ b/test/UpperPHY/LDPC/Decoding/main.cpp @@ -19,12 +19,13 @@ namespace { void ldpc_crc_attachment(const uint8_t *data_in, uint32_t k_prime, uint32_t k, - uint8_t *data_out) { + uint32_t crc_type, uint8_t *data_out) { // Initialize the output to zero, which takes care of the filler bits memset(data_out, 0, sizeof(uint8_t) * ((k + 7) >> 3)); - // Number of crc bits to be attached to the code block. For LDPC this is 24. - constexpr uint32_t l = 24; + // Number of crc bits to be attached to the code block. For LDPC this is 16/24 + // based on CRC Type. + uint32_t l = (crc_type == ARMRAL_LDPC_CRC_16) ? 16 : 24; // Number of bytes containing information bits (not including CRC bits) uint32_t num_info_bits = k_prime - l; @@ -60,7 +61,19 @@ void ldpc_crc_attachment(const uint8_t *data_in, uint32_t k_prime, uint32_t k, // Generate the CRC parity bits uint64_t crc = 0; - armral_crc24_b_be(buffer_size, (const uint64_t *)buffer.data(), &crc); + switch (crc_type) { + case ARMRAL_LDPC_CRC_16: + armral_crc16_be(buffer_size, (const uint64_t *)buffer.data(), &crc); + break; + + case ARMRAL_LDPC_CRC_24A: + armral_crc24_a_be(buffer_size, (const uint64_t *)buffer.data(), &crc); + break; + + case ARMRAL_LDPC_CRC_24B: + armral_crc24_b_be(buffer_size, (const uint64_t *)buffer.data(), &crc); + break; + } // Copy the bytes containing information bits memcpy(data_out, data_in, sizeof(uint8_t) * num_info_bytes); @@ -70,14 +83,20 @@ void ldpc_crc_attachment(const uint8_t *data_in, uint32_t k_prime, uint32_t k, uint32_t info_rem_bits = num_info_bits % 8; uint32_t shift = info_rem_bits > 0 ? 8 - info_rem_bits : 0; - // Make sure any non-information bits in the last information byte are zeroed - data_out[num_info_bytes - 1] &= (255 << shift); - - // Put the CRC bits into place - data_out[num_info_bytes - 1] |= (crc >> (24 - shift)); - data_out[num_info_bytes] = crc >> (16 - shift); - data_out[num_info_bytes + 1] = crc >> (8 - shift); - data_out[num_info_bytes + 2] = crc << shift; + if (crc_type == ARMRAL_LDPC_CRC_16) { + data_out[num_info_bytes] = (crc >> 8) & 0xFF; + data_out[num_info_bytes + 1] = crc & 0xFF; + } else { + // Make sure any non-information bits in the last information byte are + // zeroed + data_out[num_info_bytes - 1] &= (255 << shift); + + // Put the CRC bits into place + data_out[num_info_bytes - 1] |= (crc >> (24 - shift)); + data_out[num_info_bytes] = crc >> (16 - shift); + data_out[num_info_bytes + 1] = crc >> (8 - shift); + data_out[num_info_bytes + 2] = crc << shift; + } } bool check_decoded_message(uint32_t len, const uint8_t *orig, @@ -101,6 +120,7 @@ bool check_decoded_message(uint32_t len, const uint8_t *orig, template bool run_ldpc_decoding_test(uint32_t its, uint32_t z, armral_ldpc_graph_t bg, uint32_t options, uint32_t len_filler_bits, + uint32_t *its_out, LDPCDecodingFunction ldpc_decoding_under_test) { bool passed = true; @@ -119,10 +139,16 @@ bool run_ldpc_decoding_test(uint32_t its, uint32_t z, armral_ldpc_graph_t bg, auto to_encode = random.vector((buf_len_in + 7) / 8); // If we are doing CRC checking, then we need to attach CRC bits to the input + uint32_t mask = ARMRAL_LDPC_CRC_NO | ARMRAL_LDPC_CRC_16 | + ARMRAL_LDPC_CRC_24A | ARMRAL_LDPC_CRC_24B; + uint32_t crc_type = options & mask; + if (!(options & ARMRAL_LDPC_CRC_NO)) { auto info_to_encode = random.vector((buf_len_in + 7) / 8); - ldpc_crc_attachment(info_to_encode.data(), len_in, len_in - 24, - to_encode.data()); + ldpc_crc_attachment( + info_to_encode.data(), len_in, + ((crc_type == ARMRAL_LDPC_CRC_16) ? (len_in - 16) : (len_in - 24)), + crc_type, to_encode.data()); if (len_filler_bits) { memset(&to_encode.data()[(len_in + 7) >> 3], 0, sizeof(uint8_t) * ((len_filler_bits + 7) >> 3)); @@ -175,7 +201,7 @@ bool run_ldpc_decoding_test(uint32_t its, uint32_t z, armral_ldpc_graph_t bg, } if (ldpc_decoding_under_test(n, data_demod_soft.data(), bg, z, - len_filler_bits, decoded.data(), its, + len_filler_bits, decoded.data(), its, its_out, options) != ARMRAL_SUCCESS) { return false; } @@ -198,22 +224,28 @@ bool run_all_tests(char const *name, std::array bgs{LDPC_BASE_GRAPH_1, LDPC_BASE_GRAPH_2}; std::array num_its{1, 2, 5, 10}; std::array zs{2, 6, 13, 20, 30, 56, 144, 208, 224, 256, 320, 384}; - for (auto bg : bgs) { - for (uint32_t i = 0; i < zs.size(); i++) { - auto z = zs[i]; - uint32_t options = z >= 208 ? ARMRAL_LDPC_CRC_24B : ARMRAL_LDPC_CRC_NO; - uint32_t len_filler_bits = (z >= 208) ? 32 : 0; - for (auto its : num_its) { - printf("[%s] z = %d, its = %d len_filler_bits = %d\n", name, z, its, - len_filler_bits); - auto check = run_ldpc_decoding_test( - its, z, bg, options, len_filler_bits, ldpc_decoding_under_test); - if (!check) { - // GCOVR_EXCL_START - printf("Decoding failed\n"); - // GCOVR_EXCL_STOP + std::array crc_type{ARMRAL_LDPC_CRC_16, ARMRAL_LDPC_CRC_24A, + ARMRAL_LDPC_CRC_24B}; + for (uint32_t crc = 0; crc < crc_type.size(); crc++) { + for (auto bg : bgs) { + for (uint32_t i = 0; i < zs.size(); i++) { + auto z = zs[i]; + uint32_t options = z >= 208 ? crc_type[crc] : ARMRAL_LDPC_CRC_NO; + uint32_t len_filler_bits = (z >= 208) ? 32 : 0; + for (auto its : num_its) { + uint32_t its_out = 0; + printf("[%s] z = %d, its = %d len_filler_bits = %d\n", name, z, its, + len_filler_bits); + auto check = + run_ldpc_decoding_test(its, z, bg, options, len_filler_bits, + &its_out, ldpc_decoding_under_test); + if (!check) { + // GCOVR_EXCL_START + printf("Decoding failed\n"); + // GCOVR_EXCL_STOP + } + passed &= check; } - passed &= check; } } } @@ -228,14 +260,14 @@ int main(int argc, char **argv) { passed &= run_all_tests( "LDPCDecodingNoAlloc", [](uint32_t n, const int8_t *llrs, armral_ldpc_graph_t bg, uint32_t z, - uint32_t len_filler_bits, uint8_t *data_out, uint32_t max_its, - uint32_t options) { + uint32_t len_filler_bits, uint8_t *data_out, uint32_t its_max, + uint32_t *its_out, uint32_t options) { auto buffer_size = - armral_ldpc_decode_block_noalloc_buffer_size(bg, z, max_its); + armral_ldpc_decode_block_noalloc_buffer_size(bg, z, its_max); std::vector buffer(buffer_size); return armral_ldpc_decode_block_noalloc(n, llrs, bg, z, len_filler_bits, - data_out, max_its, options, - buffer.data()); + data_out, its_max, its_out, + options, buffer.data()); }); exit(passed ? EXIT_SUCCESS : EXIT_FAILURE);