From f5c7fc3b117aa8ed7b6bb4064a39531159b4c6b7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 20 May 2024 18:47:25 +0200 Subject: [PATCH] rate-match around overlapping CSI-RS resources in PDSCH reception --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 191 ++++++++++++------ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 69 ++++++- 2 files changed, 187 insertions(+), 73 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index e22f5f1d30..ddb99ea56f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -158,6 +158,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, uint8_t Nl, NR_DL_FRAME_PARMS *frame_parms, uint16_t dlDmrsSymbPos, + uint32_t csi_res_bitmap, int chest_time_type); static void nr_dlsch_channel_level_median(uint32_t rx_size_symbol, @@ -238,6 +239,82 @@ void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, unsigned short nb_rb, int length); +static bool overlap_csi_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu, int symbol) +{ + int num_l0 [18] = {1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 4, 2, 2, 4}; + for (int s = 0; s < num_l0[csi_pdu->row - 1]; s++) { + if (symbol == csi_pdu->symb_l0 + s) + return true; + } + // check also l1 if relevant + if (csi_pdu->row == 13 || csi_pdu->row == 14 || csi_pdu->row == 16 || csi_pdu->row == 17) { + for (int s = 0; s < 2; s++) { // two consecutive symbols including l1 + if (symbol == csi_pdu->symb_l1 + s) + return true; + } + } + return false; +} + +static uint32_t build_csi_overlap_bitmap(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, int symbol) +{ + // LS 16 bits for even RBs, MS 16 bits for odd RBs + uint32_t csi_res_bitmap = 0; + int num_k[18] = {1, 1, 1, 1, 1, 4, 2, 2, 6, 3, 4, 4, 3, 3, 3, 4, 4, 4}; + for (int i = 0; i < dlsch_config->numCsiRsForRateMatching; i++) { + fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_config->csiRsForRateMatching[i]; + + if (!overlap_csi_symbol(csi_pdu, symbol)) + continue; + + int num_kp = 1; + int mult = 1; + int k0_step = 0; + int num_k0 = 1; + switch (csi_pdu->row) { + case 1: + k0_step = 4; + num_k0 = 3; + break; + case 2: + break; + case 4: + num_kp = 2; + mult = 4; + k0_step = 2; + num_k0 = 2; + break; + default: + num_kp = 2; + mult = 2; + } + int found = 0; + int bit = 0; + uint32_t temp_res_map = 0; + while (found < num_k[csi_pdu->row - 1]) { + if ((csi_pdu->freq_domain >> bit) & 0x01) { + for (int k0 = 0; k0 < num_k0; k0++) { + for (int kp = 0; kp < num_kp; kp++) { + int re = (bit * mult) + (k0 * k0_step) + kp; + temp_res_map |= (1 << re); + } + } + found++; + } + bit++; + AssertFatal(bit < 13, + "Couldn't find %d positive bits in bitmap %d for CSI freq. domain\n", + num_k[csi_pdu->row - 1], + csi_pdu->freq_domain); + } + if (csi_pdu->freq_density < 2) + csi_res_bitmap |= (temp_res_map << (16 * csi_pdu->freq_density)); + else + csi_res_bitmap |= (temp_res_map + (temp_res_map << 16)); + } + return csi_res_bitmap; +} + /* Main Function */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, @@ -359,10 +436,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return(-1); } - if(symbol > ue->frame_parms.symbols_per_slot>>1) - { - slot = 1; - } + if(symbol > ue->frame_parms.symbols_per_slot >> 1) + slot = 1; uint8_t pilots = (dlsch_config->dlDmrsSymbPos >> symbol) & 1; uint8_t config_type = dlsch_config->dmrsConfigType; @@ -379,6 +454,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) c16_t rxdataF_ext[nbRx][rx_size_symbol]; memset(rxdataF_ext, 0, sizeof(rxdataF_ext)); + uint32_t csi_res_bitmap = build_csi_overlap_bitmap(dlsch_config, symbol); + + LOG_D(PHY, "%d.%d symbol %d csi overlap bitmap %d\n", frame, nr_slot_rx, symbol, csi_res_bitmap); + nr_dlsch_extract_rbs(ue->frame_parms.samples_per_slot_wCP, rxdataF, rx_size_symbol, @@ -395,6 +474,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nl, frame_parms, dlsch_config->dlDmrsSymbPos, + csi_res_bitmap, ue->chest_time); if (meas_enabled) { stop_meas(&meas); @@ -575,9 +655,22 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, /* Check for PTRS bitmap and process it respectively */ if((pduBitmap & 0x1) && (dlsch[0].rnti_type == TYPE_C_RNTI_)) { - nr_pdsch_ptrs_processing( - ue, nbRx, ptrs_phase_per_slot, ptrs_re_per_slot, rx_size_symbol, rxdataF_comp, frame_parms, dlsch0_harq, dlsch1_harq, gNB_id, nr_slot_rx, symbol, (nb_rb_pdsch * 12), dlsch[0].rnti, dlsch); - dl_valid_re[symbol-1] -= ptrs_re_per_slot[0][symbol]; + nr_pdsch_ptrs_processing(ue, + nbRx, + ptrs_phase_per_slot, + ptrs_re_per_slot, + rx_size_symbol, + rxdataF_comp, + frame_parms, + dlsch0_harq, + dlsch1_harq, + gNB_id, + nr_slot_rx, + symbol, + (nb_rb_pdsch * 12), + dlsch[0].rnti, + dlsch); + dl_valid_re[symbol - 1] -= ptrs_re_per_slot[0][symbol]; } /* at last symbol in a slot calculate LLR's for whole slot */ if(symbol == (startSymbIdx + nbSymb -1)) { @@ -1098,6 +1191,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, uint8_t Nl, NR_DL_FRAME_PARMS *frame_parms, uint16_t dlDmrsSymbPos, + uint32_t csi_res_bitmap, int chest_time_type) { if (config_type == NFAPI_NR_DMRS_TYPE1) { @@ -1125,7 +1219,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, int32_t *dl_ch0 = &dl_ch_estimates[(l * frame_parms->nb_antennas_rx) + aarx][validDmrsEst * frame_parms->ofdm_symbol_size]; int32_t *dl_ch0_ext = dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; - if (pilots == 0) { //data symbol only + if (pilots == 0 && csi_res_bitmap == 0) { // data symbol only if (l == 0) { if (start_re + nb_rb_pdsch * NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { memcpy(rxF_ext, &rxF[start_re], nb_rb_pdsch * NR_NB_SC_PER_RB * sizeof(int32_t)); @@ -1138,65 +1232,34 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, } memcpy(dl_ch0_ext, dl_ch0, nb_rb_pdsch * NR_NB_SC_PER_RB * sizeof(int32_t)); } - else if (config_type == NFAPI_NR_DMRS_TYPE1){ - if (n_dmrs_cdm_groups == 1) { //data is multiplexed - if (l == 0) { - unsigned short k = start_re; - for (unsigned short j = 0; j < 6*nb_rb_pdsch; j += 3) { - rxF_ext[j] = rxF[k+1]; - rxF_ext[j+1] = rxF[k+3]; - rxF_ext[j+2] = rxF[k+5]; - k += 6; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; + else { + int j = 0; + int k = start_re; + int max_cdm = (config_type == NFAPI_NR_DMRS_TYPE1) ? 2 : 3; + int shift = (config_type == NFAPI_NR_DMRS_TYPE1) ? 0 : 1; + for (int rb = 0; rb < nb_rb_pdsch; rb++) { + uint32_t csi_rb_map = (csi_res_bitmap >> (16 * (rb % 2))) & 0x1fff; + for (int re = 0; re < 12; re++) { + bool is_csi_re = (csi_rb_map >> re) & 0x01; + if (((re >> shift) % max_cdm) < n_dmrs_cdm_groups) { + // DMRS RE + AssertFatal(!is_csi_re, "DMRS RE overlapping with CSI RE, it shouldn't happen\n"); } - } - for (unsigned short j = 0; j < 6*nb_rb_pdsch; j += 3) { - dl_ch0_ext[j] = dl_ch0[1]; - dl_ch0_ext[j+1] = dl_ch0[3]; - dl_ch0_ext[j+2] = dl_ch0[5]; - dl_ch0 += 6; - } - } - } - else {//NFAPI_NR_DMRS_TYPE2 - if (n_dmrs_cdm_groups == 1) { //data is multiplexed - if (l == 0) { - unsigned short k = start_re; - for (unsigned short j = 0; j < 8*nb_rb_pdsch; j += 4) { - rxF_ext[j] = rxF[k+2]; - rxF_ext[j+1] = rxF[k+3]; - rxF_ext[j+2] = rxF[k+4]; - rxF_ext[j+3] = rxF[k+5]; - k += 6; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; + else { + // DATA RE + if (!is_csi_re) { + // Process RE only if not overlapping with CSI + if (l == 0) + rxF_ext[j] = rxF[k]; + dl_ch0_ext[j] = dl_ch0[re]; + j++; + } } + k++; + if (k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; } - for (unsigned short j = 0; j < 8*nb_rb_pdsch; j += 4) { - dl_ch0_ext[j] = dl_ch0[2]; - dl_ch0_ext[j+1] = dl_ch0[3]; - dl_ch0_ext[j+2] = dl_ch0[4]; - dl_ch0_ext[j+3] = dl_ch0[5]; - dl_ch0 += 6; - } - } - else if (n_dmrs_cdm_groups == 2) { //data is multiplexed - if (l == 0) { - unsigned short k = start_re; - for (unsigned short j = 0; j < 4*nb_rb_pdsch; j += 2) { - rxF_ext[j] = rxF[k+4]; - rxF_ext[j+1] = rxF[k+5]; - k += 6; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; - } - } - for (unsigned short j = 0; j < 4*nb_rb_pdsch; j += 2) { - dl_ch0_ext[j] = dl_ch0[4]; - dl_ch0_ext[j+1] = dl_ch0[5]; - dl_ch0 += 6; - } + dl_ch0 += 12; } } } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index aa4de65c08..0f08604616 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -637,6 +637,54 @@ static void send_dl_done_to_tx_thread(notifiedFIFO_t *nf, int rx_slot) } } +static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config) +{ + uint32_t unav_res = 0; + for (int i = 0; i < dlsch_config->numCsiRsForRateMatching; i++) { + fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_config->csiRsForRateMatching[i]; + // check overlapping symbols + int num_overlap_symb = 0; + // num of consecutive csi symbols from l0 included + int num_l0 [18] = {1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 4, 2, 2, 4}; + int num_symb = num_l0[csi_pdu->row - 1]; + for (int s = 0; s < num_symb; s++) { + int l0_symb = csi_pdu->symb_l0 + s; + if (l0_symb >= dlsch_config->start_symbol && l0_symb <= dlsch_config->start_symbol + dlsch_config->number_symbols) + num_overlap_symb++; + } + // check also l1 if relevant + if (csi_pdu->row == 13 || csi_pdu->row == 14 || csi_pdu->row == 16 || csi_pdu->row == 17) { + num_symb += 2; + for (int s = 0; s < 2; s++) { // two consecutive symbols including l1 + int l1_symb = csi_pdu->symb_l1 + s; + if (l1_symb >= dlsch_config->start_symbol && l1_symb <= dlsch_config->start_symbol + dlsch_config->number_symbols) + num_overlap_symb++; + } + } + if (num_overlap_symb == 0) + continue; + // check number overlapping prbs + // assuming CSI is spanning the whole BW + AssertFatal(dlsch_config->BWPSize <= csi_pdu->nr_of_rbs, "Assuming CSI-RS is spanning the whold BWP this shouldn't happen\n"); + int dlsch_start = dlsch_config->start_rb + dlsch_config->BWPStart; + int num_overlapping_prbs = dlsch_config->number_rbs; + if (num_overlapping_prbs < 1) + continue; // no overlapping prbs + if (csi_pdu->freq_density < 2) { // 0.5 density + num_overlapping_prbs /= 2; + // odd number of prbs and the start PRB is even/odd when CSI is in even/odd PRBs + if ((num_overlapping_prbs % 2) && ((dlsch_start % 2) == csi_pdu->freq_density)) + num_overlapping_prbs += 1; + } + // density is number or res per port per rb (over all symbols) + int ports [18] = {1, 1, 2, 4, 4, 8, 8, 8, 12, 12, 16, 16, 24, 24, 24, 32, 32, 32}; + int num_csi_res_per_prb = csi_pdu->freq_density == 3 ? 3 : 1; + num_csi_res_per_prb *= ports[csi_pdu->row - 1]; + unav_res += num_overlapping_prbs * num_csi_res_per_prb * num_overlap_symb / num_symb; + } + return unav_res; +} + static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], @@ -771,10 +819,10 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols); unav_res = n_ptrs * ptrsSymbPerSlot; } - int G1 = - nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[1].Nl); + unav_res += compute_csi_rm_unav_res(dlsch_config); + G = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[1].Nl); start_meas(&ue->dlsch_unscrambling_stats); - nr_dlsch_unscrambling(llr[1], G1, 0, dlsch[1].dlsch_config.dlDataScramblingId, dlsch[1].rnti); + nr_dlsch_unscrambling(llr[1], G, 0, dlsch[1].dlsch_config.dlDataScramblingId, dlsch[1].rnti); stop_meas(&ue->dlsch_unscrambling_stats); start_meas(&ue->dlsch_decoding_stats); @@ -797,12 +845,14 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, stop_meas(&ue->dlsch_decoding_stats); if (cpumeas(CPUMEAS_GETSTATE)) { - LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats.p_time)/(cpuf*1000.0)); - } - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS); + LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", (ue->dlsch_unscrambling_stats.p_time) / (cpuf * 1000.0)); + LOG_D(PHY, + "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx % 1024, + nr_slot_rx, + (ue->dlsch_decoding_stats.p_time) / (cpuf * 1000.0)); + } + LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS); } // send to mac @@ -1071,6 +1121,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols); unav_res = n_ptrs * ptrsSymbPerSlot; } + unav_res += compute_csi_rm_unav_res(dlsch_config); int G = nr_get_G(dlsch_config->number_rbs, dlsch_config->number_symbols, nb_re_dmrs,