From 0f207da28a582be26d873c462be9d4db6f77d6ff Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 8 May 2022 18:36:42 +0200 Subject: [PATCH] initial changes for multi-threaded TX for IF5 --- executables/nr-ru.c | 33 +++--- openair1/PHY/defs_RU.h | 2 + openair1/SCHED_NR/nr_ru_procedures.c | 25 ++++- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 17 +-- targets/ARCH/COMMON/common_lib.h | 2 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 100 +++++++++--------- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 2 +- 7 files changed, 92 insertions(+), 89 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index d14b3f1a88..662cbdb9e1 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -275,15 +275,15 @@ int connect_rau(RU_t *ru) { // southbound IF5 fronthaul for 16-bit OAI format void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - void *buffs[ru->nb_tx]; int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0); - for (int aid=0;aidnb_tx;aid++) buffs[aid]=&ru->common.txdata[aid][offset]; start_meas(&ru->tx_fhaul); - ru->ifdevice.trx_write_func2(&ru->ifdevice, - timestamp, - buffs, - ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms), - 0); + for (int aid=0;aidnb_tx;aid++) + ru->ifdevice.trx_write_func2(&ru->ifdevice, + timestamp, + (void*)&ru->common.txdata[aid][offset], + aid, + ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms), + 0); stop_meas(&ru->tx_fhaul); } @@ -488,7 +488,7 @@ void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *slot) { RU_proc_t *proc = &ru->proc; int tti_tx,frame_tx; openair0_timestamp timestamp_tx; - recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL,1); + AssertFatal(1==0,"Shouldn't get here\n"); // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); frame_tx = (timestamp_tx / (fp->samples_per_subframe*10))&1023; uint32_t idx_sf = timestamp_tx / fp->samples_per_subframe; @@ -565,11 +565,9 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { } void fh_if5_north_out(RU_t *ru) { - RU_proc_t *proc=&ru->proc; - uint8_t seqno=0; /// **** send_IF5 of rxdata to BBU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL); + AssertFatal(1==0,"Shouldn't get here\n"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); } @@ -1181,9 +1179,15 @@ void *ru_stats_thread(void *param) { print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); - print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); + if (ru->txfh_in_fep) { + print_meas(&ru->ofdm_mod_stats,"feptx_ofdm (with txfh)",NULL,NULL); + print_meas(&ru->ofdm_total_stats,"feptx_total (with txfh)",NULL,NULL); + } + else { + print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); + print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); + } } - print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); @@ -1851,11 +1855,12 @@ void set_function_spec_param(RU_t *ru) { case REMOTE_IF5: // the remote unit is IF5 RRU ru->do_prach = 0; +// ru->txfh_in_fep = 1; ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // this is frequency-shift + DFTs ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // need to do transmit Precoding + IDFTs ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception - ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission + ru->fh_south_out = (ru->txfh_in_fep) ? NULL : fh_if5_south_out; // synchronous IF5 transmission ru->fh_south_asynch_in = NULL; // no asynchronous UL ru->start_rf = ru->eth_params.transp_preference == ETH_UDP_IF5_ECPRI_MODE ? start_streaming : NULL; ru->stop_rf = NULL; diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 0320697ecf..6078e2f857 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -507,6 +507,8 @@ typedef struct RU_t_s { int sf_ahead; /// TX processing advance in slots (for NR) int sl_ahead; + /// flag to indicated TX FH is embedded in TX FEP + int txfh_in_fep; /// FAPI confiuration nfapi_nr_config_request_scf_t config; /// Frame parameters diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index b90f14a129..ffe847b6ce 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -56,7 +56,7 @@ 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 slot_offset,slot_offsetF; + unsigned int slot_offset,slot_offsetF,initial_slot_offset,num_samples;; int slot = tti_tx; @@ -71,17 +71,19 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { slot_offset += (idx_sym%(0x7<numerology_index)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0; slot_offset += fp->ofdm_symbol_size*first_symbol; + initial_slot_offset = slot_offset; 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); - 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 { + num_samples=num_symbols*(fp->nb_prefix_samples+fp->ofdm_symbol_size); + } else { if (fp->numerology_index != 0) { if (!(slot%(fp->slots_per_subframe/2))&&(first_symbol==0)) { // case where first symbol in slot has longer prefix @@ -98,6 +100,8 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { num_symbols-1, fp->nb_prefix_samples, CYCLIC_PREFIX); + num_samples=(num_symbols-1)*(fp->nb_prefix_samples+fp->ofdm_symbol_size)+ + fp->nb_prefix_samples0+fp->ofdm_symbol_size; } else { // all symbols in slot have shorter prefix PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], @@ -106,6 +110,7 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { num_symbols, fp->nb_prefix_samples, CYCLIC_PREFIX); + num_samples=num_symbols*(fp->nb_prefix_samples+fp->ofdm_symbol_size); } } // numerology_index!=0 else { //numerology_index == 0 @@ -130,10 +135,20 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { slot_offset += fp->nb_prefix_samples0+fp->ofdm_symbol_size; slot_offsetF += fp->ofdm_symbol_size; } - } - } + } // for(idx_symbol.. + num_samples=slot_offset-initial_slot_offset; + } // numerology 0 } + if (ru->txfh_in_fep) { + ru->ifdevice.trx_write_func2(&ru->ifdevice, + ru->proc.timestamp_tx, + (void*)&ru->common.txdata[aa][initial_slot_offset], + aa, + num_samples, + 0); + + } //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c751b33ac0..1c0c23bb0d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -608,25 +608,10 @@ bool allocate_dl_retransmission(module_id_t module_id, /* the retransmission will use a different time domain allocation, check * that we have enough resources */ NR_pdsch_semi_static_t temp_ps = *ps; -<<<<<<< HEAD + const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols); nr_set_pdsch_semi_static(sib1,scc, cg, sched_ctrl->active_bwp, bwpd,tda, ps->nrOfLayers, sched_ctrl, &temp_ps); while (rbStart < bwpSize && !(rballoc_mask[rbStart]&SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols))) -======= - - nr_set_pdsch_semi_static(sib1, - scc, - cg, - sched_ctrl->active_bwp, - bwpd, - tda, - ps->nrOfLayers, - sched_ctrl, - &temp_ps); - - const uint16_t slbitmap = SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols); - while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap) ->>>>>>> origin/develop rbStart++; while (rbStart + rbSize < bwpSize && (rballoc_mask[rbStart + rbSize] & slbitmap) == slbitmap) diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index e30a78ef75..f3dcc35e53 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -423,7 +423,7 @@ struct openair0_device_t { @param antenna_id index of the antenna if the device has multiple anteannas @param flags flags must be set to TRUE if timestamp parameter needs to be applied */ - int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int flags); + int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void *buff, int aid, int nsamps, int flags); /*! \brief Receive samples from hardware. * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index dcb23b5970..f043b6ded4 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -289,101 +289,98 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam return (bytes_sent); } -int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int flags) { +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int aid, int nsamps, int flags) { int bytes_sent=0; eth_state_t *eth = (eth_state_t*)device->priv; int sendto_flag =0; fhstate_t *fhstate = &device->fhstate; - AssertFatal((nsamps&255) == 0,"transport size should be a multiple of 256 samples, have %d\n",nsamps); //sendto_flag|=flags; eth->tx_nsamps=nsamps; - int ntx = device->openair0_cfg->tx_num_channels; - void *buff2[ntx]; + void *buff2; #if defined(__x86_64) || defined(__i386__) #ifdef __AVX2__ int nsamps2 = 256>>3; - __m256i buff_tx[ntx][nsamps2+1]; - for (int aid=0;aid>2; - __m128i buff_tx[ntx][nsamps2+2]; - for (int aid=0;aid>2; - int16x8_t buff_tx[ntx][nsamps2+2]; - for (int aid=0;aid>6; - *(uint8_t *)(buff2[aid] + 3) = 0;// 1024&0xff; - // ECPRI PC_ID (2 bytes) - *(uint16_t *)(buff2[aid] + 4) = aid; + /* construct application header */ + // ECPRI Protocol revision + reserved bits (1 byte) + *(uint8_t *)buff2 = ECPRIREV; + // ECPRI Message type (1 byte) + *(uint8_t *)(buff2 + 1) = 64; + // ECPRI PC_ID (2 bytes) + *(uint16_t *)(buff2 + 4) = aid; - } openair0_timestamp TS = timestamp + fhstate->TS0; TS = 6*device->sampling_rate_ratio_d*(TS/device->sampling_rate_ratio_n); TS -= device->txrx_offset; int TSinc = 6*256*device->sampling_rate_ratio_d/device->sampling_rate_ratio_n; + int len=256; for (int offset=0;offset>8; + *(uint8_t *)(buff2 + 3) = len&0xff; + //LOG_I(PHY,"TS %llu aa %d : offset %d, len %d\n",(unsigned long long)TS,aid,offset,len); // bring TX data into 12 MSBs #if defined(__x86_64__) || defined(__i386__) #ifdef __AVX2__ - __m256i *buff256 = (__m256i *)&((uint32_t*)buff[aid])[offset]; - for (int j=0; j<32; j+=8) { - buff_tx[aid][1+j] = _mm256_slli_epi16(buff256[j],4); - buff_tx[aid][2+j] = _mm256_slli_epi16(buff256[j+1],4); - buff_tx[aid][3+j] = _mm256_slli_epi16(buff256[j+2],4); - buff_tx[aid][4+j] = _mm256_slli_epi16(buff256[j+3],4); - buff_tx[aid][5+j] = _mm256_slli_epi16(buff256[j+4],4); - buff_tx[aid][6+j] = _mm256_slli_epi16(buff256[j+5],4); - buff_tx[aid][7+j] = _mm256_slli_epi16(buff256[j+6],4); - buff_tx[aid][8+j] = _mm256_slli_epi16(buff256[j+7],4); - } + __m256i *buff256 = (__m256i *)&((uint32_t*)buff)[offset]; + for (int j=0; j<32; j+=8) { + buff_tx[1+j] = _mm256_slli_epi16(buff256[j],4); + buff_tx[2+j] = _mm256_slli_epi16(buff256[j+1],4); + buff_tx[3+j] = _mm256_slli_epi16(buff256[j+2],4); + buff_tx[4+j] = _mm256_slli_epi16(buff256[j+3],4); + buff_tx[5+j] = _mm256_slli_epi16(buff256[j+4],4); + buff_tx[6+j] = _mm256_slli_epi16(buff256[j+5],4); + buff_tx[7+j] = _mm256_slli_epi16(buff256[j+6],4); + buff_tx[8+j] = _mm256_slli_epi16(buff256[j+7],4); + } #else - __m128i *buff128 = (__m128i *)&buff[aid][offset]; - for (int j=0; j<64; j++) buff_tx[aid][2+j] = _mm_slli_epi16(buff128[j],4); + __m128i *buff128 = (__m128i *)&buff[offset]; + for (int j=0; j<64; j++) buff_tx[2+j] = _mm_slli_epi16(buff128[j],4); #endif #elif defined(__arm__) - int16x8_t *buff128 = (__int16x8_t*)&buff[aid][offset]; - for (int j=0; j<64; j++) buff_tx[aid][2+j] = vshlq_n_s16(((int16x8_t *)buff128)[j],4); + int16x8_t *buff128 = (__int16x8_t*)&buff[offset]; + for (int j=0; j<64; j++) buff_tx[2+j] = vshlq_n_s16(((int16x8_t *)buff128)[j],4); #endif - /* Send packet */ - bytes_sent = sendto(eth->sockfdd[aid%eth->num_fd], - buff2[aid], - UDP_PACKET_SIZE_BYTES(256), - sendto_flag, - (struct sockaddr*)ð->dest_addrd, - eth->addr_len); + bytes_sent = sendto(eth->sockfdd[aid%eth->num_fd], + buff2, + UDP_PACKET_SIZE_BYTES(len>>2), + sendto_flag, + (struct sockaddr*)ð->dest_addrd, + eth->addr_len); - if ( bytes_sent == -1) { + if ( bytes_sent == -1) { eth->num_tx_errors++; perror("ETHERNET WRITE: "); exit(-1); - } else { + } else { eth->tx_actual_nsamps=bytes_sent>>2; eth->tx_count++; - } } - } + } return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2; } @@ -426,12 +423,11 @@ void *udp_read_thread(void *arg) { } sleep(1); } - + return(0); } int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps) { - eth_state_t *eth = (eth_state_t*)device->priv; fhstate_t *fhstate = &device->fhstate; openair0_timestamp prev_read_TS= fhstate->TS_read, min_TS; // block until FH is ready diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 72a3cfef63..ccf67b4ca0 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -241,7 +241,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value); * @ingroup _oai */ int eth_socket_init_udp(openair0_device *device); -int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int flags); +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buf, int aid, int nsamps, int flags); int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps);