diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index ff8a7f7fa8..55e80ce7d4 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -42,6 +42,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "openair1/PHY/MODULATION/nr_modulation.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/phy_vars_nr_ue.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" @@ -219,7 +220,6 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->rf_map.card = 0; UE->rf_map.chain = CC_id + 0; UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations; - UE->ldpc_offload_enable = nrUE_params.ldpc_offload_flag; UE->UE_scan_carrier = nrUE_params.UE_scan_carrier; UE->UE_fo_compensation = nrUE_params.UE_fo_compensation; UE->if_freq = nrUE_params.if_freq; @@ -388,6 +388,7 @@ configmodule_interface_t *uniqCfg = NULL; // A global var to reduce the changes size ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0}; +nrLDPC_coding_interface_t nrLDPC_coding_interface = {0}; int main(int argc, char **argv) { @@ -427,10 +428,8 @@ int main(int argc, char **argv) init_opt(); - if (nrUE_params.ldpc_offload_flag) - load_LDPClib("_t2", &ldpc_interface_offload); - - load_LDPClib(NULL, &ldpc_interface); + int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface); + AssertFatal(ret_loader == 0, "error loading LDPC library\n"); if (ouput_vcd) { vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd"); @@ -445,6 +444,8 @@ int main(int argc, char **argv) for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { PHY_vars_UE_g[inst][CC_id] = malloc(sizeof(*PHY_vars_UE_g[inst][CC_id])); memset(PHY_vars_UE_g[inst][CC_id], 0, sizeof(*PHY_vars_UE_g[inst][CC_id])); + // All instances use the same coding interface + PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface = nrLDPC_coding_interface; } } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 40ff2075a5..e34307e574 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -42,7 +42,6 @@ {"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, .uptr=&nrUE_params.ofdm_offset_divisor, .defuintval=8, TYPE_UINT32, 0}, \ {"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .iptr=&nrUE_params.max_ldpc_iterations, .defuintval=8, TYPE_UINT8, 0}, \ - {"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&(nrUE_params.ldpc_offload_flag), .defintval=0, TYPE_INT, 0}, \ {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&nrUE_params.vcdflag, .defintval=0, TYPE_INT, 0}, \ {"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&nrUE_params.uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \ {"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&nrUE_params.reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \ @@ -91,7 +90,6 @@ typedef struct { int nb_antennas_tx; int N_RB_DL; int ssb_start_subcarrier; - int ldpc_offload_flag; double time_sync_P; double time_sync_I; unsigned int ntn_koffset; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 022f9add0a..dfeded92ba 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -108,7 +108,6 @@ extern "C" #define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n" #define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence" #define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread" -#define CONFIG_HLP_LDPC_OFFLOAD "Enable LDPC offload to AMD Xilinx T2 telco card\n" #define CONFIG_HLP_SYNC_REF "UE acts a Sync Reference in Sidelink. 0-none 1-GNB 2-GNSS 4-localtiming\n" #define CONFIG_HLP_TADV \ "Set RF board timing_advance to compensate fix delay inside the RF board between Rx and Tx timestamps (RF board internal " \ @@ -181,7 +180,6 @@ extern int usrp_tx_thread; {"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \ {"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \ {"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \ - {"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&LDPC_OFFLOAD_FLAG, .defstrval=0, TYPE_INT, 0}, \ {"sync-ref", CONFIG_HLP_SYNC_REF, 0, .uptr=&SYNC_REF, .defintval=0, TYPE_UINT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, .iptr=&softmodem_params.command_line_sample_advance,.defintval=0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \ @@ -231,7 +229,6 @@ extern int usrp_tx_thread; { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ } // clang-format on diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 677401ae47..b0cc3803de 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -356,6 +356,7 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES free_and_zero(harq_list[j][i].c[r]); free_and_zero(harq_list[j][i].d[r]); } + free_and_zero(harq_list[j][i].b); free_and_zero(harq_list[j][i].c); free_and_zero(harq_list[j][i].d); } @@ -406,6 +407,7 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PR memset(harq_list[j] + i, 0, sizeof(NR_DL_UE_HARQ_t)); init_downlink_harq_status(harq_list[j] + i); + harq_list[j][i].b = malloc16_clear(a_segments * 1056); harq_list[j][i].c = malloc16(a_segments*sizeof(uint8_t *)); harq_list[j][i].d = malloc16(a_segments*sizeof(int16_t *)); const int sz=5*8448*sizeof(int16_t); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 8285a7036c..4fb88ec969 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -19,16 +19,8 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c -* \brief Top-level routines for decoding Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 -* \author R. Knopp -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr -* \note -* \warning -*/ +/*! \file PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c + */ #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/defs_nr_UE.h" @@ -36,6 +28,7 @@ #include "PHY/phy_extern_nr_ue.h" #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_defs.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "SCHED_NR_UE/defs.h" #include "SIMULATION/TOOLS/sim.h" @@ -45,11 +38,6 @@ #include "openair1/PHY/TOOLS/phy_scope_interface.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h" -//#define ENABLE_PHY_PAYLOAD_DEBUG 1 - -#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 -//#define OAI_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX - static extended_kpi_ue kpiStructure = {0}; extended_kpi_ue* getKPIUE(void) { @@ -69,371 +57,302 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, nr_codeword_unscrambling(llr, size, q, Nid, n_RNTI); } -static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, - ldpcDecode_ue_t *rdata, - bool last, - int b_size, - uint8_t b[b_size], - int *num_seg_ok, - const UE_nr_rxtx_proc_t *proc) +/*! \brief Prepare necessary parameters for nrLDPC_coding_interface + */ +uint32_t 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, + uint8_t *DLSCH_ids) { - NR_DL_UE_HARQ_t *harq_process = rdata->harq_process; - NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch; - int r = rdata->segment_r; + nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch]; + memset(TBs, 0, sizeof(TBs)); + nrLDPC_slot_decoding_parameters_t slot_parameters = { + .frame = proc->frame_rx, + .slot = proc->nr_slot_rx, + .nb_TBs = nb_dlsch, + .threadPool = &get_nrUE_params()->Tpool, + .TBs = TBs + }; - merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &rdata->ts_deinterleave); - merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &rdata->ts_rate_unmatch); - merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &rdata->ts_ldpc_decode); + int max_num_segments = 0; - bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations)); + 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]; - if (decodeSuccess) { - memcpy(b+rdata->offset, - harq_process->c[r], - rdata->Kr_bytes - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); + uint8_t nb_re_dmrs; - (*num_seg_ok)++; - } else { - LOG_D(PHY, "DLSCH %d in error\n", rdata->dlsch_id); + 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 dlsch[DLSCH_id].max_ldpc_iterations + 1; + } + + 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 = dlsch_config->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, + "%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, + harq_pid, + dlsch_config->TBS, + TB_parameters->G, + nb_re_dmrs, + dmrs_length, + TB_parameters->mcs, + TB_parameters->nb_layers, + dlsch_config->number_symbols, + TB_parameters->nb_rb, + TB_parameters->Qm, + Coderate); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); + + 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 dlsch[DLSCH_id].max_ldpc_iterations + 1; + } + + 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; + } + max_num_segments = max(max_num_segments, TB_parameters->C); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); + + 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 (!last) - return false; // continue decoding + nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments]; + memset(segments, 0, sizeof(segments)); + bool d_to_be_cleared[nb_dlsch][max_num_segments]; + memset(d_to_be_cleared, 0, sizeof(d_to_be_cleared)); - // all segments are done - kpiStructure.nb_total++; - kpiStructure.blockSize = dlsch->dlsch_config.TBS; - kpiStructure.dl_mcs = dlsch->dlsch_config.mcs; - kpiStructure.nofRBs = dlsch->dlsch_config.number_rbs; + 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]; - harq_process->decodeResult = *num_seg_ok == harq_process->C; + nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id]; + TB_parameters->segments = segments[pdsch_id]; - 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, 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; + 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); + + r_offset += segment_parameters->E; } } - 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[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) { + int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters); + + if (ret_decoder != 0) { + return dlsch->max_ldpc_iterations + 1; + } + + // 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 = dlsch_config->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, - "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"); + " 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) { - LOG_D(PHY, "DLSCH received ok \n"); - harq_process->status = SCH_IDLE; - dlsch->last_iteration_cnt = rdata->decodeIterations; - } else { - LOG_D(PHY, "DLSCH received nok \n"); - kpiStructure.nb_nack++; - dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; - } - return true; // end TB decoding -} - -static void nr_processDLSegment(void *arg) -{ - ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) arg; - NR_UE_DLSCH_t *dlsch = rdata->dlsch; - NR_DL_UE_HARQ_t *harq_process= rdata->harq_process; - t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int r = rdata->segment_r; - int E = rdata->E; - int Qm = rdata->Qm; - int r_offset = rdata->r_offset; - uint8_t kc = rdata->Kc; - uint32_t Tbslbrm = rdata->Tbslbrm; - short* dlsch_llr = rdata->dlsch_llr; - int8_t LDPCoutput[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); - int16_t z[68 * 384 + 16] __attribute__((aligned(16))); - int8_t l [68*384 + 16] __attribute__ ((aligned(16))); - - const int Kr = harq_process->K; - const int K_bits_F = Kr - harq_process->F; - - t_nrLDPC_time_stats procTime = {0}; - - //if we return before LDPC decoder run, the block is in error - rdata->decodeIterations = dlsch->max_ldpc_iterations + 1; - - start_meas(&rdata->ts_deinterleave); - - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_IN); - int16_t w[E]; - nr_deinterleaving_ldpc(E, - Qm, - w, // [hna] w is e - dlsch_llr+r_offset); - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_OUT); - stop_meas(&rdata->ts_deinterleave); - - start_meas(&rdata->ts_rate_unmatch); - /* LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,E %d, F %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", - harq_pid,r, G,E,harq_process->F, - Kr*3, - harq_process->TBS, - Qm, - harq_process->nb_rb, - harq_process->Nl, - harq_process->rvidx, - harq_process->round); */ - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN); - - if (nr_rate_matching_ldpc_rx(Tbslbrm, - p_decoderParms->BG, - p_decoderParms->Z, - harq_process->d[r], - w, - harq_process->C, - dlsch->dlsch_config.rv, - harq_process->first_rx, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decoderParms->Z))==-1) { - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT); - stop_meas(&rdata->ts_rate_unmatch); - LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); - return; - } - stop_meas(&rdata->ts_rate_unmatch); - - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { - LOG_D(PHY,"decoder input(segment %u) :",r); - - for (int i=0; id[r][i]); - - LOG_D(PHY,"\n"); - } - { - start_meas(&rdata->ts_ldpc_decode); - //set first 2*Z_c bits to zeros - memset(z,0,2*harq_process->Z*sizeof(int16_t)); - //set Filler bits - memset((z+K_bits_F),127,harq_process->F*sizeof(int16_t)); - //Move coded bits before filler bits - memcpy((z+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); - //skip filler bits - memcpy((z+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); - - //Saturate coded bits before decoding into 8 bits values - simde__m128i *pv = (simde__m128i*)&z; - simde__m128i *pl = (simde__m128i*)&l; - for (int i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { - pl[j] = simde_mm_packs_epi16(pv[i],pv[i+1]); + 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; + } + } } - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); - uint32_t A = dlsch->dlsch_config.TBS; - p_decoderParms->E = lenWithCrc(harq_process->C, A); - p_decoderParms->crc_type = crcType(harq_process->C, A); - rdata->decodeIterations = - ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, LDPCoutput, &procTime, &harq_process->abort_decode); - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); - - if (rdata->decodeIterations <= dlsch->max_ldpc_iterations) - memcpy(harq_process->c[r], LDPCoutput, Kr >> 3); - stop_meas(&rdata->ts_ldpc_decode); - } - completed_task_ans(rdata->ans); -} - -uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, - const UE_nr_rxtx_proc_t *proc, - int eNB_id, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_slot_rx, - uint8_t harq_pid, - int b_size, - uint8_t b[b_size], - int G) -{ - uint32_t ret,offset; - uint32_t r,r_offset=0,Kr=8424,Kr_bytes; - t_nrLDPC_dec_params decParams; - decParams.check_crc = check_crc; - - if (!harq_process) { - LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n"); - return(dlsch->max_ldpc_iterations + 1); - } - - // HARQ stats - LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv); - uint16_t nb_rb;// = 30; - uint8_t dmrs_Type = dlsch->dlsch_config.dmrsConfigType; - AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); - uint8_t nb_re_dmrs; - - if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6*dlsch->dlsch_config.n_dmrs_cdm_groups; - } else { - nb_re_dmrs = 4*dlsch->dlsch_config.n_dmrs_cdm_groups; - } - - uint16_t dmrs_length = get_num_dmrs(dlsch->dlsch_config.dlDmrsSymbPos); - vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); - - //NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0]; - - if (!dlsch_llr) { - LOG_E(PHY,"dlsch_decoding.c: NULL dlsch_llr pointer\n"); - return(dlsch->max_ldpc_iterations + 1); - } - - if (!frame_parms) { - LOG_E(PHY,"dlsch_decoding.c: NULL frame_parms pointer\n"); - return(dlsch->max_ldpc_iterations + 1); - } - - nb_rb = dlsch->dlsch_config.number_rbs; - uint32_t A = dlsch->dlsch_config.TBS; - ret = dlsch->max_ldpc_iterations + 1; - dlsch->last_iteration_cnt = ret; - - // target_code_rate is in 0.1 units - float Coderate = (float) dlsch->dlsch_config.targetCodeRate / 10240.0f; - - decParams.BG = dlsch->dlsch_config.ldpcBaseGraph; - unsigned int kc = decParams.BG == 2 ? 52 : 68; - - if (harq_process->first_rx == 1) { - // This is a new packet, so compute quantities regarding segmentation - nr_segmentation(NULL, - NULL, - lenWithCrc(1, A), // We give a max size in case of 1 segment - &harq_process->C, - &harq_process->K, - &harq_process->Z, // [hna] Z is Zc - &harq_process->F, - decParams.BG); - - if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * dlsch->Nl) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); - return(-1); + if (harq_process->decodeResult) { + LOG_D(PHY, "DLSCH received ok \n"); + harq_process->status = SCH_IDLE; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations; + } else { + LOG_D(PHY, "DLSCH received nok \n"); + kpiStructure.nb_nack++; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; } - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!frame%100)) - LOG_I(PHY,"K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, dlsch->Nl); - // clear HARQ buffer - for (int i=0; i C; i++) - memset(harq_process->d[i],0,5*8448*sizeof(int16_t)); + 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, + dlsch_config->number_rbs, + dlsch_config->qamModOrder, + Coderate); + } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); - decParams.Z = harq_process->Z; - decParams.numMaxIter = dlsch->max_ldpc_iterations; - decParams.outMode = 0; - r_offset = 0; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * dlsch->Nl; //number of segments to be allocated - - if (nb_rb != 273) { - a_segments = a_segments*nb_rb; - a_segments = a_segments/273 +1; - } - - if (harq_process->C > a_segments) { - LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); - return((1+dlsch->max_ldpc_iterations)); - } - - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); - - Kr = harq_process->K; - Kr_bytes = Kr>>3; - offset = 0; - - ldpcDecode_ue_t arr[harq_process->C]; - task_ans_t ans[harq_process->C]; - memset(ans, 0, harq_process->C * sizeof(task_ans_t)); - set_abort(&harq_process->abort_decode, false); - for (r=0; rC; r++) { - //printf("start rx segment %d\n",r); - uint32_t E = nr_get_E(G, harq_process->C, dlsch->dlsch_config.qamModOrder, dlsch->Nl, r); - decParams.R = nr_get_R_ldpc_decoder(dlsch->dlsch_config.rv, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->DLround); - ldpcDecode_ue_t *rdata = &arr[r]; - rdata->ans = &ans[r]; - - rdata->phy_vars_ue = phy_vars_ue; - rdata->harq_process = harq_process; - rdata->decoderParms = decParams; - rdata->dlsch_llr = dlsch_llr; - rdata->Kc = kc; - rdata->segment_r = r; - rdata->E = E; - rdata->Qm = dlsch->dlsch_config.qamModOrder; - rdata->r_offset = r_offset; - rdata->Kr_bytes = Kr_bytes; - rdata->rv_index = dlsch->dlsch_config.rv; - rdata->Tbslbrm = dlsch->dlsch_config.tbslbrm; - rdata->offset = offset; - rdata->dlsch = dlsch; - rdata->dlsch_id = harq_pid; - reset_meas(&rdata->ts_deinterleave); - reset_meas(&rdata->ts_rate_unmatch); - reset_meas(&rdata->ts_ldpc_decode); - task_t t = {.args = rdata, .func = nr_processDLSegment}; - pushTpool(&get_nrUE_params()->Tpool, t); - LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); - r_offset += E; - offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - ////////////////////////////////////////////////////////////////////////////////////////// - } - int num_seg_ok = 0; - int nbDecode = harq_process->C; - if (nbDecode > 0) { - join_task_ans(ans, nbDecode); - for (size_t i = 0; i < nbDecode; ++i) { - nr_ue_postDecode(phy_vars_ue, &arr[i], i == nbDecode - 1, b_size, b, &num_seg_ok, proc); - } - } - 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", - frame, - nr_slot_rx, - harq_pid, - harq_process->DLround, - harq_process->decodeResult, - A, - A / 8, - G, - nb_re_dmrs, - dmrs_length, - dlsch->dlsch_config.mcs, - dlsch->Nl, - nb_symb_sch, - nb_rb, - dlsch->dlsch_config.qamModOrder, - Coderate); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_OUT); - ret = dlsch->last_iteration_cnt; - return(ret); + return dlsch[0].last_iteration_cnt; } 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 176ed67cf3..0ca616ba34 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -65,50 +65,51 @@ void nr_conjch0_mult_ch1(int *ch0, unsigned short nb_rb, unsigned char output_shift0); -/** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several - threads (on multi-core machines) corresponding to different HARQ processes. The routine first - computes the segmentation information, followed by rate dematching and sub-block deinterleaving the of the - received LLRs computed by dlsch_demodulation for each transport block segment. It then calls the - turbo-decoding algorithm for each segment and stops after either after unsuccesful decoding of at least - one segment or correct decoding of all segments. Only the segment CRCs are check for the moment, the - overall CRC is ignored. Finally transport block reassembly is performed. - @param phy_vars_ue Pointer to ue variables - @param proc - @param eNB_id - @param dlsch_llr Pointer to LLR values computed by dlsch_demodulation - @param frame_parms Pointer to frame descriptor - @param dlsch Pointer to DLSCH descriptor - @param harq_process - @param frame Frame number - @param nb_symb_sch - @param nr_slot_rx Slot number - @param harq_pid - @param b_size - @param b +/** \brief This is the alternative top-level entry point for DLSCH decoding in UE. + It handles all the HARQ processes in only one call. The routine first + computes the segmentation information and then call LDPC decoder on the + received LLRs computed by dlsch_demodulation. + It stops after either unsuccesful decoding of at least + one segment or correct decoding of all segments. Only the segment CRCs are checked for the moment, the + overall CRC is ignored. Finally transport block reassembly is performed. + @param[in] phy_vars_ue Pointer to ue variables + @param[in] proc + @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 */ - uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, const UE_nr_rxtx_proc_t *proc, - int eNB_id, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_slot_rx, - uint8_t harq_pid, - int b_size, - uint8_t b[b_size], - int G); + short **dlsch_llr, + uint8_t **b, + int *G, + int nb_dlsch, + uint8_t *DLSCH_ids); +/** \brief This is the alternative top-level entry point for ULSCH encoding in UE. + It handles all the HARQ processes in only one call. The routine first + computes the segmentation information, followed by LDPC encoding algorithm of the + Transport Block. + @param[in] phy_vars_ue pointer to ue variables + @param[in] ulsch Pointer to ULSCH descriptor + @param[in] frame frame index + @param[in] slot slot index + @param[in] G array of Gs + @param[in] nb_ulsch number of uplink shared channels + @param[in] ULSCH_ids array of uplink shared channel ids + @returns 0 on success, -1 on unsuccessful decoding +*/ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, - NR_UE_ULSCH_t *ulsch, - NR_DL_FRAME_PARMS* frame_parms, - uint8_t harq_pid, - uint32_t tb_size, - unsigned int G); + NR_UE_ULSCH_t *ulsch, + const uint32_t frame, + const uint8_t slot, + unsigned int *G, + int nb_ulsch, + uint8_t *ULSCH_ids); /*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 @param[in] in Pointer to input bits @@ -125,18 +126,23 @@ void nr_pusch_codeword_scrambling(uint8_t *in, bool uci_on_pusch, uint32_t* out); -/** \brief Perform the following functionalities: + +/** \brief Alternative entry point to UE uplink shared channels procedures. + It handles all the HARQ processes in only one call. + Performs the following functionalities: - encoding - scrambling - modulation - transform precoding + @param[in] UE pointer to ue variables + @param[in] frame frame index + @param[in] slot slot index + @param[in] phy_data PHY layer informations + @param[in] c16_t */ - void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, - const unsigned char harq_pid, const uint32_t frame, const uint8_t slot, - const int gNB_id, nr_phy_data_tx_t *phy_data, c16_t **txdataF); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index cd24114323..419988a961 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -104,6 +104,8 @@ typedef struct { uint8_t first_rx; /// DLSCH status flag indicating SCH_status_t status; + /// Pointer to the payload (38.212 V15.4.0 section 5.1) + uint8_t *b; /// Pointers to transport block segments uint8_t **c; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) @@ -126,6 +128,8 @@ typedef struct { /// Last index of LLR buffer that contains information. /// Used for computing LDPC decoder R int llrLen; + /// Number of segments processed so far + uint32_t processedSegments; decode_abort_t abort_decode; } NR_DL_UE_HARQ_t; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index d4cf69d8f4..bed86bf852 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -19,16 +19,8 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c -* \brief Top-level routines for coding the ULSCH transport channel as described in 38.212 V15.4 2018-12 -* \author Khalid Ahmed -* \date 2019 -* \version 0.1 -* \company Fraunhofer IIS -* \email: khalid.ahmed@iis.fraunhofer.de -* \note -* \warning -*/ +/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c + */ #include "PHY/defs_UE.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -36,54 +28,68 @@ #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/lte_interleaver_inline.h" #include "PHY/CODING/nrLDPC_extern.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" +#include "executables/nr-uesoftmodem.h" #include "common/utils/LOG/vcd_signal_dumper.h" -//#define DEBUG_ULSCH_CODING - int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UE_ULSCH_t *ulsch, - NR_DL_FRAME_PARMS* frame_parms, - uint8_t harq_pid, - uint32_t tb_size, - unsigned int G) + const uint32_t frame, + const uint8_t slot, + unsigned int *G, + int nb_ulsch, + uint8_t *ULSCH_ids) { start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS); - - /////////////////////////parameters and variables initialization///////////////////////// - - unsigned int crc = 1; - NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; - uint16_t nb_rb = ulsch->pusch_pdu.rb_size; - uint32_t A = tb_size << 3; - uint32_t r_offset = 0; - // target_code_rate is in 0.1 units - float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f; - encoder_implemparams_t impp = {.n_segments = harq_process->C, - .macro_num = 0, - .K = harq_process->K, - .Kr = harq_process->K, - .Zc = harq_process->Z, - .BG = harq_process->BG, - .F = harq_process->F, - .rv = ulsch->pusch_pdu.pusch_data.rv_index, - .Qm = ulsch->pusch_pdu.qam_mod_order, - .tinput = NULL, - .tprep = NULL, - .tparity = NULL, - .toutput = NULL}; - ///////////////////////////////////////////////////////////////////////////////////////// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); - LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers); - LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, impp.Qm, Coderate); - LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, ulsch->pusch_pdu.pusch_data.new_data_indicator); - if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet -#ifdef DEBUG_ULSCH_CODING - printf("encoding thinks this is a new packet \n"); -#endif + + nrLDPC_TB_encoding_parameters_t TBs[nb_ulsch]; + memset(TBs, 0, sizeof(TBs)); + nrLDPC_slot_encoding_parameters_t slot_parameters = { + .frame = frame, + .slot = slot, + .nb_TBs = nb_ulsch, + .threadPool = &get_nrUE_params()->Tpool, + .tinput = NULL, + .tprep = NULL, + .tparity = NULL, + .toutput = NULL, + .TBs = TBs + }; + + int max_num_segments = 0; + + for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) { + uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id; + + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id]; + /* Neither harq_pid nor ULSCH_id are unique in the instance + * but their combination is. + * Since ULSCH_id < 2 + * then 2 * harq_pid + ULSCH_id is unique. + */ + TB_parameters->harq_unique_pid = 2 * harq_pid + ULSCH_id; + + /////////////////////////parameters and variables initialization///////////////////////// + + unsigned int crc = 1; + NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; + const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch->pusch_pdu; + uint16_t nb_rb = pusch_pdu->rb_size; + uint32_t A = pusch_pdu->pusch_data.tb_size << 3; + uint8_t Qm = pusch_pdu->qam_mod_order; + // target_code_rate is in 0.1 units + float Coderate = (float)pusch_pdu->target_code_rate / 10240.0f; + + LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, pusch_pdu->nrOfLayers); + LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G[pusch_id], Qm, Coderate); + LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, pusch_pdu->pusch_data.new_data_indicator); + ///////////////////////// a---->| add CRC |---->b ///////////////////////// - int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056; + + int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers * 1056; int B; if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload @@ -104,137 +110,90 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ///////////////////////// b---->| block segmentation |---->c ///////////////////////// - harq_process->BG = ulsch->pusch_pdu.ldpcBaseGraph; + harq_process->BG = pusch_pdu->ldpcBaseGraph; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); start_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS); - impp.Kb = nr_segmentation(harq_process->payload_AB, - harq_process->c, - B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - harq_process->BG); + TB_parameters->Kb = nr_segmentation(harq_process->payload_AB, + harq_process->c, + B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + harq_process->BG); + TB_parameters->C = harq_process->C; + TB_parameters->K = harq_process->K; + TB_parameters->Z = harq_process->Z; + TB_parameters->F = harq_process->F; + TB_parameters->BG = harq_process->BG; + if (TB_parameters->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B); + return (-1); + } stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS); - impp.n_segments = harq_process->C; - impp.K = harq_process->K; - impp.Kr = impp.K; - impp.Zc = harq_process->Z; - impp.F = harq_process->F; - impp.BG = harq_process->BG; - if (impp.n_segments > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * ulsch->pusch_pdu.nrOfLayers) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); - return(-1); - } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT); + max_num_segments = max(max_num_segments, TB_parameters->C); -#ifdef DEBUG_ULSCH_CODING - uint16_t Kr_bytes; - Kr_bytes = impp.Kr >> 3; -#endif + TB_parameters->nb_rb = nb_rb; + TB_parameters->Qm = Qm; + TB_parameters->mcs = pusch_pdu->mcs_index; + TB_parameters->nb_layers = pusch_pdu->nrOfLayers; + TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index; + TB_parameters->G = G[pusch_id]; + TB_parameters->tbslbrm = pusch_pdu->tbslbrm; + TB_parameters->A = A; + } // pusch_id - ///////////////////////// c---->| LDCP coding |---->d //////////////////////////////////// - for (int r = 0; r < impp.n_segments; r++) { -#ifdef DEBUG_ULSCH_CODING - printf("Encoder: B %d F %d \n", B, impp.F); - printf("start ldpc encoder segment %d/%d\n", r, impp.n_segments); - printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - for (int cnt = 0; cnt < 22 * impp.Zc / 8; cnt++) { - printf("%d ", harq_process->c[r][cnt]); - } - printf("\n"); -#endif - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); - } + nrLDPC_segment_encoding_parameters_t segments[nb_ulsch][max_num_segments]; + memset(segments, 0, sizeof(segments)); - if (ldpc_interface_offload.LDPCencoder) { - for (int j = 0; j < impp.n_segments; j++) { - impp.perCB[j].E_cb = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j); - } - start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); - ldpc_interface_offload.LDPCencoder(harq_process->c, &harq_process->f, &impp); - stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); - } else { - if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { - start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); - for (int j = 0; j < (impp.n_segments / 8 + 1); j++) { - impp.macro_num = j; - impp.Kr = impp.K; - ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp); - } - stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); + for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) { + uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id; -#ifdef DEBUG_ULSCH_CODING - write_output("ulsch_enc_input0.m", "enc_in0", &harq_process->c[0][0], Kr_bytes, 1, 4); - write_output("ulsch_enc_output0.m", "enc0", &harq_process->d[0][0], (3 * 8 * Kr_bytes) + 12, 1, 4); -#endif - } -/////////////////////////////////////////////////////////////////////////////// - for (int r = 0; r < impp.n_segments; r++) { // looping over C segments - if (impp.F > 0) { - for (int k = impp.Kr - impp.F - 2 * impp.Zc; k < impp.Kr - 2 * impp.Zc; k++) { - harq_process->d[r][k] = NR_NULL; - } - } + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id]; + NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; + TB_parameters->segments = segments[pusch_id]; - LOG_D(PHY, - "Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb " - "%d, " - "rvidx %d)...\n", - r, - G, - impp.Kr * 3, - impp.Qm, - nb_rb, - ulsch->pusch_pdu.pusch_data.rv_index); + int r_offset = 0; + for (int r = 0; r < TB_parameters->C; r++) { + nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; + segment_parameters->c = harq_process->c[r]; + segment_parameters->E = nr_get_E(TB_parameters->G, + TB_parameters->C, + TB_parameters->Qm, + TB_parameters->nb_layers, + r); + segment_parameters->output = harq_process->f + r_offset; + r_offset += segment_parameters->E; - ///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// - impp.perCB[r].E_cb = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, r); + reset_meas(&segment_parameters->ts_interleave); + reset_meas(&segment_parameters->ts_rate_match); + reset_meas(&segment_parameters->ts_ldpc_encode); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN); - start_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS]); - if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm, - impp.BG, - impp.Zc, - harq_process->d[r], - harq_process->e + r_offset, - impp.n_segments, - impp.F, - impp.Kr - impp.F - 2 * impp.Zc, - impp.rv, - impp.perCB[r].E_cb) - == -1) - return -1; + } // TB_parameters->C + } // pusch_id - stop_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS]); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT); + ///////////////////////// | LDCP coding | //////////////////////////////////// -#ifdef DEBUG_ULSCH_CODING - for (int i = 0; i < 16; i++) - printf("output ratematching e[%d]= %d r_offset %u\n", i, harq_process->e[i + r_offset], r_offset); -#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); -///////////////////////// e---->| Rate matching bit interleaving |---->f ///////////////////////// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_IN); - start_meas_nr_ue_phy(ue, ULSCH_INTERLEAVING_STATS); - nr_interleaving_ldpc(impp.perCB[r].E_cb, impp.Qm, harq_process->e + r_offset, harq_process->f + r_offset); - stop_meas_nr_ue_phy(ue, ULSCH_INTERLEAVING_STATS); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_OUT); -#ifdef DEBUG_ULSCH_CODING - for (int i = 0; i < 16; i++) - printf("output interleaving f[%d]= %d r_offset %u\n", i, harq_process->f[i+r_offset], r_offset); - if (r == impp.n_segments - 1) - write_output("enc_output.m","enc", harq_process->f, G, 1, 4); -#endif - r_offset += impp.perCB[r].E_cb; + ue->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); + + for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) { + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id]; + for (int r = 0; r < TB_parameters->C; r++) { + nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; + merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_INTERLEAVING_STATS], &segment_parameters->ts_interleave); + merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS], &segment_parameters->ts_rate_match); + merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_ENCODING_STATS], &segment_parameters->ts_ldpc_encode); } } - /////////////////////////////////////////////////////////////////////////////////////////////// + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT); stop_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS); - return(0); + return 0; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index bef7724e5d..646ac2dd94 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -462,65 +462,49 @@ static void map_symbols(const nr_phy_pxsch_params_t p, } void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, - const unsigned char harq_pid, const uint32_t frame, const uint8_t slot, - const int gNB_id, nr_phy_data_tx_t *phy_data, c16_t **txdataF) { - LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot); - int l_prime[2]; - uint8_t nb_dmrs_re_per_rb; + int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; - NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; + if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE) + return; - int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig - uint16_t number_dmrs_symbols = 0; + start_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); + + uint8_t ULSCH_ids[1]; + unsigned int G[1]; + uint8_t pusch_id = 0; + ULSCH_ids[pusch_id] = 0; + LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d prepare for coding\n", harq_pid, frame, slot); NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch; NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->ul_harq_processes[harq_pid]; const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu; - uint32_t tb_size = pusch_pdu->pusch_data.tb_size; - AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 && - pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && - pusch_pdu->pusch_uci.csi_part2_bit_length == 0, - "UCI on PUSCH not supported at PHY\n"); + uint16_t number_dmrs_symbols = 0; - int start_symbol = pusch_pdu->start_symbol_index; - uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; + uint16_t nb_rb = pusch_pdu->rb_size; uint8_t number_of_symbols = pusch_pdu->nr_of_symbols; - uint8_t dmrs_type = pusch_pdu->dmrs_config_type; - uint16_t start_rb = pusch_pdu->rb_start; - uint16_t nb_rb = pusch_pdu->rb_size; - uint8_t Nl = pusch_pdu->nrOfLayers; - uint8_t mod_order = pusch_pdu->qam_mod_order; - uint16_t rnti = pusch_pdu->rnti; - uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data; - uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+pusch_pdu->bwp_start)*NR_NB_SC_PER_RB; - - if (start_sc >= frame_parms->ofdm_symbol_size) - start_sc -= frame_parms->ofdm_symbol_size; - - ulsch_ue->Nid_cell = frame_parms->Nid_cell; + uint8_t dmrs_type = pusch_pdu->dmrs_config_type; + uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data; + uint8_t nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6 : 4) * cdm_grps_no_data; + int start_symbol = pusch_pdu->start_symbol_index; + uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; + uint8_t mod_order = pusch_pdu->qam_mod_order; + uint8_t Nl = pusch_pdu->nrOfLayers; + uint32_t tb_size = pusch_pdu->pusch_data.tb_size; + uint16_t rnti = pusch_pdu->rnti; for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) { - if((ul_dmrs_symb_pos >> i) & 0x01) + if ((ul_dmrs_symb_pos >> i) & 0x01) number_dmrs_symbols += 1; } - nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data; - - LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n", - rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb); - // TbD num_of_mod_symbols is set but never used - const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh; - harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb; - - /////////////////////////PTRS parameters' initialization///////////////////////// - /////////// + ///////////////////////PTRS parameters' initialization/////////////////// unsigned int K_ptrs = 0, k_RE_ref = 0; uint32_t unav_res = 0; @@ -531,32 +515,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, ulsch_ue->ptrs_symbols = 0; - set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols, - number_of_symbols, - start_symbol, - L_ptrs, - ul_dmrs_symb_pos); + set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols, number_of_symbols, start_symbol, L_ptrs, ul_dmrs_symb_pos); int n_ptrs = (nb_rb + K_ptrs - 1) / K_ptrs; - int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ulsch_ue->ptrs_symbols, - start_symbol, - number_of_symbols); + int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ulsch_ue->ptrs_symbols, start_symbol, number_of_symbols); unav_res = n_ptrs * ptrsSymbPerSlot; } - /////////// - //////////////////////////////////////////////////////////////////// + G[pusch_id] = nr_get_G(nb_rb, number_of_symbols, nb_dmrs_re_per_rb, number_dmrs_symbols, unav_res, mod_order, Nl); - - /////////////////////////ULSCH coding///////////////////////// - /////////// - - unsigned int G = nr_get_G(nb_rb, - number_of_symbols, - nb_dmrs_re_per_rb, - number_dmrs_symbols, - unav_res, - mod_order, - Nl); ws_trace_t tmp = {.nr = true, .direction = DIRECTION_UPLINK, .pdu_buffer = harq_process_ul_ue->payload_AB, @@ -571,19 +537,59 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, .oob_event_value = 0}; trace_pdu(&tmp); - if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1) { + /////////////////////////ULSCH coding///////////////////////// + + if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) { NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid]; harq_process_ulsch->ULstatus = SCH_IDLE; + stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); return; } - /////////// - //////////////////////////////////////////////////////////////////// + LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d\n", harq_pid, frame, slot); + + int l_prime[2]; + + NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; + + int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig + + AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 && pusch_pdu->pusch_uci.csi_part1_bit_length == 0 + && pusch_pdu->pusch_uci.csi_part2_bit_length == 0, + "UCI on PUSCH not supported at PHY\n"); + + uint16_t start_rb = pusch_pdu->rb_start; + uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB; + + if (start_sc >= frame_parms->ofdm_symbol_size) + start_sc -= frame_parms->ofdm_symbol_size; + + ulsch_ue->Nid_cell = frame_parms->Nid_cell; + + LOG_D(PHY, + "ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d " + "cdmgrpsnodata %d " + "num_dmrs %d dmrs_re_per_rb %d\n", + rnti, + start_rb, + nb_rb, + mod_order, + Nl, + pusch_pdu->Tpmi, + pusch_pdu->bwp_start, + start_sc, + start_symbol, + number_of_symbols, + cdm_grps_no_data, + number_dmrs_symbols, + nb_dmrs_re_per_rb); + // TbD num_of_mod_symbols is set but never used + const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh; + harq_process_ul_ue->num_of_mod_symbols = N_RE_prime * nb_rb; /////////////////////////ULSCH scrambling///////////////////////// - /////////// - uint32_t available_bits = G; + uint32_t available_bits = G[pusch_id]; // +1 because size can be not modulo 4 uint32_t scrambled_output[available_bits / (8 * sizeof(uint32_t)) + 1]; memset(scrambled_output, 0, sizeof(scrambled_output)); @@ -595,13 +601,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, false, scrambled_output); - ///////////// - ////////////////////////////////////////////////////////////////////////// - /////////////////////////ULSCH modulation///////////////////////// - /////////// - int max_num_re = Nl*number_of_symbols*nb_rb*NR_NB_SC_PER_RB; + int max_num_re = Nl * number_of_symbols * nb_rb * NR_NB_SC_PER_RB; c16_t d_mod[max_num_re] __attribute__((aligned(16))); nr_modulation(scrambled_output, // assume one codeword for the moment @@ -609,23 +611,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, mod_order, (int16_t *)d_mod); - - /////////// - //////////////////////////////////////////////////////////////////////// - /////////////////////////ULSCH layer mapping///////////////////////// - /////////// + const int sz = available_bits / mod_order / Nl; c16_t ulsch_mod[Nl][sz]; nr_ue_layer_mapping(d_mod, Nl, sz, ulsch_mod); - /////////// - //////////////////////////////////////////////////////////////////////// - - //////////////////////// ULSCH transform precoding //////////////////////// - /////////// l_prime[0] = 0; // single symbol ap 0 @@ -636,10 +629,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, memset(ulsch_mod_tp, 0, sizeof(ulsch_mod_tp)); if (pusch_pdu->transform_precoding == transformPrecoder_enabled) { - - uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB; + uint32_t nb_re_pusch = nb_rb * NR_NB_SC_PER_RB; uint32_t y_offset = 0; - uint16_t num_dmrs_res_per_symbol = nb_rb*(NR_NB_SC_PER_RB/2); + uint16_t num_dmrs_res_per_symbol = nb_rb * (NR_NB_SC_PER_RB / 2); // Calculate index to dmrs seq array based on number of DMRS Subcarriers on this symbol int index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol); @@ -647,14 +639,16 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, v = pusch_pdu->dfts_ofdm.low_papr_sequence_number; dmrs_seq = dmrs_lowpaprtype1_ul_ref_sig[u][v][index]; - AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n"); + AssertFatal(index >= 0, + "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs " + "cannot be multiple " + "of any other primenumber other than 2,3,5\n"); AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated"); - LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index); + LOG_D(PHY, "Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index); for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) { - - if((ul_dmrs_symb_pos >> l) & 0x01) + if ((ul_dmrs_symb_pos >> l) & 0x01) /* In the symbol with DMRS no data would be transmitted CDM groups is 2*/ continue; @@ -662,43 +656,35 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, y_offset = y_offset + nb_re_pusch; - LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset); + LOG_D(PHY, "Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset); #ifdef DEBUG_PUSCH_MAPPING - printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n", - y_offset, nb_re_pusch, l, nb_rb); + printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n", y_offset, nb_re_pusch, l, nb_rb); #endif } #ifdef DEBUG_DFT_IDFT - int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); + int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__((aligned(16))); int offset = 0; - printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order); + printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits, mod_order); - for (int ll = 0; ll < (available_bits/mod_order); ll++) { + for (int ll = 0; ll < (available_bits / mod_order); ll++) { debug_symbols[ll] = ulsch_ue->ulsch_mod_tp[ll]; } - - printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols); - for (int ll = 0; ll < (number_of_symbols-number_dmrs_symbols); ll++) { + + printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols, number_dmrs_symbols); + for (int ll = 0; ll < (number_of_symbols - number_dmrs_symbols); ll++) { nr_idft(&debug_symbols[offset], nb_re_pusch); offset = offset + nb_re_pusch; } LOG_M("preDFT_all_symbols.m", "UE_preDFT", ulsch_mod[0], number_of_symbols * nb_re_pusch, 1, 1); LOG_M("postDFT_all_symbols.m", "UE_postDFT", ulsch_mod_tp, number_of_symbols * nb_re_pusch, 1, 1); - LOG_M("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1); - LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1); + LOG_M("DEBUG_IDFT_SYMBOLS.m", "UE_Debug_IDFT", debug_symbols, number_of_symbols * nb_re_pusch, 1, 1); + LOG_M("UE_DMRS_SEQ.m", "UE_DMRS_SEQ", dmrs_seq, nb_re_pusch, 1, 1); #endif - } - - /////////// - //////////////////////////////////////////////////////////////////////// - - /////////////////////////ULSCH RE mapping///////////////////////// - /////////// const int slot_sz = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot; c16_t tx_precoding[Nl][slot_sz]; @@ -748,12 +734,13 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } // for (nl=0; nl < Nl; nl++) /////////////////////////ULSCH precoding///////////////////////// - /////////// + /// Layer Precoding and Antenna port mapping // ulsch_mod 0-3 are mapped on antenna ports // The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx // The same precoding matrix is applied on prg_size RBs, Thus // pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1 + // The Precoding matrix: for (int ap = 0; ap < frame_parms->nb_antennas_tx; ap++) { for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) { @@ -834,8 +821,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, NR_UL_UE_HARQ_t *harq_process_ulsch = NULL; harq_process_ulsch = &UE->ul_harq_processes[harq_pid]; harq_process_ulsch->ULstatus = SCH_IDLE; - /////////// - //////////////////////////////////////////////////////////////////////// + + stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); + } uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 774309831c..8cef0b6f4c 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -89,6 +89,7 @@ #include "impl_defs_nr.h" #include "time_meas.h" #include "PHY/CODING/coding_defs.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/TOOLS/tools_defs.h" #include "common/platform_types.h" #include "NR_UE_TRANSPORT/nr_transport_ue.h" @@ -481,9 +482,10 @@ typedef struct PHY_VARS_NR_UE_s { /// N0 (used for abstraction) double N0; + /// NR LDPC coding related + nrLDPC_coding_interface_t nrLDPC_coding_interface; uint8_t max_ldpc_iterations; - int ldpc_offload_enable; /// SRS variables nr_srs_info_t *nr_srs_info; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 664a293a96..a9552b1677 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -271,7 +271,6 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n { const int slot_tx = proc->nr_slot_tx; const int frame_tx = proc->frame_tx; - const int gNB_id = proc->gNB_id; AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); @@ -288,12 +287,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n start_meas_nr_ue_phy(ue, PHY_PROC_TX); - const int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; - if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE) { - start_meas_nr_ue_phy(ue, PUSCH_PROC_STATS); - nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF); - stop_meas_nr_ue_phy(ue, PUSCH_PROC_STATS); - } + nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF); ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF); @@ -685,23 +679,22 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls return unav_res; } +/*! \brief Process the whole DLSCH slot + */ static bool 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) -{ + int16_t *llr[2]) { if (dlsch[0].active == false) { LOG_E(PHY, "DLSCH should be active when calling this function\n"); return true; } - int gNB_id = proc->gNB_id; bool dec = false; int harq_pid = dlsch[0].dlsch_config.harq_process_nbr; int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; - uint32_t ret = UINT32_MAX, ret1 = UINT32_MAX; + uint32_t ret = UINT32_MAX; 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]; uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos); @@ -711,19 +704,21 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, 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 == ACTIVE) ? 1 : 0; + nb_dlsch += (is_cw1_active == ACTIVE) ? 1 : 0; uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols; uint8_t dmrs_type = dlsch[0].dlsch_config.dmrsConfigType; uint8_t nb_re_dmrs; - if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups; - } - else { - nb_re_dmrs = 4*dlsch[0].dlsch_config.n_dmrs_cdm_groups; + if (dmrs_type == NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6 * dlsch[0].dlsch_config.n_dmrs_cdm_groups; + } else { + nb_re_dmrs = 4 * dlsch[0].dlsch_config.n_dmrs_cdm_groups; } - 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 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); // exit dlsch procedures as there are no active dlsch if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) { @@ -734,44 +729,43 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, return false; } - start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); - nr_dlsch_unscrambling(llr[0], G, 0, dlsch[0].dlsch_config.dlDataScramblingId, dlsch[0].rnti); - stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); + int G[2]; + 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 != ACTIVE) continue; + + DLSCH_ids[pdsch_id++] = DLSCH_id; + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; + uint32_t unav_res = 0; + if (dlsch_config->pduBitmap & 0x1) { + uint16_t ptrsSymbPos = 0; + set_ptrs_symb_idx(&ptrsSymbPos, dlsch_config->number_symbols, dlsch_config->start_symbol, 1 << dlsch_config->PTRSTimeDensity, + dlsch_config->dlDmrsSymbPos); + int n_ptrs = (dlsch_config->number_rbs + dlsch_config->PTRSFreqDensity - 1) / dlsch_config->PTRSFreqDensity; + int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols); + unav_res = n_ptrs * ptrsSymbPerSlot; + } + unav_res += compute_csi_rm_unav_res(dlsch_config); + G[DLSCH_id] = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[DLSCH_id].Nl); + + 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_DECODING_STATS); - // create memory to store decoder output - int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated - int num_rb = dlsch[0].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 p_b[dlsch_bytes]; + ret = nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids); + stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); - ret = nr_dlsch_decoding(ue, - proc, - gNB_id, - llr[0], - &ue->frame_parms, - &dlsch[0], - dl_harq0, - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - dlsch_bytes, - p_b, - G); - - LOG_T(PHY,"dlsch decoding, ret = %d\n", ret); - - - if(retmax_ldpc_iterations+1) - dec = true; + if (ret < ue->max_ldpc_iterations + 1) dec = true; int ind_type = -1; - switch(dlsch[0].rnti_type) { + switch (dlsch[0].rnti_type) { case TYPE_RA_RNTI_: ind_type = FAPI_NR_RX_PDU_TYPE_RAR; break; @@ -790,75 +784,21 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } 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); + nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b[0]); LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8); - - stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); if (cpumeas(CPUMEAS_GETSTATE)) { LOG_D(PHY, - " --> Unscrambling for CW0 %5.3f\n", + " --> Unscrambling %5.3f\n", ue->phy_cpu_stats.cpu_time_stats[DLSCH_UNSCRAMBLING_STATS].p_time / (cpuf * 1000.0)); LOG_D(PHY, - "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", + "AbsSubframe %d.%d --> LDPC Decoding %5.3f\n", frame_rx % 1024, nr_slot_rx, ue->phy_cpu_stats.cpu_time_stats[DLSCH_DECODING_STATS].p_time / (cpuf * 1000.0)); } - if(is_cw1_active) { - // start ldpc decode for CW 1 - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[1].dlsch_config; - uint32_t unav_res = 0; - if(dlsch_config->pduBitmap & 0x1) { - uint16_t ptrsSymbPos = 0; - set_ptrs_symb_idx(&ptrsSymbPos, - dlsch_config->number_symbols, - dlsch_config->start_symbol, - 1 << dlsch_config->PTRSTimeDensity, - dlsch_config->dlDmrsSymbPos); - int n_ptrs = (dlsch_config->number_rbs + dlsch_config->PTRSFreqDensity - 1) / dlsch_config->PTRSFreqDensity; - int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols); - unav_res = n_ptrs * ptrsSymbPerSlot; - } - start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); - unav_res += compute_csi_rm_unav_res(dlsch_config); - G = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[1].Nl); - nr_dlsch_unscrambling(llr[1], G, 0, dlsch[1].dlsch_config.dlDataScramblingId, dlsch[1].rnti); - stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS); - - start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); - ret1 = nr_dlsch_decoding(ue, - proc, - gNB_id, - llr[1], - &ue->frame_parms, - &dlsch[1], - dl_harq1, - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - dlsch_bytes, - p_b, - G); - LOG_T(PHY,"CW dlsch decoding, ret1 = %d\n", ret1); - - stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); - if (cpumeas(CPUMEAS_GETSTATE)) { - LOG_D(PHY, - " --> Unscrambling for CW1 %5.3f\n", - ue->phy_cpu_stats.cpu_time_stats[DLSCH_UNSCRAMBLING_STATS].p_time / (cpuf * 1000.0)); - LOG_D(PHY, - "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx % 1024, - nr_slot_rx, - ue->phy_cpu_stats.cpu_time_stats[DLSCH_DECODING_STATS].p_time / (cpuf * 1000.0)); - } - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS); - } - - // send to mac + // send to mac if (ue->if_inst && ue->if_inst->dl_indication) { ue->if_inst->dl_indication(&dl_indication); } @@ -869,8 +809,18 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]); } - if (ue->phy_sim_dlsch_b) - memcpy(ue->phy_sim_dlsch_b, p_b, dlsch_bytes); + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated + int num_rb = dlsch[0].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 + + if (ue->phy_sim_dlsch_b && is_cw0_active == ACTIVE) + memcpy(ue->phy_sim_dlsch_b, p_b[0], dlsch_bytes); + else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE) + memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes); return dec; } @@ -1144,8 +1094,9 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS); - if (ret_pdsch >= 0) - nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G); + if (ret_pdsch >= 0) { + nr_ue_dlsch_procedures(ue, proc, dlsch, llr); + } else { LOG_E(NR_PHY, "Demodulation impossible, internal error\n"); int ack_nack_slot = (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame;