diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 5ae15c8a29..34cd950ce7 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -29,6 +29,7 @@ static int DEFENBS[] = {0}; #include #include #include +#include extern uint16_t sf_ahead; @@ -691,6 +692,13 @@ static void *ru_thread( void *param ) { L1_rxtx_proc_t L1proc; L1_rxtx_proc_t *proc=&L1proc; + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) { + initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); + initNotifiedFIFO(&L1proc.respEncode); + initNotifiedFIFO(&L1proc.respDecode); + } else + initTpool("n", &L1proc.threadPool, true); + if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index a8032b3368..fafc009e51 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -314,17 +314,17 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t proc->frame_tx,proc->subframe_tx, dlsch0->rnti,dlsch0->harq_mask, rel8->rnti, rel8->rnti_type, rel8->harq_process, rel8->new_data_indicator_1, - dlsch0_harq->round, dlsch0->harq_mask, dlsch0_harq->ndi); + dlsch0_harq->DLround, dlsch0->harq_mask, dlsch0_harq->ndi); if (dlsch0->rnti != rel8->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry - dlsch0_harq->round=0; + dlsch0_harq->DLround=0; dlsch0->harq_mask=0; } if ((dlsch0->harq_mask & (1 << rel8->harq_process)) > 0) { if (rel8->new_data_indicator_1 != dlsch0_harq->ndi) - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } else { // process is inactive, so activate and set round to 0 - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } dlsch0_harq->ndi = rel8->new_data_indicator_1; @@ -335,12 +335,12 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0->active = 1; #endif if (rel8->rnti_type == 2) - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; LOG_D(PHY,"NFAPI: rel8[rnti %x dci_format %d harq_process %d ndi1 %d rnti type %d] dlsch0[rnti %x harq_mask %x] dlsch0_harq[round %d ndi %d]\n", rel8->rnti,rel8->dci_format,rel8->harq_process, rel8->new_data_indicator_1, rel8->rnti_type, dlsch0->rnti,dlsch0->harq_mask, - dlsch0_harq->round,dlsch0_harq->ndi + dlsch0_harq->DLround,dlsch0_harq->ndi ); switch (rel8->dci_format) { @@ -503,7 +503,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t NPRB = dlsch0_harq->nb_rb; I_mcs = get_I_TBS(rel8->mcs_1); } - AssertFatal(NPRB>0,"DCI 1A: NPRB = 0 (rnti %x, rnti type %d, tpc %d, round %d, resource_block_coding %d, harq process %d)\n",rel8->rnti,rel8->rnti_type,rel8->tpc,dlsch0_harq->round,rel8->resource_block_coding,rel8->harq_process); + AssertFatal(NPRB>0,"DCI 1A: NPRB = 0 (rnti %x, rnti type %d, tpc %d, round %d, resource_block_coding %d, harq process %d)\n",rel8->rnti,rel8->rnti_type,rel8->tpc,dlsch0_harq->DLround,rel8->resource_block_coding,rel8->harq_process); dlsch0_harq->rvidx = rel8->redundancy_version_1; dlsch0_harq->Nl = 1; dlsch0_harq->mimo_mode = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI; @@ -523,12 +523,12 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0->rnti = rel8->rnti; //dlsch0->harq_ids[subframe] = rel8->harq_process; - if (dlsch0_harq->round == 0) + if (dlsch0_harq->DLround == 0) dlsch0_harq->status = ACTIVE; dlsch0->harq_mask |= (1 << rel8->harq_process); - if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->round,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding,rel8->redundancy_version_1,rel8->rnti,rel8->harq_process); + if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->DLround,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding,rel8->redundancy_version_1,rel8->rnti,rel8->harq_process); break; case NFAPI_DL_DCI_FORMAT_1: @@ -690,7 +690,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t - if (dlsch0_harq->round == 0) { + if (dlsch0_harq->DLround == 0) { dlsch0_harq->status = ACTIVE; // printf("Setting DLSCH process %d to ACTIVE\n",rel8->harq_process); @@ -1042,16 +1042,16 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t // reset HARQ process if this is the first transmission #ifdef PHY_TX_THREAD - if ((dlsch0->active[subframe]==1) && (dlsch0_harq->round == 0)) + if ((dlsch0->active[subframe]==1) && (dlsch0_harq->DLround == 0)) #else - if ((dlsch0->active==1) && (dlsch0_harq->round == 0)) + if ((dlsch0->active==1) && (dlsch0_harq->DLround == 0)) #endif dlsch0_harq->status = ACTIVE; #ifdef PHY_TX_THREAD - if ((dlsch1->active[subframe]==1) && (dlsch1_harq->round == 0)) + if ((dlsch1->active[subframe]==1) && (dlsch1_harq->DLround == 0)) #else - if ((dlsch1->active==1) && (dlsch1_harq->round == 0)) + if ((dlsch1->active==1) && (dlsch1_harq->DLround == 0)) #endif dlsch1_harq->status = ACTIVE; @@ -1479,7 +1479,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t printf ("dlsch0 eNB: NBRB %d\n", dlsch0_harq->nb_rb); printf ("dlsch0 eNB: rballoc %x\n", dlsch0_harq->rb_alloc[0]); printf ("dlsch0 eNB: harq_pid %d\n", harq_pid); - printf ("dlsch0 eNB: round %d\n", dlsch0_harq->round); + printf ("dlsch0 eNB: round %d\n", dlsch0_harq->DLround); printf ("dlsch0 eNB: rvidx %d\n", dlsch0_harq->rvidx); printf ("dlsch0 eNB: TBS %d (NPRB %d)\n", dlsch0_harq->TBS, NPRB); printf ("dlsch0 eNB: mcs %d\n", dlsch0_harq->mcs); @@ -1493,7 +1493,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t printf ("dlsch1 eNB: NBRB %d\n", dlsch1_harq->nb_rb); printf ("dlsch1 eNB: rballoc %x\n", dlsch1_harq->rb_alloc[0]); printf ("dlsch1 eNB: harq_pid %d\n", harq_pid); - printf ("dlsch1 eNB: round %d\n", dlsch1_harq->round); + printf ("dlsch1 eNB: round %d\n", dlsch1_harq->DLround); printf ("dlsch1 eNB: rvidx %d\n", dlsch1_harq->rvidx); printf ("dlsch1 eNB: TBS %d (NPRB %d)\n", dlsch1_harq->TBS, NPRB); printf ("dlsch1 eNB: mcs %d\n", dlsch1_harq->mcs); @@ -1748,19 +1748,19 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0->subframe_tx[subframe] = 1; if (dlsch0->rnti != rel13->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; dlsch0->harq_mask =0; printf("*********************** rnti %x => %x, pos %d\n",rel13->rnti,dlsch0->rnti,UE_id); } if ((dlsch0->harq_mask & (1 << rel13->harq_process)) > 0) { if ((rel13->new_data_indicator != dlsch0_harq->ndi)||(dci_alloc->ra_flag==1)) - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } else { // process is inactive, so activate and set round to 0 - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } dlsch0_harq->ndi = rel13->new_data_indicator; - if (dlsch0_harq->round == 0) { + if (dlsch0_harq->DLround == 0) { dlsch0_harq->status = ACTIVE; dlsch0_harq->mcs = rel13->mcs; if (dci_alloc->ra_flag == 0) // get TBS from table using mcs and nb_rb @@ -1782,7 +1782,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0->harq_ids[dlsch0_harq->frame%2][dlsch0_harq->subframe] = rel13->harq_process; dlsch0_harq->pdsch_start = rel13->start_symbol; - LOG_D(PHY,"Setting DLSCH harq %d round %d to active for %d.%d\n",rel13->harq_process,dlsch0_harq->round,dlsch0_harq->frame,dlsch0_harq->subframe); + LOG_D(PHY,"Setting DLSCH harq %d round %d to active for %d.%d\n",rel13->harq_process,dlsch0_harq->DLround,dlsch0_harq->frame,dlsch0_harq->subframe); dlsch0->rnti = rel13->rnti; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index b494f7bd6c..ea6bf29ac7 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -20,15 +20,15 @@ */ /*! \file PHY/LTE_TRANSPORT/dlsch_coding.c -* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 -* \author R. Knopp -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr -* \note -* \warning -*/ + * \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 + * \author R. Knopp + * \date 2011 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" @@ -42,21 +42,22 @@ #include "common/utils/LOG/log.h" #include #include "targets/RT/USER/rt_wrapper.h" +#include //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 /* -#define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ + #define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ ((pilots==1)&&(first_pilot==1)&&(((re>2)&&(re<6))||((re>8)&&(re<12)))) || \ ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \ */ #define is_not_pilot(pilots,first_pilot,re) (1) /*extern void thread_top_init(char *thread_name, - int affinity, - uint64_t runtime, - uint64_t deadline, - uint64_t period);*/ + int affinity, + uint64_t runtime, + uint64_t deadline, + uint64_t period);*/ extern WORKER_CONF_t get_thread_worker_conf(void); @@ -82,11 +83,6 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); dlsch->harq_processes[i]->c[r] = NULL; } - - if (dlsch->harq_processes[i]->d[r]) { - free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - dlsch->harq_processes[i]->d[r] = NULL; - } } free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t)); @@ -100,26 +96,26 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS *frame_parms) { LTE_eNB_DLSCH_t *dlsch; - unsigned char exit_flag = 0,i,j,r,aa,layer; + unsigned char exit_flag = 0,i,r,aa,layer; int re; unsigned char bw_scaling =1; switch (N_RB_DL) { - case 6: - bw_scaling =16; - break; + case 6: + bw_scaling =16; + break; - case 25: - bw_scaling =4; - break; + case 25: + bw_scaling =4; + break; - case 50: - bw_scaling =2; - break; + case 50: + bw_scaling =2; + break; - default: - bw_scaling =1; - break; + default: + bw_scaling =1; + break; } dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t)); @@ -145,11 +141,11 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ // NOTE: THIS HAS TO BE REVISED FOR RU, commenting to remove memory leak !!!!! /* - dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - for (aa=0; aanb_antennas_tx; aa++) { - dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); + dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); + for (aa=0; aanb_antennas_tx; aa++) { + dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - }*/ + }*/ for (i=0; i<20; i++) dlsch->harq_ids[i/10][i%10] = Mdlharq; @@ -175,7 +171,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ for (r=0; rharq_processes[i]->c[r] = (uint8_t *)malloc16(((r==0)?8:0) + 3+ 768); - dlsch->harq_processes[i]->d[r] = (uint8_t *)malloc16((96+12+3+(3*6144))); if (dlsch->harq_processes[i]->c[r]) { bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768); @@ -183,13 +178,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ printf("Can't get c\n"); exit_flag=2; } - - if (dlsch->harq_processes[i]->d[r]) { - bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - } else { - printf("Can't get d\n"); - exit_flag=2; - } } } } else { @@ -200,14 +188,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ if (exit_flag==0) { for (i=0; iharq_processes[i]->round=0; - - for (j=0; j<96; j++) - for (r=0; rharq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]); - if (dlsch->harq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; - } + dlsch->harq_processes[i]->DLround=0; } return(dlsch); @@ -222,7 +203,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { unsigned char Mdlharq; - unsigned char i,j,r; + unsigned char i; if (dlsch) { Mdlharq = dlsch->Mdlharq; @@ -244,92 +225,17 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { if (dlsch->harq_processes[i]) { // dlsch->harq_processes[i]->Ndi = 0; dlsch->harq_processes[i]->status = 0; - dlsch->harq_processes[i]->round = 0; + dlsch->harq_processes[i]->DLround = 0; - for (j=0; j<96; j++) - for (r=0; rharq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; } } } } - - - -int dlsch_encoding_2threads0(te_params *tep) { - LTE_eNB_DLSCH_t *dlsch = tep->dlsch; - unsigned int G = tep->G; - unsigned char harq_pid = tep->harq_pid; - unsigned int total_worker = tep->total_worker; - unsigned int current_worker = tep->current_worker; - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_IN); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - for (r=(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*current_worker; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0,r_offset=0; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if(r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker)) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT); - return(0); -} - - extern int oai_exit; int dlsch_encoding_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -342,45 +248,72 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, time_stats_t *te_wakeup_stats0, time_stats_t *te_wakeup_stats1, time_stats_t *i_stats) { - int encoding_return = 0; - unsigned int L,C,B; uint8_t harq_pid = dlsch->harq_ids[frame%2][subframe]; if(harq_pid >= dlsch->Mdlharq) { LOG_E(PHY,"dlsch_encoding_all illegal harq_pid %d\n", harq_pid); return(-1); } - B = dlsch->harq_processes[harq_pid]->B; + + LOG_D(PHY,"B %d, harq_pid %d\n", + dlsch->harq_processes[harq_pid]->B, + dlsch->harq_ids[frame%2][subframe]); - LOG_D(PHY,"B %d, harq_pid %d\n",B,dlsch->harq_ids[frame%2][subframe]); + return dlsch_encoding(eNB, + proc, + a, + num_pdcch_symbols, + dlsch, + frame, + subframe, + rm_stats, + te_stats, + i_stats); - if(B<=6144) { - L=0; - C=1; - } else { - L=24; - C = B/(6144-L); - - if((6144-L)*C < B) { - C = C+1; - } - } - - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); - - return encoding_return; } +static void TPencode(void * arg) { + turboEncode_t * rdata=(turboEncode_t *) arg; + unsigned char harq_pid = rdata->harq_pid; + LTE_DL_eNB_HARQ_t *hadlsch=rdata->dlsch->harq_processes[harq_pid]; + + if ( rdata-> round == 0) { + uint8_t tmp[96+12+3+3*6144]; + memset(tmp,LTE_NULL, TURBO_SIMD_SOFTBITS); + start_meas(rdata->te_stats); + encoder(rdata->input, + rdata->Kr_bytes, + tmp+96,//&dlsch->harq_processes[harq_pid]->d[r][96], + rdata->filler); + stop_meas(rdata->te_stats); + start_meas(rdata->i_stats); + hadlsch->RTC[rdata->r] = + sub_block_interleaving_turbo(4+(rdata->Kr_bytes*8), + tmp+96, + hadlsch->w[rdata->r]); + stop_meas(rdata->i_stats); + } + + // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the + // outputs for each code segment, see Section 5.1.5 p.20 + start_meas(rdata->rm_stats); + lte_rate_matching_turbo(hadlsch->RTC[rdata->r], + rdata->G, //G + hadlsch->w[rdata->r], + hadlsch->e+rdata->r_offset, + hadlsch->C, // C + rdata->dlsch->Nsoft, // Nsoft, + rdata->dlsch->Mdlharq, + rdata->dlsch->Kmimo, + hadlsch->rvidx, + hadlsch->Qm, + hadlsch->Nl, + rdata->r, + hadlsch->nb_rb); + stop_meas(rdata->rm_stats); +} int dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -389,8 +322,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, time_stats_t *rm_stats, time_stats_t *te_stats, time_stats_t *i_stats) { - unsigned int G; - unsigned int crc=1; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { @@ -398,136 +329,88 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, return(-1); } - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; + LTE_DL_eNB_HARQ_t *hadlsch=dlsch->harq_processes[harq_pid]; uint8_t beamforming_mode=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - // printf("Encoder: A: %d\n",A); - mod_order = dlsch->harq_processes[harq_pid]->Qm; - if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7) + if(hadlsch->mimo_mode == TM7) beamforming_mode = 7; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8) + else if(hadlsch->mimo_mode == TM8) beamforming_mode = 8; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10) + else if(hadlsch->mimo_mode == TM9_10) beamforming_mode = 9; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode); + unsigned int G = get_G(frame_parms,hadlsch->nb_rb, + hadlsch->rb_alloc, + hadlsch->Qm, // mod order + hadlsch->Nl, + num_pdcch_symbols, + frame,subframe,beamforming_mode); - // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING - printf("encoding thinks this is a new packet for harq_pid %d (%p), A %u \n",harq_pid,dlsch,A); -#endif - /* - int i; - printf("dlsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); - printf("\n"); - */ + proc->nbEncode=0; + + // if (hadlsch->Ndi == 1) { // this is a new packet + if (hadlsch->DLround == 0) { // this is a new packet // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, + unsigned int A=hadlsch->TBS; //6228; + unsigned int crc = crc24a(a, A)>>8; a[A>>3] = ((uint8_t *)&crc)[2]; a[1+(A>>3)] = ((uint8_t *)&crc)[1]; a[2+(A>>3)] = ((uint8_t *)&crc)[0]; // printf("CRC %x (A %d)\n",crc,A); - dlsch->harq_processes[harq_pid]->B = A+24; - // dlsch->harq_processes[harq_pid]->b = a; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) + hadlsch->B = A+24; + // hadlsch->b = a; + memcpy(hadlsch->b,a,(A/8)+4); + + if (lte_segmentation(hadlsch->b, + hadlsch->c, + hadlsch->B, + &hadlsch->C, + &hadlsch->Cplus, + &hadlsch->Cminus, + &hadlsch->Kplus, + &hadlsch->Kminus, + &hadlsch->F)<0) return(-1); - - for (r=0; rharq_processes[harq_pid]->C; r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; -#ifdef DEBUG_DLSCH_CODING - printf("Generating Code Segment %u (%u bits)\n",r,Kr); - // generate codewords - printf("bits_per_codeword (Kr)= %u, A %u\n",Kr,A); - printf("N_RB = %d\n",nb_rb); - printf("Ncp %d\n",frame_parms->Ncp); - printf("mod_order %d\n",mod_order); -#endif - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==0) - LOG_M("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); - -#endif - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); + } + + for (int r=0, r_offset=0; rC; r++) { + + union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &proc->respEncode, TPencode); + turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + rdata->input=hadlsch->c[r]; + rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; + rdata->filler=(r==0) ? hadlsch->F : 0; + rdata->r=r; + rdata->harq_pid=harq_pid; + rdata->dlsch=dlsch; + rdata->rm_stats=rm_stats; + rdata->te_stats=te_stats; + rdata->i_stats=i_stats; + rdata->round=hadlsch->DLround; + rdata->r_offset=r_offset; + rdata->G=G; + + if ( proc->threadPool.activated) { + pushTpool(&proc->threadPool,req); + proc->nbEncode++; + } else { + TPencode(rdata); } + + int Qm=hadlsch->Qm; + int C=hadlsch->C; + int Nl=hadlsch->Nl; + int Gp = G/Nl/Qm; + int GpmodC = Gp%C; + if (r < (C-(GpmodC))) + r_offset += Nl*Qm * (Gp/C); + else + r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); } - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0; rharq_processes[harq_pid]->C; r++) { -#ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); -#endif - start_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==dlsch->harq_processes[harq_pid]->C-1) - LOG_M("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4); - -#endif - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 6fab3dc59b..965ac66eef 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -102,6 +102,7 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a) AssertFatal(dlsch_encoding(eNB, + proc, a, 1, eNB->dlsch_MCH, diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 5feb1389be..9e78eb75a0 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -71,7 +71,7 @@ typedef struct { /// Subframe where current HARQ round was sent uint32_t subframe; /// Index of current HARQ round for this DLSCH - uint8_t round; + uint8_t DLround; /// Modulation order uint8_t Qm; /// MCS @@ -103,7 +103,7 @@ typedef struct { /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Turbo-code outputs (36-212 V8.6 2009-03, p.12 - uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; + //uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) uint8_t w[MAX_NUM_DLSCH_SEGMENTS][3*6144]; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) @@ -272,6 +272,7 @@ typedef struct { /// Pointer to the payload uint8_t *b; /// Pointers to transport block segments + //TBD uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; @@ -288,7 +289,10 @@ typedef struct { /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) + //TBD int16_t *d[MAX_NUM_ULSCH_SEGMENTS]; + uint32_t processedSegments; + uint32_t processedBadSegment; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) uint32_t C; /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10) diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index a795ca79a0..a358df3ff3 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -73,6 +73,7 @@ void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch); LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag); int dlsch_encoding_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -112,6 +113,7 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, @returns status */ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, uint8_t *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 1f8afe2609..64b83c524a 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -313,6 +313,14 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) r_offset += E; start_meas(&eNB->ulsch_deinterleaving_stats); + #if 0 + start_meas(&eNB->ulsch_deinterleaving_stats); + req=createRequest(DECODE,sizeof(turboDecode_t)); + req->startUELoop=eNB->proc.threadPool.startProcessingUE; + union turboReqUnion id= {.s={eNB->ulsch[UE_id]->rnti,frame,subframe,r,0}}; + req->id= id.p; + turboDecode_t * rdata=(turboDecode_t *) req->data; + #endif sub_block_deinterleaving_turbo(4+Kr, &ulsch_harq->d[r][96], ulsch_harq->w[r]); @@ -322,6 +330,58 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) crc_type = CRC24_A; else crc_type = CRC24_B; + #if 0 + rdata->frame=frame; + rdata->subframe=subframe; + rdata->UEid=UE_id; + rdata->harq_pid=harq_pid; + rdata->Kr=Kr; + rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations; + rdata->ulsch_harq=ulsch_harq; + rdata->eNB=eNB; + rdata->nbSegments=ulsch_harq->C; + rdata->segment_r=r; + rdata->Fbits=(r==0) ? ulsch_harq->F : 0; + rdata->offset=offset; + rdata->function=td; + int Fbytes=rdata->Fbits>>3; + int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0); + if ( eNB->proc.threadPool.activated) { + add_request(req, &eNB->proc.threadPool); + req=NULL; + } else { + req->startProcessingTime=rdtsc(); + rdata->decodeIterations = td( rdata->soft_bits+96, + rdata->decoded_bytes, + rdata->Kr, + f1f2mat_old[rdata->iind*2], + f1f2mat_old[(rdata->iind*2)+1], + rdata->maxIterations, + rdata->nbSegments == 1 ? CRC24_A: CRC24_B, + rdata->Fbits, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + + stop_meas(&eNB->ulsch_turbo_decoding_stats); + req->returnTime=req->endProcessingTime=rdtsc(); + req->decodeIterations=rdata->decodeIterations; + req->coreId=0; + req->processedBy[0]=0; + req->next=eNB->proc.threadPool.doneRequests; + eNB->proc.threadPool.doneRequests=req; + + if (rdata->decodeIterations > eNB->ulsch[UE_id]->max_turbo_iterations ) + // Entire TPU need retransmission + break; + } +offset += blockSize; + eNB->proc.threadPool.startProcessingUE=rdtsc(); + #endif start_meas(&eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch_harq->d[r][96], NULL, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index da213c3919..0b9fd57d19 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1332,8 +1332,6 @@ void rx_ulsch_emul(PHY_VARS_eNB *eNB, eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); sprintf(fname,"/tmp/ulsch_r%d_d",round); sprintf(vname,"/tmp/ulsch_r%d_dseq",round); - LOG_UM(fname,vname,&eNB->ulsch[UE_id]->harq_processes[harq_pid]->d[0][96], - eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0); if (eNB->common_vars.rxdata) { sprintf(fname,"/tmp/rxsig0_r%d.m",round); sprintf(vname,"rxs0_r%d",round); diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 1ae3515cd8..718ede5715 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -857,6 +857,54 @@ typedef struct PHY_VARS_eNB_s { uint8_t *FS6bufferZone; } PHY_VARS_eNB; +struct turboReqId { + uint16_t rnti; + uint16_t frame; + uint8_t subframe; + uint8_t codeblock; + uint16_t spare; +} __attribute__((packed)); + +union turboReqUnion { + struct turboReqId s; + uint64_t p; +}; + +typedef struct TurboDecode_s { + decoder_if_t *function; + int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32))); + uint8_t decoded_bytes[3+768] __attribute__((aligned(32))); + int UEid; + int harq_pid; + int frame; + int subframe; + int iind; + int Fbits; + int Kr; + LTE_UL_eNB_HARQ_t *ulsch_harq; + PHY_VARS_eNB *eNB; + int nbSegments; + int segment_r; + int offset; + int maxIterations; + int decodeIterations; +} turboDecode_t; + +#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144 +typedef struct turboEncode_s { + uint8_t * input; + int Kr_bytes; + int filler; + unsigned int G; + int r; + int harq_pid; + int round; + int r_offset; + LTE_eNB_DLSCH_t *dlsch; + time_stats_t *rm_stats; + time_stats_t *te_stats; + time_stats_t *i_stats; +} turboEncode_t; #endif /* __PHY_DEFS_ENB__H__ */ diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index b52a2eb22c..1a088563f0 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -220,13 +220,13 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro dlsch0_harq->pdsch_start = eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols; - if (dlsch0_harq->round==0) { //get pointer to SDU if this a new SDU + if (dlsch0_harq->DLround==0) { //get pointer to SDU if this a new SDU if(sdu == NULL) { LOG_E(PHY, "NFAPI: SFN/SF:%04d%d proc:TX:[frame %d subframe %d]: programming dlsch for round 0, rnti %x, UE_id %d, harq_pid %d : sdu is null for pdu_index %d dlsch0_harq[round:%d SFN/SF:%d%d pdu:%p mcs:%d ndi:%d pdschstart:%d]\n", frame,subframe, proc->frame_tx,proc->subframe_tx,rel8->rnti,UE_id,harq_pid, - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index,dlsch0_harq->round,dlsch0_harq->frame,dlsch0_harq->subframe,dlsch0_harq->pdu,dlsch0_harq->mcs,dlsch0_harq->ndi,dlsch0_harq->pdsch_start); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index,dlsch0_harq->DLround,dlsch0_harq->frame,dlsch0_harq->subframe,dlsch0_harq->pdu,dlsch0_harq->mcs,dlsch0_harq->ndi,dlsch0_harq->pdsch_start); return; } @@ -241,7 +241,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro else dlsch1_harq->pdu = sdu; } else { if (rel8->rnti != 0xFFFF) LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:[frame %d, subframe %d]: programming dlsch for round %d, rnti %x, UE_id %d, harq_pid %d\n", - frame,subframe,proc->frame_tx,proc->subframe_tx,dlsch0_harq->round, + frame,subframe,proc->frame_tx,proc->subframe_tx,dlsch0_harq->DLround, rel8->rnti,UE_id,harq_pid); } @@ -321,7 +321,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro dlsch0_harq->Nl = 1; dlsch0_harq->mimo_mode = (eNB->frame_parms.nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI; dlsch0_harq->dl_power_off = 1; - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; dlsch0_harq->status = ACTIVE; dlsch0_harq->TBS = rel8->length<<3; dlsch0_harq->Qm = rel8->modulation; @@ -346,13 +346,13 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro #else dlsch0->i0, #endif - dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->round, dlsch0_harq->status, + dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->DLround, dlsch0_harq->status, dlsch0_harq->TBS, dlsch0_harq->Qm, dlsch0_harq->codeword, dlsch0_harq->rb_alloc[0], rel8->length ); #else LOG_D(PHY,"dlsch0_harq[pdsch_start:%d nb_rb:%d vrb_type:%d rvidx:%d Nl:%d mimo_mode:%d dl_power_off:%d round:%d status:%d TBS:%d Qm:%d codeword:%d rb_alloc:%d] rel8[length:%d]\n", - dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->round, dlsch0_harq->status, + dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->DLround, dlsch0_harq->status, dlsch0_harq->TBS, dlsch0_harq->Qm, dlsch0_harq->codeword, dlsch0_harq->rb_alloc[0], rel8->length ); @@ -385,7 +385,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro #endif dlsch0_harq->pdsch_start = eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols; - if (dlsch0_harq->round==0) { //get pointer to SDU if this a new SDU + if (dlsch0_harq->DLround==0) { //get pointer to SDU if this a new SDU AssertFatal(sdu!=NULL,"NFAPI: frame %d, subframe %d: programming dlsch for round 0, rnti %x, UE_id %d, harq_pid %d : sdu is null for pdu_index %d\n", proc->frame_tx,proc->subframe_tx,rel8->rnti,UE_id,harq_pid, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index); @@ -397,7 +397,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro else dlsch1_harq->pdu = sdu; } else { if (rel8->rnti != 0xFFFF) LOG_D(PHY,"NFAPI: frame %d, subframe %d: programming dlsch for round %d, rnti %x, UE_id %d, harq_pid %d\n", - proc->frame_tx,proc->subframe_tx,dlsch0_harq->round, + proc->frame_tx,proc->subframe_tx,dlsch0_harq->DLround, rel8->rnti,UE_id,harq_pid); } } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index e5c767361d..94689ed246 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -260,16 +260,16 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, dlsch_harq->TBS, pmi2hex_2Ar1(dlsch_harq->pmi_alloc), dlsch_harq->rvidx, - dlsch_harq->round); + dlsch_harq->DLround); } if (ue_stats) ue_stats->dlsch_sliding_cnt++; - if (dlsch_harq->round == 0) { + if (dlsch_harq->DLround == 0) { if (ue_stats) ue_stats->dlsch_trials[harq_pid][0]++; } else { - ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++; + ue_stats->dlsch_trials[harq_pid][dlsch_harq->DLround]++; #ifdef DEBUG_PHY_PROC #ifdef DEBUG_DLSCH LOG_D (PHY, "[eNB] This DLSCH is a retransmission\n"); @@ -280,18 +280,19 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, if (dlsch->rnti!=0xffff) LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n", dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0], - dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round); + dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->DLround); // 36-212 if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF if (dlsch_harq->pdu==NULL) { LOG_E(PHY,"dlsch_harq->pdu == NULL SFN/SF:%04d%d dlsch[rnti:%x] dlsch_harq[pdu:%p pdsch_start:%d Qm:%d Nl:%d round:%d nb_rb:%d rb_alloc[0]:%d]\n", frame,subframe,dlsch->rnti, dlsch_harq->pdu, - dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]); + dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->DLround,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]); return false; } start_meas(&eNB->dlsch_encoding_stats); dlsch_encoding_all(eNB, + proc, dlsch_harq->pdu, dlsch_harq->pdsch_start, dlsch, @@ -306,6 +307,14 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, &eNB->dlsch_interleaving_stats); stop_meas(&eNB->dlsch_encoding_stats); + if ( proc->threadPool.activated ) { + // Wait all other threads finish to process + while (proc->nbEncode) { + pullTpool(&proc->respEncode, &proc->threadPool); + proc->nbEncode--; + } + } + if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) { print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr); } @@ -314,8 +323,8 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, #else dlsch->active = 0; #endif - dlsch_harq->round++; - LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->round); + dlsch_harq->DLround++; + LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->DLround); return true; } return false; @@ -359,7 +368,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL); stop_meas(&eNB->dlsch_modulation_stats); - LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round); + LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->DLround); } @@ -1146,7 +1155,7 @@ uci_procedures(PHY_VARS_eNB *eNB, if (eNB->first_sr[uci->ue_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 eNB->first_sr[uci->ue_id] = 0; - eNB->dlsch[uci->ue_id][0]->harq_processes[0]->round = 0; + eNB->dlsch[uci->ue_id][0]->harq_processes[0]->DLround = 0; eNB->dlsch[uci->ue_id][0]->harq_processes[0]->status = SCH_IDLE; LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d First SR\n", eNB->Mod_id, eNB->ulsch[uci->ue_id]->rnti, frame, subframe); } @@ -1156,6 +1165,87 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { } +#if 0 +void post_decode(request_t* decodeResult) { + turboDecode_t * rdata=(turboDecode_t *) decodeResult->data; + LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; + LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + PHY_VARS_eNB *eNB=rdata->eNB; + bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations; + ulsch_harq->processedSegments++; + if (decodeSucess) { + int Fbytes=rdata->Fbits>>3; + int Kr=rdata->segment_r < ulsch_harq->Cminus? + ulsch_harq->Kminus: + ulsch_harq->Kplus; + int Kr_bytes = Kr>>3; + int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0); + memcpy(ulsch_harq->b+rdata->offset, + rdata->decoded_bytes+Fbytes, + blockSize); + + } else { + if (rdata->nbSegments > 1 ) { + // Purge pending decoding of the same TDU + union turboReqUnion idInFailure= {.p=decodeResult->id}; + rnti_t rntiInFailure=idInFailure.s.rnti; + tpool_t * tp=&proc->threadPool; + mutexlock(tp->lockRequests); + request_t* pending=NULL; + while ( (pending=searchRNTI(tp, rntiInFailure)) != NULL) { + LOG_W(MAC,"removing a CB belonging to a bad TPU"); + freeRequest(pending); + mutexlock(tp->lockReportDone); + tp->notFinishedJobs--; + mutexunlock(tp->lockReportDone); + } + mutexunlock(tp->lockRequests); + } + } + + // Check if TDU is complete: either we have all blocks in success + // either at least one block can't be decoded + // Maybe we receive decoded block alter a first failure, + // so we protect ourselves against multiple executions + if ( (rdata->nbSegments == ulsch_harq->processedSegments || decodeSucess==false) && + ulsch_harq->processedBadSegment == 0 ) { + //compute the expected ULSCH RX power (for the stats) + ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,rdata->UEid,rdata->harq_pid, 0); // 0 means bw_factor is not considered + + if (ulsch_harq->cqi_crc_status == 1) + fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe, + ulsch_harq, + ulsch->rnti); + + fill_crc_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe,decodeSucess?0:1); // indicate result to MAC + fill_rx_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe); // indicate SDU to MAC + + if (!decodeSucess) { + ulsch_harq->processedBadSegment =1; + if (ulsch_harq->round >= 3) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + ulsch_harq->round = 0; + } + + /* Mark the HARQ process to release it later if max transmission reached + * (see below). + * MAC does not send the max transmission count, we have to deal with it + * locally in PHY. + */ + ulsch_harq->handled = 1; + } else { + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + } // 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); + } +} +#endif + void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { uint32_t ret=0,i; uint32_t harq_pid; @@ -1354,6 +1444,49 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; ithreadPool.activated ) { + // Wait all other threads finish to process + //printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc->threadPool.notFinishedJobs); + int rr=0; + mutexlock(proc->threadPool.lockReportDone); + while ( proc->threadPool.notFinishedJobs > 0 ) { + //printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc->threadPool.notFinishedJobs); + struct timespec t; + clock_gettime(CLOCK_REALTIME,&t); + t.tv_nsec+=1*1000*1000; + if ( t.tv_nsec >= 1000*1000*1000 ) { + t.tv_nsec -= 1000*1000*1000; + t.tv_sec++; + } + if ((rr=pthread_cond_timedwait(&proc->threadPool.notifDone,&proc.threadPool.lockReportDone, &t))!=0) { + LOG_E(PHY,"timedwait1:%s,%p,%p,%p,%d\n", rr==ETIMEDOUT?"ETIMEDOUT":"other", + proc->threadPool.oldestRequests, + proc->threadPool.newestRequests, + proc->threadPool.doneRequests, + proc->threadPool.notFinishedJobs); + proc->threadPool.oldestRequests=NULL; + proc->threadPool.newestRequests=NULL; + proc->threadPool.doneRequests=NULL; + proc->threadPool.notFinishedJobs=0; + } + } + mutexunlock(proc->threadPool.lockReportDone); + } + + request_t* tmp; + while ((tmp=proc->threadPool.doneRequests)!=NULL) { + turboDecode_t * rdata=(turboDecode_t *) tmp->data; + tmp->decodeIterations=rdata->decodeIterations; + post_decode(tmp); + tmp->returnTime=rdtsc(); + tmp->cumulSubframe=tmp->returnTime-startTime; + // Ignore write error (if no trace listner) + if (write(proc->threadPool.traceFd, tmp, sizeof(request_t)- 2*sizeof(void*))) {}; + proc->threadPool.doneRequests=tmp->next; + freeRequest(tmp); + } + #endif } extern int oai_exit; @@ -1515,7 +1648,7 @@ static void do_release_harq(PHY_VARS_eNB *eNB, #endif - if (dlsch0_harq->round >= after_rounds) { + if (dlsch0_harq->DLround >= after_rounds) { dlsch0_harq->status = SCH_IDLE; dlsch0->harq_mask &= ~(1 << harq_pid); } @@ -1564,7 +1697,7 @@ static void do_release_harq(PHY_VARS_eNB *eNB, T_INT(harq_pid)); } #endif - if (dlsch0_harq->round >= after_rounds) { + if (dlsch0_harq->DLround >= after_rounds) { dlsch0_harq->status = SCH_IDLE; if ((dlsch1_harq == NULL) || ((dlsch1_harq != NULL) && (dlsch1_harq->status == SCH_IDLE))) { diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index 0e8daf064f..790a5c98e6 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -39,6 +39,7 @@ #include "nfapi_interface.h" #include "platform_constants.h" #include "platform_types.h" +#include #define MAX_NUM_DL_PDU 100 #define MAX_NUM_UL_PDU 100 @@ -179,6 +180,11 @@ typedef struct { pthread_cond_t cond_RUs; /// mutex for RXn-TXnp4 processing thread pthread_mutex_t mutex_RUs; + tpool_t threadPool; + int nbEncode; + int nbDecode; + notifiedFIFO_t respEncode; + notifiedFIFO_t respDecode; } L1_rxtx_proc_t; typedef struct IF_Module_s{ diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 33d4dc3b09..3a02868f56 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -175,6 +175,7 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define RF_CONFIG_FILE softmodem_params.rf_config_file +#define TP_CONFIG softmodem_params.threadPoolConfig #define PHY_TEST softmodem_params.phy_test #define WAIT_FOR_SYNC softmodem_params.wait_for_sync #define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag @@ -187,6 +188,7 @@ #define USIM_TEST softmodem_params.usim_test #define CMDLINE_PARAMS_DESC { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)}, \ + {"turbo-thread-pool", NULL, 0, strptr:(char **)&TP_CONFIG, defstrval:NULL, TYPE_STRING, sizeof(TP_CONFIG)}, \ {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ @@ -253,6 +255,7 @@ typedef struct { uint64_t optmask; THREAD_STRUCT thread_struct; char rf_config_file[1024]; + char threadPoolConfig[1024]; int phy_test; uint8_t usim_test; int emulate_rf;