Commit 2d675bc3 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/NR_PHY_common_LLR' into integration_2024_w36

parents e2e57a05 db098651
...@@ -1066,7 +1066,6 @@ set(PHY_SRC_UE ...@@ -1066,7 +1066,6 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
......
...@@ -2256,7 +2256,6 @@ INPUT = \ ...@@ -2256,7 +2256,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/sss_nr.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/sss_nr.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/dci_nr.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/dci_nr.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_prach.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_prach.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c \
......
...@@ -31,357 +31,13 @@ ...@@ -31,357 +31,13 @@
*/ */
#include "PHY/defs_gNB.h" #include "PHY/defs_gNB.h"
#include "PHY/defs_nr_common.h"
#include "PHY/sse_intrin.h" #include "PHY/sse_intrin.h"
#include "PHY/impl_defs_top.h" #include "nr_phy_common.h"
#ifdef __aarch64__ #ifdef __aarch64__
#define USE_128BIT #define USE_128BIT
#endif #endif
int16_t saturating_sub(int16_t a, int16_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;
}
}
//----------------------------------------------------------------------------------------------
// QPSK
//----------------------------------------------------------------------------------------------
void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp,
int16_t *ulsch_llr,
uint32_t nb_re,
uint8_t symbol)
{
c16_t *rxF = (c16_t *)rxdataF_comp;
c16_t *llr32 = (c16_t *)ulsch_llr;
for (int i = 0; i < nb_re; i++) {
llr32[i].r = rxF[i].r >> 3;
llr32[i].i = rxF[i].i >> 3;
}
}
//----------------------------------------------------------------------------------------------
// 16-QAM
//----------------------------------------------------------------------------------------------
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)
{
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
simde__m256i *ch_mag = (simde__m256i *)ul_ch_mag;
int64_t *llr_64 = (int64_t *)ulsch_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);
// 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);
xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0);
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|
*llr_64++ = simde_mm256_extract_epi64(xmm1, 0);
*llr_64++ = simde_mm256_extract_epi64(xmm1, 1);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 0);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 1);
*llr_64++ = simde_mm256_extract_epi64(xmm1, 2);
*llr_64++ = simde_mm256_extract_epi64(xmm1, 3);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 2);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 3);
rxF_256++;
ch_mag++;
}
nb_re &= 0x7;
#endif
simde__m128i *rxF_128 = (simde__m128i *)rxF_256;
simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag;
simde__m128i *ulsch_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);
// 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);
ulsch_llr_128[0] = simde_mm_unpacklo_epi32(*rxF_128, xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs
ulsch_llr_128[1] = simde_mm_unpackhi_epi32(*rxF_128, xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs
ulsch_llr_128 += 2;
rxF_128++;
ch_mag_128++;
}
simde_mm_empty();
nb_re &= 0x3;
int16_t *rxDataF_i16 = (int16_t *)rxF_128;
int16_t *ul_ch_mag_i16 = (int16_t *)ch_mag_128;
int16_t *ulsch_llr_i16 = (int16_t *)ulsch_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 = ul_ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
ulsch_llr_i16[4 * i] = real;
ulsch_llr_i16[4 * i + 1] = imag;
ulsch_llr_i16[4 * i + 2] = saturating_sub(mag_real, abs(real));
ulsch_llr_i16[4 * i + 3] = saturating_sub(mag_imag, abs(imag));
}
}
//----------------------------------------------------------------------------------------------
// 64-QAM
//----------------------------------------------------------------------------------------------
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)
{
simde__m256i *rxF = (simde__m256i *)rxdataF_comp;
simde__m256i *ch_maga = (simde__m256i *)ul_ch_mag;
simde__m256i *ch_magb = (simde__m256i *)ul_ch_magb;
int32_t *llr_32 = (int32_t *)ulsch_llr;
#ifndef USE_128BIT
simde__m256i xmm0, xmm1, xmm2;
for (int i = 0; i < (nb_re >> 3); i++) {
xmm0 = *rxF;
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
xmm1 = simde_mm256_abs_epi16(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);
xmm2 = simde_mm256_abs_epi16(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|
// xmm2 |3rd 6th 9th 12th 15th 18th 21st 24th|
*llr_32++ = simde_mm256_extract_epi32(xmm0, 0);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 0);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 0);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 1);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 1);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 1);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 2);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 2);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 2);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 3);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 3);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 3);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 4);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 4);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 4);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 5);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 5);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 5);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 6);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 6);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 6);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 7);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 7);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 7);
rxF++;
ch_maga++;
ch_magb++;
}
nb_re &= 0x7;
#endif
simde__m128i *rxF_128 = (simde__m128i *)rxF;
simde__m128i *ch_mag_128 = (simde__m128i *)ch_maga;
simde__m128i *ch_magb_128 = (simde__m128i *)ch_magb;
simde__m64 *llr64 = (simde__m64 *)llr_32;
// Each iteration does 4 RE (gives 24 16bit-llrs)
for (int i = 0; i < (nb_re >> 2); i++) {
simde__m128i xmm0, xmm1, xmm2;
xmm0 = *rxF_128;
xmm1 = simde_mm_abs_epi16(xmm0);
xmm1 = simde_mm_subs_epi16(*ch_mag_128, xmm1);
xmm2 = simde_mm_abs_epi16(xmm1);
xmm2 = simde_mm_subs_epi16(*ch_magb_128, xmm2);
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 0), simde_mm_extract_epi32(xmm0, 0));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 1), simde_mm_extract_epi32(xmm2, 0));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 1), simde_mm_extract_epi32(xmm1, 1));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 2), simde_mm_extract_epi32(xmm0, 2));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 3), simde_mm_extract_epi32(xmm2, 2));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 3), simde_mm_extract_epi32(xmm1, 3));
rxF_128++;
ch_mag_128++;
ch_magb_128++;
}
nb_re &= 0x3;
int16_t *rxDataF_i16 = (int16_t *)rxF_128;
int16_t *ul_ch_mag_i16 = (int16_t *)ch_mag_128;
int16_t *ul_ch_magb_i16 = (int16_t *)ch_magb_128;
int16_t *llr_i16 = (int16_t *)llr64;
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 = ul_ch_mag_i16[2 * i];
int16_t mag_imag = ul_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 = ul_ch_magb_i16[2 * i];
int16_t mag_imagb = ul_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]));
}
simde_mm_empty();
}
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)
{
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
simde__m256i *llr256 = (simde__m256i *)ulsch_llr;
simde__m256i *ch_maga = (simde__m256i *)ul_ch_mag;
simde__m256i *ch_magb = (simde__m256i *)ul_ch_magb;
simde__m256i *ch_magc = (simde__m256i *)ul_ch_magc;
#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);
// 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);
xmm1 = simde_mm256_subs_epi16(*ch_magb, xmm1); // contains 16 LLRs
xmm2 = simde_mm256_abs_epi16(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
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
xmm2 = simde_mm256_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2 A6 B6 C6 D6
xmm3 = simde_mm256_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3 A7 B7 C7 D7
*llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1
*llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3
*llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5
*llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7
ch_magc++;
ch_magb++;
ch_maga++;
rxF_256++;
}
nb_re &= 0x7;
#endif
simde__m128i *rxF_128 = (simde__m128i *)rxF_256;
simde__m128i *llr_128 = (simde__m128i *)llr256;
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);
// 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 = simde_mm_subs_epi16(*ch_magb_128, xmm1); // contains 8 LLRs
xmm2 = simde_mm_abs_epi16(xmm1);
xmm2 = simde_mm_subs_epi16(*ch_magc_128, xmm2); // contains 8 LLRs
// rxF[i] A0 A1 A2 A3
// xmm0 B0 B1 B2 B3
// xmm1 C0 C1 C2 C3
// xmm2 D0 D1 D2 D3
xmm3 = simde_mm_unpacklo_epi32(*rxF_128, xmm0); // A0 B0 A1 B1
xmm4 = simde_mm_unpackhi_epi32(*rxF_128, xmm0); // A2 B2 A3 B3
xmm5 = simde_mm_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1
xmm6 = simde_mm_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3
*llr_128++ = simde_mm_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0
*llr_128++ = simde_mm_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1
*llr_128++ = simde_mm_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2
*llr_128++ = simde_mm_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3
rxF_128++;
ch_maga_128++;
ch_magb_128++;
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 *ul_ch_mag_i16 = (int16_t *)ch_maga_128;
int16_t *ul_ch_magb_i16 = (int16_t *)ch_magb_128;
int16_t *ul_ch_magc_i16 = (int16_t *)ch_magc_128;
int16_t *ulsch_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 = ul_ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
ulsch_llr_i16[8 * i] = real;
ulsch_llr_i16[8 * i + 1] = imag;
ulsch_llr_i16[8 * i + 2] = saturating_sub(mag_real, abs(real));
ulsch_llr_i16[8 * i + 3] = saturating_sub(mag_imag, abs(imag));
int16_t magb_real = ul_ch_magb_i16[2 * i];
int16_t magb_imag = ul_ch_magb_i16[2 * i + 1];
ulsch_llr_i16[8 * i + 4] = saturating_sub(magb_real, abs(ulsch_llr_i16[8 * i + 2]));
ulsch_llr_i16[8 * i + 5] = saturating_sub(magb_imag, abs(ulsch_llr_i16[8 * i + 3]));
int16_t magc_real = ul_ch_magc_i16[2 * i];
int16_t magc_imag = ul_ch_magc_i16[2 * i + 1];
ulsch_llr_i16[8 * i + 6] = saturating_sub(magc_real, abs(ulsch_llr_i16[8 * i + 4]));
ulsch_llr_i16[8 * i + 7] = saturating_sub(magc_imag, abs(ulsch_llr_i16[8 * i + 5]));
}
}
simde_mm_empty();
}
void nr_ulsch_compute_llr(int32_t *rxdataF_comp, void nr_ulsch_compute_llr(int32_t *rxdataF_comp,
int32_t *ul_ch_mag, int32_t *ul_ch_mag,
int32_t *ul_ch_magb, int32_t *ul_ch_magb,
...@@ -391,39 +47,21 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, ...@@ -391,39 +47,21 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp,
uint8_t symbol, uint8_t symbol,
uint8_t mod_order) uint8_t mod_order)
{ {
switch(mod_order){ switch(mod_order) {
case 2: case 2:
nr_ulsch_qpsk_llr(rxdataF_comp, nr_qpsk_llr(rxdataF_comp, ulsch_llr, nb_re);
ulsch_llr,
nb_re,
symbol);
break; break;
case 4: case 4:
nr_ulsch_16qam_llr(rxdataF_comp, nr_16qam_llr(rxdataF_comp, ul_ch_mag, ulsch_llr, nb_re);
ul_ch_mag,
ulsch_llr,
nb_re,
symbol);
break; break;
case 6: case 6:
nr_ulsch_64qam_llr(rxdataF_comp, nr_64qam_llr(rxdataF_comp, ul_ch_mag, ul_ch_magb, ulsch_llr, nb_re);
ul_ch_mag,
ul_ch_magb,
ulsch_llr,
nb_re,
symbol);
break; break;
case 8: case 8:
nr_ulsch_256qam_llr(rxdataF_comp, nr_256qam_llr(rxdataF_comp, ul_ch_mag, ul_ch_magb, ul_ch_magc, ulsch_llr, nb_re);
ul_ch_mag,
ul_ch_magb,
ul_ch_magc,
ulsch_llr,
nb_re,
symbol);
break; break;
default: default:
AssertFatal(1==0,"nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d\n",symbol, mod_order); AssertFatal(false, "nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d\n",symbol, mod_order);
break; break;
} }
} }
......
...@@ -25,20 +25,9 @@ ...@@ -25,20 +25,9 @@
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
extern "C" { extern "C" {
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); void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re);
void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re);
int32_t *ul_ch_mag, 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);
int32_t *ul_ch_magb,
int16_t *ulsch_llr,
uint32_t nb_re,
uint8_t symbol);
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);
struct configmodule_interface_s; struct configmodule_interface_s;
struct configmodule_interface_s *uniqCfg = NULL; struct configmodule_interface_s *uniqCfg = NULL;
...@@ -72,74 +61,72 @@ int16_t saturating_sub(int16_t a, int16_t b) ...@@ -72,74 +61,72 @@ int16_t saturating_sub(int16_t a, int16_t b)
} }
} }
void nr_ulsch_16qam_llr_ref(c16_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol) void nr_16qam_llr_ref(c16_t *rxdataF_comp, int32_t *ch_mag, int16_t *llr, uint32_t nb_re)
{ {
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag; int16_t *ch_mag_i16 = (int16_t *)ch_mag;
for (auto i = 0U; i < nb_re; i++) { for (auto i = 0U; i < nb_re; i++) {
int16_t real = rxdataF_comp[i].r; int16_t real = rxdataF_comp[i].r;
int16_t imag = rxdataF_comp[i].i; int16_t imag = rxdataF_comp[i].i;
int16_t mag_real = ul_ch_mag_i16[2 * i]; int16_t mag_real = ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1]; int16_t mag_imag = ch_mag_i16[2 * i + 1];
ulsch_llr[4 * i] = real; llr[4 * i] = real;
ulsch_llr[4 * i + 1] = imag; llr[4 * i + 1] = imag;
ulsch_llr[4 * i + 2] = saturating_sub(mag_real, std::abs(real)); llr[4 * i + 2] = saturating_sub(mag_real, std::abs(real));
ulsch_llr[4 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); llr[4 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
} }
} }
void nr_ulsch_64qam_llr_ref(c16_t *rxdataF_comp, void nr_64qam_llr_ref(c16_t *rxdataF_comp,
int32_t *ul_ch_mag, int32_t *ch_mag,
int32_t *ul_ch_magb, int32_t *ch_magb,
int16_t *ulsch_llr, int16_t *llr,
uint32_t nb_re, uint32_t nb_re)
uint8_t symbol)
{ {
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag; int16_t *ch_mag_i16 = (int16_t *)ch_mag;
int16_t *ul_ch_magb_i16 = (int16_t *)ul_ch_magb; int16_t *ch_magb_i16 = (int16_t *)ch_magb;
for (auto i = 0U; i < nb_re; i++) { for (auto i = 0U; i < nb_re; i++) {
int16_t real = rxdataF_comp[i].r; int16_t real = rxdataF_comp[i].r;
int16_t imag = rxdataF_comp[i].i; int16_t imag = rxdataF_comp[i].i;
int16_t mag_real = ul_ch_mag_i16[2 * i]; int16_t mag_real = ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1]; int16_t mag_imag = ch_mag_i16[2 * i + 1];
ulsch_llr[6 * i] = real; llr[6 * i] = real;
ulsch_llr[6 * i + 1] = imag; llr[6 * i + 1] = imag;
ulsch_llr[6 * i + 2] = saturating_sub(mag_real, std::abs(real)); llr[6 * i + 2] = saturating_sub(mag_real, std::abs(real));
ulsch_llr[6 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); llr[6 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
int16_t mag_realb = ul_ch_magb_i16[2 * i]; int16_t mag_realb = ch_magb_i16[2 * i];
int16_t mag_imagb = ul_ch_magb_i16[2 * i + 1]; int16_t mag_imagb = ch_magb_i16[2 * i + 1];
ulsch_llr[6 * i + 4] = saturating_sub(mag_realb, std::abs(ulsch_llr[6 * i + 2])); llr[6 * i + 4] = saturating_sub(mag_realb, std::abs(llr[6 * i + 2]));
ulsch_llr[6 * i + 5] = saturating_sub(mag_imagb, std::abs(ulsch_llr[6 * i + 3])); llr[6 * i + 5] = saturating_sub(mag_imagb, std::abs(llr[6 * i + 3]));
} }
} }
void nr_ulsch_256qam_llr_ref(c16_t *rxdataF_comp, void nr_256qam_llr_ref(c16_t *rxdataF_comp,
int32_t *ul_ch_mag, int32_t *ch_mag,
int32_t *ul_ch_magb, int32_t *ch_magb,
int32_t *ul_ch_magc, int32_t *ch_magc,
int16_t *ulsch_llr, int16_t *llr,
uint32_t nb_re, uint32_t nb_re)
uint8_t symbol)
{ {
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag; int16_t *ch_mag_i16 = (int16_t *)ch_mag;
int16_t *ul_ch_magb_i16 = (int16_t *)ul_ch_magb; int16_t *ch_magb_i16 = (int16_t *)ch_magb;
int16_t *ul_ch_magc_i16 = (int16_t *)ul_ch_magc; int16_t *ch_magc_i16 = (int16_t *)ch_magc;
for (auto i = 0U; i < nb_re; i++) { for (auto i = 0U; i < nb_re; i++) {
int16_t real = rxdataF_comp[i].r; int16_t real = rxdataF_comp[i].r;
int16_t imag = rxdataF_comp[i].i; int16_t imag = rxdataF_comp[i].i;
int16_t mag_real = ul_ch_mag_i16[2 * i]; int16_t mag_real = ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1]; int16_t mag_imag = ch_mag_i16[2 * i + 1];
ulsch_llr[8 * i] = real; llr[8 * i] = real;
ulsch_llr[8 * i + 1] = imag; llr[8 * i + 1] = imag;
ulsch_llr[8 * i + 2] = saturating_sub(mag_real, std::abs(real)); llr[8 * i + 2] = saturating_sub(mag_real, std::abs(real));
ulsch_llr[8 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); llr[8 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
int16_t magb_real = ul_ch_magb_i16[2 * i]; int16_t magb_real = ch_magb_i16[2 * i];
int16_t magb_imag = ul_ch_magb_i16[2 * i + 1]; int16_t magb_imag = ch_magb_i16[2 * i + 1];
ulsch_llr[8 * i + 4] = saturating_sub(magb_real, std::abs(ulsch_llr[8 * i + 2])); llr[8 * i + 4] = saturating_sub(magb_real, std::abs(llr[8 * i + 2]));
ulsch_llr[8 * i + 5] = saturating_sub(magb_imag, std::abs(ulsch_llr[8 * i + 3])); llr[8 * i + 5] = saturating_sub(magb_imag, std::abs(llr[8 * i + 3]));
int16_t magc_real = ul_ch_magc_i16[2 * i]; int16_t magc_real = ch_magc_i16[2 * i];
int16_t magc_imag = ul_ch_magc_i16[2 * i + 1]; int16_t magc_imag = ch_magc_i16[2 * i + 1];
ulsch_llr[8 * i + 6] = saturating_sub(magc_real, std::abs(ulsch_llr[8 * i + 4])); llr[8 * i + 6] = saturating_sub(magc_real, std::abs(llr[8 * i + 4]));
ulsch_llr[8 * i + 7] = saturating_sub(magc_imag, std::abs(ulsch_llr[8 * i + 5])); llr[8 * i + 7] = saturating_sub(magc_imag, std::abs(llr[8 * i + 5]));
} }
} }
...@@ -149,21 +136,21 @@ void test_function_16_qam(AlignedVector512<uint32_t> nb_res) ...@@ -149,21 +136,21 @@ void test_function_16_qam(AlignedVector512<uint32_t> nb_res)
uint32_t nb_re = nb_res[i]; uint32_t nb_re = nb_res[i];
auto rf_data = generate_random_c16(nb_re); auto rf_data = generate_random_c16(nb_re);
auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_data = generate_random_uint16(nb_re * 2);
AlignedVector512<uint64_t> ulsch_llr_ref; AlignedVector512<uint64_t> llr_ref;
ulsch_llr_ref.resize(nb_re); llr_ref.resize(nb_re);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0); std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_ulsch_16qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)ulsch_llr_ref.data(), nb_re, 0); nr_16qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)llr_ref.data(), nb_re);
AlignedVector512<uint64_t> ulsch_llr; AlignedVector512<uint64_t> llr;
ulsch_llr.resize(nb_re); llr.resize(nb_re);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0); std::fill(llr.begin(), llr.end(), 0);
nr_ulsch_16qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)ulsch_llr.data(), nb_re, 0); nr_16qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)llr.data(), nb_re);
int num_errors = 0; int num_errors = 0;
for (auto i = 0U; i < nb_re; i++) { for (auto i = 0U; i < nb_re; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i]) EXPECT_EQ(llr_ref[i], llr[i])
<< "Mismatch 16qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i; << "Mismatch 16qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[i]) { if (llr_ref[i] != llr[i]) {
num_errors++; num_errors++;
} }
} }
...@@ -178,31 +165,29 @@ void test_function_64_qam(AlignedVector512<uint32_t> nb_res) ...@@ -178,31 +165,29 @@ void test_function_64_qam(AlignedVector512<uint32_t> nb_res)
auto rf_data = generate_random_c16(nb_re); auto rf_data = generate_random_c16(nb_re);
auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_data = generate_random_uint16(nb_re * 2);
auto magnitude_b_data = generate_random_uint16(nb_re * 2); auto magnitude_b_data = generate_random_uint16(nb_re * 2);
AlignedVector512<uint32_t> ulsch_llr_ref; AlignedVector512<uint32_t> llr_ref;
ulsch_llr_ref.resize(nb_re * 3); llr_ref.resize(nb_re * 3);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0); std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_ulsch_64qam_llr_ref((c16_t *)rf_data.data(), nr_64qam_llr_ref((c16_t *)rf_data.data(),
(int32_t *)magnitude_data.data(), (int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(), (int32_t *)magnitude_b_data.data(),
(int16_t *)ulsch_llr_ref.data(), (int16_t *)llr_ref.data(),
nb_re, nb_re);
0);
AlignedVector512<uint32_t> llr;
AlignedVector512<uint32_t> ulsch_llr; llr.resize(nb_re * 3);
ulsch_llr.resize(nb_re * 3); std::fill(llr.begin(), llr.end(), 0);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0); nr_64qam_llr((int32_t *)rf_data.data(),
nr_ulsch_64qam_llr((int32_t *)rf_data.data(),
(int32_t *)magnitude_data.data(), (int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(), (int32_t *)magnitude_b_data.data(),
(int16_t *)ulsch_llr.data(), (int16_t *)llr.data(),
nb_re, nb_re);
0);
int num_errors = 0; int num_errors = 0;
for (auto i = 0U; i < nb_re * 3; i++) { for (auto i = 0U; i < nb_re * 3; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i]) EXPECT_EQ(llr_ref[i], llr[i])
<< "Mismatch 64qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i; << "Mismatch 64qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[i]) { if (llr_ref[i] != llr[i]) {
num_errors++; num_errors++;
} }
} }
...@@ -218,33 +203,31 @@ void test_function_256_qam(AlignedVector512<uint32_t> nb_res) ...@@ -218,33 +203,31 @@ void test_function_256_qam(AlignedVector512<uint32_t> nb_res)
auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_data = generate_random_uint16(nb_re * 2);
auto magnitude_b_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); auto magnitude_c_data = generate_random_uint16(nb_re * 2);
AlignedVector512<uint32_t> ulsch_llr_ref; AlignedVector512<uint32_t> llr_ref;
ulsch_llr_ref.resize(nb_re * 4); llr_ref.resize(nb_re * 4);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0); std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_ulsch_256qam_llr_ref((c16_t *)rf_data.data(), nr_256qam_llr_ref((c16_t *)rf_data.data(),
(int32_t *)magnitude_data.data(), (int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(), (int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(), (int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr_ref.data(), (int16_t *)llr_ref.data(),
nb_re, nb_re);
0);
AlignedVector512<uint32_t> llr;
AlignedVector512<uint32_t> ulsch_llr; llr.resize(nb_re * 4);
ulsch_llr.resize(nb_re * 4); std::fill(llr.begin(), llr.end(), 0);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0); nr_256qam_llr((int32_t *)rf_data.data(),
nr_ulsch_256qam_llr((int32_t *)rf_data.data(),
(int32_t *)magnitude_data.data(), (int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(), (int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(), (int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr.data(), (int16_t *)llr.data(),
nb_re, nb_re);
0);
int num_errors = 0; int num_errors = 0;
for (auto i = 0U; i < nb_re * 4; i++) { for (auto i = 0U; i < nb_re * 4; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i]) EXPECT_EQ(llr_ref[i], llr[i])
<< "Mismatch 256qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i; << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[i]) { if (llr_ref[i] != llr[i]) {
num_errors++; num_errors++;
} }
} }
...@@ -370,59 +353,57 @@ TEST(test_llr, check_2_res_256_qam) ...@@ -370,59 +353,57 @@ TEST(test_llr, check_2_res_256_qam)
AlignedVector512<int16_t> magnitude_data = {1, 1, 1, 1}; AlignedVector512<int16_t> magnitude_data = {1, 1, 1, 1};
AlignedVector512<int16_t> magnitude_b_data = {2, 2, 2, 2}; AlignedVector512<int16_t> magnitude_b_data = {2, 2, 2, 2};
AlignedVector512<int16_t> magnitude_c_data = {3, 3, 3, 3}; AlignedVector512<int16_t> magnitude_c_data = {3, 3, 3, 3};
AlignedVector512<int16_t> ulsch_llr_ref; AlignedVector512<int16_t> llr_ref;
ulsch_llr_ref.resize(2 * 8); llr_ref.resize(2 * 8);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0); std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_ulsch_256qam_llr_ref((c16_t *)rf_data.data(), nr_256qam_llr_ref((c16_t *)rf_data.data(),
(int32_t *)magnitude_data.data(), (int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(), (int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(), (int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr_ref.data(), (int16_t *)llr_ref.data(),
2, 2);
0);
AlignedVector512<int16_t> llr;
AlignedVector512<int16_t> ulsch_llr; llr.resize(2 * 8);
ulsch_llr.resize(2 * 8); std::fill(llr.begin(), llr.end(), 0);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0); nr_256qam_llr((int32_t *)rf_data.data(),
nr_ulsch_256qam_llr((int32_t *)rf_data.data(),
(int32_t *)magnitude_data.data(), (int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(), (int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(), (int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr.data(), (int16_t *)llr.data(),
2, 2);
0);
printf("\nDUT:\n"); printf("\nDUT:\n");
for (auto i = 0U; i < 2; i++) { for (auto i = 0U; i < 2; i++) {
printf("%d %d %d %d %d %d %d %d\n", printf("%d %d %d %d %d %d %d %d\n",
ulsch_llr[i * 8], llr[i * 8],
ulsch_llr[i * 8 + 1], llr[i * 8 + 1],
ulsch_llr[i * 8 + 2], llr[i * 8 + 2],
ulsch_llr[i * 8 + 3], llr[i * 8 + 3],
ulsch_llr[i * 8 + 4], llr[i * 8 + 4],
ulsch_llr[i * 8 + 5], llr[i * 8 + 5],
ulsch_llr[i * 8 + 6], llr[i * 8 + 6],
ulsch_llr[i * 8 + 7]); llr[i * 8 + 7]);
} }
printf("\nREF:\n"); printf("\nREF:\n");
for (auto i = 0U; i < 2; i++) { for (auto i = 0U; i < 2; i++) {
printf("%d %d %d %d %d %d %d %d\n", printf("%d %d %d %d %d %d %d %d\n",
ulsch_llr_ref[i * 8], llr_ref[i * 8],
ulsch_llr_ref[i * 8 + 1], llr_ref[i * 8 + 1],
ulsch_llr_ref[i * 8 + 2], llr_ref[i * 8 + 2],
ulsch_llr_ref[i * 8 + 3], llr_ref[i * 8 + 3],
ulsch_llr_ref[i * 8 + 4], llr_ref[i * 8 + 4],
ulsch_llr_ref[i * 8 + 5], llr_ref[i * 8 + 5],
ulsch_llr_ref[i * 8 + 6], llr_ref[i * 8 + 6],
ulsch_llr_ref[i * 8 + 7]); llr_ref[i * 8 + 7]);
} }
int num_errors = 0; int num_errors = 0;
for (auto i = 0U; i < 2 * 8; i++) { for (auto i = 0U; i < 2 * 8; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i]) EXPECT_EQ(llr_ref[i], llr[i])
<< "Mismatch 256qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i; << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[i]) { if (llr_ref[i] != llr[i]) {
num_errors++; num_errors++;
} }
} }
......
...@@ -1633,7 +1633,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, ...@@ -1633,7 +1633,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
nr_slot_rx, nr_slot_rx,
symbol, symbol,
frame_parms->ofdm_symbol_size, frame_parms->ofdm_symbol_size,
(int16_t *)(rxdataF_comp[0][aarx] + symbol * nb_re_pdsch), (int16_t *)(rxdataF_comp[0][aarx] + symbol * rx_size_symbol),
gold, gold,
(int16_t *)&phase_per_symbol[symbol], (int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]); &ptrs_re_symbol[symbol]);
...@@ -1654,21 +1654,21 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, ...@@ -1654,21 +1654,21 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
} }
#ifdef DEBUG_DL_PTRS #ifdef DEBUG_DL_PTRS
LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb), (*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb), 1, 1); LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * rx_size_symbol, rx_size_symbol * (*nbSymb), 1, 1);
#endif #endif
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------------------------*/
for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) { for(uint8_t i = *startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */ /* Skip rotation if the slot processing is wrong */
if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { if((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_DL_PTRS #ifdef DEBUG_DL_PTRS
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i);
#endif #endif
rotate_cpx_vector((c16_t *)&rxdataF_comp[0][aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], rotate_cpx_vector((c16_t *)&rxdataF_comp[0][aarx][i * rx_size_symbol],
&phase_per_symbol[i], &phase_per_symbol[i],
(c16_t *)&rxdataF_comp[0][aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], (c16_t *)&rxdataF_comp[0][aarx][i * rx_size_symbol],
((*nb_rb) * NR_NB_SC_PER_RB), ((*nb_rb) * NR_NB_SC_PER_RB),
15); 15);
}// if not DMRS Symbol }// if not DMRS Symbol
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
* \note * \note
* \warning * \warning
*/ */
#include "nr_phy_common.h"
#include "PHY/defs_nr_UE.h" #include "PHY/defs_nr_UE.h"
#include "PHY/phy_extern.h" #include "PHY/phy_extern.h"
#include "nr_transport_proto_ue.h" #include "nr_transport_proto_ue.h"
...@@ -101,27 +102,20 @@ static void nr_dlsch_layer_demapping(int16_t *llr_cw[2], ...@@ -101,27 +102,20 @@ static void nr_dlsch_layer_demapping(int16_t *llr_cw[2],
int16_t llr_layers[][sz]); int16_t llr_layers[][sz]);
/* compute LLR */ /* compute LLR */
static int nr_dlsch_llr(uint32_t rx_size_symbol, static void nr_dlsch_llr(uint32_t rx_size_symbol,
int nbRx, int nbRx,
uint sz, uint sz,
int16_t layer_llr[][sz], int16_t layer_llr[][sz],
NR_DL_FRAME_PARMS *frame_parms, int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int32_t dl_ch_mag[rx_size_symbol],
int32_t dl_ch_mag[rx_size_symbol], int32_t dl_ch_magb[rx_size_symbol],
int32_t dl_ch_magb[rx_size_symbol], int32_t dl_ch_magr[rx_size_symbol],
int32_t dl_ch_magr[rx_size_symbol], NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq,
NR_DL_UE_HARQ_t *dlsch1_harq, unsigned char symbol,
unsigned char harq_pid, uint32_t len,
unsigned char first_symbol_flag, NR_UE_DLSCH_t dlsch[2],
unsigned char symbol, uint32_t llr_offset_symbol);
unsigned short nb_rb,
int32_t codeword_TB0,
int32_t codeword_TB1,
uint32_t len,
uint8_t nr_slot_rx,
NR_UE_DLSCH_t dlsch[2],
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT]);
/** \fn nr_dlsch_extract_rbs /** \fn nr_dlsch_extract_rbs
\brief This function extracts the received resource blocks, both channel estimates and data symbols, for the current \brief This function extracts the received resource blocks, both channel estimates and data symbols, for the current
...@@ -220,17 +214,16 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol, ...@@ -220,17 +214,16 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol,
uint8_t pilots, uint8_t pilots,
uint32_t len, uint32_t len,
unsigned short nb_rb); unsigned short nb_rb);
void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
short n_tx, short n_tx,
short n_rx, short n_rx,
int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
int ***rho, int ***rho,
int32_t dl_ch_mag[][n_rx][rx_size_symbol], int32_t dl_ch_mag[][n_rx][rx_size_symbol],
int32_t dl_ch_magb[][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], int32_t dl_ch_magr[][n_rx][rx_size_symbol],
unsigned char symbol, unsigned char symbol,
unsigned short nb_rb, int length);
int length);
static bool overlap_csi_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu, int symbol) static bool overlap_csi_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu, int symbol)
{ {
...@@ -595,7 +588,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ...@@ -595,7 +588,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
dl_ch_magb, dl_ch_magb,
dl_ch_magr, dl_ch_magr,
symbol, symbol,
nb_rb_pdsch,
nb_re_pdsch); nb_re_pdsch);
if (nl >= 2) // Apply MMSE for 2, 3, and 4 Tx layers if (nl >= 2) // Apply MMSE for 2, 3, and 4 Tx layers
nr_dlsch_mmse(rx_size_symbol, nr_dlsch_mmse(rx_size_symbol,
...@@ -628,7 +620,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ...@@ -628,7 +620,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
/* Store the valid DL RE's */ /* Store the valid DL RE's */
dl_valid_re[symbol-1] = nb_re_pdsch; dl_valid_re[symbol] = nb_re_pdsch;
int startSymbIdx = 0; int startSymbIdx = 0;
int nbSymb = 0; int nbSymb = 0;
int pduBitmap = 0; int pduBitmap = 0;
...@@ -656,10 +648,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ...@@ -656,10 +648,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
(nb_rb_pdsch * 12), (nb_rb_pdsch * 12),
dlsch[0].rnti, dlsch[0].rnti,
dlsch); dlsch);
dl_valid_re[symbol - 1] -= ptrs_re_per_slot[0][symbol]; dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol];
} }
/* at last symbol in a slot calculate LLR's for whole slot */ /* at last symbol in a slot calculate LLR's for whole slot */
if(symbol == (startSymbIdx + nbSymb -1)) { if(symbol == (startSymbIdx + nbSymb - 1)) {
const uint32_t rx_llr_layer_size = (G + dlsch[0].Nl - 1) / dlsch[0].Nl; const uint32_t rx_llr_layer_size = (G + dlsch[0].Nl - 1) / dlsch[0].Nl;
if (dlsch[0].Nl == 0 || rx_llr_layer_size == 0 || rx_llr_layer_size > 10 * 1000 * 1000) { if (dlsch[0].Nl == 0 || rx_llr_layer_size == 0 || rx_llr_layer_size > 10 * 1000 * 1000) {
...@@ -668,42 +660,32 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ...@@ -668,42 +660,32 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
} }
int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size]; int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size];
for(int i = startSymbIdx; i < startSymbIdx+nbSymb; i++) { for(int i = startSymbIdx; i < startSymbIdx + nbSymb; i++) {
/* re evaluating the first symbol flag as LLR's are done in symbol loop */
if(i == startSymbIdx && i < 3)
first_symbol_flag = 1;
else
first_symbol_flag = 0;
/* Calculate LLR's for each symbol */ /* Calculate LLR's for each symbol */
start_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); start_meas_nr_ue_phy(ue, DLSCH_LLR_STATS);
nr_dlsch_llr(rx_size_symbol, nr_dlsch_llr(rx_size_symbol,
nbRx, nbRx,
rx_llr_layer_size, rx_llr_layer_size,
layer_llr, layer_llr,
frame_parms,
rxdataF_comp, rxdataF_comp,
dl_ch_mag[0][0], dl_ch_mag[0][0],
dl_ch_magb[0][0], dl_ch_magb[0][0],
dl_ch_magr[0][0], dl_ch_magr[0][0],
dlsch0_harq, dlsch0_harq,
dlsch1_harq, dlsch1_harq,
harq_pid,
first_symbol_flag,
i, i,
nb_rb_pdsch, dl_valid_re[i],
codeword_TB0,
codeword_TB1,
dl_valid_re[i - 1],
nr_slot_rx,
dlsch, dlsch,
llr_offset); llr_offset[i]);
if (i < startSymbIdx + nbSymb - 1) // up to the penultimate symbol
llr_offset[i + 1] = dl_valid_re[i] * dlsch_config->qamModOrder + llr_offset[i];
stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS);
} }
start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
nr_dlsch_layer_demapping(llr, nr_dlsch_layer_demapping(llr,
dlsch[0].Nl, dlsch[0].Nl,
dlsch[0].dlsch_config.qamModOrder, dlsch_config->qamModOrder,
G, G,
codeword_TB0, codeword_TB0,
codeword_TB1, codeword_TB1,
...@@ -876,15 +858,13 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, ...@@ -876,15 +858,13 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol,
QAM_amp128r = simde_mm_set1_epi16(QAM256_n3); QAM_amp128r = simde_mm_set1_epi16(QAM256_n3);
} }
// printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol);
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx];
dl_ch_mag128 = (simde__m128i *)dl_ch_mag[l][aarx]; dl_ch_mag128 = (simde__m128i *)dl_ch_mag[l][aarx];
dl_ch_mag128b = (simde__m128i *)dl_ch_magb[l][aarx]; dl_ch_mag128b = (simde__m128i *)dl_ch_magb[l][aarx];
dl_ch_mag128r = (simde__m128i *)dl_ch_magr[l][aarx]; dl_ch_mag128r = (simde__m128i *)dl_ch_magr[l][aarx];
rxdataF128 = (simde__m128i *)rxdataF_ext[aarx]; rxdataF128 = (simde__m128i *)rxdataF_ext[aarx];
rxdataF_comp128 = (simde__m128i *)(rxdataF_comp[l][aarx] + symbol * nb_rb * 12); rxdataF_comp128 = (simde__m128i *)(rxdataF_comp[l][aarx] + symbol * rx_size_symbol);
for (int rb = 0; rb < nb_rb_0; rb++) { for (int rb = 0; rb < nb_rb_0; rb++) {
if (mod_order > 2) { if (mod_order > 2) {
...@@ -1259,37 +1239,34 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, ...@@ -1259,37 +1239,34 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz,
} }
} }
void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
short n_tx, short n_tx,
short n_rx, short n_rx,
int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
int ***rho, int ***rho,
int32_t dl_ch_mag[][n_rx][rx_size_symbol], int32_t dl_ch_mag[][n_rx][rx_size_symbol],
int32_t dl_ch_magb[][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], int32_t dl_ch_magr[][n_rx][rx_size_symbol],
unsigned char symbol, unsigned char symbol,
unsigned short nb_rb, int length)
int length) { {
unsigned char aatx, aarx;
int i;
simde__m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*dl_ch_mag128_0r,*dl_ch_mag128_1r; simde__m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*dl_ch_mag128_0r,*dl_ch_mag128_1r;
uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); uint32_t nb_rb_0 = length/12 + ((length%12)?1:0);
if (n_rx>1) { if (n_rx > 1) {
for (aatx=0; aatx<n_tx; aatx++) { for (int aatx = 0; aatx < n_tx; aatx++) {
rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[aatx][0] + symbol * nb_rb * 12); rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[aatx][0] + symbol * rx_size_symbol);
dl_ch_mag128_0 = (simde__m128i *)dl_ch_mag[aatx][0]; dl_ch_mag128_0 = (simde__m128i *)dl_ch_mag[aatx][0];
dl_ch_mag128_0b = (simde__m128i *)dl_ch_magb[aatx][0]; dl_ch_mag128_0b = (simde__m128i *)dl_ch_magb[aatx][0];
dl_ch_mag128_0r = (simde__m128i *)dl_ch_magr[aatx][0]; dl_ch_mag128_0r = (simde__m128i *)dl_ch_magr[aatx][0];
for (aarx=1; aarx<n_rx; aarx++) { for (int aarx = 1; aarx < n_rx; aarx++) {
rxdataF_comp128_1 = (simde__m128i *)(rxdataF_comp[aatx][aarx] + symbol * nb_rb * 12); rxdataF_comp128_1 = (simde__m128i *)(rxdataF_comp[aatx][aarx] + symbol * rx_size_symbol);
dl_ch_mag128_1 = (simde__m128i *)dl_ch_mag[aatx][aarx]; dl_ch_mag128_1 = (simde__m128i *)dl_ch_mag[aatx][aarx];
dl_ch_mag128_1b = (simde__m128i *)dl_ch_magb[aatx][aarx]; dl_ch_mag128_1b = (simde__m128i *)dl_ch_magb[aatx][aarx];
dl_ch_mag128_1r = (simde__m128i *)dl_ch_magr[aatx][aarx]; dl_ch_mag128_1r = (simde__m128i *)dl_ch_magr[aatx][aarx];
// MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM/256 llr computation) // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM/256 llr computation)
for (i=0; i<nb_rb_0*3; i++) { for (int i = 0; i < nb_rb_0 * 3; i++) {
rxdataF_comp128_0[i] = simde_mm_adds_epi16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]); rxdataF_comp128_0[i] = simde_mm_adds_epi16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
dl_ch_mag128_0[i] = simde_mm_adds_epi16(dl_ch_mag128_0[i],dl_ch_mag128_1[i]); dl_ch_mag128_0[i] = simde_mm_adds_epi16(dl_ch_mag128_0[i],dl_ch_mag128_1[i]);
dl_ch_mag128_0b[i] = simde_mm_adds_epi16(dl_ch_mag128_0b[i],dl_ch_mag128_1b[i]); dl_ch_mag128_0b[i] = simde_mm_adds_epi16(dl_ch_mag128_0b[i],dl_ch_mag128_1b[i]);
...@@ -1298,14 +1275,14 @@ void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, ...@@ -1298,14 +1275,14 @@ void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
} }
} }
#ifdef DEBUG_DLSCH_DEMOD #ifdef DEBUG_DLSCH_DEMOD
for (i=0; i<nb_rb_0*3; i++) { for (int i = 0; i < nb_rb_0 * 3; i++) {
printf("symbol%d RB %d\n",symbol,i/3); printf("symbol%d RB %d\n", symbol,i / 3);
rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[0][0] + symbol * nb_rb * 12); rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[0][0] + symbol * rx_size_symbol);
rxdataF_comp128_1 = (simde__m128i *)(rxdataF_comp[0][n_rx] + symbol * nb_rb * 12); rxdataF_comp128_1 = (simde__m128i *)(rxdataF_comp[0][n_rx] + symbol * rx_size_symbol);
print_shorts("tx 1 mrc_re/mrc_Im:",(int16_t*)&rxdataF_comp128_0[i]); print_shorts("tx 1 mrc_re/mrc_Im:",(int16_t*)&rxdataF_comp128_0[i]);
print_shorts("tx 2 mrc_re/mrc_Im:",(int16_t*)&rxdataF_comp128_1[i]); print_shorts("tx 2 mrc_re/mrc_Im:",(int16_t*)&rxdataF_comp128_1[i]);
// printf("mrc mag0 = %d = %d \n",((int16_t*)&dl_ch_mag128_0[0])[0],((int16_t*)&dl_ch_mag128_0[0])[1]); // printf("mrc mag0 = %d = %d \n",((int16_t*)&dl_ch_mag128_0[0])[0],((int16_t*)&dl_ch_mag128_0[0])[1]);
// printf("mrc mag0b = %d = %d \n",((int16_t*)&dl_ch_mag128_0b[0])[0],((int16_t*)&dl_ch_mag128_0b[0])[1]); // printf("mrc mag0b = %d = %d \n",((int16_t*)&dl_ch_mag128_0b[0])[0],((int16_t*)&dl_ch_mag128_0b[0])[1]);
} }
#endif #endif
if (rho) { if (rho) {
...@@ -1876,60 +1853,44 @@ static void nr_dlsch_layer_demapping(int16_t *llr_cw[2], ...@@ -1876,60 +1853,44 @@ static void nr_dlsch_layer_demapping(int16_t *llr_cw[2],
} }
} }
static int nr_dlsch_llr(uint32_t rx_size_symbol, static void nr_dlsch_llr(uint32_t rx_size_symbol,
int nbRx, int nbRx,
uint sz, uint sz,
int16_t layer_llr[][sz], int16_t layer_llr[][sz],
NR_DL_FRAME_PARMS *frame_parms, int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int32_t dl_ch_mag[rx_size_symbol],
int32_t dl_ch_mag[rx_size_symbol], int32_t dl_ch_magb[rx_size_symbol],
int32_t dl_ch_magb[rx_size_symbol], int32_t dl_ch_magr[rx_size_symbol],
int32_t dl_ch_magr[rx_size_symbol], NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq,
NR_DL_UE_HARQ_t *dlsch1_harq, unsigned char symbol,
unsigned char harq_pid, uint32_t len,
unsigned char first_symbol_flag, NR_UE_DLSCH_t dlsch[2],
unsigned char symbol, uint32_t llr_offset_symbol)
unsigned short nb_rb,
int32_t codeword_TB0,
int32_t codeword_TB1,
uint32_t len,
uint8_t nr_slot_rx,
NR_UE_DLSCH_t dlsch[2],
uint32_t llr_offset[14])
{ {
uint32_t llr_offset_symbol;
if (first_symbol_flag==1)
llr_offset[symbol-1] = 0;
llr_offset_symbol = llr_offset[symbol-1];
llr_offset[symbol] = len*dlsch[0].dlsch_config.qamModOrder + llr_offset_symbol;
switch (dlsch[0].dlsch_config.qamModOrder) { switch (dlsch[0].dlsch_config.qamModOrder) {
case 2 : case 2 :
for(int l=0; l < dlsch[0].Nl; l++) for(int l = 0; l < dlsch[0].Nl; l++)
nr_dlsch_qpsk_llr(frame_parms, rxdataF_comp[l][0], layer_llr[l] + llr_offset_symbol, symbol, len, first_symbol_flag, nb_rb); nr_qpsk_llr(&rxdataF_comp[l][0][symbol * rx_size_symbol], layer_llr[l] + llr_offset_symbol, len);
break; break;
case 4 : case 4 :
for(int l=0; l < dlsch[0].Nl; l++) for(int l = 0; l < dlsch[0].Nl; l++)
nr_dlsch_16qam_llr(frame_parms, rxdataF_comp[l][0], layer_llr[l] + llr_offset_symbol, dl_ch_mag, symbol, len, first_symbol_flag, nb_rb); nr_16qam_llr(&rxdataF_comp[l][0][symbol * rx_size_symbol], dl_ch_mag, layer_llr[l] + llr_offset_symbol, len);
break; break;
case 6 : case 6 :
for(int l=0; l < dlsch[0].Nl; l++) for(int l=0; l < dlsch[0].Nl; l++)
nr_dlsch_64qam_llr(frame_parms, rxdataF_comp[l][0], layer_llr[l] + llr_offset_symbol, dl_ch_mag, dl_ch_magb, symbol, len, first_symbol_flag, nb_rb); nr_64qam_llr(&rxdataF_comp[l][0][symbol * rx_size_symbol], dl_ch_mag, dl_ch_magb, layer_llr[l] + llr_offset_symbol, len);
break; break;
case 8: case 8:
for(int l=0; l < dlsch[0].Nl; l++) for(int l=0; l < dlsch[0].Nl; l++)
nr_dlsch_256qam_llr(frame_parms, rxdataF_comp[l][0], layer_llr[l] + llr_offset_symbol, dl_ch_mag, dl_ch_magb, dl_ch_magr, symbol, len, first_symbol_flag, nb_rb); nr_256qam_llr(&rxdataF_comp[l][0][symbol * rx_size_symbol], dl_ch_mag, dl_ch_magb, dl_ch_magr, layer_llr[l] + llr_offset_symbol, len);
break; break;
default: default:
LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); AssertFatal(false, "Unknown mod_order!!!!\n");
return(-1);
break; break;
} }
...@@ -1937,27 +1898,25 @@ static int nr_dlsch_llr(uint32_t rx_size_symbol, ...@@ -1937,27 +1898,25 @@ static int nr_dlsch_llr(uint32_t rx_size_symbol,
if (dlsch1_harq) { if (dlsch1_harq) {
switch (dlsch[1].dlsch_config.qamModOrder) { switch (dlsch[1].dlsch_config.qamModOrder) {
case 2 : case 2 :
nr_dlsch_qpsk_llr(frame_parms, rxdataF_comp[0][0], layer_llr[0] + llr_offset_symbol, symbol, len, first_symbol_flag, nb_rb); nr_qpsk_llr(&rxdataF_comp[0][0][symbol * rx_size_symbol], layer_llr[0] + llr_offset_symbol, len);
break; break;
case 4: case 4:
nr_dlsch_16qam_llr(frame_parms, rxdataF_comp[0][0], layer_llr[0] + llr_offset_symbol, dl_ch_mag, symbol, len, first_symbol_flag, nb_rb); nr_16qam_llr(&rxdataF_comp[0][0][symbol * rx_size_symbol], dl_ch_mag, layer_llr[0] + llr_offset_symbol, len);
break; break;
case 6 : case 6 :
nr_dlsch_64qam_llr(frame_parms, rxdataF_comp[0][0], layer_llr[0] + llr_offset_symbol, dl_ch_mag, dl_ch_magb, symbol, len, first_symbol_flag, nb_rb); nr_64qam_llr(&rxdataF_comp[0][0][symbol * rx_size_symbol], dl_ch_mag, dl_ch_magb, layer_llr[0] + llr_offset_symbol, len);
break; break;
case 8 : case 8 :
nr_dlsch_256qam_llr(frame_parms, rxdataF_comp[0][0], layer_llr[0] + llr_offset_symbol, dl_ch_mag, dl_ch_magb, dl_ch_magr, symbol, len, first_symbol_flag, nb_rb); nr_256qam_llr(&rxdataF_comp[0][0][symbol * rx_size_symbol], dl_ch_mag, dl_ch_magb, dl_ch_magr, layer_llr[0] + llr_offset_symbol, len);
break; break;
default: default:
LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); AssertFatal(false, "Unknown mod_order!!!!\n");
return(-1);
break; break;
} }
} }
return 0;
} }
//============================================================================================== //==============================================================================================
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
* \brief Top-level routines for LLR computation of the PDSCH physical channel
* \author H. WANG
* \date 2018
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
#include "PHY/defs_nr_UE.h"
#include "PHY/phy_extern_nr_ue.h"
#include "nr_transport_proto_ue.h"
#include "PHY/TOOLS/tools_defs.h"
#include "PHY/sse_intrin.h"
//#define DEBUG_LLR_SIC
//==============================================================================================
// SINGLE-STREAM
//==============================================================================================
//----------------------------------------------------------------------------------------------
// QPSK
//----------------------------------------------------------------------------------------------
int nr_dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb)
{
c16_t *rxF = (c16_t *)&rxdataF_comp[((int32_t)symbol*nb_rb*12)];
c16_t *llr32 = (c16_t *)dlsch_llr;
int i;
if (!llr32) {
LOG_E(PHY,"nr_dlsch_qpsk_llr: llr is null, symbol %d, llr32=%p\n",symbol, llr32);
return(-1);
}
/*
LOG_I(PHY,"dlsch_qpsk_llr: [symb %d / Length %d]: @LLR Buff %x, @LLR Buff(symb) %x \n",
symbol,
len,
dlsch_llr,
llr32);
*/
for (i=0; i<len; i++) {
//*llr32 = *rxF;
llr32->r = rxF->r >> 3;
llr32->i = rxF->i >> 3;
LOG_D(PHY,"dlsch_qpsk_llr %d : (%d,%d)\n", i, llr32->r, llr32->i);
rxF++;
llr32++;
}
return(0);
}
//----------------------------------------------------------------------------------------------
// 16-QAM
//----------------------------------------------------------------------------------------------
void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb)
{
simde__m128i *rxF = (simde__m128i*)&rxdataF_comp[(symbol*nb_rb*12)];
simde__m128i *ch_mag;
simde__m128i llr128[2];
uint32_t *llr32;
int i;
unsigned char len_mod4=0;
llr32 = (uint32_t*)dlsch_llr;
ch_mag = (simde__m128i *)dl_ch_mag;
// printf("len=%d\n", len);
len_mod4 = len&3;
// printf("len_mod4=%d\n", len_mod4);
len>>=2; // length in quad words (4 REs)
// printf("len>>=2=%d\n", len);
len+=(len_mod4==0 ? 0 : 1);
// printf("len+=%d\n", len);
for (i=0; i<len; i++) {
simde__m128i xmm0 =simde_mm_abs_epi16(rxF[i]);
xmm0 =simde_mm_subs_epi16(ch_mag[i],xmm0);
// lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2
llr128[0] =simde_mm_unpacklo_epi32(rxF[i],xmm0);
llr128[1] =simde_mm_unpackhi_epi32(rxF[i],xmm0);
llr32[0] =simde_mm_extract_epi32(llr128[0],0); //((uint32_t *)&llr128[0])[0];
llr32[1] =simde_mm_extract_epi32(llr128[0],1); //((uint32_t *)&llr128[0])[1];
llr32[2] =simde_mm_extract_epi32(llr128[0],2); //((uint32_t *)&llr128[0])[2];
llr32[3] =simde_mm_extract_epi32(llr128[0],3); //((uint32_t *)&llr128[0])[3];
llr32[4] =simde_mm_extract_epi32(llr128[1],0); //((uint32_t *)&llr128[1])[0];
llr32[5] =simde_mm_extract_epi32(llr128[1],1); //((uint32_t *)&llr128[1])[1];
llr32[6] =simde_mm_extract_epi32(llr128[1],2); //((uint32_t *)&llr128[1])[2];
llr32[7] =simde_mm_extract_epi32(llr128[1],3); //((uint32_t *)&llr128[1])[3];
llr32+=8;
}
simde_mm_empty();
simde_m_empty();
}
//----------------------------------------------------------------------------------------------
// 64-QAM
//----------------------------------------------------------------------------------------------
void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
int32_t *dl_ch_magb,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb)
{
simde__m128i *rxF = (simde__m128i*)&rxdataF_comp[(symbol*nb_rb*12)];
simde__m128i *ch_mag,*ch_magb;
int i,len2;
unsigned char len_mod4;
int16_t *llr2;
llr2 = dlsch_llr;
ch_mag = (simde__m128i *)dl_ch_mag;
ch_magb = (simde__m128i *)dl_ch_magb;
// printf("nr_dlsch_64qam_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust);
/* LOG_I(PHY,"nr_dlsch_64qam_llr [symb %d / FirstSym %d / Length %d]: @LLR Buff %x \n",
symbol,
first_symbol_flag,
len,
dlsch_llr,
pllr_symbol);*/
len_mod4 =len&3;
len2=len>>2; // length in quad words (4 REs)
len2+=((len_mod4==0)?0:1);
for (i=0; i<len2; i++) {
simde__m128i xmm1, xmm2;
xmm1 =simde_mm_abs_epi16(rxF[i]);
xmm1 =simde_mm_subs_epi16(ch_mag[i],xmm1);
xmm2 =simde_mm_abs_epi16(xmm1);
xmm2 =simde_mm_subs_epi16(ch_magb[i],xmm2);
// loop over all LLRs in quad word (24 coded bits)
/*
for (j=0;j<8;j+=2) {
llr2[0] = ((short *)&rxF[i])[j];
llr2[1] = ((short *)&rxF[i])[j+1];
llr2[2] = ((short *)&xmm1)[j];
llr2[3] = ((short *)&xmm1)[j+1];
llr2[4] = ((short *)&xmm2)[j];
llr2[5] = ((short *)&xmm2)[j+1];
llr2+=6;
}
*/
llr2[0] = ((short *)&rxF[i])[0];
llr2[1] = ((short *)&rxF[i])[1];
llr2[2] =simde_mm_extract_epi16(xmm1,0);
llr2[3] =simde_mm_extract_epi16(xmm1,1);//((short *)&xmm1)[j+1];
llr2[4] =simde_mm_extract_epi16(xmm2,0);//((short *)&xmm2)[j];
llr2[5] =simde_mm_extract_epi16(xmm2,1);//((short *)&xmm2)[j+1];
llr2+=6;
llr2[0] = ((short *)&rxF[i])[2];
llr2[1] = ((short *)&rxF[i])[3];
llr2[2] =simde_mm_extract_epi16(xmm1,2);
llr2[3] =simde_mm_extract_epi16(xmm1,3);//((short *)&xmm1)[j+1];
llr2[4] =simde_mm_extract_epi16(xmm2,2);//((short *)&xmm2)[j];
llr2[5] =simde_mm_extract_epi16(xmm2,3);//((short *)&xmm2)[j+1];
llr2+=6;
llr2[0] = ((short *)&rxF[i])[4];
llr2[1] = ((short *)&rxF[i])[5];
llr2[2] =simde_mm_extract_epi16(xmm1,4);
llr2[3] =simde_mm_extract_epi16(xmm1,5);//((short *)&xmm1)[j+1];
llr2[4] =simde_mm_extract_epi16(xmm2,4);//((short *)&xmm2)[j];
llr2[5] =simde_mm_extract_epi16(xmm2,5);//((short *)&xmm2)[j+1];
llr2+=6;
llr2[0] = ((short *)&rxF[i])[6];
llr2[1] = ((short *)&rxF[i])[7];
llr2[2] =simde_mm_extract_epi16(xmm1,6);
llr2[3] =simde_mm_extract_epi16(xmm1,7);//((short *)&xmm1)[j+1];
llr2[4] =simde_mm_extract_epi16(xmm2,6);//((short *)&xmm2)[j];
llr2[5] =simde_mm_extract_epi16(xmm2,7);//((short *)&xmm2)[j+1];
llr2+=6;
}
simde_mm_empty();
simde_m_empty();
}
//----------------------------------------------------------------------------------------------
// 256-QAM
//----------------------------------------------------------------------------------------------
void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
int32_t *dl_ch_magb,
int32_t *dl_ch_magr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb)
{
simde__m128i *rxF = (simde__m128i*)&rxdataF_comp[(symbol*nb_rb*12)];
simde__m128i *ch_mag,*ch_magb,*ch_magr;
int i,len2;
unsigned char len_mod4;
int16_t *llr2;
llr2 = dlsch_llr;
ch_mag = (simde__m128i *)dl_ch_mag;
ch_magb = (simde__m128i *)dl_ch_magb;
ch_magr = (simde__m128i *)dl_ch_magr;
len_mod4 =len&3;
len2=len>>2; // length in quad words (4 REs)
len2+=((len_mod4==0)?0:1);
for (i=0; i<len2; i++) {
simde__m128i xmm1 = simde_mm_abs_epi16(rxF[i]);
xmm1 = simde_mm_subs_epi16(ch_mag[i],xmm1);
simde__m128i xmm2 = simde_mm_abs_epi16(xmm1);
xmm2 = simde_mm_subs_epi16(ch_magb[i],xmm2);
simde__m128i xmm3 = simde_mm_abs_epi16(xmm2);
xmm3 = simde_mm_subs_epi16(ch_magr[i], xmm3);
llr2[0] = ((short *)&rxF[i])[0];
llr2[1] = ((short *)&rxF[i])[1];
llr2[2] = simde_mm_extract_epi16(xmm1,0);
llr2[3] = simde_mm_extract_epi16(xmm1,1);//((short *)&xmm1)[j+1];
llr2[4] = simde_mm_extract_epi16(xmm2,0);//((short *)&xmm2)[j];
llr2[5] = simde_mm_extract_epi16(xmm2,1);//((short *)&xmm2)[j+1];
llr2[6] = simde_mm_extract_epi16(xmm3,0);
llr2[7] = simde_mm_extract_epi16(xmm3,1);
llr2+=8;
llr2[0] = ((short *)&rxF[i])[2];
llr2[1] = ((short *)&rxF[i])[3];
llr2[2] = simde_mm_extract_epi16(xmm1,2);
llr2[3] = simde_mm_extract_epi16(xmm1,3);//((short *)&xmm1)[j+1];
llr2[4] = simde_mm_extract_epi16(xmm2,2);//((short *)&xmm2)[j];
llr2[5] = simde_mm_extract_epi16(xmm2,3);//((short *)&xmm2)[j+1];
llr2[6] = simde_mm_extract_epi16(xmm3,2);
llr2[7] = simde_mm_extract_epi16(xmm3,3);
llr2+=8;
llr2[0] = ((short *)&rxF[i])[4];
llr2[1] = ((short *)&rxF[i])[5];
llr2[2] = simde_mm_extract_epi16(xmm1,4);
llr2[3] = simde_mm_extract_epi16(xmm1,5);//((short *)&xmm1)[j+1];
llr2[4] = simde_mm_extract_epi16(xmm2,4);//((short *)&xmm2)[j];
llr2[5] = simde_mm_extract_epi16(xmm2,5);//((short *)&xmm2)[j+1];
llr2[6] = simde_mm_extract_epi16(xmm3,4);
llr2[7] = simde_mm_extract_epi16(xmm3,5);
llr2+=8;
llr2[0] = ((short *)&rxF[i])[6];
llr2[1] = ((short *)&rxF[i])[7];
llr2[2] = simde_mm_extract_epi16(xmm1,6);
llr2[3] = simde_mm_extract_epi16(xmm1,7);//((short *)&xmm1)[j+1];
llr2[4] = simde_mm_extract_epi16(xmm2,6);//((short *)&xmm2)[j];
llr2[5] = simde_mm_extract_epi16(xmm2,7);//((short *)&xmm2)[j+1];
llr2[6] = simde_mm_extract_epi16(xmm3,6);
llr2[7] = simde_mm_extract_epi16(xmm3,7);
llr2+=8;
}
simde_mm_empty();
simde_m_empty();
}
//==============================================================================================
// DUAL-STREAM
//==============================================================================================
//----------------------------------------------------------------------------------------------
// QPSK
//----------------------------------------------------------------------------------------------
simde__m128i y0r_over2 __attribute__ ((aligned(16)));
simde__m128i y0i_over2 __attribute__ ((aligned(16)));
simde__m128i y1r_over2 __attribute__ ((aligned(16)));
simde__m128i y1i_over2 __attribute__ ((aligned(16)));
simde__m128i A __attribute__ ((aligned(16)));
simde__m128i B __attribute__ ((aligned(16)));
simde__m128i C __attribute__ ((aligned(16)));
simde__m128i D __attribute__ ((aligned(16)));
simde__m128i E __attribute__ ((aligned(16)));
simde__m128i F __attribute__ ((aligned(16)));
simde__m128i G __attribute__ ((aligned(16)));
simde__m128i H __attribute__ ((aligned(16)));
void nr_qpsk_qpsk(short *stream0_in,
short *stream1_in,
short *stream0_out,
short *rho01,
int length
)
{
/*
This function computes the LLRs of stream 0 (s_0) in presence of the interfering stream 1 (s_1) assuming that both symbols are QPSK. It can be used for both MU-MIMO interference-aware receiver or for SU-MIMO receivers.
Parameters:
stream0_in = Matched filter output y0' = (h0*g0)*y0
stream1_in = Matched filter output y1' = (h0*g1)*y0
stream0_out = LLRs
rho01 = Correlation between the two effective channels \rho_{10} = (h1*g1)*(h0*g0)
length = number of resource elements
*/
simde__m128i *rho01_128i = (simde__m128i *)rho01;
simde__m128i *stream0_128i_in = (simde__m128i *)stream0_in;
simde__m128i *stream1_128i_in = (simde__m128i *)stream1_in;
simde__m128i *stream0_128i_out = (simde__m128i *)stream0_out;
simde__m128i ONE_OVER_SQRT_8 =simde_mm_set1_epi16(23170); //round(2^16/sqrt(8))
int i;
for (i=0; i<length>>2; i+=2) {
// in each iteration, we take 8 complex samples
simde__m128i xmm0 = rho01_128i[i]; // 4 symbols
simde__m128i xmm1 = rho01_128i[i+1];
// put (rho_r + rho_i)/2sqrt2 in rho_rpi
// put (rho_r - rho_i)/2sqrt2 in rho_rmi
xmm0 =simde_mm_shufflelo_epi16(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm0 =simde_mm_shufflehi_epi16(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm0 =simde_mm_shuffle_epi32(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shufflelo_epi16(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shufflehi_epi16(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shuffle_epi32(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
//xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)]
//xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)]
simde__m128i xmm2 = simde_mm_unpacklo_epi64(xmm0, xmm1); // Re(rho)
simde__m128i xmm3 = simde_mm_unpackhi_epi64(xmm0, xmm1); // Im(rho)
simde__m128i rho_rpi = simde_mm_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho)
simde__m128i rho_rmi = simde_mm_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho)
// divide by sqrt(8), no shift needed ONE_OVER_SQRT_8 = Q1.16
rho_rpi =simde_mm_mulhi_epi16(rho_rpi,ONE_OVER_SQRT_8);
rho_rmi =simde_mm_mulhi_epi16(rho_rmi,ONE_OVER_SQRT_8);
// Compute LLR for first bit of stream 0
// Compute real and imaginary parts of MF output for stream 0
xmm0 = stream0_128i_in[i];
xmm1 = stream0_128i_in[i+1];
xmm0 =simde_mm_shufflelo_epi16(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm0 =simde_mm_shufflehi_epi16(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm0 =simde_mm_shuffle_epi32(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shufflelo_epi16(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shufflehi_epi16(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shuffle_epi32(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
//xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)]
//xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)]
simde__m128i y0r = simde_mm_unpacklo_epi64(xmm0, xmm1); // = [y0r(1),y0r(2),y0r(3),y0r(4)]
simde__m128i y0i = simde_mm_unpackhi_epi64(xmm0, xmm1);
simde__m128i y0r_over2 = simde_mm_srai_epi16(y0r, 1); // divide by 2
simde__m128i y0i_over2 = simde_mm_srai_epi16(y0i, 1); // divide by 2
// Compute real and imaginary parts of MF output for stream 1
xmm0 = stream1_128i_in[i];
xmm1 = stream1_128i_in[i+1];
xmm0 =simde_mm_shufflelo_epi16(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm0 =simde_mm_shufflehi_epi16(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm0 =simde_mm_shuffle_epi32(xmm0,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shufflelo_epi16(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shufflehi_epi16(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
xmm1 =simde_mm_shuffle_epi32(xmm1,0xd8); // SIMDE_MM_SHUFFLE(0,2,1,3));
//xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)]
//xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)]
simde__m128i y1r = simde_mm_unpacklo_epi64(xmm0, xmm1); //[y1r(1),y1r(2),y1r(3),y1r(4)]
simde__m128i y1i = simde_mm_unpackhi_epi64(xmm0, xmm1); //[y1i(1),y1i(2),y1i(3),y1i(4)]
simde__m128i y1r_over2 = simde_mm_srai_epi16(y1r, 1); // divide by 2
simde__m128i y1i_over2 = simde_mm_srai_epi16(y1i, 1); // divide by 2
// Compute the terms for the LLR of first bit
xmm0 =simde_mm_setzero_si128(); // ZERO
// 1 term for numerator of LLR
xmm3 =simde_mm_subs_epi16(y1r_over2,rho_rpi);
A =simde_mm_abs_epi16(xmm3); // A = |y1r/2 - rho/sqrt(8)|
xmm2 =simde_mm_adds_epi16(A,y0i_over2); // = |y1r/2 - rho/sqrt(8)| + y0i/2
xmm3 =simde_mm_subs_epi16(y1i_over2,rho_rmi);
B =simde_mm_abs_epi16(xmm3); // B = |y1i/2 - rho*/sqrt(8)|
simde__m128i logmax_num_re0 =simde_mm_adds_epi16(B,xmm2); // = |y1r/2 - rho/sqrt(8)|+|y1i/2 - rho*/sqrt(8)| + y0i/2
// 2 term for numerator of LLR
xmm3 =simde_mm_subs_epi16(y1r_over2,rho_rmi);
C =simde_mm_abs_epi16(xmm3); // C = |y1r/2 - rho*/4|
xmm2 =simde_mm_subs_epi16(C,y0i_over2); // = |y1r/2 - rho*/4| - y0i/2
xmm3 =simde_mm_adds_epi16(y1i_over2,rho_rpi);
D =simde_mm_abs_epi16(xmm3); // D = |y1i/2 + rho/4|
xmm2 =simde_mm_adds_epi16(xmm2,D); // |y1r/2 - rho*/4| + |y1i/2 + rho/4| - y0i/2
logmax_num_re0 =simde_mm_max_epi16(logmax_num_re0,xmm2); // max, numerator done
// 1 term for denominator of LLR
xmm3 =simde_mm_adds_epi16(y1r_over2,rho_rmi);
E =simde_mm_abs_epi16(xmm3); // E = |y1r/2 + rho*/4|
xmm2 =simde_mm_adds_epi16(E,y0i_over2); // = |y1r/2 + rho*/4| + y0i/2
xmm3 =simde_mm_subs_epi16(y1i_over2,rho_rpi);
F =simde_mm_abs_epi16(xmm3); // F = |y1i/2 - rho/4|
simde__m128i logmax_den_re0 =simde_mm_adds_epi16(F,xmm2); // = |y1r/2 + rho*/4| + |y1i/2 - rho/4| + y0i/2
// 2 term for denominator of LLR
xmm3 =simde_mm_adds_epi16(y1r_over2,rho_rpi);
G =simde_mm_abs_epi16(xmm3); // G = |y1r/2 + rho/4|
xmm2 =simde_mm_subs_epi16(G,y0i_over2); // = |y1r/2 + rho/4| - y0i/2
xmm3 =simde_mm_adds_epi16(y1i_over2,rho_rmi);
H =simde_mm_abs_epi16(xmm3); // H = |y1i/2 + rho*/4|
xmm2 =simde_mm_adds_epi16(xmm2,H); // = |y1r/2 + rho/4| + |y1i/2 + rho*/4| - y0i/2
logmax_den_re0 =simde_mm_max_epi16(logmax_den_re0,xmm2); // max, denominator done
// Compute the terms for the LLR of first bit
// 1 term for nominator of LLR
xmm2 = simde_mm_adds_epi16(A,y0r_over2);
simde__m128i logmax_num_im0 = simde_mm_adds_epi16(B, xmm2); // = |y1r/2 - rho/4| + |y1i/2 - rho*/4| + y0r/2
// 2 term for nominator of LLR
xmm2 =simde_mm_subs_epi16(E,y0r_over2);
xmm2 =simde_mm_adds_epi16(xmm2,F); // = |y1r/2 + rho*/4| + |y1i/2 - rho/4| - y0r/2
logmax_num_im0 =simde_mm_max_epi16(logmax_num_im0,xmm2); // max, nominator done
// 1 term for denominator of LLR
xmm2 =simde_mm_adds_epi16(C,y0r_over2);
simde__m128i logmax_den_im0 =simde_mm_adds_epi16(D,xmm2); // = |y1r/2 - rho*/4| + |y1i/2 + rho/4| - y0r/2
xmm2 =simde_mm_subs_epi16(G,y0r_over2);
xmm2 =simde_mm_adds_epi16(xmm2,H); // = |y1r/2 + rho/4| + |y1i/2 + rho*/4| - y0r/2
logmax_den_im0 =simde_mm_max_epi16(logmax_den_im0,xmm2); // max, denominator done
// LLR of first bit [L1(1), L1(2), L1(3), L1(4)]
y0r =simde_mm_adds_epi16(y0r,logmax_num_re0);
y0r =simde_mm_subs_epi16(y0r,logmax_den_re0);
// LLR of second bit [L2(1), L2(2), L2(3), L2(4)]
y0i =simde_mm_adds_epi16(y0i,logmax_num_im0);
y0i =simde_mm_subs_epi16(y0i,logmax_den_im0);
simde_mm_storeu_si128(&stream0_128i_out[i],simde_mm_unpacklo_epi16(y0r,y0i)); // = [L1(1), L2(1), L1(2), L2(2)]
if (i<((length>>1) - 1)) // false if only 2 REs remain
simde_mm_storeu_si128(&stream0_128i_out[i+1],simde_mm_unpackhi_epi16(y0r,y0i));
}
}
...@@ -52,116 +52,6 @@ ...@@ -52,116 +52,6 @@
*/ */
void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations); void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations);
/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream QPSK/QPSK reception.
@param stream0_in Input from channel compensated (MR combined) stream 0
@param stream1_in Input from channel compensated (MR combined) stream 1
@param stream0_out Output from LLR unit for stream0
@param rho01 Cross-correlation between channels (MR combined)
@param length in complex channel outputs*/
void nr_qpsk_qpsk(int16_t *stream0_in,
int16_t *stream1_in,
int16_t *stream0_out,
int16_t *rho01,
int32_t length);
/** \brief This function perform LLR computation for dual-stream (QPSK/QPSK) transmission.
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param rxdataF_comp_i Compensated channel output for interference
@param rho_i Correlation between channel of signal and inteference
@param dlsch_llr llr output
@param symbol OFDM symbol index in sub-frame
@param len
@param first_symbol_flag flag to indicate this is the first symbol of the dlsch
@param nb_rb number of RBs for this allocation
@param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
@param llr128p pointer to pointer to symbol in dlsch_llr*/
int32_t nr_dlsch_qpsk_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
int32_t **rxdataF_comp_i,
int32_t **rho_i,
int16_t *dlsch_llr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adj,
int16_t **llr128p);
/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param dlsch_llr llr output
@param symbol OFDM symbol index in sub-frame
@param len
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
*/
int32_t nr_dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
/**
\brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param dlsch_llr llr output
@param dl_ch_mag Squared-magnitude of channel in each resource element position corresponding to allocation and weighted for
mid-point in 16QAM constellation
@param len
@param symbol OFDM symbol index in sub-frame
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
*/
void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
/**
\brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param dlsch_llr llr output
@param dl_ch_mag Squared-magnitude of channel in each resource element position corresponding to allocation, weighted by first
mid-point of 64-QAM constellation
@param dl_ch_magb Squared-magnitude of channel in each resource element position corresponding to allocation, weighted by second
mid-point of 64-QAM constellation
@param symbol OFDM symbol index in sub-frame
@param len
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
*/
void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
int32_t *dl_ch_magb,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
int32_t *dl_ch_magb,
int32_t *dl_ch_magr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
void nr_dlsch_deinterleaving(uint8_t symbol, void nr_dlsch_deinterleaving(uint8_t symbol,
uint8_t start_symbol, uint8_t start_symbol,
uint16_t L, uint16_t L,
......
add_library(nr_phy_common src/nr_phy_common.c) add_library(nr_phy_common src/nr_phy_common.c)
target_link_libraries(nr_phy_common PRIVATE UTIL) target_link_libraries(nr_phy_common PRIVATE UTIL PHY_COMMON)
target_include_directories(nr_phy_common PUBLIC inc/) target_include_directories(nr_phy_common PUBLIC inc/)
add_library(nr_ue_phy_meas src/nr_ue_phy_meas.c) add_library(nr_ue_phy_meas src/nr_ue_phy_meas.c)
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
#include "PHY/impl_defs_top.h" #include "PHY/impl_defs_top.h"
#include "PHY/TOOLS/tools_defs.h" #include "PHY/TOOLS/tools_defs.h"
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 freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal); 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); 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); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
......
...@@ -21,6 +21,339 @@ ...@@ -21,6 +21,339 @@
#include "nr_phy_common.h" #include "nr_phy_common.h"
#ifdef __aarch64__
#define USE_128BIT
#endif
int16_t saturating_sub(int16_t a, int16_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;
}
}
//----------------------------------------------------------------------------------------------
// QPSK
//----------------------------------------------------------------------------------------------
void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re)
{
c16_t *rxF = (c16_t *)rxdataF_comp;
c16_t *llr32 = (c16_t *)llr;
for (int i = 0; i < nb_re; i++) {
llr32[i].r = rxF[i].r >> 3;
llr32[i].i = rxF[i].i >> 3;
}
}
//----------------------------------------------------------------------------------------------
// 16-QAM
//----------------------------------------------------------------------------------------------
void nr_16qam_llr(int32_t *rxdataF_comp, int32_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;
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);
// 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);
xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0);
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|
*llr_64++ = simde_mm256_extract_epi64(xmm1, 0);
*llr_64++ = simde_mm256_extract_epi64(xmm1, 1);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 0);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 1);
*llr_64++ = simde_mm256_extract_epi64(xmm1, 2);
*llr_64++ = simde_mm256_extract_epi64(xmm1, 3);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 2);
*llr_64++ = simde_mm256_extract_epi64(xmm2, 3);
rxF_256++;
ch_mag++;
}
nb_re &= 0x7;
#endif
simde__m128i *rxF_128 = (simde__m128i *)rxF_256;
simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag;
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);
// 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);
llr_128[0] = simde_mm_unpacklo_epi32(*rxF_128, xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs
llr_128[1] = simde_mm_unpackhi_epi32(*rxF_128, xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs
llr_128 += 2;
rxF_128++;
ch_mag_128++;
}
simde_mm_empty();
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;
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));
}
}
//----------------------------------------------------------------------------------------------
// 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)
{
simde__m256i *rxF = (simde__m256i *)rxdataF_comp;
simde__m256i *ch_maga = (simde__m256i *)ch_mag;
simde__m256i *ch_magb = (simde__m256i *)ch_mag2;
int32_t *llr_32 = (int32_t *)llr;
#ifndef USE_128BIT
simde__m256i xmm0, xmm1, xmm2;
for (int i = 0; i < (nb_re >> 3); i++) {
xmm0 = *rxF;
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
xmm1 = simde_mm256_abs_epi16(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);
xmm2 = simde_mm256_abs_epi16(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|
// xmm2 |3rd 6th 9th 12th 15th 18th 21st 24th|
*llr_32++ = simde_mm256_extract_epi32(xmm0, 0);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 0);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 0);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 1);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 1);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 1);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 2);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 2);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 2);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 3);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 3);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 3);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 4);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 4);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 4);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 5);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 5);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 5);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 6);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 6);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 6);
*llr_32++ = simde_mm256_extract_epi32(xmm0, 7);
*llr_32++ = simde_mm256_extract_epi32(xmm1, 7);
*llr_32++ = simde_mm256_extract_epi32(xmm2, 7);
rxF++;
ch_maga++;
ch_magb++;
}
nb_re &= 0x7;
#endif
simde__m128i *rxF_128 = (simde__m128i *)rxF;
simde__m128i *ch_mag_128 = (simde__m128i *)ch_maga;
simde__m128i *ch_magb_128 = (simde__m128i *)ch_magb;
simde__m64 *llr64 = (simde__m64 *)llr_32;
// Each iteration does 4 RE (gives 24 16bit-llrs)
for (int i = 0; i < (nb_re >> 2); i++) {
simde__m128i xmm0, xmm1, xmm2;
xmm0 = *rxF_128;
xmm1 = simde_mm_abs_epi16(xmm0);
xmm1 = simde_mm_subs_epi16(*ch_mag_128, xmm1);
xmm2 = simde_mm_abs_epi16(xmm1);
xmm2 = simde_mm_subs_epi16(*ch_magb_128, xmm2);
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 0), simde_mm_extract_epi32(xmm0, 0));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 1), simde_mm_extract_epi32(xmm2, 0));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 1), simde_mm_extract_epi32(xmm1, 1));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 2), simde_mm_extract_epi32(xmm0, 2));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 3), simde_mm_extract_epi32(xmm2, 2));
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 3), simde_mm_extract_epi32(xmm1, 3));
rxF_128++;
ch_mag_128++;
ch_magb_128++;
}
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 *)llr64;
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]));
}
simde_mm_empty();
}
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)
{
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
simde__m256i *llr256 = (simde__m256i *)llr;
simde__m256i *ch_maga = (simde__m256i *)ch_mag;
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);
// 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);
xmm1 = simde_mm256_subs_epi16(*ch_magb, xmm1); // contains 16 LLRs
xmm2 = simde_mm256_abs_epi16(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
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
xmm2 = simde_mm256_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2 A6 B6 C6 D6
xmm3 = simde_mm256_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3 A7 B7 C7 D7
*llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1
*llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3
*llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5
*llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7
ch_magc++;
ch_magb++;
ch_maga++;
rxF_256++;
}
nb_re &= 0x7;
#endif
simde__m128i *rxF_128 = (simde__m128i *)rxF_256;
simde__m128i *llr_128 = (simde__m128i *)llr256;
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);
// 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 = simde_mm_subs_epi16(*ch_magb_128, xmm1); // contains 8 LLRs
xmm2 = simde_mm_abs_epi16(xmm1);
xmm2 = simde_mm_subs_epi16(*ch_magc_128, xmm2); // contains 8 LLRs
// rxF[i] A0 A1 A2 A3
// xmm0 B0 B1 B2 B3
// xmm1 C0 C1 C2 C3
// xmm2 D0 D1 D2 D3
xmm3 = simde_mm_unpacklo_epi32(*rxF_128, xmm0); // A0 B0 A1 B1
xmm4 = simde_mm_unpackhi_epi32(*rxF_128, xmm0); // A2 B2 A3 B3
xmm5 = simde_mm_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1
xmm6 = simde_mm_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3
*llr_128++ = simde_mm_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0
*llr_128++ = simde_mm_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1
*llr_128++ = simde_mm_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2
*llr_128++ = simde_mm_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3
rxF_128++;
ch_maga_128++;
ch_magb_128++;
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]));
}
}
simde_mm_empty();
}
void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal) void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal)
{ {
const idft_size_idx_t idft_size = get_idft(ofdm_symbol_size); const idft_size_idx_t idft_size = get_idft(ofdm_symbol_size);
......
...@@ -509,7 +509,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -509,7 +509,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
int32_t ptrs_re_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT]; int32_t ptrs_re_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_re_per_slot, 0, sizeof(ptrs_re_per_slot)); memset(ptrs_re_per_slot, 0, sizeof(ptrs_re_per_slot));
const uint32_t rx_size_symbol = dlsch[0].dlsch_config.number_rbs * NR_NB_SC_PER_RB; const uint32_t rx_size_symbol = (dlsch[0].dlsch_config.number_rbs * NR_NB_SC_PER_RB + 15) & ~15;
__attribute__((aligned(32))) int32_t rxdataF_comp[dlsch[0].Nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT]; __attribute__((aligned(32))) int32_t rxdataF_comp[dlsch[0].Nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT];
memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); memset(rxdataF_comp, 0, sizeof(rxdataF_comp));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment