From 032fc5e9c24f97726e078e7a752f0099d3a1a990 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 31 Oct 2025 12:25:54 +0100 Subject: [PATCH 1/3] fix bugs in scope for pdcch, and optimize cpu cost of pdcch decoding by not processing useless samples in one symbol --- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 17 ++------ openair1/PHY/NR_REFSIG/refsig_defs_ue.h | 5 +-- .../nr_dl_channel_estimation.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 39 +++++++++---------- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index e25d9700da..62dc85e90c 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -150,22 +150,11 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, return(0); } -int nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, - c16_t *output, - unsigned short p, - unsigned short nb_rb_coreset) +void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) { - if (p==2000) { - for (int i=0; i<((nb_rb_coreset*6)>>1); i++) { - output[i] = get_modulated(nr_gold_pdcch, i, true); -#ifdef DEBUG_PDCCH - if (i<8) - printf("i %d idx %d pdcch mod_dmrs %d %d\n", i, idx, output[i].r, output[i].i); -#endif - } + for (int i = 0; i < ((nb_rb_coreset * 6) >> 1); i++) { + output[i] = get_modulated(nr_gold_pdcch, i, true); } - - return(0); } void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output, bool sidelink) diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 414dae9976..d9d1ef4534 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -35,10 +35,7 @@ void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output, /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables */ -int nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, - c16_t *output, - unsigned short p, - unsigned short nb_rb_corset); +void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned int Ns, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 6a49a17608..f310c0236b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -846,7 +846,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_rx(gold, pilot, 2000, (nb_rb_coreset + dmrs_ref)); + nr_pdcch_dmrs_rx(gold, pilot, nb_rb_coreset + dmrs_ref); for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 9e48f52a03..d956ca7cc3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -294,8 +294,9 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } static void nr_pdcch_channel_compensation(int arraySz, - c16_t rxdataF_ext[][arraySz], - c16_t dl_ch_estimates_ext[][arraySz], + int sz2, + c16_t rxdataF_ext[][sz2], + c16_t dl_ch_estimates_ext[][sz2], c16_t rxdataF_comp[][arraySz], int antRx, uint8_t output_shift) @@ -306,17 +307,17 @@ static void nr_pdcch_channel_compensation(int arraySz, } } -static void nr_pdcch_detection_mrc(int sz, c16_t rxdataF_comp[][sz]) +static void nr_pdcch_detection_mrc(int nb_ant, int sz, c16_t rxdataF_comp[][sz]) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); c16_t *rx0 = rxdataF_comp[0]; - c16_t *rx1 = rxdataF_comp[1]; - // MRC on each re of rb // input always aligned and accepting tail padding to process all actual samples - for (int i = 0; i < sz; i += 4) { - *(simde__m128i *)(rx0 + i) = - simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); + for (int a = 1; a < nb_ant; a++) { + c16_t *rx = rxdataF_comp[a]; + for (int i = 0; i < sz; i += 4) { + *(simde__m128i *)(rx0 + i) = simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), + simde_mm_srai_epi16(*(simde__m128i *)(rx + i), 1)); + } } } @@ -334,7 +335,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset; - int32_t pdcch_est_size = ((((fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH) + 15) / 16) * 16); + int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16); __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size]; nr_pdcch_channel_estimation(ue, @@ -347,12 +348,9 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, pdcch_dl_ch_estimates, rxdataF); - const int32_t rx_size = ((4 * fp->N_RB_DL * 12 + 31) >> 5) << 5; + const int32_t rx_size = ceil_mod(fp->N_RB_DL * 12, 32); __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; - __attribute__((aligned(32))) c16_t rxdataF_comp[fp->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); - int n_rb; int rb_offset; get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); @@ -376,20 +374,21 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, for (int i = 1; i < fp->nb_antennas_rx; i++) avgs = cmax(avgs, avg[i]); const int log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; - - nr_pdcch_channel_compensation(rx_size, + int rx_comp_sz = ceil_mod(llr_size_symbol, 4); + __attribute__((aligned(32))) c16_t rxdataF_comp[fp->nb_antennas_rx][rx_comp_sz]; + memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); + nr_pdcch_channel_compensation(rx_comp_sz, + rx_size, rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, fp->nb_antennas_rx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), fp->nb_antennas_rx, rx_size, 0); - if (fp->nb_antennas_rx > 1) { - nr_pdcch_detection_mrc(rx_size, rxdataF_comp); + nr_pdcch_detection_mrc(fp->nb_antennas_rx, rx_comp_sz, rxdataF_comp); } - + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), 1, llr_size_symbol, 0); nr_pdcch_llr(llr_size_symbol, rxdataF_comp[0], llr); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index cbef1dc62a..51c7bf2c55 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1041,7 +1041,7 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr); if (symbol == last_symb_pdcch) { nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr); - UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr), 0); + UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr) / sizeof(c16_t), 0); } } stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); From f982d9b5df9f713699ba6eedd52dac714503f6c0 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 3 Nov 2025 20:24:37 +0100 Subject: [PATCH 2/3] rename a function to what it does (it generate a reference signal) and minor readability changes --- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 2 +- openair1/PHY/NR_REFSIG/refsig_defs_ue.h | 2 +- .../nr_dl_channel_estimation.c | 58 ++++++++----------- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 62dc85e90c..3624d754e9 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -150,7 +150,7 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, return(0); } -void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) +void nr_pdcch_dmrs_ref(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) { for (int i = 0; i < ((nb_rb_coreset * 6) >> 1); i++) { output[i] = get_modulated(nr_gold_pdcch, i, true); diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index d9d1ef4534..fb7dce4489 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -35,7 +35,7 @@ void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output, /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables */ -void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); +void nr_pdcch_dmrs_ref(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned int Ns, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index f310c0236b..823c38c88d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -807,10 +807,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]) { + const int symb_sz = ue->frame_parms.ofdm_symbol_size; int slot = proc->nr_slot_rx; - unsigned char aarx; - unsigned short k; - unsigned int pilot_cnt; int nb_rb_coreset=0; int coreset_start_rb=0; @@ -824,14 +822,6 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12; -#ifdef DEBUG_PDCCH - printf("PDCCH Channel Estimation : OFDM size %d, Ncp=%d, slot=%d, symbol %d\n", - ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp, - slot, - symbol); -#endif - #if CH_INTERP int16_t *fl = filt16a_l1; int16_t *fm = filt16a_m1; @@ -846,14 +836,13 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_rx(gold, pilot, nb_rb_coreset + dmrs_ref); + nr_pdcch_dmrs_ref(gold, pilot, nb_rb_coreset + dmrs_ref); - for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - - k = coreset_start_subcarrier; + for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { + int k = coreset_start_subcarrier; c16_t *pil = &pilot[dmrs_ref * 3]; c16_t *rxF = &rxdataF[aarx][k + 1]; - c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][0]; + c16_t *dl_ch = pdcch_dl_ch_estimates[aarx]; memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size); @@ -871,36 +860,36 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, rxF += 4; k += 2; - if (k >= ue->frame_parms.ofdm_symbol_size) { - k -= ue->frame_parms.ofdm_symbol_size; + if (k >= symb_sz) { + k -= symb_sz; rxF = &rxdataF[aarx][k + 1]; } multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1)]; multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); dl_ch += 12; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; - for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) { + for (int pilot_cnt = 3; pilot_cnt < (3 * nb_rb_coreset); pilot_cnt += 3) { multadd_real_vector_complex_scalar(fl, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); dl_ch += 12; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; } - #else //ELSE CH_INTERP +#else //ELSE CH_INTERP c32_t ch_sum = {0, 0}; - for (pilot_cnt = 0; pilot_cnt < 3*nb_rb_coreset; pilot_cnt++) { + for (int pilot_cnt = 0; pilot_cnt < 3 * nb_rb_coreset; pilot_cnt++) { #ifdef DEBUG_PDCCH printf("pilot[%u] = (%d, %d)\trxF[%d] = (%d, %d)\n", pilot_cnt, pil[0], pil[1], k+1, rxF[0], rxF[1]); @@ -908,8 +897,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t ch = c16mulShift(*pil++, *rxF, 15); ch_sum.r += ch.r; ch_sum.i += ch.i; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; if (pilot_cnt % 3 == 2) { ch.r = ch_sum.r / 3; @@ -923,11 +912,10 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch_sum = (c32_t){0}; } } - #endif //END CH_INTERP +#endif //END CH_INTERP //} - } } From ab14e3ad229f1042030c506c3343136a138699ac Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 3 Nov 2025 20:33:20 +0100 Subject: [PATCH 3/3] move all antennas comon code of begining of nr_pdcch_channel_estimation to prepare the future move of the antenna loop above the serial call of functions to decode pdcch --- .../nr_dl_channel_estimation.c | 29 +++++-------------- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 11 +++---- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 27 ++++++++++++----- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 823c38c88d..a95ef9f6f8 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -797,23 +797,18 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, return(0); } -void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - fapi_nr_coreset_t *coreset, +void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, + int nb_rb_coreset, + int coreset_start_rb, + int dmrs_ref, uint16_t first_carrier_offset, uint16_t BWPStart, int32_t pdcch_est_size, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]) + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t *pilot) { const int symb_sz = ue->frame_parms.ofdm_symbol_size; - int slot = proc->nr_slot_rx; - - int nb_rb_coreset=0; - int coreset_start_rb=0; - get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb); - if(nb_rb_coreset==0) return; #ifdef DEBUG_PDCCH printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d\n", @@ -828,23 +823,13 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, int16_t *fr = filt16a_r1; #endif - unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; - int dmrs_ref = 0; - if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_ref = BWPStart; - // generate pilot - c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); - // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_ref(gold, pilot, nb_rb_coreset + dmrs_ref); - for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { int k = coreset_start_subcarrier; c16_t *pil = &pilot[dmrs_ref * 3]; c16_t *rxF = &rxdataF[aarx][k + 1]; c16_t *dl_ch = pdcch_dl_ch_estimates[aarx]; - memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size); + memset(dl_ch, 0, sizeof(c16_t) * symb_sz); #ifdef DEBUG_PDCCH printf("pdcch ch est pilot addr %p RB_DL %d\n",&pilot[dmrs_ref*3], ue->frame_parms.N_RB_DL); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 85b8999118..4ed05ce9cf 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -44,15 +44,16 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t /*! \brief This function performs channel estimation including frequency and temporal interpolation */ -void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - fapi_nr_coreset_t *coreset, +void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, + int nb_rb, + int rb_offset, + int dmrs_ref, uint16_t first_carrier_offset, uint16_t BWPStart, int32_t pdcch_est_size, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]); + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t *pilot); c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index d956ca7cc3..4c5c6e6f39 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -40,7 +40,7 @@ #include "PHY/sse_intrin.h" #include "common/utils/nr/nr_common.h" #include -#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "assertions.h" @@ -337,23 +337,34 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset; int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16); __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size]; + int n_rb; + int rb_offset; + get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); + unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; + int dmrs_ref = 0; + if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) + dmrs_ref = phy_pdcch_config->pdcch_config[ss_idx].BWPStart; + // generate pilot + c16_t pilot[(n_rb + dmrs_ref) * 3] __attribute__((aligned(16))); + // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS + const uint32_t *gold = + nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); + nr_pdcch_dmrs_ref(gold, pilot, n_rb + dmrs_ref); nr_pdcch_channel_estimation(ue, - proc, - symbol, - coreset, + n_rb, + rb_offset, + dmrs_ref, fp->first_carrier_offset, phy_pdcch_config->pdcch_config[ss_idx].BWPStart, pdcch_est_size, pdcch_dl_ch_estimates, - rxdataF); + rxdataF, + pilot); const int32_t rx_size = ceil_mod(fp->N_RB_DL * 12, 32); __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - int n_rb; - int rb_offset; - get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); nr_pdcch_extract_rbs_single(ue->frame_parms.ofdm_symbol_size, rxdataF,