From 3645c96c090772130e6e9cd109417a48933353eb Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 5 May 2023 12:05:54 +0200 Subject: [PATCH] remove generic thread pool abort --- common/utils/threadPool/thread-pool.c | 6 - common/utils/threadPool/thread-pool.h | 58 --- common/utils/threadPool/thread-pool.md | 23 +- .../CODING/3gpplte_turbo_decoder_sse_16bit.c | 13 +- .../CODING/3gpplte_turbo_decoder_sse_8bit.c | 10 +- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 10 +- openair1/PHY/CODING/coding_load.c | 31 +- .../CODING/nrLDPC_decoder/nrLDPC_decoder.c | 34 +- .../CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c | 8 +- openair1/PHY/CODING/nrLDPC_defs.h | 2 +- openair1/PHY/INIT/nr_init_ue.c | 14 +- openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 1 + openair1/PHY/LTE_TRANSPORT/transport_proto.h | 14 - openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 19 +- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 8 +- openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h | 1 + openair1/PHY/NR_TRANSPORT/nr_ulsch.h | 31 +- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 374 +++++++++--------- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 121 +++--- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 1 + openair1/PHY/defs_common.h | 32 +- openair1/PHY/defs_gNB.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 57 ++- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 59 ++- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 7 +- openair1/SCHED_UE/phy_procedures_lte_ue.c | 2 + openair1/SIMULATION/NR_PHY/ulschsim.c | 44 +-- openair1/SIMULATION/NR_PHY/ulsim.c | 31 +- 28 files changed, 457 insertions(+), 556 deletions(-) diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index f0f4769faf..5531a3aed3 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -218,14 +218,8 @@ int main() { tmp=pullNotifiedFIFO(&myFifo); printf("pulled: %lu\n", tmp->key); displayList(&myFifo); - abortNotifiedFIFOJob(&myFifo,1005); - printf("aborted 1005\n"); - displayList(&myFifo); pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 12345678, NULL, NULL)); displayList(&myFifo); - abortNotifiedFIFOJob(&myFifo,12345678); - printf("aborted 12345678\n"); - displayList(&myFifo); do { tmp=pollNotifiedFIFO(&myFifo); diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index b06671c728..66e1152f48 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -197,31 +197,6 @@ static inline time_stats_t exec_time_stats_NotifiedFIFO(const notifiedFIFO_elt_t return ts; } -// This function aborts all messages matching the key -// If the queue is used in thread pools, it doesn't cancels already running processing -// because the message has already been picked -static inline int abortNotifiedFIFOJob(notifiedFIFO_t *nf, uint64_t key) { - mutexlock(nf->lockF); - int nbDeleted=0; - notifiedFIFO_elt_t **start=&nf->outF; - - while(*start!=NULL) { - if ( (*start)->key == key ) { - notifiedFIFO_elt_t *request=*start; - *start=(*start)->next; - delNotifiedFIFO_elt(request); - nbDeleted++; - } else - start=&(*start)->next; - } - - if (nf->outF == NULL) - nf->inF=NULL; - - mutexunlock(nf->lockF); - return nbDeleted; -} - // This functions aborts all messages in the queue, and marks the queue as // "aborted", such that every call to it will return NULL static inline void abortNotifiedFIFO(notifiedFIFO_t *nf) { @@ -317,39 +292,6 @@ static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpo return msg; } -static inline int abortTpoolJob(tpool_t *t, uint64_t key) { - int nbRemoved=0; - notifiedFIFO_t *nf=&t->incomingFifo; - - mutexlock(nf->lockF); - notifiedFIFO_elt_t **start=&nf->outF; - - while(*start!=NULL) { - if ( (*start)->key == key ) { - notifiedFIFO_elt_t *request=*start; - *start=(*start)->next; - delNotifiedFIFO_elt(request); - nbRemoved++; - } else - start=&(*start)->next; - } - - if (t->incomingFifo.outF==NULL) - t->incomingFifo.inF=NULL; - - struct one_thread *thread = t->allthreads; - while (thread != NULL) { - if (thread->runningOnKey == key) { - thread->dropJob = true; - nbRemoved++; - } - - thread = thread->next; - } - - mutexunlock(nf->lockF); - return nbRemoved; -} static inline int abortTpool(tpool_t *t) { int nbRemoved=0; /* disables threading: if a message comes in now, we cannot have a race below diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md index 249951666c..311857ff3e 100644 --- a/common/utils/threadPool/thread-pool.md +++ b/common/utils/threadPool/thread-pool.md @@ -2,8 +2,6 @@ The **thread pool** is a working server, made of a set of worker threads that can be mapped on CPU cores. Each thread pool has an **input queue** ("**FIFO**"), from which its workers pick **jobs** (FIFO element) to execute. When a job is done, the worker sends a message to an output queue, if it has been defined. -A selective abort allows to cancel parallel jobs. This can be useful, e.g., if a client pushed jobs, but from a response of one job, the other linked jobs become useless. - All the thread pool functions are thread safe. The functions executed by worker threads are provided by the thread pool client, so the client has to handle the concurrency/parallel execution of his functions. ## license @@ -56,7 +54,6 @@ Queues can be used to enqueue messages/jobs, of type `notifiedFIFO_t`. * `pushNotifiedFIFO()`: Add a job to a queue * `pullNotifiedFIFO()`: Pull a job from a queue. This call is blocking until a job arrived. * `pollNotifiedFIFO()`: Pull a job from a queue. This call is not blocking, so it returns always very shortly -* `abortNotifiedFIFOJob()`: Allows to delete all waiting jobs that match a key (see `key` in jobs definition) * `abortNotifiedFIFO()`: Aborts a FIFO, such that it will always return `NULL` Note that in 99.9% of cases, `pull()` is better than `poll()`. @@ -104,12 +101,6 @@ Like `pullNotifiedFIFO()`, but non-blocking: they check if the queue `nf` contai Note that unlike for `pullNotifiedFIFO()`, returning `NULL` does not inform whether the queue has been aborted; the caller should manually check the `abortFIFO` flag of `nf` in this case. -### `int abortNotifiedFIFOJob(notifiedFIFO_t *nf, uint64_t key)` - -Aborts all jobs in FIFO queue `nf` with key `key`. Jobs already under execution will be silently dropped and not put in the FIFO return queue, if any. - -Returns the number of aborted jobs. - ### `void abortNotifiedFIFO(notifiedFIFO_t *nf)` Aborts the entire FIFO queue `nf`: all jobs will be dropped, and the FIFO is marked as aborted, such that a call to `pullNotifiedFIFO()` returns `NULL`. @@ -135,10 +126,6 @@ If they need a return value (e.g., result of a computation), they have to create ## Abort -A abort service `abortTpoolJob()` allows to abort all jobs that match a key (see a job's `key`). When the abort returns, it garanties that no job (matching the key) response will be posted on response queues. - -Nevertheless, jobs already performed before the return of `abortTpoolJob()` are pushed in the response Fifo queue. - `abortTpool()` kills all jobs in the Tpool, and terminates the pool. ## API details @@ -171,7 +158,7 @@ Adds a job for processing in the thread pool. The job data you can set are, inside `msg`: -* `key`: an arbitrary key to find a job in a response queue, and which can be used to abort jobs using `abortTpoolJob()`. +* `key`: an arbitrary key to find a job in a response queue. * `reponseFifo`: if non-`NULL`, the message will be sent back on this queue when the job is done. If `NULL`, the thread pool automatically frees the job when it is done. * `processingFunc`: the function to execute for this job. @@ -187,14 +174,6 @@ Multiple return queues might be useful. Consider the following example in the eN The same as `pullTpool()` in a non-blocking fashion (an alternative name would have been `pollTpool()`). -### `int abortTpoolJob(tpool_t *t, uint64_t key)` - -Is a facility to cancel work you pushed to a thread pool: every job with a given `key` will be deleted, and results of jobs with such `key` under execution will be dropped. - -It returns the number of aborted jobs, including the ones that are currently being executed. - -I used it once: when eNB performs turbo decode, I push all segments in the thread pool. But when I get back the decoding results, if one segment can't be decoded, I don't need the results of the other segments of the same UE. - ### `int abortTpool(tpool_t *t)` Aborts the complete Tpool: cancel every work in the input queue, marks to drop existing jobs in processing, and terminates all worker threads. It is afterwards still possible to call functions such as `pushTpool()`, but each calling thread will execute the job itself. diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c index 896e69a4b1..110a659000 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c @@ -982,7 +982,9 @@ uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, time_stats_t *gamma_stats, time_stats_t *ext_stats, time_stats_t *intl1_stats, - time_stats_t *intl2_stats) { + time_stats_t *intl2_stats, + decode_abort_t *ab) +{ /* y is a pointer to the input decoded_bytes is a pointer to the decoded output n is the size in bits of the coded block, with the tail */ @@ -1356,7 +1358,8 @@ uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, return(iteration_cnt); } } - + if (check_abort(ab)) + return max_iterations + 2; // do log_map from first parity bit if (iteration_cnt < max_iterations) { log_map16(systematic1,yparity1,m11,m10,alpha,beta,ext,n,0,F,offset8_flag,alpha_stats,beta_stats,gamma_stats,ext_stats); @@ -1390,9 +1393,7 @@ uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, _mm_empty(); _m_empty(); #endif + if (iteration_cnt > max_iterations) + set_abort(ab, true); return(iteration_cnt); } - - - - diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c index 0614a9d071..1c18f909a7 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c @@ -792,7 +792,9 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, time_stats_t *gamma_stats, time_stats_t *ext_stats, time_stats_t *intl1_stats, - time_stats_t *intl2_stats) { + time_stats_t *intl2_stats, + decode_abort_t *ab) +{ /* y is a pointer to the input decoded_bytes is a pointer to the decoded output n is the size in bits of the coded block, with the tail */ @@ -1278,7 +1280,8 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, return(iteration_cnt); } } - + if (check_abort(ab)) + return max_iterations + 2; // do a new iteration if it is not yet decoded if (iteration_cnt < max_iterations) { log_map8(systematic1,yparity1,m11,m10,alpha,beta,ext,n2,0,F,offset8_flag,alpha_stats,beta_stats,gamma_stats,ext_stats); @@ -1303,6 +1306,7 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, } } } - + if (iteration_cnt > max_iterations) + set_abort(ab, true); return(iteration_cnt); } diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 66cd8ffde7..45bfb2cfd5 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -185,7 +185,6 @@ int test_ldpc(short max_iterations, } } - //determine number of bits in codeword if (block_length>3840) { @@ -270,6 +269,8 @@ int test_ldpc(short max_iterations, if (ntrials==0) encoder_orig(test_input,channel_input, Zc, BG, block_length, BG, &impp); impp.gen_code=0; + decode_abort_t dec_abort; + init_abort(&dec_abort); for (int trial=0; trial < ntrials; trial++) { segment_bler = 0; @@ -359,7 +360,12 @@ int test_ldpc(short max_iterations, } for(int j=0;j p_decParams->numMaxIter) + set_abort(ab, true); return numIter; } @@ -147,7 +158,13 @@ int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_ \param p_decParamsnrLDPC decoder parameters \param p_profilernrLDPC profiler statistics */ -static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler) +static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, + int8_t* p_out, + uint32_t numLLR, + t_nrLDPC_lut* p_lut, + t_nrLDPC_dec_params* p_decParams, + t_nrLDPC_time_stats* p_profiler, + decode_abort_t* ab) { uint16_t Z = p_decParams->Z; uint8_t BG = p_decParams->BG; @@ -478,8 +495,9 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_ while ( (i < numMaxIter) && (pcRes != 0) ) { // Increase iteration counter i++; - - // CN processing + if (check_abort(ab)) + return numMaxIter + 2; + // CN processing #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->cnProc); #endif diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c index c60286ab3a..74b3dbb41b 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c @@ -334,8 +334,12 @@ void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_ // init_LLR_DMA(p_decParams, p_llr, p_out); } - -int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out,t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats *time_decoder) +int32_t nrLDPC_decod(t_nrLDPC_dec_params *p_decParams, + int8_t *p_llr, + int8_t *p_out, + t_nrLDPC_procBuf *p_procBuf, + t_nrLDPC_time_stats *time_decoder, + decode_abort_t *ab) { uint16_t Zc = p_decParams->Z; uint8_t BG = p_decParams->BG; diff --git a/openair1/PHY/CODING/nrLDPC_defs.h b/openair1/PHY/CODING/nrLDPC_defs.h index 1aab887640..57d84bf8cb 100644 --- a/openair1/PHY/CODING/nrLDPC_defs.h +++ b/openair1/PHY/CODING/nrLDPC_defs.h @@ -73,7 +73,7 @@ typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,sho \param p_profiler LDPC profiler statistics */ -typedef int32_t(*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params* , int8_t*, int8_t* , t_nrLDPC_time_stats* ); +typedef int32_t (*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params *, int8_t *, int8_t *, t_nrLDPC_time_stats *, decode_abort_t *ab); typedef int32_t(*nrLDPC_decoffloadfunc_t)(t_nrLDPC_dec_params* , uint8_t, uint8_t, uint8_t , uint8_t, uint16_t, uint32_t, uint8_t, int8_t*, int8_t* ,uint8_t); typedef int32_t(*nrLDPC_dectopfunc_t)(void); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index c72dd8cad1..1fb9ca985f 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -573,18 +573,10 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PR 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); + init_abort(&harq_list[j][i].abort_decode); for (int r=0; rharq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); + init_abort(&ulsch->harq_processes[i]->abort_decode); ulsch->harq_processes[i]->decodedBytes = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); if (ulsch->harq_processes[i]->decodedBytes) @@ -281,11 +282,21 @@ void processULSegment(void * arg) { &eNB->ulsch_tc_gamma_stats, &eNB->ulsch_tc_ext_stats, &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); + &eNB->ulsch_tc_intl2_stats, + &ulsch_harq->abort_decode); } -int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, - int UE_id,int harq_pid,int llr8_flag) { +/*! + \brief Decoding of ULSCH data component from 36-212. This one is single thread. + @param phy_vars_eNB Pointer to eNB top-level descriptor + @param UE_id ID of UE transmitting this PUSCH + @param harq_pid HARQ process ID + @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used + @returns 0 on success +*/ + +static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag) +{ unsigned int r_offset=0; int offset = 0; LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; @@ -297,7 +308,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, decoder_if_t * td=llr8_flag == 0 ? *decoder16 : *decoder8; ulsch_harq->processedSegments=0; - + set_abort(&ulsch_harq->abort_decode, false); for (int r=0; rC; r++) { // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); // Get Turbo interleaver parameters diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index 129dcef447..a89588050f 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -106,9 +106,10 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_ for (i=0; iharq_processes[i] = (LTE_DL_UE_HARQ_t *)malloc16(sizeof(LTE_DL_UE_HARQ_t)); - if (dlsch->harq_processes[i]) { memset(dlsch->harq_processes[i],0,sizeof(LTE_DL_UE_HARQ_t)); + init_abort(&dlsch->harq_processes[i]->abort_decode); + dlsch->harq_processes[i]->first_tx=1; dlsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling); @@ -277,7 +278,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, printf("Segmentation: C %d, Cminus %d, Kminus %d, Kplus %d\n",harq_process->C,harq_process->Cminus,harq_process->Kminus,harq_process->Kplus); #endif opp_enabled=1; - + set_abort(&harq_process->abort_decode, false); for (r=0; rC; r++) { // Get Turbo interleaver parameters if (rCminus) @@ -381,7 +382,8 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, &phy_vars_ue->dlsch_tc_gamma_stats, &phy_vars_ue->dlsch_tc_ext_stats, &phy_vars_ue->dlsch_tc_intl1_stats, - &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1); + &phy_vars_ue->dlsch_tc_intl2_stats, + &harq_process->abort_decode); //(is_crnti==0)?harq_pid:harq_pid+1); stop_UE_TIMING(phy_vars_ue->dlsch_turbo_decoding_stats); } diff --git a/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h b/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h index 5f8763414e..a10e0515a5 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h +++ b/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h @@ -269,6 +269,7 @@ typedef struct { uint32_t errors[8]; /// codeword this transport block is mapped to uint8_t codeword; + decode_abort_t abort_decode; } LTE_DL_UE_HARQ_t; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index f2028e6591..ec7f6cae69 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -49,16 +49,15 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL); @param is_crnti */ -uint32_t 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); - +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); /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 @param llr, Pointer to llr bits @@ -70,17 +69,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, void nr_ulsch_unscrambling(int16_t* llr, uint32_t size, uint32_t Nid, uint32_t n_RNTI); -void nr_ulsch_layer_demapping(int16_t *llr_cw, - uint8_t Nl, - uint8_t mod_order, - uint32_t length, - int16_t **llr_layers); - -void nr_ulsch_procedures(PHY_VARS_gNB *gNB, - int frame_rx, - int slot_rx, - int UE_id, - uint8_t harq_pid); +void nr_ulsch_layer_demapping(int16_t *llr_cw, uint8_t Nl, uint8_t mod_order, uint32_t length, int16_t **llr_layers); NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index bcd73c58a9..0e48d807d8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -51,7 +51,12 @@ //#define gNB_DEBUG_TRACE #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 -//#define PRINT_CRC_CHECK +//#define DEBUG_CRC +#ifdef DEBUG_CRC +#define PRINT_CRC_CHECK(a) a +#else +#define PRINT_CRC_CHECK(a) +#endif //extern double cpuf; @@ -100,6 +105,7 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) ulsch.active = false; NR_UL_gNB_HARQ_t *harq = malloc16_clear(sizeof(*harq)); + init_abort(&harq->abort_decode); ulsch.harq_process = harq; harq->b = malloc16_clear(ulsch_bytes * sizeof(*harq->b)); harq->c = malloc16_clear(a_segments * sizeof(*harq->c)); @@ -113,170 +119,160 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) return(ulsch); } -#ifdef PRINT_CRC_CHECK - static uint32_t prnt_crc_cnt = 0; -#endif - - void nr_processULSegment(void *arg) - { - ldpcDecode_t *rdata = (ldpcDecode_t *)arg; - PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; - NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; - t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int length_dec; - int no_iteration_ldpc; - int Kr; - int Kr_bytes; - int K_bits_F; - uint8_t crc_type; - int i; - int j; - int r = rdata->segment_r; - int A = rdata->A; - int E = rdata->E; - int Qm = rdata->Qm; - int rv_index = rdata->rv_index; - int r_offset = rdata->r_offset; - uint8_t kc = rdata->Kc; - short *ulsch_llr = rdata->ulsch_llr; - int max_ldpc_iterations = p_decoderParms->numMaxIter; - int8_t llrProcBuf[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))); - - __m128i *pv = (__m128i *)&z; - __m128i *pl = (__m128i *)&l; - - Kr = ulsch_harq->K; - Kr_bytes = Kr >> 3; - K_bits_F = Kr - ulsch_harq->F; - - t_nrLDPC_time_stats procTime = {0}; - t_nrLDPC_time_stats *p_procTime = &procTime; - - // start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - - //////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////// 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); - - stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// - - // start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - - 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) { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - - LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); - rdata->decodeIterations = max_ldpc_iterations + 1; - return; - } else { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - } - - ulsch_harq->d_to_be_cleared[r] = false; - - memset(ulsch_harq->c[r], 0, Kr_bytes); - - if (ulsch_harq->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = ulsch_harq->B; - } else { - crc_type = CRC24_B; - length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; - } - - // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); - - // set first 2*Z_c bits to zeros - memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t)); - // set Filler bits - memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t)); - // Move coded bits before filler bits - memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t)); - // skip filler bits - memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t)); - // Saturate coded bits before decoding into 8 bits values - for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { - pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]); - } - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - p_decoderParms->block_length = length_dec; - no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], llrProcBuf, p_procTime); - - if (check_crc((uint8_t *)llrProcBuf, length_dec, ulsch_harq->F, crc_type)) { -#ifdef PRINT_CRC_CHECK - LOG_I(PHY,"Segment %d CRC OK, iterations %d/%d\n",r,no_iteration_ldpc,max_ldpc_iterations); -#endif - rdata->decodeIterations = no_iteration_ldpc; - if (rdata->decodeIterations > p_decoderParms->numMaxIter) rdata->decodeIterations--; - } else { -#ifdef PRINT_CRC_CHECK - LOG_I(PHY,"CRC NOK\n"); -#endif - rdata->decodeIterations = max_ldpc_iterations + 1; - } - - for (int m=0; m < Kr>>3; m ++) { - ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m]; - } - - //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); - } - -uint32_t 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) +static void nr_processULSegment(void *arg) { -#ifdef PRINT_CRC_CHECK - prnt_crc_cnt++; -#endif + ldpcDecode_t *rdata = (ldpcDecode_t *)arg; + PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; + NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; + int length_dec; + int Kr; + int Kr_bytes; + int K_bits_F; + uint8_t crc_type; + int i; + int j; + int r = rdata->segment_r; + int A = rdata->A; + int E = rdata->E; + int Qm = rdata->Qm; + int rv_index = rdata->rv_index; + int r_offset = rdata->r_offset; + uint8_t kc = rdata->Kc; + short *ulsch_llr = rdata->ulsch_llr; + int max_ldpc_iterations = p_decoderParms->numMaxIter; + int8_t llrProcBuf[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))); + + __m128i *pv = (__m128i *)&z; + __m128i *pl = (__m128i *)&l; + + Kr = ulsch_harq->K; + Kr_bytes = Kr >> 3; + K_bits_F = Kr - ulsch_harq->F; + + t_nrLDPC_time_stats procTime = {0}; + t_nrLDPC_time_stats *p_procTime = &procTime; + + // start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + + //////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// 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); + + stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// + + // start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + + 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) { + stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + + LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); + rdata->decodeIterations = max_ldpc_iterations + 1; + return; + } else { + stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + } + + ulsch_harq->d_to_be_cleared[r] = false; + + memset(ulsch_harq->c[r], 0, Kr_bytes); + + if (ulsch_harq->C == 1) { + if (A > 3824) + crc_type = CRC24_A; + else + crc_type = CRC16; + + length_dec = ulsch_harq->B; + } else { + crc_type = CRC24_B; + length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; + } + + // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); + + // set first 2*Z_c bits to zeros + memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t)); + // set Filler bits + memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t)); + // Move coded bits before filler bits + memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t)); + // skip filler bits + memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t)); + // Saturate coded bits before decoding into 8 bits values + for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { + pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]); + } + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// + p_decoderParms->block_length = length_dec; + rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], llrProcBuf, p_procTime, &ulsch_harq->abort_decode); + + if (rdata->decodeIterations == p_decoderParms->numMaxIter+1 ) { + // We have not decoded succesfully and we have not aborted + // We check the CRC, itf it is ok, let's assume the payload is correctly decoded + // (so the remaining errors are only in the redundancy (parity) bits) + if (check_crc((uint8_t *)llrProcBuf, length_dec, ulsch_harq->F, crc_type)) { + PRINT_CRC_CHECK(LOG_I(PHY,"Segment %d CRC OK, iterations %d/%d\n",r,rdata->decodeIterations,max_ldpc_iterations)); + rdata->decodeIterations = p_decoderParms->numMaxIter; + } else { + PRINT_CRC_CHECK(LOG_I(PHY,"CRC NOK\n")); + rdata->decodeIterations = max_ldpc_iterations + 1; + } + } + + if (rdata->decodeIterations <= p_decoderParms->numMaxIter) + memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); + //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); +} + +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) + { NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; @@ -284,14 +280,13 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (!harq_process) { LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n"); - return 1; + return -1; } uint8_t dtx_det = 0; int Kr; int Kr_bytes; - - phy_vars_gNB->nbDecode = 0; + harq_process->processedSegments = 0; // ------------------------------------------------------------------ @@ -303,7 +298,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (!ulsch_llr) { LOG_E(PHY,"ulsch_decoding.c: NULL ulsch_llr pointer\n"); - return 1; + return -1; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,1); @@ -383,7 +378,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); - return 1; + return -1; } #ifdef DEBUG_ULSCH_DECODING printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); @@ -425,7 +420,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, crc_type = CRC24_B; length_dec = (harq_process->B + 24 * harq_process->C) / harq_process->C; } - int no_iteration_ldpc = 2; + int decodeIterations = 2; for (int r = 0; r < harq_process->C; r++) { int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); memset(harq_process->c[r], 0, Kr_bytes); @@ -446,8 +441,8 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (ret < 0) { LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); - no_iteration_ldpc = ulsch->max_ldpc_iterations + 1; - return 1; + decodeIterations = ulsch->max_ldpc_iterations + 1; + return -1; } } else { int K_bits_F = Kr - harq_process->F; @@ -472,8 +467,8 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, Kr - harq_process->F - 2 * (decParams.Z)) == -1) { LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); - no_iteration_ldpc = ulsch->max_ldpc_iterations + 1; - return 1; + decodeIterations = ulsch->max_ldpc_iterations + 1; + return -1; } harq_process->d_to_be_cleared[r] = false; @@ -491,7 +486,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]); } - no_iteration_ldpc = nrLDPC_decoder(&decParams, (int8_t *)pl, llrProcBuf, p_procTime); + decodeIterations = nrLDPC_decoder(&decParams, (int8_t *)pl, llrProcBuf, p_procTime, &harq_process->abort_decode); } for (int m = 0; m < Kr >> 3; m++) { @@ -499,16 +494,12 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, } if (check_crc((uint8_t *)llrProcBuf, length_dec, harq_process->F, crc_type)) { -#ifdef PRINT_CRC_CHECK - LOG_I(PHY, "Segment %d CRC OK\n", r); -#endif - no_iteration_ldpc = 2; + PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); + decodeIterations = 2; } else { -#ifdef PRINT_CRC_CHECK - LOG_I(PHY, "segment %d CRC NOK\n", r); -#endif - no_iteration_ldpc = ulsch->max_ldpc_iterations + 1; - } + PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); + decodeIterations = ulsch->max_ldpc_iterations + 1; + } //} r_offset += E; @@ -521,9 +512,9 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, */ } else { dtx_det = 0; - no_iteration_ldpc = ulsch->max_ldpc_iterations + 1; + decodeIterations = ulsch->max_ldpc_iterations + 1; } - bool decodeSuccess = (no_iteration_ldpc <= ulsch->max_ldpc_iterations); + bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations); if (decodeSuccess) { memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); @@ -556,16 +547,16 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, harq_process->round, harq_process->TBS); ulsch->handled = 1; - no_iteration_ldpc = ulsch->max_ldpc_iterations + 1; + decodeIterations = ulsch->max_ldpc_iterations + 1; LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); } - ulsch->last_iteration_cnt = no_iteration_ldpc; + ulsch->last_iteration_cnt = decodeIterations; } else { dtx_det = 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); union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}}; @@ -591,12 +582,11 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, rdata->ulsch_id = ULSCH_id; rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; pushTpool(&phy_vars_gNB->threadPool, req); - phy_vars_gNB->nbDecode++; - LOG_D(PHY, "Added a block to decode, in pipe: %d\n", phy_vars_gNB->nbDecode); + 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)); ////////////////////////////////////////////////////////////////////////////////////////// } } - return 1; + return harq_process->C; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 1c049acbc6..5b3c726934 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -70,7 +70,15 @@ 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); } -bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p, int b_size, uint8_t b[b_size], int *num_seg_ok, UE_nr_rxtx_proc_t *proc) { +static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, + notifiedFIFO_elt_t *req, + notifiedFIFO_t *nf_p, + bool last, + int b_size, + uint8_t b[b_size], + int *num_seg_ok, + UE_nr_rxtx_proc_t *proc) +{ ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req); NR_DL_UE_HARQ_t *harq_process = rdata->harq_process; NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch; @@ -89,13 +97,7 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool (*num_seg_ok)++; } else { - if ( !last ) { - int nb=abortTpoolJob(&get_nrUE_params()->Tpool, req->key); - nb+=abortNotifiedFIFOJob(nf_p, req->key); - LOG_D(PHY,"downlink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); - LOG_D(PHY, "DLSCH %d in error\n",rdata->dlsch_id); - last = true; - } + LOG_D(PHY, "DLSCH %d in error\n", rdata->dlsch_id); } // if all segments are done @@ -153,18 +155,16 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool } } -void nr_processDLSegment(void* arg) { +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 length_dec; - int no_iteration_ldpc; int Kr; int K_bits_F; uint8_t crc_type; - int i; - int j; int r = rdata->segment_r; int A = rdata->A; int E = rdata->E; @@ -174,20 +174,17 @@ void nr_processDLSegment(void* arg) { uint8_t kc = rdata->Kc; uint32_t Tbslbrm = rdata->Tbslbrm; short* dlsch_llr = rdata->dlsch_llr; - rdata->decodeIterations = dlsch->max_ldpc_iterations + 1; - int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); - int16_t z [68*384 + 16] __attribute__ ((aligned(16))); + 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))); - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - Kr = harq_process->K; 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); @@ -226,7 +223,6 @@ void nr_processDLSegment(void* arg) { //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"); - rdata->decodeIterations = dlsch->max_ldpc_iterations + 1; return; } stop_meas(&rdata->ts_rate_unmatch); @@ -255,49 +251,45 @@ void nr_processDLSegment(void* arg) { { start_meas(&rdata->ts_ldpc_decode); //set first 2*Z_c bits to zeros - memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); + memset(z,0,2*harq_process->Z*sizeof(int16_t)); //set Filler bits - memset((&z[0]+K_bits_F),127,harq_process->F*sizeof(int16_t)); + memset((z+K_bits_F),127,harq_process->F*sizeof(int16_t)); //Move coded bits before filler bits - memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); + 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[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); + 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 - for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { + __m128i *pv = (__m128i*)&z; + __m128i *pl = (__m128i*)&l; + for (int i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); } //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); p_decoderParms->block_length=length_dec; - nrLDPC_initcall(p_decoderParms, (int8_t*)&pl[0], llrProcBuf); - no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, - (int8_t *)&pl[0], - llrProcBuf, - &procTime); + nrLDPC_initcall(p_decoderParms, (int8_t*)&pl[0], LDPCoutput); + rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], LDPCoutput, &procTime, &harq_process->abort_decode); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); - LOG_D(PHY,"no_iteration_ldpc = %d\n", no_iteration_ldpc); - // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int - if (check_crc((uint8_t *)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n",r); - if (no_iteration_ldpc > dlsch->max_ldpc_iterations) - no_iteration_ldpc = dlsch->max_ldpc_iterations; - } else { - LOG_D(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx); - no_iteration_ldpc = dlsch->max_ldpc_iterations + 1; - } - - if (r==0) { - for (int i=0; i<10; i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t *)llrProcBuf)[i]); - } - - rdata->decodeIterations = no_iteration_ldpc; - - for (int m=0; m < Kr>>3; m ++) { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } + LOG_W(PHY,"rdata->decodeIterations = %d\n", rdata->decodeIterations); + if (rdata->decodeIterations < dlsch->max_ldpc_iterations + 2) { + // We have not aborted the decoding + if (check_crc((uint8_t *)LDPCoutput, length_dec, harq_process->F, crc_type)) { + LOG_D(PHY, "Segment %u CRC OK\n", r); + if (rdata->decodeIterations > dlsch->max_ldpc_iterations) { + LOG_W(PHY, "force ok\n"); + rdata->decodeIterations = dlsch->max_ldpc_iterations; + } + } else { + LOG_D(PHY, "%d.%d CRC NOT OK, iter %d\n", rdata->proc->frame_rx, rdata->proc->nr_slot_rx, rdata->decodeIterations); + rdata->decodeIterations = dlsch->max_ldpc_iterations + 1; + } + } else + LOG_D(PHY, "%d.%d another segment failure aborted this decode\n", rdata->proc->frame_rx, rdata->proc->nr_slot_rx); + if (rdata->decodeIterations <= dlsch->max_ldpc_iterations) + memcpy(harq_process->c[r], LDPCoutput, Kr >> 3); stop_meas(&rdata->ts_ldpc_decode); } } @@ -346,9 +338,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, 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]; - - int nbDecode = 0; - + if (!dlsch_llr) { LOG_E(PHY,"dlsch_decoding.c: NULL dlsch_llr pointer\n"); return(dlsch->max_ldpc_iterations + 1); @@ -406,7 +396,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, harq_process->B = A+24; else harq_process->B = A+16; - + nr_segmentation(NULL, NULL, harq_process->B, @@ -415,7 +405,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, &harq_process->Z, // [hna] Z is Zc &harq_process->F, p_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, B %d\n",harq_process->C,harq_process->B); return(-1); @@ -423,6 +413,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, 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)); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); @@ -450,15 +443,15 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" Kr_bytes = Kr>>3; offset = 0; - void (*nr_processDLSegment_ptr)(void*) = &nr_processDLSegment; notifiedFIFO_t nf; initNotifiedFIFO(&nf); + set_abort(&harq_process->abort_decode, false); for (r=0; rC; r++) { //printf("start rx segment %d\n",r); 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); union ldpcReqUnion id = {.s={dlsch->rnti,frame,nr_slot_rx,0,0}}; - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, nr_processDLSegment_ptr); + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, &nr_processDLSegment); ldpcDecode_ue_t * rdata=(ldpcDecode_ue_t *) NotifiedFifoData(req); rdata->phy_vars_ue = phy_vars_ue; @@ -484,24 +477,20 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, reset_meas(&rdata->ts_rate_unmatch); reset_meas(&rdata->ts_ldpc_decode); pushTpool(&get_nrUE_params()->Tpool,req); - nbDecode++; - LOG_D(PHY,"Added a block to decode, in pipe: %d\n",nbDecode); + 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; - for (r=0; rC; + while (nbDecode) { notifiedFIFO_elt_t *req=pullTpool(&nf, &get_nrUE_params()->Tpool); if (req == NULL) break; // Tpool has been stopped - bool last = false; - if (r == nbDecode - 1) - last = true; - bool stop = nr_ue_postDecode(phy_vars_ue, req, last, &nf, b_size, b, &num_seg_ok, proc); + nr_ue_postDecode(phy_vars_ue, req, &nf, nbDecode == 1, b_size, b, &num_seg_ok, proc); delNotifiedFIFO_elt(req); - if (stop) - break; + nbDecode--; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_OUT); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 811fa7711b..2d41e3d600 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -143,6 +143,7 @@ typedef struct { /// Last index of LLR buffer that contains information. /// Used for computing LDPC decoder R int llrLen; + decode_abort_t abort_decode; } NR_DL_UE_HARQ_t; typedef struct { diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index 6336c7e5ef..dfadfa2c58 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -960,7 +960,36 @@ extern int sync_var; #define MBSFN_FDD_SF6 0x10 #define MBSFN_FDD_SF7 0x08 #define MBSFN_FDD_SF8 0x04 +typedef struct { + pthread_mutex_t mutex_failure; + bool failed; +} decode_abort_t; +static inline void init_abort(decode_abort_t *ab) +{ + int ret = pthread_mutex_init(&ab->mutex_failure, NULL); + AssertFatal(ret == 0, "mutex failed with %d\n", ret); + ab->failed = false; +} + +static inline bool check_abort(decode_abort_t *ab) +{ + int ret = pthread_mutex_lock(&ab->mutex_failure); + AssertFatal(ret == 0, "mutex failed with %d\n", ret); + bool failed = ab->failed; + ret = pthread_mutex_unlock(&ab->mutex_failure); + AssertFatal(ret == 0, "mutex failed with %d\n", ret); + return failed; +} + +static inline void set_abort(decode_abort_t *ab, bool v) +{ + int ret = pthread_mutex_lock(&ab->mutex_failure); + AssertFatal(ret == 0, "mutex failed with %d\n", ret); + ab->failed = v; + ret = pthread_mutex_unlock(&ab->mutex_failure); + AssertFatal(ret == 0, "mutex failed with %d\n", ret); +} typedef uint8_t(decoder_if_t)(int16_t *y, int16_t *y2, @@ -976,7 +1005,8 @@ typedef uint8_t(decoder_if_t)(int16_t *y, time_stats_t *gamma_stats, time_stats_t *ext_stats, time_stats_t *intl1_stats, - time_stats_t *intl2_stats); + time_stats_t *intl2_stats, + decode_abort_t *abort_decode); typedef uint8_t(encoder_if_t)(uint8_t *input, uint16_t input_length_bytes, diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index c82db65718..4066550d76 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -221,6 +221,7 @@ typedef struct { uint32_t E; /// Number of segments processed so far uint32_t processedSegments; + decode_abort_t abort_decode; /// Last index of LLR buffer that contains information. /// Used for computing LDPC decoder R int llrLen; @@ -774,7 +775,6 @@ typedef struct PHY_VARS_gNB_s { pthread_t L1_tx_thread; int L1_tx_thread_core; struct processingData_L1tx *msgDataTx; - int nbDecode; void *scopeData; /// structure for analyzing high-level RT measurements rt_L1_profiling_t rt_L1_profiling; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index efeba1d546..a789142b0b 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1228,7 +1228,8 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) { } -void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) +{ turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; @@ -1244,19 +1245,7 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { if (decodeSucess) { int Fbytes=(rdata->segment_r==0) ? rdata->Fbits>>3 : 0; int sz=(rdata->Kr>>3) - Fbytes - ((ulsch_harq->C>1)?3:0); - memcpy(ulsch_harq->decodedBytes+rdata->offset, - rdata->decoded_bytes+Fbytes, - sz); - } else { - if ( rdata->nbSegments != ulsch_harq->processedSegments ) { - int nb=abortTpoolJob(proc->threadPool, req->key); - nb+=abortNotifiedFIFOJob(proc->respDecode, req->key); - proc->nbDecode-=nb; - LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); - AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", - ulsch_harq->processedSegments, nb, rdata->nbSegments); - ulsch_harq->processedSegments=rdata->nbSegments; - } + memcpy(ulsch_harq->decodedBytes + rdata->offset, rdata->decoded_bytes + Fbytes, sz); } // if this UE segments are all done @@ -1276,8 +1265,8 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { } } } - - if (!decodeSucess) { + + if (check_abort(&ulsch_harq->abort_decode)) { T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(rdata->frame), T_INT(rdata->subframe), T_INT(ulsch->rnti), T_INT(rdata->harq_pid)); fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,1); // indicate NAK to MAC @@ -1302,28 +1291,28 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { * locally in PHY. */ ulsch_harq->handled = 1; - } // ulsch in error - else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ - fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,0); // indicate ACK to MAC - fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC - ulsch_harq->status = SCH_IDLE; - ulsch->harq_mask &= ~(1 << rdata->harq_pid); - for (int j=0;julsch_stats[j].rnti == ulsch->rnti) { - eNB->ulsch_stats[j].total_bytes_rx+=ulsch_harq->TBS; - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { - eNB->ulsch_stats[j].ulsch_power[aa] = dB_fixed_x10(eNB->pusch_vars[rdata->UEid]->ulsch_power[aa]); - eNB->ulsch_stats[j].ulsch_noise_power[aa] = dB_fixed_x10(eNB->pusch_vars[rdata->UEid]->ulsch_noise_power[aa]); - } - break; - } + } // ulsch in error + else if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { + fill_crc_indication(eNB, i, rdata->frame, rdata->subframe, 0); // indicate ACK to MAC + fill_rx_indication(eNB, i, rdata->frame, rdata->subframe); // indicate SDU to MAC + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + for (int j = 0; j < NUMBER_OF_ULSCH_MAX; j++) + if (eNB->ulsch_stats[j].rnti == ulsch->rnti) { + eNB->ulsch_stats[j].total_bytes_rx += ulsch_harq->TBS; + for (int aa = 0; aa < eNB->frame_parms.nb_antennas_rx; aa++) { + eNB->ulsch_stats[j].ulsch_power[aa] = dB_fixed_x10(eNB->pusch_vars[rdata->UEid]->ulsch_power[aa]); + eNB->ulsch_stats[j].ulsch_noise_power[aa] = dB_fixed_x10(eNB->pusch_vars[rdata->UEid]->ulsch_noise_power[aa]); + } + break; + } T (T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(rdata->frame), T_INT(rdata->subframe), T_INT(ulsch->rnti), T_INT(rdata->harq_pid)); - } // ulsch not in error - + } // ulsch not in error + if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling); - } + } } void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 0e8e2cfd56..df26ebf81e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -232,7 +232,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0); } -void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) +static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; @@ -241,32 +241,22 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) 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\n", - rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments); - gNB->nbDecode--; - LOG_D(PHY,"remain to decoded in subframe: %d\n", gNB->nbDecode); + LOG_D(PHY, + "processing result of segment: %d, processed %d/%d\n", + rdata->segment_r, + ulsch_harq->processedSegments, + rdata->nbSegments); 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)); + memcpy(ulsch_harq->b + rdata->offset, ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0)); } else { - if ( rdata->nbSegments != ulsch_harq->processedSegments ) { - int nb = abortTpoolJob(&gNB->threadPool, req->key); - nb += abortNotifiedFIFOJob(&gNB->respDecode, req->key); - gNB->nbDecode-=nb; - LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); - LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id); - AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", - ulsch_harq->processedSegments, nb, rdata->nbSegments); - ulsch_harq->processedSegments=rdata->nbSegments; - } + LOG_D(PHY, "ULSCH %d in error\n", rdata->ulsch_id); } //int dumpsig=0; // if all segments are done if (rdata->nbSegments == ulsch_harq->processedSegments) { - if (decodeSuccess && !gNB->pusch_vars[rdata->ulsch_id].DTX) { + if (!check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) { LOG_D(PHY, "[gNB %d] ULSCH: 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", @@ -306,6 +296,7 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0); // dumpsig=1; } + 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; @@ -348,13 +339,12 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) } } -void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid) +static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid) { 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; - uint8_t enable_ldpc_offload = gNB->ldpc_offload_flag; uint16_t start_symbol = pusch_pdu->start_symbol_index; uint16_t number_symbols = pusch_pdu->nr_of_symbols; @@ -407,17 +397,10 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH //---------------------------------------------------------- start_meas(&gNB->ulsch_decoding_stats); - nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G); - if (enable_ldpc_offload == 0) { - while (gNB->nbDecode > 0) { - notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); - if (req == NULL) - break; // Tpool has been stopped - nr_postDecode(gNB, req); - delNotifiedFIFO_elt(req); - } - } + int nbDecode = + nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G); stop_meas(&gNB->ulsch_decoding_stats); + return nbDecode; } @@ -848,6 +831,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } } + int totalDecode = 0; 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; @@ -944,11 +928,20 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) // 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); - nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + totalDecode += nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } - + if (totalDecode > 0 && gNB->ldpc_offload_flag == 0) { + while (totalDecode > 0) { + notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); + if (req == NULL) + break; // Tpool has been stopped + nr_postDecode(gNB, req); + delNotifiedFIFO_elt(req); + totalDecode--; + } + } for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; if (srs) { diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 5609f7d608..cb18f8f53b 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -127,11 +127,16 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_DL_UE_HARQ_t *dl_harq0 = NULL; if ((pdu_type != FAPI_NR_RX_PDU_TYPE_SSB) && dlsch0) { + int t=WS_C_RNTI; + if (pdu_type == FAPI_NR_RX_PDU_TYPE_RAR) + t=WS_RA_RNTI; + if (pdu_type == FAPI_NR_RX_PDU_TYPE_SIB) + t=WS_SI_RNTI; dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; trace_NRpdu(DIRECTION_DOWNLINK, b, dlsch0->dlsch_config.TBS / 8, - WS_C_RNTI, + t, dlsch0->rnti, proc->frame_rx, proc->nr_slot_rx, diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index 47ab3c7a91..ee3ecd221d 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -2995,6 +2995,8 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, void copy_harq_proc_struct(LTE_DL_UE_HARQ_t *harq_processes_dest, LTE_DL_UE_HARQ_t *current_harq_processes) { + init_abort(&harq_processes_dest->abort_decode); + set_abort(&harq_processes_dest->abort_decode, check_abort(¤t_harq_processes->abort_decode)); harq_processes_dest->B = current_harq_processes->B ; harq_processes_dest->C = current_harq_processes->C ; harq_processes_dest->Cminus = current_harq_processes->Cminus ; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 69dcbe728a..4b25863e85 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -91,42 +91,24 @@ void deref_sched_response(int _) exit(1); } -int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { +int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req, int *nb_ok) +{ ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; - NR_gNB_ULSCH_t *ulsch = rdata->ulsch; int r = rdata->segment_r; bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter); ulsch_harq->processedSegments++; - gNB->nbDecode--; 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 { - if ( rdata->nbSegments != ulsch_harq->processedSegments ) { - int nb=abortTpoolJob(&gNB->threadPool, req->key); - nb+=abortNotifiedFIFOJob(&gNB->respDecode, req->key); - gNB->nbDecode-=nb; - AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", - ulsch_harq->processedSegments, nb, rdata->nbSegments); - ulsch_harq->processedSegments=rdata->nbSegments; - return 1; - } } - // if all segments are done - if (rdata->nbSegments == ulsch_harq->processedSegments) { - if (decodeSuccess) { - return 0; - } else { - return 1; - } - - } - ulsch->last_iteration_cnt = rdata->decodeIterations; + // if all segments are done + if (rdata->nbSegments == ulsch_harq->processedSegments) + return *nb_ok == rdata->nbSegments; return 0; } @@ -612,13 +594,15 @@ int main(int argc, char **argv) rel15_ul->qam_mod_order, rel15_ul->nrOfLayers); - nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, - frame, subframe, harq_pid, G); - while (gNB->nbDecode > 0) { - notifiedFIFO_elt_t *req=pullTpool(&gNB->respDecode, &gNB->threadPool); - ret = nr_postDecode_sim(gNB, req); - delNotifiedFIFO_elt(req); - } + int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G); + int nb_ok = 0; + if (nbDecode > 0) + while (nbDecode > 0) { + notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); + ret = nr_postDecode_sim(gNB, req, &nb_ok); + delNotifiedFIFO_elt(req); + nbDecode--; + } if (ret) n_errors++; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 835ba9ef99..10953c9050 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -680,7 +680,7 @@ int main(int argc, char **argv) c16_t **rxdata; rxdata = malloc(n_rx * sizeof(*rxdata)); for (int i = 0; i < n_rx; ++i) - rxdata[i] = malloc(gNB->frame_parms.samples_per_frame * sizeof(**rxdata)); + rxdata[i] = calloc(gNB->frame_parms.samples_per_frame * sizeof(**rxdata),1); NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; @@ -705,8 +705,7 @@ int main(int argc, char **argv) } // Configure UE - UE = malloc(sizeof(PHY_VARS_NR_UE)); - memset((void*)UE,0,sizeof(PHY_VARS_NR_UE)); + UE = calloc(sizeof(PHY_VARS_NR_UE), 1); PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE**)); PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE*)); PHY_vars_UE_g[0][0] = UE; @@ -756,21 +755,11 @@ int main(int argc, char **argv) nr_phy_data_tx_t phy_data = {0}; - unsigned char *estimated_output_bit; - unsigned char *test_input_bit; uint32_t errors_decoding = 0; - - test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - - nr_scheduled_response_t scheduled_response; - fapi_nr_ul_config_request_t ul_config; - fapi_nr_tx_request_t tx_req; - - memset(&scheduled_response, 0, sizeof(scheduled_response)); - memset(&ul_config, 0, sizeof(ul_config)); - memset(&tx_req, 0, sizeof(tx_req)); + nr_scheduled_response_t scheduled_response={0}; + fapi_nr_ul_config_request_t ul_config={0}; + fapi_nr_tx_request_t tx_req={0}; uint8_t ptrs_mcs1 = 2; uint8_t ptrs_mcs2 = 4; @@ -851,7 +840,7 @@ int main(int argc, char **argv) ulsch_input_buffer[0] = 0x31; for (i = 1; i < TBS/8; i++) { - ulsch_input_buffer[i] = (unsigned char) rand(); + ulsch_input_buffer[i] = (unsigned char) uniformrandom(); } uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table); @@ -1524,10 +1513,10 @@ int main(int argc, char **argv) } for (i = 0; i < TBS; i++) { - estimated_output_bit[i] = (ulsch_gNB->harq_process->b[i / 8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (UE->ul_harq_processes[harq_pid].b[i / 8] & (1 << (i & 7))) >> (i & 7); + uint8_t estimated_output_bit = (ulsch_gNB->harq_process->b[i / 8] & (1 << (i & 7))) >> (i & 7); + uint8_t test_input_bit = (UE->ul_harq_processes[harq_pid].b[i / 8] & (1 << (i & 7))) >> (i & 7); - if (estimated_output_bit[i] != test_input_bit[i]) { + if (estimated_output_bit != test_input_bit) { /*if(errors_decoding == 0) printf("\x1B[34m""[frame %d][trial %d]\t1st bit in error in decoding = %d\n" "\x1B[0m", frame, trial, i);*/ errors_decoding++; @@ -1662,8 +1651,6 @@ int main(int argc, char **argv) num_dmrs_cdm_grps_no_data); free_MIB_NR(mib); - free(test_input_bit); - free(estimated_output_bit); if (gNB->ldpc_offload_flag) free_nrLDPClib_offload();