diff --git a/executables/nr-ru.c b/executables/nr-ru.c index ef1d253c64..f801f7b325 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1213,6 +1213,10 @@ static void *ru_stats_thread(void *param) { sleep(1); if (opp_enabled == 1) { + if (ru->feptx_prec) { + print_meas(&ru->total_precoding_stats,"feptx_prec",NULL,NULL); + } + if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); @@ -1273,7 +1277,7 @@ static void *ru_thread_tx( void *param ) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); + //if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); @@ -1488,7 +1492,7 @@ static void *ru_thread( void *param ) { if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); + //if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); @@ -1704,6 +1708,7 @@ void init_RU_proc(RU_t *ru) { if (ru->feprx) init_fep_thread(ru); if (ru->feptx_ofdm) nr_init_feptx_thread(ru); + //if (ru->feptx_prec) nr_init_feptx_prec_thread(ru); } if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW); @@ -2018,7 +2023,7 @@ void set_function_spec_param(RU_t *ru) { ru->do_prach = 0; // no prach processing in RU ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? ru_fep_full_2thread : fep_full; // RX DFTs ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding - ru->feptx_prec = nr_feptx_prec; // this is fep with idft and precoding + ru->feptx_prec = nr_feptx_prec; // this is fep with idft and precoding ru->fh_north_in = NULL; // no incoming fronthaul from north ru->fh_north_out = NULL; // no outgoing fronthaul to north ru->nr_start_if = NULL; // no if interface diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 3a4206ec3f..f6550fff97 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -74,6 +74,10 @@ int nr_phy_init_RU(RU_t *ru) { } + // allocate precoding input buffers (TX) + ru->common.txdataF = (int32_t **)malloc16(15*sizeof(int32_t*)); + for(i=0; i< 15; ++i) ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); // [hna] samples_per_frame without CP + // allocate IFFT input buffers (TX) ru->common.txdataF_BF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*)); LOG_I(PHY,"[INIT] common.txdata_BF= %p (%lu bytes)\n",ru->common.txdataF_BF, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index aa75bd6555..074e30a5f9 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -205,7 +205,6 @@ for (int i=0; i>4; i++) { printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_symbols %d)\n", start_sc, rel15->start_symbol, rel15->n_prb, rel15->nb_symbols); #endif - for (int ap=0; apnb_layers; ap++) { // DMRS params for this ap diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 6eeec696ec..13552ae2fb 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -103,6 +103,10 @@ typedef struct { /// - first index: tx antenna [0..nb_antennas_tx[ /// - second index: sample [0..] int32_t **txdataF_BF; + /// \brief holds the transmit data before beamforming in the frequency domain. + /// - first index: tx antenna [0..nb_antennas_tx[ + /// - second index: sample [0..] + int32_t **txdataF; /// \brief holds the transmit data before beamforming for epdcch/mpdcch /// - first index : tx antenna [0..nb_epdcch_antenna_ports[ /// - second index: sampl [0..] @@ -146,6 +150,41 @@ typedef struct { } RU_CALIBRATION; +typedef struct RU_prec_t_s{ + /// \internal This variable is protected by \ref mutex_feptx_prec + int instance_cnt_feptx_prec; + /// pthread struct for RU TX FEP PREC worker thread + pthread_t pthread_feptx_prec; + /// pthread attributes for worker feptx prec thread + pthread_attr_t attr_feptx_prec; + /// condition varible for RU TX FEP PREC thread + pthread_cond_t cond_feptx_prec; + /// mutex for fep PREC TX worker thread + pthread_mutex_t mutex_feptx_prec; + int symbol; + int p;//logical + int aa;//physical MAX nb_tx + struct RU_t_s *ru; + int index; +} RU_prec_t; + +typedef struct RU_feptx_t_s{ + /// \internal This variable is protected by \ref mutex_feptx_prec + int instance_cnt_feptx; + /// pthread struct for RU TX FEP PREC worker thread + pthread_t pthread_feptx; + /// pthread attributes for worker feptx prec thread + pthread_attr_t attr_feptx; + /// condition varible for RU TX FEP PREC thread + pthread_cond_t cond_feptx; + /// mutex for fep PREC TX worker thread + pthread_mutex_t mutex_feptx; + struct RU_t_s *ru; + int aa;//physical MAX nb_tx + int half_slot;//first or second half of a slot + int slot;//current slot +}RU_feptx_t; + typedef struct RU_proc_t_s { /// Pointer to associated RU descriptor struct RU_t_s *ru; @@ -205,8 +244,6 @@ typedef struct RU_proc_t_s { int instance_cnt_asynch_rxtx; /// \internal This variable is protected by \ref mutex_fep int instance_cnt_fep; - /// \internal This variable is protected by \ref mutex_feptx - int instance_cnt_feptx; /// \internal This variable is protected by \ref mutex_ru_thread int instance_cnt_ru; /// This varible is protected by \ref mutex_emulatedRF @@ -226,8 +263,6 @@ typedef struct RU_proc_t_s { pthread_t pthread_synch; /// pthread struct for RU RX FEP worker thread pthread_t pthread_fep; - /// pthread struct for RU TX FEP worker thread - pthread_t pthread_feptx; /// pthread struct for emulated RF pthread_t pthread_emulateRF; /// pthread structure for asychronous RX/TX processing thread @@ -253,8 +288,6 @@ typedef struct RU_proc_t_s { pthread_attr_t attr_asynch_rxtx; /// pthread attributes for worker fep thread pthread_attr_t attr_fep; - /// pthread attributes for worker feptx thread - pthread_attr_t attr_feptx; /// pthread attributes for emulated RF pthread_attr_t attr_emulateRF; /// scheduling parameters for RU FH thread @@ -285,8 +318,6 @@ typedef struct RU_proc_t_s { pthread_cond_t cond_asynch_rxtx; /// condition varible for RU RX FEP thread pthread_cond_t cond_fep; - /// condition varible for RU TX FEP thread - pthread_cond_t cond_feptx; /// condition varible for emulated RF pthread_cond_t cond_emulateRF; /// condition variable for eNB signal @@ -314,8 +345,6 @@ typedef struct RU_proc_t_s { pthread_mutex_t mutex_asynch_rxtx; /// mutex for fep RX worker thread pthread_mutex_t mutex_fep; - /// mutex for fep TX worker thread - pthread_mutex_t mutex_feptx; /// mutex for ru_thread pthread_mutex_t mutex_ru; /// mutex for emulated RF thread @@ -360,8 +389,11 @@ typedef struct RU_proc_t_s { int ru_rx_ready; int ru_tx_ready; int emulate_rf_busy; -} RU_proc_t; + RU_prec_t prec[16]; + /// structure for feptx thread + RU_feptx_t feptx[16]; +} RU_proc_t; typedef enum { LOCAL_RF =0, @@ -518,6 +550,8 @@ typedef struct RU_t_s{ void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string, struct RU_t_s *ru); void (*gNB_top)(struct PHY_VARS_gNB_s *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru); + /// Timing statistics (TX) + time_stats_t total_precoding_stats; /// Timing statistics time_stats_t ofdm_demod_stats; /// Timing statistics (TX) diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 9113238cd8..01e217b183 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -56,70 +56,85 @@ extern openair0_config_t openair0_cfg[MAX_CARDS]; extern int oai_exit; -void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols) { +void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - unsigned int aa,slot_offset,slot_offsetF; + unsigned int slot_offset,slot_offsetF; int slot = tti_tx; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 ); slot_offset = slot*fp->samples_per_slot; slot_offsetF = first_symbol*fp->ofdm_symbol_size; + if (first_symbol>0) slot_offset += (fp->ofdm_symbol_size*first_symbol) + (fp->nb_prefix_samples0) + (fp->nb_prefix_samples*(first_symbol-1)); LOG_D(PHY,"SFN/SF:RU:TX:%d/%d Generating slot %d (first_symbol %d num_symbols %d)\n",ru->proc.frame_tx, ru->proc.tti_tx,slot,first_symbol,num_symbols); - for (aa=0; aanb_tx; aa++) { - if (fp->Ncp == 1) { + if (fp->Ncp == 1) { + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], + (int*)&ru->common.txdata[aa][slot_offset], + fp->ofdm_symbol_size, + num_symbols, + fp->nb_prefix_samples, + CYCLIC_PREFIX); + } + else { + if (first_symbol==0) { PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], - (int*)&ru->common.txdata[aa][slot_offset], - fp->ofdm_symbol_size, - num_symbols, - fp->nb_prefix_samples, - CYCLIC_PREFIX); + (int*)&ru->common.txdata[aa][slot_offset], + fp->ofdm_symbol_size, + 1, + fp->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size], + (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size], + fp->ofdm_symbol_size, + num_symbols-1, + fp->nb_prefix_samples, + CYCLIC_PREFIX); } else { - if (first_symbol==0) { - PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], - (int*)&ru->common.txdata[aa][slot_offset], - fp->ofdm_symbol_size, - 1, - fp->nb_prefix_samples0, - CYCLIC_PREFIX); - PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size], - (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size], - fp->ofdm_symbol_size, - num_symbols-1, - fp->nb_prefix_samples, - CYCLIC_PREFIX); - } - else { - PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], - (int*)&ru->common.txdata[aa][slot_offset], - fp->ofdm_symbol_size, - num_symbols, - fp->nb_prefix_samples, - CYCLIC_PREFIX); - } + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], + (int*)&ru->common.txdata[aa][slot_offset], + fp->ofdm_symbol_size, + num_symbols, + fp->nb_prefix_samples, + CYCLIC_PREFIX); } } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0); } void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) { - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config; - RU_proc_t *proc = &ru->proc; - struct timespec wait; - int slot = tti_tx; + RU_proc_t *proc = &ru->proc; + RU_feptx_t *feptx = proc->feptx; - wait.tv_sec=0; - wait.tv_nsec=5000000L; + PHY_VARS_gNB *gNB; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + + int slot = tti_tx; + int i = 0; + int ret = 0; + + + start_meas(&ru->total_precoding_stats); + if (ru->num_gNB == 1){ + gNB = ru->gNB_list[0]; + cfg = &gNB->gNB_config; + if (nr_slot_select(cfg,tti_tx) == SF_UL) return; + + for(i=0; iLmax; ++i) + memcpy((void*)ru->common.txdataF[i], + (void*)gNB->common_vars.txdataF[i], + fp->samples_per_slot_wCP*sizeof(int32_t)); + }//num_gNB == 1 + stop_meas(&ru->total_precoding_stats); start_meas(&ru->ofdm_mod_stats); @@ -129,37 +144,25 @@ void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) { if (nr_slot_select(cfg,slot)==SF_DL) { // If this is not an S-tti - if (pthread_mutex_timedlock(&proc->mutex_feptx,&wait) != 0) { - printf("[RU] ERROR pthread_mutex_lock for feptx thread (IC %d)\n", proc->instance_cnt_feptx); - exit_fun( "error locking mutex_feptx" ); - return; - } - - if (proc->instance_cnt_feptx==0) { - printf("[RU] FEPtx thread busy\n"); - exit_fun("FEPtx thread busy"); - pthread_mutex_unlock( &proc->mutex_feptx ); - return; - } - - ++proc->instance_cnt_feptx; - // slot to pass to worker thread - proc->slot_feptx = slot; - pthread_mutex_unlock( &proc->mutex_feptx ); - - - if (pthread_cond_signal(&proc->cond_feptx) != 0) { - printf("[RU] ERROR pthread_cond_signal for feptx thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return; + for(i=0; inb_tx*2; ++i){ + AssertFatal((ret=pthread_mutex_lock(&feptx[i].mutex_feptx))==0,"mutex_lock return %d\n",ret); + feptx[i].half_slot = i%2; + feptx[i].aa = i>>1; + feptx[i].ru = ru; + feptx[i].slot = slot; + feptx[i].instance_cnt_feptx = 0; + AssertFatal(pthread_cond_signal(&feptx[i].cond_feptx) == 0,"ERROR pthread_cond_signal for gNB_L1_thread\n"); + AssertFatal((ret=pthread_mutex_unlock(&feptx[i].mutex_feptx))==0,"mutex_lock returns %d\n",ret); } } // call first half-slot in this thread - nr_feptx0(ru,slot,0,fp->symbols_per_slot>>1); - wait_on_busy_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"NR feptx thread"); - + i = 0; + while(1){ + if(feptx[i].instance_cnt_feptx == -1) ++i; + if(i == 16) break; + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 ); //write_output @@ -170,41 +173,64 @@ void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) { static void *nr_feptx_thread(void *param) { - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; + RU_feptx_t *feptx = (RU_feptx_t *)param; + RU_t *ru; + int aa, slot, start, l; + int32_t ***bw; + NR_DL_FRAME_PARMS *fp; while (!oai_exit) { - if (wait_on_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"NR feptx thread")<0) break; - int slot=proc->slot_feptx; - if (release_thread(&proc->mutex_feptx,&proc->instance_cnt_feptx,"NR feptx thread")<0) break; + if (wait_on_condition(&feptx->mutex_feptx,&feptx->cond_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break; + ru = feptx->ru; + slot = feptx->slot; + aa = feptx->aa; + fp = ru->nr_frame_parms; + start = (feptx->half_slot)? fp->symbols_per_slot>>1 : 0; - nr_feptx0(ru,slot,ru->nr_frame_parms->symbols_per_slot>>1,ru->nr_frame_parms->symbols_per_slot>>1); + bw = ru->beam_weights[0]; + for (l=0;lsymbols_per_slot>>1;l++) { + nr_beam_precoding(ru->common.txdataF, + ru->common.txdataF_BF, + fp, + bw, + slot, + l+start, + aa); + }// for (l=0;lsymbols_per_slot;l++) - if (pthread_cond_signal(&proc->cond_feptx) != 0) { + + nr_feptx0(ru,slot,start,fp->symbols_per_slot>>1,aa); + + if (pthread_cond_signal(&feptx->cond_feptx) != 0) { LOG_E(PHY,"[gNB] ERROR pthread_cond_signal for NR feptx thread exit\n"); exit_fun( "ERROR pthread_cond_signal" ); return NULL; } + if (release_thread(&feptx->mutex_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break; } return(NULL); } void nr_init_feptx_thread(RU_t *ru) { - RU_proc_t *proc = &ru->proc; + RU_proc_t *proc = &ru->proc; + RU_feptx_t *feptx = proc->feptx; + int i = 0; - proc->instance_cnt_feptx = -1; + for(i=0; i<16; i++){ + feptx[i].instance_cnt_feptx = -1; - pthread_mutex_init( &proc->mutex_feptx, NULL); - pthread_cond_init( &proc->cond_feptx, NULL); - - threadCreate(&proc->pthread_feptx, nr_feptx_thread, (void*)ru, "feptx", -1, OAI_PRIORITY_RT); + pthread_mutex_init( &feptx[i].mutex_feptx, NULL); + pthread_cond_init( &feptx[i].cond_feptx, NULL); + threadCreate(&feptx[i].pthread_feptx, nr_feptx_thread, (void*)&feptx[i], "feptx", -1, OAI_PRIORITY_RT); + } } + // is this supposed to generate a slot or a subframe??? // seems to be hardcoded to numerology 1 (2 slots=1 subframe) void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) { @@ -225,7 +251,7 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) { ((nr_slot_select(cfg,slot)==SF_S))) { // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); - nr_feptx0(ru,slot,0,fp->symbols_per_slot); + nr_feptx0(ru,slot,0,fp->symbols_per_slot,aa); } @@ -239,6 +265,94 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) { } +static void *nr_feptx_prec_thread(void *param) { + + RU_prec_t *prec = (RU_prec_t *) param; + RU_t *ru; + NR_DL_FRAME_PARMS *fp; + int symbol; + int p; + int aa; + int32_t *bw; + int32_t **txdataF; + int32_t **txdataF_BF; + + while(!oai_exit) + { + if (wait_on_condition(&prec->mutex_feptx_prec,&prec->cond_feptx_prec,&prec->instance_cnt_feptx_prec,"NR feptx prec thread")<0) break; + ru = prec->ru; + symbol = prec->symbol; + p = prec->p; + aa = prec->aa; + fp = ru->nr_frame_parms; + bw = ru->beam_weights[0][p][aa]; + txdataF = ru->common.txdataF; + txdataF_BF = ru->common.txdataF_BF; + multadd_cpx_vector((int16_t*)&txdataF[p][symbol*fp->ofdm_symbol_size], + (int16_t*)bw, + (int16_t*)&txdataF_BF[aa][symbol*fp->ofdm_symbol_size], + 0, + fp->ofdm_symbol_size, + 15); + + if (release_thread(&prec->mutex_feptx_prec,&prec->instance_cnt_feptx_prec,"NR feptx thread")<0) break; + } + return 0; +} + +void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx) { + + int ret = 0; + int i = 0; + int symbol = 0; + int p = 0; + int aa = 0; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + int nb_antenna_ports = fp->Lmax; // for now logical antenna ports corresponds to SSB + RU_prec_t *prec = ru->proc.prec; + PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB; + + gNB = gNB_list[0]; + + start_meas(&ru->total_precoding_stats); + for(i=0; icommon.txdataF[i], + (void*)gNB->common_vars.txdataF[i], + fp->samples_per_slot_wCP*sizeof(int32_t)); + + for(symbol = 0; symbol < fp->symbols_per_slot; ++symbol){ + for(p=0; pnb_tx;aa++){ + if ((fp->L_ssb >> p) & 0x01){ + while(1){ + if(prec[i].instance_cnt_feptx_prec == -1){ + AssertFatal((ret=pthread_mutex_lock(&prec[i].mutex_feptx_prec))==0,"mutex_lock return %d\n",ret); + prec[i].instance_cnt_feptx_prec = 0; + prec[i].symbol = symbol; + prec[i].p = p; + prec[i].aa = aa; + prec[i].index = i; + prec[i].ru = ru; + AssertFatal(pthread_cond_signal(&prec[i].cond_feptx_prec) == 0,"ERROR pthread_cond_signal for gNB_L1_thread\n"); + AssertFatal((ret=pthread_mutex_unlock(&prec[i].mutex_feptx_prec))==0,"mutex_lock returns %d\n",ret); + i = (i+1) % 16; + break; + } + i = (i+1) % 16; + } + }//(frame_params->Lssb >> p) & 0x01 + }//aa + }//p + }//symbol + + i = 0; + while(1){ + if(prec[i].instance_cnt_feptx_prec == -1) ++i; + if(i == 16) break; + } + + stop_meas(&ru->total_precoding_stats); +} void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) { @@ -247,13 +361,19 @@ void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_t *cfg; int32_t ***bw; + int i=0; - + start_meas(&ru->total_precoding_stats); if (ru->num_gNB == 1){ gNB = gNB_list[0]; cfg = &gNB->gNB_config; if (nr_slot_select(cfg,tti_tx) == SF_UL) return; + for(i=0; iLmax; ++i) + memcpy((void*)ru->common.txdataF[i], + (void*)gNB->common_vars.txdataF[i], + fp->samples_per_slot_wCP*sizeof(int32_t)); + if (ru->nb_tx == 1) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1); @@ -261,10 +381,11 @@ void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) { AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx); for (int p=0; pLmax; p++) { - if ((fp->L_ssb >> p) & 0x01) - memcpy((void*)ru->common.txdataF_BF[0], - (void*)gNB->common_vars.txdataF[p], - fp->samples_per_slot_wCP*sizeof(int32_t)); + if ((fp->L_ssb >> p) & 0x01){ + memcpy((void*)ru->common.txdataF_BF[0], + (void*)ru->common.txdataF[p], + fp->samples_per_slot_wCP*sizeof(int32_t)); + } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 0); @@ -273,17 +394,32 @@ void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) { bw = ru->beam_weights[0]; for (l=0;lsymbols_per_slot;l++) { for (aa=0;aanb_tx;aa++) { - nr_beam_precoding(gNB->common_vars.txdataF, + nr_beam_precoding(ru->common.txdataF, ru->common.txdataF_BF, fp, bw, tti_tx, l, aa); - }// for (aa=0;aanb_tx;aa++) }// for (l=0;lsymbols_per_slot;l++) }// if (ru->nb_tx == 1) }// if (ru->num_gNB == 1) + stop_meas(&ru->total_precoding_stats); +} + +void nr_init_feptx_prec_thread(RU_t *ru){ + + RU_proc_t *proc = &ru->proc; + RU_prec_t *prec = proc->prec; + int i=0; + + for(i=0; i<16; ++i){ + prec[i].instance_cnt_feptx_prec = -1; + pthread_mutex_init( &prec[i].mutex_feptx_prec, NULL); + pthread_cond_init( &prec[i].cond_feptx_prec, NULL); + + threadCreate(&prec[i].pthread_feptx_prec, nr_feptx_prec_thread, (void*)&prec[i], "nr_feptx_prec", -1, OAI_PRIORITY_RT); + } } diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index e6c4b90c4e..c532df8241 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -42,10 +42,12 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, u void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx); -void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols); +void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); void nr_init_feptx_thread(RU_t *ru); void fep_full(RU_t *ru,int slot); void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx); +void nr_init_feptx_prec_thread(RU_t *ru); +void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx); int nr_phy_init_RU(RU_t *ru); void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params, diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf index 26f6eddf52..80d9ea10e6 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf @@ -246,7 +246,7 @@ L1s = ( RUs = ( { local_rf = "yes" - nb_tx = 1 + nb_tx = 8 nb_rx = 1 att_tx = 0 att_rx = 0; @@ -264,7 +264,7 @@ THREAD_STRUCT = ( #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_DISABLE"; + worker_config = "WORKER_ENABLE"; } );