From f57f6a8d4e44e0aceece71a15409df6f725aef43 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 1 Jul 2025 17:44:11 +0200 Subject: [PATCH 1/3] factorize code that initialize all 0xff simd vectors --- .../LTE_UE_TRANSPORT/dlsch_llr_computation.c | 31 +++++++++------ .../dlsch_llr_computation_avx2.c | 38 ++++++------------- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 20 +++------- openair1/PHY/TOOLS/tools_defs.h | 24 ++++++++++++ 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c index fd1b2a3e9a..bcab4cd8dd 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c @@ -38,12 +38,9 @@ #include "transport_proto_ue.h" #include "PHY/sse_intrin.h" -//#define DEBUG_LLR_SIC - -const int16_t zeros[8] __attribute__((aligned(16))) = {0, 0, 0, 0, 0, 0, 0, 0}; -const int16_t ones[8] __attribute__((aligned(16))) = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +// #define DEBUG_LLR_SIC //============================================================================================== -// Auxiliary Makros +// Auxiliary Makros // calculates psi_a = psi_r*a_r + psi_i*a_i #define prodsum_psi_a_epi16(psi_r, a_r, psi_i, a_i, psi_a) \ @@ -54,18 +51,18 @@ const int16_t ones[8] __attribute__((aligned(16))) = {0xffff, 0xffff, 0xffff, 0x simde__m128i psi_a = simde_mm_adds_epi16(tmp_result, tmp_result2); // calculate interference magnitude -#define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ - tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); \ - tmp_result2 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); \ - tmp_result = simde_mm_and_si128(tmp_result, c1); \ - tmp_result2 = simde_mm_and_si128(tmp_result2, c2); \ +#define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ + tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); \ + tmp_result2 = simde_mm_xor_si128(tmp_result, ones); \ + tmp_result = simde_mm_and_si128(tmp_result, c1); \ + tmp_result2 = simde_mm_and_si128(tmp_result2, c2); \ simde__m128i int_mag = simde_mm_or_si128(tmp_result, tmp_result2); // calculate interference magnitude // tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 #define interference_abs_64qam_epi16(psi, int_ch_mag, int_two_ch_mag, int_three_ch_mag, a, c1, c3, c5, c7) \ tmp_result = simde_mm_cmplt_epi16(psi, int_two_ch_mag); \ - tmp_result3 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); \ + tmp_result3 = simde_mm_xor_si128(tmp_result, ones); \ tmp_result2 = simde_mm_cmplt_epi16(psi, int_ch_mag); \ tmp_result = simde_mm_xor_si128(tmp_result, tmp_result2); \ tmp_result4 = simde_mm_cmpgt_epi16(psi, int_three_ch_mag); \ @@ -1123,6 +1120,8 @@ void qpsk_qam16(int16_t *stream0_in, oai_mm_separate_real_imag_parts(&ch_mag_int, NULL, xmm2, xmm3); simde__m128i tmp_result, tmp_result2; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); // calculate optimal interference amplitudes interference_abs_epi16(psi_r_p1_p1 , ch_mag_int, a_r_p1_p1 , ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_i_p1_p1 , ch_mag_int, a_i_p1_p1 , ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); @@ -1351,6 +1350,8 @@ void qpsk_qam64(short *stream0_in, two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 three_ch_mag_int_with_sigma2 = simde_mm_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 simde__m128i tmp_result, tmp_result2, tmp_result3, tmp_result4; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); interference_abs_64qam_epi16(psi_r_p1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, SEVEN_OVER_SQRT_2_42); interference_abs_64qam_epi16(psi_i_p1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, @@ -2081,6 +2082,8 @@ void qam16_qam16(short *stream0_in, simde__m128i y0_p_3_3 = simde_mm_adds_epi16(y0r_three_over_sqrt10, y0i_three_over_sqrt10); simde__m128i y0_m_3_3 = simde_mm_subs_epi16(y0r_three_over_sqrt10, y0i_three_over_sqrt10); simde__m128i tmp_result, tmp_result2; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); // Compute optimal interfering symbol magnitude interference_abs_epi16(psi_r_p1_p1 ,ch_mag_int,a_r_p1_p1,ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_i_p1_p1 ,ch_mag_int,a_i_p1_p1,ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); @@ -2597,6 +2600,8 @@ void qam16_qam64(int16_t *stream0_in, ch_mag_int_with_sigma2 = simde_mm_srai_epi16(ch_mag_int, 1); // *2 two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 simde__m128i tmp_result, tmp_result2, tmp_result3, tmp_result4; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); three_ch_mag_int_with_sigma2 = simde_mm_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 interference_abs_64qam_epi16(psi_r_p1_p1 ,ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p1,ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42,FIVE_OVER_SQRT_2_42, @@ -4927,6 +4932,8 @@ void qam64_qam16(short *stream0_in, simde__m128i y0_m_7_5 = simde_mm_subs_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); simde__m128i y0_m_7_7 = simde_mm_subs_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); simde__m128i tmp_result, tmp_result2; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); interference_abs_epi16(psi_r_p7_p7, ch_mag_int, a_r_p7_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_r_p7_p5, ch_mag_int, a_r_p7_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_r_p7_p3, ch_mag_int, a_r_p7_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); @@ -6425,6 +6432,8 @@ void qam64_qam64(short *stream0_in, two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 three_ch_mag_int_with_sigma2 = simde_mm_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 simde__m128i tmp_result, tmp_result2, tmp_result3, tmp_result4; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); interference_abs_64qam_epi16(psi_r_p7_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, SEVEN_OVER_SQRT_2_42); interference_abs_64qam_epi16(psi_r_p7_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c index 0877b2ba7e..a4f641896b 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c @@ -37,40 +37,21 @@ #if defined(__x86_64__) - static const int16_t ones256[16] __attribute__((aligned(32))) = {0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff}; - - - // Auxiliary Makros - + // Auxiliary Macros // calculate interference magnitude #define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ - tmp_result = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ - tmp_result2 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); \ - tmp_result = simde_mm256_and_si256(tmp_result, c1); \ - tmp_result2 = simde_mm256_and_si256(tmp_result2, c2); \ - const simde__m256i int_mag = simde_mm256_or_si256(tmp_result, tmp_result2); + tmp_result = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ + tmp_result2 = simde_mm256_xor_si256(tmp_result, ff256); \ + tmp_result = simde_mm256_and_si256(tmp_result, c1); \ + tmp_result2 = simde_mm256_and_si256(tmp_result2, c2); \ + const simde__m256i int_mag = simde_mm256_or_si256(tmp_result, tmp_result2); // calculate interference magnitude // tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 #define interference_abs_64qam_epi16(psi, int_ch_mag, int_two_ch_mag, int_three_ch_mag, a, c1, c3, c5, c7) \ tmp_result = simde_mm256_cmpgt_epi16(int_two_ch_mag, psi); \ - tmp_result3 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); \ + tmp_result3 = simde_mm256_xor_si256(tmp_result, ff256); \ tmp_result2 = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ tmp_result = simde_mm256_xor_si256(tmp_result, tmp_result2); \ tmp_result4 = simde_mm256_cmpgt_epi16(psi, int_three_ch_mag); \ @@ -195,7 +176,8 @@ void qam64_qam16_avx2(short *stream0_in, int i,j; uint32_t len256 = (length)>>3; - + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m256i ff256 = allones256(); for (i=0; i>3; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m256i ff256 = allones256(); for (i=0; i6 @@ -409,7 +404,7 @@ static inline simde__m128i interference_abs_64qam_epi16(simde__m128i psi, simde__m128i c7) { simde__m128i tmp_result = simde_mm_cmpgt_epi16(int_two_ch_mag, psi); - simde__m128i tmp_result3 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); + simde__m128i tmp_result3 = simde_mm_xor_si128(tmp_result, allones128()); simde__m128i tmp_result2 = simde_mm_cmpgt_epi16(int_ch_mag, psi); tmp_result = simde_mm_xor_si128(tmp_result, tmp_result2); simde__m128i tmp_result4 = simde_mm_cmpgt_epi16(psi, int_three_ch_mag); @@ -437,7 +432,7 @@ static inline simde__m128i prodsum_psi_a_epi16(simde__m128i psi_r, simde__m128i static inline simde__m128i interference_abs_epi16(simde__m128i psi, simde__m128i int_ch_mag, simde__m128i c1, simde__m128i c2) { simde__m128i tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); - simde__m128i tmp_result2 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); + simde__m128i tmp_result2 = simde_mm_xor_si128(tmp_result,allones128()); tmp_result = simde_mm_and_si128(tmp_result, c1); tmp_result2 = simde_mm_and_si128(tmp_result2, c2); return simde_mm_or_si128(tmp_result, tmp_result2); @@ -492,9 +487,6 @@ static inline simde__m128i max_epi16(simde__m128i m0, simde__m128i m1, simde__m1 #else -static const int16_t ones256[16] __attribute__((aligned(32))) = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; - // calculate interference magnitude // tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 @@ -508,7 +500,7 @@ static inline simde__m256i interference_abs_64qam_epi16_256(simde__m256i psi, simde__m256i c7) { simde__m256i tmp_result = simde_mm256_cmpgt_epi16(int_two_ch_mag, psi); - simde__m256i tmp_result3 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); + simde__m256i tmp_result3 = simde_mm256_xor_si256(tmp_result, allones256()); simde__m256i tmp_result2 = simde_mm256_cmpgt_epi16(int_ch_mag, psi); tmp_result = simde_mm256_xor_si256(tmp_result, tmp_result2); simde__m256i tmp_result4 = simde_mm256_cmpgt_epi16(psi, int_three_ch_mag); @@ -536,7 +528,7 @@ static inline simde__m256i prodsum_psi_a_epi16_256(simde__m256i psi_r, simde__m2 static inline simde__m256i interference_abs_epi16_256(simde__m256i psi, simde__m256i int_ch_mag, simde__m256i c1, simde__m256i c2) { simde__m256i tmp_result = simde_mm256_cmpgt_epi16(int_ch_mag, psi); - simde__m256i tmp_result2 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); + simde__m256i tmp_result2 = simde_mm256_xor_si256(tmp_result, allones256()); tmp_result = simde_mm256_and_si256(tmp_result, c1); tmp_result2 = simde_mm256_and_si256(tmp_result2, c2); return simde_mm256_or_si256(tmp_result, tmp_result2); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 64e5061476..7d60e19bae 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -532,6 +532,20 @@ static inline void multadd_cpx_vector(const c16_t *x1, const c16_t *x2, c16_t *y } } +static const int16_t ones_epi16[16] __attribute__((aligned(32))) = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static inline simde__m256i protected_abs256(const simde__m256i in) +{ + const simde__m256i no32768 = + simde_mm256_adds_epi16(simde_mm256_subs_epi16(in, *(simde__m256i *)ones_epi16), *(simde__m256i *)ones_epi16); + return simde_mm256_abs_epi16(no32768); +} + +static inline simde__m128i protected_abs128(const simde__m128i in) +{ + const simde__m128i no32768 = simde_mm_adds_epi16(simde_mm_subs_epi16(in, *(simde__m128i *)ones_epi16), *(simde__m128i *)ones_epi16); + return simde_mm_abs_epi16(no32768); +} + // lte_dfts.c void init_fft(uint16_t size, uint8_t logsize, @@ -919,6 +933,16 @@ c32_t dot_product(const c16_t *x, void oai_mm_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1); void oai_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1); +// generates vpcmpeqd ymm0, ymm0, ymm0 +static inline simde__m256i allones256(void) +{ + return simde_mm256_set1_epi64x(-1); +} +static inline simde__m128i allones128(void) +{ + return simde_mm_set1_epi32(-1); +} + void InitSinLUT(void); // fast calculation of e^{i*2*pi*phase} From 3264eca6dbbca3475b49265d692239390fcc1259 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 1 Jul 2025 17:46:37 +0200 Subject: [PATCH 2/3] enhance llr unitary tests --- openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp | 95 +++++++++----------- openair1/PHY/TOOLS/phy_test_tools.hpp | 2 +- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp b/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp index bd0c95d2ae..f07aa8e552 100644 --- a/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp +++ b/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp @@ -48,12 +48,11 @@ void exit_function(const char *file, const char *function, const int line, const #include "openair1/PHY/TOOLS/phy_test_tools.hpp" #include -int16_t saturating_sub(int16_t a, int16_t b) +int16_t saturating_sub(int a, int b) { - int32_t result = (int32_t)a - (int32_t)b; - - if (result < INT16_MIN) { - return INT16_MIN; + int result = a - abs(b); + if (result < -INT16_MAX) { + return -INT16_MAX; } else if (result > INT16_MAX) { return INT16_MAX; } else { @@ -71,8 +70,8 @@ void nr_16qam_llr_ref(c16_t *rxdataF_comp, int32_t *ch_mag, int16_t *llr, uint32 int16_t mag_imag = ch_mag_i16[2 * i + 1]; llr[4 * i] = real; llr[4 * i + 1] = imag; - llr[4 * i + 2] = saturating_sub(mag_real, std::abs(real)); - llr[4 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); + llr[4 * i + 2] = saturating_sub(mag_real, real); + llr[4 * i + 3] = saturating_sub(mag_imag, imag); } } @@ -91,12 +90,12 @@ void nr_64qam_llr_ref(c16_t *rxdataF_comp, int16_t mag_imag = ch_mag_i16[2 * i + 1]; llr[6 * i] = real; llr[6 * i + 1] = imag; - llr[6 * i + 2] = saturating_sub(mag_real, std::abs(real)); - llr[6 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); + llr[6 * i + 2] = saturating_sub(mag_real, real); + llr[6 * i + 3] = saturating_sub(mag_imag, imag); int16_t mag_realb = ch_magb_i16[2 * i]; int16_t mag_imagb = ch_magb_i16[2 * i + 1]; - llr[6 * i + 4] = saturating_sub(mag_realb, std::abs(llr[6 * i + 2])); - llr[6 * i + 5] = saturating_sub(mag_imagb, std::abs(llr[6 * i + 3])); + llr[6 * i + 4] = saturating_sub(mag_realb, llr[6 * i + 2]); + llr[6 * i + 5] = saturating_sub(mag_imagb, llr[6 * i + 3]); } } @@ -117,16 +116,16 @@ void nr_256qam_llr_ref(c16_t *rxdataF_comp, int16_t mag_imag = ch_mag_i16[2 * i + 1]; llr[8 * i] = real; llr[8 * i + 1] = imag; - llr[8 * i + 2] = saturating_sub(mag_real, std::abs(real)); - llr[8 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); + llr[8 * i + 2] = saturating_sub(mag_real, real); + llr[8 * i + 3] = saturating_sub(mag_imag, imag); int16_t magb_real = ch_magb_i16[2 * i]; int16_t magb_imag = ch_magb_i16[2 * i + 1]; - llr[8 * i + 4] = saturating_sub(magb_real, std::abs(llr[8 * i + 2])); - llr[8 * i + 5] = saturating_sub(magb_imag, std::abs(llr[8 * i + 3])); + llr[8 * i + 4] = saturating_sub(magb_real, llr[8 * i + 2]); + llr[8 * i + 5] = saturating_sub(magb_imag, llr[8 * i + 3]); int16_t magc_real = ch_magc_i16[2 * i]; int16_t magc_imag = ch_magc_i16[2 * i + 1]; - llr[8 * i + 6] = saturating_sub(magc_real, std::abs(llr[8 * i + 4])); - llr[8 * i + 7] = saturating_sub(magc_imag, std::abs(llr[8 * i + 5])); + llr[8 * i + 6] = saturating_sub(magc_real, llr[8 * i + 4]); + llr[8 * i + 7] = saturating_sub(magc_imag, llr[8 * i + 5]); } } @@ -136,23 +135,21 @@ void test_function_16_qam(AlignedVector512 nb_res) uint32_t nb_re = nb_res[i]; auto rf_data = generate_random_c16(nb_re); auto magnitude_data = generate_random_uint16(nb_re * 2); - AlignedVector512 llr_ref; - llr_ref.resize(nb_re); + AlignedVector512 llr_ref; + llr_ref.resize(nb_re * 4); std::fill(llr_ref.begin(), llr_ref.end(), 0); nr_16qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)llr_ref.data(), nb_re); - AlignedVector512 llr; - llr.resize(nb_re); + AlignedVector512 llr; + llr.resize(nb_re * 4); std::fill(llr.begin(), llr.end(), 0); nr_16qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)llr.data(), nb_re); int num_errors = 0; - for (auto i = 0U; i < nb_re; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 16qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + for (auto i = 0U; i < llr_ref.size(); i++) { + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 16qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 16qam llr " << num_errors << " nb res " << nb_re; } @@ -165,8 +162,8 @@ void test_function_64_qam(AlignedVector512 nb_res) auto rf_data = generate_random_c16(nb_re); auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_b_data = generate_random_uint16(nb_re * 2); - AlignedVector512 llr_ref; - llr_ref.resize(nb_re * 3); + AlignedVector512 llr_ref; + llr_ref.resize(nb_re * 6); std::fill(llr_ref.begin(), llr_ref.end(), 0); nr_64qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -174,8 +171,8 @@ void test_function_64_qam(AlignedVector512 nb_res) (int16_t *)llr_ref.data(), nb_re); - AlignedVector512 llr; - llr.resize(nb_re * 3); + AlignedVector512 llr; + llr.resize(nb_re * 6); std::fill(llr.begin(), llr.end(), 0); nr_64qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -184,12 +181,10 @@ void test_function_64_qam(AlignedVector512 nb_res) nb_re); int num_errors = 0; - for (auto i = 0U; i < nb_re * 3; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 64qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + for (auto i = 0U; i < llr.size(); i++) { + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 64qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 64qam llr " << num_errors << " nb res " << nb_re; } @@ -203,8 +198,8 @@ void test_function_256_qam(AlignedVector512 nb_res) auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_b_data = generate_random_uint16(nb_re * 2); auto magnitude_c_data = generate_random_uint16(nb_re * 2); - AlignedVector512 llr_ref; - llr_ref.resize(nb_re * 4); + AlignedVector512 llr_ref; + llr_ref.resize(nb_re * 8); std::fill(llr_ref.begin(), llr_ref.end(), 0); nr_256qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -213,8 +208,8 @@ void test_function_256_qam(AlignedVector512 nb_res) (int16_t *)llr_ref.data(), nb_re); - AlignedVector512 llr; - llr.resize(nb_re * 4); + AlignedVector512 llr; + llr.resize(nb_re * 8); std::fill(llr.begin(), llr.end(), 0); nr_256qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -224,12 +219,10 @@ void test_function_256_qam(AlignedVector512 nb_res) nb_re); int num_errors = 0; - for (auto i = 0U; i < nb_re * 4; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + for (auto i = 0U; i < llr.size(); i++) { + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 256qam llr " << num_errors << " nb res " << nb_re; } @@ -401,11 +394,9 @@ TEST(test_llr, check_2_res_256_qam) int num_errors = 0; for (auto i = 0U; i < 2 * 8; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 256qam llr " << num_errors << " nb res " << 2; } diff --git a/openair1/PHY/TOOLS/phy_test_tools.hpp b/openair1/PHY/TOOLS/phy_test_tools.hpp index dcaa192dd4..bf9760cde6 100644 --- a/openair1/PHY/TOOLS/phy_test_tools.hpp +++ b/openair1/PHY/TOOLS/phy_test_tools.hpp @@ -81,7 +81,7 @@ AlignedVector512 generate_random_c16(size_t num) { std::random_device rd; std::mt19937 rng(rd()); - std::uniform_int_distribution dist(INT16_MIN, INT16_MAX); + std::uniform_int_distribution dist(-INT16_MAX, INT16_MAX); AlignedVector512 vec; vec.resize(num); auto gen = [&]() { return (c16_t){dist(rng), dist(rng)}; }; From 8dd2119d4ea0d18c3dfeb32c34191748e0bfa599 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 1 Jul 2025 18:31:02 +0200 Subject: [PATCH 3/3] bad type multi casts with wrong meaning like cast to ** a array of 2D (wrong in C) --- .../PHY/NR_ESTIMATION/nr_freq_equalization.c | 14 +- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 6 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 69 +------ .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 125 ++++++------- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 6 +- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 60 +++--- .../PHY/nr_phy_common/inc/nr_phy_common.h | 6 +- .../PHY/nr_phy_common/src/nr_phy_common.c | 172 +++++++----------- 8 files changed, 181 insertions(+), 277 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c index c593c04cc5..8f12f100c2 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c +++ b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c @@ -34,13 +34,13 @@ void nr_init_fde() nr_inv_ch[i] = simde_mm_set1_epi16(4096/i); } -void nr_freq_equalization (NR_DL_FRAME_PARMS *frame_parms, - int32_t *rxdataF_comp, - int32_t *ul_ch_mag, - int32_t *ul_ch_magb, - uint8_t symbol, - uint16_t Msc_RS, - uint8_t Qm) +void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxdataF_comp, + c16_t *ul_ch_mag, + c16_t *ul_ch_magb, + uint8_t symbol, + uint16_t Msc_RS, + uint8_t Qm) { simde__m128i *rxdataF_comp128 = (simde__m128i *)rxdataF_comp; simde__m128i *ul_ch_mag128 = (simde__m128i *)ul_ch_mag; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 483e1ea090..768b75ae62 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -90,9 +90,9 @@ int nr_srs_channel_estimation( int8_t *snr); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, - int *rxdataF_comp, - int *ul_ch_mag, - int *ul_ch_mag_b, + c16_t *rxdataF_comp, + c16_t *ul_ch_mag, + c16_t *ul_ch_mag_b, unsigned char symbol, unsigned short Msc_RS, unsigned char Qm); diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index db49237a9e..1aabf118ef 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -159,63 +159,6 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, c16_t *rho01, uint32_t length); -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. - @param rxdataF_comp Compensated channel output - @param ulsch_llr llr output - @param nb_re number of REs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - - -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16 QAM received waveforms. - @param rxdataF_comp Compensated channel output - @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 16 - @param ulsch_llr llr output - @param nb_re number of RBs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, - int32_t **ul_ch_mag, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 64 QAM received waveforms. - @param rxdataF_comp Compensated channel output - @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 - @param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64 - @param ulsch_llr llr output - @param nb_re number of REs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, - int32_t **ul_ch_mag, - int32_t **ul_ch_magb, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 256 QAM received waveforms. - @param rxdataF_comp Compensated channel output - @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 256 - @param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 256 - @param ul_ch_magc uplink channel magnitude multiplied by the 3rd amplitude threshold in QAM 256 - @param ulsch_llr llr output - @param nb_re number of REs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, - int32_t **ul_ch_mag, - int32_t **ul_ch_magb, - int32_t **ul_ch_magc, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - /** \brief This function computes the log-likelihood ratios for 4, 16, and 64 QAM @param rxdataF_comp Compensated channel output @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 @@ -226,13 +169,13 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, @param mod_order modulation order */ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, - int32_t *ul_ch_mag, - int32_t *ul_ch_magb, - int32_t *ul_ch_magc, - int16_t *ulsch_llr, + c16_t *ul_ch_mag, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, + int16_t *ulsch_llr, uint32_t nb_re, - uint8_t symbol, - uint8_t mod_order); + uint8_t symbol, + uint8_t mod_order); void reset_active_stats(PHY_VARS_gNB *gNB, int frame); void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 1729c8c8c4..5b8b9c4291 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -225,22 +225,22 @@ static void nr_ulsch_channel_level(int size_est, } -static void nr_ulsch_channel_compensation(c16_t *rxFext, - c16_t *chFext, - c16_t *ul_ch_maga, - c16_t *ul_ch_magb, - c16_t *ul_ch_magc, +static void nr_ulsch_channel_compensation(uint32_t buffer_length, + int nb_rx_ant, + c16_t rxFext[][buffer_length], + c16_t chFext[][nb_rx_ant][buffer_length], + c16_t ul_ch_maga[][buffer_length], + c16_t ul_ch_magb[][buffer_length], + c16_t ul_ch_magc[][buffer_length], int32_t **rxComp, - c16_t *rho, - NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t* rel15_ul, + int nb_layers, + c16_t rho[][nb_layers][buffer_length], + nfapi_nr_pusch_pdu_t *rel15_ul, uint32_t symbol, - uint32_t buffer_length, uint32_t output_shift) { int mod_order = rel15_ul->qam_mod_order; int nrOfLayers = rel15_ul->nrOfLayers; - int nb_rx_ant = frame_parms->nb_antennas_rx; simde__m256i QAM_ampa_256 = simde_mm256_setzero_si256(); simde__m256i QAM_ampb_256 = simde_mm256_setzero_si256(); @@ -263,13 +263,13 @@ static void nr_ulsch_channel_compensation(c16_t *rxFext, } for (int aatx = 0; aatx < nrOfLayers; aatx++) { - simde__m256i *rxComp_256 = (simde__m256i*)&rxComp[aatx * nb_rx_ant][symbol * buffer_length]; - simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * buffer_length]; - simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * buffer_length]; - simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * buffer_length]; + simde__m256i *rxComp_256 = (simde__m256i *)&rxComp[aatx * nb_rx_ant][symbol * buffer_length]; + simde__m256i *rxF_ch_maga_256 = (simde__m256i *)ul_ch_maga[aatx]; + simde__m256i *rxF_ch_magb_256 = (simde__m256i *)ul_ch_magb[aatx]; + simde__m256i *rxF_ch_magc_256 = (simde__m256i *)ul_ch_magc[aatx]; for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - simde__m256i *rxF_256 = (simde__m256i*) &rxFext[aarx * buffer_length]; - simde__m256i *chF_256 = (simde__m256i*) &chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; + simde__m256i *rxF_256 = (simde__m256i *)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; for (int i = 0; i < buffer_length >> 3; i++) { @@ -292,11 +292,11 @@ static void nr_ulsch_channel_compensation(c16_t *rxFext, rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], simde_mm256_mulhrs_epi16(mag, QAM_ampc_256)); } } - if (rho != NULL) { + if (nb_layers > 1) { for (int atx = 0; atx < nrOfLayers; atx++) { - simde__m256i *rho_256 = (simde__m256i * )&rho[(aatx * nrOfLayers + atx) * buffer_length]; - simde__m256i *chF_256 = (simde__m256i *)&chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; - simde__m256i *chF2_256 = (simde__m256i *)&chFext[ (atx * nb_rx_ant + aarx) * buffer_length]; + simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; + simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; for (int i = 0; i < buffer_length >> 3; i++) { rho_256[i] = simde_mm256_adds_epi16(rho_256[i], oai_mm256_cpx_mult_conj(chF_256[i], chF2_256[i], output_shift)); } @@ -523,25 +523,20 @@ static void nr_ulsch_construct_HhH_elements(c16_t *conjch00_ch00, } // MMSE Rx function: nr_ulsch_mmse_2layers() -static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, - int **rxdataF_comp, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int nb_layer, - int nb_rx_ant, +static uint8_t nr_ulsch_mmse_2layers(int **rxdataF_comp, uint32_t buffer_length, - c16_t ul_ch_estimates_ext[nb_layer][nb_rx_ant][buffer_length], + int nb_rx_ant, + c16_t ul_ch_mag[][buffer_length], + c16_t ul_ch_magb[][buffer_length], + c16_t ul_ch_magc[][buffer_length], + c16_t ul_ch_estimates_ext[][nb_rx_ant][buffer_length], unsigned short nb_rb, - unsigned char n_rx, unsigned char mod_order, int shift, unsigned char symbol, int length, uint32_t noise_var) { - c16_t *ch00, *ch01, *ch10, *ch11; - c16_t *ch20, *ch30, *ch21, *ch31; uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); /* we need at least alignment to 16 bytes, let's put 32 to be sure @@ -570,7 +565,9 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, c16_t af_mf_11[12 * nb_rb] __attribute__((aligned(32))); uint32_t determ_fin[12*nb_rb] __attribute__((aligned(32))); - switch (n_rx) { + c16_t *ch00, *ch01, *ch10, *ch11; + c16_t *ch20, *ch30, *ch21, *ch31; + switch (nb_rx_ant) { case 2:// ch00 = ul_ch_estimates_ext[0][0]; ch01 = ul_ch_estimates_ext[1][0]; @@ -606,7 +603,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, * */ - if (n_rx>=2){ + if (nb_rx_ant >= 2) { // (1/2^log2_maxh)*conj_H_00xH_00: (1/(64*2))conjH_00*H_00*2^15 nr_ulsch_conjch0_mult_ch1(ch00, ch00, @@ -656,7 +653,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, nb_rb_0, shift); } - if (n_rx==4){ + if (nb_rx_ant == 4) { // (1/2^log2_maxh)*conj_H_20xH_20: (1/(64*2*16))conjH_20*H_20*2^15 nr_ulsch_conjch0_mult_ch1(ch20, ch20, @@ -732,7 +729,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, nb_rb_0, symbol); } - if (n_rx==2){ + if (nb_rx_ant == 2) { nr_ulsch_construct_HhH_elements(conjch00_ch00, conjch01_ch01, conjch11_ch11, @@ -805,7 +802,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, simde__m128i *after_mf_d_128 = (simde__m128i *)af_mf_11; simde__m128i *rxdataF_comp128_0 = (simde__m128i *)&rxdataF_comp[0][symbol * buffer_length]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[n_rx][symbol * buffer_length]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[nb_rx_ant][symbol * buffer_length]; if (mod_order > 2) { if (mod_order == 4) { @@ -821,12 +818,12 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, QAM_amp128b = simde_mm_set1_epi16(QAM256_n2); QAM_amp128c = simde_mm_set1_epi16(QAM256_n3); } - ul_ch_mag128_0 = (simde__m128i *) &ul_ch_mag[0]; + ul_ch_mag128_0 = (simde__m128i *)&ul_ch_mag[0]; ul_ch_mag128b_0 = (simde__m128i *)&ul_ch_magb[0]; ul_ch_mag128c_0 = (simde__m128i *)&ul_ch_magc[0]; - ul_ch_mag128_1 = (simde__m128i *) &((int *)ul_ch_mag)[1 * buffer_length]; - ul_ch_mag128b_1 = (simde__m128i *)&((int *)ul_ch_magb)[1 * buffer_length]; - ul_ch_mag128c_1 = (simde__m128i *)&((int *)ul_ch_magc)[1 * buffer_length]; + ul_ch_mag128_1 = (simde__m128i *)&ul_ch_mag[1]; + ul_ch_mag128b_1 = (simde__m128i *)&ul_ch_magb[1]; + ul_ch_mag128c_1 = (simde__m128i *)&ul_ch_magc[1]; } for (int rb = 0; rb < 3 * nb_rb_0; rb++) { @@ -973,28 +970,29 @@ static void inner_rx(PHY_VARS_gNB *gNB, for (int i = 0; i < nb_layer; i++) memset(&pusch_vars->rxdataF_comp[i*nb_rx_ant][symbol * buffer_length], 0, sizeof(int32_t) * buffer_length); - nr_ulsch_channel_compensation((c16_t*)rxFext, - (c16_t*)chFext, - (c16_t*)rxF_ch_maga, - (c16_t*)rxF_ch_magb, - (c16_t*)rxF_ch_magc, + nr_ulsch_channel_compensation(buffer_length, + nb_rx_ant, + rxFext, + chFext, + rxF_ch_maga, + rxF_ch_magb, + rxF_ch_magc, pusch_vars->rxdataF_comp, - (nb_layer == 1) ? NULL : (c16_t*)rho, - frame_parms, + nb_layer, + rho, rel15_ul, symbol, - buffer_length, output_shift); if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { if (rel15_ul->qam_mod_order > 2) nr_freq_equalization(frame_parms, - &pusch_vars->rxdataF_comp[0][symbol * buffer_length], - (int *)rxF_ch_maga, - (int *)rxF_ch_magb, - symbol, - pusch_vars->ul_valid_re_per_slot[symbol], - rel15_ul->qam_mod_order); + (c16_t *)&pusch_vars->rxdataF_comp[0][symbol * buffer_length], + rxF_ch_maga[0], + rxF_ch_magb[0], + symbol, + pusch_vars->ul_valid_re_per_slot[symbol], + rel15_ul->qam_mod_order); nr_idft(&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]); } if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { @@ -1024,17 +1022,14 @@ static void inner_rx(PHY_VARS_gNB *gNB, rel15_ul->qam_mod_order); } else { - nr_ulsch_mmse_2layers(frame_parms, - (int32_t **)pusch_vars->rxdataF_comp, - (int **)rxF_ch_maga, - (int **)rxF_ch_magb, - (int **)rxF_ch_magc, - nb_layer, - nb_rx_ant, + nr_ulsch_mmse_2layers((int32_t **)pusch_vars->rxdataF_comp, buffer_length, + nb_rx_ant, + rxF_ch_maga, + rxF_ch_magb, + rxF_ch_magc, chFext, rel15_ul->rb_size, - frame_parms->nb_antennas_rx, rel15_ul->qam_mod_order, pusch_vars->log2_maxh, symbol, @@ -1045,9 +1040,9 @@ static void inner_rx(PHY_VARS_gNB *gNB, if (nb_layer != 2 || rel15_ul->qam_mod_order > 6) for (int aatx = 0; aatx < nb_layer; aatx++) nr_ulsch_compute_llr((int32_t *)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * buffer_length], - (int32_t *)rxF_ch_maga[aatx], - (int32_t *)rxF_ch_magb[aatx], - (int32_t *)rxF_ch_magc[aatx], + rxF_ch_maga[aatx], + rxF_ch_magb[aatx], + rxF_ch_magc[aatx], llr[aatx], pusch_vars->ul_valid_re_per_slot[symbol], symbol, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index a118cf629e..3f4660744d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -39,9 +39,9 @@ #endif void nr_ulsch_compute_llr(int32_t *rxdataF_comp, - int32_t *ul_ch_mag, - int32_t *ul_ch_magb, - int32_t *ul_ch_magc, + c16_t *ul_ch_mag, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 37c8382ec5..9289c67919 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -82,9 +82,9 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, unsigned char n_rx, unsigned char n_tx, // number of layer int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], unsigned short nb_rb, unsigned char mod_order, @@ -109,9 +109,9 @@ static void nr_dlsch_llr(uint32_t rx_size_symbol, uint sz, int16_t layer_llr[][sz], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[rx_size_symbol], - int32_t dl_ch_magb[rx_size_symbol], - int32_t dl_ch_magr[rx_size_symbol], + c16_t dl_ch_mag[rx_size_symbol], + c16_t dl_ch_magb[rx_size_symbol], + c16_t dl_ch_magr[rx_size_symbol], NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq, unsigned char symbol, @@ -178,9 +178,9 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, int nbRx, c16_t rxdataF_ext[][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], - int32_t dl_ch_mag[][nbRx][rx_size_symbol], - int32_t dl_ch_magb[][nbRx][rx_size_symbol], - int32_t dl_ch_magr[][nbRx][rx_size_symbol], + c16_t dl_ch_mag[][nbRx][rx_size_symbol], + c16_t dl_ch_magb[][nbRx][rx_size_symbol], + c16_t dl_ch_magr[][nbRx][rx_size_symbol], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, NR_DL_FRAME_PARMS *frame_parms, @@ -221,9 +221,9 @@ static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, short n_rx, int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], unsigned char symbol, int length); @@ -331,13 +331,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol]; memset(dl_ch_estimates_ext, 0, sizeof(dl_ch_estimates_ext)); - __attribute__((aligned(32))) int32_t dl_ch_mag[nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_mag[nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol]; memset(dl_ch_mag, 0, sizeof(dl_ch_mag)); - __attribute__((aligned(32))) int32_t dl_ch_magb[nl][nbRx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_magb[nl][nbRx][rx_size_symbol]; memset(dl_ch_magb, 0, sizeof(dl_ch_magb)); - __attribute__((aligned(32))) int32_t dl_ch_magr[nl][nbRx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_magr[nl][nbRx][rx_size_symbol]; memset(dl_ch_magr, 0, sizeof(dl_ch_magr)); NR_UE_COMMON *common_vars = &ue->common_vars; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; @@ -866,9 +866,9 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, int nbRx, c16_t rxdataF_ext[][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], - int32_t dl_ch_mag[][nbRx][rx_size_symbol], - int32_t dl_ch_magb[][nbRx][rx_size_symbol], - int32_t dl_ch_magr[][nbRx][rx_size_symbol], + c16_t dl_ch_mag[][nbRx][rx_size_symbol], + c16_t dl_ch_magb[][nbRx][rx_size_symbol], + c16_t dl_ch_magr[][nbRx][rx_size_symbol], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, NR_DL_FRAME_PARMS *frame_parms, @@ -882,7 +882,7 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, PHY_NR_MEASUREMENTS *measurements) { simde__m128i *dl_ch128, *dl_ch128_2, *dl_ch_mag128, *dl_ch_mag128b, *dl_ch_mag128r, *rxdataF128, *rxdataF_comp128, *rho128; - simde__m128i mmtmpD0, mmtmpD1, QAM_amp128 = {0}, QAM_amp128b = {0}, QAM_amp128r = {0}; + simde__m128i QAM_amp128 = {0}, QAM_amp128b = {0}, QAM_amp128r = {0}; uint32_t nb_rb_0 = length / 12 + ((length % 12) ? 1 : 0); @@ -913,10 +913,10 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, if (mod_order > 2) { // get channel amplitude if not QPSK - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0], dl_ch128[0]); + simde__m128i mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0], dl_ch128[0]); mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_madd_epi16(dl_ch128[1], dl_ch128[1]); + simde__m128i mmtmpD1 = simde_mm_madd_epi16(dl_ch128[1], dl_ch128[1]); mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); mmtmpD0 = simde_mm_packs_epi32(mmtmpD0, mmtmpD1); //|H[0]|^2 |H[1]|^2 |H[2]|^2 |H[3]|^2 |H[4]|^2 |H[5]|^2 |H[6]|^2 |H[7]|^2 @@ -1224,9 +1224,9 @@ static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, short n_rx, int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], unsigned char symbol, int length) { @@ -1557,9 +1557,9 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, unsigned char n_rx, unsigned char nl, // number of layer int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], unsigned short nb_rb, unsigned char mod_order, @@ -1754,9 +1754,9 @@ static void nr_dlsch_llr(uint32_t rx_size_symbol, uint sz, int16_t layer_llr[][sz], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[rx_size_symbol], - int32_t dl_ch_magb[rx_size_symbol], - int32_t dl_ch_magr[rx_size_symbol], + c16_t dl_ch_mag[rx_size_symbol], + c16_t dl_ch_magb[rx_size_symbol], + c16_t dl_ch_magr[rx_size_symbol], NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq, unsigned char symbol, diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 97e9bee87e..d52b6d9c43 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -47,9 +47,9 @@ typedef struct { csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1); int get_cdm_group_size(int cdm_type); void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re); -void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re); -void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re); -void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int32_t *ch_mag3, int16_t *llr, uint32_t nb_re); +void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re); +void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t *llr, uint32_t nb_re); +void nr_256qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, c16_t *ch_mag3, int16_t *llr, uint32_t nb_re); void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal); void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index 5a950eba86..e86652bd49 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -43,17 +43,17 @@ void init_byte2bit16(void) } simde__m128i byte2m128i[256]; -void init_byte2m128i(void) { - - for (int s=0;s<256;s++) { - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*(s&1)),0); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>1)&1)),1); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>2)&1)),2); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>3)&1)),3); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>4)&1)),4); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>5)&1)),5); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>6)&1)),6); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>7)&1)),7); +void init_byte2m128i(void) +{ + for (int s = 0; s < 256; s++) { + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * (s & 1)), 0); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 1) & 1)), 1); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 2) & 1)), 2); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 3) & 1)), 3); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 4) & 1)), 4); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 5) & 1)), 5); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 6) & 1)), 6); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 7) & 1)), 7); } } @@ -71,17 +71,12 @@ void init_delay_table(uint16_t ofdm_symbol_size, } } -int16_t saturating_sub(int16_t a, int16_t b) +static inline c16_t saturating_sub(c16_t a, c16_t b) { - int32_t result = (int32_t)a - (int32_t)b; - - if (result < INT16_MIN) { - return INT16_MIN; - } else if (result > INT16_MAX) { - return INT16_MAX; - } else { - return (int16_t)result; - } + c32_t tmp = {a.r - abs(b.r), a.i - abs(b.i)}; + tmp = (c32_t){min(tmp.r, INT16_MAX), min(tmp.i, INT16_MAX)}; + c16_t tmp2 = (c16_t){max(tmp.r, -INT16_MAX), max(tmp.i, -INT16_MAX)}; + return tmp2; } //---------------------------------------------------------------------------------------------- @@ -101,23 +96,21 @@ void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re) // 16-QAM //---------------------------------------------------------------------------------------------- -void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re) +void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re) { simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp; - simde__m256i *ch_mag = (simde__m256i *)ch_mag_in; + simde__m256i *ch_mag256 = (simde__m256i *)ch_mag_in; int64_t *llr_64 = (int64_t *)llr; #ifndef USE_128BIT - simde__m256i xmm0, xmm1, xmm2; - for (int i = 0; i < (nb_re >> 3); i++) { // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_abs_epi16(*rxF_256); + simde__m256i xmm0 = protected_abs256(*rxF_256); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmm0 = simde_mm256_subs_epi16(*ch_mag, xmm0); + xmm0 = simde_mm256_subs_epi16(*ch_mag256, xmm0); - xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); - xmm2 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); + simde__m256i xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); + simde__m256i xmm2 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // xmm1 |1st 2ed 3rd 4th 9th 10th 13rd 14th| // xmm2 |5th 6th 7th 8th 11st 12ed 15th 16th| @@ -131,20 +124,20 @@ void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint3 *llr_64++ = simde_mm256_extract_epi64(xmm2, 2); *llr_64++ = simde_mm256_extract_epi64(xmm2, 3); rxF_256++; - ch_mag++; + ch_mag256++; } nb_re &= 0x7; #endif simde__m128i *rxF_128 = (simde__m128i *)rxF_256; - simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag; + simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag256; simde__m128i *llr_128 = (simde__m128i *)llr_64; // Each iteration does 4 RE (gives 16 16bit-llrs) for (int i = 0; i < (nb_re >> 2); i++) { // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - simde__m128i xmm0 = simde_mm_abs_epi16(*rxF_128); + simde__m128i xmm0 = protected_abs128(*rxF_128); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm0 = simde_mm_subs_epi16(*ch_mag_128, xmm0); @@ -157,18 +150,13 @@ void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint3 nb_re &= 0x3; - int16_t *rxDataF_i16 = (int16_t *)rxF_128; - int16_t *ch_mag_i16 = (int16_t *)ch_mag_128; - int16_t *llr_i16 = (int16_t *)llr_128; + c16_t *rxDataF = (c16_t *)rxF_128; + c16_t *ch_mag = (c16_t *)ch_mag_128; + c16_t *llr_tail = (c16_t *)llr_128; for (uint i = 0U; i < nb_re; i++) { - int16_t real = rxDataF_i16[2 * i]; - int16_t imag = rxDataF_i16[2 * i + 1]; - int16_t mag_real = ch_mag_i16[2 * i]; - int16_t mag_imag = ch_mag_i16[2 * i + 1]; - llr_i16[4 * i] = real; - llr_i16[4 * i + 1] = imag; - llr_i16[4 * i + 2] = saturating_sub(mag_real, abs(real)); - llr_i16[4 * i + 3] = saturating_sub(mag_imag, abs(imag)); + c16_t tmp = *rxDataF++; + *llr_tail++ = tmp; + *llr_tail++ = saturating_sub(*ch_mag++, tmp); } } @@ -176,7 +164,7 @@ void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint3 // 64-QAM //---------------------------------------------------------------------------------------------- -void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re) +void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t *llr, uint32_t nb_re) { simde__m256i *rxF = (simde__m256i *)rxdataF_comp; @@ -184,15 +172,14 @@ void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int1 simde__m256i *ch_magb = (simde__m256i *)ch_mag2; int32_t *llr_32 = (int32_t *)llr; - #ifndef USE_128BIT for (int i = 0; i < (nb_re >> 3); i++) { simde__m256i xmm0 = simde_mm256_loadu_si256(rxF); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - simde__m256i xmm1 = simde_mm256_abs_epi16(xmm0); + simde__m256i xmm1 = protected_abs256(xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm1 = simde_mm256_subs_epi16(*ch_maga, xmm1); - simde__m256i xmm2 = simde_mm256_abs_epi16(xmm1); + simde__m256i xmm2 = protected_abs256(xmm1); xmm2 = simde_mm256_subs_epi16(*ch_magb, xmm2); // xmm0 |1st 4th 7th 10th 13th 16th 19th 22ed| // xmm1 |2ed 5th 8th 11th 14th 17th 20th 23rd| @@ -244,9 +231,9 @@ void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int1 for (int i = 0; i < (nb_re >> 2); i++) { simde__m128i xmm0, xmm1, xmm2; xmm0 = *rxF_128; - xmm1 = simde_mm_abs_epi16(xmm0); + xmm1 = protected_abs128(xmm0); xmm1 = simde_mm_subs_epi16(*ch_mag_128, xmm1); - xmm2 = simde_mm_abs_epi16(xmm1); + xmm2 = protected_abs128(xmm1); xmm2 = simde_mm_subs_epi16(*ch_magb_128, xmm2); *llr_32++ = simde_mm_extract_epi32(xmm0, 0); @@ -268,27 +255,19 @@ void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int1 nb_re &= 0x3; - int16_t *rxDataF_i16 = (int16_t *)rxF_128; - int16_t *ch_mag_i16 = (int16_t *)ch_mag_128; - int16_t *ch_magb_i16 = (int16_t *)ch_magb_128; - int16_t *llr_i16 = (int16_t *)llr_32; + c16_t *rxDataF = (c16_t *)rxF_128; + c16_t *ch_mag_tail = (c16_t *)ch_mag_128; + c16_t *ch_magb_tail = (c16_t *)ch_magb_128; + c16_t *llr_tail = (c16_t *)llr_32; for (int i = 0; i < nb_re; i++) { - int16_t real = rxDataF_i16[2 * i]; - int16_t imag = rxDataF_i16[2 * i + 1]; - int16_t mag_real = ch_mag_i16[2 * i]; - int16_t mag_imag = ch_mag_i16[2 * i + 1]; - llr_i16[6 * i] = real; - llr_i16[6 * i + 1] = imag; - llr_i16[6 * i + 2] = saturating_sub(mag_real, abs(real)); - llr_i16[6 * i + 3] = saturating_sub(mag_imag, abs(imag)); - int16_t mag_realb = ch_magb_i16[2 * i]; - int16_t mag_imagb = ch_magb_i16[2 * i + 1]; - llr_i16[6 * i + 4] = saturating_sub(mag_realb, abs(llr_i16[6 * i + 2])); - llr_i16[6 * i + 5] = saturating_sub(mag_imagb, abs(llr_i16[6 * i + 3])); + *llr_tail++ = *rxDataF; + c16_t tmp = saturating_sub(*ch_mag_tail++, *rxDataF++); + *llr_tail++ = tmp; + *llr_tail++ = saturating_sub(*ch_magb_tail++, tmp); } } -void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int32_t *ch_mag3, int16_t *llr, uint32_t nb_re) +void nr_256qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, c16_t *ch_mag3, int16_t *llr, uint32_t nb_re) { simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp; simde__m256i *llr256 = (simde__m256i *)llr; @@ -297,26 +276,24 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde__m256i *ch_magb = (simde__m256i *)ch_mag2; simde__m256i *ch_magc = (simde__m256i *)ch_mag3; #ifndef USE_128BIT - simde__m256i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; - for (int i = 0; i < (nb_re >> 3); i++) { // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_abs_epi16(*rxF_256); + simde__m256i xmm0 = protected_abs256(*rxF_256); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm0 = simde_mm256_subs_epi16(*ch_maga, xmm0); // xmmtmpD2 contains 16 LLRs - xmm1 = simde_mm256_abs_epi16(xmm0); + simde__m256i xmm1 = protected_abs256(xmm0); xmm1 = simde_mm256_subs_epi16(*ch_magb, xmm1); // contains 16 LLRs - xmm2 = simde_mm256_abs_epi16(xmm1); + simde__m256i xmm2 = protected_abs256(xmm1); xmm2 = simde_mm256_subs_epi16(*ch_magc, xmm2); // contains 16 LLRs // rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6 // xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4 // xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2 // xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0 - xmm3 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 - xmm4 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 - xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 - xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 + simde__m256i xmm3 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 + simde__m256i xmm4 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 + simde__m256i xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 + simde__m256i xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 xmm0 = simde_mm256_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 A4 B4 C4 D4 xmm1 = simde_mm256_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 A5 B5 C5 D5 @@ -341,16 +318,15 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde__m128i *ch_maga_128 = (simde__m128i *)ch_maga; simde__m128i *ch_magb_128 = (simde__m128i *)ch_magb; simde__m128i *ch_magc_128 = (simde__m128i *)ch_magc; - for (int i = 0; i < (nb_re >> 2); i++) { simde__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_abs_epi16(*rxF_128); + xmm0 = protected_abs128(*rxF_128); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm0 = simde_mm_subs_epi16(*ch_maga_128, xmm0); - xmm1 = simde_mm_abs_epi16(xmm0); + xmm1 = protected_abs128(xmm0); xmm1 = simde_mm_subs_epi16(*ch_magb_128, xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_epi16(xmm1); + xmm2 = protected_abs128(xmm1); xmm2 = simde_mm_subs_epi16(*ch_magc_128, xmm2); // contains 8 LLRs // rxF[i] A0 A1 A2 A3 // xmm0 B0 B1 B2 B3 @@ -372,30 +348,20 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int ch_magc_128++; } - if (nb_re & 3) { - for (int i = 0; i < (nb_re & 0x3); i++) { - int16_t *rxDataF_i16 = (int16_t *)rxF_128; - int16_t *ch_mag_i16 = (int16_t *)ch_maga_128; - int16_t *ch_magb_i16 = (int16_t *)ch_magb_128; - int16_t *ch_magc_i16 = (int16_t *)ch_magc_128; - int16_t *llr_i16 = (int16_t *)llr_128; - int16_t real = rxDataF_i16[2 * i + 0]; - int16_t imag = rxDataF_i16[2 * i + 1]; - int16_t mag_real = ch_mag_i16[2 * i]; - int16_t mag_imag = ch_mag_i16[2 * i + 1]; - llr_i16[8 * i] = real; - llr_i16[8 * i + 1] = imag; - llr_i16[8 * i + 2] = saturating_sub(mag_real, abs(real)); - llr_i16[8 * i + 3] = saturating_sub(mag_imag, abs(imag)); - int16_t magb_real = ch_magb_i16[2 * i]; - int16_t magb_imag = ch_magb_i16[2 * i + 1]; - llr_i16[8 * i + 4] = saturating_sub(magb_real, abs(llr_i16[8 * i + 2])); - llr_i16[8 * i + 5] = saturating_sub(magb_imag, abs(llr_i16[8 * i + 3])); - int16_t magc_real = ch_magc_i16[2 * i]; - int16_t magc_imag = ch_magc_i16[2 * i + 1]; - llr_i16[8 * i + 6] = saturating_sub(magc_real, abs(llr_i16[8 * i + 4])); - llr_i16[8 * i + 7] = saturating_sub(magc_imag, abs(llr_i16[8 * i + 5])); - } + nb_re &= 0x3; + c16_t *rxDataF = (c16_t *)rxF_128; + c16_t *ch_mag_tail = (c16_t *)ch_maga_128; + c16_t *ch_magb_tail = (c16_t *)ch_magb_128; + c16_t *ch_magc_tail = (c16_t *)ch_magc_128; + c16_t *llr_tail = (c16_t *)llr_128; + for (int i = 0; i < nb_re; i++) { + c16_t tmp = *rxDataF++; + *llr_tail++ = tmp; + c16_t tmp1 = saturating_sub(*ch_mag_tail++, tmp); + *llr_tail++ = tmp1; + c16_t tmp2 = saturating_sub(*ch_magb_tail++, tmp1); + *llr_tail++ = tmp2; + *llr_tail++ = saturating_sub(*ch_magc_tail++, tmp2); } }