diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 4206cfd585..4636395f65 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -403,7 +403,6 @@ void init_eNB_afterRU(void) { for (inst=0; instldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag; phy_init_nr_gNB(gNB); diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 5c8e032d5e..022f9add0a 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -142,7 +142,6 @@ extern "C" #define EMULATE_L1 softmodem_params.emulate_l1 #define CONTINUOUS_TX softmodem_params.continuous_tx #define SYNC_REF softmodem_params.sync_ref -#define LDPC_OFFLOAD_FLAG softmodem_params.ldpc_offload_flag #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat"; @@ -321,7 +320,6 @@ typedef struct { int continuous_tx; uint32_t sync_ref; int no_itti; - int ldpc_offload_flag; int threequarter_fs; } softmodem_params_t; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index e723b3a330..07cdca7692 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -26,6 +26,7 @@ #include "PHY/defs_gNB.h" #include "PHY/NR_REFSIG/nr_refsig.h" #include "PHY/INIT/nr_phy_init.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" @@ -40,6 +41,7 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "SCHED_NR/fapi_nr_l1.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" +#include int l1_north_init_gNB() { @@ -96,9 +98,6 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame) } } -// A global var to reduce the changes size -ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0}; - void phy_init_nr_gNB(PHY_VARS_gNB *gNB) { // shortcuts @@ -134,15 +133,11 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH - load_LDPClib(NULL, &ldpc_interface); + int ret_loader = load_nrLDPC_coding_interface(NULL, &gNB->nrLDPC_coding_interface); + AssertFatal(ret_loader == 0, "error loading LDPC library\n"); pthread_mutex_init(&gNB->UL_INFO.crc_rx_mutex, NULL); - if (gNB->ldpc_offload_flag) - load_LDPClib("_t2", &ldpc_interface_offload); - else - load_LDPClib(NULL, &ldpc_interface); - gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB; init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index e69e6b2f89..1202774798 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -65,6 +65,67 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats; time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats; + size_t size_output = 0; + + for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { + NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + + LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n", + rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize); + + const int Qm = rel15->qamModOrder[0]; + + /* PTRS */ + uint16_t dlPtrsSymPos = 0; + int n_ptrs = 0; + uint32_t ptrsSymbPerSlot = 0; + if(rel15->pduBitmap & 0x1) { + set_ptrs_symb_idx(&dlPtrsSymPos, + rel15->NrOfSymbols, + rel15->StartSymbolIndex, + 1 << rel15->PTRSTimeDensity, + rel15->dlDmrsSymbPos); + n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity; + ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols); + } + harq->unav_res = ptrsSymbPerSlot * n_ptrs; + + /// CRC, coding, interleaving and rate matching + AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); + + /* output and its parts for each dlsch should be aligned on 64 bytes + * => size_output is a sum of parts sizes rounded up to a multiple of 64 + */ + size_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; + size_output += (size_output_tb + 63 - ((size_output_tb + 63) % 64)); + } + + unsigned char output[size_output] __attribute__((aligned(64))); + + bzero(output, size_output); + + size_t offset_output = 0; + + start_meas(dlsch_encoding_stats); + if (nr_dlsch_encoding(gNB, + msgTx, + frame, + slot, + frame_parms, + output, + tinput, + tprep, + tparity, + toutput, + dlsch_rate_matching_stats, + dlsch_interleaving_stats, + dlsch_segmentation_stats) == -1) { + return; + } + stop_meas(dlsch_encoding_stats); + for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; @@ -100,45 +161,24 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) } harq->unav_res = ptrsSymbPerSlot * n_ptrs; - /// CRC, coding, interleaving and rate matching - AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); - unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers] __attribute__((aligned(64))); - bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers); - start_meas(dlsch_encoding_stats); - - if (nr_dlsch_encoding(gNB, - frame, - slot, - harq, - frame_parms, - output, - tinput, - tprep, - tparity, - toutput, - dlsch_rate_matching_stats, - dlsch_interleaving_stats, - dlsch_segmentation_stats) == -1) - return; - stop_meas(dlsch_encoding_stats); #ifdef DEBUG_DLSCH printf("PDSCH encoding:\nPayload:\n"); - for (int i=0; iB>>7; i++) { - for (int j=0; j<16; j++) - printf("0x%02x\t", harq->pdu[(i<<4)+j]); + for (int i = 0; i < (harq->B>>3); i += 16) { + for (int j=0; j < 16; j++) + printf("0x%02x\t", harq->pdu[i + j]); printf("\n"); } printf("\nEncoded payload:\n"); - for (int i=0; i>3; i++) { - for (int j=0; j<8; j++) - printf("%d", output[(i<<3)+j]); + for (int i = 0; i < encoded_length; i += 8) { + for (int j = 0; j < 8; j++) + printf("%d", output[offset_output + i + j]); printf("\t"); } printf("\n"); #endif if (IS_SOFTMODEM_DLSIM) - memcpy(harq->f, output, encoded_length); + memcpy(harq->f, &output[offset_output], encoded_length); c16_t mod_symbs[rel15->NrOfCodewords][encoded_length]; for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) { @@ -147,7 +187,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) uint32_t scrambled_output[(encoded_length>>5)+4]; // modulator acces by 4 bytes in some cases memset(scrambled_output, 0, sizeof(scrambled_output)); if ( encoded_length > rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers) abort(); - nr_pdsch_codeword_scrambling(output, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output); + nr_pdsch_codeword_scrambling(&output[offset_output], encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output); #ifdef DEBUG_DLSCH printf("PDSCH scrambling:\n"); @@ -176,6 +216,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) } /// Resource mapping + /* output and its parts for each dlsch should be aligned on 64 bytes + * => offset_output should remain a multiple of 64 with enough offset to fit each dlsch + */ + uint32_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; + offset_output += (size_output_tb + 63) & ~63; + // Non interleaved VRB to PRB mapping uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart+rel15->BWPStart)*NR_NB_SC_PER_RB; if (start_sc >= frame_parms->ofdm_symbol_size) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 17bfe2878a..53e0c17065 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -44,18 +44,18 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int slot); int nr_dlsch_encoding(PHY_VARS_gNB *gNB, - int frame, - uint8_t slot, - NR_DL_gNB_HARQ_t *harq, - NR_DL_FRAME_PARMS* frame_parms, - unsigned char * output, - time_stats_t *tinput, - time_stats_t *tprep, - time_stats_t *tparity, - time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats, - time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats); + processingData_L1tx_t *msgTx, + int frame, + uint8_t slot, + NR_DL_FRAME_PARMS *frame_parms, + unsigned char *output, + time_stats_t *tinput, + time_stats_t *tprep, + time_stats_t *tparity, + time_stats_t *toutput, + time_stats_t *dlsch_rate_matching_stats, + time_stats_t *dlsch_interleaving_stats, + time_stats_t *dlsch_segmentation_stats); void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index b66b785b7d..33ecfb3737 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -19,21 +19,15 @@ * contact@openairinterface.org */ -/*! \file PHY/LTE_TRANSPORT/dlsch_coding.c +/*! \file PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c * \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2 -* \author H.Wang -* \date 2018 -* \version 0.1 -* \company Eurecom -* \email: -* \note -* \warning */ #include "PHY/defs_gNB.h" #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_defs.h" #include "PHY/CODING/lte_interleaver_inline.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/CODING/nrLDPC_extern.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" @@ -117,130 +111,10 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) return(dlsch); } -static void ldpc8blocks(void *p) -{ - encoder_implemparams_t *impp=(encoder_implemparams_t *) p; - NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - uint8_t mod_order = rel15->qamModOrder[0]; - uint16_t nb_rb = rel15->rbSize; - uint8_t nb_symb_sch = rel15->NrOfSymbols; - uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); - uint32_t A = rel15->TBSize[0]<<3; - uint8_t nb_re_dmrs; - - if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) - nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; - else - nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - - unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq->unav_res, mod_order, rel15->nrOfLayers); - LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", - A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order); - // nrLDPC_encoder output is in "d" - // let's make this interface happy! - uint8_t tmp[8][68 * 384]__attribute__((aligned(32))); - uint8_t *d[impp->n_segments]; - for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ ) - d[rr] = tmp[i]; - ldpc_interface.LDPCencoder(harq->c, d, impp); - // Compute where to place in output buffer that is concatenation of all segments - uint32_t r_offset=0; - for (int i=0; i < impp->macro_num*8; i++ ) - r_offset+=nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, i); - for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) { - if (impp->F>0) { - // writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212 - memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F); - } - -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]); -#endif - uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr); - //#ifdef DEBUG_DLSCH_CODING - LOG_D(NR_PHY, - "Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb " - "%d,nrOfLayer %d)...\n", - rr, - impp->n_segments, - G, - E, - impp->F, - impp->K - impp->F - 2 * impp->Zc, - mod_order, - nb_rb, - rel15->nrOfLayers); - - uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes; - - uint8_t e[E]; - bzero (e, E); - nr_rate_matching_ldpc(Tbslbrm, - impp->BG, - impp->Zc, - d[rr], - e, - impp->n_segments, - impp->F, - impp->K - impp->F - 2 * impp->Zc, - rel15->rvIndex[0], - E); - if (impp->K - impp->F - 2 * impp->Zc > E) { - LOG_E(PHY, - "dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", - A, - impp->K, - G, - nb_rb, - nb_symb_sch, - nb_re_dmrs, - length_dmrs, - (int)mod_order); - - LOG_E(NR_PHY, - "Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, " - "nb_rb %d)...\n", - rr, - impp->n_segments, - G, - E, - impp->K, - impp->F, - impp->K - impp->F - 2 * impp->Zc, - mod_order, - nb_rb); - } -#ifdef DEBUG_DLSCH_CODING - - for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %u\n", i,e[i], r_offset); - -#endif - nr_interleaving_ldpc(E, - mod_order, - e, - impp->output+r_offset); -#ifdef DEBUG_DLSCH_CODING - - for (int i =0; i<16; i++) - printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset); - - if (r==impp->n_segments-1) - write_output("enc_output.m","enc",impp->output,G,1,4); - -#endif - r_offset += E; - } - - // Task running in // completed - completed_task_ans(impp->ans); -} - int nr_dlsch_encoding(PHY_VARS_gNB *gNB, + processingData_L1tx_t *msgTx, int frame, uint8_t slot, - NR_DL_gNB_HARQ_t *harq, NR_DL_FRAME_PARMS *frame_parms, unsigned char *output, time_stats_t *tinput, @@ -251,145 +125,195 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, time_stats_t *dlsch_interleaving_stats, time_stats_t *dlsch_segmentation_stats) { - encoder_implemparams_t impp; - impp.output=output; - unsigned int crc=1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - impp.Zc = harq->Z; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); - uint32_t A = rel15->TBSize[0]<<3; - unsigned char *a=harq->pdu; - if (rel15->rnti != SI_RNTI) { - ws_trace_t tmp = {.nr = true, - .direction = DIRECTION_DOWNLINK, - .pdu_buffer = a, - .pdu_buffer_size = rel15->TBSize[0], - .ueid = 0, - .rntiType = WS_C_RNTI, - .rnti = rel15->rnti, - .sysFrame = frame, - .subframe = slot, - .harq_pid = 0, // difficult to find the harq pid here - .oob_event = 0, - .oob_event_value = 0}; - trace_pdu(&tmp); - } - NR_gNB_PHY_STATS_t *phy_stats = NULL; - if (rel15->rnti != 0xFFFF) - phy_stats = get_phy_stats(gNB, rel15->rnti); + nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot]; + memset(TBs, 0, sizeof(TBs)); + nrLDPC_slot_encoding_parameters_t slot_parameters = { + .frame = frame, + .slot = slot, + .nb_TBs = msgTx->num_pdsch_slot, + .threadPool = &gNB->threadPool, + .tinput = tinput, + .tprep = tprep, + .tparity = tparity, + .toutput = toutput, + .TBs = TBs + }; - if (phy_stats) { - phy_stats->frame = frame; - phy_stats->dlsch_stats.total_bytes_tx += rel15->TBSize[0]; - phy_stats->dlsch_stats.current_RI = rel15->nrOfLayers; - phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0]; - } + int num_segments = 0; - int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056; - int B; - if (A > NR_MAX_PDSCH_TBS) { - // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a,A)>>8; - a[A>>3] = ((uint8_t *)&crc)[2]; - a[1+(A>>3)] = ((uint8_t *)&crc)[1]; - a[2+(A>>3)] = ((uint8_t *)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - B = A + 24; - // harq->b = a; - AssertFatal((A / 8) + 4 <= max_bytes, - "A %d is too big (A/8+4 = %d > %d)\n", - A, - (A / 8) + 4, - max_bytes); - memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? - } else { - // Add 16-bit crc (polynomial A) to payload - crc = crc16(a,A)>>16; - a[A>>3] = ((uint8_t *)&crc)[1]; - a[1+(A>>3)] = ((uint8_t *)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - B = A + 16; - // harq->b = a; - AssertFatal((A / 8) + 3 <= max_bytes, - "A %d is too big (A/8+3 = %d > %d)\n", - A, - (A / 8) + 3, - max_bytes); - memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc - } + for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { - impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; + NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; - start_meas(dlsch_segmentation_stats); - impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, &impp.Zc, &impp.F, impp.BG); - stop_meas(dlsch_segmentation_stats); - - if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); - return(-1); - } - for (int r=0; rd[r][0]; - //channel_input[r] = &harq->d[r][0]; -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, impp.F); - LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,impp.n_segments); - LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]); - - for (int cnt =0 ; cnt < 22*(*impp.Zc)/8; cnt ++) { - LOG_D(PHY,"%d ", harq->c[r][cnt]); + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + unsigned int crc=1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + uint32_t A = rel15->TBSize[0]<<3; + unsigned char *a=harq->pdu; + if (rel15->rnti != SI_RNTI) { + ws_trace_t tmp = {.nr = true, + .direction = DIRECTION_DOWNLINK, + .pdu_buffer = a, + .pdu_buffer_size = rel15->TBSize[0], + .ueid = 0, + .rntiType = WS_C_RNTI, + .rnti = rel15->rnti, + .sysFrame = frame, + .subframe = slot, + .harq_pid = 0, // difficult to find the harq pid here + .oob_event = 0, + .oob_event_value = 0}; + trace_pdu(&tmp); } - LOG_D(PHY,"\n"); -#endif - //ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0); - //ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL); + NR_gNB_PHY_STATS_t *phy_stats = NULL; + if (rel15->rnti != 0xFFFF) + phy_stats = get_phy_stats(gNB, rel15->rnti); + + if (phy_stats) { + phy_stats->frame = frame; + phy_stats->dlsch_stats.total_bytes_tx += rel15->TBSize[0]; + phy_stats->dlsch_stats.current_RI = rel15->nrOfLayers; + phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0]; + } + + int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056; + int B; + if (A > NR_MAX_PDSCH_TBS) { + // Add 24-bit crc (polynomial A) to payload + crc = crc24a(a,A)>>8; + a[A>>3] = ((uint8_t *)&crc)[2]; + a[1+(A>>3)] = ((uint8_t *)&crc)[1]; + a[2+(A>>3)] = ((uint8_t *)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); + B = A + 24; + // harq->b = a; + AssertFatal((A / 8) + 4 <= max_bytes, + "A %d is too big (A/8+4 = %d > %d)\n", + A, + (A / 8) + 4, + max_bytes); + memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? + } else { + // Add 16-bit crc (polynomial A) to payload + crc = crc16(a,A)>>16; + a[A>>3] = ((uint8_t *)&crc)[1]; + a[1+(A>>3)] = ((uint8_t *)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); + B = A + 16; + // harq->b = a; + AssertFatal((A / 8) + 3 <= max_bytes, + "A %d is too big (A/8+3 = %d > %d)\n", + A, + (A / 8) + 3, + max_bytes); + memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc + } + + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + + // The harq_pid is not unique among the active HARQ processes in the instance so we use dlsch_id instead + TB_parameters->harq_unique_pid = dlsch_id; + TB_parameters->BG = rel15->maintenance_parms_v3.ldpcBaseGraph; + TB_parameters->Z = harq->Z; + TB_parameters->A = A; + start_meas(dlsch_segmentation_stats); + TB_parameters->Kb = nr_segmentation(harq->b, + harq->c, + B, + &TB_parameters->C, + &TB_parameters->K, + &TB_parameters->Z, + &TB_parameters->F, + TB_parameters->BG); + stop_meas(dlsch_segmentation_stats); + + if (TB_parameters->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B); + return(-1); + } + num_segments += TB_parameters->C; + } - impp.tprep = tprep; - impp.tinput = tinput; - impp.tparity = tparity; - impp.toutput = toutput; - impp.harq = harq; - if (gNB->ldpc_offload_flag) { - impp.Qm = rel15->qamModOrder[0]; - impp.Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes; - impp.rv = rel15->rvIndex[0]; + nrLDPC_segment_encoding_parameters_t segments[num_segments]; + memset(segments, 0, sizeof(segments)); + size_t segments_offset = 0; + size_t dlsch_offset = 0; + + for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { + NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + +#ifdef DEBUG_DLSCH_CODING + for (int r = 0; r < TB_parameters->C; r++) { + LOG_D(PHY, "Encoder: B %d F %d \n", harq->B, TB_parameters->F); + LOG_D(PHY, "start ldpc encoder segment %d/%d\n", r, TB_parameters->C); + LOG_D(PHY, "input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2], harq->c[r][3], harq->c[r][4]); + for (int cnt = 0; cnt < 22 * (TB_parameters->Z) / 8; cnt++) { + LOG_D(PHY, "%d ", harq->c[r][cnt]); + } + LOG_D(PHY, "\n"); + } +#endif + + TB_parameters->nb_rb = rel15->rbSize; + TB_parameters->Qm = rel15->qamModOrder[0]; + TB_parameters->mcs = rel15->mcsIndex[0]; + TB_parameters->nb_layers = rel15->nrOfLayers; + TB_parameters->rv_index = rel15->rvIndex[0]; + int nb_re_dmrs = (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData); - impp.G = nr_get_G(rel15->rbSize, - rel15->NrOfSymbols, - nb_re_dmrs, - get_num_dmrs(rel15->dlDmrsSymbPos), - harq->unav_res, - rel15->qamModOrder[0], - rel15->nrOfLayers); - for (int r = 0; r < impp.n_segments; r++) { - impp.perCB[r].E_cb = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r); - } - ldpc_interface_offload.LDPCencoder(harq->c, &impp.output, &impp); - } else { - size_t const n_seg = (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); + TB_parameters->G = nr_get_G(rel15->rbSize, + rel15->NrOfSymbols, + nb_re_dmrs, + get_num_dmrs(rel15->dlDmrsSymbPos), + harq->unav_res, + rel15->qamModOrder[0], + rel15->nrOfLayers); - encoder_implemparams_t arr[n_seg]; - task_ans_t ans[n_seg]; - memset(ans, 0, n_seg * sizeof(task_ans_t)); + TB_parameters->tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes; - for (int j = 0; j < n_seg; j++) { - encoder_implemparams_t *perJobImpp = &arr[j]; - *perJobImpp = impp; - perJobImpp->macro_num = j; - perJobImpp->ans = &ans[j]; + TB_parameters->segments = &segments[segments_offset]; + + size_t 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->c[r]; + segment_parameters->E = nr_get_E(TB_parameters->G, + TB_parameters->C, + TB_parameters->Qm, + rel15->nrOfLayers, + r); + segment_parameters->output = &output[dlsch_offset + r_offset]; + r_offset += segment_parameters->E; + + reset_meas(&segment_parameters->ts_interleave); + reset_meas(&segment_parameters->ts_rate_match); + reset_meas(&segment_parameters->ts_ldpc_encode); - task_t t = {.func = ldpc8blocks, .args = perJobImpp}; - pushTpool(&gNB->threadPool, t); } - join_task_ans(ans, n_seg); + segments_offset += TB_parameters->C; + + /* output and its parts for each dlsch should be aligned on 64 bytes + * => dlsch_offset should remain a multiple of 64 with enough offset to fit each dlsch + */ + const size_t dlsch_size = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers; + dlsch_offset += (dlsch_size + 63 - ((dlsch_size + 63) % 64)); } + + gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index f771d9050a..95474f64c0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -42,28 +42,23 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL); NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL); -/*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2 +/*! \brief Perform PUSCH decoding for the whole current received TTI. TS 38.212 V15.4.0 subclause 6.2 @param phy_vars_gNB, Pointer to PHY data structure for gNB - @param UE_id, ID of UE transmitting this PUSCH - @param ulsch_llr, Pointer to received llr in ulsch @param frame_parms, Pointer to frame descriptor structure - @param nb_symb_sch, number of symbols used in the uplink shared channel - @param nb_re_dmrs, number of DMRS resource elements in one RB + @param frame, current received frame @param nr_tti_rx, current received TTI - @param harq_pid, harq process id - @param is_crnti + @param G + @param ULSCH_ids, array of ULSCH ids + @param nb_pusch, number of uplink shared channels */ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, - uint8_t UE_id, - short *ulsch_llr, NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *pusch_pdu, uint32_t frame, uint8_t nr_tti_rx, - uint8_t harq_pid, - uint32_t G, - thread_info_tm_t *t_info); + uint32_t *G, + uint8_t *ULSCH_ids, + int nb_pusch); /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 @param llr, Pointer to llr bits diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 55c32b48d2..c61898e9bb 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -19,15 +19,8 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding.c +/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c * \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12 -* \author Ahmed Hussein -* \date 2019 -* \version 0.1 -* \company Fraunhofer IIS -* \email: ahmed.hussein@iis.fraunhofer.de -* \note -* \warning */ @@ -36,6 +29,7 @@ #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_defs.h" #include "PHY/CODING/lte_interleaver_inline.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/CODING/nrLDPC_extern.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" @@ -50,10 +44,6 @@ //#define DEBUG_ULSCH_DECODING //#define gNB_DEBUG_TRACE -#include -#include -#include - #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 //#define DEBUG_CRC #ifdef DEBUG_CRC @@ -123,361 +113,215 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) return(ulsch); } -static void nr_processULSegment(void *arg) -{ - ldpcDecode_t *rdata = (ldpcDecode_t *)arg; - NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; - t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - const int Kr = ulsch_harq->K; - const int Kr_bytes = Kr >> 3; - const int K_bits_F = Kr - ulsch_harq->F; - const int r = rdata->segment_r; - const int A = rdata->A; - const int E = rdata->E; - const int Qm = rdata->Qm; - const int rv_index = rdata->rv_index; - const int r_offset = rdata->r_offset; - const uint8_t kc = rdata->Kc; - short *ulsch_llr = rdata->ulsch_llr; - const int max_ldpc_iterations = p_decoderParms->numMaxIter; - int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); - - t_nrLDPC_time_stats procTime = {0}; - t_nrLDPC_time_stats *p_procTime = &procTime; - - //////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - //////////////////////////// ulsch_llr =====> ulsch_harq->e ////////////////////////////// - - /// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) - int16_t harq_e[E]; - - nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset); - - // for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset); - - - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// - - - if (nr_rate_matching_ldpc_rx(rdata->tbslbrm, - p_decoderParms->BG, - p_decoderParms->Z, - ulsch_harq->d[r], - harq_e, - ulsch_harq->C, - rv_index, - ulsch_harq->d_to_be_cleared[r], - E, - ulsch_harq->F, - Kr - ulsch_harq->F - 2 * (p_decoderParms->Z)) - == -1) { - - LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); - rdata->decodeIterations = max_ldpc_iterations + 1; - set_abort(&ulsch_harq->abort_decode, true); - - // Task completed - completed_task_ans(rdata->ans); - return; - } - - ulsch_harq->d_to_be_cleared[r] = false; - - memset(ulsch_harq->c[r], 0, Kr_bytes); - p_decoderParms->crc_type = crcType(ulsch_harq->C, A); - p_decoderParms->E = lenWithCrc(ulsch_harq->C, A); - - // set first 2*Z_c bits to zeros - - int16_t z[68 * 384 + 16] __attribute__((aligned(16))); - - memset(z, 0, 2 * ulsch_harq->Z * sizeof(*z)); - // set Filler bits - memset(z + K_bits_F, 127, ulsch_harq->F * sizeof(*z)); - // Move coded bits before filler bits - memcpy(z + 2 * ulsch_harq->Z, ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(*z)); - // skip filler bits - memcpy(z + Kr, ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(*z)); - // Saturate coded bits before decoding into 8 bits values - simde__m128i *pv = (simde__m128i *)&z; - int8_t l[68 * 384 + 16] __attribute__((aligned(16))); - simde__m128i *pl = (simde__m128i *)&l; - for (int i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { - pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]); - } - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - rdata->decodeIterations = - ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); - - if (rdata->decodeIterations <= p_decoderParms->numMaxIter) - memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); - - // Task completed - completed_task_ans(rdata->ans); -} - -int decode_offload(PHY_VARS_gNB *phy_vars_gNB, - uint8_t ULSCH_id, - short *ulsch_llr, - nfapi_nr_pusch_pdu_t *pusch_pdu, - t_nrLDPC_dec_params *decParams, - uint8_t harq_pid, - uint32_t G) -{ - NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; - int16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); - int8_t l_ol[NR_LDPC_MAX_NUM_CB * LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); - const int kc = decParams->BG == 2 ? 52 : 68; - uint32_t A = (harq_process->TBS) << 3; - const int Kr = harq_process->K; - const int Kr_bytes = Kr >> 3; - int8_t decodeIterations = 0; - int r_offset = 0; - int offset = 0; - // new data received, set processedSegments to 0 - if (!decParams->setCombIn) - harq_process->processedSegments = 0; - - for (int r = 0; r < harq_process->C; r++) { - decParams->perCB[r].E_cb = nr_get_E(G, harq_process->C, decParams->Qm, pusch_pdu->nrOfLayers, r); - memcpy(z_ol, ulsch_llr + r_offset, decParams->perCB[r].E_cb * sizeof(int16_t)); - simde__m128i *pv_ol128 = (simde__m128i *)z_ol; - simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset]; - for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { - pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); - } - decParams->F = harq_process->F; - r_offset += decParams->perCB[r].E_cb; - offset += LDPC_MAX_CB_SIZE; - } - - int8_t p_outDec[harq_process->C * Kr_bytes]; - memset(p_outDec, 0, sizeof(p_outDec)); - decodeIterations = - ldpc_interface_offload.LDPCdecoder(decParams, harq_pid, ULSCH_id, harq_process->C, (int8_t *)l_ol, p_outDec, NULL, NULL); - - if (decodeIterations < 0) { - LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); - return -1; - } - - int offset_b = 0; - for (int r = 0; r < harq_process->C; r++) { - if (decParams->perCB[r].status_cb == 0 || harq_process->C == 1) { - memcpy(harq_process->b + offset_b, &p_outDec[offset_b], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - harq_process->processedSegments++; - } - offset_b += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - } - - bool crc_valid = false; - // CRC check made by the T2, no need to perform CRC check for a single code block twice - if (harq_process->processedSegments == harq_process->C) { - crc_valid = check_crc(harq_process->b, lenWithCrc(1, A), crcType(1, A)); - if (harq_process->C == 1 && !crc_valid) { - harq_process->processedSegments--; - } - } - - if (crc_valid) { - LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS); - nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); - ulsch->active = false; - harq_process->round = 0; - } else { - LOG_D(PHY, - "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", - phy_vars_gNB->Mod_id, - ulsch->frame, - ulsch->slot, - harq_pid, - ulsch->active, - harq_process->round, - harq_process->TBS); - nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); - ulsch->handled = 1; - decodeIterations = ulsch->max_ldpc_iterations + 1; - LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - } - - ulsch->last_iteration_cnt = decodeIterations; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0); - return 0; -} - int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, - uint8_t ULSCH_id, - short *ulsch_llr, NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *pusch_pdu, uint32_t frame, uint8_t nr_tti_rx, - uint8_t harq_pid, - uint32_t G, - thread_info_tm_t *t_info) + uint32_t *G, + uint8_t *ULSCH_ids, + int nb_pusch) { - if (!ulsch_llr) { - LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); - return -1; - } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1); - NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; - NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + nrLDPC_TB_decoding_parameters_t TBs[nb_pusch]; + memset(TBs, 0, sizeof(TBs)); + nrLDPC_slot_decoding_parameters_t slot_parameters = { + .frame = frame, + .slot = nr_tti_rx, + .nb_TBs = nb_pusch, + .threadPool = &phy_vars_gNB->threadPool, + .TBs = TBs + }; - if (!harq_process) { - LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); - return -1; - } + int max_num_segments = 0; - // ------------------------------------------------------------------ - const uint16_t nb_rb = pusch_pdu->rb_size; - const uint8_t Qm = pusch_pdu->qam_mod_order; - const uint8_t mcs = pusch_pdu->mcs_index; - const uint8_t n_layers = pusch_pdu->nrOfLayers; - // ------------------------------------------------------------------ + for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) { + uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; - harq_process->TBS = pusch_pdu->pusch_data.tb_size; + nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id]; - t_nrLDPC_dec_params decParams = {.check_crc = check_crc}; - decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; - const uint32_t A = (harq_process->TBS) << 3; - NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); - if (stats) { - stats->frame = frame; - stats->ulsch_stats.round_trials[harq_process->round]++; - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]); - stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]); + TB_parameters->G = G[pusch_id]; + + if (!harq_process) { + LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); + return -1; } - if (!harq_process->harq_to_be_cleared) { - stats->ulsch_stats.current_Qm = Qm; - stats->ulsch_stats.current_RI = n_layers; - stats->ulsch_stats.total_bytes_tx += harq_process->TBS; + + // The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead + TB_parameters->harq_unique_pid = ULSCH_id; + + // ------------------------------------------------------------------ + TB_parameters->nb_rb = pusch_pdu->rb_size; + TB_parameters->Qm = pusch_pdu->qam_mod_order; + TB_parameters->mcs = pusch_pdu->mcs_index; + TB_parameters->nb_layers = pusch_pdu->nrOfLayers; + // ------------------------------------------------------------------ + + TB_parameters->processedSegments = &harq_process->processedSegments; + harq_process->TBS = pusch_pdu->pusch_data.tb_size; + + TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; + TB_parameters->A = (harq_process->TBS) << 3; + NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); + if (stats) { + stats->frame = frame; + stats->ulsch_stats.round_trials[harq_process->round]++; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]); + stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]); + } + if (!harq_process->harq_to_be_cleared) { + stats->ulsch_stats.current_Qm = TB_parameters->Qm; + stats->ulsch_stats.current_RI = TB_parameters->nb_layers; + stats->ulsch_stats.total_bytes_tx += harq_process->TBS; + } } - } - - LOG_D(PHY, - "ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", - harq_pid, - ulsch->rnti, - A, - G, - mcs, - n_layers, - nb_rb, - Qm, - pusch_pdu->target_code_rate / 10240.0f, - pusch_pdu->pusch_data.rv_index, - harq_process->round, - harq_process->harq_to_be_cleared); - - // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F) - nr_segmentation(NULL, - NULL, - lenWithCrc(1, A), // size in case of 1 segment - &harq_process->C, - &harq_process->K, - &harq_process->Z, // [hna] Z is Zc - &harq_process->F, - decParams.BG); - - uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * n_layers; // number of segments to be allocated - if (harq_process->C > a_segments) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); - return(-1); - } - 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; - } - + + uint8_t harq_pid = ulsch->harq_pid; + LOG_D(PHY, + "ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", + harq_pid, + ulsch->rnti, + TB_parameters->A, + TB_parameters->G, + TB_parameters->mcs, + TB_parameters->nb_layers, + TB_parameters->nb_rb, + TB_parameters->Qm, + pusch_pdu->target_code_rate / 10240.0f, + pusch_pdu->pusch_data.rv_index, + harq_process->round, + harq_process->harq_to_be_cleared); + + // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F) + nr_segmentation(NULL, + NULL, + lenWithCrc(1, TB_parameters->A), // 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; + + uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers; // number of segments to be allocated + if (TB_parameters->C > a_segments) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A); + return(-1); + } + if (TB_parameters->nb_rb != 273) { + a_segments = a_segments*TB_parameters->nb_rb; + a_segments = a_segments/273 +1; + } + if (TB_parameters->C > a_segments) { + LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); + return -1; + } + max_num_segments = max(max_num_segments, TB_parameters->C); + #ifdef DEBUG_ULSCH_DECODING - printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); - if (!frame % 100) - printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); - printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); + printf("ulsch decoding nr segmentation Z %d\n", TB_parameters->Z); + if (!frame % 100) + printf("K %d C %d Z %d \n", + TB_parameters->K, + TB_parameters->C, + TB_parameters->Z); + printf("Segmentation: C %d, K %d\n", + TB_parameters->C, + TB_parameters->K); #endif + + TB_parameters->max_ldpc_iterations = ulsch->max_ldpc_iterations; + TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index; + TB_parameters->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; + TB_parameters->abort_decode = &harq_process->abort_decode; + set_abort(&harq_process->abort_decode, false); - decParams.Z = harq_process->Z; - decParams.numMaxIter = ulsch->max_ldpc_iterations; - decParams.Qm = Qm; - decParams.rv = pusch_pdu->pusch_data.rv_index; - decParams.outMode = 0; - decParams.setCombIn = !harq_process->harq_to_be_cleared; - if (harq_process->harq_to_be_cleared) { - for (int r = 0; r < harq_process->C; r++) - harq_process->d_to_be_cleared[r] = true; - harq_process->harq_to_be_cleared = false; } - if (phy_vars_gNB->ldpc_offload_flag) - return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G); - harq_process->processedSegments = 0; - uint32_t offset = 0, r_offset = 0; - set_abort(&harq_process->abort_decode, false); - for (int r = 0; r < harq_process->C; r++) { - int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); + nrLDPC_segment_decoding_parameters_t segments[nb_pusch][max_num_segments]; + memset(segments, 0, sizeof(segments)); - ldpcDecode_t *rdata = &((ldpcDecode_t *)t_info->buf)[t_info->len]; - DevAssert(t_info->len < t_info->cap); - rdata->ans = &t_info->ans[t_info->len]; - t_info->len += 1; + for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) { + uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + short *ulsch_llr = phy_vars_gNB->pusch_vars[ULSCH_id].llr; - decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, - E, - decParams.BG, - decParams.Z, - &harq_process->llrLen, - harq_process->round); - rdata->gNB = phy_vars_gNB; - rdata->ulsch_harq = harq_process; - rdata->decoderParms = decParams; - rdata->ulsch_llr = ulsch_llr; - rdata->Kc = decParams.BG == 2 ? 52 : 68; - rdata->harq_pid = harq_pid; - rdata->segment_r = r; - rdata->nbSegments = harq_process->C; - rdata->E = E; - rdata->A = A; - rdata->Qm = Qm; - rdata->r_offset = r_offset; - rdata->Kr_bytes = harq_process->K >> 3; - rdata->rv_index = pusch_pdu->pusch_data.rv_index; - rdata->offset = offset; - rdata->ulsch = ulsch; - rdata->ulsch_id = ULSCH_id; - rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; + if (!ulsch_llr) { + LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); + return -1; + } - task_t t = {.func = &nr_processULSegment, .args = rdata}; - pushTpool(&phy_vars_gNB->threadPool, t); + nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id]; + TB_parameters->segments = segments[pusch_id]; + + uint32_t r_offset = 0; + for (int r = 0; r < TB_parameters->C; r++) { + 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->round); + segment_parameters->llr = ulsch_llr + r_offset; + segment_parameters->d = harq_process->d[r]; + segment_parameters->d_to_be_cleared = &harq_process->d_to_be_cleared[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->harq_to_be_cleared) { + for (int r = 0; r < TB_parameters->C; r++) { + harq_process->d_to_be_cleared[r] = true; + } + harq_process->harq_to_be_cleared = false; + } - LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); - r_offset += E; - offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); } - return harq_process->C; + + int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters); + + // post decode + for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) { + uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + + nrLDPC_TB_decoding_parameters_t TB_parameters = TBs[pusch_id]; + + uint32_t offset = 0; + for (int r = 0; r < TB_parameters.C; r++) { + nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = TB_parameters.segments[r]; + // Copy c to b in case of decoding success + if (nrLDPC_segment_decoding_parameters.decodeSuccess) { + memcpy(harq_process->b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + } else { + LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); + LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); + } + offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + } + } + + return ret_decoder; } diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index f6e6559414..e8fdfd4dda 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -40,6 +40,7 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/impl_defs_top.h" #include "PHY/defs_common.h" +#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" #include "PHY/CODING/nrLDPC_extern.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" #include "executables/rt_profiling.h" @@ -494,9 +495,10 @@ typedef struct PHY_VARS_gNB_s { /// OFDM symbol offset divisor for UL uint32_t ofdm_offset_divisor; - int ldpc_offload_flag; - + /// NR LDPC coding related + nrLDPC_coding_interface_t nrLDPC_coding_interface; int max_ldpc_iterations; + /// indicate the channel estimation technique in time domain int chest_time; /// indicate the channel estimation technique in freq domain diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 7b3a82c7ce..26251506c7 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -305,187 +305,144 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0); } -static void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata) +static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, bool *ulsch_to_decode) { - NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; - NR_gNB_ULSCH_t *ulsch = rdata->ulsch; - int r = rdata->segment_r; - nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[rdata->ulsch_id].harq_process->ulsch_pdu; - bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter); - ulsch_harq->processedSegments++; - LOG_D(PHY, - "processing result of segment: %d, processed %d/%d, %s\n", - rdata->segment_r, - ulsch_harq->processedSegments, - rdata->nbSegments, - decodeSuccess ? "Decoded Successfully" : "Decoding Unsuccessful"); + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - if (decodeSuccess) { - memcpy(ulsch_harq->b + rdata->offset, ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0)); - - } else { - LOG_D(PHY, "ULSCH %d in error\n", rdata->ulsch_id); + int nb_pusch = 0; + for (uint8_t ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { + if (ulsch_to_decode[ULSCH_id]) { + nb_pusch++; + } } - //int dumpsig=0; - // if all segments are done - if (ulsch_harq->processedSegments == ulsch_harq->C) { - // When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the - // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block - bool crc_valid = true; - if (ulsch_harq->C > 1) { - crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, rdata->A), crcType(1, rdata->A)); + if (nb_pusch == 0) { + return 0; + } + + uint8_t ULSCH_ids[nb_pusch]; + uint32_t G[nb_pusch]; + int pusch_id = 0; + for (uint8_t ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { + + if (ulsch_to_decode[ULSCH_id]) { + + ULSCH_ids[pusch_id] = ULSCH_id; + + nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu; + + uint16_t nb_re_dmrs; + uint16_t start_symbol = pusch_pdu->start_symbol_index; + uint16_t number_symbols = pusch_pdu->nr_of_symbols; + + uint8_t number_dmrs_symbols = 0; + for (int l = start_symbol; l < start_symbol + number_symbols; l++) + number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01; + + if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1) + nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data; + else + nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data; + + G[pusch_id] = nr_get_G(pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + gNB->ulsch[ULSCH_id].unav_res, + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); + AssertFatal(G[pusch_id]>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n", + pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); + LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n", + pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + pusch_pdu->ul_dmrs_symb_pos, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); + pusch_id++; + } + } + + //---------------------------------------------------------- + //--------------------- ULSCH decoding --------------------- + //---------------------------------------------------------- + + int ret_nr_ulsch_decoding = + nr_ulsch_decoding(gNB, frame_parms, frame_rx, slot_rx, G, ULSCH_ids, nb_pusch); + + // CRC check per uplink shared channel + for (pusch_id = 0; pusch_id < nb_pusch; pusch_id++) { + uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; + NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; + NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; + nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu; + + bool crc_valid = false; + + // if all segments are done + if (ulsch_harq->processedSegments == ulsch_harq->C) { + if (ulsch_harq->C > 1) { + crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, (ulsch_harq->TBS) << 3), crcType(1, (ulsch_harq->TBS) << 3)); + } else { + // When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the + // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block + crc_valid = true; + } } - if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) { + if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !pusch->DTX) { LOG_D(NR_PHY, "[gNB %d] ULSCH %d: Setting ACK for SFN/SF %d.%d (rnti %x, pid %d, ndi %d, status %d, round %d, TBS %d, Max interation " "(all seg) %d)\n", gNB->Mod_id, - rdata->ulsch_id, + ULSCH_id, ulsch->frame, ulsch->slot, ulsch->rnti, - rdata->harq_pid, + ulsch->harq_pid, pusch_pdu->pusch_data.new_data_indicator, ulsch->active, ulsch_harq->round, ulsch_harq->TBS, - rdata->decodeIterations); - nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0); + ulsch->max_ldpc_iterations); + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 0, 0); LOG_D(PHY, "ULSCH received ok \n"); ulsch->active = false; ulsch_harq->round = 0; - //dumpsig=1; + ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure } else { LOG_D(PHY, "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, " - "TBS %d) r %d\n", + "TBS %d)\n", gNB->Mod_id, ulsch->frame, ulsch->slot, - rdata->harq_pid, + ulsch->harq_pid, pusch_pdu->pusch_data.new_data_indicator, ulsch->active, ulsch_harq->round, ulsch_harq->ulsch_pdu.pusch_data.rv_index, ulsch_harq->ulsch_pdu.rb_start, ulsch_harq->ulsch_pdu.rb_size, - ulsch_harq->TBS, - r); - nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0); + ulsch_harq->TBS); + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0); ulsch->handled = 1; - LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id); - // dumpsig=1; + LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); + ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure } - ulsch->last_iteration_cnt = rdata->decodeIterations; - /* - if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) { - int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0; - - LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][0][(ulsch_harq->slot%RU_RX_SLOT_DEPTH)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); - LOG_M("rxsigF0_ext.m","rxsF0_ext", - &gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0", - &gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); - LOG_M("rxsigF0_comp.m","rxsF0_comp", - &gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr", - &gNB->pusch_vars[0].llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size * - ulsch_harq->ulsch_pdu.qam_mod_order,1,0); if (gNB->frame_parms.nb_antennas_rx > 1) { - - LOG_M("rxsigF1_ext.m","rxsF0_ext", - &gNB->pusch_vars[0].rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1", - &gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); - LOG_M("rxsigF1_comp.m","rxsF1_comp", - &gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * - ulsch_harq->ulsch_pdu.rb_size)),1,1); - } - exit(-1); - - } - */ - ulsch->last_iteration_cnt = rdata->decodeIterations; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0); } + + return ret_nr_ulsch_decoding; } -static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, - int frame_rx, - int slot_rx, - int ULSCH_id, - uint8_t harq_pid, - thread_info_tm_t *t_info) -{ - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu; - - uint16_t nb_re_dmrs; - uint16_t start_symbol = pusch_pdu->start_symbol_index; - uint16_t number_symbols = pusch_pdu->nr_of_symbols; - - uint8_t number_dmrs_symbols = 0; - for (int l = start_symbol; l < start_symbol + number_symbols; l++) - number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01; - - if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1) - nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data; - else - nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data; - - uint32_t G = nr_get_G(pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - gNB->ulsch[ULSCH_id].unav_res, - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - - AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n", - pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n", - pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - pusch_pdu->ul_dmrs_symb_pos, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - - //---------------------------------------------------------- - //--------------------- ULSCH decoding --------------------- - //---------------------------------------------------------- - /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 - * (valid for unitary physical simulators). ULSCH processing lopp is then executed - * only once, which ensures exactly one start and stop of the ULSCH decoding time - * measurement per processed TB.*/ - if (gNB->max_nb_pusch == 1) - start_meas(&gNB->ulsch_decoding_stats); - - int const nbDecode = nr_ulsch_decoding(gNB, - ULSCH_id, - gNB->pusch_vars[ULSCH_id].llr, - frame_parms, - pusch_pdu, - frame_rx, - slot_rx, - harq_pid, - G, - t_info); - return nbDecode; -} - - void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag) { NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; @@ -840,12 +797,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } } - ldpcDecode_t arr[64]; - task_ans_t ans[64] = {0}; - thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .len = 0, .cap = 64, .ans = ans}; - - // int64_t const t0 = time_now_ns(); - int totalDecode = 0; + bool ulsch_to_decode[gNB->max_nb_pusch]; + bzero((void *)ulsch_to_decode, sizeof(ulsch_to_decode)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; @@ -937,25 +890,26 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) pusch_vars->DTX = 0; } + ulsch_to_decode[ULSCH_id] = true; stop_meas(&gNB->rx_pusch_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0); // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); - int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, &t_info); - if (tasks_added > 0) - totalDecode += tasks_added; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } - DevAssert(totalDecode == t_info.len); + /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 + * (valid for unitary physical simulators). ULSCH processing lopp is then executed + * only once, which ensures exactly one start and stop of the ULSCH decoding time + * measurement per processed TB.*/ + if (gNB->max_nb_pusch == 1) + start_meas(&gNB->ulsch_decoding_stats); - join_task_ans(t_info.ans, t_info.len); - for (int i = 0; i < t_info.len; ++i) { - nr_postDecode(gNB, &arr[i]); + int const ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_to_decode); + if (ret_nr_ulsch_procedures != 0) { + LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures); } + /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 * (valid for unitary physical simulators). ULSCH processing loop is then executed * only once, which ensures exactly one start and stop of the ULSCH decoding time