From d9abc574fc0fcfb2d4e448047ac3e19cf5f77427 Mon Sep 17 00:00:00 2001 From: Ahmed Hussein Date: Wed, 17 Apr 2019 16:11:04 +0200 Subject: [PATCH] Added RB extraction + FFT (completed with testing) --- cmake_targets/CMakeLists.txt | 1 + openair1/PHY/INIT/nr_parms.c | 12 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 45 ++++++ openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 2 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 49 ++++++ .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 2 +- openair1/PHY/impl_defs_top.h | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 142 +++++++++++++++--- 8 files changed, 221 insertions(+), 34 deletions(-) create mode 100644 openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 95b6385d68..02c2ca1b7d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1286,6 +1286,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 5c38ab3056..00b2b6a7da 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -133,13 +133,13 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case 106: //40 MHz if (fp->threequarter_fs) { fp->ofdm_symbol_size = 1536; - fp->first_carrier_offset = 900; //1536 - 636 + fp->first_carrier_offset = 900; //1536 - ( (106*12) / 2 ) fp->nb_prefix_samples0 = 132; fp->nb_prefix_samples = 108; } else { fp->ofdm_symbol_size = 2048; - fp->first_carrier_offset = 1412; //2048 - 636 + fp->first_carrier_offset = 1412; //2048 - ( (106*12) / 2 ) fp->nb_prefix_samples0 = 176; fp->nb_prefix_samples = 144; } @@ -152,13 +152,13 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case 217: //80 MHz if (fp->threequarter_fs) { fp->ofdm_symbol_size = 3072; - fp->first_carrier_offset = 1770; //3072 - 1302 + fp->first_carrier_offset = 1770; //3072 - ( (217*12) / 2 ) fp->nb_prefix_samples0 = 264; fp->nb_prefix_samples = 216; } else { fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2794; //4096 - 1302 + fp->first_carrier_offset = 2794; //4096 - ( (217*12) / 2 ) fp->nb_prefix_samples0 = 352; fp->nb_prefix_samples = 288; } @@ -167,14 +167,14 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case 245: AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for N_RB %d and MU %d\n",N_RB_DL,mu); fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2626; //4096 - 1478 + fp->first_carrier_offset = 2626; //4096 - ( (245*12) / 2 ) fp->nb_prefix_samples0 = 352; fp->nb_prefix_samples = 288; break; case 273: AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for N_RB %d and MU %d\n",N_RB_DL,mu); fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2458; //4096 - 1638 + fp->first_carrier_offset = 2458; //4096 - ( (273*12) / 2 ) fp->nb_prefix_samples0 = 352; fp->nb_prefix_samples = 288; break; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index b4662084e0..f00a534966 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -33,6 +33,49 @@ #include "PHY/defs_nr_common.h" +/** \brief This function is the top-level entry point to PUSCH demodulation, after frequency-domain transformation and channel estimation. It performs + - RB extraction (signal and channel estimates) + - channel compensation (matched filtering) + - RE extraction (dmrs) + - antenna combining (MRC, Alamouti, cycling) + - LLR computation + This function supports TM1, 2, 3, 5, and 6. + @param ue Pointer to PHY variables + @param UE_id id of current UE + @param frame Frame number + @param nr_tti_rx TTI number + @param symbol Symbol on which to act (within-in nr_TTI_rx) + @param first_symbol_flag set to 1 on first ULSCH symbol +*/ +int nr_rx_ulsch(PHY_VARS_gNB *gNB, + uint8_t UE_id, + uint32_t frame, + uint8_t nr_tti_rx, + unsigned char symbol, + unsigned char first_symbol_flag, + unsigned char harq_pid); + + +/** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented) + @param rxdataF pointer to the received frequency domain signal + @param rxdataF_ext pointer to the extracted frequency domain signal + @param rb_alloc RB allocation map (used for Resource Allocation Type 0 in NR) + @param symbol Symbol on which to act (within-in nr_TTI_rx) + @param start_rb The starting RB in the RB allocation (used for Resource Allocation Type 1 in NR) + @param nb_pusch_rb The number of RBs allocated (used for Resource Allocation Type 1 in NR) + @param frame_parms, Pointer to frame descriptor structure + +*/ +unsigned short nr_ulsch_extract_rbs_single(int **rxdataF, + int **rxdataF_ext, + uint32_t rxdataF_ext_offset, + // unsigned int *rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + unsigned char symbol, + unsigned short start_rb, + unsigned short nb_pusch_rb, + NR_DL_FRAME_PARMS *frame_parms); + + /** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. @param rxdataF_comp Compensated channel output @param ulsch_llr llr output @@ -44,6 +87,7 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol); + /** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16 QAM received waveforms. @param rxdataF_comp Compensated channel output @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 16 @@ -57,6 +101,7 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol); + /** \brief This function generates log-likelihood ratios (decoder input) for single-stream 64 QAM received waveforms. @param rxdataF_comp Compensated channel output @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 1466dafff6..295fb88d50 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -291,7 +291,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0]; + NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id+1][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; nfapi_nr_ul_config_ulsch_pdu_rel15_t *nfapi_ulsch_pdu_rel15 = &harq_process->ulsch_pdu.ulsch_pdu_rel15; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c new file mode 100644 index 0000000000..222db1f73d --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -0,0 +1,49 @@ +// This should have nr_rx_pdsch, nr_ulsch_extract_rbs_single, and nr_ulsch_compute_llr +#include "PHY/defs_gNB.h" +#include "nr_transport_proto.h" +#include "PHY/impl_defs_top.h" + +//============================================================================================== +// Extraction functions +//============================================================================================== + +unsigned short nr_ulsch_extract_rbs_single(int **rxdataF, + int **rxdataF_ext, + uint32_t rxdataF_ext_offset, + // unsigned int *rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + unsigned char symbol, + unsigned short start_rb, + unsigned short nb_rb_pdsch, + NR_DL_FRAME_PARMS *frame_parms) +{ + unsigned short start_re,re; + unsigned char aarx, is_dmrs_symbol = 0; + uint32_t rxF_ext_index = 0, nb_re_pdsch = 0; + + int16_t *rxF,*rxF_ext; + + is_dmrs_symbol = (symbol == 2) ? 1 : 0; //to be updated from config + + start_re = frame_parms->first_carrier_offset + (start_rb * NR_NB_SC_PER_RB); + + nb_re_pdsch = NR_NB_SC_PER_RB * nb_rb_pdsch; + + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + + rxF = (int16_t *)&rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; + rxF_ext = (int16_t *)&rxdataF_ext[aarx][rxdataF_ext_offset]; + + for (re = 0; re < nb_re_pdsch; re++) { + + if ( (is_dmrs_symbol && ((re&1) != frame_parms->nushift)) || (is_dmrs_symbol == 0) ) { // [hna] (re&1) != frame_parms->nushift) assuming only dmrs type 1 and mapping type A + + rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)] << 15) >> AMP_SHIFT; + rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)] << 15) >> AMP_SHIFT; + + rxF_ext_index = rxF_ext_index + 2; + } + } + } + + return(nb_rb_pdsch/frame_parms->nb_antennas_rx); +} \ No newline at end of file diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 270b5e14cf..b9d607fdc4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -240,7 +240,7 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, xmm2 = vsubq_s16(ch_magb[i],xmm2); #endif - // ---------------------------------------s + // --------------------------------------- // 1st RE // --------------------------------------- ulsch_llr[0] = ((short *)&rxF[i])[0]; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index 90645e2c11..8f300596ff 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -245,7 +245,7 @@ #ifdef BIT8_TX #define AMP_SHIFT 7 #else -#define AMP_SHIFT 9 +#define AMP_SHIFT 10 // [hna] was 9, but 9 doesn't work in case of mod_order = 6 (problem due to IFFT/FFT) #endif #define AMP ((1)<ulsch[UE_id][0]; + NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id+1][0]; // "+1" because first element in ulsch is for RA nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15; NR_UE_PUSCH *pusch_ue = UE->pusch_vars[0][eNB_id]; @@ -481,6 +482,7 @@ int main(int argc, char **argv) { unsigned int errors_bit_uncoded; unsigned int errors_bit; uint8_t bit_index; + uint32_t error_extraction; uint32_t errors_scrambling; uint32_t scrambling_index; uint8_t symbol; @@ -621,7 +623,7 @@ int main(int argc, char **argv) { txdataF = UE->common_vars.txdataF; amp = AMP; - start_rb = 0; + start_rb = 90; start_sc = frame_parms->first_carrier_offset + start_rb*NR_NB_SC_PER_RB; if (start_sc >= frame_parms->ofdm_symbol_size) @@ -742,14 +744,15 @@ int main(int argc, char **argv) { for (trial = 0; trial < n_trials; trial++) { errors_bit_uncoded = 0; + error_extraction = 0; errors_scrambling = 0; errors_bit = 0; scrambling_index = 0; for (i=0; inb_antennas_rx; ap++) { - ((short*) gNB->common_vars.rxdata[ap])[2*i] = (r_re[ap][i] + (int16_t)(sqrt(sigma2/2)*gaussdouble(0.0,1.0)*512.0)); // convert to fixed point - ((short*) gNB->common_vars.rxdata[ap])[2*i+1] = (r_im[ap][i] + (int16_t)(sqrt(sigma2/2)*gaussdouble(0.0,1.0)*512.0)); + ((short*) gNB->common_vars.rxdata[ap])[2*i] = (r_re[ap][i] + (int16_t)(sqrt(sigma2/2)*gaussdouble(0.0,1.0)*(double)amp)); // convert to fixed point + ((short*) gNB->common_vars.rxdata[ap])[2*i+1] = (r_im[ap][i] + (int16_t)(sqrt(sigma2/2)*gaussdouble(0.0,1.0)*(double)amp)); } } @@ -808,23 +811,111 @@ int main(int argc, char **argv) { #endif - //---------------------------------------------------------- - //-------------------- LLRs computation -------------------- - //---------------------------------------------------------- + + uint32_t nb_re, nb_rb_per_antenna; + uint32_t rxdataF_ext_offset = 0; // [hna] should be a member in the NR_gNB_PUSCH struct + uint32_t rxdata_offset = 0; + uint32_t d_mod_offset = 0; + uint32_t llr_offset = 0; // [hna] should be a member in the NR_gNB_PUSCH struct + uint32_t start_re = frame_parms->first_carrier_offset + (start_rb * NR_NB_SC_PER_RB); + uint8_t sch_sym_start = NR_SYMBOLS_PER_SLOT - nb_symb_sch; - int sch_sym_start = NR_SYMBOLS_PER_SLOT-nb_symb_sch; - uint32_t nb_re; - uint32_t d_mod_offset = 0; - uint32_t llr_offset = 0; + void (*dft)(int16_t *,int16_t *, int); - for(symbol = sch_sym_start; symbol < 14; symbol++) { + switch (frame_parms->ofdm_symbol_size) { + case 128: + dft = dft128; + break; + + case 256: + dft = dft256; + break; + + case 512: + dft = dft512; + break; + + case 1024: + dft = dft1024; + break; + + case 1536: + dft = dft1536; + break; + + case 2048: + dft = dft2048; + break; + + case 4096: + dft = dft4096; + break; + + case 8192: + dft = dft8192; + break; + + default: + dft = dft512; + break; + } - if (symbol == 2) // [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1) - nb_re = nb_rb*6; + + for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) { + + //---------------------------------------------------------- + //-------------------------- DFT --------------------------- + //---------------------------------------------------------- + + if(symbol == 0) + rxdata_offset = frame_parms->nb_prefix_samples0; else - nb_re = nb_rb*12; + rxdata_offset = frame_parms->nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples)); - nr_ulsch_compute_llr(&ulsch_ue[0]->d_mod[d_mod_offset], + dft((int16_t *)&gNB->common_vars.rxdata[0][rxdata_offset], + (int16_t *)&gNB->common_vars.rxdataF[0][symbol*frame_parms->ofdm_symbol_size],1); + //////////////////////////////////////////////////////////// + + // [hna] start RBs extraction and llr_computation starting from sch_sym_start + if(symbol < sch_sym_start) + continue; + + if (symbol == 2) // [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1) + nb_re = nb_rb*6; + else + nb_re = nb_rb*12; + + + //---------------------------------------------------------- + //--------------------- RBs extraction --------------------- + //---------------------------------------------------------- + + nb_rb_per_antenna = nr_ulsch_extract_rbs_single(UE->common_vars.txdataF, + gNB->pusch_vars[UE_id]->rxdataF_ext, + rxdataF_ext_offset, + // rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + symbol, + start_rb, + nb_rb, + frame_parms) ; + + for(i = 0; i < nb_re; i++) + { + if(symbol != 2) + if(gNB->pusch_vars[UE_id]->rxdataF_ext[0][rxdataF_ext_offset + i] != UE->common_vars.txdataF[0][(symbol*frame_parms->ofdm_symbol_size) + ((i+start_re) % frame_parms->ofdm_symbol_size)]) + error_extraction++; + } + + rxdataF_ext_offset = rxdataF_ext_offset + nb_re; + + //////////////////////////////////////////////////////////// + + + //---------------------------------------------------------- + //-------------------- LLRs computation -------------------- + //---------------------------------------------------------- + + nr_ulsch_compute_llr(&gNB->pusch_vars[UE_id]->rxdataF_ext[0][d_mod_offset], gNB->pusch_vars[UE_id]->ul_ch_mag, gNB->pusch_vars[UE_id]->ul_ch_magb, &gNB->pusch_vars[UE_id]->llr[llr_offset], @@ -833,12 +924,12 @@ int main(int argc, char **argv) { rel15_ul->Qm); d_mod_offset = d_mod_offset + nb_re; // [hna] d_mod is incremented by nb_re - llr_offset = llr_offset + (nb_re * rel15_ul->Qm); // [hna] llr is incremented by (nb_re*mod_order) because each RE has (mod_order) coded bit (i.e LLRs) + llr_offset = llr_offset + (nb_re * rel15_ul->Qm); // [hna] llr is incremented by (nb_re*mod_order) because each RE has (mod_order) coded bits (i.e LLRs) + + //////////////////////////////////////////////////////////// } - - //////////////////////////////////////////////////////////// - + //---------------------------------------------------------- //------------------- ULSCH unscrambling ------------------- //---------------------------------------------------------- @@ -904,7 +995,7 @@ int main(int argc, char **argv) { (float) n_false_positive / (float) n_trials); printf("*****************************************\n"); - if ((float) n_errors / (float) n_trials < target_error_rate) { + if (errors_bit == 0) { printf("PUSCH test OK\n"); break; } @@ -923,7 +1014,7 @@ int main(int argc, char **argv) { printf("gNB ulsch[%d][%d]\n",UE_id, i); - free_gNB_ulsch(gNB->ulsch[UE_id][i]); + free_gNB_ulsch(gNB->ulsch[UE_id+1][i]); // "+1" because first element in ulsch is for RA for (sf = 0; sf < 2; sf++) { @@ -943,6 +1034,7 @@ int main(int argc, char **argv) { free(r_re); free(r_im); + free(txdata); if (output_fd) fclose(output_fd);