Commit 3645c96c authored by Laurent THOMAS's avatar Laurent THOMAS Committed by laurent

remove generic thread pool abort

parent f8f9f8ac
......@@ -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);
......
......@@ -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
......
......@@ -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.
......
......@@ -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);
}
......@@ -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);
}
......@@ -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<n_segments;j++) {
start_meas(time_decoder);
n_iter = nrLDPC_decoder(&decParams[j], (int8_t*)channel_output_fixed[j], (int8_t*)estimated_output[j], &decoder_profiler);
set_abort(&dec_abort, false);
n_iter = nrLDPC_decoder(&decParams[j],
(int8_t *)channel_output_fixed[j],
(int8_t *)estimated_output[j],
&decoder_profiler,
&dec_abort);
stop_meas(time_decoder);
//count errors
if ( memcmp(estimated_output[j], test_input[j], block_length/8 ) != 0 ) {
......
......@@ -58,21 +58,22 @@ decoder_if_t *decoder8;
encoder_if_t *encoder;
extern int _may_i_use_cpu_feature(unsigned __int64);
uint8_t nodecod(int16_t *y,
int16_t *y2,
uint8_t *decoded_bytes,
uint8_t *decoded_bytes2,
uint16_t n,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats)
uint8_t nodecod(int16_t *y,
int16_t *y2,
uint8_t *decoded_bytes,
uint8_t *decoded_bytes2,
uint16_t n,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats,
decode_abort_t *ab)
{
return max_iterations+1;
};
......
......@@ -33,6 +33,7 @@
#include "nrLDPC_mPass.h"
#include "nrLDPC_cnProc.h"
#include "nrLDPC_bnProc.h"
#include "openair1/PHY/CODING/coding_defs.h"
#define UNROLL_CN_PROC 1
#define UNROLL_BN_PROC 1
#define UNROLL_BN_PROC_PC 1
......@@ -118,11 +119,20 @@
#include "nrLDPC_tools/nrLDPC_debug.h"
#endif
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);
int check_crc(uint8_t* decoded_bytes, uint32_t n, uint32_t F, uint8_t crc_type);
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);
void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) {
}
int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, t_nrLDPC_time_stats* p_profiler)
int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams,
int8_t* p_llr,
int8_t* p_out,
t_nrLDPC_time_stats* p_profiler,
decode_abort_t* ab)
{
uint32_t numLLR;
uint32_t numIter = 0;
......@@ -133,8 +143,9 @@ int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_
numLLR = nrLDPC_init(p_decParams, p_lut);
// Launch LDPC decoder core for one segment
numIter = nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler);
numIter = nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler, ab);
if (numIter > 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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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; r<a_segments; r++) {
harq_list[j][i].c[r] = malloc16(1056);
harq_list[j][i].d[r] = malloc16(sz);
if (harq_list[j][i].c[r])
memset(harq_list[j][i].c[r],0,1056);
else
AssertFatal(true, "Unable to reset harq memory \"c\"\n");
if (harq_list[j][i].d[r])
memset(harq_list[j][i].d[r], 0, sz);
else
AssertFatal(true, "Unable to reset harq memory \"d\"\n");
harq_list[j][i].c[r] = malloc16_clear(1056);
harq_list[j][i].d[r] = malloc16_clear(sz);
}
harq_list[j][i].status = 0;
harq_list[j][i].DLround = 0;
......
......@@ -327,6 +327,7 @@ typedef struct {
uint32_t repetition_number ;
// PUSCH Total number of repetitions
uint32_t total_number_of_repetitions;
decode_abort_t abort_decode;
} LTE_UL_eNB_HARQ_t;
typedef struct {
......
......@@ -538,20 +538,6 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB,
uint8_t Nbundled,
uint8_t 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
*/
int ulsch_decoding_data(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
int UE_id,
int harq_pid,
int llr8_flag);
void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,
int16_t amp);
......
......@@ -113,6 +113,7 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin
if (ulsch->harq_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; r<ulsch_harq->C; r++) {
// printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
// Get Turbo interleaver parameters
......
......@@ -106,9 +106,10 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_
for (i=0; i<Mdlharq; i++) {
// printf("new_ue_dlsch: Harq process %d\n",i);
dlsch->harq_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; r<harq_process->C; r++) {
// Get Turbo interleaver parameters
if (r<harq_process->Cminus)
......@@ -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);
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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 {
......
......@@ -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,
......
......@@ -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;
......
......@@ -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;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;
}
} // 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) {
......
......@@ -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) {
......
......@@ -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,
......
......@@ -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(&current_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 ;
......
......@@ -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++;
......
......@@ -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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment