From 15417570aad27cdd027bfb1623e391029c818c04 Mon Sep 17 00:00:00 2001 From: Ahmed Hussein Date: Tue, 23 Apr 2019 20:06:19 +0200 Subject: [PATCH] Restructuring ulsim and introducing more functionalities in RX at gNB --- .../nfapi/public_inc/nfapi_nr_interface.h | 1 - openair1/PHY/INIT/nr_init.c | 10 +- openair1/PHY/MODULATION/nr_modulation.h | 17 + openair1/PHY/MODULATION/slot_fep_nr.c | 72 +++- openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h | 2 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 34 +- openair1/PHY/NR_TRANSPORT/nr_ulsch.h | 10 +- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 7 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 88 ++++- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 28 +- openair1/PHY/defs_gNB.h | 2 + openair1/SCHED_NR/phy_procedures_nr_gNB.c | 68 +++- openair1/SCHED_NR/sched_nr.h | 4 +- openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 349 +++--------------- 15 files changed, 335 insertions(+), 359 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index d53e91f666..7ce54a7957 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -694,7 +694,6 @@ typedef struct { uint8_t Qm; uint8_t ndi; uint8_t rv; - uint8_t harq_process_nbr; int8_t accumulated_delta_PUSCH; int8_t absolute_delta_PUSCH; uint8_t n_layers; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index e929720897..e2e71b0032 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -452,10 +452,14 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { gNB->dlsch[i][j]->rnti=0; LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,gNB->dlsch[i][j], gNB->dlsch[i][j]->rnti); }*/ + } + } - ///////////////////////// Initializing gNB ULSCH ///////////////////////// - LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + for (i=0; iulsch[i][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0); @@ -487,7 +491,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { LOG_D(PHY,"gNB %d.%d : RA %p\n",gNB->Mod_id,gNB->CC_id,gNB->dlsch_ra); gNB->rx_total_gain_dB=130; - for(i=0; imu_mimo_mode[i].dl_pow_off = 2; gNB->check_for_total_transmissions = 0; diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index dbe6214ff4..01b62025c2 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -24,6 +24,7 @@ #include #include "PHY/defs_nr_common.h" +#include "PHY/defs_gNB.h" #define DMRS_MOD_ORDER 2 @@ -51,4 +52,20 @@ void nr_layer_mapping(int16_t **mod_symbs, uint16_t n_symbs, int16_t **tx_layers); + +/*! +\brief This function implements the OFDM front end processor on reception (FEP) +\param phy_vars_ue Pointer to PHY variables +\param symbol symbol within slot (0..12/14) +\param Ns Slot number (0..19) +\param sample_offset offset within rxdata (points to beginning of subframe) +\param no_prefix if 1 prefix is removed by HW +*/ + +int nr_slot_fep_ul(PHY_VARS_gNB *phy_vars_gNB, + unsigned char symbol, + unsigned char Ns, + int sample_offset, + int no_prefix); + #endif \ No newline at end of file diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 7ff88612a1..1f14876b85 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -19,9 +19,10 @@ * contact@openairinterface.org */ -#include "PHY/defs_UE.h" #include "PHY/defs_nr_UE.h" +#include "PHY/defs_gNB.h" #include "modulation_UE.h" +#include "nr_modulation.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" @@ -198,3 +199,72 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, return(0); } + +int nr_slot_fep_ul(PHY_VARS_gNB *gNB, + unsigned char symbol, + unsigned char Ns, + int sample_offset, + int no_prefix) +{ + unsigned char aa; + uint32_t slot_offset; + uint32_t rxdata_offset; + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + + void (*dft)(int16_t *,int16_t *, int); + + 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; + } + + slot_offset = Ns * frame_parms->samples_per_slot; + + for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + if(symbol == 0) + rxdata_offset = slot_offset + nb_prefix_samples0 - SOFFSET; + else + rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; + + dft((int16_t *)&gNB->common_vars.rxdata[0][rxdata_offset], + (int16_t *)&gNB->common_vars.rxdataF[0][symbol * frame_parms->ofdm_symbol_size], 1); + } + + return(0); +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h index 3351b63a0d..54d4a9b6ef 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_TRANSPORT/nr_sch_dmrs.c +/*! \file PHY/NR_TRANSPORT/nr_sch_dmrs.h * \brief * \author * \date diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index f00a534966..90f6119d2b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -32,7 +32,6 @@ #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) @@ -45,15 +44,14 @@ @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 + @param harq_pid HARQ process ID */ -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); +void nr_rx_pusch(PHY_VARS_gNB *gNB, + uint8_t UE_id, + uint32_t frame, + uint8_t nr_tti_rx, + unsigned char symbol, + unsigned char harq_pid); /** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented) @@ -62,18 +60,18 @@ int nr_rx_ulsch(PHY_VARS_gNB *gNB, @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 nb_rb_pusch 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); +void 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_pusch, + NR_DL_FRAME_PARMS *frame_parms); /** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index b4c1b9822c..11521563e4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -46,7 +46,6 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8 @param nr_tti_rx, current received TTI @param harq_pid, harq process id @param is_crnti - @param llr8_flag If 1, indicate that the 8-bit decoder should be used */ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, @@ -57,8 +56,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint16_t nb_symb_sch, uint8_t nr_tti_rx, uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag); + uint8_t is_crnti); /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 @@ -75,3 +73,9 @@ void nr_ulsch_unscrambling(int16_t* llr, uint32_t Nid, uint32_t n_RNTI); + +void nr_ulsch_procedures(PHY_VARS_gNB *gNB, + gNB_L1_rxtx_proc_t *proc, + int UE_id, + uint8_t harq_pid); + diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 295fb88d50..7959f673cf 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -278,13 +278,13 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint16_t nb_symb_sch, uint8_t nr_tti_rx, uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag) + uint8_t is_crnti) { uint32_t A,E; uint32_t G; uint32_t ret,offset; + uint32_t nb_rb; int32_t no_iteration_ldpc, length_dec; uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0; uint8_t crc_type; @@ -306,7 +306,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t kc; uint8_t Ilbrm = 0; uint32_t Tbslbrm = 950984; - uint16_t nb_rb = 30; //to update uint8_t nb_re_dmrs = 6; uint16_t length_dmrs = 1; double Coderate = 0.0; @@ -341,7 +340,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, A = harq_process->TBS; ret = ulsch->max_ldpc_iterations; - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->Qm,nfapi_ulsch_pdu_rel15->n_layers); + // harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->Qm,nfapi_ulsch_pdu_rel15->n_layers); G = harq_process->G; LOG_I(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nfapi_ulsch_pdu_rel15->mcs, nfapi_ulsch_pdu_rel15->n_layers, nb_symb_sch,nb_rb); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 222db1f73d..e327f6b28d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1,49 +1,97 @@ -// 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" +#include "PHY/NR_TRANSPORT/nr_sch_dmrs.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) + +void 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_pusch, + 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; + uint32_t rxF_ext_index = 0, nb_re_pusch = 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; + nb_re_pusch = NR_NB_SC_PER_RB * nb_rb_pusch; 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++) { + for (re = 0; re < nb_re_pusch; 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 + 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[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; } } } +} + + + +void nr_rx_pusch(PHY_VARS_gNB *gNB, + uint8_t UE_id, + uint32_t frame, + uint8_t nr_tti_rx, + unsigned char symbol, + unsigned char harq_pid) +{ - return(nb_rb_pdsch/frame_parms->nb_antennas_rx); + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15; + uint32_t nb_re; + + if(symbol == rel15_ul->start_symbol) + gNB->pusch_vars[UE_id]->rxdataF_ext_offset = 0; + + if (symbol == 2) // [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1) + nb_re = rel15_ul->number_rbs * 6; + else + nb_re = rel15_ul->number_rbs * 12; + + //---------------------------------------------------------- + //--------------------- RBs extraction --------------------- + //---------------------------------------------------------- + + nr_ulsch_extract_rbs_single(gNB->common_vars.rxdataF, + gNB->pusch_vars[UE_id]->rxdataF_ext, + gNB->pusch_vars[UE_id]->rxdataF_ext_offset, + // rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + symbol, + rel15_ul->start_rb, + nb_re, + frame_parms); + + + //---------------------------------------------------------- + //-------------------- LLRs computation -------------------- + //---------------------------------------------------------- + + nr_ulsch_compute_llr(&gNB->pusch_vars[UE_id]->rxdataF_ext[0][gNB->pusch_vars[UE_id]->rxdataF_ext_offset], + gNB->pusch_vars[UE_id]->ul_ch_mag, + gNB->pusch_vars[UE_id]->ul_ch_magb, + &gNB->pusch_vars[UE_id]->llr[gNB->pusch_vars[UE_id]->rxdataF_ext_offset * rel15_ul->Qm], + nb_re, + symbol, + rel15_ul->Qm); + + gNB->pusch_vars[UE_id]->rxdataF_ext_offset = gNB->pusch_vars[UE_id]->rxdataF_ext_offset + nb_re; + } \ 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 b9d607fdc4..485252dcd5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -116,7 +116,7 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, nb_re >>= 2; // length in quad words (4 REs) nb_re += (len_mod4 == 0 ? 0 : 1); - temp_channel = _mm_set1_epi16((int16_t)((QAM64_n1 * one_over_sqrt_2)>>15)); + temp_channel = _mm_set1_epi16((int16_t)((QAM16_n1 * one_over_sqrt_2)>>15)); for (i=0; i>2; // length in quad words (4 REs) - nb_re+=((len_mod4==0)?0:1); + len_mod4 = nb_re&3; + nb_re = nb_re>>2; // length in quad words (4 REs) + nb_re += ((len_mod4 == 0) ? 0 : 1); temp_channel[0] = _mm_set1_epi16((int16_t)((QAM64_n1 * one_over_sqrt_2)>>15)); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 7fbe86eb56..7f6dd2fe6e 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -363,6 +363,8 @@ typedef struct { /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_ext2; + /// \brief Offset for calculating the index of rxdataF_ext for the current symbol + uint32_t rxdataF_ext_offset; /// \brief Hold the channel estimates in time domain based on DRS. /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index: ? [0..4*ofdm_symbol_size[ diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 364f2124fa..2d01c0df5f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -23,7 +23,9 @@ #include "PHY/defs_gNB.h" #include "sched_nr.h" #include "PHY/NR_TRANSPORT/nr_transport.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "SCHED/sched_eNB.h" #include "SCHED/sched_common_extern.h" #include "nfapi_interface.h" @@ -31,7 +33,7 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/INIT/phy_init.h" - +#include "PHY/MODULATION/nr_modulation.h" #include "T.h" #include "assertions.h" @@ -200,3 +202,67 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0); } + + +void nr_ulsch_procedures(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int UE_id, uint8_t harq_pid) { + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->ulsch_pdu; + uint8_t ret; + int Nid_cell = 0; // shouldn't be a local variable + + //---------------------------------------------------------- + //------------------- ULSCH unscrambling ------------------- + //---------------------------------------------------------- + + nr_ulsch_unscrambling(gNB->pusch_vars[UE_id]->llr, gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->G, 0, Nid_cell, rel15_ul->rnti); + + //////////////////////////////////////////////////////////// + + + //---------------------------------------------------------- + //--------------------- ULSCH decoding --------------------- + //---------------------------------------------------------- + + ret = nr_ulsch_decoding(gNB, UE_id, gNB->pusch_vars[UE_id]->llr, frame_parms, proc->frame_rx, + rel15_ul->ulsch_pdu_rel15.number_symbols, proc->slot_rx, harq_pid, 0); + + // if (ret > ulsch_gNB->max_ldpc_iterations) + // n_errors++; + +} + + +void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc) { + + uint8_t symbol; + + for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) { + nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0); + } + +} + + +void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, uint8_t symbol_start, uint8_t symbol_end) { + + uint8_t UE_id; + uint8_t symbol; + uint8_t harq_pid = 0; // [hna] Previously in LTE, the harq_pid was obtained from the subframe number (Synchronous HARQ) + // In NR, this should be signaled through uplink scheduling dci (i.e, DCI 0_0, 0_1) (Asynchronous HARQ) + + for (UE_id = 0; UE_id < NUMBER_OF_NR_UE_MAX; UE_id++) { + + + + for(symbol = symbol_start; symbol < symbol_end; symbol++) { + + nr_rx_pusch(gNB, UE_id, proc->frame_rx, proc->slot_rx, symbol, harq_pid); + + } + + nr_ulsch_procedures(gNB, proc, UE_id, harq_pid); + + } + +} diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 9d290742bf..1470510c5c 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -36,7 +36,9 @@ nr_slot_t nr_slot_select (nfapi_nr_config_request_t *cfg, unsigned char slot); void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp); -void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx,int slot_tx, int do_meas); +void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas); +void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc); +void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, uint8_t symbol_start, uint8_t symbol_end); 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); diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index ff996af506..95beaa81c5 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -546,7 +546,7 @@ int main(int argc, char **argv) { #endif ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, - frame, nb_symb_sch, subframe, harq_pid, is_crnti, llr8_flag); + frame, nb_symb_sch, subframe, harq_pid, is_crnti); if (ret > ulsch_gNB->max_ldpc_iterations) n_errors++; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 4b614a1a5f..27d62bc7e2 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -41,7 +41,6 @@ #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_REFSIG/nr_mod_table.h" #include "PHY/MODULATION/nr_modulation.h" -#include "PHY/MODULATION/modulation_eNB.h" #include "PHY/MODULATION/modulation_UE.h" #include "PHY/NR_TRANSPORT/nr_transport.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" @@ -51,13 +50,14 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "SCHED_NR/sched_nr.h" #include "PHY/TOOLS/tools_defs.h" +#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" //#include "PHY/MODULATION/modulation_common.h" //#include "common/config/config_load_configmodule.h" //#include "UTIL/LISTS/list.h" //#include "common/ran_context.h" -//#define DEBUG_ULSCHSIM +//#define DEBUG_ULSIM PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -194,14 +194,11 @@ int main(int argc, char **argv) { char c; int i,sf; - double SNR, SNR_lin, snr0 = -2.0, snr1 = 2.0; - double sigma2, sigma2_dB; + double SNR, snr0 = -2.0, snr1 = 2.0; + double sigma, sigma_dB; double snr_step = 0.1; uint8_t snr1set = 0; int slot = 0; - int **txdata; - int32_t **txdataF; - int16_t **r_re, **r_im; FILE *output_fd = NULL; //uint8_t write_output_file = 0; int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; @@ -216,22 +213,21 @@ int main(int argc, char **argv) { ulsim_params_t ulsim_params; uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; //unsigned char frame_type = 0; - int frame = 0, subframe = 0; + int frame = 0; int frame_length_complex_samples; NR_DL_FRAME_PARMS *frame_parms; - double sigma; - unsigned char qbits = 8; int ret; int loglvl = OAILOG_WARNING; uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; + int start_symbol = NR_SYMBOLS_PER_SLOT - nb_symb_sch; uint16_t nb_rb = 50; uint8_t Imcs = 9; int eNB_id = 0; int ap; int tx_offset; double txlev; - int start_rb = 0; + int start_rb = 90; cpuf = get_cpu_freq_GHz(); @@ -444,6 +440,10 @@ int main(int argc, char **argv) { RC.gNB[0][0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0][0]; //gNB_config = &gNB->gNB_config; + gNB_L1_rxtx_proc_t gNB_proc; + + gNB_proc.frame_rx = frame; + gNB_proc.slot_rx = slot; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; @@ -461,15 +461,6 @@ int main(int argc, char **argv) { frame_length_complex_samples = frame_parms->samples_per_subframe; //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; - r_re = malloc(2 * sizeof(int16_t *)); - r_im = malloc(2 * sizeof(int16_t *)); - - for (i = 0; i < 2; i++) { - r_re[i] = malloc(frame_length_complex_samples * sizeof(int16_t)); - bzero(r_re[i], frame_length_complex_samples * sizeof(int16_t)); - r_im[i] = malloc(frame_length_complex_samples * sizeof(int16_t)); - bzero(r_im[i], frame_length_complex_samples * sizeof(int16_t)); - } //configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -510,328 +501,114 @@ int main(int argc, char **argv) { ulsim_params.n_rnti = n_rnti; unsigned char harq_pid = 0; - uint8_t is_crnti = 0, llr8_flag = 0; + uint8_t is_crnti = 0; unsigned int TBS = 8424; unsigned int available_bits; uint8_t nb_re_dmrs = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4; uint16_t length_dmrs = 1; unsigned char mod_order; - NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[ulsim_params.UE_id+1][0]; - nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15; - - NR_UE_ULSCH_t **ulsch_ue = UE->ulsch[0][0]; mod_order = nr_get_Qm(Imcs, 1); available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1); TBS = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, ulsim_params.Nl); + NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[ulsim_params.UE_id+1][0]; + ulsch_gNB->harq_processes[harq_pid]->G = available_bits; // [hna] temp until length_dmrs and nb_re_dmrs are signaled + nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu; + + NR_UE_ULSCH_t **ulsch_ue = UE->ulsch[0][0]; + + printf("available bits %d TBS %d mod_order %d\n", available_bits, TBS, mod_order); - /////////// setting rel15_ul parameters /////////// - rel15_ul->number_rbs = nb_rb; - rel15_ul->number_symbols = nb_symb_sch; - rel15_ul->Qm = mod_order; - rel15_ul->mcs = Imcs; - rel15_ul->rv = ulsim_params.rvidx; - rel15_ul->n_layers = ulsim_params.Nl; + // --------- setting rel15_ul parameters ---------- + rel15_ul->rnti = n_rnti; + rel15_ul->ulsch_pdu_rel15.start_rb = start_rb; + rel15_ul->ulsch_pdu_rel15.number_rbs = nb_rb; + rel15_ul->ulsch_pdu_rel15.start_symbol = start_symbol; + rel15_ul->ulsch_pdu_rel15.number_symbols = nb_symb_sch; + rel15_ul->ulsch_pdu_rel15.Qm = mod_order; + rel15_ul->ulsch_pdu_rel15.mcs = Imcs; + rel15_ul->ulsch_pdu_rel15.rv = ulsim_params.rvidx; + rel15_ul->ulsch_pdu_rel15.n_layers = ulsim_params.Nl; /////////////////////////////////////////////////// - - double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc - short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384); - short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384); - unsigned char *estimated_output_bit; unsigned char *test_input_bit; unsigned char *test_input; - 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; - uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; + unsigned int errors_bit = 0; + uint32_t errors_scrambling = 0; test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8); test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - int UE_id = ulsim_params.UE_id; + int UE_id = ulsim_params.UE_id; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault) /////////////////////////phy_procedures_nr_ue_TX/////////////////////// /////////// - for (i = 0; i < TBS / 8; i++) test_input[i] = (unsigned char) rand(); - generate_ue_ulsch_params(UE, - &ulsim_params, - 0, - harq_pid, - test_input); - - - - nr_ue_ulsch_procedures(UE, - harq_pid, - slot, + generate_ue_ulsch_params(UE, + &ulsim_params, 0, - eNB_id); + harq_pid, + test_input); - nr_ue_pusch_common_procedures(UE, - slot, - ulsim_params.Nl, - &UE->frame_parms); + nr_ue_ulsch_procedures(UE, + harq_pid, + slot, + 0, + eNB_id); + + nr_ue_pusch_common_procedures(UE, + slot, + ulsim_params.Nl, + &UE->frame_parms); /////////// //////////////////////////////////////////////////// - tx_offset = slot*frame_parms->samples_per_slot; - txdata = UE->common_vars.txdata; - txdataF = UE->common_vars.txdataF; - for (i=0; inb_antennas_tx; ap++) { - r_re[ap][i] = ((int16_t *)txdata[ap])[(i<<1)]; - r_im[ap][i] = ((int16_t *)txdata[ap])[(i<<1)+1]; - } - } - - txlev = (double) signal_energy_amp_shift(&txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + txlev = (double) signal_energy_amp_shift(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); - txlev = txlev/512.0; // output of signal_energy is fixed point representation - + txlev = txlev/(double)AMP; // output of signal_energy is fixed point representation for (SNR = snr0; SNR < snr1; SNR += snr_step) { n_errors = 0; n_false_positive = 0; - SNR_lin = pow(10, SNR / 10.0); - sigma = 1.0 / sqrt(2 * SNR_lin); - //AWGN - sigma2_dB = 10*log10((double)txlev)-SNR; - sigma2 = pow(10,sigma2_dB/10); - + sigma_dB = 10*log10((double)txlev)-SNR; + sigma = pow(10,sigma_dB/10); 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)*(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)); + + // [hna] doesn't work with noise in case of mod_order = 6 + ((short*) gNB->common_vars.rxdata[ap])[2*i] = (((int16_t *)UE->common_vars.txdata[ap])[(i<<1)]);// + (int16_t)(sqrt(sigma/2)*gaussdouble(0.0,1.0)*(double)AMP)); // convert to fixed point + ((short*) gNB->common_vars.rxdata[ap])[2*i+1] = (((int16_t *)UE->common_vars.txdata[ap])[(i<<1)+1]);// + (int16_t)(sqrt(sigma/2)*gaussdouble(0.0,1.0)*(double)AMP)); } } - for (i = 0; i < available_bits; i++) { - -#ifdef DEBUG_CODER - if ((i&0xf)==0) - printf("\ne %d..%d: ",i,i+15); -#endif - - -//////////////////////////////////////////// -// Modulate bit-wise the scrambled output // -//////////////////////////////////////////// - - bit_index = i & 0x1f; - - if ((bit_index == 0) && (i != 0)) { - scrambling_index++; - } - - if(((scrambled_output[0][scrambling_index] >> bit_index) & 1) == 0) - modulated_input[i] = 1.0; ///sqrt(2); //QPSK - else - modulated_input[i] = -1.0; ///sqrt(2); - -//////////////////////////////////////////// - -#if 1 - channel_output_fixed[i] = (short) quantize(sigma / 4.0 / 4.0, - modulated_input[i] + sigma * gaussdouble(0.0, 1.0), - qbits); -#else - channel_output_fixed[i] = (short) quantize(0.01, modulated_input[i], qbits); -#endif - //channel_output_fixed[i] = (char)quantize8bit(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0)); - //printf("channel_output_fixed[%d]: %d\n",i,channel_output_fixed[i]); - - //Uncoded BER - if (channel_output_fixed[i] < 0) - channel_output_uncoded[i] = 1; //QPSK demod - else - channel_output_uncoded[i] = 0; - - if (channel_output_uncoded[i] != ((scrambled_output[0][scrambling_index] >> bit_index) & 1)) { - errors_bit_uncoded = errors_bit_uncoded + 1; - } - } - - printf("errors bits uncoded = %u\n", errors_bit_uncoded); - - -#ifdef DEBUG_CODER - printf("\n"); - exit(-1); -#endif + phy_procedures_gNB_common_RX(gNB, &gNB_proc); - - 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; - - void (*dft)(int16_t *,int16_t *, int); - - 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; - } - - - for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) { - - //---------------------------------------------------------- - //-------------------------- DFT --------------------------- - //---------------------------------------------------------- - - if(symbol == 0) - rxdata_offset = frame_parms->nb_prefix_samples0; - else - rxdata_offset = frame_parms->nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples)); - - 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], - nb_re, - symbol, - 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 bits (i.e LLRs) - - //////////////////////////////////////////////////////////// - } - - - //---------------------------------------------------------- - //------------------- ULSCH unscrambling ------------------- - //---------------------------------------------------------- - - nr_ulsch_unscrambling(gNB->pusch_vars[UE_id]->llr, available_bits, 0, Nid_cell, n_rnti); - - //////////////////////////////////////////////////////////// - - - //---------------------------------------------------------- - //--------------------- ULSCH decoding --------------------- - //---------------------------------------------------------- - - ret = nr_ulsch_decoding(gNB, UE_id, gNB->pusch_vars[UE_id]->llr, frame_parms, frame, - nb_symb_sch, subframe, harq_pid, is_crnti, llr8_flag); - - if (ret > ulsch_gNB->max_ldpc_iterations) - n_errors++; - - //////////////////////////////////////////////////////////// + phy_procedures_gNB_uespec_RX(gNB, &gNB_proc, rel15_ul->ulsch_pdu_rel15.start_symbol, rel15_ul->ulsch_pdu_rel15.start_symbol + rel15_ul->ulsch_pdu_rel15.number_symbols); //---------------------------------------------------------- //---------------------- count errors ---------------------- - //---------------------------------------------------------- + //---------------------------------------------------------- for (i = 0; i < TBS; i++) { @@ -867,8 +644,7 @@ int main(int argc, char **argv) { } // [hna] for (trial = 0; trial < n_trials; trial++) printf("*****************************************\n"); - printf("SNR %f, BLER %f (false positive %f)\n", SNR, - (float) n_errors / (float) n_trials, + printf("SNR %f, (false positive %f)\n", SNR, (float) n_false_positive / (float) n_trials); printf("*****************************************\n"); @@ -904,15 +680,6 @@ int main(int argc, char **argv) { printf("\n"); } - for (i = 0; i < 2; i++) { - free(r_re[i]); - free(r_im[i]); - } - - free(r_re); - free(r_im); - free(txdata); - if (output_fd) fclose(output_fd);