From 2368633642f067be3ba67ee9c2b1a736c4863027 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 9 Jan 2021 07:13:13 +0100 Subject: [PATCH] testing of LTE with 2x2 20 MHz TDD on N310. Modifications in pipelined threading --- executables/nr-gnb.c | 3 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 18 +++++-- targets/RT/USER/lte-enb.c | 23 +++++---- targets/RT/USER/lte-ru.c | 52 +++++++++++--------- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index be9261a117..2aa9635af2 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -588,10 +588,9 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); // the thread can now be woken up - // the thread can now be woken up + AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); - AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); return(0); } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 0c544acf19..fd73086168 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -464,7 +464,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI write_package[end].buff[i] = buff[i]; write_thread->count_write++; write_thread->end = (write_thread->end + 1)% MAX_WRITE_THREAD_PACKAGE; - LOG_I(HW,"Signaling TX TS %llu\n",(unsigned long long)timestamp); + LOG_D(HW,"Signaling TX TS %llu\n",(unsigned long long)timestamp); pthread_cond_signal(&write_thread->cond_write); pthread_mutex_unlock(&write_thread->mutex_write); return 0; @@ -638,9 +638,21 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp // receive multiple channels (e.g. RF A and RF B) std::vector buff_ptrs; - for (int i=0; irx_stream->recv(buff_ptrs, nsamps, s->rx_md); + while (samples_received != nsamps) { + for (int i=0; irx_stream->recv(buff_ptrs,nsamps-samples_received, s->rx_md); + + + if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) + break; + + if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) { + printf("sleep...\n"); //usleep(100); + } + } + if (samples_received == nsamps) s->wait_for_first_pps=0; } else { // receive a single channel (e.g. from connector RF A) samples_received=0; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 8d50eceb67..03ef480131 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -355,21 +355,21 @@ static void *L1_thread_tx(void *param) { LOG_D(PHY,"L1 TX processing %d.%d\n",proc->frame_tx,proc->subframe_tx); phy_procedures_eNB_TX(eNB, proc, 1); AssertFatal((ret= pthread_mutex_lock( &proc->mutex ))==0,"error locking L1_proc_tx mutex, return %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt); int subframe_tx = proc->subframe_tx; int frame_tx = proc->frame_tx; uint64_t timestamp_tx = proc->timestamp_tx; proc->instance_cnt = -1; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt); LOG_D(PHY,"L1 TX signaling done for %d.%d\n",proc->frame_tx,proc->subframe_tx); // the thread can now be woken up LOG_D(PHY,"L1_thread_tx: signaling completion in %d.%d\n",proc->frame_tx,proc->subframe_tx); + AssertFatal((ret= pthread_mutex_unlock( &proc->mutex ))==0,"error unlocking L1_proc_tx mutex, return %d\n",ret); if (pthread_cond_signal(&proc->cond) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); exit_fun( "ERROR pthread_cond_signal" ); } - AssertFatal((ret= pthread_mutex_unlock( &proc->mutex ))==0,"error unlocking L1_proc_tx mutex, return %d\n",ret); wakeup_txfh(eNB,proc,frame_tx,subframe_tx,timestamp_tx); } @@ -408,7 +408,7 @@ static void *L1_thread( void *param ) { LOG_I(PHY,"thread rxtx created id=%ld\n", syscall(__NR_gettid)); while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, 0 ); T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); LOG_D(PHY,"L1RX waiting for RU RX\n"); @@ -416,7 +416,7 @@ static void *L1_thread( void *param ) { LOG_D(PHY,"L1RX starting in %d.%d\n",proc->frame_rx,proc->subframe_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu()); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB,proc->subframe_tx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB,proc->subframe_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB,proc->frame_tx); @@ -430,6 +430,8 @@ static void *L1_thread( void *param ) { LOG_D(PHY,"L1 RX %d.%d done\n",proc->frame_rx,proc->subframe_rx); + if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC, proc->instance_cnt); if (NFAPI_MODE!=NFAPI_MODE_VNF) { if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx); else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) { @@ -438,9 +440,7 @@ static void *L1_thread( void *param ) { } } - if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break; } // while !oai_exit - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); LOG_D(PHY, " *** Exiting eNB thread RXn_TXnp4\n"); eNB_thread_rxtx_status = 0; @@ -532,10 +532,10 @@ int wakeup_txfh(PHY_VARS_eNB *eNB, ru_proc->tti_tx = subframe_tx; ru_proc->frame_tx = frame_tx; LOG_D(PHY,"L1 TX Waking up TX FH (2) %d.%d\n",frame_tx,subframe_tx); + AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_eNBs))==0,"mutex_unlock returned %d\n",ret); // the thread can now be woken up AssertFatal(pthread_cond_signal(&ru_proc->cond_eNBs) == 0, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); - AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_eNBs))==0,"mutex_unlock returned %d\n",ret); } return(0); @@ -560,7 +560,6 @@ int wakeup_tx(PHY_VARS_eNB *eNB, } LOG_D(PHY,"L1 RX Got signal that TX %d.%d is done\n",L1_proc_tx->frame_tx,L1_proc_tx->subframe_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt); L1_proc_tx->instance_cnt = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt); L1_proc_tx->subframe_rx = subframe_rx; @@ -570,8 +569,9 @@ int wakeup_tx(PHY_VARS_eNB *eNB, L1_proc_tx->timestamp_tx = timestamp_tx; // the thread can now be woken up LOG_D(PHY,"L1 RX Waking up L1 TX %d.%d\n",L1_proc->frame_tx,L1_proc->subframe_tx); - AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for eNB L1 thread tx\n"); AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); + + AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for eNB L1 thread tx\n"); return(0); } @@ -595,6 +595,8 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB, } ++L1_proc->instance_cnt; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC, L1_proc->instance_cnt); + // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). @@ -612,6 +614,8 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB, VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx); + AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); + // the thread can now be woken up if (pthread_cond_signal(&L1_proc->cond) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); @@ -619,7 +623,6 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB, return(-1); } - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); return(0); } diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 87747b17a3..639190aaf0 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -648,7 +648,7 @@ void rx_rf(RU_t *ru, proc->tti_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; // synchronize first reception to frame 0 subframe 0 - if (ru->fh_north_asynch_in == NULL) { + if (get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD && ru->fh_north_asynch_in == NULL) { #ifdef PHY_TX_THREAD proc->timestamp_phy_tx = proc->timestamp_rx+((sf_ahead-1)*fp->samples_per_tti); proc->subframe_phy_tx = (proc->tti_rx+(sf_ahead-1))%10; @@ -676,16 +676,12 @@ void rx_rf(RU_t *ru, proc->frame_rx, proc->tti_rx); - // dump VCD output for first RU in list - if (ru->idx == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); + } - if (ru->fh_north_asynch_in == NULL) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx ); - } - } + // dump VCD output for first RU in list + if (ru->idx == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); } if (proc->first_rx == 0) { @@ -776,6 +772,7 @@ void tx_rf(RU_t *ru, /* add fail safe for late command */ if(late_control!=STATE_BURST_NORMAL) { //stop burst + LOG_E(PHY,"%d.%d late_control : %d\n",frame,subframe,late_control); switch (late_control) { case STATE_BURST_TERMINATE: flags=10; // end of burst and no time spec @@ -804,12 +801,12 @@ void tx_rf(RU_t *ru, break; } } - - /* add fail safe for late command end */ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + + /* add fail safe for late command end */ + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers txs = ru->rfdevice.trx_write_func(&ru->rfdevice, timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, @@ -827,7 +824,7 @@ void tx_rf(RU_t *ru, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); // AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %d/%d)\n",txs, siglen); - if( (txs != siglen+sf_extension) && (late_control==STATE_BURST_NORMAL) ) { /* add fail safe for late command */ + if( usrp_tx_thread == 0 && (txs != siglen+sf_extension) && (late_control==STATE_BURST_NORMAL) ) { /* add fail safe for late command */ late_control=STATE_BURST_TERMINATE; LOG_E(PHY,"TX : Timeout (sent %d/%d) state =%d\n",txs, siglen,late_control); } @@ -1510,36 +1507,43 @@ static void *ru_thread_tx( void *param ) { LOG_D(PHY,"ru_thread_tx (ru %d): Waiting for TX processing\n",ru->idx); // wait until eNBs are finished subframe RX n and TX n+4 wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx"); - LOG_D(PHY,"ru_thread_tx: TX in %d.%d\n",ru->proc.frame_tx,ru->proc.tti_tx); + ret = pthread_mutex_lock(&proc->mutex_eNBs); + AssertFatal(ret == 0,"mutex_lock return %d\n",ret); + int frame_tx=proc->frame_tx; + int tti_tx =proc->tti_tx; + uint64_t timestamp_tx = proc->timestamp_tx; + ret = pthread_mutex_unlock(&proc->mutex_eNBs); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + if (oai_exit) break; // 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,frame_tx,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); + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); if(!(ru->emulate_rf)) { //if(!emulate_rf){ // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); if (ru->fh_north_out) ru->fh_north_out(ru); } else { for (int i=0; inb_tx; i++) { - if(proc->frame_tx == 2) { - sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,proc->frame_tx,proc->tti_tx); + if(frame_tx == 2) { + sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,frame_tx,tti_tx); LOG_M(filename,"txdataF_frame",ru->common.txdataF_BF[i],fp->symbols_per_tti*fp->ofdm_symbol_size, 1, 1); } - if(proc->frame_tx == 2 && proc->tti_tx==0) { - sprintf(filename,"txdata%d_frame%d.m",i,proc->frame_tx); + if(frame_tx == 2 && tti_tx==0) { + sprintf(filename,"txdata%d_frame%d.m",i,frame_tx); LOG_M(filename,"txdata_frame",ru->common.txdata[i],fp->samples_per_tti*10, 1, 1); } } } - LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n", proc->frame_tx, proc->tti_tx); + LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n", frame_tx, tti_tx); release_thread(&proc->mutex_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx"); for(int i = 0; inum_eNB; i++) { @@ -1571,7 +1575,7 @@ static void *ru_thread_tx( void *param ) { AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); AssertFatal((ret=pthread_mutex_lock( &L1_proc->mutex_RUs))==0,"mutex_lock returns %d\n",ret); L1_proc->instance_cnt_RUs = 0; - LOG_D(PHY,"ru_thread_tx: Signaling RU TX done in %d.%d\n", proc->frame_tx, proc->tti_tx); + LOG_D(PHY,"ru_thread_tx: Signaling RU TX done in %d.%d\n", frame_tx, tti_tx); // the thread can now be woken up LOG_D(PHY,"ru_thread_tx: clearing mask and Waking up L1 thread\n");