Merge remote-tracking branch 'origin/ue-simplify-dlsch-llr' into integration_2026_w13 (!3851)

Bugfix in UE DLSCH LLR functions

Closes #1044
Fix bug in PTRS compensation.
This commit is contained in:
Jaroslava Fiedlerova
2026-03-23 17:13:03 +01:00
16 changed files with 792 additions and 907 deletions
+11
View File
@@ -20,6 +20,17 @@ extern "C" {
#define sizeofArray(a) (sizeof(a)/sizeof(*(a)))
#define CHECK_INDEX(ARRAY, INDEX) assert((INDEX) < sizeofArray(ARRAY))
#define GET_ARRAY_MAX(arr, size, max_val) \
do { \
DevAssert((size) > 0); \
(max_val) = (arr)[0]; \
for (size_t _i = 1; _i < (size); _i++) { \
if ((arr)[_i] > (max_val)) { \
(max_val) = (arr)[_i]; \
} \
} \
} while (0)
// Prevent double evaluation in max macro
#define cmax(a,b) ({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
+2 -2
View File
@@ -204,11 +204,11 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
pusch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->rxdataF_comp = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->rxdataF_comp = (c16_t **)malloc16(n_buf * sizeof(*pusch->rxdataF_comp));
for (int i = 0; i < n_buf; i++) {
pusch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size * fp->symbols_per_slot);
pusch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->symbols_per_slot); // symbols per slot
pusch->rxdataF_comp[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
pusch->rxdataF_comp[i] = (c16_t *)malloc16_clear(sizeof(**pusch->rxdataF_comp) * nb_re_pusch2 * fp->symbols_per_slot);
}
for (int i = 0; i < max_ul_mimo_layers; i++) {
@@ -725,7 +725,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
*nb_rb,
rel15_ul->rnti,
frame_parms->ofdm_symbol_size,
(int16_t *)&pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
&pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
gold,
(int16_t *)&phase_per_symbol[symbol],
ptrs_re_symbol);
@@ -754,9 +754,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
#ifdef DEBUG_UL_PTRS
printf("[PHY][UL][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 *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
rotate_cpx_vector(&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
&phase_per_symbol[i],
(c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
((*nb_rb) * NR_NB_SC_PER_RB),
15);
} // if not DMRS Symbol
+3 -7
View File
@@ -195,7 +195,7 @@ void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
uint16_t nb_rb,
uint16_t rnti,
uint16_t ofdm_symbol_size,
int16_t *rxF_comp,
c16_t *rxF_comp,
const uint32_t *gold_seq,
int16_t *error_est,
int32_t *ptrs_sc)
@@ -223,15 +223,11 @@ void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
0,// start_re is 0 here
ofdm_symbol_size);
if(is_ptrs_re) {
dmrs_comp_p[re_cnt].r = rxF_comp[re *2];
dmrs_comp_p[re_cnt].i = rxF_comp[(re *2)+1];
re_cnt++;
dmrs_comp_p[re_cnt++] = rxF_comp[re];
}
else {
/* Skip PTRS symbols and keep data in a continuous vector */
rxF_comp[cnt *2]= rxF_comp[re *2];
rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1];
cnt++;
rxF_comp[cnt++] = rxF_comp[re];
}
}/* RE loop */
/* update the total ptrs RE in a symbol */
+1 -1
View File
@@ -80,7 +80,7 @@ void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
uint16_t nb_rb,
uint16_t rnti,
uint16_t ofdm_symbol_size,
int16_t *rxF_comp,
c16_t *rxF_comp,
const uint32_t *gold_seq,
int16_t *error_est,
int32_t *ptrs_sc);
@@ -159,7 +159,7 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in,
@param symbol OFDM symbol index in sub-frame
@param mod_order modulation order
*/
void nr_ulsch_compute_llr(int32_t *rxdataF_comp,
void nr_ulsch_compute_llr(c16_t *rxdataF_comp,
c16_t *ul_ch_mag,
c16_t *ul_ch_magb,
c16_t *ul_ch_magc,
@@ -181,7 +181,7 @@ static void nr_ulsch_channel_compensation(uint32_t buffer_length,
c16_t ul_ch_maga[][buffer_length],
c16_t ul_ch_magb[][buffer_length],
c16_t ul_ch_magc[][buffer_length],
int32_t **rxComp,
c16_t **rxComp,
int nb_layers,
c16_t rho[][nb_layers][buffer_length],
nfapi_nr_pusch_pdu_t *rel15_ul,
@@ -472,7 +472,7 @@ static void nr_ulsch_construct_HhH_elements(c16_t *conjch00_ch00,
}
// MMSE Rx function: nr_ulsch_mmse_2layers()
static uint8_t nr_ulsch_mmse_2layers(int **rxdataF_comp,
static uint8_t nr_ulsch_mmse_2layers(c16_t **rxdataF_comp,
uint32_t buffer_length,
int nb_rx_ant,
c16_t ul_ch_mag[][buffer_length],
@@ -948,13 +948,13 @@ static void inner_rx(PHY_VARS_gNB *gNB,
if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) {
if (rel15_ul->qam_mod_order > 2)
nr_freq_equalization(frame_parms,
(c16_t *)&pusch_vars->rxdataF_comp[0][symbol * buffer_length],
&pusch_vars->rxdataF_comp[0][symbol * buffer_length],
rxF_ch_maga[0],
rxF_ch_magb[0],
symbol,
pusch_vars->ul_valid_re_per_slot[symbol],
rel15_ul->qam_mod_order);
nr_idft(&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]);
nr_idft((int32_t *)&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]);
}
if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
nr_pusch_ptrs_processing(gNB,
@@ -971,8 +971,8 @@ static void inner_rx(PHY_VARS_gNB *gNB,
if (rel15_ul->qam_mod_order <= 6) {
nr_ulsch_compute_ML_llr(pusch_vars,
symbol,
(c16_t *)&pusch_vars->rxdataF_comp[0][symbol * buffer_length],
(c16_t *)&pusch_vars->rxdataF_comp[nb_rx_ant][symbol * buffer_length],
&pusch_vars->rxdataF_comp[0][symbol * buffer_length],
&pusch_vars->rxdataF_comp[nb_rx_ant][symbol * buffer_length],
rxF_ch_maga[0],
rxF_ch_maga[1],
llr[0],
@@ -983,7 +983,7 @@ static void inner_rx(PHY_VARS_gNB *gNB,
rel15_ul->qam_mod_order);
}
else {
nr_ulsch_mmse_2layers((int32_t **)pusch_vars->rxdataF_comp,
nr_ulsch_mmse_2layers(pusch_vars->rxdataF_comp,
buffer_length,
nb_rx_ant,
rxF_ch_maga,
@@ -1000,7 +1000,7 @@ static void inner_rx(PHY_VARS_gNB *gNB,
}
if (nb_layer != 2 || rel15_ul->qam_mod_order > 6)
for (int aatx = 0; aatx < nb_layer; aatx++)
nr_ulsch_compute_llr((int32_t *)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * buffer_length],
nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * buffer_length],
rxF_ch_maga[aatx],
rxF_ch_magb[aatx],
rxF_ch_magc[aatx],
@@ -38,7 +38,7 @@
#define USE_128BIT
#endif
void nr_ulsch_compute_llr(int32_t *rxdataF_comp,
void nr_ulsch_compute_llr(c16_t *rxdataF_comp,
c16_t *ul_ch_mag,
c16_t *ul_ch_magb,
c16_t *ul_ch_magc,
@@ -1384,7 +1384,8 @@ void nr_pdsch_ptrs_processing(int nbRx,
c16_t ptrs_phase_per_slot[][14],
int32_t ptrs_re_per_slot[][14],
uint32_t rx_size_symbol,
int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms,
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
@@ -1477,7 +1478,7 @@ void nr_pdsch_ptrs_processing(int nbRx,
*nb_rb,
rnti,
frame_parms->ofdm_symbol_size,
(int16_t *)(rxdataF_comp[0][aarx] + symbol * rx_size_symbol),
rxdataF_comp[symbol][0][aarx],
gold,
(int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]);
@@ -1510,9 +1511,9 @@ void nr_pdsch_ptrs_processing(int nbRx,
#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 * rx_size_symbol],
rotate_cpx_vector(rxdataF_comp[i][0][aarx],
&phase_per_symbol[i],
(c16_t *)&rxdataF_comp[0][aarx][i * rx_size_symbol],
rxdataF_comp[i][0][aarx],
((*nb_rb) * NR_NB_SC_PER_RB),
15);
}// if not DMRS Symbol
@@ -141,7 +141,8 @@ void nr_pdsch_ptrs_processing(int nbRx,
c16_t ptrs_phase_per_slot[][14],
int32_t ptrs_re_per_slot[][14],
uint32_t rx_size_symbol,
int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms,
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
File diff suppressed because it is too large Load Diff
@@ -309,16 +309,16 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
unsigned char harq_pid,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size],
int layer_llr_size,
int16_t layer_llr[][layer_llr_size],
int16_t *llr[2],
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT],
int32_t *log2_maxh,
int rx_size_symbol,
int nbRx,
int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT],
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G,
+1 -1
View File
@@ -236,7 +236,7 @@ typedef struct {
/// \brief Holds the compensated signal.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t **rxdataF_comp;
c16_t **rxdataF_comp;
/// \f$\log_2(\max|H_i|^2)\f$
int16_t log2_maxh;
/// measured RX power based on DRS
@@ -349,10 +349,10 @@ typedef struct {
} csi_mapping_parms_t;
csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1);
int get_cdm_group_size(int cdm_type);
void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re);
void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re);
void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t *llr, uint32_t nb_re);
void nr_256qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, c16_t *ch_mag3, int16_t *llr, uint32_t nb_re);
void nr_qpsk_llr(const c16_t *rxdataF_comp, int16_t *llr, uint32_t nb_re);
void nr_16qam_llr(const c16_t *rxdataF_comp, const c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re);
void nr_64qam_llr(const c16_t *rxdataF_comp, const c16_t *ch_mag, const c16_t *ch_mag2, int16_t *llr, uint32_t nb_re);
void nr_256qam_llr(const c16_t *rxdataF_comp, const c16_t *ch_mag, const c16_t *ch_mag2, const c16_t *ch_mag3, int16_t *llr, uint32_t nb_re);
void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal);
void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay);
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
@@ -66,9 +66,9 @@ static inline c16_t saturating_sub(c16_t a, c16_t b)
//----------------------------------------------------------------------------------------------
// QPSK
//----------------------------------------------------------------------------------------------
void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re)
void nr_qpsk_llr(const c16_t *rxdataF_comp, int16_t *llr, uint32_t nb_re)
{
c16_t *rxF = (c16_t *)rxdataF_comp;
const c16_t *rxF = rxdataF_comp;
c16_t *llr32 = (c16_t *)llr;
for (int i = 0; i < nb_re; i++) {
llr32[i].r = rxF[i].r >> 4;
@@ -80,7 +80,7 @@ void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re)
// 16-QAM
//----------------------------------------------------------------------------------------------
void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re)
void nr_16qam_llr(const c16_t *rxdataF_comp, const c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re)
{
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
simde__m256i *ch_mag256 = (simde__m256i *)ch_mag_in;
@@ -148,7 +148,7 @@ void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_
// 64-QAM
//----------------------------------------------------------------------------------------------
void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t *llr, uint32_t nb_re)
void nr_64qam_llr(const c16_t *rxdataF_comp, const c16_t *ch_mag, const c16_t *ch_mag2, int16_t *llr, uint32_t nb_re)
{
simde__m256i *rxF = (simde__m256i *)rxdataF_comp;
@@ -251,7 +251,7 @@ void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t
}
}
void nr_256qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, c16_t *ch_mag3, int16_t *llr, uint32_t nb_re)
void nr_256qam_llr(const c16_t *rxdataF_comp, const c16_t *ch_mag, const c16_t *ch_mag2, const c16_t *ch_mag3, int16_t *llr, uint32_t nb_re)
{
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
simde__m256i *llr256 = (simde__m256i *)llr;
+192 -169
View File
@@ -571,197 +571,220 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
int nr_slot_rx = proc->nr_slot_rx;
// We handle only one CW now
if (!(NR_MAX_NB_LAYERS>4)) {
NR_UE_DLSCH_t *dlsch0 = &dlsch[0];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg = &dlsch0->dlsch_config;
int harq_pid = dlschCfg->harq_process_nbr;
// dlsch0_harq contains the previous transmissions data for this harq pid
NR_DL_UE_HARQ_t *dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
if (NR_MAX_NB_LAYERS > 4) {
LOG_E(NR_PHY, "Handling of more than one CW not implemented\n");
return -1;
}
NR_UE_DLSCH_t *dlsch0 = &dlsch[0];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg = &dlsch0->dlsch_config;
int harq_pid = dlschCfg->harq_process_nbr;
// dlsch0_harq contains the previous transmissions data for this harq pid
NR_DL_UE_HARQ_t *dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
freq_alloc_bitmap_t freq_alloc = {0};
if (dlschCfg->resource_alloc == 0) {
int alloc_size = (dlschCfg->BWPSize / 8) + (dlschCfg->BWPSize % 8 > 0);
freq_alloc = set_start_end_from_bitmap(dlschCfg->BWPSize, alloc_size, dlschCfg->rb_bitmap);
} else
freq_alloc = set_bitmap_from_start_size(dlschCfg->start_rb, dlschCfg->number_rbs);
freq_alloc_bitmap_t freq_alloc = {0};
if (dlschCfg->resource_alloc == 0) {
int alloc_size = (dlschCfg->BWPSize / 8) + (dlschCfg->BWPSize % 8 > 0);
freq_alloc = set_start_end_from_bitmap(dlschCfg->BWPSize, alloc_size, dlschCfg->rb_bitmap);
} else
freq_alloc = set_bitmap_from_start_size(dlschCfg->start_rb, dlschCfg->number_rbs);
LOG_D(PHY,
"[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, start RB %d, end RB %d, symbol_start %d, nb_symbols %d, DMRS mask "
"%x, Nl %d\n",
ue->Mod_id,
frame_rx,
nr_slot_rx,
harq_pid,
dlsch0_harq->status,
dlschCfg->BWPStart,
freq_alloc.start[0],
freq_alloc.end[freq_alloc.num_blocks - 1],
dlschCfg->start_symbol,
dlschCfg->number_symbols,
dlschCfg->dlDmrsSymbPos,
dlsch0->Nl);
LOG_D(PHY,
"[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, start RB %d, end RB %d, symbol_start %d, nb_symbols "
"%d, DMRS mask "
"%x, Nl %d\n",
ue->Mod_id,
frame_rx,
nr_slot_rx,
harq_pid,
dlsch0_harq->status,
dlschCfg->BWPStart,
freq_alloc.start[0],
freq_alloc.end[freq_alloc.num_blocks - 1],
dlschCfg->start_symbol,
dlschCfg->number_symbols,
dlschCfg->dlDmrsSymbPos,
dlsch0->Nl);
const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size + 15) / 16) * 16;
fourDimArray_t *toFree = NULL;
allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch0->Nl, pdsch_est_size, false);
const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size + 15) / 16) * 16;
fourDimArray_t *toFree = NULL;
allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch0->Nl, pdsch_est_size, false);
c16_t ptrs_phase_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_phase_per_slot, 0, sizeof(ptrs_phase_per_slot));
c16_t ptrs_phase_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_phase_per_slot, 0, sizeof(ptrs_phase_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));
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 = (freq_alloc.num_rbs * NR_NB_SC_PER_RB + 15) & ~15;
fourDimArray_t *toFree2 = NULL;
allocCast3D(rxdataF_comp,
int32_t,
toFree2,
dlsch[0].Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol * ue->frame_parms.symbols_per_slot,
false);
const uint32_t rx_size_symbol = (freq_alloc.num_rbs * NR_NB_SC_PER_RB + 15) & ~15;
fourDimArray_t *toFree2 = NULL;
allocCast4D(rxdataF_comp,
c16_t,
toFree2,
ue->frame_parms.symbols_per_slot,
dlsch[0].Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
uint32_t nvar = 0;
uint32_t nvar = 0;
start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) {
if (dlschCfg->dlDmrsSymbPos & (1 << m)) {
for (int nl = 0; nl < dlsch0->Nl; nl++) { //for MIMO Config: it shall loop over no_layers
LOG_D(PHY,"PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m);
uint32_t nvar_tmp = 0;
nr_pdsch_channel_estimation(ue,
proc,
dlschCfg,
&freq_alloc,
nl,
get_dmrs_port(nl, dlschCfg->dmrs_ports),
m,
pdsch_est_size,
pdsch_dl_ch_estimates,
ue->frame_parms.samples_per_slot_wCP,
rxdataF,
&nvar_tmp);
nvar += nvar_tmp;
start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) {
if (dlschCfg->dlDmrsSymbPos & (1 << m)) {
for (int nl = 0; nl < dlsch0->Nl; nl++) { // for MIMO Config: it shall loop over no_layers
LOG_D(PHY, "PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m);
uint32_t nvar_tmp = 0;
nr_pdsch_channel_estimation(ue,
proc,
dlschCfg,
&freq_alloc,
nl,
get_dmrs_port(nl, dlschCfg->dmrs_ports),
m,
pdsch_est_size,
pdsch_dl_ch_estimates,
ue->frame_parms.samples_per_slot_wCP,
rxdataF,
&nvar_tmp);
nvar += nvar_tmp;
#if 0
///LOG_M: the channel estimation
char filename[100];
for (uint8_t aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", frame_rx, nr_slot_rx, m, nl, aarx);
int **dl_ch_estimates = ue->pdsch_vars[gNB_id]->dl_ch_estimates;
LOG_M(filename,"channel_F",&dl_ch_estimates[nl*ue->frame_parms.nb_antennas_rx+aarx][ue->frame_parms.ofdm_symbol_size*m],ue->frame_parms.ofdm_symbol_size, 1, 1);
}
#endif
///LOG_M: the channel estimation
char filename[100];
for (uint8_t aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", frame_rx, nr_slot_rx, m, nl, aarx);
int **dl_ch_estimates = ue->pdsch_vars[gNB_id]->dl_ch_estimates;
LOG_M(filename,"channel_F",&dl_ch_estimates[nl*ue->frame_parms.nb_antennas_rx+aarx][ue->frame_parms.ofdm_symbol_size*m],ue->frame_parms.ofdm_symbol_size, 1, 1);
}
#endif
}
}
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx);
nr_ue_measurement_procedures(2, ue, proc, freq_alloc.num_rbs, pdsch_est_size, pdsch_dl_ch_estimates);
}
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx);
nr_ue_measurement_procedures(2, ue, proc, freq_alloc.num_rbs, pdsch_est_size, pdsch_dl_ch_estimates);
if (ue->chest_time == 1) { // averaging time domain channel estimates
nr_chest_time_domain_avg(&ue->frame_parms,
(int32_t **)pdsch_dl_ch_estimates,
dlschCfg->number_symbols,
dlschCfg->start_symbol,
dlschCfg->dlDmrsSymbPos,
freq_alloc.num_rbs);
}
if (ue->chest_time == 1) { // averaging time domain channel estimates
nr_chest_time_domain_avg(&ue->frame_parms,
(int32_t **)pdsch_dl_ch_estimates,
dlschCfg->number_symbols,
dlschCfg->start_symbol,
dlschCfg->dlDmrsSymbPos,
freq_alloc.num_rbs);
}
uint16_t first_symbol_with_data = dlschCfg->start_symbol;
uint32_t dmrs_data_re;
uint16_t first_symbol_with_data = dlschCfg->start_symbol;
uint32_t dmrs_data_re;
if (dlschCfg->dmrsConfigType == NFAPI_NR_DMRS_TYPE1)
dmrs_data_re = 12 - 6 * dlschCfg->n_dmrs_cdm_groups;
else
dmrs_data_re = 12 - 4 * dlschCfg->n_dmrs_cdm_groups;
if (dlschCfg->dmrsConfigType == NFAPI_NR_DMRS_TYPE1)
dmrs_data_re = 12 - 6 * dlschCfg->n_dmrs_cdm_groups;
else
dmrs_data_re = 12 - 4 * dlschCfg->n_dmrs_cdm_groups;
while ((dmrs_data_re == 0) && (dlschCfg->dlDmrsSymbPos & (1 << first_symbol_with_data))) {
first_symbol_with_data++;
}
while ((dmrs_data_re == 0) && (dlschCfg->dlDmrsSymbPos & (1 << first_symbol_with_data))) {
first_symbol_with_data++;
}
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT] = {0};
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT] = {0};
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT] = {0};
int32_t log2_maxh = 0;
int32_t log2_maxh = 0;
const uint32_t rx_llr_layer_size = (G + dlsch[0].Nl - 1) / dlsch[0].Nl;
start_meas_nr_ue_phy(ue, RX_PDSCH_STATS);
pdsch_scope_req_t scope_req = {.copy_chanest_to_scope = false, .copy_rxdataF_to_scope = false, .scope_rxdataF_offset = 0};
if (UEScopeHasTryLock(ue)) {
metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx};
scope_req.copy_chanest_to_scope = UETryLockScopeData(ue,
pdschChanEstimates,
sizeof(c16_t),
1,
freq_alloc.num_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols,
&mt);
scope_req.copy_rxdataF_to_scope = UETryLockScopeData(ue,
pdschRxdataF,
sizeof(c16_t),
1,
freq_alloc.num_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols,
&mt);
}
fourDimArray_t *toFree3 = NULL;
allocCast4D(dl_ch_mag,
c16_t,
toFree3,
NR_SYMBOLS_PER_SLOT,
dlsch[0].Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
fourDimArray_t *toFree4 = NULL;
allocCast4D(dl_ch_magb,
c16_t,
toFree4,
NR_SYMBOLS_PER_SLOT,
dlsch[0].Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
fourDimArray_t *toFree5 = NULL;
allocCast4D(dl_ch_magr,
c16_t,
toFree5,
NR_SYMBOLS_PER_SLOT,
dlsch[0].Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) {
bool first_symbol_flag = false;
if (m == first_symbol_with_data)
first_symbol_flag = true;
if (dlsch[0].Nl == 0 || rx_llr_layer_size == 0 || rx_llr_layer_size > 10 * 1000 * 1000) {
LOG_E(PHY, "rx_llr_layer_size %d, G %d, Nl, %d, discarding this pdsch\n", rx_llr_layer_size, G, dlsch[0].Nl);
// process DLSCH received symbols in the slot
// symbol by symbol processing (if data/DMRS are multiplexed is checked inside the function)
if (nr_rx_pdsch(ue,
proc,
dlsch,
&freq_alloc,
m,
first_symbol_flag,
harq_pid,
pdsch_est_size,
pdsch_dl_ch_estimates,
llr,
dl_valid_re,
rxdataF,
&log2_maxh,
rx_size_symbol,
ue->frame_parms.nb_antennas_rx,
rxdataF_comp,
dl_ch_mag,
dl_ch_magb,
dl_ch_magr,
ptrs_phase_per_slot,
ptrs_re_per_slot,
G,
nvar,
&scope_req)
< 0) {
if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates);
}
if (scope_req.copy_rxdataF_to_scope) {
UEunlockScopeData(ue, pdschRxdataF);
}
return -1;
}
__attribute__((aligned(32))) int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size];
start_meas_nr_ue_phy(ue, RX_PDSCH_STATS);
pdsch_scope_req_t scope_req = { .copy_chanest_to_scope = false,
.copy_rxdataF_to_scope = false,
.scope_rxdataF_offset = 0 };
if (UEScopeHasTryLock(ue)) {
metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx};
scope_req.copy_chanest_to_scope = UETryLockScopeData(ue,
pdschChanEstimates,
sizeof(c16_t),
1,
freq_alloc.num_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols,
&mt);
scope_req.copy_rxdataF_to_scope = UETryLockScopeData(ue,
pdschRxdataF,
sizeof(c16_t),
1,
freq_alloc.num_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols,
&mt);
}
for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) {
bool first_symbol_flag = false;
if (m == first_symbol_with_data)
first_symbol_flag = true;
// process DLSCH received symbols in the slot
// symbol by symbol processing (if data/DMRS are multiplexed is checked inside the function)
if (nr_rx_pdsch(ue,
proc,
dlsch,
&freq_alloc,
m,
first_symbol_flag,
harq_pid,
pdsch_est_size,
pdsch_dl_ch_estimates,
rx_llr_layer_size,
layer_llr,
llr,
dl_valid_re,
rxdataF,
llr_offset,
&log2_maxh,
rx_size_symbol,
ue->frame_parms.nb_antennas_rx,
rxdataF_comp,
ptrs_phase_per_slot,
ptrs_re_per_slot,
G,
nvar,
&scope_req)
< 0) {
if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates);
}
if (scope_req.copy_rxdataF_to_scope) {
UEunlockScopeData(ue, pdschRxdataF);
}
return -1;
}
} // CRNTI active
stop_meas_nr_ue_phy(ue, RX_PDSCH_STATS);
if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates);
}
if (scope_req.copy_rxdataF_to_scope) {
UEunlockScopeData(ue, pdschRxdataF);
}
free(toFree);
free(toFree2);
} // CRNTI active
stop_meas_nr_ue_phy(ue, RX_PDSCH_STATS);
if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates);
}
if (scope_req.copy_rxdataF_to_scope) {
UEunlockScopeData(ue, pdschRxdataF);
}
free(toFree);
free(toFree2);
free(toFree3);
free(toFree4);
free(toFree5);
return 0;
}
@@ -1294,7 +1317,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
unav_res,
dlsch_config->qamModOrder,
dlsch[0].Nl);
const uint32_t rx_llr_buf_sz = ((G + 15) / 16) * 16;
const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G, 32); // each LLR is 2 bytes hence 64 byte aligned
const uint32_t nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1;
int16_t* llr[2];
for (int i = 0; i < nb_codewords; i++)