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
${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_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_prach_common.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
......
......@@ -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/sss_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_transport_proto_ue.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c \
......
......@@ -31,357 +31,13 @@
*/
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_common.h"
#include "PHY/sse_intrin.h"
#include "PHY/impl_defs_top.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_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,
int32_t *ul_ch_mag,
int32_t *ul_ch_magb,
......@@ -391,39 +47,21 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp,
uint8_t symbol,
uint8_t mod_order)
{
switch(mod_order){
switch(mod_order) {
case 2:
nr_ulsch_qpsk_llr(rxdataF_comp,
ulsch_llr,
nb_re,
symbol);
nr_qpsk_llr(rxdataF_comp, ulsch_llr, nb_re);
break;
case 4:
nr_ulsch_16qam_llr(rxdataF_comp,
ul_ch_mag,
ulsch_llr,
nb_re,
symbol);
nr_16qam_llr(rxdataF_comp, ul_ch_mag, ulsch_llr, nb_re);
break;
case 6:
nr_ulsch_64qam_llr(rxdataF_comp,
ul_ch_mag,
ul_ch_magb,
ulsch_llr,
nb_re,
symbol);
nr_64qam_llr(rxdataF_comp, ul_ch_mag, ul_ch_magb, ulsch_llr, nb_re);
break;
case 8:
nr_ulsch_256qam_llr(rxdataF_comp,
ul_ch_mag,
ul_ch_magb,
ul_ch_magc,
ulsch_llr,
nb_re,
symbol);
nr_256qam_llr(rxdataF_comp, ul_ch_mag, ul_ch_magb, ul_ch_magc, ulsch_llr, nb_re);
break;
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;
}
}
......
......@@ -25,20 +25,9 @@
#include <algorithm>
#include <numeric>
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_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);
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);
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);
struct configmodule_interface_s;
struct configmodule_interface_s *uniqCfg = NULL;
......@@ -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++) {
int16_t real = rxdataF_comp[i].r;
int16_t imag = rxdataF_comp[i].i;
int16_t mag_real = ul_ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
ulsch_llr[4 * i] = real;
ulsch_llr[4 * i + 1] = imag;
ulsch_llr[4 * i + 2] = saturating_sub(mag_real, std::abs(real));
ulsch_llr[4 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
int16_t mag_real = ch_mag_i16[2 * i];
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));
}
}
void nr_ulsch_64qam_llr_ref(c16_t *rxdataF_comp,
int32_t *ul_ch_mag,
int32_t *ul_ch_magb,
int16_t *ulsch_llr,
uint32_t nb_re,
uint8_t symbol)
void nr_64qam_llr_ref(c16_t *rxdataF_comp,
int32_t *ch_mag,
int32_t *ch_magb,
int16_t *llr,
uint32_t nb_re)
{
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag;
int16_t *ul_ch_magb_i16 = (int16_t *)ul_ch_magb;
int16_t *ch_mag_i16 = (int16_t *)ch_mag;
int16_t *ch_magb_i16 = (int16_t *)ch_magb;
for (auto i = 0U; i < nb_re; i++) {
int16_t real = rxdataF_comp[i].r;
int16_t imag = rxdataF_comp[i].i;
int16_t mag_real = ul_ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
ulsch_llr[6 * i] = real;
ulsch_llr[6 * i + 1] = imag;
ulsch_llr[6 * i + 2] = saturating_sub(mag_real, std::abs(real));
ulsch_llr[6 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
int16_t mag_realb = ul_ch_magb_i16[2 * i];
int16_t mag_imagb = ul_ch_magb_i16[2 * i + 1];
ulsch_llr[6 * i + 4] = saturating_sub(mag_realb, std::abs(ulsch_llr[6 * i + 2]));
ulsch_llr[6 * i + 5] = saturating_sub(mag_imagb, std::abs(ulsch_llr[6 * i + 3]));
int16_t mag_real = ch_mag_i16[2 * i];
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));
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]));
}
}
void nr_ulsch_256qam_llr_ref(c16_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)
void nr_256qam_llr_ref(c16_t *rxdataF_comp,
int32_t *ch_mag,
int32_t *ch_magb,
int32_t *ch_magc,
int16_t *llr,
uint32_t nb_re)
{
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag;
int16_t *ul_ch_magb_i16 = (int16_t *)ul_ch_magb;
int16_t *ul_ch_magc_i16 = (int16_t *)ul_ch_magc;
int16_t *ch_mag_i16 = (int16_t *)ch_mag;
int16_t *ch_magb_i16 = (int16_t *)ch_magb;
int16_t *ch_magc_i16 = (int16_t *)ch_magc;
for (auto i = 0U; i < nb_re; i++) {
int16_t real = rxdataF_comp[i].r;
int16_t imag = rxdataF_comp[i].i;
int16_t mag_real = ul_ch_mag_i16[2 * i];
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
ulsch_llr[8 * i] = real;
ulsch_llr[8 * i + 1] = imag;
ulsch_llr[8 * i + 2] = saturating_sub(mag_real, std::abs(real));
ulsch_llr[8 * i + 3] = saturating_sub(mag_imag, std::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[8 * i + 4] = saturating_sub(magb_real, std::abs(ulsch_llr[8 * i + 2]));
ulsch_llr[8 * i + 5] = saturating_sub(magb_imag, std::abs(ulsch_llr[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[8 * i + 6] = saturating_sub(magc_real, std::abs(ulsch_llr[8 * i + 4]));
ulsch_llr[8 * i + 7] = saturating_sub(magc_imag, std::abs(ulsch_llr[8 * i + 5]));
int16_t mag_real = ch_mag_i16[2 * i];
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));
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]));
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]));
}
}
......@@ -149,21 +136,21 @@ void test_function_16_qam(AlignedVector512<uint32_t> 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<uint64_t> ulsch_llr_ref;
ulsch_llr_ref.resize(nb_re);
std::fill(ulsch_llr_ref.begin(), ulsch_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);
AlignedVector512<uint64_t> llr_ref;
llr_ref.resize(nb_re);
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<uint64_t> ulsch_llr;
ulsch_llr.resize(nb_re);
std::fill(ulsch_llr.begin(), ulsch_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);
AlignedVector512<uint64_t> llr;
llr.resize(nb_re);
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(ulsch_llr_ref[i], ulsch_llr[i])
<< "Mismatch 16qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[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++;
}
}
......@@ -178,31 +165,29 @@ void test_function_64_qam(AlignedVector512<uint32_t> 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<uint32_t> ulsch_llr_ref;
ulsch_llr_ref.resize(nb_re * 3);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
nr_ulsch_64qam_llr_ref((c16_t *)rf_data.data(),
AlignedVector512<uint32_t> llr_ref;
llr_ref.resize(nb_re * 3);
std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_64qam_llr_ref((c16_t *)rf_data.data(),
(int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(),
(int16_t *)ulsch_llr_ref.data(),
nb_re,
0);
AlignedVector512<uint32_t> ulsch_llr;
ulsch_llr.resize(nb_re * 3);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
nr_ulsch_64qam_llr((int32_t *)rf_data.data(),
(int16_t *)llr_ref.data(),
nb_re);
AlignedVector512<uint32_t> llr;
llr.resize(nb_re * 3);
std::fill(llr.begin(), llr.end(), 0);
nr_64qam_llr((int32_t *)rf_data.data(),
(int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(),
(int16_t *)ulsch_llr.data(),
nb_re,
0);
(int16_t *)llr.data(),
nb_re);
int num_errors = 0;
for (auto i = 0U; i < nb_re * 3; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
<< "Mismatch 64qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[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++;
}
}
......@@ -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_b_data = generate_random_uint16(nb_re * 2);
auto magnitude_c_data = generate_random_uint16(nb_re * 2);
AlignedVector512<uint32_t> ulsch_llr_ref;
ulsch_llr_ref.resize(nb_re * 4);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
nr_ulsch_256qam_llr_ref((c16_t *)rf_data.data(),
AlignedVector512<uint32_t> llr_ref;
llr_ref.resize(nb_re * 4);
std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_256qam_llr_ref((c16_t *)rf_data.data(),
(int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr_ref.data(),
nb_re,
0);
AlignedVector512<uint32_t> ulsch_llr;
ulsch_llr.resize(nb_re * 4);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
nr_ulsch_256qam_llr((int32_t *)rf_data.data(),
(int16_t *)llr_ref.data(),
nb_re);
AlignedVector512<uint32_t> llr;
llr.resize(nb_re * 4);
std::fill(llr.begin(), llr.end(), 0);
nr_256qam_llr((int32_t *)rf_data.data(),
(int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr.data(),
nb_re,
0);
(int16_t *)llr.data(),
nb_re);
int num_errors = 0;
for (auto i = 0U; i < nb_re * 4; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
<< "Mismatch 256qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[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++;
}
}
......@@ -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_b_data = {2, 2, 2, 2};
AlignedVector512<int16_t> magnitude_c_data = {3, 3, 3, 3};
AlignedVector512<int16_t> ulsch_llr_ref;
ulsch_llr_ref.resize(2 * 8);
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
nr_ulsch_256qam_llr_ref((c16_t *)rf_data.data(),
AlignedVector512<int16_t> llr_ref;
llr_ref.resize(2 * 8);
std::fill(llr_ref.begin(), llr_ref.end(), 0);
nr_256qam_llr_ref((c16_t *)rf_data.data(),
(int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr_ref.data(),
2,
0);
AlignedVector512<int16_t> ulsch_llr;
ulsch_llr.resize(2 * 8);
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
nr_ulsch_256qam_llr((int32_t *)rf_data.data(),
(int16_t *)llr_ref.data(),
2);
AlignedVector512<int16_t> llr;
llr.resize(2 * 8);
std::fill(llr.begin(), llr.end(), 0);
nr_256qam_llr((int32_t *)rf_data.data(),
(int32_t *)magnitude_data.data(),
(int32_t *)magnitude_b_data.data(),
(int32_t *)magnitude_c_data.data(),
(int16_t *)ulsch_llr.data(),
2,
0);
(int16_t *)llr.data(),
2);
printf("\nDUT:\n");
for (auto i = 0U; i < 2; i++) {
printf("%d %d %d %d %d %d %d %d\n",
ulsch_llr[i * 8],
ulsch_llr[i * 8 + 1],
ulsch_llr[i * 8 + 2],
ulsch_llr[i * 8 + 3],
ulsch_llr[i * 8 + 4],
ulsch_llr[i * 8 + 5],
ulsch_llr[i * 8 + 6],
ulsch_llr[i * 8 + 7]);
llr[i * 8],
llr[i * 8 + 1],
llr[i * 8 + 2],
llr[i * 8 + 3],
llr[i * 8 + 4],
llr[i * 8 + 5],
llr[i * 8 + 6],
llr[i * 8 + 7]);
}
printf("\nREF:\n");
for (auto i = 0U; i < 2; i++) {
printf("%d %d %d %d %d %d %d %d\n",
ulsch_llr_ref[i * 8],
ulsch_llr_ref[i * 8 + 1],
ulsch_llr_ref[i * 8 + 2],
ulsch_llr_ref[i * 8 + 3],
ulsch_llr_ref[i * 8 + 4],
ulsch_llr_ref[i * 8 + 5],
ulsch_llr_ref[i * 8 + 6],
ulsch_llr_ref[i * 8 + 7]);
llr_ref[i * 8],
llr_ref[i * 8 + 1],
llr_ref[i * 8 + 2],
llr_ref[i * 8 + 3],
llr_ref[i * 8 + 4],
llr_ref[i * 8 + 5],
llr_ref[i * 8 + 6],
llr_ref[i * 8 + 7]);
}
int num_errors = 0;
for (auto i = 0U; i < 2 * 8; i++) {
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
<< "Mismatch 256qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
if (ulsch_llr_ref[i] != ulsch_llr[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++;
}
}
......
......@@ -1633,7 +1633,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
nr_slot_rx,
symbol,
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,
(int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]);
......@@ -1654,21 +1654,21 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
}
#ifdef DEBUG_DL_PTRS
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
/*------------------------------------------------------------------------------------------------------- */
/* 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 */
/* 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
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i);
#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],
(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),
15);
}// if not DMRS Symbol
......
......@@ -28,6 +28,7 @@
* \note
* \warning
*/
#include "nr_phy_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/phy_extern.h"
#include "nr_transport_proto_ue.h"
......@@ -101,27 +102,20 @@ static void nr_dlsch_layer_demapping(int16_t *llr_cw[2],
int16_t llr_layers[][sz]);
/* compute LLR */
static int nr_dlsch_llr(uint32_t rx_size_symbol,
int nbRx,
uint 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 dl_ch_mag[rx_size_symbol],
int32_t dl_ch_magb[rx_size_symbol],
int32_t dl_ch_magr[rx_size_symbol],
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
unsigned char harq_pid,
unsigned char first_symbol_flag,
unsigned char 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]);
static void nr_dlsch_llr(uint32_t rx_size_symbol,
int nbRx,
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],
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
unsigned char symbol,
uint32_t len,
NR_UE_DLSCH_t dlsch[2],
uint32_t llr_offset_symbol);
/** \fn nr_dlsch_extract_rbs
\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,
uint8_t pilots,
uint32_t len,
unsigned short nb_rb);
void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
short n_tx,
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],
unsigned char symbol,
unsigned short nb_rb,
int length);
static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
short n_tx,
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],
unsigned char symbol,
int length);
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,
dl_ch_magb,
dl_ch_magr,
symbol,
nb_rb_pdsch,
nb_re_pdsch);
if (nl >= 2) // Apply MMSE for 2, 3, and 4 Tx layers
nr_dlsch_mmse(rx_size_symbol,
......@@ -628,7 +620,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
/* 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 nbSymb = 0;
int pduBitmap = 0;
......@@ -656,10 +648,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
(nb_rb_pdsch * 12),
dlsch[0].rnti,
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 */
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;
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,
}
int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size];
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;
for(int i = startSymbIdx; i < startSymbIdx + nbSymb; i++) {
/* Calculate LLR's for each symbol */
start_meas_nr_ue_phy(ue, DLSCH_LLR_STATS);
nr_dlsch_llr(rx_size_symbol,
nbRx,
rx_llr_layer_size,
layer_llr,
frame_parms,
rxdataF_comp,
dl_ch_mag[0][0],
dl_ch_magb[0][0],
dl_ch_magr[0][0],
dlsch0_harq,
dlsch1_harq,
harq_pid,
first_symbol_flag,
i,
nb_rb_pdsch,
codeword_TB0,
codeword_TB1,
dl_valid_re[i - 1],
nr_slot_rx,
dl_valid_re[i],
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);
}
start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
nr_dlsch_layer_demapping(llr,
dlsch[0].Nl,
dlsch[0].dlsch_config.qamModOrder,
dlsch_config->qamModOrder,
G,
codeword_TB0,
codeword_TB1,
......@@ -876,15 +858,13 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol,
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++) {
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_mag128b = (simde__m128i *)dl_ch_magb[l][aarx];
dl_ch_mag128r = (simde__m128i *)dl_ch_magr[l][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++) {
if (mod_order > 2) {
......@@ -1259,37 +1239,34 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz,
}
}
void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
short n_tx,
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],
unsigned char symbol,
unsigned short nb_rb,
int length) {
unsigned char aatx, aarx;
int i;
static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
short n_tx,
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],
unsigned char symbol,
int length)
{
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);
if (n_rx>1) {
for (aatx=0; aatx<n_tx; aatx++) {
rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[aatx][0] + symbol * nb_rb * 12);
if (n_rx > 1) {
for (int aatx = 0; aatx < n_tx; aatx++) {
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_0b = (simde__m128i *)dl_ch_magb[aatx][0];
dl_ch_mag128_0r = (simde__m128i *)dl_ch_magr[aatx][0];
for (aarx=1; aarx<n_rx; aarx++) {
rxdataF_comp128_1 = (simde__m128i *)(rxdataF_comp[aatx][aarx] + symbol * nb_rb * 12);
for (int aarx = 1; aarx < n_rx; aarx++) {
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_1b = (simde__m128i *)dl_ch_magb[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)
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]);
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]);
......@@ -1298,14 +1275,14 @@ void nr_dlsch_detection_mrc(uint32_t rx_size_symbol,
}
}
#ifdef DEBUG_DLSCH_DEMOD
for (i=0; i<nb_rb_0*3; i++) {
printf("symbol%d RB %d\n",symbol,i/3);
rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[0][0] + symbol * nb_rb * 12);
rxdataF_comp128_1 = (simde__m128i *)(rxdataF_comp[0][n_rx] + symbol * nb_rb * 12);
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]);
// 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]);
for (int i = 0; i < nb_rb_0 * 3; i++) {
printf("symbol%d RB %d\n", symbol,i / 3);
rxdataF_comp128_0 = (simde__m128i *)(rxdataF_comp[0][0] + symbol * rx_size_symbol);
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 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 mag0b = %d = %d \n",((int16_t*)&dl_ch_mag128_0b[0])[0],((int16_t*)&dl_ch_mag128_0b[0])[1]);
}
#endif
if (rho) {
......@@ -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,
int nbRx,
uint 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 dl_ch_mag[rx_size_symbol],
int32_t dl_ch_magb[rx_size_symbol],
int32_t dl_ch_magr[rx_size_symbol],
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
unsigned char harq_pid,
unsigned char first_symbol_flag,
unsigned char 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])
static void nr_dlsch_llr(uint32_t rx_size_symbol,
int nbRx,
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],
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
unsigned char symbol,
uint32_t len,
NR_UE_DLSCH_t dlsch[2],
uint32_t llr_offset_symbol)
{
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) {
case 2 :
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);
for(int l = 0; l < dlsch[0].Nl; l++)
nr_qpsk_llr(&rxdataF_comp[l][0][symbol * rx_size_symbol], layer_llr[l] + llr_offset_symbol, len);
break;
case 4 :
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);
for(int l = 0; l < dlsch[0].Nl; l++)
nr_16qam_llr(&rxdataF_comp[l][0][symbol * rx_size_symbol], dl_ch_mag, layer_llr[l] + llr_offset_symbol, len);
break;
case 6 :
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;
case 8:
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;
default:
LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
return(-1);
AssertFatal(false, "Unknown mod_order!!!!\n");
break;
}
......@@ -1937,27 +1898,25 @@ static int nr_dlsch_llr(uint32_t rx_size_symbol,
if (dlsch1_harq) {
switch (dlsch[1].dlsch_config.qamModOrder) {
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;
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;
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;
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;
default:
LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
return(-1);
AssertFatal(false, "Unknown mod_order!!!!\n");
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 @@
*/
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,
uint8_t start_symbol,
uint16_t L,
......
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/)
add_library(nr_ue_phy_meas src/nr_ue_phy_meas.c)
......
......@@ -24,6 +24,10 @@
#include "PHY/impl_defs_top.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 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);
......
......@@ -21,6 +21,339 @@
#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)
{
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,
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));
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];
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