diff --git a/executables/nr-ue.c b/executables/nr-ue.c index ac7dace077..15f5040139 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -558,8 +558,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, if (phy_data->dlsch[0].active && (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) { // indicate to tx thread to wait for DLSCH decoding - if (phy_data->dlsch[0].dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH - const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % fp->slots_per_frame; + if (phy_data->dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH + const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch_config.k1_feedback) % fp->slots_per_frame; tx_wait_for_dlsch[ack_nack_slot]++; } } diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 1ccaf2ee68..b66fdc9b41 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -118,6 +118,7 @@ typedef struct { typedef struct { uint8_t harq_pid; + uint8_t cw_idx; uint8_t ack_nack; uint32_t pdu_length; uint8_t* pdu; @@ -466,6 +467,17 @@ typedef struct { typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t; +typedef struct { + uint8_t mcs; + bool new_data_indicator; + uint8_t rv; + uint16_t targetCodeRate; + uint8_t qamModOrder; + uint32_t TBS; + uint8_t ldpcBaseGraph; + uint8_t Nl; +} fapi_nr_dl_cw_info_t; + typedef struct { uint16_t BWPSize; uint16_t BWPStart; @@ -482,15 +494,8 @@ typedef struct { uint8_t prb_bundling_size_ind; uint8_t rate_matching_ind; uint8_t zp_csi_rs_trigger; - uint8_t mcs; - bool new_data_indicator; - uint8_t rv; - uint16_t targetCodeRate; - uint8_t qamModOrder; - uint32_t TBS; - uint8_t tb2_mcs; - bool tb2_new_data_indicator; - uint8_t tb2_rv; + uint8_t n_codewords; + fapi_nr_dl_cw_info_t cw_info[2]; uint8_t harq_process_nbr; vrb_to_prb_mapping_t vrb_to_prb_mapping; uint8_t dai; @@ -523,7 +528,6 @@ typedef struct { uint16_t dlDataScramblingId; uint16_t pduBitmap; uint32_t k1_feedback; - uint8_t ldpcBaseGraph; uint8_t numCsiRsForRateMatching; fapi_nr_dl_config_csirs_pdu_rel15_t csiRsForRateMatching[NFAPI_MAX_NUM_CSI_RATEMATCH]; } fapi_nr_dl_config_dlsch_pdu_rel15_t; 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 a8ea145c60..2ed339de8a 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1374,127 +1374,94 @@ void nr_pdsch_ptrs_processing(int nbRx, 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, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, uint8_t nr_slot_rx, unsigned char symbol, int nb_rb, uint16_t rnti, - NR_UE_DLSCH_t dlsch[2]) + uint16_t *ptrsSymbPos, + uint8_t *ptrsSymbIdx) { //#define DEBUG_DL_PTRS 1 int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; /* harq specific variables */ - uint8_t symbInSlot = 0; - uint16_t *startSymbIndex = NULL; - uint16_t *nbSymb = NULL; - uint8_t *L_ptrs = NULL; - uint8_t *K_ptrs = NULL; - uint16_t *dmrsSymbPos = NULL; - uint16_t *ptrsSymbPos = NULL; - uint8_t *ptrsSymbIdx = NULL; - uint8_t *ptrsReOffset = NULL; - int nscid = 0; + int symbInSlot = dlsch_config->start_symbol + dlsch_config->number_symbols; + int startSymbIndex = dlsch_config->start_symbol; + int nbSymb = dlsch_config->number_symbols; + int L_ptrs = dlsch_config->PTRSTimeDensity; + int K_ptrs = dlsch_config->PTRSFreqDensity; + int dmrsSymbPos = dlsch_config->dlDmrsSymbPos; + int ptrsReOffset = dlsch_config->PTRSReOffset; + int nscid = dlsch_config->nscid; - if(dlsch0_harq->status == NR_ACTIVE) { - symbInSlot = dlsch[0].dlsch_config.start_symbol + dlsch[0].dlsch_config.number_symbols; - startSymbIndex = &dlsch[0].dlsch_config.start_symbol; - nbSymb = &dlsch[0].dlsch_config.number_symbols; - L_ptrs = &dlsch[0].dlsch_config.PTRSTimeDensity; - K_ptrs = &dlsch[0].dlsch_config.PTRSFreqDensity; - dmrsSymbPos = &dlsch[0].dlsch_config.dlDmrsSymbPos; - ptrsReOffset = &dlsch[0].dlsch_config.PTRSReOffset; - ptrsSymbPos = &dlsch[0].ptrs_symbols; - ptrsSymbIdx = &dlsch[0].ptrs_symbol_index; - nscid = dlsch[0].dlsch_config.nscid; - } - if(dlsch1_harq) { - symbInSlot = dlsch[1].dlsch_config.start_symbol + dlsch[1].dlsch_config.number_symbols; - startSymbIndex = &dlsch[1].dlsch_config.start_symbol; - nbSymb = &dlsch[1].dlsch_config.number_symbols; - L_ptrs = &dlsch[1].dlsch_config.PTRSTimeDensity; - K_ptrs = &dlsch[1].dlsch_config.PTRSFreqDensity; - dmrsSymbPos = &dlsch[1].dlsch_config.dlDmrsSymbPos; - ptrsReOffset = &dlsch[1].dlsch_config.PTRSReOffset; - ptrsSymbPos = &dlsch[1].ptrs_symbols; - ptrsSymbIdx = &dlsch[1].ptrs_symbol_index; - nscid = dlsch[1].dlsch_config.nscid; - } /* loop over antennas */ - for (int aarx=0; aarxnb_antennas_rx; aarx++) { + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx]; ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx]; ptrs_re_symbol[symbol] = 0; phase_per_symbol[symbol].i = 0; // Imag /* set DMRS estimates to 0 angle with magnitude 1 */ - if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { + if(is_dmrs_symbol(symbol, dmrsSymbPos)) { /* set DMRS real estimation to 32767 */ phase_per_symbol[symbol].r=INT16_MAX; // 32767 #ifdef DEBUG_DL_PTRS printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i); #endif - } - else { // real ptrs value is set to 0 + } else { // real ptrs value is set to 0 phase_per_symbol[symbol].r = 0; // Real } - if(dlsch0_harq->status == NR_ACTIVE) { - if(symbol == *startSymbIndex) { - *ptrsSymbPos = 0; - set_ptrs_symb_idx(ptrsSymbPos, - *nbSymb, - *startSymbIndex, - 1<< *L_ptrs, - *dmrsSymbPos); - } - /* if not PTRS symbol set current ptrs symbol index to zero*/ - *ptrsSymbIdx = 0; - /* Check if current symbol contains PTRS */ - if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { - *ptrsSymbIdx = symbol; - /*------------------------------------------------------------------------------------------------------- */ - /* 1) Estimate common phase error per PTRS symbol */ - /*------------------------------------------------------------------------------------------------------- */ - const uint32_t *gold = + if (symbol == startSymbIndex) { + *ptrsSymbPos = 0; + set_ptrs_symb_idx(ptrsSymbPos, nbSymb, startSymbIndex, 1 << L_ptrs, dmrsSymbPos); + } + /* if not PTRS symbol set current ptrs symbol index to zero*/ + *ptrsSymbIdx = 0; + /* Check if current symbol contains PTRS */ + if (is_ptrs_symbol(symbol, *ptrsSymbPos)) { + *ptrsSymbIdx = symbol; + /*------------------------------------------------------------------------------------------------------- */ + /* 1) Estimate common phase error per PTRS symbol */ + /*------------------------------------------------------------------------------------------------------- */ + const uint32_t *gold = nr_gold_pdsch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, frame_parms->Nid_cell, nscid, nr_slot_rx, symbol); - nr_ptrs_cpe_estimation(*K_ptrs, - *ptrsReOffset, - nb_rb, - rnti, - frame_parms->ofdm_symbol_size, - rxdataF_comp[symbol][0][aarx], - gold, - (int16_t *)&phase_per_symbol[symbol], - &ptrs_re_symbol[symbol]); - } - }// HARQ 0 + nr_ptrs_cpe_estimation(K_ptrs, + ptrsReOffset, + nb_rb, + rnti, + frame_parms->ofdm_symbol_size, + rxdataF_comp[symbol][0][aarx], + gold, + (int16_t *)&phase_per_symbol[symbol], + &ptrs_re_symbol[symbol]); + } /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ - if(symbol == (symbInSlot -1)) { + if (symbol == (symbInSlot -1)) { /*------------------------------------------------------------------------------------------------------- */ /* 2) Interpolate PTRS estimated value in TD */ /*------------------------------------------------------------------------------------------------------- */ /* If L-PTRS is > 0 then we need interpolation */ - if(*L_ptrs > 0) { - ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb); + if (L_ptrs > 0) { + ret = nr_ptrs_process_slot(dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, startSymbIndex, nbSymb); if(ret != 0) { LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); } } #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) * rx_size_symbol, rx_size_symbol * (*nbSymb), 1, 1); + LOG_M("ptrsEst.m","est", ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1); + LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + startSymbIndex * 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); + 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(rxdataF_comp[i][0][aarx], &phase_per_symbol[i], rxdataF_comp[i][0][aarx], nb_rb * NR_NB_SC_PER_RB, 15); }// if not DMRS Symbol diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 474debc2f7..5224337f96 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -126,13 +126,13 @@ void nr_pdsch_ptrs_processing(int nbRx, 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, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, uint8_t nr_slot_rx, unsigned char symbol, int nb_rb, uint16_t rnti, - NR_UE_DLSCH_t dlsch[2]); + uint16_t *ptrsSymbPos, + uint8_t *ptrsSymbIdx); int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue, sl_nr_ue_phy_params_t *sl_phy_params, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 65d0f11593..fe5e1513c2 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -170,7 +170,7 @@ static void send_ssb_rsrp_meas(PHY_VARS_NR_UE *ue, nr_downlink_indication_t dl_indication = {0}; fapi_nr_rx_indication_t rx_ind = {0}; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, &l1_measurements, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, &l1_measurements, NULL); ue->if_inst->dl_indication(&dl_indication); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 1944ce7ca4..8ade018829 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -961,6 +961,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind = {0}; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, (void *)&l1_measurements, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, (void *)&l1_measurements, NULL); ue->if_inst->dl_indication(&dl_indication); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 7ccc366dfa..07542dac64 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -43,178 +43,143 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t *dlsch, - int16_t **dlsch_llr, - uint8_t **b, - int *G, - int nb_dlsch, + int cw_idx, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, + int16_t *dlsch_llr, + uint8_t *b, int number_rbs, - uint8_t *DLSCH_ids) + int G) { - nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch]; - memset(TBs, 0, sizeof(TBs)); + nrLDPC_TB_decoding_parameters_t TB_parameters = {0}; nrLDPC_slot_decoding_parameters_t slot_parameters = { .frame = proc->frame_rx, .slot = proc->nr_slot_rx, - .nb_TBs = nb_dlsch, + .nb_TBs = 1, .threadPool = &get_nrUE_params()->Tpool, - .TBs = TBs + .TBs = &TB_parameters }; - int max_num_segments = 0; + uint8_t dmrs_Type = dlsch_config->dmrsConfigType; + int harq_pid = dlsch_config->harq_process_nbr; + AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); + fapi_nr_dl_cw_info_t *cw_info = &dlsch->cw_info; + NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[cw_idx][dlsch_config->harq_process_nbr]; + LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, cw_info->rv); + uint8_t nb_re_dmrs; + if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) + nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups; + else + nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups; + uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos); - for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) { - uint8_t DLSCH_id = DLSCH_ids[pdsch_id]; - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; - uint8_t dmrs_Type = dlsch_config->dmrsConfigType; - int harq_pid = dlsch_config->harq_process_nbr; - NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid]; + TB_parameters.harq_unique_pid = 2 * harq_pid + cw_idx; + TB_parameters.G = G; + TB_parameters.nb_rb = number_rbs; + TB_parameters.Qm = cw_info->qamModOrder; + TB_parameters.mcs = cw_info->mcs; + TB_parameters.nb_layers = cw_info->Nl; + TB_parameters.BG = cw_info->ldpcBaseGraph; + TB_parameters.A = cw_info->TBS; + TB_parameters.processedSegments = &harq_process->processedSegments; - AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); - uint8_t nb_re_dmrs; + float Coderate = (float)cw_info->targetCodeRate / 10240.0f; - LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv); - - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) - nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups; - else - nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups; - uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos); - - if (!harq_process) { - LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n"); - return; - } - - nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id]; - - /* Neither harq_pid nor DLSCH_id are unique in the instance - * but their combination is. - * Since DLSCH_id < 2 - * then 2 * harq_pid + DLSCH_id is unique. - */ - TB_parameters->harq_unique_pid = 2 * harq_pid + DLSCH_id; - - // ------------------------------------------------------------------ - TB_parameters->G = G[DLSCH_id]; - TB_parameters->nb_rb = number_rbs; - TB_parameters->Qm = dlsch_config->qamModOrder; - TB_parameters->mcs = dlsch_config->mcs; - TB_parameters->nb_layers = dlsch[DLSCH_id].Nl; - TB_parameters->BG = dlsch_config->ldpcBaseGraph; - TB_parameters->A = dlsch_config->TBS; - // ------------------------------------------------------------------ - - TB_parameters->processedSegments = &harq_process->processedSegments; - - float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f; - - LOG_D( - PHY, + LOG_D(PHY, "%d.%d DLSCH %d Decoding, harq_pid %d TBS %d G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d " "Coderate %f\n", slot_parameters.frame, slot_parameters.slot, - DLSCH_id, + cw_idx, harq_pid, - dlsch_config->TBS, - TB_parameters->G, + cw_info->TBS, + G, nb_re_dmrs, dmrs_length, - TB_parameters->mcs, - TB_parameters->nb_layers, + TB_parameters.mcs, + TB_parameters.nb_layers, dlsch_config->number_symbols, - TB_parameters->nb_rb, - TB_parameters->Qm, + TB_parameters.nb_rb, + TB_parameters.Qm, Coderate); - if (harq_process->first_rx == 1) { - // This is a new packet, so compute quantities regarding segmentation - nr_segmentation(NULL, - NULL, - lenWithCrc(1, TB_parameters->A), // We give a max size in case of 1 segment - &TB_parameters->C, - &TB_parameters->K, - &TB_parameters->Z, // [hna] Z is Zc - &TB_parameters->F, - TB_parameters->BG); - harq_process->C = TB_parameters->C; - harq_process->K = TB_parameters->K; - harq_process->Z = TB_parameters->Z; - harq_process->F = TB_parameters->F; + if (harq_process->first_rx == 1) { + // This is a new packet, so compute quantities regarding segmentation + nr_segmentation(NULL, + NULL, + lenWithCrc(1, TB_parameters.A), // We give a max size in case of 1 segment + &TB_parameters.C, + &TB_parameters.K, + &TB_parameters.Z, // [hna] Z is Zc + &TB_parameters.F, + TB_parameters.BG); + harq_process->C = TB_parameters.C; + harq_process->K = TB_parameters.K; + harq_process->Z = TB_parameters.Z; + harq_process->F = TB_parameters.F; - if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A); - return; - } - - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100)) - LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters->nb_layers); - // clear HARQ buffer - for (int i = 0; i < harq_process->C; i++) - memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t)); - } else { - // This is not a new packet, so retrieve previously computed quantities regarding segmentation - TB_parameters->C = harq_process->C; - TB_parameters->K = harq_process->K; - TB_parameters->Z = harq_process->Z; - TB_parameters->F = harq_process->F; + if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters.nb_layers) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters.A); + return; } - max_num_segments = max(max_num_segments, TB_parameters->C); - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K); - - TB_parameters->max_ldpc_iterations = dlsch[DLSCH_id].max_ldpc_iterations; - TB_parameters->rv_index = dlsch_config->rv; - TB_parameters->tbslbrm = dlsch_config->tbslbrm; - TB_parameters->abort_decode = &harq_process->abort_decode; - set_abort(&harq_process->abort_decode, false); + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100)) + LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters.nb_layers); + // clear HARQ buffer + for (int i = 0; i < harq_process->C; i++) + memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t)); + } else { + // This is not a new packet, so retrieve previously computed quantities regarding segmentation + TB_parameters.C = harq_process->C; + TB_parameters.K = harq_process->K; + TB_parameters.Z = harq_process->Z; + TB_parameters.F = harq_process->F; } - nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments]; + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K); + + TB_parameters.max_ldpc_iterations = dlsch->max_ldpc_iterations; + TB_parameters.rv_index = cw_info->rv; + TB_parameters.tbslbrm = dlsch_config->tbslbrm; + TB_parameters.abort_decode = &harq_process->abort_decode; + set_abort(&harq_process->abort_decode, false); + + nrLDPC_segment_decoding_parameters_t segments[TB_parameters.C]; memset(segments, 0, sizeof(segments)); - bool d_to_be_cleared[nb_dlsch][max_num_segments]; + bool d_to_be_cleared[TB_parameters.C]; memset(d_to_be_cleared, 0, sizeof(d_to_be_cleared)); - for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) { - uint8_t DLSCH_id = DLSCH_ids[pdsch_id]; - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; - int harq_pid = dlsch_config->harq_process_nbr; - NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid]; + TB_parameters.segments = segments; - nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id]; - TB_parameters->segments = segments[pdsch_id]; + uint32_t r_offset = 0; + for (int r = 0; r < TB_parameters.C; r++) { + if (harq_process->first_rx == 1) + d_to_be_cleared[r] = true; + else + d_to_be_cleared[r] = false; + nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters.segments[r]; + segment_parameters->E = nr_get_E(TB_parameters.G, + TB_parameters.C, + TB_parameters.Qm, + TB_parameters.nb_layers, + r); + segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters.rv_index, + segment_parameters->E, + TB_parameters.BG, + TB_parameters.Z, + &harq_process->llrLen, + harq_process->DLround); + segment_parameters->llr = dlsch_llr + r_offset; + segment_parameters->d = harq_process->d[r]; + segment_parameters->d_to_be_cleared = &d_to_be_cleared[r]; + segment_parameters->c = harq_process->c[r]; + segment_parameters->decodeSuccess = false; - uint32_t r_offset = 0; - for (int r = 0; r < TB_parameters->C; r++) { - if (harq_process->first_rx == 1) - d_to_be_cleared[pdsch_id][r] = true; - else - d_to_be_cleared[pdsch_id][r] = false; - nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; - segment_parameters->E = nr_get_E(TB_parameters->G, - TB_parameters->C, - TB_parameters->Qm, - TB_parameters->nb_layers, - r); - segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index, - segment_parameters->E, - TB_parameters->BG, - TB_parameters->Z, - &harq_process->llrLen, - harq_process->DLround); - segment_parameters->llr = dlsch_llr[DLSCH_id] + r_offset; - segment_parameters->d = harq_process->d[r]; - segment_parameters->d_to_be_cleared = &d_to_be_cleared[pdsch_id][r]; - segment_parameters->c = harq_process->c[r]; - segment_parameters->decodeSuccess = false; + reset_meas(&segment_parameters->ts_deinterleave); + reset_meas(&segment_parameters->ts_rate_unmatch); + reset_meas(&segment_parameters->ts_ldpc_decode); - reset_meas(&segment_parameters->ts_deinterleave); - reset_meas(&segment_parameters->ts_rate_unmatch); - reset_meas(&segment_parameters->ts_ldpc_decode); - - r_offset += segment_parameters->E; - } + r_offset += segment_parameters->E; } int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters); @@ -224,114 +189,90 @@ void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, return; } - // post decode - for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) { - uint8_t DLSCH_id = DLSCH_ids[pdsch_id]; - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; - int harq_pid = dlsch_config->harq_process_nbr; - NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid]; - - nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id]; - - uint32_t offset = 0; - for (int r = 0; r < TB_parameters->C; r++) { - nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; - if (segment_parameters->decodeSuccess) { - memcpy(b[DLSCH_id] + offset, - harq_process->c[r], - (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - } else { - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; - LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, dlsch_config->rv); - LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C); - LOG_D(PHY, "DLSCH %d in error\n", DLSCH_id); - } - offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0); - - merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &segment_parameters->ts_deinterleave); - merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &segment_parameters->ts_rate_unmatch); - merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &segment_parameters->ts_ldpc_decode); - - } - - kpiStructure.nb_total++; - kpiStructure.blockSize = dlsch_config->TBS; - kpiStructure.dl_mcs = dlsch_config->mcs; - kpiStructure.nofRBs = number_rbs; - - harq_process->decodeResult = harq_process->processedSegments == harq_process->C; - - if (harq_process->decodeResult && harq_process->C > 1) { - /* check global CRC */ - int A = dlsch->dlsch_config.TBS; - // we have regrouped the transport block - if (!check_crc(b[DLSCH_id], lenWithCrc(1, A), crcType(1, A))) { - LOG_E(PHY, - " Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n", - proc->frame_rx, - proc->nr_slot_rx, - harq_process->C); - harq_process->decodeResult = false; - } - } - - if (harq_process->decodeResult) { - // We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we - const int sz = dlsch->dlsch_config.TBS / 8; - if (b[DLSCH_id][sz] == 0 && b[DLSCH_id][sz + 1] == 0) { - // do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24) - int i = 0; - while (b[DLSCH_id][i] == 0 && i < sz) - i++; - if (i == sz) { - LOG_E(PHY, - "received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the " - "corresponding CRC, and nothing prevents to have a all 0 packet\n"); - harq_process->decodeResult = false; - } - } - } - - if (harq_process->decodeResult) { - LOG_D(PHY, "DLSCH received ok \n"); - harq_process->status = NR_SCH_IDLE; - dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1; + uint32_t offset = 0; + for (int r = 0; r < TB_parameters.C; r++) { + nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters.segments[r]; + if (segment_parameters->decodeSuccess) { + memcpy(b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); } else { - LOG_D(PHY, "DLSCH received nok \n"); - kpiStructure.nb_nack++; - dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations; - UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK"); + LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, cw_info->rv); + LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C); } + offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0); - uint8_t dmrs_Type = dlsch_config->dmrsConfigType; - uint8_t nb_re_dmrs; - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) - nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups; - else - nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups; - uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos); - float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f; - LOG_D(PHY, - "%d.%d DLSCH Decoded, harq_pid %d, round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d " - "nb_symb_sch %d " - "nb_rb %d Qm %d Coderate %f\n", - proc->frame_rx, - proc->nr_slot_rx, - harq_pid, - harq_process->DLround, - harq_process->decodeResult, - dlsch->dlsch_config.TBS, - dlsch->dlsch_config.TBS / 8, - G[DLSCH_id], - nb_re_dmrs, - dmrs_length, - dlsch->dlsch_config.mcs, - dlsch->Nl, - dlsch_config->number_symbols, - number_rbs, - dlsch_config->qamModOrder, - Coderate); + merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &segment_parameters->ts_deinterleave); + merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &segment_parameters->ts_rate_unmatch); + merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &segment_parameters->ts_ldpc_decode); } + kpiStructure.nb_total++; + kpiStructure.blockSize = cw_info->TBS; + kpiStructure.dl_mcs = cw_info->mcs; + kpiStructure.nofRBs = number_rbs; + + harq_process->decodeResult = harq_process->processedSegments == harq_process->C; + + if (harq_process->decodeResult && harq_process->C > 1) { + /* check global CRC */ + // we have regrouped the transport block + if (!check_crc(b, lenWithCrc(1, cw_info->TBS), crcType(1, cw_info->TBS))) { + LOG_E(PHY, + " Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n", + proc->frame_rx, + proc->nr_slot_rx, + harq_process->C); + harq_process->decodeResult = false; + } + } + + if (harq_process->decodeResult) { + // We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we + const int sz = cw_info->TBS / 8; + if (b[sz] == 0 && b[sz + 1] == 0) { + // do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24) + int i = 0; + while (b[i] == 0 && i < sz) + i++; + if (i == sz) { + LOG_E(PHY, + "received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the " + "corresponding CRC, and nothing prevents to have a all 0 packet\n"); + harq_process->decodeResult = false; + } + } + } + + if (harq_process->decodeResult) { + LOG_D(PHY, "DLSCH received ok \n"); + harq_process->status = NR_SCH_IDLE; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1; + } else { + LOG_D(PHY, "DLSCH received nok \n"); + kpiStructure.nb_nack++; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations; + UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK"); + } + + LOG_D(PHY, + "%d.%d DLSCH Decoded, harq_pid %d, cw_idx %d round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d " + "nb_symb_sch %d " + "nb_rb %d Qm %d Coderate %f\n", + proc->frame_rx, + proc->nr_slot_rx, + harq_pid, + cw_idx, + harq_process->DLround, + harq_process->decodeResult, + cw_info->TBS, + cw_info->TBS / 8, + G, + nb_re_dmrs, + dmrs_length, + cw_info->mcs, + cw_info->Nl, + dlsch_config->number_symbols, + number_rbs, + cw_info->qamModOrder, + Coderate); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 6dea229ef5..c94dfef849 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -856,12 +856,12 @@ static void nr_dlsch_layer_demapping(const uint8_t Nl, const uint8_t mod_order, const int llrLayerSize, const int16_t llr_layers[NR_SYMBOLS_PER_SLOT][Nl][llrLayerSize], - const NR_UE_DLSCH_t *dlsch, + const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, const uint32_t re_len[NR_SYMBOLS_PER_SLOT], int16_t *llr) { - const int s0 = dlsch->dlsch_config.start_symbol; - const int s1 = dlsch->dlsch_config.number_symbols; + const int s0 = dlsch_config->start_symbol; + const int s1 = dlsch_config->number_symbols; int k = 0; switch (Nl) { @@ -901,28 +901,28 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch, const c16_t dl_ch_magb[rx_size_symbol], const c16_t dl_ch_magr[rx_size_symbol], const int nb_antennas_rx, - const c16_t rxdataF_comp[dlsch->Nl][nb_antennas_rx][rx_size_symbol], + const c16_t rxdataF_comp[dlsch->cw_info.Nl][nb_antennas_rx][rx_size_symbol], const int llrSize, - int16_t layer_llr[dlsch->Nl][llrSize]) + int16_t layer_llr[dlsch->cw_info.Nl][llrSize]) { - switch (dlsch->dlsch_config.qamModOrder) { + switch (dlsch->cw_info.qamModOrder) { case 2 : - for (int l = 0; l < dlsch[0].Nl; l++) + for (int l = 0; l < dlsch->cw_info.Nl; l++) nr_qpsk_llr(rxdataF_comp[l][0], layer_llr[l], len); break; case 4 : - for (int l = 0; l < dlsch[0].Nl; l++) + for (int l = 0; l < dlsch->cw_info.Nl; l++) nr_16qam_llr(rxdataF_comp[l][0], dl_ch_mag, layer_llr[l], len); break; case 6 : - for(int l=0; l < dlsch[0].Nl; l++) + for(int l=0; l < dlsch->cw_info.Nl; l++) nr_64qam_llr(rxdataF_comp[l][0], dl_ch_mag, dl_ch_magb, layer_llr[l], len); break; case 8: - for(int l=0; l < dlsch[0].Nl; l++) + for(int l=0; l < dlsch->cw_info.Nl; l++) nr_256qam_llr(rxdataF_comp[l][0], dl_ch_mag, dl_ch_magb, @@ -943,23 +943,25 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch, /* Main Function */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t dlsch[2], + NR_UE_DLSCH_t *dlsch, const freq_alloc_bitmap_t *freq_alloc, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, + NR_DL_UE_HARQ_t *dlsch_harq, unsigned char symbol, bool first_symbol_flag, unsigned char harq_pid, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size], - int16_t *llr[2], + int16_t *llr, uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], int32_t *log2_maxh, int rx_size_symbol, int nbRx, - 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 rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], + c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], + c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], + c16_t dl_ch_magr[][dlsch->cw_info.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, @@ -967,7 +969,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, pdsch_scope_req_t *scope_req) { NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - const int nl = dlsch[0].Nl; + const int nl = dlsch->cw_info.Nl; const int n_rx = fp->nb_antennas_rx; const int matrixSz = n_rx * nl; __attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol]; @@ -979,72 +981,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const int gNB_id = proc->gNB_id; uint8_t slot = 0; - int32_t codeword_TB0 = -1; - int32_t codeword_TB1 = -1; - uint32_t nb_re_pdsch = -1; - - NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL; - dlsch0_harq = &ue->dl_harq_processes[0][harq_pid]; - if (NR_MAX_NB_LAYERS>4) - dlsch1_harq = &ue->dl_harq_processes[1][harq_pid]; - - if (dlsch0_harq && dlsch1_harq){ - - LOG_D(PHY, - "AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", - frame, - nr_slot_rx, - symbol, - harq_pid, - dlsch0_harq->status, - dlsch1_harq->status); - - if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){ - codeword_TB0 = dlsch0_harq->codeword; // SV: where is this set? revisit for DL MIMO. - codeword_TB1 = dlsch1_harq->codeword; - dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid]; - dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid]; - - DEBUG_HARQ("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1); - - } else if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status != NR_ACTIVE) ) { - codeword_TB0 = dlsch0_harq->codeword; - dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid]; - dlsch1_harq = NULL; - - DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0); - - } else if ((dlsch0_harq->status != NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){ - codeword_TB1 = dlsch1_harq->codeword; - dlsch0_harq = NULL; - dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid]; - - DEBUG_HARQ("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1); - LOG_E(PHY, "[DEMOD] slot %d TB0 not active and TB1 active case is not supported\n", nr_slot_rx); - return -1; - - } else { - LOG_E(PHY, "[DEMOD] slot %d: no active DLSCH (2 layers case)\n", nr_slot_rx); - return (-1); - } - } else if (dlsch0_harq) { - if (dlsch0_harq->status == NR_ACTIVE) { - codeword_TB0 = dlsch0_harq->codeword; - dlsch0_harq = &ue->dl_harq_processes[0][harq_pid]; - DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active\n"); - } else { - LOG_E(PHY, "[DEMOD] slot %d nr_rx_pdsch no active DLSCH (one layer case)\n", nr_slot_rx); - return (-1); - } - } else { - LOG_E(PHY, "[DEMOD] slot %d Inconsistent call to nr_rx_pdsch (no layer 0)\n", nr_slot_rx); - return -1; - } - - DEBUG_HARQ("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1); - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config; - DevAssert(dlsch0_harq); + DevAssert(dlsch_harq); if (gNB_id > 2) { LOG_E(PHY, "Illegal gNB_id %d\n", gNB_id); @@ -1229,7 +1167,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, fp, symbol, nb_re_pdsch, - dlsch_config->qamModOrder, + dlsch->cw_info.qamModOrder, nb_rb_pdsch, *log2_maxh); // log2_maxh+I0_shift stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_COMPENSATION_STATS); @@ -1286,7 +1224,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dl_ch_magb[symbol], dl_ch_magr[symbol], dl_ch_estimates_ext, - dlsch_config->qamModOrder, + dlsch->cw_info.qamModOrder, *log2_maxh, symbol, nb_re_pdsch, @@ -1312,14 +1250,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, int nbSymb = 0; int pduBitmap = 0; - if(dlsch0_harq->status == NR_ACTIVE) { + if(dlsch_harq->status == NR_ACTIVE) { startSymbIdx = dlsch_config->start_symbol; nbSymb = dlsch_config->number_symbols; pduBitmap = dlsch_config->pduBitmap; } /* Check for PTRS bitmap and process it respectively */ - if((pduBitmap & 0x1) && (dlsch[0].rnti_type == TYPE_C_RNTI_)) { + if((pduBitmap & 0x1) && (dlsch->rnti_type == TYPE_C_RNTI_)) { nr_pdsch_ptrs_processing(nbRx, ptrs_phase_per_slot, ptrs_re_per_slot, @@ -1327,13 +1265,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nl, rxdataF_comp, fp, - dlsch0_harq, - dlsch1_harq, + dlsch_config, nr_slot_rx, symbol, freq_alloc->num_rbs, - dlsch[0].rnti, - dlsch); + dlsch->rnti, + &dlsch->ptrs_symbols, + &dlsch->ptrs_symbol_index); dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol]; } /* at last symbol in a slot calculate LLR's for whole slot */ @@ -1341,7 +1279,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, /* create LLR layer buffer */ int max_symb_re = 0; GET_ARRAY_MAX(dl_valid_re, NR_SYMBOLS_PER_SLOT, max_symb_re); - const int llr_per_symbol = max_symb_re * dlsch->dlsch_config.qamModOrder; + const int llr_per_symbol = max_symb_re * dlsch->cw_info.qamModOrder; __attribute__((aligned(32))) int16_t layer_llr[NR_SYMBOLS_PER_SLOT][nl][llr_per_symbol]; // Generate LLR from PTRS compensated signal @@ -1360,14 +1298,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, } stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); - nr_dlsch_layer_demapping(nl, dlsch_config->qamModOrder, llr_per_symbol, layer_llr, dlsch, dl_valid_re, llr[0]); + nr_dlsch_layer_demapping(nl, dlsch->cw_info.qamModOrder, llr_per_symbol, layer_llr, dlsch_config, dl_valid_re, llr); stop_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); - /* - for (int i=0; i < 2; i++){ - snprintf(filename, 50, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx); - write_output(filename,"llr", &llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb_pdsch*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb_pdsch*4*dlsch1_harq->Qm), 1, 0); - } - */ + if (UEScopeHasTryLock(ue)) { metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx }; int total_valid_res = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 77b7d7964a..ca9ac4872a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -446,7 +446,8 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, - NULL, + 0, + 0, NULL, number_pdus, proc, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 89f868b210..924ab86aed 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -404,7 +404,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, if (decoderState) { if (ue) { // decoding failed in synced state nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, NULL, NULL); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication); } @@ -464,7 +464,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, if (ue) { nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, (void *)result, NULL); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index ed269cd1de..a53cd2bc59 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -60,19 +60,17 @@ int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb @param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation @param[in] b @param[in] G array of Gs - @param[in] nb_dlsch number of active downlink shared channels - @param[in] DLSCH_ids array of active downlink shared channels @returns 0 on success, 1 on unsuccessful decoding */ void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t *dlsch, - short **dlsch_llr, - uint8_t **b, - int *G, - int nb_dlsch, + int cw_idx, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, + int16_t *dlsch_llr, + uint8_t *b, int number_rbs, - uint8_t *DLSCH_ids); + int G); int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue, const NR_UE_ULSCH_t *ulsch, @@ -278,23 +276,25 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue, */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t dlsch[2], + NR_UE_DLSCH_t *dlsch, const freq_alloc_bitmap_t *freq_alloc, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, + NR_DL_UE_HARQ_t *dlsch_harq, unsigned char symbol, bool first_symbol_flag, unsigned char harq_pid, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size], - int16_t *llr[2], + int16_t *llr, uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], int32_t *log2_maxh, int rx_size_symbol, int nbRx, - 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 rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], + c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], + c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], + c16_t dl_ch_magr[][dlsch->cw_info.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, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index f269b2694d..411fe655de 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -97,16 +97,13 @@ typedef struct { } NR_DL_UE_HARQ_t; typedef struct { + fapi_nr_dl_cw_info_t cw_info; /// RNTI uint16_t rnti; /// RNTI type uint8_t rnti_type; /// Active flag for DLSCH demodulation bool active; - /// Structure to hold dlsch config from MAC - fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config; - /// Number of MIMO layers (streams) - uint8_t Nl; /// Maximum number of LDPC iterations uint8_t max_ldpc_iterations; /// number of iterations used in last turbo decoding diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 3f4c29bdaf..03615427c1 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -521,8 +521,9 @@ typedef struct nr_phy_data_tx_s { typedef struct nr_phy_data_s { NR_UE_PDCCH_CONFIG phy_pdcch_config; + fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config; NR_UE_DLSCH_t dlsch[2]; - + int n_dlsch_codewords; // Sidelink Rx action decided by MAC sl_nr_rx_config_type_enum_t sl_rx_action; NR_UE_CSI_RS csirs_vars; @@ -535,7 +536,7 @@ enum stream_status_e { STREAM_STATUS_UNSYNC, STREAM_STATUS_SYNCING, STREAM_STATU */ typedef struct nr_rxtx_thread_data_s { UE_nr_rxtx_proc_t proc; - PHY_VARS_NR_UE *UE; + PHY_VARS_NR_UE *UE; int writeBlockSize; nr_phy_data_t phy_data; dynamic_barrier_t* next_barrier; diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 415e4442d9..7696f1f893 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -102,8 +102,9 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t pdu_type, PHY_VARS_NR_UE *ue, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, + int cw_idx, + int harq_pid, + NR_UE_DLSCH_t *dlsch, uint16_t n_pdus, const UE_nr_rxtx_proc_t *proc, void *typeSpecific, diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 4a521f5613..93d6681af0 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -21,48 +21,44 @@ extern PHY_VARS_NR_UE ***PHY_vars_UE_g; const char *const dl_pdu_type[] = {"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"}; const char *const ul_pdu_type[] = {"PRACH", "PUCCH", "PUSCH", "SRS"}; -static void configure_dlsch(NR_UE_DLSCH_t *dlsch0, +static void configure_dlsch(NR_UE_DLSCH_t *dlsch, NR_DL_UE_HARQ_t *harq_list, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, NR_UE_MAC_INST_t *mac, + int cw_idx, int rnti) { const uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr; - dlsch0->active = true; - dlsch0->rnti = rnti; + dlsch->active = true; + dlsch->rnti = rnti; - LOG_D(PHY,"current_harq_pid = %d\n", current_harq_pid); + LOG_D(PHY,"Configure DLSCH for pid = %d\n", current_harq_pid); - NR_DL_UE_HARQ_t *dlsch0_harq = &harq_list[current_harq_pid]; + NR_DL_UE_HARQ_t *dlsch_harq = &harq_list[current_harq_pid]; + dlsch->cw_info = dlsch_config_pdu->cw_info[cw_idx]; - //get nrOfLayers from DCI info - uint8_t Nl = 0; - for (int i = 0; i < 12; i++) { // max 12 ports - if ((dlsch_config_pdu->dmrs_ports >> i) & 0x01) - Nl += 1; - } - if (Nl == 0) { - LOG_E(PHY, "Invalid number of layers %d for DLSCH\n", Nl); + if (dlsch->cw_info.Nl == 0) { + LOG_E(PHY, "Invalid number of layers %d for DLSCH\n", dlsch->cw_info.Nl); // setting NACK for this TB - dlsch0->active = false; - update_harq_status(mac, current_harq_pid, 0); + dlsch->active = false; + update_harq_status(mac, current_harq_pid, cw_idx, 0); return; } - dlsch0->Nl = Nl; - if (dlsch_config_pdu->new_data_indicator) { - dlsch0_harq->first_rx = true; - dlsch0_harq->DLround = 0; + + if (dlsch->cw_info.new_data_indicator) { + dlsch_harq->first_rx = true; + dlsch_harq->DLround = 0; } else { - dlsch0_harq->first_rx = false; - dlsch0_harq->DLround++; + dlsch_harq->first_rx = false; + dlsch_harq->DLround++; } - downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->new_data_indicator, dlsch_config_pdu->rv, dlsch0->rnti_type); - if (dlsch0_harq->status != NR_ACTIVE) { - // dlsch0_harq->status not ACTIVE due to false retransmission + downlink_harq_process(dlsch_harq, current_harq_pid, dlsch->cw_info.new_data_indicator, dlsch->cw_info.rv, dlsch->rnti_type); + if (dlsch_harq->status != NR_ACTIVE) { + // dlsch_harq->status not ACTIVE due to false retransmission // Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status - dlsch0->active = false; + dlsch->active = false; LOG_W(NR_MAC, "dlsch0_harq->status not ACTIVE due to false retransmission harq pid: %d\n", current_harq_pid); - update_harq_status(mac, current_harq_pid, dlsch0_harq->decodeResult); + update_harq_status(mac, current_harq_pid, cw_idx, dlsch_harq->decodeResult); } } @@ -161,23 +157,28 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac, case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH: { fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15; NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0; + phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords; + phy_data->dlsch_config = *dlsch_config_pdu; dlsch0->rnti_type = TYPE_RA_RNTI_; - dlsch0->dlsch_config = *dlsch_config_pdu; - configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti); + configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, 0, pdu->dlsch_config_pdu.rnti); } break; case FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH: { fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15; NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0; + phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords; + phy_data->dlsch_config = *dlsch_config_pdu; dlsch0->rnti_type = TYPE_SI_RNTI_; - dlsch0->dlsch_config = *dlsch_config_pdu; - configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti); + configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, 0, pdu->dlsch_config_pdu.rnti); } break; case FAPI_NR_DL_CONFIG_TYPE_DLSCH: { fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15; - NR_UE_DLSCH_t *dlsch0 = &phy_data->dlsch[0]; - dlsch0->rnti_type = TYPE_C_RNTI_; - dlsch0->dlsch_config = *dlsch_config_pdu; - configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti); + phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords; + phy_data->dlsch_config = *dlsch_config_pdu; + for (int c = 0; c < dlsch_config_pdu->n_codewords; c++) { + NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[c]; + dlsch->rnti_type = TYPE_C_RNTI_; + configure_dlsch(dlsch, phy->dl_harq_processes[c], dlsch_config_pdu, mac, c, pdu->dlsch_config_pdu.rnti); + } } break; case FAPI_NR_CONFIG_TA_COMMAND: configure_ta_command(phy, &pdu->ta_command_pdu); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h index 90085746da..8d749283a0 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h @@ -29,6 +29,6 @@ void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config); \param synch_request including target_Nid_cell*/ void nr_ue_synch_request(nr_synch_request_t *synch_request); -void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack); +void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, int cw_idx, uint8_t ack_nack); #endif diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 2d09377b5b..c0aaf2978b 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -94,31 +94,35 @@ static uint32_t get_ssb_arfcn(NR_DL_FRAME_PARMS *frame_parms) uint64_t ssb_freq = frame_parms->dl_CarrierFreq - (band_size_hz / 2) + frame_parms->subcarrier_spacing * ssb_center_sc; return to_nrarfcn(ssb_freq); } + void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t pdu_type, PHY_VARS_NR_UE *ue, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, + int cw_idx, + int harq_pid, + NR_UE_DLSCH_t *dlsch, uint16_t n_pdus, const UE_nr_rxtx_proc_t *proc, void *typeSpecific, uint8_t *b) { - if (n_pdus > 1){ - LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__); + if (n_pdus > 1) { + LOG_E(PHY, "Multiple number of DL PDUs not supported yet...\n"); + return; } fapi_nr_rx_indication_body_t *rx = rx_ind->rx_indication_body + n_pdus - 1; switch (pdu_type){ case FAPI_NR_RX_PDU_TYPE_SIB: case FAPI_NR_RX_PDU_TYPE_RAR: case FAPI_NR_RX_PDU_TYPE_DLSCH: - if(dlsch0) { - NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; - rx->pdsch_pdu.harq_pid = dlsch0->dlsch_config.harq_process_nbr; - rx->pdsch_pdu.ack_nack = dl_harq0->decodeResult; + if(dlsch) { + NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[cw_idx][harq_pid]; + rx->pdsch_pdu.harq_pid = harq_pid; + rx->pdsch_pdu.cw_idx = cw_idx; + rx->pdsch_pdu.ack_nack = dl_harq->decodeResult; rx->pdsch_pdu.pdu = b; - rx->pdsch_pdu.pdu_length = dlsch0->dlsch_config.TBS / 8; - if (dl_harq0->decodeResult) { + rx->pdsch_pdu.pdu_length = dlsch->cw_info.TBS / 8; + if (dl_harq->decodeResult) { int t = WS_C_RNTI; if (pdu_type == FAPI_NR_RX_PDU_TYPE_RAR) t = WS_RA_RNTI; @@ -130,16 +134,13 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, .pdu_buffer_size = rx->pdsch_pdu.pdu_length, .ueid = 0, .rntiType = t, - .rnti = dlsch0->rnti, + .rnti = dlsch->rnti, .sysFrame = proc->frame_rx, .subframe = proc->nr_slot_rx, - .harq_pid = dlsch0->dlsch_config.harq_process_nbr}; + .harq_pid = harq_pid}; trace_pdu(&tmp); } } - if(dlsch1) { - AssertFatal(1==0,"Second codeword currently not supported\n"); - } break; case FAPI_NR_RX_PDU_TYPE_SSB: { if (typeSpecific) { @@ -168,7 +169,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx->pdu_type = pdu_type; rx_ind->number_pdus = n_pdus; - } int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){ @@ -488,8 +488,10 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t dlsch[2], - int16_t *llr[2], + NR_UE_DLSCH_t *dlsch, + NR_DL_UE_HARQ_t *dlsch_harq, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg, + int16_t *llr, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], int G, freq_alloc_bitmap_t *freq_alloc) @@ -502,11 +504,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, 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]; 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 " @@ -516,18 +515,18 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, frame_rx, nr_slot_rx, harq_pid, - dlsch0_harq->status, + dlsch_harq->status, dlschCfg->BWPStart, freq_alloc->first_rb, freq_alloc->last_rb, dlschCfg->start_symbol, dlschCfg->number_symbols, dlschCfg->dlDmrsSymbPos, - dlsch0->Nl); + dlsch->cw_info.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); + allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch->cw_info.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)); @@ -541,7 +540,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, c16_t, toFree2, ue->frame_parms.symbols_per_slot, - dlsch[0].Nl, + dlsch->cw_info.Nl, ue->frame_parms.nb_antennas_rx, rx_size_symbol, false); @@ -551,7 +550,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, 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 + for (int nl = 0; nl < dlsch->cw_info.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, @@ -580,7 +579,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, } } stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS); - nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx); + nvar /= (dlschCfg->number_symbols * dlsch->cw_info.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 @@ -589,7 +588,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, dlschCfg->number_symbols, dlschCfg->start_symbol, dlschCfg->dlDmrsSymbPos, - freq_alloc->num_rbs); + freq_alloc->num_rbs, + dlsch->cw_info.Nl); } uint16_t first_symbol_with_data = dlschCfg->start_symbol; @@ -630,7 +630,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, c16_t, toFree3, NR_SYMBOLS_PER_SLOT, - dlsch[0].Nl, + dlsch->cw_info.Nl, ue->frame_parms.nb_antennas_rx, rx_size_symbol, false); @@ -639,7 +639,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, c16_t, toFree4, NR_SYMBOLS_PER_SLOT, - dlsch[0].Nl, + dlsch->cw_info.Nl, ue->frame_parms.nb_antennas_rx, rx_size_symbol, false); @@ -648,7 +648,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, c16_t, toFree5, NR_SYMBOLS_PER_SLOT, - dlsch[0].Nl, + dlsch->cw_info.Nl, ue->frame_parms.nb_antennas_rx, rx_size_symbol, false); @@ -663,6 +663,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, proc, dlsch, freq_alloc, + dlschCfg, + dlsch_harq, m, first_symbol_flag, harq_pid, @@ -760,90 +762,68 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls */ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t dlsch[2], - int16_t *llr[2], - int G[2], - freq_alloc_bitmap_t *freq_alloc) + NR_UE_DLSCH_t *dlsch, + int cw_idx, + int G, + freq_alloc_bitmap_t *freq_alloc, + fapi_nr_dl_config_dlsch_pdu_rel15_t *config, + int16_t *llr) { - if (dlsch[0].active == false) { + if (dlsch->active == false) { LOG_E(PHY, "DLSCH should be active when calling this function\n"); return; } - int harq_pid = dlsch[0].dlsch_config.harq_process_nbr; + int harq_pid = config->harq_process_nbr; int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; - NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid]; - NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid]; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind = {0}; uint16_t number_pdus = 1; - uint8_t is_cw0_active = dl_harq0->status; - uint8_t is_cw1_active = dl_harq1->status; - int nb_dlsch = 0; - nb_dlsch += (is_cw0_active == NR_ACTIVE) ? 1 : 0; - nb_dlsch += (is_cw1_active == NR_ACTIVE) ? 1 : 0; - - LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw0_active); - LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw1_active); + LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW%d [harq_pid %d]\n", frame_rx % 1024, nr_slot_rx, cw_idx, harq_pid); + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; // exit dlsch procedures as there are no active dlsch - if (is_cw0_active != ACTIVE && is_cw1_active != NR_ACTIVE) { + NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[cw_idx][harq_pid]; + if (dl_harq->status != NR_ACTIVE) { // don't wait anymore LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid); - if (dlsch[0].dlsch_config.k1_feedback) { - const int ack_nack_slot_and_frame = - (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame; + if (config->k1_feedback) { + const int ack_nack_slot_and_frame = (proc->nr_slot_rx + config->k1_feedback) + proc->frame_rx * fp->slots_per_frame; dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]); } return; } - uint8_t DLSCH_ids[nb_dlsch]; - int pdsch_id = 0; - uint8_t *p_b[2] = {NULL}; - for (uint8_t DLSCH_id = 0; DLSCH_id < 2; DLSCH_id++) { - NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[DLSCH_id][harq_pid]; - if (dl_harq->status != NR_ACTIVE) - continue; - - DLSCH_ids[pdsch_id++] = DLSCH_id; - - start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); - nr_dlsch_unscrambling(llr[DLSCH_id], G[DLSCH_id], 0, dlsch[DLSCH_id].dlsch_config.dlDataScramblingId, dlsch[DLSCH_id].rnti); - stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); - - p_b[DLSCH_id] = dl_harq->b; - } + start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); + nr_dlsch_unscrambling(llr, G, 0, config->dlDataScramblingId, dlsch->rnti); + stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); - nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, freq_alloc->num_rbs, DLSCH_ids); + nr_dlsch_decoding(ue, proc, dlsch, cw_idx, config, llr, dl_harq->b, freq_alloc->num_rbs, G); stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); int ind_type = -1; - switch (dlsch[0].rnti_type) { + switch (dlsch->rnti_type) { case TYPE_RA_RNTI_: ind_type = FAPI_NR_RX_PDU_TYPE_RAR; break; - case TYPE_SI_RNTI_: ind_type = FAPI_NR_RX_PDU_TYPE_SIB; break; - case TYPE_C_RNTI_: ind_type = FAPI_NR_RX_PDU_TYPE_DLSCH; break; - default: - AssertFatal(true, "Invalid DLSCH type %d\n", dlsch[0].rnti_type); + AssertFatal(false, "Invalid DLSCH type %d\n", dlsch->rnti_type); break; } nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b[0]); + nr_fill_rx_indication(&rx_ind, ind_type, ue, cw_idx, harq_pid, dlsch, number_pdus, proc, NULL, dl_harq->b); - LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8); + LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch->cw_info.TBS, dlsch->cw_info.TBS / 8); if (cpumeas(CPUMEAS_GETSTATE)) { LOG_D(PHY, " --> Unscrambling %5.3f\n", @@ -861,9 +841,8 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } // DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH - if ((dlsch[0].rnti_type == TYPE_C_RNTI_ || dlsch[0].rnti_type == TYPE_RA_RNTI_) && dlsch[0].dlsch_config.k1_feedback) { - const int ack_nack_slot_and_frame = - (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame; + if ((dlsch->rnti_type == TYPE_C_RNTI_ || dlsch->rnti_type == TYPE_RA_RNTI_) && config->k1_feedback) { + const int ack_nack_slot_and_frame = (proc->nr_slot_rx + config->k1_feedback) + proc->frame_rx * fp->slots_per_frame; dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]); } @@ -874,11 +853,8 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment - if (ue->phy_sim_dlsch_b && is_cw0_active == NR_ACTIVE) - memcpy(ue->phy_sim_dlsch_b, p_b[0], dlsch_bytes); - else if (ue->phy_sim_dlsch_b && is_cw1_active == NR_ACTIVE) - memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes); - + if (ue->phy_sim_dlsch_b) + memcpy(ue->phy_sim_dlsch_b, dl_harq->b, dlsch_bytes); } static bool check_meas_to_perform(PHY_VARS_NR_UE *ue, int nr_slot_rx) @@ -1150,7 +1126,6 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ int nr_slot_rx = proc->nr_slot_rx; int gNB_id = proc->gNB_id; - NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[0]; // do procedures for C-RNTI bool slot_fep_map[14] = {0}; @@ -1182,9 +1157,13 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ nr_ue_csi_rs_procedures(ue, proc, rxdataF, &phy_data->csirs_vars.csirs_config_pdu); } - int G[2] = {0}; - if (dlsch[0].active) { - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config; + int16_t *llr[2]; + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &phy_data->dlsch_config; + for (int c = 0; c < phy_data->n_dlsch_codewords; c++) { + NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[c]; + if (!dlsch->active) + continue; + uint16_t nb_symb_sch = dlsch_config->number_symbols; uint16_t start_symb_sch = dlsch_config->start_symbol; @@ -1219,32 +1198,30 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ unav_res = n_ptrs * ptrsSymbPerSlot; } unav_res += compute_csi_rm_unav_res(dlsch_config); - G[0] = nr_get_G(freq_alloc.num_rbs, - dlsch_config->number_symbols, - nb_re_dmrs, - dmrs_len, - unav_res, - dlsch_config->qamModOrder, - dlsch[0].Nl); - const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G[0], 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++) - llr[i] = (int16_t *)malloc16_clear(rx_llr_buf_sz * sizeof(int16_t)); + int G = nr_get_G(freq_alloc.num_rbs, + dlsch_config->number_symbols, + nb_re_dmrs, + dmrs_len, + unav_res, + dlsch->cw_info.qamModOrder, + dlsch->cw_info.Nl); + const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G, 32); // each LLR is 2 bytes hence 64 byte aligned + llr[c] = (int16_t *)malloc16_clear(rx_llr_buf_sz * sizeof(int16_t)); + // dlsch_harq contains the previous transmissions data for this harq pid + NR_DL_UE_HARQ_t *harq = &ue->dl_harq_processes[c][dlsch_config->harq_process_nbr]; // it returns -1 in case of internal failure, or 0 in case of normal result - int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, llr, rxdataF, G[0], &freq_alloc); - TracyCPlot("pdsch mcs", dlsch->dlsch_config.mcs); + int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, harq, dlsch_config, llr[c], rxdataF, &freq_alloc); + TracyCPlot("pdsch mcs", dlsch->cw_info.mcs); - UEscopeCopy(ue, pdschLlr, llr[0], sizeof(int16_t), 1, G[0], 0); + UEscopeCopy(ue, pdschLlr, llr[c], sizeof(int16_t), 1, G, 0); LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx); start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS); if (ret_pdsch >= 0) { - nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G, &freq_alloc); - } - else { + nr_ue_dlsch_procedures(ue, proc, dlsch, c, G, &freq_alloc, dlsch_config, llr[c]); + } else { LOG_E(NR_PHY, "Demodulation impossible, internal error\n"); if (dlsch_config->k1_feedback) { const int ack_nack_slot_and_frame = @@ -1264,10 +1241,9 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ &rxdataF[0][start_symb_sch * ue->frame_parms.ofdm_symbol_size], sizeof(int32_t) * nb_symb_sch * ue->frame_parms.ofdm_symbol_size); if (ue->phy_sim_pdsch_llr) - memcpy(ue->phy_sim_pdsch_llr, llr[0], sizeof(int16_t) * rx_llr_buf_sz); + memcpy(ue->phy_sim_pdsch_llr, llr[c], sizeof(int16_t) * rx_llr_buf_sz); - for (int i=0; idl_harq_processes[0][harq_pid]; harq_process->first_rx = 1; - dlsch0_ue->dlsch_config.mcs = Imcs; - dlsch0_ue->dlsch_config.mcs_table = mcs_table; - dlsch0_ue->Nl = Nl; - dlsch0_ue->dlsch_config.number_rbs = nb_rb; - dlsch0_ue->dlsch_config.qamModOrder = mod_order; - dlsch0_ue->dlsch_config.rv = rvidx; - dlsch0_ue->dlsch_config.targetCodeRate = rate; - dlsch0_ue->dlsch_config.TBS = TBS; - dlsch0_ue->dlsch_config.ldpcBaseGraph = get_BG(TBS, rate); - dlsch0_ue->dlsch_config.dmrsConfigType = NFAPI_NR_DMRS_TYPE1; - dlsch0_ue->dlsch_config.dlDmrsSymbPos = 4; - dlsch0_ue->dlsch_config.n_dmrs_cdm_groups = 1; - dlsch0_ue->dlsch_config.tbslbrm = Tbslbrm; - printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch0_ue->dlsch_config.mcs, dlsch0_ue->dlsch_config.qamModOrder, nb_symb_sch); + fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config; + dlsch_config.cw_info[0].mcs = Imcs; + dlsch_config.mcs_table = mcs_table; + dlsch_config.number_rbs = nb_rb; + dlsch_config.cw_info[0].Nl = Nl; + dlsch_config.cw_info[0].qamModOrder = mod_order; + dlsch_config.cw_info[0].rv = rvidx; + dlsch_config.cw_info[0].targetCodeRate = rate; + dlsch_config.cw_info[0].TBS = TBS; + dlsch_config.cw_info[0].ldpcBaseGraph = get_BG(TBS, rate); + dlsch_config.dmrsConfigType = NFAPI_NR_DMRS_TYPE1; + dlsch_config.dlDmrsSymbPos = 4; + dlsch_config.n_dmrs_cdm_groups = 1; + dlsch_config.tbslbrm = Tbslbrm; + dlsch0_ue->cw_info = dlsch_config.cw_info[0]; + printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch_config.cw_info[0].mcs, dlsch_config.cw_info[0].qamModOrder, nb_symb_sch); uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding() dlsch->pdu = test_input; @@ -536,27 +538,23 @@ int main(int argc, char **argv) exit(-1); #endif - int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated - int num_rb = dlsch0_ue->dlsch_config.number_rbs; + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; // number of segments to be allocated + int num_rb = dlsch_config.number_rbs; if (num_rb != 273) { a_segments = a_segments*num_rb; a_segments = (a_segments/273)+1; } uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment __attribute__ ((aligned(32))) uint8_t b[dlsch_bytes]; - uint8_t DLSCH_ids[1] = {0}; - short *p_channel_output_fixed = channel_output_fixed; - uint8_t *p_b = b; - int available_bits_array[1] = { available_bits }; nr_dlsch_decoding(UE, &proc, dlsch0_ue, - &p_channel_output_fixed, - &p_b, - available_bits_array, - 1, + 0, + &dlsch_config, + channel_output_fixed, + b, num_rb, - DLSCH_ids); + available_bits); if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations) n_errors++; @@ -634,4 +632,3 @@ int main(int argc, char **argv) return (n_errors); } - diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 2c08ab3b6e..dd73881fb1 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1310,12 +1310,14 @@ int main(int argc, char **argv) int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; - TBS = dlsch0->dlsch_config.TBS; - uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos); - uint16_t nb_rb = dlsch0->dlsch_config.number_rbs; - uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups; - uint8_t mod_order = dlsch0->dlsch_config.qamModOrder; - uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols; + TBS = phy_data.dlsch_config.cw_info[0].TBS; + uint16_t length_dmrs = get_num_dmrs(phy_data.dlsch_config.dlDmrsSymbPos); + uint16_t nb_rb = phy_data.dlsch_config.number_rbs; + uint8_t nb_re_dmrs = phy_data.dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? + 6 * phy_data.dlsch_config.n_dmrs_cdm_groups : + 4 * phy_data.dlsch_config.n_dmrs_cdm_groups; + uint8_t mod_order = phy_data.dlsch_config.cw_info[0].qamModOrder; + uint8_t nb_symb_sch = phy_data.dlsch_config.number_symbols; uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb; available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers); if (pdu_bit_map & 0x1) { @@ -1457,10 +1459,10 @@ int main(int argc, char **argv) const int s = pdsch_pdu_rel15->StartSymbolIndex; const int n = pdsch_pdu_rel15->NrOfSymbols; for (int i = s; i < s + n; i++) { - const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos; - const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType; - const uint32_t nrb = phy_data.dlsch[0].dlsch_config.number_rbs; - const uint32_t ncdmg = phy_data.dlsch[0].dlsch_config.n_dmrs_cdm_groups; + const uint32_t dmrsBitMap = phy_data.dlsch_config.dlDmrsSymbPos; + const uint32_t dmrsCfg = phy_data.dlsch_config.dmrsConfigType; + const uint32_t nrb = phy_data.dlsch_config.number_rbs; + const uint32_t ncdmg = phy_data.dlsch_config.n_dmrs_cdm_groups; const uint32_t numValidReSym = ((dmrsBitMap >> i) & 1) ? ((dmrsCfg == NFAPI_NR_DMRS_TYPE1) ? nrb * (12 - 6 * ncdmg) : nrb * (12 - 4 * ncdmg)) : (nrb * 12); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index a06d61cda6..0a65b04330 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -83,8 +83,9 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t pdu_type, PHY_VARS_NR_UE *ue, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, + int cw_idx, + int harq_pid, + NR_UE_DLSCH_t *dlsch, uint16_t n_pdus, const UE_nr_rxtx_proc_t *proc, void *typeSpecific, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 6003693126..ea1b2b1dc5 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3033,7 +3033,7 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, size += 8; // TB2 long *maxCWperDCI = pdsch_Config ? pdsch_Config->maxNrofCodeWordsScheduledByDCI : NULL; - if ((maxCWperDCI != NULL) && (*maxCWperDCI == 2)) { + if (maxCWperDCI && (*maxCWperDCI == NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n2)) { size += 8; } // HARQ process number – 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-1-1 is configured; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 8029235fac..a1ef0b9f08 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -595,7 +595,7 @@ typedef struct NR_UE_MAC_INST_s { // Defined for abstracted mode nr_downlink_indication_t dl_info; - NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES]; + NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES][2]; // one harq process for each codeword NR_UE_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES]; NR_TAG_Id_t tag_Id; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 8576028f9b..a028c3ead6 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -200,12 +200,14 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) nr_mac->scheduling_info.phr_info.phr_reporting = 0; nr_mac->scheduling_info.phr_info.was_mac_reset = true; - // flush the soft buffers for all DL HARQ processes - memset(nr_mac->dl_harq_info, 0, sizeof(nr_mac->dl_harq_info)); - - // for each DL HARQ process, consider the next received transmission for a TB as the very first transmission - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) - nr_mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value + for (int c = 0; c < 2; c++) { + // flush the soft buffers for all DL HARQ processes + // for each DL HARQ process, consider the next received transmission for a TB as the very first transmission + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + memset(&nr_mac->dl_harq_info[k][c], 0, sizeof(NR_UE_DL_HARQ_STATUS_t)); + nr_mac->dl_harq_info[k][c].last_ndi = -1; // initialize to invalid value + } + } // release, if any, Temporary C-RNTI nr_mac->ra.t_crnti = 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 8be86c95ad..b1bcd1b1ed 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1190,7 +1190,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order) void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) { - NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid][0]; // single cw for MSG4 int sched_slot = current_harq->ul_slot; int sched_frame = current_harq->ul_frame; PUCCH_sched_t pucch = {.n_CCE = current_harq->n_CCE, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c index 66c5104458..177ddf7b1d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c @@ -218,9 +218,11 @@ int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame) const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(&mac->sc_info); for (int i = 0; i < num_dl_harq; i++) { - if (mac->dl_harq_info[i].active && mac->dl_harq_info[i].ul_slot == slot && mac->dl_harq_info[i].ul_frame == frame) { - delta_tpc_sum += mac->dl_harq_info[i].delta_pucch; - mac->dl_harq_info[i].delta_pucch = 0; + for (int c = 0; c < 2; c++) { + if (mac->dl_harq_info[i][c].active && mac->dl_harq_info[i][c].ul_slot == slot && mac->dl_harq_info[i][c].ul_frame == frame) { + delta_tpc_sum += mac->dl_harq_info[i][c].delta_pucch; + mac->dl_harq_info[i][c].delta_pucch = 0; + } } } return delta_tpc_sum; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f269d11f51..83a6693b23 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -435,6 +435,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p static void set_harq_status(NR_UE_MAC_INST_t *mac, uint8_t pucch_id, uint8_t harq_id, + int cw_id, int8_t delta_pucch, uint16_t data_toul_fb, uint8_t dai, @@ -443,7 +444,7 @@ static void set_harq_status(NR_UE_MAC_INST_t *mac, frame_t frame, int slot) { - NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id][cw_id]; current_harq->active = true; current_harq->ack_received = false; current_harq->pucch_resource_indicator = pucch_id; @@ -469,13 +470,15 @@ static void set_harq_status(NR_UE_MAC_INST_t *mac, // looking for other active HARQ processes with feedback in the same frame/slot if (i == harq_id) continue; - NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i]; - if (harq->active && - harq->ul_frame == current_harq->ul_frame && - harq->ul_slot == current_harq->ul_slot) { - // highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot - if (harq->dai_cumul > highest_dai) - highest_dai = harq->dai_cumul - 1; + for (int c = 0; c < 2; c++) { + NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i][c]; + if (harq->active && + harq->ul_frame == current_harq->ul_frame && + harq->ul_slot == current_harq->ul_slot) { + // highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot + if (harq->dai_cumul > highest_dai) + highest_dai = harq->dai_cumul - 1; + } } } @@ -667,6 +670,99 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac, return ret; } +// Table 7.3.1.3-1 of 38.211 +static int get_nl_for_cw(int Nl, int cw_idx) +{ + AssertFatal(Nl >= 0 && Nl <= 8, "Invalid number of layers %d\n", Nl); + if (Nl < 5) + return Nl; + else { + if (cw_idx == 0) + return Nl / 2; + else + return Nl / 2 + Nl % 2; + } +} + +static bool get_cw_info(NR_UE_DL_HARQ_STATUS_t *current_harq, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu, + uint8_t pdu_type, + fapi_nr_dl_cw_info_t *cw_info, + int number_rbs, + int nb_re_dmrs, + int nb_rb_oh, + int rv, + int mcs, + int ndi, + int cw_idx) +{ + uint8_t Nl = 0; + for (int i = 0; i < 12; i++) { // max 12 ports + if ((dlsch_pdu->dmrs_ports >> i) & 0x01) + Nl += 1; + } + + cw_info->mcs = mcs; + /* RV for transport block */ + cw_info->rv = rv; + /* NDI for transport block*/ + if (pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH || pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH || ndi != current_harq->last_ndi) { + // new data + cw_info->new_data_indicator = true; + current_harq->R = 0; + current_harq->TBS = 0; + } else + cw_info->new_data_indicator = false; + if (pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH && pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) { + current_harq->last_ndi = ndi; + if (cw_info->new_data_indicator) + current_harq->round = 0; + else + current_harq->round++; + } + cw_info->qamModOrder = nr_get_Qm_dl(cw_info->mcs, dlsch_pdu->mcs_table); + if (cw_info->qamModOrder == 0) { + LOG_W(NR_MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI\n"); + return false; + } + + cw_info->Nl = get_nl_for_cw(Nl, cw_idx); + int R = nr_get_code_rate_dl(cw_info->mcs, dlsch_pdu->mcs_table); + if (R > 0) { + cw_info->targetCodeRate = R; + cw_info->TBS = nr_compute_tbs(cw_info->qamModOrder, + R, + number_rbs, + dlsch_pdu->number_symbols, + nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos), + nb_rb_oh, + 0, + cw_info->Nl); + // storing for possible retransmissions + if (!cw_info->new_data_indicator && current_harq->TBS != cw_info->TBS) { + LOG_W(NR_MAC, + "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n", + cw_info->TBS, + current_harq->TBS); + cw_info->new_data_indicator = true; // treated as new data + } + current_harq->R = cw_info->targetCodeRate; + current_harq->TBS = cw_info->TBS; + } + else { + cw_info->targetCodeRate = current_harq->R; + cw_info->TBS = current_harq->TBS; + } + + if (cw_info->TBS == 0) { + LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); + return false; + } + cw_info->ldpcBaseGraph = get_BG(cw_info->TBS, cw_info->targetCodeRate); + + return true; +} + static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, @@ -789,7 +885,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, 0, dci->frequency_domain_assignment) < 0) { - LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); + LOG_W(NR_MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } @@ -873,76 +969,28 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, NULL, // SPS not implemented, false, // as above NULL); // MCS-C-RNTI not implemented - /* MCS */ - dlsch_pdu->mcs = dci->mcs; - NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; - /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ - if (dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH || - dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH || - dci->ndi != current_harq->last_ndi) { - // new data - dlsch_pdu->new_data_indicator = true; - current_harq->R = 0; - current_harq->TBS = 0; - } else { - dlsch_pdu->new_data_indicator = false; - } - - if (dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH && - dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) { - current_harq->last_ndi = dci->ndi; - } - - dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); - if (dlsch_pdu->qamModOrder == 0) { - LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); + int nb_re_dmrs = ((dlsch_pdu->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups; + int nb_rb_oh = mac->sc_info.xOverhead_PDSCH ? nb_rb_oh = 6 * (1 + *mac->sc_info.xOverhead_PDSCH) : 0; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val][0]; + if (!get_cw_info(current_harq, + dlsch_pdu, + dl_conf_req->pdu_type, + &dlsch_pdu->cw_info[0], + dlsch_pdu->number_rbs, + nb_re_dmrs, + nb_rb_oh, + dci->rv, + dci->mcs, + dci->ndi, + 0)) return -1; - } - int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); - if (R > 0) { - dlsch_pdu->targetCodeRate = R; - int nb_rb_oh; - if (mac->sc_info.xOverhead_PDSCH) - nb_rb_oh = 6 * (1 + *mac->sc_info.xOverhead_PDSCH); - else - nb_rb_oh = 0; - int nb_re_dmrs = ((dlsch_pdu->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups; - dlsch_pdu->TBS = nr_compute_tbs(dlsch_pdu->qamModOrder, - R, - dlsch_pdu->number_rbs, - dlsch_pdu->number_symbols, - nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos), - nb_rb_oh, - 0, - 1); - // storing for possible retransmissions - current_harq->R = dlsch_pdu->targetCodeRate; - if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) { - LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n", - dlsch_pdu->TBS, current_harq->TBS); - dlsch_pdu->new_data_indicator = true; // treated as new data - } - current_harq->TBS = dlsch_pdu->TBS; - } - else { - dlsch_pdu->targetCodeRate = current_harq->R; - dlsch_pdu->TBS = current_harq->TBS; - } - - dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate); - - if (dlsch_pdu->TBS == 0) { - LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); - return -1; - } + dlsch_pdu->n_codewords = 1; int bw_tbslbrm = current_DL_BWP ? mac->sc_info.dl_bw_tbslbrm : dlsch_pdu->BWPSize; dlsch_pdu->tbslbrm = nr_compute_tbslbrm(dlsch_pdu->mcs_table, bw_tbslbrm, 1); - /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ - dlsch_pdu->rv = dci->rv; /* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_pdu->harq_process_nbr = dci->harq_pid.val; /* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */ @@ -1009,6 +1057,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, set_harq_status(mac, dci->pucch_resource_indicator, dci->harq_pid.val, + 0, tpc[dci->tpc], feedback_ti, dci->dai[0].val, @@ -1017,10 +1066,6 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, frame, slot); } - if (dlsch_pdu->new_data_indicator) - current_harq->round = 0; - else - current_harq->round++; if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) mac->stats.dl.rounds[current_harq->round]++; } @@ -1043,9 +1088,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, "(nr_ue_procedures.c) vrb_to_prb_mapping=%d \n>>> mcs=%d\n>>> ndi=%d\n>>> rv=%d\n>>> harq_process_nbr=%d\n>>> dai=%d\n>>> " "scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n", dlsch_pdu->vrb_to_prb_mapping, - dlsch_pdu->mcs, - dlsch_pdu->new_data_indicator, - dlsch_pdu->rv, + dlsch_pdu->cw_info[0].mcs, + dlsch_pdu->cw_info[0].new_data_indicator, + dlsch_pdu->cw_info[0].rv, dlsch_pdu->harq_process_nbr, dci->dai[0].val, dlsch_pdu->scaling_factor_S, @@ -1055,7 +1100,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->k1_feedback = feedback_ti; - LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n\n", dl_conf_req->pdu_type); + LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n", dl_conf_req->pdu_type); // the prepared dci is valid, we add it in the list dl_config->number_pdus++; @@ -1213,9 +1258,6 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, dlsch_pdu->dmrsConfigType = dl_dmrs_config->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2; - /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214, - using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ - dlsch_pdu->n_dmrs_cdm_groups = 1; /* VRB_TO_PRB_MAPPING */ if ((pdsch_Config->resourceAllocation == 1) && (pdsch_Config->vrb_ToPRB_Interleaver != NULL)) dlsch_pdu->vrb_to_prb_mapping = @@ -1226,28 +1268,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, dlsch_pdu->rate_matching_ind = dci->rate_matching_indicator.val; /* ZP_CSI_RS_TRIGGER */ dlsch_pdu->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val; - /* MCS (for transport block 1)*/ - dlsch_pdu->mcs = dci->mcs; - /* NDI (for transport block 1)*/ - NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; - if (dci->ndi != current_harq->last_ndi) { - // new data - dlsch_pdu->new_data_indicator = true; - current_harq->R = 0; - current_harq->TBS = 0; - } - else { - dlsch_pdu->new_data_indicator = false; - } - current_harq->last_ndi = dci->ndi; - /* RV (for transport block 1)*/ - dlsch_pdu->rv = dci->rv; - /* MCS (for transport block 2)*/ - dlsch_pdu->tb2_mcs = dci->mcs2.val; - /* NDI (for transport block 2)*/ - dlsch_pdu->tb2_new_data_indicator = dci->ndi2.val; - /* RV (for transport block 2)*/ - dlsch_pdu->tb2_rv = dci->rv2.val; + /* HARQ_PROCESS_NUMBER */ dlsch_pdu->harq_process_nbr = dci->harq_pid.val; /* TPC_PUCCH */ @@ -1276,13 +1297,32 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, return -1; } + NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info; + int nb_rb_oh; + if (sc_info->xOverhead_PDSCH) + nb_rb_oh = 6 * (1 + *sc_info->xOverhead_PDSCH); + else + nb_rb_oh = 0; + /* ANTENNA_PORTS */ - uint8_t n_codewords = 1; // FIXME!!! long *max_length = dl_dmrs_config->maxLength; long *dmrs_type = dl_dmrs_config->dmrs_Type; + // In case the higher layer parameter maxNrofCodeWordsScheduledByDCI indicates that two codeword transmission is enabled, + // then one of the two transport blocks is disabled by DCI format 1_1 + // if IMCS = 26 and if rvid = 1 for the corresponding transport block + bool cw0 = true; + bool cw1 = true; + if (pdsch_Config->maxNrofCodeWordsScheduledByDCI + && *pdsch_Config->maxNrofCodeWordsScheduledByDCI == NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n2) { + cw0 = dci->rv != 1 || dci->mcs != 26; + cw1 = dci->rv2.val != 1 || dci->mcs2.val != 26; + } else + cw1 = false; + dlsch_pdu->n_front_load_symb = 1; // default value - set_antenna_port_parameters(dlsch_pdu, n_codewords, max_length, dmrs_type, dci->antenna_ports.val); + set_antenna_port_parameters(dlsch_pdu, cw0 + cw1, max_length, dmrs_type, dci->antenna_ports.val); + int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups; /* dmrs symbol positions*/ dlsch_pdu->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config, @@ -1293,6 +1333,105 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, tda_info.mapping_type, dlsch_pdu->n_front_load_symb); + dlsch_pdu->mcs_table = get_dlsch_mcs_table(NR_DL_DCI_FORMAT_1_1, + rnti_type, + dci_ind->ss_type, + pdsch_Config ? pdsch_Config->mcs_Table : NULL, + NULL, // SPS not implemented, + false, // as above + NULL); // MCS-C-RNTI not implemented + + /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ + // according to TS 38.213 Table 9.2.3-1 + const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing); + uint16_t feedback_ti = 0; + const int tpc[] = {-1, 0, 1, 3}; + if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) { + feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset; + AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing), + "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config " + "file (min_rxtxtime).\n", + feedback_ti, + GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing)); + } + + + int number_rbs; + if (dlsch_pdu->resource_alloc == 1) { + number_rbs = dlsch_pdu->number_rbs; + } else { + uint32_t temp_bitmap[9]; + memcpy(temp_bitmap, dlsch_pdu->rb_bitmap, 36); + number_rbs = count_bits(temp_bitmap, 9); + } + + int cw_idx = 0; + NR_UE_DL_HARQ_STATUS_t *current_harq = NULL; + if (cw0) { + current_harq = &mac->dl_harq_info[dci->harq_pid.val][0]; + if (get_cw_info(current_harq, + dlsch_pdu, + dl_conf_req->pdu_type, + &dlsch_pdu->cw_info[0], + number_rbs, + nb_re_dmrs, + nb_rb_oh, + dci->rv, + dci->mcs, + dci->ndi, + cw_idx)) { + if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) + mac->stats.dl.rounds[current_harq->round]++; + // set the harq status at MAC for feedback + set_harq_status(mac, + dci->pucch_resource_indicator, + dci->harq_pid.val, + 0, + tpc[dci->tpc], + feedback_ti, + dci->dai[0].val, + dci_ind->n_CCE, + dci_ind->N_CCE, + frame, + slot); + cw_idx++; + } else + return -1; + } + + if (cw1) { + current_harq = &mac->dl_harq_info[dci->harq_pid.val][cw_idx]; + if (get_cw_info(current_harq, + dlsch_pdu, + dl_conf_req->pdu_type, + &dlsch_pdu->cw_info[1], + number_rbs, + nb_re_dmrs, + nb_rb_oh, + dci->rv2.val, + dci->mcs2.val, + dci->ndi2.val, + cw_idx)) { + if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) + mac->stats.dl.rounds[current_harq->round]++; + // set the harq status at MAC for feedback + set_harq_status(mac, + dci->pucch_resource_indicator, + dci->harq_pid.val, + 1, + tpc[dci->tpc], + feedback_ti, + dci->dai[0].val, + dci_ind->n_CCE, + dci_ind->N_CCE, + frame, + slot); + cw_idx++; + } else + return -1; + } + + dlsch_pdu->n_codewords = cw_idx; /* TCI */ if (dl_conf_req->dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1) { // 0 bit if higher layer parameter tci-PresentInDCI is not enabled @@ -1311,107 +1450,9 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, /* DMRS_SEQ_INI */ // FIXME!!! - /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ - // according to TS 38.213 Table 9.2.3-1 - const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing); - uint16_t feedback_ti = 0; - - if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) { - feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset; - AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing), - "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config " - "file (min_rxtxtime).\n", - feedback_ti, - GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing)); - - // set the harq status at MAC for feedback - const int tpc[] = {-1, 0, 1, 3}; - set_harq_status(mac, - dci->pucch_resource_indicator, - dci->harq_pid.val, - tpc[dci->tpc], - feedback_ti, - dci->dai[0].val, - dci_ind->n_CCE, - dci_ind->N_CCE, - frame, - slot); - } - if (dlsch_pdu->new_data_indicator) - current_harq->round = 0; - else - current_harq->round++; - if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) - mac->stats.dl.rounds[current_harq->round]++; // send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding dlsch_pdu->k1_feedback = feedback_ti; - dlsch_pdu->mcs_table = get_dlsch_mcs_table(NR_DL_DCI_FORMAT_1_1, - rnti_type, - dci_ind->ss_type, - pdsch_Config ? pdsch_Config->mcs_Table : NULL, - NULL, // SPS not implemented, - false, // as above - NULL); // MCS-C-RNTI not implemented - dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); - if (dlsch_pdu->qamModOrder == 0) { - LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); - return -1; - } - uint8_t Nl = 0; - for (int i = 0; i < 12; i++) { // max 12 ports - if ((dlsch_pdu->dmrs_ports >> i) & 0x01) - Nl += 1; - } - - NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info; - int nb_rb_oh; - if (sc_info->xOverhead_PDSCH) - nb_rb_oh = 6 * (1 + *sc_info->xOverhead_PDSCH); - else - nb_rb_oh = 0; - int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups; - - int number_rbs; - if (dlsch_pdu->resource_alloc == 1) { - number_rbs = dlsch_pdu->number_rbs; - } else { - uint32_t temp_bitmap[9]; - memcpy(temp_bitmap, dlsch_pdu->rb_bitmap, 36); - number_rbs = count_bits(temp_bitmap, 9); - } - int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); - if (R > 0) { - dlsch_pdu->targetCodeRate = R; - dlsch_pdu->TBS = nr_compute_tbs(dlsch_pdu->qamModOrder, - R, - number_rbs, - dlsch_pdu->number_symbols, - nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos), - nb_rb_oh, - 0, - Nl); - // storing for possible retransmissions - if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) { - LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n", - dlsch_pdu->TBS, current_harq->TBS); - dlsch_pdu->new_data_indicator = true; // treated as new data - } - current_harq->R = dlsch_pdu->targetCodeRate; - current_harq->TBS = dlsch_pdu->TBS; - } - else { - dlsch_pdu->targetCodeRate = current_harq->R; - dlsch_pdu->TBS = current_harq->TBS; - } - - dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate); - - if (dlsch_pdu->TBS == 0) { - LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); - return -1; - } - // TBS_LBRM according to section 5.4.2.1 of 38.212 int max_mimo_layers = 0; if (sc_info->maxMIMO_Layers_PDSCH) @@ -1424,10 +1465,11 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, /*PTRS configuration */ dlsch_pdu->pduBitmap = 0; if (dl_dmrs_config->phaseTrackingRS != NULL) { + AssertFatal(cw_idx == 1, "Cannot handle PTRS with 2 codewords\n"); bool valid_ptrs_setup = set_dl_ptrs_values(dl_dmrs_config->phaseTrackingRS->choice.setup, number_rbs, - dlsch_pdu->mcs, + dlsch_pdu->cw_info[0].mcs, dlsch_pdu->mcs_table, &dlsch_pdu->PTRSFreqDensity, &dlsch_pdu->PTRSTimeDensity, @@ -2339,11 +2381,8 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche /* look for dl acknowledgment which should be done on current uplink slot */ for (int code_word = 0; code_word < number_of_code_word; code_word++) { - for (int dl_harq_pid = 0; dl_harq_pid < num_dl_harq; dl_harq_pid++) { - - NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid]; - + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid][code_word]; if (current_harq->active) { LOG_D(PHY, "HARQ pid %d is active for %d.%d\n", dl_harq_pid, current_harq->ul_frame, current_harq->ul_slot); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 47ee80a529..f952bfe791 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -116,15 +116,22 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity nr_timer_stop(&mac->scheduling_info.sr_DelayTimer); } +static void flush_harq_buffers(NR_UE_MAC_INST_t *mac) +{ + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + for (int c = 0; c < 2; c++) { + memset(&mac->dl_harq_info[k][c], 0, sizeof(NR_UE_DL_HARQ_STATUS_t)); + mac->dl_harq_info[k][c].last_ndi = -1; // initialize to invalid value + } + memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info)); + mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value + } +} + void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) { // flush all HARQ buffers for all Serving Cells - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { - memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info)); - memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info)); - mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value - mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value - } + flush_harq_buffers(mac); // release PUCCH for all Serving Cells; // release SRS for all Serving Cells; release_PUCCH_SRS(mac); @@ -142,12 +149,7 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) void handle_ulsync_loss(NR_UE_MAC_INST_t *mac) { // flush all HARQ buffers for all Serving Cells - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { - memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info)); - memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info)); - mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value - mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value - } + flush_harq_buffers(mac); // clear any configured downlink assignments and uplink grants; if (mac->dl_config_request) memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index f00eebf321..9c29d1584c 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -145,6 +145,7 @@ static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i if (mac->ra.ra_state != nrRA_WAIT_RAR) // no HARQ for MSG2 update_harq_status(mac, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid, + dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.cw_idx, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack); if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack) nr_ue_send_sdu(mac, dl_info, pdu_id); @@ -167,9 +168,9 @@ static int8_t handle_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int s return 0; } -void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack) +void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, int cw_idx, uint8_t ack_nack) { - NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid][cw_idx]; if (current_harq->active) { LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack);