From cd7f8333f73f2a043e5124bbdcb396ae76ee9759 Mon Sep 17 00:00:00 2001 From: Sagar Parsawar Date: Mon, 25 Jul 2022 13:57:56 +0200 Subject: [PATCH] Adding 16x IDFT interpolation for PRS peak estimation --- .../nr_dl_channel_estimation.c | 60 +++++++-- openair1/PHY/TOOLS/oai_dfts.c | 119 +++++++++++++++++- openair1/PHY/TOOLS/tools_defs.h | 3 + openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 +- 4 files changed, 169 insertions(+), 19 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 591d4d037b..9756f1105f 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -38,6 +38,7 @@ //#define DEBUG_CH //#define DEBUG_PRS_CHEST //#define DEBUG_PRS_PRINTS +#define IDFT_INTERPOL_FACTOR 1 extern short nr_qpsk_mod_table[8]; int k_prime_table[4][12] = { {0,1,0,1,0,1,0,1,0,1,0,1}, @@ -62,12 +63,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas; int32_t **prs_chestF = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_ch_estimates; int32_t **prs_chestT = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_ch_estimates_time; - int slot_prs; - if(rep_num > 0) - slot_prs = (proc->nr_slot_rx - prs_cfg->PRSResourceTimeGap)%frame_params->slots_per_frame; - else - slot_prs = proc->nr_slot_rx; - + int slot_prs = (proc->nr_slot_rx - rep_num*prs_cfg->PRSResourceTimeGap + frame_params->slots_per_frame)%frame_params->slots_per_frame; uint32_t **nr_gold_prs = ue->nr_gold_prs[gNB_id][rsc_id][slot_prs]; uint8_t rxAnt = 0, idx = 0; @@ -76,13 +72,18 @@ int nr_prs_channel_estimation(uint8_t gNB_id, int16_t k_prime = 0, k = 0, re_offset = 0, first_half = 0, second_half = 0; int16_t *ch_tmp = (int16_t *)malloc16_clear(frame_params->ofdm_symbol_size*sizeof(int32_t)); AssertFatal((ch_tmp != NULL), "[%s] channel estimate buffer initialization failed!!", __FUNCTION__); + int16_t *chF_interpol = (int16_t *)malloc16_clear(IDFT_INTERPOL_FACTOR*frame_params->ofdm_symbol_size*sizeof(int32_t)); + AssertFatal((chF_interpol != NULL), "[%s] channel estimate buffer initialization failed!!", __FUNCTION__); + int16_t *chT_interpol = (int16_t *)malloc16_clear(IDFT_INTERPOL_FACTOR*frame_params->ofdm_symbol_size*sizeof(int32_t)); + AssertFatal((chT_interpol != NULL), "[%s] channel estimate buffer initialization failed!!", __FUNCTION__); int32_t ch_pwr = 0, snr = 0; #ifdef DEBUG_PRS_CHEST char filename[64] = {0}, varname[64] = {0}; #endif - int16_t *ch_init = ch_tmp; + int16_t *ch_init = ch_tmp; int16_t scale_factor = (1.0f/(float)(prs_cfg->NumPRSSymbols))*(1<<15); - int16_t num_pilots = (12/prs_cfg->CombSize)*prs_cfg->NumRB; + int16_t num_pilots = (12/prs_cfg->CombSize)*prs_cfg->NumRB; + int16_t start_offset = (IDFT_INTERPOL_FACTOR-1)*frame_params->ofdm_symbol_size>>1; for(int l = prs_cfg->SymbolStart; l < prs_cfg->SymbolStart+prs_cfg->NumPRSSymbols; l++) { @@ -434,9 +435,12 @@ int nr_prs_channel_estimation(uint8_t gNB_id, if(second_half > 0) memcpy((int16_t *)&prs_chestF[rxAnt][0], &ch_tmp[(first_half<<1)], second_half*sizeof(int32_t)); + memcpy((int16_t *)&chF_interpol[start_offset+re_offset], &ch_tmp[0], first_half*sizeof(int32_t)); + memcpy((int16_t *)&chF_interpol[start_offset], &ch_tmp[(first_half<<1)], second_half*sizeof(int32_t)); + // Time domain IMPULSE response idft_size_idx_t idftsizeidx; - switch (frame_params->ofdm_symbol_size) { + switch (IDFT_INTERPOL_FACTOR*frame_params->ofdm_symbol_size) { case 128: idftsizeidx = IDFT_128; break; @@ -473,18 +477,46 @@ int nr_prs_channel_estimation(uint8_t gNB_id, idftsizeidx = IDFT_4096; break; + case 8192: + idftsizeidx = IDFT_8192; + break; + + case 12288: + idftsizeidx = IDFT_12288; + break; + + case 16384: + idftsizeidx = IDFT_16384; + break; + + case 24576: + idftsizeidx = IDFT_24576; + break; + + case 32768: + idftsizeidx = IDFT_32768; + break; + + case 49152: + idftsizeidx = IDFT_49152; + break; + + case 65536: + idftsizeidx = IDFT_65536; + break; + default: LOG_I(PHY, "%s: unsupported ofdm symbol size \n", __FUNCTION__); assert(0); } idft(idftsizeidx, - (int16_t *)&prs_chestF[rxAnt][0], - (int16_t *)&ch_tmp[0],1); + (int16_t *)&chF_interpol[0], + (int16_t *)&chT_interpol[0],1); // rearrange impulse response - memcpy((int16_t *)&prs_chestT[rxAnt][0], &ch_tmp[frame_params->ofdm_symbol_size], (frame_params->ofdm_symbol_size>>1)*sizeof(int32_t)); - memcpy((int16_t *)&prs_chestT[rxAnt][(frame_params->ofdm_symbol_size>>1)], &ch_tmp[0], (frame_params->ofdm_symbol_size>>1)*sizeof(int32_t)); + memcpy((int16_t *)&prs_chestT[rxAnt][0], &chT_interpol[IDFT_INTERPOL_FACTOR*frame_params->ofdm_symbol_size], (frame_params->ofdm_symbol_size>>1)*sizeof(int32_t)); + memcpy((int16_t *)&prs_chestT[rxAnt][(frame_params->ofdm_symbol_size>>1)], &chT_interpol[start_offset], (frame_params->ofdm_symbol_size>>1)*sizeof(int32_t)); // peak estimator peak_estimator(&prs_chestT[rxAnt][0], @@ -530,6 +562,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, } free(ch_tmp); + free(chF_interpol); + free(chT_interpol); return(0); } diff --git a/openair1/PHY/TOOLS/oai_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c index 5e8622bb24..014199831f 100644 --- a/openair1/PHY/TOOLS/oai_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -5363,7 +5363,7 @@ void idft8192(int16_t *x,int16_t *y,unsigned char scale) #endif -int16_t tw16384[3*2*4096]; +int16_t tw16384[3*2*4096] __attribute__((aligned(32))); #ifndef __AVX2__ void dft16384(int16_t *x,int16_t *y,unsigned char scale) @@ -7013,6 +7013,122 @@ void idft49152(int16_t *input, int16_t *output,uint8_t scale) { _m_empty(); } +int16_t tw65536[3*2*4096] __attribute__((aligned(32))); + +#ifndef __AVX2__ +void idft65536(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd_q15_t xtmp[16384],ytmp[16384],*tw65536_128p=(simd_q15_t *)tw65536,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; + simd_q15_t *ytmpp = &ytmp[0]; + int i,j; + + for (i=0,j=0; i<16384; i+=4,j++) { + transpose16_ooff(x128+i,xtmp+j,4096); + } + + + idft16384((int16_t*)(xtmp),(int16_t*)(ytmp),1); + idft16384((int16_t*)(xtmp+4096),(int16_t*)(ytmp+4096),1); + idft16384((int16_t*)(xtmp+8192),(int16_t*)(ytmp+8192),1); + idft16384((int16_t*)(xtmp+12288),(int16_t*)(ytmp+12288),1); + + for (i=0; i<4096; i++) { + ibfly4(ytmpp,ytmpp+4096,ytmpp+8192,ytmpp+12288, + y128p,y128p+4096,y128p+8192,y128p+12288, + tw65536_128p,tw63536_128p+4096,tw65536_128p+8192); + tw65536_128p++; + y128p++; + ytmpp++; + } + + if (scale>0) { + + for (i=0; i<1024; i++) { + y128[0] = shiftright_int16(y128[0],scale); + y128[1] = shiftright_int16(y128[1],scale); + y128[2] = shiftright_int16(y128[2],scale); + y128[3] = shiftright_int16(y128[3],scale); + y128[4] = shiftright_int16(y128[4],scale); + y128[5] = shiftright_int16(y128[5],scale); + y128[6] = shiftright_int16(y128[6],scale); + y128[7] = shiftright_int16(y128[7],scale); + y128[8] = shiftright_int16(y128[8],scale); + y128[9] = shiftright_int16(y128[9],scale); + y128[10] = shiftright_int16(y128[10],scale); + y128[11] = shiftright_int16(y128[11],scale); + y128[12] = shiftright_int16(y128[12],scale); + y128[13] = shiftright_int16(y128[13],scale); + y128[14] = shiftright_int16(y128[14],scale); + y128[15] = shiftright_int16(y128[15],scale); + + y128+=16; + } + + } + + _mm_empty(); + _m_empty(); +} + +#else // __AVX2__ +void idft65536(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd256_q15_t xtmp[8192],ytmp[8192],*tw65536_256p=(simd256_q15_t *)tw65536,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; + simd256_q15_t *ytmpp = &ytmp[0]; + int i,j; + + for (i=0,j=0; i<8192; i+=4,j++) { + transpose16_ooff_simd256(x256+i,xtmp+j,2048); + } + + + idft16384((int16_t*)(xtmp),(int16_t*)(ytmp),1); + idft16384((int16_t*)(xtmp+2048),(int16_t*)(ytmp+2048),1); + idft16384((int16_t*)(xtmp+4096),(int16_t*)(ytmp+4096),1); + idft16384((int16_t*)(xtmp+6144),(int16_t*)(ytmp+6144),1); + + for (i=0; i<2048; i++) { + ibfly4_256(ytmpp,ytmpp+2048,ytmpp+4096,ytmpp+6144, + y256p,y256p+2048,y256p+4096,y256p+6144, + tw65536_256p,tw65536_256p+4096,tw65536_256p+8192); + tw65536_256p++; + y256p++; + ytmpp++; + } + + if (scale>0) { + + for (i=0; i<512; i++) { + y256[0] = shiftright_int16_simd256(y256[0],scale); + y256[1] = shiftright_int16_simd256(y256[1],scale); + y256[2] = shiftright_int16_simd256(y256[2],scale); + y256[3] = shiftright_int16_simd256(y256[3],scale); + y256[4] = shiftright_int16_simd256(y256[4],scale); + y256[5] = shiftright_int16_simd256(y256[5],scale); + y256[6] = shiftright_int16_simd256(y256[6],scale); + y256[7] = shiftright_int16_simd256(y256[7],scale); + y256[8] = shiftright_int16_simd256(y256[8],scale); + y256[9] = shiftright_int16_simd256(y256[9],scale); + y256[10] = shiftright_int16_simd256(y256[10],scale); + y256[11] = shiftright_int16_simd256(y256[11],scale); + y256[12] = shiftright_int16_simd256(y256[12],scale); + y256[13] = shiftright_int16_simd256(y256[13],scale); + y256[14] = shiftright_int16_simd256(y256[14],scale); + y256[15] = shiftright_int16_simd256(y256[15],scale); + + y256+=16; + } + + } + + _mm_empty(); + _m_empty(); +} + +#endif //__AVX2__ + int16_t twa73728[49152] __attribute__((aligned(32))); int16_t twb73728[49152] __attribute__((aligned(32))); // 24576 x 3 @@ -10708,6 +10824,7 @@ int dfts_autoinit(void) init_rad2(8192,tw8192); init_rad4(16384,tw16384); init_rad2(32768,tw32768); + init_rad4(65536,tw65536); init_rad3(768,twa768,twb768); init_rad3(1536,twa1536,twb1536); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 8303e088b4..f272e513c2 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -275,10 +275,13 @@ This function performs optimized fixed-point radix-2 FFT/IFFT. SZ_DEF(8192) \ SZ_DEF(9216) \ SZ_DEF(12288) \ + SZ_DEF(16384) \ SZ_DEF(18432) \ SZ_DEF(24576) \ + SZ_DEF(32768) \ SZ_DEF(36864) \ SZ_DEF(49152) \ + SZ_DEF(65536) \ SZ_DEF(73728) \ SZ_DEF(98304) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 3fbd0e654d..ffbedf3da7 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -149,11 +149,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, { if( (((frame*fp->slots_per_frame + slot) - (gNB->prs_vars.prs_cfg[rsc_id].PRSResourceSetPeriod[1] + gNB->prs_vars.prs_cfg[rsc_id].PRSResourceOffset)+gNB->prs_vars.prs_cfg[rsc_id].PRSResourceSetPeriod[0])%gNB->prs_vars.prs_cfg[rsc_id].PRSResourceSetPeriod[0]) == i*gNB->prs_vars.prs_cfg[rsc_id].PRSResourceTimeGap ) { - if (i > 0) - slot_prs = (slot - gNB->prs_vars.prs_cfg[rsc_id].PRSResourceTimeGap + fp->slots_per_frame)%fp->slots_per_frame; - else - slot_prs = slot; - + slot_prs = (slot - i*gNB->prs_vars.prs_cfg[rsc_id].PRSResourceTimeGap + fp->slots_per_frame)%fp->slots_per_frame; LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id); nr_generate_prs(gNB->nr_gold_prs[rsc_id][slot_prs],&gNB->common_vars.txdataF[0][txdataF_offset], AMP, &gNB->prs_vars.prs_cfg[rsc_id], cfg, fp); }