From 1246d949ecc31234984b371570b2c00da21d4bd0 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 25 Apr 2025 12:07:37 +0000 Subject: [PATCH] feat(LDPC Rate Matching): Fix Bit Selection starting position In the rate matching function, the starting position of bit selection `k0` is calculated in the way instructed by 3GPP TS 38.212 and then used to copy the selected part of the encoder output. But, this `k0` is the starting position of bit selection in the encoder output **including the filler bits**. While bits are selected from a buffer `in_bits` **where filler bits were previously removed**. The result is that if `k0` falls within or after the filler bits then bits selection starts at the wrong position which introduces an offset in the bit selection output with regard to the expected output. This commit fixes this behavior in the library at `src/UpperPHY/LDPC/arm_ldpc_rate_matching.cpp` but also in the reference implementation at `test/UpperPHY/LDPC/RateMatching/main.cpp`. The fix is to test where k0 falls relatively to the filler bits and reduce it accordingly before proceeding with bit selection. --- CHANGELOG.md | 7 +++++++ src/UpperPHY/LDPC/arm_ldpc_rate_matching.cpp | 10 ++++++++++ test/UpperPHY/LDPC/RateMatching/main.cpp | 10 ++++++++++ 3 files changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ddc959..710afc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,13 @@ documented in this file. ### Fixed +- Fixed starting position of bit selection in LDPC rate matching. + Removal of filler bits in the `in_bits` intermediate buffer + was not taken into account when computing the starting position + of bit selection, which was sometime creating an offset after bit selection. + The issue was affecting the library implementation and + reference implementation. + ### Security diff --git a/src/UpperPHY/LDPC/arm_ldpc_rate_matching.cpp b/src/UpperPHY/LDPC/arm_ldpc_rate_matching.cpp index 8efac64..58857d5 100644 --- a/src/UpperPHY/LDPC/arm_ldpc_rate_matching.cpp +++ b/src/UpperPHY/LDPC/arm_ldpc_rate_matching.cpp @@ -59,6 +59,16 @@ void bit_selection(uint32_t z, uint32_t n, uint32_t e, uint32_t len_filler_bits, } in_bits = scratch_buf1; + + // k0 is an index within the encoder output with filler bits + // but in_bits is now without filler bits + // so there is an offset to take into account depending on + // whether k0 falls before, within or after the filler bits + if (k0 > len_s_f_bits) { + k0 = k0 - len_filler_bits; + } else if (k0 > len_s_bits && k0 <= len_s_f_bits) { + k0 = len_s_bits; + } } // k0 depends on the redundancy version id. diff --git a/test/UpperPHY/LDPC/RateMatching/main.cpp b/test/UpperPHY/LDPC/RateMatching/main.cpp index 9b93620..e68c7d9 100644 --- a/test/UpperPHY/LDPC/RateMatching/main.cpp +++ b/test/UpperPHY/LDPC/RateMatching/main.cpp @@ -65,6 +65,16 @@ void ref_bit_selection(uint32_t z, uint32_t n, uint32_t e, } in_bits = scratch_ptr1; + + // k0 is an index within the encoder output with filler bits + // but in_bits is now without filler bits + // so there is an offset to take into account depending on + // whether k0 falls before, within or after the filler bits + if (k0 > len_s_f_bits) { + k0 = k0 - len_filler_bits; + } else if (k0 > len_s_bits && k0 <= len_s_f_bits) { + k0 = len_s_bits; + } } // k0 depends on the redundancy version id. -- GitLab