From b8c1129dfe279fa22e6d41e96e10366721905b3a Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 22 Aug 2023 18:51:49 +0200 Subject: [PATCH 01/43] Init RA at the right time at UE --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 5 ++++- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 54d91e9971..9328d75b37 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -71,6 +71,7 @@ void init_RA(module_id_t mod_id, ra->first_Msg3 = 1; ra->starting_preamble_nb = 0; ra->RA_backoff_cnt = 0; + ra->RA_window_cnt = -1; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; @@ -653,7 +654,9 @@ uint8_t nr_ue_get_rach(module_id_t mod_id, if (ra->ra_state > RA_UE_IDLE && ra->ra_state < RA_SUCCEEDED) { if (ra->RA_active == 0) { - /* RA not active - checking if RRC is ready to initiate the RA procedure */ + NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP.rach_ConfigCommon; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + init_RA(mod_id, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); LOG_D(NR_MAC, "In %s: RA not active. Checking for data to transmit from upper layers...\n", __FUNCTION__); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 94aff89a56..e2c7833535 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2474,7 +2474,6 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr if (is_nr_prach_slot) { AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); - init_RA(module_idP, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); nr_get_RA_window(mac); uint16_t format = prach_occasion_info_p->format; From 4ef9e17156b8d0933dd4f9d80b007a0be3473004 Mon Sep 17 00:00:00 2001 From: ajit Date: Fri, 15 Sep 2023 17:05:15 +0530 Subject: [PATCH 02/43] updating libuhd version in build_helper script --- cmake_targets/tools/build_helper | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 4f1ea858a4..4e8cfb7e68 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -326,6 +326,7 @@ check_install_usrp_uhd_driver(){ if [[ "$distribution" == "ubuntu18.04" || "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" ]]; then $SUDO apt-get remove libuhd4.0.0 -y || true $SUDO apt-get remove libuhd4.1.0 -y || true + $SUDO apt-get remove libuhd4.4.0 -y || true fi v=$(lsb_release -cs) $SUDO apt-add-repository --remove "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" @@ -355,7 +356,7 @@ check_install_usrp_uhd_driver(){ $SUDO apt-get -y install python-tk $boost_libs_ubuntu libusb-1.0-0-dev case "$(get_distribution_release)" in "ubuntu18.04" | "ubuntu20.04" | "ubuntu22.04") - $SUDO apt-get -y install libuhd-dev libuhd4.4.0 uhd-host + $SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host ;; esac elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then From 20c23475a232a621cc06525c748b7a5e94ad6e79 Mon Sep 17 00:00:00 2001 From: ajit Date: Fri, 15 Sep 2023 18:00:27 +0530 Subject: [PATCH 03/43] libuhd removal made generic in build helper --- cmake_targets/tools/build_helper | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 4e8cfb7e68..3d7b3d74ff 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -324,9 +324,7 @@ check_install_usrp_uhd_driver(){ $SUDO apt-get remove libuhd3.15.0 -y || true local distribution=$(get_distribution_release) if [[ "$distribution" == "ubuntu18.04" || "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" ]]; then - $SUDO apt-get remove libuhd4.0.0 -y || true - $SUDO apt-get remove libuhd4.1.0 -y || true - $SUDO apt-get remove libuhd4.4.0 -y || true + $SUDO apt-get remove libuhd4.?.? -y || true fi v=$(lsb_release -cs) $SUDO apt-add-repository --remove "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" From a6baa6d6f1e18d3e703bc92a1e358c68bf3a883d Mon Sep 17 00:00:00 2001 From: ajit Date: Wed, 20 Sep 2023 05:50:08 +0530 Subject: [PATCH 04/43] Changed max ofdm symbol size to 8192 for 100MHzi USRP --- openair1/PHY/defs_nr_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index ad04ee9436..c5af8b8415 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -43,7 +43,7 @@ #define nr_slot_t lte_subframe_t #define MAX_NUM_SUBCARRIER_SPACING 5 -#define NR_MAX_OFDM_SYMBOL_SIZE 4096 +#define NR_MAX_OFDM_SYMBOL_SIZE 8192 #define NR_SYMBOLS_PER_SLOT NR_NUMBER_OF_SYMBOLS_PER_SLOT From 1a42fa5326599d9c5e090558c17cb1c2f731c7b9 Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Thu, 20 Jul 2023 12:04:11 +0200 Subject: [PATCH 05/43] feat / parallelize LLR by symbol --- openair1/PHY/NR_TRANSPORT/nr_scrambling.c | 19 + .../NR_TRANSPORT/nr_transport_common_proto.h | 1 + .../PHY/NR_TRANSPORT/nr_transport_proto.h | 24 + .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 1890 +++++++++++++++++ openair1/PHY/defs_gNB.h | 35 + openair1/SCHED_NR/phy_procedures_nr_gNB.c | 33 +- openair1/SIMULATION/NR_PHY/ulsim.c | 39 +- 7 files changed, 2017 insertions(+), 24 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c index 9663b1f3d4..fd0da127c8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c +++ b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c @@ -76,3 +76,22 @@ void nr_codeword_unscrambling(int16_t* llr, uint32_t size, uint8_t q, uint32_t N } #endif } + +void nr_codeword_unscrambling_init(int16_t *s2, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI) +{ + uint32_t x1; + uint32_t x2 = (n_RNTI << 15) + (q << 14) + Nid; + uint32_t s = 0; + + uint8_t *s8=(uint8_t *)&s; + s = lte_gold_generic(&x1, &x2, 1); + simde__m128i *s128=(simde__m128i *)s2; + + for (int i = 0, j = 0; i < ((size >> 5) + ((size & 0x1f) > 0 ? 1 : 0)); i++, j += 4) { + s128[j] = byte2m128i[s8[0]]; + s128[j+1] = byte2m128i[s8[1]]; + s128[j+2] = byte2m128i[s8[2]]; + s128[j+3] = byte2m128i[s8[3]]; + s = lte_gold_generic(&x1, &x2, 0); + } +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index 5437e2e815..64ffc9a36a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -73,6 +73,7 @@ void nr_codeword_scrambling(uint8_t *in, uint32_t* out); void nr_codeword_unscrambling(int16_t* llr, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI); +void nr_codeword_unscrambling_init(int16_t *s, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI); /**@}*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 2478748688..97d32232cf 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -131,6 +131,12 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, uint8_t slot, unsigned char harq_pid); +int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, + uint8_t ulsch_id, + uint32_t frame, + uint8_t slot, + 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 @@ -209,6 +215,24 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, */ void nr_idft(int32_t *z, uint32_t Msc_PUSCH); +void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, c16_t *stream1_in, c16_t *stream0_out, c16_t *rho01, uint32_t length); + +void nr_ulsch_qam16_qam16(c16_t *stream0_in, + c16_t *stream1_in, + c16_t *ch_mag, + c16_t *ch_mag_i, + c16_t *stream0_out, + c16_t *rho01, + uint32_t length); + +void nr_ulsch_qam64_qam64(c16_t *stream0_in, + c16_t *stream1_in, + c16_t *ch_mag, + c16_t *ch_mag_i, + c16_t *stream0_out, + c16_t *rho01, + uint32_t length); + /** \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 diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 6f491ffafa..9c398d1664 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -18,6 +18,10 @@ #define INVALID_VALUE 255 +#ifdef __aarch64__ +#define USE_128BIT +#endif + void nr_idft(int32_t *z, uint32_t Msc_PUSCH) { @@ -281,6 +285,228 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) } +void nr_ulsch_extract_rbs0 (c16_t *rxdataF, + int32_t *chF, + int32_t *rxFext, + int32_t *chFext, + int rxoffset, + int choffset, + int aarx, + int is_dmrs_symbol, + nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_DL_FRAME_PARMS *frame_parms) +{ + + uint8_t delta = 0; + + int start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size; + int nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; + + + int32_t *rxF = (int32_t*)&rxdataF[rxoffset]; + int32_t *rxF_ext = &rxFext[0]; + int32_t *ul_ch0 = &chF[choffset]; + int32_t *ul_ch0_ext = &chFext[0]; + + + if (is_dmrs_symbol == 0) { + if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) { + memcpy((void*)rxF_ext, + (void*)&rxF[start_re], + nb_re_pusch*sizeof(int32_t)); + } + else + { + int neg_length = frame_parms->ofdm_symbol_size-start_re; + int pos_length = nb_re_pusch - neg_length; + memcpy((void*)rxF_ext, (void*)&rxF[start_re], neg_length * sizeof(int32_t)); + memcpy((void*)&rxF_ext[neg_length], (void*)rxF, pos_length * sizeof(int32_t)); + } + memcpy((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t)); + } + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) // 6 REs / PRB + { + AssertFatal(delta==0||delta==1,"Illegal delta %d\n",delta); + int32_t *rxF32 = &rxF[start_re]; + int32_t *rxF_ext32 = rxF_ext; + int32_t *ul_ch032 = ul_ch0; + int32_t *ul_ch0_ext32 = ul_ch0_ext; + int idx,idx2,idx3; + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { + for (idx=1-delta,idx2=0;idxofdm_symbol_size-start_re; + int pos_length = nb_re_pusch-neg_length; + + for (idx=1-delta,idx2=0;idxdmrs_config_type == pusch_dmrs_type2) // 8 REs / PRB + { + AssertFatal(delta==0||delta==2||delta==4,"Illegal delta %d\n",delta); + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { + int64_t *rxF64 = (int64_t*)&rxF[start_re]; + int64_t *rxF_ext64 = (int64_t*)rxF_ext; + int64_t *ul_ch064 = (int64_t*)ul_ch0; + int64_t *ul_ch0_ext64 = (int64_t*)ul_ch0_ext; + if (delta==0) { + for (int idx=0;idx>1;idx+=6) { + rxF_ext64[idx]=rxF64[idx+1]; + rxF_ext64[idx+1]=rxF64[idx+2]; + rxF_ext64[idx+2]=rxF64[idx+4]; + rxF_ext64[idx+3]=rxF64[idx+5]; + ul_ch0_ext64[idx]=ul_ch064[idx+1]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+4]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; + } + } + else if (delta==2) { + for (int idx=0;idx>1;idx+=6) { + rxF_ext64[idx]=rxF64[idx+0]; + rxF_ext64[idx+1]=rxF64[idx+2]; + rxF_ext64[idx+2]=rxF64[idx+3]; + rxF_ext64[idx+3]=rxF64[idx+5]; + ul_ch0_ext64[idx]=ul_ch064[idx+0]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; + } + } + else if (delta==4) { + for (int idx=0;idx>1;idx+=6) { + rxF_ext64[idx]=rxF64[idx+0]; + rxF_ext64[idx+1]=rxF64[idx+1]; + rxF_ext64[idx+2]=rxF64[idx+3]; + rxF_ext64[idx+3]=rxF64[idx+4]; + ul_ch0_ext64[idx]=ul_ch064[idx+0]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+1]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+4]; + } + } + } + else { + int neg_length = frame_parms->ofdm_symbol_size-start_re; + int pos_length = nb_re_pusch-neg_length; + if ((pos_length%12) > 0 ) pos_length+=12; + int64_t *rxF64 = (int64_t*)&rxF[start_re]; + int64_t *rxF_ext64 = (int64_t*)rxF_ext; + int64_t *ul_ch064 = (int64_t*)ul_ch0; + int64_t *ul_ch0_ext64 = (int64_t*)ul_ch0_ext; + int idx=0; + if (delta==0) { + for (idx=0;idx>1;idx+=6) { + rxF_ext64[idx] =rxF64[idx+1]; + rxF_ext64[idx+1]=rxF64[idx+2]; + rxF_ext64[idx+2]=rxF64[idx+4]; + rxF_ext64[idx+3]=rxF64[idx+5]; + ul_ch0_ext64[idx]=ul_ch064[idx+1]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+4]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; + } + if ((neg_length%12) > 0) { + rxF_ext64[idx+4]=rxF64[idx+7]; + rxF_ext64[idx+5]=rxF64[idx+8]; + ul_ch0_ext64[idx+4]=ul_ch064[idx+7]; + ul_ch0_ext64[idx+5]=ul_ch064[idx+8]; + } + rxF_ext64+=(neg_length/3); + rxF64=(int64_t*)rxF; + ul_ch0_ext64+=(neg_length/3); + ul_ch064+=(neg_length>>1); + for (idx=0;idx>1;idx+=6) { + rxF_ext64[idx] =rxF64[idx+1]; + rxF_ext64[idx+1]=rxF64[idx+2]; + rxF_ext64[idx+2]=rxF64[idx+4]; + rxF_ext64[idx+3]=rxF64[idx+5]; + ul_ch0_ext64[idx]=ul_ch064[idx+1]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+4]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; + } + } + else if (delta==2) { + for (idx=0;idx>1;idx+=6) { + rxF_ext64[idx] =rxF64[idx+0]; + rxF_ext64[idx+1]=rxF64[idx+2]; + rxF_ext64[idx+2]=rxF64[idx+3]; + rxF_ext64[idx+3]=rxF64[idx+5]; + ul_ch0_ext64[idx]=ul_ch064[idx+0]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; + } + if ((neg_length%12) > 0) { + rxF_ext64[idx+4]=rxF64[idx+6]; + rxF_ext64[idx+5]=rxF64[idx+8]; + ul_ch0_ext64[idx+4]=ul_ch064[idx+6]; + ul_ch0_ext64[idx+5]=ul_ch064[idx+8]; + } + rxF_ext64+=(neg_length/3); + rxF64=(int64_t*)rxF; + ul_ch0_ext64+=(neg_length/3); + ul_ch064+=(neg_length>>1); + for (idx=0;idx>1;idx+=6) { + rxF_ext64[idx] =rxF64[idx+0]; + rxF_ext64[idx+1]=rxF64[idx+2]; + rxF_ext64[idx+2]=rxF64[idx+3]; + rxF_ext64[idx+3]=rxF64[idx+5]; + ul_ch0_ext64[idx]=ul_ch064[idx+0]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; + } + } + else if (delta==4) { + for (idx=0;idx>1;idx+=6) { + rxF_ext64[idx] =rxF64[idx+0]; + rxF_ext64[idx+1]=rxF64[idx+1]; + rxF_ext64[idx+2]=rxF64[idx+3]; + rxF_ext64[idx+3]=rxF64[idx+4]; + ul_ch0_ext64[idx]=ul_ch064[idx+0]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+1]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+4]; + } + if ((neg_length%12) > 0) { + rxF_ext64[idx+4]=rxF64[idx+6]; + rxF_ext64[idx+5]=rxF64[idx+7]; + ul_ch0_ext64[idx+4]=ul_ch064[idx+6]; + ul_ch0_ext64[idx+5]=ul_ch064[idx+7]; + } + rxF_ext64+=(neg_length/3); + rxF64=(int64_t*)rxF; + ul_ch0_ext64+=(neg_length/3); + ul_ch064+=(neg_length>>1); + for (idx=0;idx>1;idx+=6) { + rxF_ext64[idx] =rxF64[idx+0]; + rxF_ext64[idx+1]=rxF64[idx+1]; + rxF_ext64[idx+2]=rxF64[idx+3]; + rxF_ext64[idx+3]=rxF64[idx+4]; + ul_ch0_ext64[idx]=ul_ch064[idx+0]; + ul_ch0_ext64[idx+1]=ul_ch064[idx+1]; + ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; + ul_ch0_ext64[idx+3]=ul_ch064[idx+4]; + } + } + } + } +} void nr_ulsch_extract_rbs(c16_t **rxdataF, NR_gNB_PUSCH *pusch_vars, @@ -420,6 +646,1439 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, } } +int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol) +{ + uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + if (dmrs_symbol_flag == 1) { + if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) + AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); + + if (rel15_ul->dmrs_config_type == 0) { + // if no data in dmrs cdm group is 1 only even REs have no data + // if no data in dmrs cdm group is 2 both odd and even REs have no data + return(rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6))); + } + else return(rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4))); + } else return(rel15_ul->rb_size * NR_NB_SC_PER_RB); +} + +void inner_rx_qpsk (int *rxF, + int *ul_ch, + int16_t *llr, + int aarx, + int length, + int output_shift) +{ +#ifndef USE_128BIT + register simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + + simde__m256i *rxF256 = (simde__m256i*)rxF; + simde__m256i *ulch256 = (simde__m256i*)ul_ch; + // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits + simde__m64 *llr64 = (simde__m64 *)llr; + for (int i=0; i<((length>>3)+((length&7)>0?1:0)); i++) { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); + if (aarx == 0) + { + *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,0); llr64++; + *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,1); llr64++; + *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,2); llr64++; + *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,3); llr64++; + } + else + { + *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,0))); llr64++; + *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,1))); llr64++; + *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,2))); llr64++; + *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,3))); llr64++; + } + } +#else + simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + + simde__m128i *rxF128 = (simde__m128i*)rxF; + simde__m128i *ulch128 = (simde__m128i*)ul_ch; + simde__m128i *llr128 = (simde__m128i*)llr; + for (int i = 0; i < (length >> 2); i++) { + xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); + xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); + + if (aarx == 0) + *llr128 = xmmp4; + else + *llr128 = simde_mm_add_epi16(*llr128, xmmp4); + llr128++; + } + if (length & 3) + { + int i = (length>>1) - 1; + simde__m64* llr64 = (simde__m64*)llr128; + simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4; + simde__m64 complex_shuffle64 = simde_mm_set_pi8(5, 4, 7, 6, 1, 0, 3, 2); + simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); + simde__m64 *rxF64 = (simde__m64*)rxF; + simde__m64 *ulch64 = (simde__m64*)ul_ch; + + xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); + // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); + xmm1 = simde_mm_sign_pi16(xmm1, conj64); + xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); + // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm1 = simde_mm_srai_pi32(xmm1, output_shift); + xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); + xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); + xmm4 = simde_mm_packs_pi32(xmm2, xmm3); + + if (aarx == 0) + *llr64 = xmm4; + else + *llr64 = simde_mm_add_pi16(*llr64, xmm4); + } +#endif +} + +void inner_rx_16qam (int *rxF, + int *ul_ch, + int16_t *llr, + int aarx, + int length, + int output_shift) +{ +#ifndef USE_128BIT + register simde__m256i xmmp0,xmmp1,xmmp2,xmmp3,xmmp4,xmmp5; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + + register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); // 2/sqrt(10) + simde__m256i *rxF256 = (simde__m256i*)rxF; + simde__m256i *ulch256 = (simde__m256i*)ul_ch; + // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits + simde__m64 *llr64 = (simde__m64 *)llr; + + for (int i = 0; i < ((length >> 3) + ((length & 7) > 0 ? 1 : 0)); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + // compute channel amplitude for LLR + xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); + + xmmp2 = simde_mm256_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmmp2 = simde_mm256_subs_epi16(xmmp1,xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + + xmmp3 = simde_mm256_unpacklo_epi32(xmmp4,xmmp2); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs + xmmp5 = simde_mm256_unpackhi_epi32(xmmp4,xmmp2); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + if (aarx == 0) + { + // 1st/2nd RE + llr64[0] = (simde__m64)simde_mm256_extract_epi64(xmmp3,0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I + // 3rd/4th RE + llr64[1] = (simde__m64)simde_mm256_extract_epi64(xmmp3,1); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I + // 5th/6th RE + llr64[2] = (simde__m64)simde_mm256_extract_epi64(xmmp5,0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I + // 7Rh/8th RE + llr64[3] = (simde__m64)simde_mm256_extract_epi64(xmmp5,1); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I + // 9th/10th RE + llr64[4] = (simde__m64)simde_mm256_extract_epi64(xmmp3,2); // llr32[8] low 16 bits-> y_R , high 16 bits-> y_I + // 11th/12th RE + llr64[5] = (simde__m64)simde_mm256_extract_epi64(xmmp3,3); // llr32[10] low 16 bits-> y_R , high 16 bits-> y_I + // 13th/14th RE + llr64[6] = (simde__m64)simde_mm256_extract_epi64(xmmp5,2); // llr32[12] low 16 bits-> y_R , high 16 bits-> y_I + // 15th/16th RE + llr64[7] = (simde__m64)simde_mm256_extract_epi64(xmmp5,3); // llr32[14] low 16 bits-> y_R , high 16 bits-> y_I + llr64+=8; + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0],(simde__m64)simde_mm256_extract_epi64(xmmp3,0)); + llr64[1] = simde_mm_adds_pi16(llr64[1],(simde__m64)simde_mm256_extract_epi64(xmmp3,1)); + llr64[2] = simde_mm_adds_pi16(llr64[2],(simde__m64)simde_mm256_extract_epi64(xmmp5,0)); + llr64[3] = simde_mm_adds_pi16(llr64[3],(simde__m64)simde_mm256_extract_epi64(xmmp5,1)); + llr64[4] = simde_mm_adds_pi16(llr64[4],(simde__m64)simde_mm256_extract_epi64(xmmp3,2)); + llr64[5] = simde_mm_adds_pi16(llr64[5],(simde__m64)simde_mm256_extract_epi64(xmmp3,3)); + llr64[6] = simde_mm_adds_pi16(llr64[6],(simde__m64)simde_mm256_extract_epi64(xmmp5,2)); + llr64[7] = simde_mm_adds_pi16(llr64[7],(simde__m64)simde_mm256_extract_epi64(xmmp5,3)); + llr64 += 8; + } + } +#else + simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp5; + register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + + register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM16_n1); // 2/sqrt(10) + simde__m128i *rxF128 = (simde__m128i*)rxF; + simde__m128i *ulch128 = (simde__m128i*)ul_ch; + // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits + simde__m64 *llr64 = (simde__m64 *)llr; + + for (int i = 0; i < (length >> 2); i++) + { + xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); + xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); + + // compute channel amplitude for LLR + xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm_mulhrs_epi16(xmmp1, QAM_amp128); + + xmmp2 = simde_mm_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmmp2 = simde_mm_subs_epi16(xmmp1, xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + + xmmp3 = simde_mm_unpacklo_epi32(xmmp4, xmmp2); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs + xmmp5 = simde_mm_unpackhi_epi32(xmmp4, xmmp2); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + if (aarx == 0) + { + llr64[0] = (simde__m64)simde_mm_extract_epi64(xmmp3, 0); // llr32[0] low 16 bits-> y_R, high 16 bits-> y_I + llr64[1] = (simde__m64)simde_mm_extract_epi64(xmmp3, 1); // llr32[2] low 16 bits-> y_R, high 16 bits-> y_I + llr64[2] = (simde__m64)simde_mm_extract_epi64(xmmp5, 0); // llr32[4] low 16 bits-> y_R, high 16 bits-> y_I + llr64[3] = (simde__m64)simde_mm_extract_epi64(xmmp5, 1); // llr32[6] low 16 bits-> y_R, high 16 bits-> y_I + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0], (simde__m64)simde_mm_extract_epi64(xmmp3, 0)); + llr64[1] = simde_mm_adds_pi16(llr64[1], (simde__m64)simde_mm_extract_epi64(xmmp3, 1)); + llr64[2] = simde_mm_adds_pi16(llr64[2], (simde__m64)simde_mm_extract_epi64(xmmp5, 0)); + llr64[3] = simde_mm_adds_pi16(llr64[3], (simde__m64)simde_mm_extract_epi64(xmmp5, 1)); + } + llr64 += 4; + } + if (length & 3) + { + int i = (length>>1) - 1; + simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4; + simde__m64 complex_shuffle64 = simde_mm_set_pi8(5,4,7,6,1,0,3,2); + simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); + simde__m64 *rxF64 = (simde__m64*)rxF; + simde__m64 *ulch64 = (simde__m64*)ul_ch; + simde__m64 QAM_amp = simde_mm_set1_pi16(QAM16_n1); + + xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); + // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); + xmm1 = simde_mm_sign_pi16(xmm1, conj64); + xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); + // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm1 = simde_mm_srai_pi32(xmm1, output_shift); + xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); + xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); + xmm4 = simde_mm_packs_pi32(xmm2, xmm3); + + // compute channel amplitude for LLR + xmm0 = simde_mm_madd_pi16(ulch64[i], ulch64[i]); // |h|^2 + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm0 = simde_mm_packs_pi32(xmm0, xmm0); + xmm2 = simde_mm_unpacklo_pi16(xmm0, xmm0); + + xmm1 = simde_mm_mulhrs_pi16(xmm2, QAM_amp); + + xmm0 = simde_mm_abs_pi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm_subs_pi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + if (aarx == 0) + { + llr64[0] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0), simde_mm_extract_pi16(xmm4, 0)); + llr64[1] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 1), simde_mm_extract_pi16(xmm4, 1)); + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0], simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0),simde_mm_extract_pi16(xmm4, 0))); + llr64[1] = simde_mm_adds_pi16(llr64[1], simde_mm_set_pi32(simde_mm_extract_pi16(xmm4, 1),simde_mm_extract_pi16(xmm1, 0))); + } + } + +#endif +} + +void inner_rx_64qam (int *restrict rxF, + int *restrict ul_ch, + int16_t *restrict llr, + int aarx, + int length, + int output_shift) +{ +#ifndef USE_128BIT + register simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp6, xmmp7; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29, 28, 31, 30, 25, 24, 27, 26, 21, 20, 23, 22, 17, 16, 19, 18, 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m256i conj256 = simde_mm256_set_epi16(1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1); + + register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) + register simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM64_n2); + simde__m256i *rxF256 = (simde__m256i*)rxF; + simde__m256i *ulch256 = (simde__m256i*)ul_ch; + // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits + + simde__m64 *llr64 = (simde__m64 *)llr; + for (int i=0;i<((length>>3)+((length&7)>0?1:0));i++) { + xmmp0 = simde_mm256_madd_epi16(ulch256[i],rxF256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i],complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1,conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1,rxF256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1,output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0,xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0,xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); + + // compute channel amplitude for LLR + xmmp0 = simde_mm256_madd_epi16(ulch256[i],ulch256[i]); + xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0,xmmp0); + xmmp2 = simde_mm256_unpacklo_epi16(xmmp0,xmmp0); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256); + xmmp6 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256b); + + xmmp2 = simde_mm256_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmmp2 = simde_mm256_subs_epi16(xmmp1,xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + xmmp7 = simde_mm256_abs_epi16(xmmp2); + xmmp7 = simde_mm256_subs_epi16(xmmp6,xmmp7); + + if (aarx == 0) + { + llr64[0] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,0),simde_mm256_extract_epi32(xmmp4,0)); + llr64[1] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,1),simde_mm256_extract_epi32(xmmp7,0)); + llr64[2] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,1),simde_mm256_extract_epi32(xmmp2,1)); + llr64[3] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,2),simde_mm256_extract_epi32(xmmp4,2)); + llr64[4] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,3),simde_mm256_extract_epi32(xmmp7,2)); + llr64[5] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,3),simde_mm256_extract_epi32(xmmp2,3)); + llr64[6] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,4),simde_mm256_extract_epi32(xmmp4,4)); + llr64[7] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,5),simde_mm256_extract_epi32(xmmp7,4)); + llr64[8] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,5),simde_mm256_extract_epi32(xmmp2,5)); + llr64[9] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,6),simde_mm256_extract_epi32(xmmp4,6)); + llr64[10] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,7),simde_mm256_extract_epi32(xmmp7,6)); + llr64[11] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,7),simde_mm256_extract_epi32(xmmp2,7)); + llr64+=12; + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,0),simde_mm256_extract_epi32(xmmp4,0))); + llr64[1] = simde_mm_adds_pi16(llr64[1],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,1),simde_mm256_extract_epi32(xmmp7,0))); + llr64[2] = simde_mm_adds_pi16(llr64[2],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,1),simde_mm256_extract_epi32(xmmp2,1))); + llr64[3] = simde_mm_adds_pi16(llr64[3],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,2),simde_mm256_extract_epi32(xmmp4,2))); + llr64[4] = simde_mm_adds_pi16(llr64[4],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,3),simde_mm256_extract_epi32(xmmp7,2))); + llr64[5] = simde_mm_adds_pi16(llr64[5],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,3),simde_mm256_extract_epi32(xmmp2,3))); + llr64[6] = simde_mm_adds_pi16(llr64[6],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,4),simde_mm256_extract_epi32(xmmp4,4))); + llr64[7] = simde_mm_adds_pi16(llr64[7],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,5),simde_mm256_extract_epi32(xmmp7,4))); + llr64[8] = simde_mm_adds_pi16(llr64[8],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,5),simde_mm256_extract_epi32(xmmp2,5))); + llr64[9] = simde_mm_adds_pi16(llr64[9],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,6),simde_mm256_extract_epi32(xmmp4,6))); + llr64[10] = simde_mm_adds_pi16(llr64[10],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,7),simde_mm256_extract_epi32(xmmp7,6))); + llr64[11] = simde_mm_adds_pi16(llr64[11],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,7),simde_mm256_extract_epi32(xmmp2,7))); + llr64+=12; + } + } +#else + register simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp6, xmmp7; + register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + // register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM64_n1); // 4/sqrt(42) + register simde__m128i QAM_amp128b = simde_mm_set1_epi16(QAM64_n2); // 2/sqrt(42) + simde__m128i *rxF128 = (simde__m128i*) rxF; + simde__m128i *ulch128 = (simde__m128i*) ul_ch; + // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits + simde__m64 *llr64 = (simde__m64 *)llr; + for (int i = 0; i < (length>>2); i++) + { + xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); + xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); + + // compute channel amplitude for LLR + xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); + xmmp2 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm_mulhrs_epi16(xmmp2, QAM_amp128); + xmmp6 = simde_mm_mulhrs_epi16(xmmp2, QAM_amp128b); + + xmmp2 = simde_mm_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmmp2 = simde_mm_subs_epi16(xmmp1, xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + xmmp7 = simde_mm_abs_epi16(xmmp2); + xmmp7 = simde_mm_subs_epi16(xmmp6, xmmp7); + + if (aarx == 0) + { + llr64[0] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 0), simde_mm_extract_epi32(xmmp4, 0)); + llr64[1] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 1), simde_mm_extract_epi32(xmmp7, 0)); + llr64[2] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 1), simde_mm_extract_epi32(xmmp2, 1)); + llr64[3] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 2), simde_mm_extract_epi32(xmmp4, 2)); + llr64[4] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 3), simde_mm_extract_epi32(xmmp7, 2)); + llr64[5] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 3), simde_mm_extract_epi32(xmmp2, 3)); + llr64 += 6; + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 0),simde_mm_extract_epi32(xmmp4, 0))); + llr64[1] = simde_mm_adds_pi16(llr64[1], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 1),simde_mm_extract_epi32(xmmp7, 0))); + llr64[2] = simde_mm_adds_pi16(llr64[2], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 1),simde_mm_extract_epi32(xmmp2, 1))); + llr64[3] = simde_mm_adds_pi16(llr64[3], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 2),simde_mm_extract_epi32(xmmp4, 2))); + llr64[4] = simde_mm_adds_pi16(llr64[4], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 3),simde_mm_extract_epi32(xmmp7, 2))); + llr64[5] = simde_mm_adds_pi16(llr64[5], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 3),simde_mm_extract_epi32(xmmp2, 3))); + llr64 += 6; + } + } + if (length & 3) + { + int i = (length>>1) - 1; + simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5; + simde__m64 complex_shuffle64 = simde_mm_set_pi8(5,4,7,6,1,0,3,2); + simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); + simde__m64 *rxF64 = (simde__m64*)rxF; + simde__m64 *ulch64 = (simde__m64*)ul_ch; + simde__m64 QAM_amp = simde_mm_set1_pi16(QAM64_n1); + simde__m64 QAM_ampb = simde_mm_set1_pi16(QAM64_n2); + + xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); + // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); + xmm1 = simde_mm_sign_pi16(xmm1, conj64); + xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); + // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm1 = simde_mm_srai_pi32(xmm1, output_shift); + xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); + xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); + xmm4 = simde_mm_packs_pi32(xmm2, xmm3); + + // compute channel amplitude for LLR + xmm0 = simde_mm_madd_pi16(ulch64[i], ulch64[i]); // |h|^2 + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm0 = simde_mm_packs_pi32(xmm0, xmm0); + xmm2 = simde_mm_unpacklo_pi16(xmm0, xmm0); + + xmm1 = simde_mm_mulhrs_pi16(xmm2, QAM_amp); + xmm5 = simde_mm_mulhrs_pi16(xmm2, QAM_ampb); + + xmm0 = simde_mm_abs_pi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm_subs_pi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + xmm1 = simde_mm_abs_pi16(xmm0); + xmm1 = simde_mm_subs_pi16(xmm5, xmm1); // contains 8 LLRs + if (aarx == 0) + { + llr64[0] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0), simde_mm_extract_pi16(xmm4, 0)); + llr64[1] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm4, 1), simde_mm_extract_pi16(xmm1, 0)); + llr64[2] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm1, 1), simde_mm_extract_pi16(xmm0, 1)); + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0], simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0),simde_mm_extract_pi16(xmm4, 0))); + llr64[1] = simde_mm_adds_pi16(llr64[1], simde_mm_set_pi32(simde_mm_extract_pi16(xmm4, 1),simde_mm_extract_pi16(xmm1, 0))); + llr64[2] = simde_mm_adds_pi16(llr64[2], simde_mm_set_pi32(simde_mm_extract_pi16(xmm1, 1),simde_mm_extract_pi16(xmm0, 1))); + } + } +#endif +} + +void inner_rx_256qam (int *rxF, + int *ul_ch, + int16_t *llr, + int aarx, + int length, + int output_shift) +{ +#ifndef USE_128BIT + register simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp5, xmmp6, xmmp7, xmmp8, xmmp9; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + + register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM256_n1); + register simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM256_n2); + register simde__m256i QAM_amp256c = simde_mm256_set1_epi16(QAM256_n3); + simde__m256i *rxF256 = (simde__m256i*)rxF; + simde__m256i *ulch256 = (simde__m256i*)ul_ch; + simde__m256i *llr256 = (simde__m256i *)llr; + for (int i = 0; i < ((length >> 3) + (( length & 7) > 0 ? 1 : 0)); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i],rxF256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i],complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1,conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1,rxF256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1,output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0,xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0,xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); + + // compute channel amplitude for LLR + xmmp0 = simde_mm256_madd_epi16(ulch256[i],ulch256[i]); + xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0,xmmp0); // contains 16 LLRs + xmmp2 = simde_mm256_unpacklo_epi16(xmmp0,xmmp0); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256); + xmmp6 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256b); + xmmp8 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256c); + + xmmp2 = simde_mm256_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmmp2 = simde_mm256_subs_epi16(xmmp1,xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + // xmmp2 contains 16 LLRs + xmmp7 = simde_mm256_abs_epi16(xmmp2); + xmmp7 = simde_mm256_subs_epi16(xmmp6,xmmp7); // contains 16 LLRs + xmmp9 = simde_mm256_abs_epi16(xmmp7); + xmmp9 = simde_mm256_subs_epi16(xmmp8,xmmp9); // contains 16 LLRs + + // xmmp4 A0 A1 A2 A3 A4 A5 A6 A7 + // xmmp2 B0 B1 B2 B3 B4 B5 B6 B7 + // xmmp7 C0 C1 C2 C3 C4 C5 C6 C7 + // xmmp9 D0 D1 D2 D3 D4 D5 D6 D7 + xmmp1 = simde_mm256_unpacklo_epi32(xmmp4,xmmp2); // A0 B0 A1 B1 A4 B4 A5 B5 + xmmp3 = simde_mm256_unpackhi_epi32(xmmp4,xmmp2); // A2 B2 A3 B3 A6 B6 A7 B7 + xmmp5 = simde_mm256_unpacklo_epi32(xmmp7,xmmp9); // C0 D0 C1 D1 C4 D4 C5 D5 + xmmp6 = simde_mm256_unpackhi_epi32(xmmp7,xmmp9); // C2 D2 C3 D3 C6 D6 C7 D7 + + xmmp2 = simde_mm256_unpacklo_epi64(xmmp1,xmmp5); // A0 B0 C0 D0 A4 B4 C4 D4 + xmmp4 = simde_mm256_unpackhi_epi64(xmmp1,xmmp5); // A1 B1 C1 D1 A5 B5 C5 D5 + xmmp1 = simde_mm256_unpacklo_epi64(xmmp3,xmmp6); // A2 B2 C2 D2 A6 B6 C6 D6 + xmmp5 = simde_mm256_unpackhi_epi64(xmmp3,xmmp6); // A3 B3 C3 D3 A7 B7 C7 D7 + if (aarx == 0) + { + llr256[0] = simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1 + llr256[1] = simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3 + llr256[2] = simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5 + llr256[3] = simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7 + llr256+=4; + } + else + { + llr256[0] = simde_mm256_adds_epi16(llr256[0],simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x20)); // A0 B0 C0 D0 A1 B1 C1 D1 + llr256[1] = simde_mm256_adds_epi16(llr256[1],simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x20)); // A2 B2 C2 D2 A3 B3 C3 D3 + llr256[2] = simde_mm256_adds_epi16(llr256[2],simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x31)); // A4 B4 C4 D4 A5 B5 C5 D5 + llr256[3] = simde_mm256_adds_epi16(llr256[3],simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x31)); // A6 B6 C6 D6 A7 B7 C7 D7 + llr256+=4; + } + } + simde__m128i *llr128 = (simde__m128i*)llr256; + if ((length&7) >= 4) { //there is a single 128-bit input element remaining + int nb_re128 = length>>2; + simde__m128i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; + simde__m128i complex_shuffle128 = simde_mm_set_epi8(13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m128i conj128 = simde_mm_set_epi16(1,-1,1,-1,1,-1,1,-1); + simde__m128i *rxF128 = (simde__m128i*)rxF; + simde__m128i *ulch128 = (simde__m128i*)ul_ch; + simde__m128i QAM_amp = simde_mm_set1_epi16(QAM256_n1); // 2/sqrt(10) + simde__m128i QAM_ampb = simde_mm_set1_epi16(QAM256_n2); + simde__m128i QAM_ampc = simde_mm_set1_epi16(QAM256_n3); + + xmm0 = simde_mm_madd_epi16(ulch128[nb_re128-1],rxF128[nb_re128-1]); + // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm1 = simde_mm_shuffle_epi8(ulch128[nb_re128-1],complex_shuffle128); + xmm1 = simde_mm_sign_epi16(xmm1,conj128); + xmm1 = simde_mm_madd_epi16(xmm1,rxF128[nb_re128-1]); + // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm0 = simde_mm_srai_epi32(xmm0,output_shift); + xmm1 = simde_mm_srai_epi32(xmm1,output_shift); + xmm2 = simde_mm_unpacklo_epi32(xmm0,xmm1); + xmm3 = simde_mm_unpackhi_epi32(xmm0,xmm1); + xmm4 = simde_mm_packs_epi32(xmm2,xmm3); + + // compute channel amplitude for LLR + xmm0 = simde_mm_madd_epi16(ulch128[nb_re128-1],ulch128[nb_re128-1]); + xmm0 = simde_mm_srai_epi32(xmm0,output_shift); + xmm0 = simde_mm_packs_epi32(xmm0,xmm0); // contains 16 LLRs + xmm2 = simde_mm_unpacklo_epi16(xmm0,xmm0); + xmm1 = simde_mm_mulhrs_epi16(xmm2,QAM_amp); + xmm5 = simde_mm_mulhrs_epi16(xmm2,QAM_ampb); + xmm6 = simde_mm_mulhrs_epi16(xmm2,QAM_ampc); + xmm0 = simde_mm_abs_epi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm_subs_epi16(xmm1,xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + // xmmp2 contains 8 LLRs + xmm1 = simde_mm_abs_epi16(xmm0); + xmm1 = simde_mm_subs_epi16(xmm5,xmm1); // contains 8 LLRs + xmm2 = simde_mm_abs_epi16(xmm1); + xmm2 = simde_mm_subs_epi16(xmm6,xmm2); // contains 8 LLRs + // rxF[i] A0 A1 A2 A3 + // xmm0 B0 B1 B2 B3 + // xmm1 C0 C1 C2 C3 + // xmm2 D0 D1 D2 D3 + xmm3 = simde_mm_unpacklo_epi32(rxF128[nb_re128-1],xmm0); // A0 B0 A1 B1 + xmm4 = simde_mm_unpackhi_epi32(rxF128[nb_re128-1],xmm0); // A2 B2 A3 B3 + xmm5 = simde_mm_unpacklo_epi32(xmm1,xmm2); // C0 D0 C1 D1 + xmm6 = simde_mm_unpackhi_epi32(xmm1,xmm2); // C2 D2 C3 D3 + if (aarx == 0) { + llr128[0] = simde_mm_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0 + llr128[1] = simde_mm_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1 + llr128[2] = simde_mm_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2 + llr128[3] = simde_mm_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3 + llr128+=4; + } + else + { + llr128[0] = simde_mm_adds_epi16(llr128[0],simde_mm_unpacklo_epi64(xmm3,xmm5)); // A0 B0 C0 D0 + llr128[1] = simde_mm_adds_epi16(llr128[1],simde_mm_unpackhi_epi64(xmm3,xmm5)); // A1 B1 C1 D1 + llr128[2] = simde_mm_adds_epi16(llr128[2],simde_mm_unpacklo_epi64(xmm4,xmm6)); // A2 B2 C2 D2 + llr128[3] = simde_mm_adds_epi16(llr128[3],simde_mm_unpackhi_epi64(xmm4,xmm6)); // A3 B3 C3 D3 + llr128+=4; + } + } +#else + simde__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; + simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + simde__m128i *rxF128 = (simde__m128i*)rxF; + simde__m128i *ulch128 = (simde__m128i*)ul_ch; + simde__m128i QAM_amp = simde_mm_set1_epi16(QAM256_n1); + simde__m128i QAM_ampb = simde_mm_set1_epi16(QAM256_n2); + simde__m128i QAM_ampc = simde_mm_set1_epi16(QAM256_n3); + simde__m128i *llr128 = (simde__m128i*)llr; + for (int i = 0; i < (length >> 2); i++) + { + xmm0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmm1 = simde_mm_sign_epi16(xmm1, conj128); + xmm1 = simde_mm_madd_epi16(xmm1, rxF128[i]); + // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm0 = simde_mm_srai_epi32(xmm0, output_shift); + xmm1 = simde_mm_srai_epi32(xmm1, output_shift); + xmm2 = simde_mm_unpacklo_epi32(xmm0, xmm1); + xmm3 = simde_mm_unpackhi_epi32(xmm0, xmm1); + xmm4 = simde_mm_packs_epi32(xmm2, xmm3); + + // compute channel amplitude for LLR + xmm0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 + xmm0 = simde_mm_srai_epi32(xmm0, output_shift); + xmm0 = simde_mm_packs_epi32(xmm0, xmm0); + xmm2 = simde_mm_unpacklo_epi16(xmm0, xmm0); + + xmm1 = simde_mm_mulhrs_epi16(xmm2, QAM_amp); + xmm5 = simde_mm_mulhrs_epi16(xmm2, QAM_ampb); + xmm6 = simde_mm_mulhrs_epi16(xmm2, QAM_ampc); + + xmm0 = simde_mm_abs_epi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm_subs_epi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + xmm1 = simde_mm_abs_epi16(xmm0); + xmm1 = simde_mm_subs_epi16(xmm5, xmm1); // contains 8 LLRs + xmm2 = simde_mm_abs_epi16(xmm1); + xmm2 = simde_mm_subs_epi16(xmm6, xmm2); // contains 8 LLRs + // rxF[i] A0 A1 A2 A3 + // xmm0 B0 B1 B2 B3 + // xmm1 C0 C1 C2 C3 + // xmm2 D0 D1 D2 D3 + xmm3 = simde_mm_unpacklo_epi32(xmm4, xmm0); // A0 B0 A1 B1 + xmm4 = simde_mm_unpackhi_epi32(xmm4, xmm0); // A2 B2 A3 B3 + xmm5 = simde_mm_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 + xmm6 = simde_mm_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 + if (aarx == 0) { + llr128[0] = simde_mm_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 + llr128[1] = simde_mm_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 + llr128[2] = simde_mm_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2 + llr128[3] = simde_mm_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3 + } + else { + llr128[0] = simde_mm_adds_epi16(llr128[0], simde_mm_unpacklo_epi64(xmm3, xmm5)); // A0 B0 C0 D0 + llr128[1] = simde_mm_adds_epi16(llr128[1], simde_mm_unpackhi_epi64(xmm3, xmm5)); // A1 B1 C1 D1 + llr128[2] = simde_mm_adds_epi16(llr128[2], simde_mm_unpacklo_epi64(xmm4, xmm6)); // A2 B2 C2 D2 + llr128[3] = simde_mm_adds_epi16(llr128[3], simde_mm_unpackhi_epi64(xmm4, xmm6)); // A3 B3 C3 D3 + } + llr128+=4; + } + if (length & 3) + { + simde__m64 *llr64 = (simde__m64*) llr128; + int i = (length>>1) - 1; + simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; + simde__m64 complex_shuffle64 = simde_mm_set_pi8(5,4,7,6,1,0,3,2); + simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); + simde__m64 *rxF64 = (simde__m64*)rxF; + simde__m64 *ulch64 = (simde__m64*)ul_ch; + simde__m64 QAM_amp = simde_mm_set1_pi16(QAM256_n1); + simde__m64 QAM_ampb = simde_mm_set1_pi16(QAM256_n2); + simde__m64 QAM_ampc = simde_mm_set1_pi16(QAM256_n3); + + xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); + // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); + xmm1 = simde_mm_sign_pi16(xmm1, conj64); + xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); + // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm1 = simde_mm_srai_pi32(xmm1, output_shift); + xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); + xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); + xmm4 = simde_mm_packs_pi32(xmm2, xmm3); + + // compute channel amplitude for LLR + xmm0 = simde_mm_madd_pi16(ulch64[i], ulch64[i]); // |h|^2 + xmm0 = simde_mm_srai_pi32(xmm0, output_shift); + xmm0 = simde_mm_packs_pi32(xmm0, xmm0); + xmm2 = simde_mm_unpacklo_pi16(xmm0, xmm0); + + xmm1 = simde_mm_mulhrs_pi16(xmm2, QAM_amp); + xmm5 = simde_mm_mulhrs_pi16(xmm2, QAM_ampb); + xmm6 = simde_mm_mulhrs_pi16(xmm2, QAM_ampc); + + xmm0 = simde_mm_abs_pi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm_subs_pi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + xmm1 = simde_mm_abs_pi16(xmm0); + xmm1 = simde_mm_subs_pi16(xmm5, xmm1); // contains 8 LLRs + xmm2 = simde_mm_abs_pi16(xmm1); + xmm2 = simde_mm_subs_pi16(xmm6, xmm2); // contains 8 LLRs + + xmm3 = simde_mm_unpacklo_pi32(xmm4, xmm0); + xmm4 = simde_mm_unpackhi_pi32(xmm4, xmm0); + xmm5 = simde_mm_unpacklo_pi32(xmm1, xmm2); + xmm6 = simde_mm_unpackhi_pi32(xmm1, xmm2); + if (aarx == 0) { + llr64[0] = simde_m_punpckldq(xmm3, xmm5); + llr64[1] = simde_m_punpckhdq(xmm3, xmm5); + llr64[2] = simde_m_punpckldq(xmm4, xmm6); + llr64[3] = simde_m_punpckhdq(xmm4, xmm6); + } + else + { + llr64[0] = simde_mm_adds_pi16(llr64[0], simde_m_punpckldq(xmm3, xmm5)); + llr64[1] = simde_mm_adds_pi16(llr64[1], simde_m_punpckhdq(xmm3, xmm5)); + llr64[2] = simde_mm_adds_pi16(llr64[2], simde_m_punpckldq(xmm4, xmm6)); + llr64[3] = simde_mm_adds_pi16(llr64[3], simde_m_punpckhdq(xmm4, xmm6)); + } + } +#endif +} + +void inner_rx_qpsk_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + int **rxF, + int **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int add_shift = 0; + if (length % 8) + add_shift = 8 - length % 8; + int32_t rxFext[nb_rx_ant][length + add_shift] __attribute__((aligned(32))); + int32_t chFext[nb_layer*nb_rx_ant][length + add_shift] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int aatx = 0; aatx < nb_layer; aatx++) + { + nr_ulsch_extract_rbs0((c16_t *)rxF[aarx], + pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx * nb_rx_ant + aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + int32_t rho[nb_layer*nb_layer][length + add_shift] __attribute__((aligned(32))); + int32_t rxFext_comp[nb_layer][length + add_shift] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int aatx = 0; aatx < nb_layer; aatx++) + { + for (int atx = 0; atx < nb_layer; atx++) + { +#ifdef USE_128BIT + simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, mmtmpD4; + simde__m128i *rho128 = (simde__m128i *)rho[aatx*nb_layer+atx]; + simde__m128i *ul_ch128 = (simde__m128i *)chFext[aatx * nb_rx_ant + aarx]; + simde__m128i *ul_ch128_2 = (simde__m128i *)chFext[atx * nb_rx_ant + aarx]; + for (int i = 0; i < (length >> 2)+((length&3)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm_madd_epi16(ul_ch128[i], ul_ch128_2[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[i], SIMDE_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i*)&conjugate[0]); + mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, ul_ch128_2[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); + mmtmpD4 = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); + if (aarx == 0) + rho128[i] = mmtmpD4; + else + rho128[i] = simde_mm_adds_epi16(rho128[i], mmtmpD4); + } +#else + simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, mmtmpD4; + simde__m256i *rho256 = (simde__m256i *)rho[aatx*nb_layer+atx]; + simde__m256i *ul_ch256 = (simde__m256i *)chFext[aatx * nb_rx_ant + aarx]; + simde__m256i *ul_ch256_2 = (simde__m256i *)chFext[atx * nb_rx_ant + aarx]; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + for (int i = 0; i < ((length >> 3)+((length&7)?1:0)); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm256_madd_epi16(ul_ch256[i], ul_ch256_2[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm256_shuffle_epi8(ul_ch256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, ul_ch256_2[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + mmtmpD4 = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); + if (aarx == 0) + rho256[i] = mmtmpD4; + else + rho256[i] = simde_mm256_adds_epi16(rho256[i], mmtmpD4); + } +#endif + } + // compensation +#ifdef USE_128BIT + simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + simde__m128i *rxF128 = (simde__m128i*)rxFext[aarx]; + simde__m128i *ulch128 = (simde__m128i*)chFext[aatx * nb_rx_ant + aarx]; + simde__m128i *rxF_comp128 = (simde__m128i*)rxFext_comp[aatx]; + for (int i = 0; i < (length>>2) + ((length&3)?1:0); i++) + { + xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); + xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); + + if (aarx == 0) + *rxF_comp128 = xmmp4; + else + *rxF_comp128 = simde_mm_adds_epi16(*rxF_comp128, xmmp4); + + rxF_comp128++; + } +#else + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *ulch256 = (simde__m256i*)chFext[aatx * nb_rx_ant + aarx]; + simde__m256i *rxF_comp256 = (simde__m256i*)rxFext_comp[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + if (aarx == 0) + *rxF_comp256 = xmmp4; + else + *rxF_comp256 = simde_mm256_adds_epi16(*rxF_comp256, xmmp4); + + rxF_comp256++; + } +#endif + } + } + c16_t *rho0 = (c16_t *)rho[1]; + c16_t *rho1 = (c16_t *)rho[2]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + + nr_ulsch_qpsk_qpsk((c16_t *)rxFext_comp[0], (c16_t *)rxFext_comp[1], llr_0, rho0, length); + nr_ulsch_qpsk_qpsk((c16_t *)rxFext_comp[1], (c16_t *)rxFext_comp[0], llr_1, rho1, length); + + nr_ulsch_shift_llr(pusch_vars->llr_layers, length, pusch_vars->llr_offset[symbol] >> 1, 2, 4); + +} + + +void inner_rx_16qam_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + int **rxF, + int **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int add_shift = 0; + if (length % 8) + add_shift = 8 - length % 8; + + int32_t rxFext[nb_rx_ant][length + add_shift] __attribute__((aligned(32))); + int32_t chFext[nb_layer*nb_rx_ant][length + add_shift] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int aatx = 0; aatx < nb_layer; aatx++) + { + nr_ulsch_extract_rbs0((c16_t *)rxF[aarx], + pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx * nb_rx_ant + aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + + int32_t rho[nb_layer*nb_layer][length + add_shift] __attribute__((aligned(32))); + int32_t rxFext_comp[nb_layer][length + add_shift] __attribute__((aligned(32))); + int32_t ul_ch_mag[nb_layer][length + add_shift] __attribute__((aligned(32))); + for (int aatx = 0; aatx < nb_layer; aatx++) + { + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int atx = 0; atx < nb_layer; atx++) + { +#ifdef USE_128BIT + simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + simde__m128i *rho128 = (simde__m128i *)rho[aatx*nb_layer+atx]; + simde__m128i *ul_ch128 = (simde__m128i *)chFext[aatx * nb_rx_ant + aarx]; + simde__m128i *ul_ch128_2 = (simde__m128i *)chFext[atx * nb_rx_ant + aarx]; + for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm_madd_epi16(ul_ch128[i], ul_ch128_2[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[i], SIMDE_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i*)&conjugate[0]); + mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, ul_ch128_2[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); + if (aarx == 0) + rho128[i] = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); + else + rho128[i] = simde_mm_adds_epi16(rho128[i], simde_mm_packs_epi32(mmtmpD2, mmtmpD3)); + } +#else + simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + simde__m256i *rho256 = (simde__m256i *)rho[aatx*nb_layer+atx]; + simde__m256i *ul_ch256 = (simde__m256i *)chFext[aatx * nb_rx_ant + aarx]; + simde__m256i *ul_ch256_2 = (simde__m256i *)chFext[atx * nb_rx_ant + aarx]; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm256_madd_epi16(ul_ch256[i], ul_ch256_2[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm256_shuffle_epi8(ul_ch256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, ul_ch256_2[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + if (aarx == 0) + rho256[i] = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); + else + rho256[i] = simde_mm256_adds_epi16(rho256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); + } +#endif + } + // compensation +#ifdef USE_128BIT + simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM16_n1); // 2/sqrt(10) + simde__m128i *rxF128 = (simde__m128i*)rxFext[aarx]; + simde__m128i *ulch128 = (simde__m128i*)chFext[aatx * nb_rx_ant + aarx]; + simde__m128i *rxF_comp128 = (simde__m128i*)rxFext_comp[aatx]; + simde__m128i *ul_ch_mag128 = (simde__m128i*)ul_ch_mag[aatx]; + for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) + { + xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); + xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm_mulhrs_epi16(xmmp1, QAM_amp128); + + if (aarx == 0) + { + *rxF_comp128 = xmmp4; + *ul_ch_mag128 = xmmp1; + } + else + { + *rxF_comp128 = simde_mm_adds_epi16(*rxF_comp128, xmmp4); + *ul_ch_mag128 = simde_mm_adds_epi16(*ul_ch_mag128, xmmp1); + } + rxF_comp128++; + ul_ch_mag128++; + } +#else + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); // 2/sqrt(10) + simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *ulch256 = (simde__m256i*)chFext[aatx * nb_rx_ant + aarx]; + simde__m256i *rxF_comp256 = (simde__m256i*)rxFext_comp[aatx]; + simde__m256i *ul_ch_mag256 = (simde__m256i*)ul_ch_mag[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); + + if (aarx == 0) + { + *rxF_comp256 = xmmp4; + *ul_ch_mag256 = xmmp1; + } + else + { + *rxF_comp256 = simde_mm256_adds_epi16(*rxF_comp256, xmmp4); + *ul_ch_mag256 = simde_mm256_adds_epi16(*ul_ch_mag256, xmmp1); + } + rxF_comp256++; + ul_ch_mag256++; + } +#endif + } + } + c16_t *rho0 = (c16_t *)rho[1]; + c16_t *rho1 = (c16_t *)rho[2]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + c16_t *ul_ch_mag0 = (c16_t *)ul_ch_mag[0]; + c16_t *ul_ch_mag1 = (c16_t *)ul_ch_mag[1]; + nr_ulsch_qam16_qam16((c16_t *)rxFext_comp[0], (c16_t *)rxFext_comp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); + nr_ulsch_qam16_qam16((c16_t *)rxFext_comp[1], (c16_t *)rxFext_comp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); +} + +void inner_rx_64qam_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + int **rxF, + int **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int add_shift = 0; + if (length % 8) + add_shift = 8 - length % 8; + + int32_t rxFext[nb_rx_ant][length + add_shift] __attribute__((aligned(32))); + int32_t chFext[nb_layer*nb_rx_ant][length + add_shift] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int aatx = 0; aatx < nb_layer; aatx++) + { + nr_ulsch_extract_rbs0((c16_t *)rxF[aarx], + pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx * nb_rx_ant + aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + int32_t rho[nb_layer*nb_layer][length + add_shift] __attribute__((aligned(32))); + int32_t rxFext_comp[nb_layer][length + add_shift] __attribute__((aligned(32))); + int32_t ul_ch_mag[nb_layer][length + add_shift] __attribute__((aligned(32))); + for (int aatx = 0; aatx < nb_layer; aatx++) + { + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int atx = 0; atx < nb_layer; atx++) + { +#ifdef USE_128BIT + simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + simde__m128i *rho128 = (simde__m128i *)rho[aatx*nb_layer+atx]; + simde__m128i *ul_ch128 = (simde__m128i *)chFext[aatx * nb_rx_ant + aarx]; + simde__m128i *ul_ch128_2 = (simde__m128i *)chFext[atx * nb_rx_ant + aarx]; + for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm_madd_epi16(ul_ch128[i], ul_ch128_2[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[i], SIMDE_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i*)&conjugate[0]); + mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, ul_ch128_2[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); + if (aarx == 0) + rho128[i] = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); + else + rho128[i] = simde_mm_adds_epi16(rho128[i], simde_mm_packs_epi32(mmtmpD2, mmtmpD3)); + } +#else + simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + simde__m256i *rho256 = (simde__m256i *)rho[aatx*nb_layer+atx]; + simde__m256i *ul_ch256 = (simde__m256i *)chFext[aatx * nb_rx_ant + aarx]; + simde__m256i *ul_ch256_2 = (simde__m256i *)chFext[atx * nb_rx_ant + aarx]; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm256_madd_epi16(ul_ch256[i], ul_ch256_2[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm256_shuffle_epi8(ul_ch256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, ul_ch256_2[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + if (aarx == 0) + rho256[i] = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); + else + rho256[i] = simde_mm256_adds_epi16(rho256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); + } +#endif + } + // compensation +#ifdef USE_128BIT + simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); + register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM64_n1); // 2/sqrt(10) + simde__m128i *rxF128 = (simde__m128i*)rxFext[aarx]; + simde__m128i *ulch128 = (simde__m128i*)chFext[aatx * nb_rx_ant + aarx]; + simde__m128i *rxF_comp128 = (simde__m128i*)rxFext_comp[aatx]; + simde__m128i *ul_ch_mag128 = (simde__m128i*)ul_ch_mag[aatx]; + for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) + { + xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); + xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); + xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 + xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm_mulhrs_epi16(xmmp1, QAM_amp128); + + if (aarx == 0) + { + *rxF_comp128 = xmmp4; + *ul_ch_mag128 = xmmp1; + } + else + { + *rxF_comp128 = simde_mm_adds_epi16(*rxF_comp128, xmmp4); + *ul_ch_mag128 = simde_mm_adds_epi16(*ul_ch_mag128, xmmp1); + } + rxF_comp128++; + ul_ch_mag128++; + } +#else + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) + simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *ulch256 = (simde__m256i*)chFext[aatx * nb_rx_ant + aarx]; + simde__m256i *rxF_comp256 = (simde__m256i*)rxFext_comp[aatx]; + simde__m256i *ul_ch_mag256 = (simde__m256i*)ul_ch_mag[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); + + if (aarx == 0) + { + *rxF_comp256 = xmmp4; + *ul_ch_mag256 = xmmp1; + } + else + { + *rxF_comp256 = simde_mm256_adds_epi16(*rxF_comp256, xmmp4); + *ul_ch_mag256 = simde_mm256_adds_epi16(*ul_ch_mag256, xmmp1); + } + rxF_comp256++; + ul_ch_mag256++; + } +#endif + } + } + c16_t *rho0 = (c16_t *)rho[1]; + c16_t *rho1 = (c16_t *)rho[2]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + c16_t *ul_ch_mag0 = (c16_t *)ul_ch_mag[0]; + c16_t *ul_ch_mag1 = (c16_t *)ul_ch_mag[1]; + nr_ulsch_qam64_qam64((c16_t *)rxFext_comp[0], (c16_t *)rxFext_comp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); + nr_ulsch_qam64_qam64((c16_t *)rxFext_comp[1], (c16_t *)rxFext_comp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); +} + +void nr_pusch_symbol_processing_noprecoding(void *arg) +{ + + puschSymbolProc_t *rdata=(puschSymbolProc_t*)arg; + + PHY_VARS_gNB *gNB = rdata->gNB; + NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; + nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; + int ulsch_id = rdata->ulsch_id; + int slot = rdata->slot; + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; + int16_t *s = rdata->s; + for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) + { + int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; + // this needs to be reworded for parrellization, we need a table which give dmrs symbol location + // used for chennel estimate, they are being run in parallel! + if (dmrs_symbol_flag == 1) + { + if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) + AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); + + gNB->pusch_vars[ulsch_id].dmrs_symbol = symbol; + } + + LOG_I(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id].dmrs_symbol); + + if (nb_re_pusch == 0) continue; + if (rel15_ul->nrOfLayers == 1) + { + int16_t *llr = &rdata->llr[pusch_vars->llr_offset[symbol]]; + void (*inner_rx)(int *,int *,int16_t *,int,int,int); + if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk; + else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam; + else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam; + else if (rel15_ul->qam_mod_order == 8) inner_rx = inner_rx_256qam; + else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", + rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); + + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + int32_t rxFext[nb_re_pusch+8] __attribute__((aligned(32))); + int32_t chFext[nb_re_pusch+8] __attribute__((aligned(32))); + int16_t llr_temp[(nb_re_pusch*rel15_ul->qam_mod_order)+16] __attribute__((aligned(32))); + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) + { + nr_ulsch_extract_rbs0(gNB->common_vars.rxdataF[aa], + gNB->pusch_vars[ulsch_id].ul_ch_estimates[aa], + rxFext, + chFext, + soffset+(symbol * frame_parms->ofdm_symbol_size), + gNB->pusch_vars[ulsch_id].dmrs_symbol*frame_parms->ofdm_symbol_size, + aa, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + // demodulation + inner_rx(rxFext, chFext, llr_temp, aa, nb_re_pusch, gNB->pusch_vars[ulsch_id].log2_maxh); + } + + // unscrambling + simde__m64 *llr64 = (simde__m64 *) llr; + for (int i=0;i<(nb_re_pusch*rel15_ul->qam_mod_order)>>2;i++) + llr64[i] = simde_mm_mullo_pi16(((simde__m64 *)llr_temp)[i],((simde__m64 *)s)[i]); + + s += nb_re_pusch * rel15_ul->qam_mod_order; + llr += nb_re_pusch * rel15_ul->qam_mod_order; + } + else // MIMO for 2x2 + { + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + void (*inner_rx)(NR_DL_FRAME_PARMS *, + NR_gNB_PUSCH *, + nfapi_nr_pusch_pdu_t *, + int32_t **, + int32_t **, + int16_t **, + int32_t, + int32_t, + int32_t, + int32_t, + int32_t, + int16_t, + int32_t, + int32_t); + if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk_2layer; + else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam_2layer; + else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam_2layer; + else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", + rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); + + inner_rx(frame_parms, + pusch_vars, + rel15_ul, + (int32_t**)gNB->common_vars.rxdataF, + gNB->pusch_vars[ulsch_id].ul_ch_estimates, + rdata->llr_layers, + rel15_ul->nrOfLayers, + frame_parms->nb_antennas_rx, + soffset, + nb_re_pusch, // length + symbol, // symbol index + rel15_ul->rb_size, // ofdm size + dmrs_symbol_flag, + gNB->pusch_vars[ulsch_id].log2_maxh); + + // layer de-mapping + int16_t* llr_cw = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch); i++) + for (int l = 0; l < rel15_ul->nrOfLayers; l++) + for (int m = 0; m < rel15_ul->qam_mod_order; m++) + llr_cw[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; + + // unscrambling + simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch*rel15_ul->qam_mod_order*rel15_ul->nrOfLayers)>>2; i++) + llr64[i] = simde_mm_mullo_pi16(((simde__m64 *)llr64)[i], ((simde__m64 *)s)[i]); + + s += (nb_re_pusch*rel15_ul->qam_mod_order*rel15_ul->nrOfLayers); + } + } +} + //compute average channel_level on each (TX,RX) antenna pair void nr_ulsch_channel_level(int **ul_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, @@ -1919,3 +3578,234 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, GnbScopeUpdate(gNB, puschIQe, num_re_total); } } + +int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, + uint8_t ulsch_id, + uint32_t frame, + uint8_t slot, + unsigned char harq_pid) +{ + uint8_t aarx; + uint32_t bwp_start_subcarrier; + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id].harq_process->ulsch_pdu; + + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; + pusch_vars->dmrs_symbol = INVALID_VALUE; + pusch_vars->cl_done = 0; + memset(pusch_vars->extraction_done,0,14*sizeof(int)); + gNB->nbSymb=0; + bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; + LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); + LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos); + + //---------------------------------------------------------- + //------------------- Channel estimation ------------------- + //---------------------------------------------------------- + start_meas(&gNB->ulsch_channel_estimation_stats); + int max_ch = 0; + for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) + { + uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag); + if (dmrs_symbol_flag == 1) + { + if (pusch_vars->dmrs_symbol == INVALID_VALUE) + pusch_vars->dmrs_symbol = symbol; + for (int nl=0; nlnrOfLayers; nl++) + { + nr_pusch_channel_estimation(gNB, + slot, + get_dmrs_port(nl,rel15_ul->dmrs_ports), + symbol, + ulsch_id, + bwp_start_subcarrier, + rel15_ul, + &max_ch, + 0 /* nvar*/); + } + // measure the SNR from the channel estimation + nr_gnb_measurements(gNB, + &gNB->ulsch[ulsch_id], + pusch_vars, + symbol, + rel15_ul->nrOfLayers); + allocCast2D(n0_subband_power, + unsigned int, + gNB->measurements.n0_subband_power, + frame_parms->nb_antennas_rx, + frame_parms->N_RB_UL, + false); + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + { + if (symbol == rel15_ul->start_symbol_index) + { + pusch_vars->ulsch_power[aarx] = 0; + pusch_vars->ulsch_noise_power[aarx] = 0; + } + for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) { + pusch_vars->ulsch_power[aarx] += signal_energy_nodc( + &pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size], + rel15_ul->rb_size * 12); + } + for (int rb = 0; rb < rel15_ul->rb_size; rb++) + pusch_vars->ulsch_noise_power[aarx] += + n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size; + } + } + } + + // averaging time domain channel estimates + if (gNB->chest_time == 1) + { + nr_chest_time_domain_avg(frame_parms, + pusch_vars->ul_ch_estimates, + rel15_ul->nr_of_symbols, + rel15_ul->start_symbol_index, + rel15_ul->ul_dmrs_symb_pos, + rel15_ul->rb_size); + pusch_vars->dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, + rel15_ul->start_symbol_index, + rel15_ul->nr_of_symbols); + } + + stop_meas(&gNB->ulsch_channel_estimation_stats); + + start_meas(&gNB->rx_pusch_init_stats); + + // Scrambling initialization + int number_dmrs_symbols = 0; + for (int l = rel15_ul->start_symbol_index; l < rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; l++) + number_dmrs_symbols += ((rel15_ul->ul_dmrs_symb_pos)>>l) & 0x01; + int nb_re_dmrs; + if (rel15_ul->dmrs_config_type == pusch_dmrs_type1) + nb_re_dmrs = 6*rel15_ul->num_dmrs_cdm_grps_no_data; + else + nb_re_dmrs = 4*rel15_ul->num_dmrs_cdm_grps_no_data; + + // get how many bit in a slot // + int G = nr_get_G(rel15_ul->rb_size, + rel15_ul->nr_of_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + rel15_ul->qam_mod_order, + rel15_ul->nrOfLayers); + // initialize scrambling sequence // + int16_t s[G+96] __attribute__((aligned(32))); + + nr_codeword_unscrambling_init(s, G, 0, rel15_ul->data_scrambling_id, rel15_ul->rnti); + + // first the computation of channel levels + + int nb_re_pusch = 0, meas_symbol = -1; + for(meas_symbol = rel15_ul->start_symbol_index; + meas_symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); + meas_symbol++) + if ((nb_re_pusch = get_nb_re_pusch(frame_parms,rel15_ul,meas_symbol)) > 0) + break; + + AssertFatal(nb_re_pusch>0 && meas_symbol>=0,"nb_re_pusch %d cannot be 0 or meas_symbol %d cannot be negative here\n",nb_re_pusch,meas_symbol); + + start_meas(&gNB->ulsch_rbs_extraction_stats); + // extract the first dmrs for the channel level computation + // extract the data in the OFDM frame, to the start of the array + nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, + pusch_vars, + slot, + meas_symbol, + (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, + rel15_ul, + frame_parms); + stop_meas(&gNB->ulsch_rbs_extraction_stats); + + int avgs = 0; + int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; + uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0; + + //---------------------------------------------------------- + //--------------------- Channel Scaling -------------------- + //---------------------------------------------------------- + nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext, + frame_parms, + &gNB->ulsch[ulsch_id], + meas_symbol, + (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, + nb_re_pusch, + rel15_ul->nrOfLayers, + rel15_ul->rb_size, + shift_ch_ext); + + nr_ulsch_channel_level(pusch_vars->ul_ch_estimates_ext, + frame_parms, + avg, + meas_symbol, // index of the start symbol + nb_re_pusch, // number of the re in pusch + rel15_ul->nrOfLayers, + rel15_ul->rb_size); + + for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + avgs = cmax(avgs, avg[aatx*frame_parms->nb_antennas_rx+aarx]); + + if (rel15_ul->nrOfLayers == 1) + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + 2; + else + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1); + + pusch_vars->cl_done = 1; + pusch_vars->extraction_done[meas_symbol] = 1; + + stop_meas(&gNB->rx_pusch_init_stats); + + start_meas(&gNB->rx_pusch_symbol_processing_stats); + int numSymbols = gNB->num_pusch_symbols_per_thread; + + for(uint8_t symbol = rel15_ul->start_symbol_index; + symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); + symbol += numSymbols) + { + int total_res = 0; + for (int s = 0; s < numSymbols;s++) + { + pusch_vars->ul_valid_re_per_slot[symbol+s] = get_nb_re_pusch(frame_parms,rel15_ul,symbol+s); + pusch_vars->llr_offset[symbol+s] = ((symbol+s) == rel15_ul->start_symbol_index) ? + 0 : + pusch_vars->llr_offset[symbol+s-1] + pusch_vars->ul_valid_re_per_slot[symbol+s-1] * rel15_ul->qam_mod_order; + total_res+=pusch_vars->ul_valid_re_per_slot[symbol+s]; + } + if (total_res > 0) + { + union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}}; + id.p=1+symbol; + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, gNB->respPuschSymb, &nr_pusch_symbol_processing_noprecoding); // create a job for Tpool + puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job + + rdata->gNB = gNB; + rdata->frame_parms = frame_parms; + rdata->rel15_ul = rel15_ul; + rdata->slot = slot; + rdata->startSymbol = symbol; + rdata->numSymbols = numSymbols; + rdata->ulsch_id = ulsch_id; + rdata->llr = pusch_vars->llr; + rdata->llr_layers = pusch_vars->llr_layers; + rdata->s = &s[pusch_vars->llr_offset[symbol]*rel15_ul->nrOfLayers]; + + pushTpool(&gNB->threadPool, req); + gNB->nbSymb++; + + LOG_D(PHY,"%d.%d Added symbol %d (count %d) to process, in pipe\n",frame,slot,symbol,gNB->nbSymb); + } + } // symbol loop + + while (gNB->nbSymb > 0) + { + notifiedFIFO_elt_t *req=pullTpool(gNB->respPuschSymb, &gNB->threadPool); + gNB->nbSymb--; + delNotifiedFIFO_elt(req); + } + + stop_meas(&gNB->rx_pusch_symbol_processing_stats); + return 0; +} diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index c2e6dfba75..f1f931e1f4 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -409,8 +409,12 @@ typedef struct { /// \brief Total RE count after DMRS/PTRS RE's are extracted from respective symbol. /// - first index: ? [0...14] smybol per slot int16_t *ul_valid_re_per_slot; + /// \brief offset for llr corresponding to each symbol + int llr_offset[14]; /// flag to verify if channel level computation is done uint8_t cl_done; + /// flag to indicate if channel extraction is done + int extraction_done[14]; /// flag to indicate DTX on reception int DTX; } NR_gNB_PUSCH; @@ -728,6 +732,8 @@ typedef struct PHY_VARS_gNB_s { time_stats_t dlsch_segmentation_stats; time_stats_t rx_pusch_stats; + time_stats_t rx_pusch_init_stats; + time_stats_t rx_pusch_symbol_processing_stats; time_stats_t ul_indication_stats; time_stats_t schedule_response_stats; time_stats_t ulsch_decoding_stats; @@ -754,6 +760,7 @@ typedef struct PHY_VARS_gNB_s { time_stats_t rx_dft_stats; time_stats_t ulsch_freq_offset_estimation_stats; */ + notifiedFIFO_t *respPuschSymb; notifiedFIFO_t respDecode; notifiedFIFO_t resp_L1; notifiedFIFO_t L1_tx_free; @@ -761,6 +768,9 @@ typedef struct PHY_VARS_gNB_s { notifiedFIFO_t L1_tx_out; notifiedFIFO_t resp_RU_tx; tpool_t threadPool; + int nbSymb; + int use_pusch_tp; + int num_pusch_symbols_per_thread; pthread_t L1_rx_thread; int L1_rx_thread_core; pthread_t L1_tx_thread; @@ -771,6 +781,31 @@ typedef struct PHY_VARS_gNB_s { rt_L1_profiling_t rt_L1_profiling; } PHY_VARS_gNB; +typedef struct puschSymbolProc_s { + PHY_VARS_gNB *gNB; + NR_DL_FRAME_PARMS *frame_parms; + nfapi_nr_pusch_pdu_t *rel15_ul; + int ulsch_id; + int slot; + int startSymbol; + int numSymbols; + int16_t *llr; + int16_t **llr_layers; + int16_t *s; +} puschSymbolProc_t; + +struct puschSymbolReqId { + uint16_t ulsch_id; + uint16_t frame; + uint8_t slot; + uint16_t spare; +} __attribute__((packed)); + +union puschSymbolReqUnion { + struct puschSymbolReqId s; + uint64_t p; +}; + typedef struct LDPCDecode_s { PHY_VARS_gNB *gNB; NR_UL_gNB_HARQ_t *ulsch_harq; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 184e3ec63b..35afb44fe1 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -398,18 +398,21 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, - pusch_pdu->nrOfLayers, - pusch_pdu->qam_mod_order, - G, - gNB->pusch_vars[ULSCH_id].llr_layers); - - //---------------------------------------------------------- - //------------------- ULSCH unscrambling ------------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_unscrambling_stats); - nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); - stop_meas(&gNB->ulsch_unscrambling_stats); + if (gNB->use_pusch_tp == 0 ) + { + nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, + pusch_pdu->nrOfLayers, + pusch_pdu->qam_mod_order, + G, + gNB->pusch_vars[ULSCH_id].llr_layers); + //---------------------------------------------------------- + //------------------- ULSCH unscrambling ------------------- + //---------------------------------------------------------- + start_meas(&gNB->ulsch_unscrambling_stats); + nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); + stop_meas(&gNB->ulsch_unscrambling_stats); + } + //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- //---------------------------------------------------------- @@ -417,7 +420,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int start_meas(&gNB->ulsch_decoding_stats); int nbDecode = nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G); - stop_meas(&gNB->ulsch_decoding_stats); + return nbDecode; } @@ -899,7 +902,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); start_meas(&gNB->rx_pusch_stats); - nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + if (gNB->use_pusch_tp) nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + else nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; pusch_vars->ulsch_power_tot = 0; pusch_vars->ulsch_noise_power_tot = 0; @@ -962,6 +966,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) delNotifiedFIFO_elt(req); totalDecode--; } + stop_meas(&gNB->ulsch_decoding_stats); } for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 5ee660d1e0..879d6deda1 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -222,6 +222,7 @@ int main(int argc, char *argv[]) int ibwp_rboffset=41; int params_from_file = 0; int threadCnt=0; + int use_tpool = 0; int max_ldpc_iterations = 5; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) { exit_fun("[NR_ULSIM] Error, configuration module init failed\n"); @@ -363,6 +364,7 @@ int main(int argc, char *argv[]) case 'C': threadCnt = atoi(optarg); + use_tpool = 1; break; case 'u': @@ -562,9 +564,13 @@ int main(int argc, char *argv[]) gNB = RC.gNB[0]; gNB->ofdm_offset_divisor = UINT_MAX; initNotifiedFIFO(&gNB->respDecode); + gNB->use_pusch_tp = use_tpool; + gNB->num_pusch_symbols_per_thread = 1; initFloatingCoresTpool(threadCnt, &gNB->threadPool, false, "gNB-tpool"); initNotifiedFIFO(&gNB->respDecode); + gNB->respPuschSymb = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->respPuschSymb); initNotifiedFIFO(&gNB->L1_tx_free); initNotifiedFIFO(&gNB->L1_tx_filled); initNotifiedFIFO(&gNB->L1_tx_out); @@ -927,6 +933,8 @@ int main(int argc, char *argv[]) roundStats = 0; reset_meas(&gNB->phy_proc_rx); reset_meas(&gNB->rx_pusch_stats); + reset_meas(&gNB->rx_pusch_init_stats); + reset_meas(&gNB->rx_pusch_symbol_processing_stats); reset_meas(&gNB->ulsch_decoding_stats); reset_meas(&gNB->ulsch_deinterleaving_stats); reset_meas(&gNB->ulsch_rate_unmatching_stats); @@ -1588,25 +1596,36 @@ int main(int argc, char *argv[]) dump_pusch_stats(fd,gNB); fclose(fd); - if (print_perf==1) { + if (print_perf==1) + { + printf("gNB RX\n"); printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time"); printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); - printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); - printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); - printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); - printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); - printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); - printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); + if (use_tpool == 1) + { + printStatIndent2(&gNB->rx_pusch_init_stats,"RX PUSCH Initialization time"); + printStatIndent2(&gNB->rx_pusch_symbol_processing_stats,"RX PUSCH Symbol Processing time"); + } + else + { + printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); + printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); + printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); + printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); + printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); + printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); + } printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); + // printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); + // printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); + // printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); + printf("\nUE TX\n"); printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time"); printStatIndent2(&UE->ulsch_segmentation_stats,"ULSCH segmentation time"); printStatIndent2(&UE->ulsch_ldpc_encoding_stats,"ULSCH LDPC encoder time"); printStatIndent2(&UE->ulsch_rate_matching_stats,"ULSCH rate-matching time"); printStatIndent2(&UE->ulsch_interleaving_stats,"ULSCH interleaving time"); - //printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); - //printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); - //printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); printStatIndent(&gNB->rx_srs_stats,"RX SRS time"); printStatIndent2(&gNB->generate_srs_stats,"Generate SRS sequence time"); printStatIndent2(&gNB->get_srs_signal_stats,"Get SRS signal time"); From 04073b03e46225e98ba98940cd18f456f39c0ebd Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Tue, 5 Sep 2023 14:31:48 +0200 Subject: [PATCH 06/43] feat / add the MMSE and precoding - avoid the finction duplication - add the transform predoding to the nr_rx_pusch_tp - add the MMSE for 2 layer which modulation greater than 16 qam - can support to 256 qam for 1 layer and 2 layer --- CMakeLists.txt | 1 + executables/nr-gnb.c | 1 + openair1/PHY/INIT/nr_init.c | 3 + .../PHY/NR_ESTIMATION/nr_freq_equalization.c | 73 + openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 11 + .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 3061 ++++++----------- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 316 +- openair1/PHY/defs_gNB.h | 4 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 33 +- openair1/SIMULATION/NR_PHY/ulsim.c | 32 +- 10 files changed, 1276 insertions(+), 2259 deletions(-) create mode 100644 openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ec60df8b35..e1527d227c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1040,6 +1040,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c + ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_freq_equalization.c ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 33fe6b3f2a..d436828294 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -479,6 +479,7 @@ void init_gNB_Tpool(int inst) { // ULSCH decoding threadpool initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE)); // ULSCH decoder result FIFO + initNotifiedFIFO(&gNB->respPuschSymb); initNotifiedFIFO(&gNB->respDecode); // L1 RX result FIFO diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index ed3fd55079..09898d383b 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -28,6 +28,7 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "openair1/PHY/MODULATION/nr_modulation.h" #include "openair1/PHY/defs_RU.h" #include "openair1/PHY/CODING/nrLDPC_extern.h" @@ -525,6 +526,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) init_scrambling_luts(); init_pucch2_luts(); + nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH + load_nrLDPClib(NULL); if (gNB->ldpc_offload_flag) diff --git a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c new file mode 100644 index 0000000000..e73ac48fab --- /dev/null +++ b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c @@ -0,0 +1,73 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "PHY/defs_eNB.h" +#include "PHY/sse_intrin.h" +#include "PHY/NR_ESTIMATION/nr_ul_estimation.h" + +// Reference of openair1/PHY/LTE_ESTIMATION/freq_equalization.c + +// This is 4096/(1:4096) in simde__m128i format +simde__m128i nr_inv_ch[4096];/* = {0, 4096/1, 4096/2, 4096/3, 4096/4...}*/ + +void nr_init_fde() +{ + for (int i = 1;i < 4096; i++) + nr_inv_ch[i] = simde_mm_set1_epi16(4096/i); +} + +void nr_freq_equalization (NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdataF_comp, + int32_t *ul_ch_mag, + int32_t *ul_ch_magb, + uint8_t symbol, + uint16_t Msc_RS, + uint8_t Qm) +{ + simde__m128i *rxdataF_comp128 = (simde__m128i *)rxdataF_comp; + simde__m128i *ul_ch_mag128 = (simde__m128i *)ul_ch_mag; + simde__m128i *ul_ch_magb128 = (simde__m128i *)ul_ch_magb; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "symbol %d >= %d\n", + symbol, frame_parms->symbols_per_slot); + AssertFatal(Msc_RS <= frame_parms->N_RB_UL*12, "Msc_RS %d >= %d\n", + Msc_RS, frame_parms->N_RB_UL*12); + + for (uint16_t re = 0; re < (Msc_RS >> 2); re++) + { + int16_t amp = (*((int16_t*)&ul_ch_mag128[re])); + + if (amp > 4095) + amp = 4095; + + rxdataF_comp128[re] = simde_mm_srai_epi16(simde_mm_mullo_epi16(rxdataF_comp128[re],nr_inv_ch[amp]),3); + + if (Qm == 4) + ul_ch_mag128[re] = simde_mm_set1_epi16(324); // this is 512*2/sqrt(10) + else if (Qm == 6) + { + ul_ch_mag128[re] = simde_mm_set1_epi16(316); // this is 512*4/sqrt(42) + ul_ch_magb128[re] = simde_mm_set1_epi16(158); // this is 512*2/sqrt(42) + } + else if(Qm != 2) + AssertFatal(1, "nr_freq_equalization(), Qm = %d, should be 2, 4 or 6. symbol=%d, Msc_RS=%d\n", Qm, symbol, Msc_RS); + } +} diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index c75b4d4ed7..4934498a4a 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -83,4 +83,15 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, int32_t srs_estimated_channel_time_shifted[][1<num_ant_ports][gNB->frame_parms.ofdm_symbol_size], int8_t *snr_per_rb, int8_t *snr); + +void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, + int *rxdataF_comp, + int *ul_ch_mag, + int *ul_ch_mag_b, + unsigned char symbol, + unsigned short Msc_RS, + unsigned char Qm); + +void nr_init_fde(void); + #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 9c398d1664..3e0b3506b1 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -18,10 +18,6 @@ #define INVALID_VALUE 255 -#ifdef __aarch64__ -#define USE_128BIT -#endif - void nr_idft(int32_t *z, uint32_t Msc_PUSCH) { @@ -285,16 +281,16 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) } -void nr_ulsch_extract_rbs0 (c16_t *rxdataF, - int32_t *chF, - int32_t *rxFext, - int32_t *chFext, - int rxoffset, - int choffset, - int aarx, - int is_dmrs_symbol, - nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_DL_FRAME_PARMS *frame_parms) +static void nr_ulsch_extract_rbs0 (c16_t* const rxdataF, + c16_t* const chF, + c16_t *rxFext, + c16_t *chFext, + int rxoffset, + int choffset, + int aarx, + int is_dmrs_symbol, + nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_DL_FRAME_PARMS *frame_parms) { uint8_t delta = 0; @@ -303,206 +299,87 @@ void nr_ulsch_extract_rbs0 (c16_t *rxdataF, int nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; - int32_t *rxF = (int32_t*)&rxdataF[rxoffset]; - int32_t *rxF_ext = &rxFext[0]; - int32_t *ul_ch0 = &chF[choffset]; - int32_t *ul_ch0_ext = &chFext[0]; - + c16_t *rxF = &rxdataF[rxoffset]; + c16_t *rxF_ext = &rxFext[0]; + c16_t *ul_ch0 = &chF[choffset]; + c16_t *ul_ch0_ext = &chFext[0]; if (is_dmrs_symbol == 0) { - if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) { - memcpy((void*)rxF_ext, - (void*)&rxF[start_re], - nb_re_pusch*sizeof(int32_t)); - } + if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) + memcpy(rxF_ext, &rxF[start_re], nb_re_pusch * sizeof(c16_t)); else { - int neg_length = frame_parms->ofdm_symbol_size-start_re; + int neg_length = frame_parms->ofdm_symbol_size - start_re; int pos_length = nb_re_pusch - neg_length; - memcpy((void*)rxF_ext, (void*)&rxF[start_re], neg_length * sizeof(int32_t)); - memcpy((void*)&rxF_ext[neg_length], (void*)rxF, pos_length * sizeof(int32_t)); + memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(c16_t)); + memcpy(&rxF_ext[neg_length], rxF, pos_length * sizeof(c16_t)); } - memcpy((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t)); + memcpy(ul_ch0_ext, ul_ch0, nb_re_pusch * sizeof(c16_t)); } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) // 6 REs / PRB { - AssertFatal(delta==0||delta==1,"Illegal delta %d\n",delta); - int32_t *rxF32 = &rxF[start_re]; - int32_t *rxF_ext32 = rxF_ext; - int32_t *ul_ch032 = ul_ch0; - int32_t *ul_ch0_ext32 = ul_ch0_ext; - int idx,idx2,idx3; + AssertFatal(delta == 0 || delta == 1, "Illegal delta %d\n",delta); + c16_t *rxF32 = &rxF[start_re]; if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { - for (idx=1-delta,idx2=0;idxofdm_symbol_size-start_re; - int pos_length = nb_re_pusch-neg_length; - - for (idx=1-delta,idx2=0;idxofdm_symbol_size - start_re; + int pos_length = nb_re_pusch - neg_length; + int idx, idx2; + for (idx = 1 - delta; idx < neg_length; idx += 2) + { + *rxF_ext++ = rxF32[idx]; + *ul_ch0_ext++= ul_ch0[idx]; } - rxF32=(int32_t*)rxF; - idx3=idx; - for (idx=1-delta;idxdmrs_config_type == pusch_dmrs_type2) // 8 REs / PRB { AssertFatal(delta==0||delta==2||delta==4,"Illegal delta %d\n",delta); - if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { - int64_t *rxF64 = (int64_t*)&rxF[start_re]; - int64_t *rxF_ext64 = (int64_t*)rxF_ext; - int64_t *ul_ch064 = (int64_t*)ul_ch0; - int64_t *ul_ch0_ext64 = (int64_t*)ul_ch0_ext; - if (delta==0) { - for (int idx=0;idx>1;idx+=6) { - rxF_ext64[idx]=rxF64[idx+1]; - rxF_ext64[idx+1]=rxF64[idx+2]; - rxF_ext64[idx+2]=rxF64[idx+4]; - rxF_ext64[idx+3]=rxF64[idx+5]; - ul_ch0_ext64[idx]=ul_ch064[idx+1]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+4]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; - } - } - else if (delta==2) { - for (int idx=0;idx>1;idx+=6) { - rxF_ext64[idx]=rxF64[idx+0]; - rxF_ext64[idx+1]=rxF64[idx+2]; - rxF_ext64[idx+2]=rxF64[idx+3]; - rxF_ext64[idx+3]=rxF64[idx+5]; - ul_ch0_ext64[idx]=ul_ch064[idx+0]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; - } - } - else if (delta==4) { - for (int idx=0;idx>1;idx+=6) { - rxF_ext64[idx]=rxF64[idx+0]; - rxF_ext64[idx+1]=rxF64[idx+1]; - rxF_ext64[idx+2]=rxF64[idx+3]; - rxF_ext64[idx+3]=rxF64[idx+4]; - ul_ch0_ext64[idx]=ul_ch064[idx+0]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+1]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+4]; - } + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) + { + for (int idx = 0; idx < nb_re_pusch; idx ++) + { + if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1) + continue; + *rxF_ext++ = rxF[idx]; + *ul_ch0_ext++ = ul_ch0[idx]; } } - else { - int neg_length = frame_parms->ofdm_symbol_size-start_re; - int pos_length = nb_re_pusch-neg_length; - if ((pos_length%12) > 0 ) pos_length+=12; - int64_t *rxF64 = (int64_t*)&rxF[start_re]; - int64_t *rxF_ext64 = (int64_t*)rxF_ext; - int64_t *ul_ch064 = (int64_t*)ul_ch0; - int64_t *ul_ch0_ext64 = (int64_t*)ul_ch0_ext; - int idx=0; - if (delta==0) { - for (idx=0;idx>1;idx+=6) { - rxF_ext64[idx] =rxF64[idx+1]; - rxF_ext64[idx+1]=rxF64[idx+2]; - rxF_ext64[idx+2]=rxF64[idx+4]; - rxF_ext64[idx+3]=rxF64[idx+5]; - ul_ch0_ext64[idx]=ul_ch064[idx+1]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+4]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; - } - if ((neg_length%12) > 0) { - rxF_ext64[idx+4]=rxF64[idx+7]; - rxF_ext64[idx+5]=rxF64[idx+8]; - ul_ch0_ext64[idx+4]=ul_ch064[idx+7]; - ul_ch0_ext64[idx+5]=ul_ch064[idx+8]; - } - rxF_ext64+=(neg_length/3); - rxF64=(int64_t*)rxF; - ul_ch0_ext64+=(neg_length/3); - ul_ch064+=(neg_length>>1); - for (idx=0;idx>1;idx+=6) { - rxF_ext64[idx] =rxF64[idx+1]; - rxF_ext64[idx+1]=rxF64[idx+2]; - rxF_ext64[idx+2]=rxF64[idx+4]; - rxF_ext64[idx+3]=rxF64[idx+5]; - ul_ch0_ext64[idx]=ul_ch064[idx+1]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+4]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; - } + else + { + int neg_length = frame_parms->ofdm_symbol_size - start_re; + int pos_length = nb_re_pusch - neg_length; + c16_t *rxF64 = &rxF[start_re]; + int idx, idx2; + for (idx = 0; idx < neg_length; idx ++) + { + if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1) + continue; + *rxF_ext++ = rxF64[idx]; + *ul_ch0_ext++ = ul_ch0[idx]; } - else if (delta==2) { - for (idx=0;idx>1;idx+=6) { - rxF_ext64[idx] =rxF64[idx+0]; - rxF_ext64[idx+1]=rxF64[idx+2]; - rxF_ext64[idx+2]=rxF64[idx+3]; - rxF_ext64[idx+3]=rxF64[idx+5]; - ul_ch0_ext64[idx]=ul_ch064[idx+0]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; - } - if ((neg_length%12) > 0) { - rxF_ext64[idx+4]=rxF64[idx+6]; - rxF_ext64[idx+5]=rxF64[idx+8]; - ul_ch0_ext64[idx+4]=ul_ch064[idx+6]; - ul_ch0_ext64[idx+5]=ul_ch064[idx+8]; - } - rxF_ext64+=(neg_length/3); - rxF64=(int64_t*)rxF; - ul_ch0_ext64+=(neg_length/3); - ul_ch064+=(neg_length>>1); - for (idx=0;idx>1;idx+=6) { - rxF_ext64[idx] =rxF64[idx+0]; - rxF_ext64[idx+1]=rxF64[idx+2]; - rxF_ext64[idx+2]=rxF64[idx+3]; - rxF_ext64[idx+3]=rxF64[idx+5]; - ul_ch0_ext64[idx]=ul_ch064[idx+0]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+2]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+5]; - } - } - else if (delta==4) { - for (idx=0;idx>1;idx+=6) { - rxF_ext64[idx] =rxF64[idx+0]; - rxF_ext64[idx+1]=rxF64[idx+1]; - rxF_ext64[idx+2]=rxF64[idx+3]; - rxF_ext64[idx+3]=rxF64[idx+4]; - ul_ch0_ext64[idx]=ul_ch064[idx+0]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+1]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+4]; - } - if ((neg_length%12) > 0) { - rxF_ext64[idx+4]=rxF64[idx+6]; - rxF_ext64[idx+5]=rxF64[idx+7]; - ul_ch0_ext64[idx+4]=ul_ch064[idx+6]; - ul_ch0_ext64[idx+5]=ul_ch064[idx+7]; - } - rxF_ext64+=(neg_length/3); - rxF64=(int64_t*)rxF; - ul_ch0_ext64+=(neg_length/3); - ul_ch064+=(neg_length>>1); - for (idx=0;idx>1;idx+=6) { - rxF_ext64[idx] =rxF64[idx+0]; - rxF_ext64[idx+1]=rxF64[idx+1]; - rxF_ext64[idx+2]=rxF64[idx+3]; - rxF_ext64[idx+3]=rxF64[idx+4]; - ul_ch0_ext64[idx]=ul_ch064[idx+0]; - ul_ch0_ext64[idx+1]=ul_ch064[idx+1]; - ul_ch0_ext64[idx+2]=ul_ch064[idx+3]; - ul_ch0_ext64[idx+3]=ul_ch064[idx+4]; - } + rxF64 = rxF; + idx2 = idx; + for (idx = 0; idx < pos_length; idx++, idx2++) + { + if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1) + continue; + *rxF_ext++ = rxF64[idx]; + *ul_ch0_ext++ = ul_ch0[idx2]; } } } @@ -662,1423 +539,6 @@ int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15 } else return(rel15_ul->rb_size * NR_NB_SC_PER_RB); } -void inner_rx_qpsk (int *rxF, - int *ul_ch, - int16_t *llr, - int aarx, - int length, - int output_shift) -{ -#ifndef USE_128BIT - register simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - - simde__m256i *rxF256 = (simde__m256i*)rxF; - simde__m256i *ulch256 = (simde__m256i*)ul_ch; - // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits - simde__m64 *llr64 = (simde__m64 *)llr; - for (int i=0; i<((length>>3)+((length&7)>0?1:0)); i++) { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); - if (aarx == 0) - { - *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,0); llr64++; - *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,1); llr64++; - *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,2); llr64++; - *llr64 = (simde__m64)simde_mm256_extract_epi64(xmmp4,3); llr64++; - } - else - { - *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,0))); llr64++; - *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,1))); llr64++; - *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,2))); llr64++; - *llr64 = simde_mm_adds_pi16(*llr64,(simde__m64)(simde_mm256_extract_epi64(xmmp4,3))); llr64++; - } - } -#else - simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - - simde__m128i *rxF128 = (simde__m128i*)rxF; - simde__m128i *ulch128 = (simde__m128i*)ul_ch; - simde__m128i *llr128 = (simde__m128i*)llr; - for (int i = 0; i < (length >> 2); i++) { - xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); - xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); - - if (aarx == 0) - *llr128 = xmmp4; - else - *llr128 = simde_mm_add_epi16(*llr128, xmmp4); - llr128++; - } - if (length & 3) - { - int i = (length>>1) - 1; - simde__m64* llr64 = (simde__m64*)llr128; - simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4; - simde__m64 complex_shuffle64 = simde_mm_set_pi8(5, 4, 7, 6, 1, 0, 3, 2); - simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); - simde__m64 *rxF64 = (simde__m64*)rxF; - simde__m64 *ulch64 = (simde__m64*)ul_ch; - - xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); - // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); - xmm1 = simde_mm_sign_pi16(xmm1, conj64); - xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); - // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm1 = simde_mm_srai_pi32(xmm1, output_shift); - xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); - xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); - xmm4 = simde_mm_packs_pi32(xmm2, xmm3); - - if (aarx == 0) - *llr64 = xmm4; - else - *llr64 = simde_mm_add_pi16(*llr64, xmm4); - } -#endif -} - -void inner_rx_16qam (int *rxF, - int *ul_ch, - int16_t *llr, - int aarx, - int length, - int output_shift) -{ -#ifndef USE_128BIT - register simde__m256i xmmp0,xmmp1,xmmp2,xmmp3,xmmp4,xmmp5; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - - register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); // 2/sqrt(10) - simde__m256i *rxF256 = (simde__m256i*)rxF; - simde__m256i *ulch256 = (simde__m256i*)ul_ch; - // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits - simde__m64 *llr64 = (simde__m64 *)llr; - - for (int i = 0; i < ((length >> 3) + ((length & 7) > 0 ? 1 : 0)); i++) - { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - // compute channel amplitude for LLR - xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); - - xmmp2 = simde_mm256_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmmp2 = simde_mm256_subs_epi16(xmmp1,xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - - xmmp3 = simde_mm256_unpacklo_epi32(xmmp4,xmmp2); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs - xmmp5 = simde_mm256_unpackhi_epi32(xmmp4,xmmp2); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs - if (aarx == 0) - { - // 1st/2nd RE - llr64[0] = (simde__m64)simde_mm256_extract_epi64(xmmp3,0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I - // 3rd/4th RE - llr64[1] = (simde__m64)simde_mm256_extract_epi64(xmmp3,1); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I - // 5th/6th RE - llr64[2] = (simde__m64)simde_mm256_extract_epi64(xmmp5,0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I - // 7Rh/8th RE - llr64[3] = (simde__m64)simde_mm256_extract_epi64(xmmp5,1); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I - // 9th/10th RE - llr64[4] = (simde__m64)simde_mm256_extract_epi64(xmmp3,2); // llr32[8] low 16 bits-> y_R , high 16 bits-> y_I - // 11th/12th RE - llr64[5] = (simde__m64)simde_mm256_extract_epi64(xmmp3,3); // llr32[10] low 16 bits-> y_R , high 16 bits-> y_I - // 13th/14th RE - llr64[6] = (simde__m64)simde_mm256_extract_epi64(xmmp5,2); // llr32[12] low 16 bits-> y_R , high 16 bits-> y_I - // 15th/16th RE - llr64[7] = (simde__m64)simde_mm256_extract_epi64(xmmp5,3); // llr32[14] low 16 bits-> y_R , high 16 bits-> y_I - llr64+=8; - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0],(simde__m64)simde_mm256_extract_epi64(xmmp3,0)); - llr64[1] = simde_mm_adds_pi16(llr64[1],(simde__m64)simde_mm256_extract_epi64(xmmp3,1)); - llr64[2] = simde_mm_adds_pi16(llr64[2],(simde__m64)simde_mm256_extract_epi64(xmmp5,0)); - llr64[3] = simde_mm_adds_pi16(llr64[3],(simde__m64)simde_mm256_extract_epi64(xmmp5,1)); - llr64[4] = simde_mm_adds_pi16(llr64[4],(simde__m64)simde_mm256_extract_epi64(xmmp3,2)); - llr64[5] = simde_mm_adds_pi16(llr64[5],(simde__m64)simde_mm256_extract_epi64(xmmp3,3)); - llr64[6] = simde_mm_adds_pi16(llr64[6],(simde__m64)simde_mm256_extract_epi64(xmmp5,2)); - llr64[7] = simde_mm_adds_pi16(llr64[7],(simde__m64)simde_mm256_extract_epi64(xmmp5,3)); - llr64 += 8; - } - } -#else - simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp5; - register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - - register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM16_n1); // 2/sqrt(10) - simde__m128i *rxF128 = (simde__m128i*)rxF; - simde__m128i *ulch128 = (simde__m128i*)ul_ch; - // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits - simde__m64 *llr64 = (simde__m64 *)llr; - - for (int i = 0; i < (length >> 2); i++) - { - xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); - xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); - - // compute channel amplitude for LLR - xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm_mulhrs_epi16(xmmp1, QAM_amp128); - - xmmp2 = simde_mm_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmmp2 = simde_mm_subs_epi16(xmmp1, xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - - xmmp3 = simde_mm_unpacklo_epi32(xmmp4, xmmp2); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs - xmmp5 = simde_mm_unpackhi_epi32(xmmp4, xmmp2); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs - if (aarx == 0) - { - llr64[0] = (simde__m64)simde_mm_extract_epi64(xmmp3, 0); // llr32[0] low 16 bits-> y_R, high 16 bits-> y_I - llr64[1] = (simde__m64)simde_mm_extract_epi64(xmmp3, 1); // llr32[2] low 16 bits-> y_R, high 16 bits-> y_I - llr64[2] = (simde__m64)simde_mm_extract_epi64(xmmp5, 0); // llr32[4] low 16 bits-> y_R, high 16 bits-> y_I - llr64[3] = (simde__m64)simde_mm_extract_epi64(xmmp5, 1); // llr32[6] low 16 bits-> y_R, high 16 bits-> y_I - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0], (simde__m64)simde_mm_extract_epi64(xmmp3, 0)); - llr64[1] = simde_mm_adds_pi16(llr64[1], (simde__m64)simde_mm_extract_epi64(xmmp3, 1)); - llr64[2] = simde_mm_adds_pi16(llr64[2], (simde__m64)simde_mm_extract_epi64(xmmp5, 0)); - llr64[3] = simde_mm_adds_pi16(llr64[3], (simde__m64)simde_mm_extract_epi64(xmmp5, 1)); - } - llr64 += 4; - } - if (length & 3) - { - int i = (length>>1) - 1; - simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4; - simde__m64 complex_shuffle64 = simde_mm_set_pi8(5,4,7,6,1,0,3,2); - simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); - simde__m64 *rxF64 = (simde__m64*)rxF; - simde__m64 *ulch64 = (simde__m64*)ul_ch; - simde__m64 QAM_amp = simde_mm_set1_pi16(QAM16_n1); - - xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); - // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); - xmm1 = simde_mm_sign_pi16(xmm1, conj64); - xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); - // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm1 = simde_mm_srai_pi32(xmm1, output_shift); - xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); - xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); - xmm4 = simde_mm_packs_pi32(xmm2, xmm3); - - // compute channel amplitude for LLR - xmm0 = simde_mm_madd_pi16(ulch64[i], ulch64[i]); // |h|^2 - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm0 = simde_mm_packs_pi32(xmm0, xmm0); - xmm2 = simde_mm_unpacklo_pi16(xmm0, xmm0); - - xmm1 = simde_mm_mulhrs_pi16(xmm2, QAM_amp); - - xmm0 = simde_mm_abs_pi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_pi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - if (aarx == 0) - { - llr64[0] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0), simde_mm_extract_pi16(xmm4, 0)); - llr64[1] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 1), simde_mm_extract_pi16(xmm4, 1)); - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0], simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0),simde_mm_extract_pi16(xmm4, 0))); - llr64[1] = simde_mm_adds_pi16(llr64[1], simde_mm_set_pi32(simde_mm_extract_pi16(xmm4, 1),simde_mm_extract_pi16(xmm1, 0))); - } - } - -#endif -} - -void inner_rx_64qam (int *restrict rxF, - int *restrict ul_ch, - int16_t *restrict llr, - int aarx, - int length, - int output_shift) -{ -#ifndef USE_128BIT - register simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp6, xmmp7; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29, 28, 31, 30, 25, 24, 27, 26, 21, 20, 23, 22, 17, 16, 19, 18, 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m256i conj256 = simde_mm256_set_epi16(1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1); - - register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) - register simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM64_n2); - simde__m256i *rxF256 = (simde__m256i*)rxF; - simde__m256i *ulch256 = (simde__m256i*)ul_ch; - // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits - - simde__m64 *llr64 = (simde__m64 *)llr; - for (int i=0;i<((length>>3)+((length&7)>0?1:0));i++) { - xmmp0 = simde_mm256_madd_epi16(ulch256[i],rxF256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i],complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1,conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1,rxF256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1,output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0,xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0,xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); - - // compute channel amplitude for LLR - xmmp0 = simde_mm256_madd_epi16(ulch256[i],ulch256[i]); - xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0,xmmp0); - xmmp2 = simde_mm256_unpacklo_epi16(xmmp0,xmmp0); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256); - xmmp6 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256b); - - xmmp2 = simde_mm256_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmmp2 = simde_mm256_subs_epi16(xmmp1,xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmmp7 = simde_mm256_abs_epi16(xmmp2); - xmmp7 = simde_mm256_subs_epi16(xmmp6,xmmp7); - - if (aarx == 0) - { - llr64[0] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,0),simde_mm256_extract_epi32(xmmp4,0)); - llr64[1] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,1),simde_mm256_extract_epi32(xmmp7,0)); - llr64[2] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,1),simde_mm256_extract_epi32(xmmp2,1)); - llr64[3] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,2),simde_mm256_extract_epi32(xmmp4,2)); - llr64[4] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,3),simde_mm256_extract_epi32(xmmp7,2)); - llr64[5] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,3),simde_mm256_extract_epi32(xmmp2,3)); - llr64[6] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,4),simde_mm256_extract_epi32(xmmp4,4)); - llr64[7] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,5),simde_mm256_extract_epi32(xmmp7,4)); - llr64[8] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,5),simde_mm256_extract_epi32(xmmp2,5)); - llr64[9] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,6),simde_mm256_extract_epi32(xmmp4,6)); - llr64[10] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,7),simde_mm256_extract_epi32(xmmp7,6)); - llr64[11] = simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,7),simde_mm256_extract_epi32(xmmp2,7)); - llr64+=12; - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,0),simde_mm256_extract_epi32(xmmp4,0))); - llr64[1] = simde_mm_adds_pi16(llr64[1],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,1),simde_mm256_extract_epi32(xmmp7,0))); - llr64[2] = simde_mm_adds_pi16(llr64[2],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,1),simde_mm256_extract_epi32(xmmp2,1))); - llr64[3] = simde_mm_adds_pi16(llr64[3],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,2),simde_mm256_extract_epi32(xmmp4,2))); - llr64[4] = simde_mm_adds_pi16(llr64[4],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,3),simde_mm256_extract_epi32(xmmp7,2))); - llr64[5] = simde_mm_adds_pi16(llr64[5],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,3),simde_mm256_extract_epi32(xmmp2,3))); - llr64[6] = simde_mm_adds_pi16(llr64[6],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,4),simde_mm256_extract_epi32(xmmp4,4))); - llr64[7] = simde_mm_adds_pi16(llr64[7],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,5),simde_mm256_extract_epi32(xmmp7,4))); - llr64[8] = simde_mm_adds_pi16(llr64[8],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,5),simde_mm256_extract_epi32(xmmp2,5))); - llr64[9] = simde_mm_adds_pi16(llr64[9],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp2,6),simde_mm256_extract_epi32(xmmp4,6))); - llr64[10] = simde_mm_adds_pi16(llr64[10],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp4,7),simde_mm256_extract_epi32(xmmp7,6))); - llr64[11] = simde_mm_adds_pi16(llr64[11],simde_mm_set_pi32(simde_mm256_extract_epi32(xmmp7,7),simde_mm256_extract_epi32(xmmp2,7))); - llr64+=12; - } - } -#else - register simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp6, xmmp7; - register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - // register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM64_n1); // 4/sqrt(42) - register simde__m128i QAM_amp128b = simde_mm_set1_epi16(QAM64_n2); // 2/sqrt(42) - simde__m128i *rxF128 = (simde__m128i*) rxF; - simde__m128i *ulch128 = (simde__m128i*) ul_ch; - // need to use simde__m64 because llr output is not necessarily aligned to 256 bits, but it is always to 64 bits - simde__m64 *llr64 = (simde__m64 *)llr; - for (int i = 0; i < (length>>2); i++) - { - xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); - xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); - - // compute channel amplitude for LLR - xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); - xmmp2 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm_mulhrs_epi16(xmmp2, QAM_amp128); - xmmp6 = simde_mm_mulhrs_epi16(xmmp2, QAM_amp128b); - - xmmp2 = simde_mm_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmmp2 = simde_mm_subs_epi16(xmmp1, xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmmp7 = simde_mm_abs_epi16(xmmp2); - xmmp7 = simde_mm_subs_epi16(xmmp6, xmmp7); - - if (aarx == 0) - { - llr64[0] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 0), simde_mm_extract_epi32(xmmp4, 0)); - llr64[1] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 1), simde_mm_extract_epi32(xmmp7, 0)); - llr64[2] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 1), simde_mm_extract_epi32(xmmp2, 1)); - llr64[3] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 2), simde_mm_extract_epi32(xmmp4, 2)); - llr64[4] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 3), simde_mm_extract_epi32(xmmp7, 2)); - llr64[5] = simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 3), simde_mm_extract_epi32(xmmp2, 3)); - llr64 += 6; - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 0),simde_mm_extract_epi32(xmmp4, 0))); - llr64[1] = simde_mm_adds_pi16(llr64[1], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 1),simde_mm_extract_epi32(xmmp7, 0))); - llr64[2] = simde_mm_adds_pi16(llr64[2], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 1),simde_mm_extract_epi32(xmmp2, 1))); - llr64[3] = simde_mm_adds_pi16(llr64[3], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp2, 2),simde_mm_extract_epi32(xmmp4, 2))); - llr64[4] = simde_mm_adds_pi16(llr64[4], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp4, 3),simde_mm_extract_epi32(xmmp7, 2))); - llr64[5] = simde_mm_adds_pi16(llr64[5], simde_mm_set_pi32(simde_mm_extract_epi32(xmmp7, 3),simde_mm_extract_epi32(xmmp2, 3))); - llr64 += 6; - } - } - if (length & 3) - { - int i = (length>>1) - 1; - simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5; - simde__m64 complex_shuffle64 = simde_mm_set_pi8(5,4,7,6,1,0,3,2); - simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); - simde__m64 *rxF64 = (simde__m64*)rxF; - simde__m64 *ulch64 = (simde__m64*)ul_ch; - simde__m64 QAM_amp = simde_mm_set1_pi16(QAM64_n1); - simde__m64 QAM_ampb = simde_mm_set1_pi16(QAM64_n2); - - xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); - // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); - xmm1 = simde_mm_sign_pi16(xmm1, conj64); - xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); - // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm1 = simde_mm_srai_pi32(xmm1, output_shift); - xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); - xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); - xmm4 = simde_mm_packs_pi32(xmm2, xmm3); - - // compute channel amplitude for LLR - xmm0 = simde_mm_madd_pi16(ulch64[i], ulch64[i]); // |h|^2 - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm0 = simde_mm_packs_pi32(xmm0, xmm0); - xmm2 = simde_mm_unpacklo_pi16(xmm0, xmm0); - - xmm1 = simde_mm_mulhrs_pi16(xmm2, QAM_amp); - xmm5 = simde_mm_mulhrs_pi16(xmm2, QAM_ampb); - - xmm0 = simde_mm_abs_pi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_pi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmm1 = simde_mm_abs_pi16(xmm0); - xmm1 = simde_mm_subs_pi16(xmm5, xmm1); // contains 8 LLRs - if (aarx == 0) - { - llr64[0] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0), simde_mm_extract_pi16(xmm4, 0)); - llr64[1] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm4, 1), simde_mm_extract_pi16(xmm1, 0)); - llr64[2] = simde_mm_set_pi32(simde_mm_extract_pi16(xmm1, 1), simde_mm_extract_pi16(xmm0, 1)); - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0], simde_mm_set_pi32(simde_mm_extract_pi16(xmm0, 0),simde_mm_extract_pi16(xmm4, 0))); - llr64[1] = simde_mm_adds_pi16(llr64[1], simde_mm_set_pi32(simde_mm_extract_pi16(xmm4, 1),simde_mm_extract_pi16(xmm1, 0))); - llr64[2] = simde_mm_adds_pi16(llr64[2], simde_mm_set_pi32(simde_mm_extract_pi16(xmm1, 1),simde_mm_extract_pi16(xmm0, 1))); - } - } -#endif -} - -void inner_rx_256qam (int *rxF, - int *ul_ch, - int16_t *llr, - int aarx, - int length, - int output_shift) -{ -#ifndef USE_128BIT - register simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4, xmmp5, xmmp6, xmmp7, xmmp8, xmmp9; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - - register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM256_n1); - register simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM256_n2); - register simde__m256i QAM_amp256c = simde_mm256_set1_epi16(QAM256_n3); - simde__m256i *rxF256 = (simde__m256i*)rxF; - simde__m256i *ulch256 = (simde__m256i*)ul_ch; - simde__m256i *llr256 = (simde__m256i *)llr; - for (int i = 0; i < ((length >> 3) + (( length & 7) > 0 ? 1 : 0)); i++) - { - xmmp0 = simde_mm256_madd_epi16(ulch256[i],rxF256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i],complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1,conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1,rxF256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1,output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0,xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0,xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); - - // compute channel amplitude for LLR - xmmp0 = simde_mm256_madd_epi16(ulch256[i],ulch256[i]); - xmmp0 = simde_mm256_srai_epi32(xmmp0,output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0,xmmp0); // contains 16 LLRs - xmmp2 = simde_mm256_unpacklo_epi16(xmmp0,xmmp0); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256); - xmmp6 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256b); - xmmp8 = simde_mm256_mulhrs_epi16(xmmp2,QAM_amp256c); - - xmmp2 = simde_mm256_abs_epi16(xmmp4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmmp2 = simde_mm256_subs_epi16(xmmp1,xmmp2); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmp2 contains 16 LLRs - xmmp7 = simde_mm256_abs_epi16(xmmp2); - xmmp7 = simde_mm256_subs_epi16(xmmp6,xmmp7); // contains 16 LLRs - xmmp9 = simde_mm256_abs_epi16(xmmp7); - xmmp9 = simde_mm256_subs_epi16(xmmp8,xmmp9); // contains 16 LLRs - - // xmmp4 A0 A1 A2 A3 A4 A5 A6 A7 - // xmmp2 B0 B1 B2 B3 B4 B5 B6 B7 - // xmmp7 C0 C1 C2 C3 C4 C5 C6 C7 - // xmmp9 D0 D1 D2 D3 D4 D5 D6 D7 - xmmp1 = simde_mm256_unpacklo_epi32(xmmp4,xmmp2); // A0 B0 A1 B1 A4 B4 A5 B5 - xmmp3 = simde_mm256_unpackhi_epi32(xmmp4,xmmp2); // A2 B2 A3 B3 A6 B6 A7 B7 - xmmp5 = simde_mm256_unpacklo_epi32(xmmp7,xmmp9); // C0 D0 C1 D1 C4 D4 C5 D5 - xmmp6 = simde_mm256_unpackhi_epi32(xmmp7,xmmp9); // C2 D2 C3 D3 C6 D6 C7 D7 - - xmmp2 = simde_mm256_unpacklo_epi64(xmmp1,xmmp5); // A0 B0 C0 D0 A4 B4 C4 D4 - xmmp4 = simde_mm256_unpackhi_epi64(xmmp1,xmmp5); // A1 B1 C1 D1 A5 B5 C5 D5 - xmmp1 = simde_mm256_unpacklo_epi64(xmmp3,xmmp6); // A2 B2 C2 D2 A6 B6 C6 D6 - xmmp5 = simde_mm256_unpackhi_epi64(xmmp3,xmmp6); // A3 B3 C3 D3 A7 B7 C7 D7 - if (aarx == 0) - { - llr256[0] = simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1 - llr256[1] = simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3 - llr256[2] = simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5 - llr256[3] = simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7 - llr256+=4; - } - else - { - llr256[0] = simde_mm256_adds_epi16(llr256[0],simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x20)); // A0 B0 C0 D0 A1 B1 C1 D1 - llr256[1] = simde_mm256_adds_epi16(llr256[1],simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x20)); // A2 B2 C2 D2 A3 B3 C3 D3 - llr256[2] = simde_mm256_adds_epi16(llr256[2],simde_mm256_permute2x128_si256(xmmp2, xmmp4, 0x31)); // A4 B4 C4 D4 A5 B5 C5 D5 - llr256[3] = simde_mm256_adds_epi16(llr256[3],simde_mm256_permute2x128_si256(xmmp1, xmmp5, 0x31)); // A6 B6 C6 D6 A7 B7 C7 D7 - llr256+=4; - } - } - simde__m128i *llr128 = (simde__m128i*)llr256; - if ((length&7) >= 4) { //there is a single 128-bit input element remaining - int nb_re128 = length>>2; - simde__m128i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; - simde__m128i complex_shuffle128 = simde_mm_set_epi8(13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m128i conj128 = simde_mm_set_epi16(1,-1,1,-1,1,-1,1,-1); - simde__m128i *rxF128 = (simde__m128i*)rxF; - simde__m128i *ulch128 = (simde__m128i*)ul_ch; - simde__m128i QAM_amp = simde_mm_set1_epi16(QAM256_n1); // 2/sqrt(10) - simde__m128i QAM_ampb = simde_mm_set1_epi16(QAM256_n2); - simde__m128i QAM_ampc = simde_mm_set1_epi16(QAM256_n3); - - xmm0 = simde_mm_madd_epi16(ulch128[nb_re128-1],rxF128[nb_re128-1]); - // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm1 = simde_mm_shuffle_epi8(ulch128[nb_re128-1],complex_shuffle128); - xmm1 = simde_mm_sign_epi16(xmm1,conj128); - xmm1 = simde_mm_madd_epi16(xmm1,rxF128[nb_re128-1]); - // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm0 = simde_mm_srai_epi32(xmm0,output_shift); - xmm1 = simde_mm_srai_epi32(xmm1,output_shift); - xmm2 = simde_mm_unpacklo_epi32(xmm0,xmm1); - xmm3 = simde_mm_unpackhi_epi32(xmm0,xmm1); - xmm4 = simde_mm_packs_epi32(xmm2,xmm3); - - // compute channel amplitude for LLR - xmm0 = simde_mm_madd_epi16(ulch128[nb_re128-1],ulch128[nb_re128-1]); - xmm0 = simde_mm_srai_epi32(xmm0,output_shift); - xmm0 = simde_mm_packs_epi32(xmm0,xmm0); // contains 16 LLRs - xmm2 = simde_mm_unpacklo_epi16(xmm0,xmm0); - xmm1 = simde_mm_mulhrs_epi16(xmm2,QAM_amp); - xmm5 = simde_mm_mulhrs_epi16(xmm2,QAM_ampb); - xmm6 = simde_mm_mulhrs_epi16(xmm2,QAM_ampc); - xmm0 = simde_mm_abs_epi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_epi16(xmm1,xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmp2 contains 8 LLRs - xmm1 = simde_mm_abs_epi16(xmm0); - xmm1 = simde_mm_subs_epi16(xmm5,xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_epi16(xmm1); - xmm2 = simde_mm_subs_epi16(xmm6,xmm2); // contains 8 LLRs - // rxF[i] A0 A1 A2 A3 - // xmm0 B0 B1 B2 B3 - // xmm1 C0 C1 C2 C3 - // xmm2 D0 D1 D2 D3 - xmm3 = simde_mm_unpacklo_epi32(rxF128[nb_re128-1],xmm0); // A0 B0 A1 B1 - xmm4 = simde_mm_unpackhi_epi32(rxF128[nb_re128-1],xmm0); // A2 B2 A3 B3 - xmm5 = simde_mm_unpacklo_epi32(xmm1,xmm2); // C0 D0 C1 D1 - xmm6 = simde_mm_unpackhi_epi32(xmm1,xmm2); // C2 D2 C3 D3 - if (aarx == 0) { - llr128[0] = simde_mm_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0 - llr128[1] = simde_mm_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1 - llr128[2] = simde_mm_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2 - llr128[3] = simde_mm_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3 - llr128+=4; - } - else - { - llr128[0] = simde_mm_adds_epi16(llr128[0],simde_mm_unpacklo_epi64(xmm3,xmm5)); // A0 B0 C0 D0 - llr128[1] = simde_mm_adds_epi16(llr128[1],simde_mm_unpackhi_epi64(xmm3,xmm5)); // A1 B1 C1 D1 - llr128[2] = simde_mm_adds_epi16(llr128[2],simde_mm_unpacklo_epi64(xmm4,xmm6)); // A2 B2 C2 D2 - llr128[3] = simde_mm_adds_epi16(llr128[3],simde_mm_unpackhi_epi64(xmm4,xmm6)); // A3 B3 C3 D3 - llr128+=4; - } - } -#else - simde__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; - simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - simde__m128i *rxF128 = (simde__m128i*)rxF; - simde__m128i *ulch128 = (simde__m128i*)ul_ch; - simde__m128i QAM_amp = simde_mm_set1_epi16(QAM256_n1); - simde__m128i QAM_ampb = simde_mm_set1_epi16(QAM256_n2); - simde__m128i QAM_ampc = simde_mm_set1_epi16(QAM256_n3); - simde__m128i *llr128 = (simde__m128i*)llr; - for (int i = 0; i < (length >> 2); i++) - { - xmm0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmm1 = simde_mm_sign_epi16(xmm1, conj128); - xmm1 = simde_mm_madd_epi16(xmm1, rxF128[i]); - // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm0 = simde_mm_srai_epi32(xmm0, output_shift); - xmm1 = simde_mm_srai_epi32(xmm1, output_shift); - xmm2 = simde_mm_unpacklo_epi32(xmm0, xmm1); - xmm3 = simde_mm_unpackhi_epi32(xmm0, xmm1); - xmm4 = simde_mm_packs_epi32(xmm2, xmm3); - - // compute channel amplitude for LLR - xmm0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 - xmm0 = simde_mm_srai_epi32(xmm0, output_shift); - xmm0 = simde_mm_packs_epi32(xmm0, xmm0); - xmm2 = simde_mm_unpacklo_epi16(xmm0, xmm0); - - xmm1 = simde_mm_mulhrs_epi16(xmm2, QAM_amp); - xmm5 = simde_mm_mulhrs_epi16(xmm2, QAM_ampb); - xmm6 = simde_mm_mulhrs_epi16(xmm2, QAM_ampc); - - xmm0 = simde_mm_abs_epi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_epi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmm1 = simde_mm_abs_epi16(xmm0); - xmm1 = simde_mm_subs_epi16(xmm5, xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_epi16(xmm1); - xmm2 = simde_mm_subs_epi16(xmm6, xmm2); // contains 8 LLRs - // rxF[i] A0 A1 A2 A3 - // xmm0 B0 B1 B2 B3 - // xmm1 C0 C1 C2 C3 - // xmm2 D0 D1 D2 D3 - xmm3 = simde_mm_unpacklo_epi32(xmm4, xmm0); // A0 B0 A1 B1 - xmm4 = simde_mm_unpackhi_epi32(xmm4, xmm0); // A2 B2 A3 B3 - xmm5 = simde_mm_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 - xmm6 = simde_mm_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 - if (aarx == 0) { - llr128[0] = simde_mm_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 - llr128[1] = simde_mm_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 - llr128[2] = simde_mm_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2 - llr128[3] = simde_mm_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3 - } - else { - llr128[0] = simde_mm_adds_epi16(llr128[0], simde_mm_unpacklo_epi64(xmm3, xmm5)); // A0 B0 C0 D0 - llr128[1] = simde_mm_adds_epi16(llr128[1], simde_mm_unpackhi_epi64(xmm3, xmm5)); // A1 B1 C1 D1 - llr128[2] = simde_mm_adds_epi16(llr128[2], simde_mm_unpacklo_epi64(xmm4, xmm6)); // A2 B2 C2 D2 - llr128[3] = simde_mm_adds_epi16(llr128[3], simde_mm_unpackhi_epi64(xmm4, xmm6)); // A3 B3 C3 D3 - } - llr128+=4; - } - if (length & 3) - { - simde__m64 *llr64 = (simde__m64*) llr128; - int i = (length>>1) - 1; - simde__m64 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; - simde__m64 complex_shuffle64 = simde_mm_set_pi8(5,4,7,6,1,0,3,2); - simde__m64 conj64 = simde_mm_set_pi16(1, -1, 1, -1); - simde__m64 *rxF64 = (simde__m64*)rxF; - simde__m64 *ulch64 = (simde__m64*)ul_ch; - simde__m64 QAM_amp = simde_mm_set1_pi16(QAM256_n1); - simde__m64 QAM_ampb = simde_mm_set1_pi16(QAM256_n2); - simde__m64 QAM_ampc = simde_mm_set1_pi16(QAM256_n3); - - xmm0 = simde_mm_madd_pi16(ulch64[i], rxF64[i]); - // xmm0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm1 = simde_mm_shuffle_pi8(ulch64[i], complex_shuffle64); - xmm1 = simde_mm_sign_pi16(xmm1, conj64); - xmm1 = simde_mm_madd_pi16(xmm1, rxF64[i]); - // xmm1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm1 = simde_mm_srai_pi32(xmm1, output_shift); - xmm2 = simde_mm_unpacklo_pi32(xmm0, xmm1); - xmm3 = simde_mm_unpackhi_pi32(xmm0, xmm1); - xmm4 = simde_mm_packs_pi32(xmm2, xmm3); - - // compute channel amplitude for LLR - xmm0 = simde_mm_madd_pi16(ulch64[i], ulch64[i]); // |h|^2 - xmm0 = simde_mm_srai_pi32(xmm0, output_shift); - xmm0 = simde_mm_packs_pi32(xmm0, xmm0); - xmm2 = simde_mm_unpacklo_pi16(xmm0, xmm0); - - xmm1 = simde_mm_mulhrs_pi16(xmm2, QAM_amp); - xmm5 = simde_mm_mulhrs_pi16(xmm2, QAM_ampb); - xmm6 = simde_mm_mulhrs_pi16(xmm2, QAM_ampc); - - xmm0 = simde_mm_abs_pi16(xmm4); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_pi16(xmm1, xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmm1 = simde_mm_abs_pi16(xmm0); - xmm1 = simde_mm_subs_pi16(xmm5, xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_pi16(xmm1); - xmm2 = simde_mm_subs_pi16(xmm6, xmm2); // contains 8 LLRs - - xmm3 = simde_mm_unpacklo_pi32(xmm4, xmm0); - xmm4 = simde_mm_unpackhi_pi32(xmm4, xmm0); - xmm5 = simde_mm_unpacklo_pi32(xmm1, xmm2); - xmm6 = simde_mm_unpackhi_pi32(xmm1, xmm2); - if (aarx == 0) { - llr64[0] = simde_m_punpckldq(xmm3, xmm5); - llr64[1] = simde_m_punpckhdq(xmm3, xmm5); - llr64[2] = simde_m_punpckldq(xmm4, xmm6); - llr64[3] = simde_m_punpckhdq(xmm4, xmm6); - } - else - { - llr64[0] = simde_mm_adds_pi16(llr64[0], simde_m_punpckldq(xmm3, xmm5)); - llr64[1] = simde_mm_adds_pi16(llr64[1], simde_m_punpckhdq(xmm3, xmm5)); - llr64[2] = simde_mm_adds_pi16(llr64[2], simde_m_punpckldq(xmm4, xmm6)); - llr64[3] = simde_mm_adds_pi16(llr64[3], simde_m_punpckhdq(xmm4, xmm6)); - } - } -#endif -} - -void inner_rx_qpsk_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - int **rxF, - int **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) -{ - int add_shift = 0; - if (length % 8) - add_shift = 8 - length % 8; - int32_t rxFext[nb_rx_ant][length + add_shift] __attribute__((aligned(32))); - int32_t chFext[nb_layer*nb_rx_ant][length + add_shift] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - for (int aatx = 0; aatx < nb_layer; aatx++) - { - nr_ulsch_extract_rbs0((c16_t *)rxF[aarx], - pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx * nb_rx_ant + aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - int32_t rho[nb_layer*nb_layer][length + add_shift] __attribute__((aligned(32))); - int32_t rxFext_comp[nb_layer][length + add_shift] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - for (int aatx = 0; aatx < nb_layer; aatx++) - { - for (int atx = 0; atx < nb_layer; atx++) - { -#ifdef USE_128BIT - simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, mmtmpD4; - simde__m128i *rho128 = (simde__m128i *)rho[aatx*nb_layer+atx]; - simde__m128i *ul_ch128 = (simde__m128i *)chFext[aatx * nb_rx_ant + aarx]; - simde__m128i *ul_ch128_2 = (simde__m128i *)chFext[atx * nb_rx_ant + aarx]; - for (int i = 0; i < (length >> 2)+((length&3)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[i], ul_ch128_2[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[i], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i*)&conjugate[0]); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, ul_ch128_2[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - mmtmpD4 = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); - if (aarx == 0) - rho128[i] = mmtmpD4; - else - rho128[i] = simde_mm_adds_epi16(rho128[i], mmtmpD4); - } -#else - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, mmtmpD4; - simde__m256i *rho256 = (simde__m256i *)rho[aatx*nb_layer+atx]; - simde__m256i *ul_ch256 = (simde__m256i *)chFext[aatx * nb_rx_ant + aarx]; - simde__m256i *ul_ch256_2 = (simde__m256i *)chFext[atx * nb_rx_ant + aarx]; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - for (int i = 0; i < ((length >> 3)+((length&7)?1:0)); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(ul_ch256[i], ul_ch256_2[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(ul_ch256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, ul_ch256_2[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - mmtmpD4 = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); - if (aarx == 0) - rho256[i] = mmtmpD4; - else - rho256[i] = simde_mm256_adds_epi16(rho256[i], mmtmpD4); - } -#endif - } - // compensation -#ifdef USE_128BIT - simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - simde__m128i *rxF128 = (simde__m128i*)rxFext[aarx]; - simde__m128i *ulch128 = (simde__m128i*)chFext[aatx * nb_rx_ant + aarx]; - simde__m128i *rxF_comp128 = (simde__m128i*)rxFext_comp[aatx]; - for (int i = 0; i < (length>>2) + ((length&3)?1:0); i++) - { - xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); - xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); - - if (aarx == 0) - *rxF_comp128 = xmmp4; - else - *rxF_comp128 = simde_mm_adds_epi16(*rxF_comp128, xmmp4); - - rxF_comp128++; - } -#else - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *ulch256 = (simde__m256i*)chFext[aatx * nb_rx_ant + aarx]; - simde__m256i *rxF_comp256 = (simde__m256i*)rxFext_comp[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - if (aarx == 0) - *rxF_comp256 = xmmp4; - else - *rxF_comp256 = simde_mm256_adds_epi16(*rxF_comp256, xmmp4); - - rxF_comp256++; - } -#endif - } - } - c16_t *rho0 = (c16_t *)rho[1]; - c16_t *rho1 = (c16_t *)rho[2]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - - nr_ulsch_qpsk_qpsk((c16_t *)rxFext_comp[0], (c16_t *)rxFext_comp[1], llr_0, rho0, length); - nr_ulsch_qpsk_qpsk((c16_t *)rxFext_comp[1], (c16_t *)rxFext_comp[0], llr_1, rho1, length); - - nr_ulsch_shift_llr(pusch_vars->llr_layers, length, pusch_vars->llr_offset[symbol] >> 1, 2, 4); - -} - - -void inner_rx_16qam_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - int **rxF, - int **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) -{ - int add_shift = 0; - if (length % 8) - add_shift = 8 - length % 8; - - int32_t rxFext[nb_rx_ant][length + add_shift] __attribute__((aligned(32))); - int32_t chFext[nb_layer*nb_rx_ant][length + add_shift] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - for (int aatx = 0; aatx < nb_layer; aatx++) - { - nr_ulsch_extract_rbs0((c16_t *)rxF[aarx], - pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx * nb_rx_ant + aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - - int32_t rho[nb_layer*nb_layer][length + add_shift] __attribute__((aligned(32))); - int32_t rxFext_comp[nb_layer][length + add_shift] __attribute__((aligned(32))); - int32_t ul_ch_mag[nb_layer][length + add_shift] __attribute__((aligned(32))); - for (int aatx = 0; aatx < nb_layer; aatx++) - { - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - for (int atx = 0; atx < nb_layer; atx++) - { -#ifdef USE_128BIT - simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m128i *rho128 = (simde__m128i *)rho[aatx*nb_layer+atx]; - simde__m128i *ul_ch128 = (simde__m128i *)chFext[aatx * nb_rx_ant + aarx]; - simde__m128i *ul_ch128_2 = (simde__m128i *)chFext[atx * nb_rx_ant + aarx]; - for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[i], ul_ch128_2[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[i], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i*)&conjugate[0]); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, ul_ch128_2[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - if (aarx == 0) - rho128[i] = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); - else - rho128[i] = simde_mm_adds_epi16(rho128[i], simde_mm_packs_epi32(mmtmpD2, mmtmpD3)); - } -#else - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m256i *rho256 = (simde__m256i *)rho[aatx*nb_layer+atx]; - simde__m256i *ul_ch256 = (simde__m256i *)chFext[aatx * nb_rx_ant + aarx]; - simde__m256i *ul_ch256_2 = (simde__m256i *)chFext[atx * nb_rx_ant + aarx]; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(ul_ch256[i], ul_ch256_2[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(ul_ch256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, ul_ch256_2[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - if (aarx == 0) - rho256[i] = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); - else - rho256[i] = simde_mm256_adds_epi16(rho256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); - } -#endif - } - // compensation -#ifdef USE_128BIT - simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM16_n1); // 2/sqrt(10) - simde__m128i *rxF128 = (simde__m128i*)rxFext[aarx]; - simde__m128i *ulch128 = (simde__m128i*)chFext[aatx * nb_rx_ant + aarx]; - simde__m128i *rxF_comp128 = (simde__m128i*)rxFext_comp[aatx]; - simde__m128i *ul_ch_mag128 = (simde__m128i*)ul_ch_mag[aatx]; - for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) - { - xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); - xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm_mulhrs_epi16(xmmp1, QAM_amp128); - - if (aarx == 0) - { - *rxF_comp128 = xmmp4; - *ul_ch_mag128 = xmmp1; - } - else - { - *rxF_comp128 = simde_mm_adds_epi16(*rxF_comp128, xmmp4); - *ul_ch_mag128 = simde_mm_adds_epi16(*ul_ch_mag128, xmmp1); - } - rxF_comp128++; - ul_ch_mag128++; - } -#else - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); // 2/sqrt(10) - simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *ulch256 = (simde__m256i*)chFext[aatx * nb_rx_ant + aarx]; - simde__m256i *rxF_comp256 = (simde__m256i*)rxFext_comp[aatx]; - simde__m256i *ul_ch_mag256 = (simde__m256i*)ul_ch_mag[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); - - if (aarx == 0) - { - *rxF_comp256 = xmmp4; - *ul_ch_mag256 = xmmp1; - } - else - { - *rxF_comp256 = simde_mm256_adds_epi16(*rxF_comp256, xmmp4); - *ul_ch_mag256 = simde_mm256_adds_epi16(*ul_ch_mag256, xmmp1); - } - rxF_comp256++; - ul_ch_mag256++; - } -#endif - } - } - c16_t *rho0 = (c16_t *)rho[1]; - c16_t *rho1 = (c16_t *)rho[2]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - c16_t *ul_ch_mag0 = (c16_t *)ul_ch_mag[0]; - c16_t *ul_ch_mag1 = (c16_t *)ul_ch_mag[1]; - nr_ulsch_qam16_qam16((c16_t *)rxFext_comp[0], (c16_t *)rxFext_comp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); - nr_ulsch_qam16_qam16((c16_t *)rxFext_comp[1], (c16_t *)rxFext_comp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); -} - -void inner_rx_64qam_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - int **rxF, - int **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) -{ - int add_shift = 0; - if (length % 8) - add_shift = 8 - length % 8; - - int32_t rxFext[nb_rx_ant][length + add_shift] __attribute__((aligned(32))); - int32_t chFext[nb_layer*nb_rx_ant][length + add_shift] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - for (int aatx = 0; aatx < nb_layer; aatx++) - { - nr_ulsch_extract_rbs0((c16_t *)rxF[aarx], - pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx * nb_rx_ant + aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - int32_t rho[nb_layer*nb_layer][length + add_shift] __attribute__((aligned(32))); - int32_t rxFext_comp[nb_layer][length + add_shift] __attribute__((aligned(32))); - int32_t ul_ch_mag[nb_layer][length + add_shift] __attribute__((aligned(32))); - for (int aatx = 0; aatx < nb_layer; aatx++) - { - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - for (int atx = 0; atx < nb_layer; atx++) - { -#ifdef USE_128BIT - simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m128i *rho128 = (simde__m128i *)rho[aatx*nb_layer+atx]; - simde__m128i *ul_ch128 = (simde__m128i *)chFext[aatx * nb_rx_ant + aarx]; - simde__m128i *ul_ch128_2 = (simde__m128i *)chFext[atx * nb_rx_ant + aarx]; - for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[i], ul_ch128_2[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[i], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i*)&conjugate[0]); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, ul_ch128_2[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - if (aarx == 0) - rho128[i] = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); - else - rho128[i] = simde_mm_adds_epi16(rho128[i], simde_mm_packs_epi32(mmtmpD2, mmtmpD3)); - } -#else - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m256i *rho256 = (simde__m256i *)rho[aatx*nb_layer+atx]; - simde__m256i *ul_ch256 = (simde__m256i *)chFext[aatx * nb_rx_ant + aarx]; - simde__m256i *ul_ch256_2 = (simde__m256i *)chFext[atx * nb_rx_ant + aarx]; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(ul_ch256[i], ul_ch256_2[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(ul_ch256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, ul_ch256_2[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - if (aarx == 0) - rho256[i] = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); - else - rho256[i] = simde_mm256_adds_epi16(rho256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); - } -#endif - } - // compensation -#ifdef USE_128BIT - simde__m128i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m128i complex_shuffle128 = simde_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); - register simde__m128i conj128 = simde_mm_set_epi16(1, -1, 1, -1, 1, -1, 1, -1); - register simde__m128i QAM_amp128 = simde_mm_set1_epi16(QAM64_n1); // 2/sqrt(10) - simde__m128i *rxF128 = (simde__m128i*)rxFext[aarx]; - simde__m128i *ulch128 = (simde__m128i*)chFext[aatx * nb_rx_ant + aarx]; - simde__m128i *rxF_comp128 = (simde__m128i*)rxFext_comp[aatx]; - simde__m128i *ul_ch_mag128 = (simde__m128i*)ul_ch_mag[aatx]; - for (int i = 0; i < (length>>2)+((length&3)?1:0); i++) - { - xmmp0 = simde_mm_madd_epi16(ulch128[i], rxF128[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm_shuffle_epi8(ulch128[i], complex_shuffle128); - xmmp1 = simde_mm_sign_epi16(xmmp1, conj128); - xmmp1 = simde_mm_madd_epi16(xmmp1, rxF128[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm_madd_epi16(ulch128[i], ulch128[i]); // |h|^2 - xmmp0 = simde_mm_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm_mulhrs_epi16(xmmp1, QAM_amp128); - - if (aarx == 0) - { - *rxF_comp128 = xmmp4; - *ul_ch_mag128 = xmmp1; - } - else - { - *rxF_comp128 = simde_mm_adds_epi16(*rxF_comp128, xmmp4); - *ul_ch_mag128 = simde_mm_adds_epi16(*ul_ch_mag128, xmmp1); - } - rxF_comp128++; - ul_ch_mag128++; - } -#else - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - register simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - register simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - register simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) - simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *ulch256 = (simde__m256i*)chFext[aatx * nb_rx_ant + aarx]; - simde__m256i *rxF_comp256 = (simde__m256i*)rxFext_comp[aatx]; - simde__m256i *ul_ch_mag256 = (simde__m256i*)ul_ch_mag[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); - - if (aarx == 0) - { - *rxF_comp256 = xmmp4; - *ul_ch_mag256 = xmmp1; - } - else - { - *rxF_comp256 = simde_mm256_adds_epi16(*rxF_comp256, xmmp4); - *ul_ch_mag256 = simde_mm256_adds_epi16(*ul_ch_mag256, xmmp1); - } - rxF_comp256++; - ul_ch_mag256++; - } -#endif - } - } - c16_t *rho0 = (c16_t *)rho[1]; - c16_t *rho1 = (c16_t *)rho[2]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - c16_t *ul_ch_mag0 = (c16_t *)ul_ch_mag[0]; - c16_t *ul_ch_mag1 = (c16_t *)ul_ch_mag[1]; - nr_ulsch_qam64_qam64((c16_t *)rxFext_comp[0], (c16_t *)rxFext_comp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); - nr_ulsch_qam64_qam64((c16_t *)rxFext_comp[1], (c16_t *)rxFext_comp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); -} - -void nr_pusch_symbol_processing_noprecoding(void *arg) -{ - - puschSymbolProc_t *rdata=(puschSymbolProc_t*)arg; - - PHY_VARS_gNB *gNB = rdata->gNB; - NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; - nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; - int ulsch_id = rdata->ulsch_id; - int slot = rdata->slot; - NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; - int16_t *s = rdata->s; - for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) - { - int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; - // this needs to be reworded for parrellization, we need a table which give dmrs symbol location - // used for chennel estimate, they are being run in parallel! - if (dmrs_symbol_flag == 1) - { - if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) - AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); - - gNB->pusch_vars[ulsch_id].dmrs_symbol = symbol; - } - - LOG_I(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id].dmrs_symbol); - - if (nb_re_pusch == 0) continue; - if (rel15_ul->nrOfLayers == 1) - { - int16_t *llr = &rdata->llr[pusch_vars->llr_offset[symbol]]; - void (*inner_rx)(int *,int *,int16_t *,int,int,int); - if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk; - else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam; - else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam; - else if (rel15_ul->qam_mod_order == 8) inner_rx = inner_rx_256qam; - else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", - rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); - - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - int32_t rxFext[nb_re_pusch+8] __attribute__((aligned(32))); - int32_t chFext[nb_re_pusch+8] __attribute__((aligned(32))); - int16_t llr_temp[(nb_re_pusch*rel15_ul->qam_mod_order)+16] __attribute__((aligned(32))); - for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) - { - nr_ulsch_extract_rbs0(gNB->common_vars.rxdataF[aa], - gNB->pusch_vars[ulsch_id].ul_ch_estimates[aa], - rxFext, - chFext, - soffset+(symbol * frame_parms->ofdm_symbol_size), - gNB->pusch_vars[ulsch_id].dmrs_symbol*frame_parms->ofdm_symbol_size, - aa, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - // demodulation - inner_rx(rxFext, chFext, llr_temp, aa, nb_re_pusch, gNB->pusch_vars[ulsch_id].log2_maxh); - } - - // unscrambling - simde__m64 *llr64 = (simde__m64 *) llr; - for (int i=0;i<(nb_re_pusch*rel15_ul->qam_mod_order)>>2;i++) - llr64[i] = simde_mm_mullo_pi16(((simde__m64 *)llr_temp)[i],((simde__m64 *)s)[i]); - - s += nb_re_pusch * rel15_ul->qam_mod_order; - llr += nb_re_pusch * rel15_ul->qam_mod_order; - } - else // MIMO for 2x2 - { - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - void (*inner_rx)(NR_DL_FRAME_PARMS *, - NR_gNB_PUSCH *, - nfapi_nr_pusch_pdu_t *, - int32_t **, - int32_t **, - int16_t **, - int32_t, - int32_t, - int32_t, - int32_t, - int32_t, - int16_t, - int32_t, - int32_t); - if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk_2layer; - else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam_2layer; - else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam_2layer; - else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", - rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); - - inner_rx(frame_parms, - pusch_vars, - rel15_ul, - (int32_t**)gNB->common_vars.rxdataF, - gNB->pusch_vars[ulsch_id].ul_ch_estimates, - rdata->llr_layers, - rel15_ul->nrOfLayers, - frame_parms->nb_antennas_rx, - soffset, - nb_re_pusch, // length - symbol, // symbol index - rel15_ul->rb_size, // ofdm size - dmrs_symbol_flag, - gNB->pusch_vars[ulsch_id].log2_maxh); - - // layer de-mapping - int16_t* llr_cw = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; - for (int i = 0; i < (nb_re_pusch); i++) - for (int l = 0; l < rel15_ul->nrOfLayers; l++) - for (int m = 0; m < rel15_ul->qam_mod_order; m++) - llr_cw[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; - - // unscrambling - simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; - for (int i = 0; i < (nb_re_pusch*rel15_ul->qam_mod_order*rel15_ul->nrOfLayers)>>2; i++) - llr64[i] = simde_mm_mullo_pi16(((simde__m64 *)llr64)[i], ((simde__m64 *)s)[i]); - - s += (nb_re_pusch*rel15_ul->qam_mod_order*rel15_ul->nrOfLayers); - } - } -} - //compute average channel_level on each (TX,RX) antenna pair void nr_ulsch_channel_level(int **ul_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, @@ -2088,8 +548,6 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, uint8_t nrOfLayers, unsigned short nb_rb) { - - short rb; unsigned char aatx, aarx; simde__m128i *ul_ch128, avg128U; @@ -2124,10 +582,9 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, simde_mm_empty(); simde_m_empty(); - } -static simde__m128i a_mult_conjb(simde__m128i a, simde__m128i b, unsigned char output_shift) +static simde__m128i a_mult_conjb(__m128i a, __m128i b, unsigned char output_shift) { simde__m128i mmtmpD0 = simde_mm_madd_epi16(b, a); simde__m128i mmtmpD1 = simde_mm_shufflelo_epi16(b, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); @@ -2138,7 +595,7 @@ static simde__m128i a_mult_conjb(simde__m128i a, simde__m128i b, unsigned char o mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); simde__m128i mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); simde__m128i mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - return simde_mm_packs_epi32(mmtmpD2, mmtmpD3); + return _mm_packs_epi32(mmtmpD2, mmtmpD3); } //============================================================================================== @@ -2202,29 +659,30 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, #endif +#if defined(__i386) || defined(__x86_64__) unsigned short rb; unsigned char aatx,aarx; - simde__m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*ul_ch_mag128c,*rxdataF128,*rxdataF_comp128,*rho128; - simde__m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128c={0}; - QAM_amp128b = simde_mm_setzero_si128(); + __m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*ul_ch_mag128c,*rxdataF128,*rxdataF_comp128,*rho128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128c={0}; + QAM_amp128b = _mm_setzero_si128(); uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); for (aatx=0; aatxnb_antennas_rx][symbol * (off + nb_rb * 12)]; - ul_ch_mag128b_1 = (simde__m128i *)&ul_ch_magb[frame_parms->nb_antennas_rx][symbol * (off + nb_rb * 12)]; - ul_ch_mag128c_1 = (simde__m128i *)&ul_ch_magc[frame_parms->nb_antennas_rx][symbol * (off + nb_rb * 12)]; + ul_ch_mag128_1 = (simde__m128i *) &((int *)ul_ch_mag)[1 * (length + length_aligned)]; + ul_ch_mag128b_1 = (simde__m128i *)&((int *)ul_ch_magb)[1 * (length + length_aligned)]; + ul_ch_mag128c_1 = (simde__m128i *)&((int *)ul_ch_magc)[1 * (length + length_aligned)]; } for (int rb = 0; rb < 3 * nb_rb_0; rb++) { @@ -3245,340 +1696,981 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, return(0); } -//============================================================================================== +void inner_rx_qpsk (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t *llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; -/* Main Function */ -void nr_rx_pusch(PHY_VARS_gNB *gNB, - uint8_t ulsch_id, - uint32_t frame, - uint8_t slot, - unsigned char harq_pid) + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t*)pusch_vars->ul_ch_estimates[aarx], + rxFext[aarx], + chFext[aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + + simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *ulch256 = (simde__m256i*)chFext[aarx]; + simde__m256i *llr256 = (simde__m256i *)llr; + for (int i = 0; i < ((length>>3) + ((length&7) > 0 ? 1:0)); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); + + // MRC & LLR + llr256[i] = simde_mm256_add_epi16(llr256[i], xmmp4); + } + } + // Perform IDFT if transform precoding is enabled + if(rel15_ul->transform_precoding == transformPrecoder_enabled) + nr_idft((int32_t *)llr, length); +} + +void inner_rx_16qam (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t *llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t rxComp[length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_maga[length + length_aligned] __attribute__((aligned(32))); + + memset(rxComp, 0, sizeof(c16_t) * (length + length_aligned)); + memset(rxF_ch_maga, 0, sizeof(c16_t) * (length + length_aligned)); + + simde__m256i *rxComp_256 = (simde__m256i *)rxComp; + simde__m256i *rxF_ch_maga_256 = (simde__m256i *)rxF_ch_maga; + + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t*)pusch_vars->ul_ch_estimates[aarx], + rxFext[aarx], + chFext[aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); + + simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i*)chFext[aarx]; + for (int i = 0; i < ((length>>3) + ((length&7) > 0 ? 1:0)); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp0 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + + xmmp1 = simde_mm256_mulhrs_epi16(xmmp0, QAM_amp256); + + // MRC + rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp1); + rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); + } + } + + if (rel15_ul->transform_precoding == transformPrecoder_enabled) + { + nr_freq_equalization(frame_parms, + (int *)rxComp, + (int *)rxF_ch_maga, + (int *)rxF_ch_maga, + symbol, + length, + rel15_ul->qam_mod_order); + nr_idft((int32_t*)rxComp, length); + } + nr_ulsch_compute_llr((int32_t *)rxComp, + (int32_t *)rxF_ch_maga, + NULL, + NULL, + llr, + rel15_ul->rb_size, + length, + symbol, + rel15_ul->qam_mod_order); +} + +void inner_rx_64qam (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t *llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + + c16_t rxComp[length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_maga[length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_magb[length + length_aligned] __attribute__((aligned(32))); + + memset(rxComp, 0, sizeof(c16_t) * (length + length_aligned)); + memset(rxF_ch_maga, 0, sizeof(c16_t) * (length + length_aligned)); + memset(rxF_ch_magb, 0, sizeof(c16_t) * (length + length_aligned)); + + simde__m256i *rxComp_256 = (simde__m256i *)rxComp; + simde__m256i *rxF_ch_maga_256 = (simde__m256i *)rxF_ch_maga; + simde__m256i *rxF_ch_magb_256 = (simde__m256i *)rxF_ch_magb; + + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t*)pusch_vars->ul_ch_estimates[aarx], + rxFext[aarx], + chFext[aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) + simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM64_n2); + + simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i*)chFext[aarx]; + for (int i = 0; i < ((length>>3) + ((length&7) > 0 ? 1:0)); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp0 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + + xmmp1 = simde_mm256_mulhrs_epi16(xmmp0, QAM_amp256); + xmmp2 = simde_mm256_mulhrs_epi16(xmmp0, QAM_amp256b); + + // MRC + rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); + rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp1); + rxF_ch_magb_256[i] = simde_mm256_add_epi16(rxF_ch_magb_256[i], xmmp2); + } + } + + if (rel15_ul->transform_precoding == transformPrecoder_enabled) { + nr_freq_equalization(frame_parms, + (int *)rxComp, + (int *)rxF_ch_maga, + (int *)rxF_ch_magb, + symbol, + length, + rel15_ul->qam_mod_order); + nr_idft((int32_t*)rxComp, length); + } + nr_ulsch_compute_llr((int32_t*)rxComp, + (int32_t*)rxF_ch_maga, + (int32_t*)rxF_ch_magb, + NULL, + llr, + rel15_ul->rb_size, + length, + symbol, + rel15_ul->qam_mod_order); +} + +void inner_rx_256qam (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t *llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t rxComp[length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_maga[length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_magb[length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_magc[length + length_aligned] __attribute__((aligned(32))); + + memset(rxComp, 0, sizeof(c16_t) * (length + length_aligned)); + memset(rxF_ch_maga, 0, sizeof(c16_t) * (length + length_aligned)); + memset(rxF_ch_magb, 0, sizeof(c16_t) * (length + length_aligned)); + memset(rxF_ch_magc, 0, sizeof(c16_t) * (length + length_aligned)); + + simde__m256i *rxComp_256 = (simde__m256i *)rxComp; + simde__m256i *rxF_ch_maga_256 = (simde__m256i *)rxF_ch_maga; + simde__m256i *rxF_ch_magb_256 = (simde__m256i *)rxF_ch_magb; + simde__m256i *rxF_ch_magc_256 = (simde__m256i *)rxF_ch_magc; + + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t*)pusch_vars->ul_ch_estimates[aarx], + rxFext[aarx], + chFext[aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + + simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM256_n1); + simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM256_n2); + simde__m256i QAM_amp256c = simde_mm256_set1_epi16(QAM256_n3); + + simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *ulch256 = (simde__m256i*)chFext[aarx]; + for (int i = 0; i < ((length >> 3) + (( length & 7) > 0 ? 1 : 0)); i++) + { + xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); + // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); + // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + // compute channel amplitude for LLR + xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); // contains 16 LLRs + xmmp2 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + xmmp0 = simde_mm256_mulhrs_epi16(xmmp2, QAM_amp256); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp2, QAM_amp256b); + xmmp2 = simde_mm256_mulhrs_epi16(xmmp2, QAM_amp256c); + + // MRC + rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); + rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp0); + rxF_ch_magb_256[i] = simde_mm256_add_epi16(rxF_ch_magb_256[i], xmmp1); + rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], xmmp2); + } + } + nr_ulsch_compute_llr((int32_t*)rxComp, + (int32_t*)rxF_ch_maga, + (int32_t*)rxF_ch_magb, + (int32_t*)rxF_ch_magc, + llr, + rel15_ul->rb_size, + length, + symbol, + rel15_ul->qam_mod_order); +} + +void inner_rx_qpsk_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift, + uint32_t nvar) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) + { + for (int aatx = 0; aatx < nb_layer; aatx++) + { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t*)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx][aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); + + memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer * (length + length_aligned)); + + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int aatx = 0; aatx < nb_layer; aatx++) { + for (int atx = 0; atx < nb_layer; atx++) { + simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, mmtmpD4; + simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; + simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + for (int i = 0; i < ((length >> 3)+((length&7)?1:0)); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + mmtmpD4 = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); + + rho_256[i] = simde_mm256_adds_epi16(rho_256[i], mmtmpD4); + } + } + // compensation + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; + simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); + } + } + } + c16_t *rho0 = rho[0][1]; + c16_t *rho1 = rho[1][0]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + + nr_ulsch_qpsk_qpsk(rxComp[0], rxComp[1], llr_0, rho0, length); + nr_ulsch_qpsk_qpsk(rxComp[1], rxComp[0], llr_1, rho1, length); + + nr_ulsch_shift_llr(pusch_vars->llr_layers, length, pusch_vars->llr_offset[symbol] >> 1, 2, 4); +} + + +void inner_rx_16qam_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift, + uint32_t nvar) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int aatx = 0; aatx < nb_layer; aatx++) { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t*)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx][aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + + c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); + + memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer * (length + length_aligned)); + memset(ul_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + + for (int aatx = 0; aatx < nb_layer; aatx++) { + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int atx = 0; atx < nb_layer; atx++) { + simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; + simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; + simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; + for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + + rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); + } + } + // compensation + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); // 2/sqrt(10) + simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; + simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; + simde__m256i *ul_ch_maga_256 = (simde__m256i*)ul_ch_maga[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); + + rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); + ul_ch_maga_256[i] = simde_mm256_adds_epi16(ul_ch_maga_256[i], xmmp1); + } + } + } + c16_t *rho0 = rho[0][1]; + c16_t *rho1 = rho[1][0]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + c16_t *ul_ch_mag0 = ul_ch_maga[0]; + c16_t *ul_ch_mag1 = ul_ch_maga[1]; + nr_ulsch_qam16_qam16(rxComp[0], rxComp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); + nr_ulsch_qam16_qam16(rxComp[1], rxComp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); +} + +void inner_rx_64qam_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift, + uint32_t nvar) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int aatx = 0; aatx < nb_layer; aatx++) { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx][aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); + + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); + memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(ul_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(ul_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(ul_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + + for (int aatx = 0; aatx < nb_layer; aatx++) { + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { +#ifdef USE_ML + for (int atx = 0; atx < nb_layer; atx++) { + simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; + simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) + { + // multiply by conjugated channel + mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + + rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); + } + } +#endif + // compensation + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i QAM_ampa_256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) + simde__m256i QAM_ampb_256 = simde_mm256_set1_epi16(QAM64_n2); // 2/sqrt(10) + simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; + simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; + simde__m256i *ul_ch_maga_256 = (simde__m256i*)ul_ch_maga[aatx]; + simde__m256i *ul_ch_magb_256 = (simde__m256i*)ul_ch_magb[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + + xmmp2 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampa_256); + xmmp3 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampb_256); + + rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); + ul_ch_maga_256[i] = simde_mm256_adds_epi16(ul_ch_maga_256[i], xmmp2); + ul_ch_magb_256[i] = simde_mm256_adds_epi16(ul_ch_magb_256[i], xmmp3); + } + } + } +#ifdef USE_ML + c16_t *rho0 = rho[0][1]; + c16_t *rho1 = rho[1][0]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + c16_t *ul_ch_mag0 = ul_ch_maga[0]; + c16_t *ul_ch_mag1 = ul_ch_maga[1]; + nr_ulsch_qam64_qam64(rxComp[0], rxComp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); + nr_ulsch_qam64_qam64(rxComp[1], rxComp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); +#else + nr_ulsch_mmse_2layers(frame_parms, + (int **)rxComp, + (int **)ul_ch_maga, + (int **)ul_ch_magb, + (int **)ul_ch_magc, + (int **)chFext, + rel15_ul->rb_size, + frame_parms->nb_antennas_rx, + rel15_ul->qam_mod_order, + pusch_vars->log2_maxh, + symbol, + length, + nvar); + for (int aatx = 0; aatx < nb_layer; aatx++) + nr_ulsch_compute_llr((int32_t*)rxComp[aatx], + (int32_t*)ul_ch_maga[aatx], + (int32_t*)ul_ch_magb[aatx], + (int32_t*)ul_ch_magc[aatx], + &llr[aatx][pusch_vars->llr_offset[symbol]], + rel15_ul->rb_size, + length, + symbol, + rel15_ul->qam_mod_order); +#endif +} + +void inner_rx_256qam_2layer (NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift, + uint32_t nvar) +{ + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int aatx = 0; aatx < nb_layer; aatx++) { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx][aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t ul_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); + + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); + memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(ul_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(ul_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(ul_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + + // compensation + for (int aatx = 0; aatx < nb_layer; aatx++) { + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); + simde__m256i QAM_ampa_256 = simde_mm256_set1_epi16(QAM256_n1); // 2/sqrt(10) + simde__m256i QAM_ampb_256 = simde_mm256_set1_epi16(QAM256_n2); // 2/sqrt(10) + simde__m256i QAM_ampc_256 = simde_mm256_set1_epi16(QAM256_n3); // 2/sqrt(10) + simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; + simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; + simde__m256i *ul_ch_maga_256 = (simde__m256i*)ul_ch_maga[aatx]; + simde__m256i *ul_ch_magb_256 = (simde__m256i*)ul_ch_magb[aatx]; + simde__m256i *ul_ch_magc_256 = (simde__m256i*)ul_ch_magc[aatx]; + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + + xmmp2 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampa_256); + xmmp3 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampb_256); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampc_256); + + rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); + ul_ch_maga_256[i] = simde_mm256_adds_epi16(ul_ch_maga_256[i], xmmp2); + ul_ch_magb_256[i] = simde_mm256_adds_epi16(ul_ch_magb_256[i], xmmp3); + ul_ch_magc_256[i] = simde_mm256_adds_epi16(ul_ch_magc_256[i], xmmp1); + } + } + } + + nr_ulsch_mmse_2layers(frame_parms, + (int **)rxComp, + (int **)ul_ch_maga, + (int **)ul_ch_magb, + (int **)ul_ch_magc, + (int **)chFext, + rel15_ul->rb_size, + frame_parms->nb_antennas_rx, + rel15_ul->qam_mod_order, + pusch_vars->log2_maxh, + symbol, + length, + nvar); + for (int aatx = 0; aatx < nb_layer; aatx++) + nr_ulsch_compute_llr((int32_t*)rxComp[aatx], + (int32_t*)ul_ch_maga[aatx], + (int32_t*)ul_ch_magb[aatx], + (int32_t*)ul_ch_magc[aatx], + &llr[aatx][pusch_vars->llr_offset[symbol]], + rel15_ul->rb_size, + length, + symbol, + rel15_ul->qam_mod_order); +} + +void nr_pusch_symbol_processing_noprecoding(void *arg) { - uint8_t aarx, aatx; - uint32_t nb_re_pusch, bwp_start_subcarrier; - int avgs = 0; - - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ulsch_id]; - nfapi_nr_pusch_pdu_t *rel15_ul = &ulsch->harq_process->ulsch_pdu; - int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; + puschSymbolProc_t *rdata=(puschSymbolProc_t*)arg; + PHY_VARS_gNB *gNB = rdata->gNB; + NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; + nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; + int ulsch_id = rdata->ulsch_id; + int slot = rdata->slot; NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; - pusch_vars->dmrs_symbol = INVALID_VALUE; - pusch_vars->cl_done = 0; - - bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; - LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); - LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos); - LOG_D(PHY,"ulsch RX %x : start_rb %d nb_rb %d mcs %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_ports %d\n", - rel15_ul->rnti,rel15_ul->rb_start,rel15_ul->rb_size,rel15_ul->mcs_index, - rel15_ul->nrOfLayers,0,rel15_ul->bwp_start,0,rel15_ul->start_symbol_index,rel15_ul->nr_of_symbols, - rel15_ul->num_dmrs_cdm_grps_no_data,rel15_ul->ul_dmrs_symb_pos,rel15_ul->dmrs_ports); - //---------------------------------------------------------- - //--------------------- Channel estimation --------------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_channel_estimation_stats); - int max_ch = 0; - uint32_t nvar = 0; - for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { - uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag); - - if (dmrs_symbol_flag == 1) { - if (pusch_vars->dmrs_symbol == INVALID_VALUE) - pusch_vars->dmrs_symbol = symbol; - - for (int nl=0; nlnrOfLayers; nl++) { - uint32_t nvar_tmp = 0; - nr_pusch_channel_estimation(gNB, - slot, - get_dmrs_port(nl,rel15_ul->dmrs_ports), - symbol, - ulsch_id, - bwp_start_subcarrier, - rel15_ul, - &max_ch, - &nvar_tmp); - nvar += nvar_tmp; - } - - nr_gnb_measurements(gNB, ulsch, pusch_vars, symbol, rel15_ul->nrOfLayers); - allocCast2D(n0_subband_power, - unsigned int, - gNB->measurements.n0_subband_power, - frame_parms->nb_antennas_rx, - frame_parms->N_RB_UL, - false); - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - if (symbol == rel15_ul->start_symbol_index) { - pusch_vars->ulsch_power[aarx] = 0; - pusch_vars->ulsch_noise_power[aarx] = 0; - } - for (aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) { - pusch_vars->ulsch_power[aarx] += signal_energy_nodc( - &pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size], - rel15_ul->rb_size * 12); - } - for (int rb = 0; rb < rel15_ul->rb_size; rb++) { - pusch_vars->ulsch_noise_power[aarx] += - n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size; - } - LOG_D(PHY, - "aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n", - aarx, - rel15_ul->bwp_start, - rel15_ul->rb_start, - rel15_ul->rb_size, - pusch_vars->ulsch_power[aarx], - pusch_vars->ulsch_noise_power[aarx]); - } - } - } - - nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx); - - if (gNB->chest_time == 1) { // averaging time domain channel estimates - nr_chest_time_domain_avg(frame_parms, - pusch_vars->ul_ch_estimates, - rel15_ul->nr_of_symbols, - rel15_ul->start_symbol_index, - rel15_ul->ul_dmrs_symb_pos, - rel15_ul->rb_size); - - pusch_vars->dmrs_symbol = - get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols); - } - stop_meas(&gNB->ulsch_channel_estimation_stats); - - int off = ((rel15_ul->rb_size&1) == 1)? 4:0; - uint32_t rxdataF_ext_offset = 0; - uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0; - - // Flag to select the receiver: (true) Nonlinear ML receiver, (false) Linear MMSE receiver - // By default, we are using the Nonlinear ML receiver, except - // - for 256QAM as Nonlinear ML receiver is not implemented for 256QAM - // - for 64QAM as Nonlinear ML receiver requires more processing time than MMSE, and many machines are not powerful enough - bool ml_rx = true; - if (rel15_ul->nrOfLayers != 2 || rel15_ul->qam_mod_order >= 6) { - ml_rx = false; - } - - int ad_shift = 0; - if (rel15_ul->nrOfLayers == 1) { - ad_shift = 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); - } else if (ml_rx == false) { - ad_shift = -3; // For 2-layers, we are already doing a bit shift in the nr_ulsch_mmse_2layers() function, so we can use more bits - } - - int num_re_total = 0; - for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { - uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - if (dmrs_symbol_flag == 1) { + simde__m64 *s = (simde__m64 *)rdata->s; + for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) + { + int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; + // this needs to be reworded for parrellization, we need a table which give dmrs symbol location + // used for chennel estimate, they are being run in parallel! + if (dmrs_symbol_flag == 1) + { if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); - - if (gNB->chest_time == 0) // Non averaging time domain channel estimates - pusch_vars->dmrs_symbol = symbol; - - if (rel15_ul->dmrs_config_type == 0) { - // if no data in dmrs cdm group is 1 only even REs have no data - // if no data in dmrs cdm group is 2 both odd and even REs have no data - nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6)); - } - else { - nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)); - } - } - else { - nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; + gNB->pusch_vars[ulsch_id].dmrs_symbol = symbol; } - num_re_total += nb_re_pusch; - pusch_vars->ul_valid_re_per_slot[symbol] = nb_re_pusch; - LOG_D(PHY, "symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, pusch_vars->dmrs_symbol); + LOG_I(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id].dmrs_symbol); - //---------------------------------------------------------- - //--------------------- RBs extraction --------------------- - //---------------------------------------------------------- - if (nb_re_pusch > 0) { - start_meas(&gNB->ulsch_rbs_extraction_stats); - nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, rel15_ul, frame_parms); - stop_meas(&gNB->ulsch_rbs_extraction_stats); + if (nb_re_pusch == 0) continue; + if (rel15_ul->nrOfLayers == 1) + { + void (*inner_rx)(NR_DL_FRAME_PARMS *, + NR_gNB_PUSCH *, + nfapi_nr_pusch_pdu_t *, + c16_t **, + c16_t **, + int16_t *, + int32_t, + int32_t, + int32_t, + int32_t, + int32_t, + int16_t, + int32_t, + int32_t); + + if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk; + else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam; + else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam; + else if (rel15_ul->qam_mod_order == 8) inner_rx = inner_rx_256qam; + else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", + rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); - //---------------------------------------------------------- - //--------------------- Channel Scaling -------------------- - //---------------------------------------------------------- - nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext, - frame_parms, - ulsch, - symbol, - dmrs_symbol_flag, - nb_re_pusch, - rel15_ul->nrOfLayers, - rel15_ul->rb_size, - shift_ch_ext); + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + int16_t llr_tmp[(nb_re_pusch + 8) * rel15_ul->qam_mod_order] __attribute__((aligned(32))); + memset(llr_tmp, 0, sizeof(int16_t) * (nb_re_pusch + 8) * rel15_ul->qam_mod_order); + inner_rx(frame_parms, + pusch_vars, + rel15_ul, + gNB->common_vars.rxdataF, + (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, + llr_tmp, + rel15_ul->nrOfLayers, + frame_parms->nb_antennas_rx, + soffset, + nb_re_pusch, // length + symbol, // symbol index + rel15_ul->rb_size, // ofdm size + dmrs_symbol_flag, + gNB->pusch_vars[ulsch_id].log2_maxh); + + // unscrambling + simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol]]; + for (int i = 0; i < nb_re_pusch*rel15_ul->qam_mod_order >> 2; i++) + llr64[i] = simde_mm_mullo_pi16(((simde__m64 *)llr_tmp)[i], s[i]); + + } + else // MIMO for 2x2 + { + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + void (*inner_rx)(NR_DL_FRAME_PARMS *, + NR_gNB_PUSCH *, + nfapi_nr_pusch_pdu_t *, + c16_t **, + c16_t **, + int16_t **, + int32_t, + int32_t, + int32_t, + int32_t, + int32_t, + int16_t, + int32_t, + int32_t, + uint32_t); + if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk_2layer; + else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam_2layer; + else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam_2layer; + else if (rel15_ul->qam_mod_order == 8) inner_rx = inner_rx_256qam_2layer; + else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", + rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); + + inner_rx(frame_parms, + pusch_vars, + rel15_ul, + gNB->common_vars.rxdataF, + (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, + rdata->llr_layers, + rel15_ul->nrOfLayers, + frame_parms->nb_antennas_rx, + soffset, + nb_re_pusch, // length + symbol, // symbol index + rel15_ul->rb_size, // ofdm size + dmrs_symbol_flag, + gNB->pusch_vars[ulsch_id].log2_maxh, + rdata->nvar); + + // layer de-mapping + int16_t* llr_cw = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch); i++) + for (int l = 0; l < rel15_ul->nrOfLayers; l++) + for (int m = 0; m < rel15_ul->qam_mod_order; m++) + llr_cw[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; + + // unscrambling + simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch*rel15_ul->qam_mod_order * rel15_ul->nrOfLayers) >> 2; i++) + llr64[i] = simde_mm_mullo_pi16(llr64[i], s[i]); - if (pusch_vars->cl_done == 0) { - nr_ulsch_channel_level(pusch_vars->ul_ch_estimates_ext, - frame_parms, - avg, - symbol, - nb_re_pusch, - rel15_ul->nrOfLayers, - rel15_ul->rb_size); - - avgs = 0; - - for (aatx=0;aatxnrOfLayers;aatx++) - for (aarx=0;aarxnb_antennas_rx;aarx++) - avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]); - - pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + ad_shift; - if (pusch_vars->log2_maxh < 0) { - pusch_vars->log2_maxh = 0; - } - pusch_vars->cl_done = 1; - } - - //---------------------------------------------------------- - //--------------------- Channel Compensation --------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_channel_compensation_stats); - LOG_D(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n" ,pusch_vars->log2_maxh, avgs,avg[0], avg[1]); - nr_ulsch_channel_compensation(pusch_vars->rxdataF_ext, - pusch_vars->ul_ch_estimates_ext, - pusch_vars->ul_ch_mag0, - pusch_vars->ul_ch_magb0, - pusch_vars->ul_ch_magc0, - pusch_vars->rxdataF_comp, - (rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL, - frame_parms, - symbol, - nb_re_pusch, - dmrs_symbol_flag, - rel15_ul->qam_mod_order, - rel15_ul->nrOfLayers, - rel15_ul->rb_size, - pusch_vars->log2_maxh); - stop_meas(&gNB->ulsch_channel_compensation_stats); - - start_meas(&gNB->ulsch_mrc_stats); - nr_ulsch_detection_mrc(frame_parms, - pusch_vars->rxdataF_comp, - pusch_vars->ul_ch_mag0, - pusch_vars->ul_ch_magb0, - pusch_vars->ul_ch_magc0, - (rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL, - rel15_ul->nrOfLayers, - symbol, - rel15_ul->rb_size, - nb_re_pusch); - - // Apply MMSE for 2 Tx layers - if (ml_rx == false && rel15_ul->nrOfLayers == 2) { - nr_ulsch_mmse_2layers(frame_parms, - pusch_vars->rxdataF_comp, - pusch_vars->ul_ch_mag0, - pusch_vars->ul_ch_magb0, - pusch_vars->ul_ch_magc0, - pusch_vars->ul_ch_estimates_ext, - rel15_ul->rb_size, - frame_parms->nb_antennas_rx, - rel15_ul->qam_mod_order, - pusch_vars->log2_maxh, - symbol, - nb_re_pusch, - nvar); - } - - stop_meas(&gNB->ulsch_mrc_stats); - - if (rel15_ul->transform_precoding == transformPrecoder_enabled) { - // For odd number of resource blocks need byte alignment to multiple of 8 - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); - - // perform IDFT operation on the compensated rxdata if transform precoding is enabled - nr_idft(&pusch_vars->rxdataF_comp[0][symbol * nb_re_pusch2], nb_re_pusch); - LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d\n", symbol, nb_re_pusch); - } - - //---------------------------------------------------------- - //--------------------- PTRS Processing -------------------- - //---------------------------------------------------------- - /* In case PTRS is enabled then LLR will be calculated after PTRS symbols are processed * - * otherwise LLR are calculated for each symbol based upon DMRS channel estimates only. */ - if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - start_meas(&gNB->ulsch_ptrs_processing_stats); - nr_pusch_ptrs_processing(gNB, - frame_parms, - rel15_ul, - ulsch_id, - slot, - symbol, - nb_re_pusch); - stop_meas(&gNB->ulsch_ptrs_processing_stats); - - /* Subtract total PTRS RE's in the symbol from PUSCH RE's */ - pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot; - } - - /*---------------------------------------------------------------------------------------------------- */ - /*-------------------- LLRs computation -------------------------------------------------------------*/ - /*-----------------------------------------------------------------------------------------------------*/ - start_meas(&gNB->ulsch_llr_stats); - if (ml_rx == false || rel15_ul->nrOfLayers == 1) { - for (aatx=0; aatx < rel15_ul->nrOfLayers; aatx++) { - nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], - pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx], - pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx], - pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx], - &pusch_vars->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order], - rel15_ul->rb_size, - pusch_vars->ul_valid_re_per_slot[symbol], - symbol, - rel15_ul->qam_mod_order); - } - } else { - nr_ulsch_compute_ML_llr(pusch_vars->rxdataF_comp, - pusch_vars->ul_ch_mag0, - pusch_vars->rho, - pusch_vars->llr_layers, - frame_parms->nb_antennas_rx, - rel15_ul->rb_size, - nb_re_pusch, - symbol, - rxdataF_ext_offset, - rel15_ul->qam_mod_order); - - if (rel15_ul->qam_mod_order == 2) { - nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re_pusch, rxdataF_ext_offset, rel15_ul->qam_mod_order, 4); - } - -#ifdef ML_DEBUG - c16_t *llr_layers0 = (c16_t *)&pusch_vars->llr_layers[0][rxdataF_ext_offset * rel15_ul->qam_mod_order]; - c16_t *llr_layers1 = (c16_t *)&pusch_vars->llr_layers[1][rxdataF_ext_offset * rel15_ul->qam_mod_order]; - printf("===============================\n"); - printf("AFTER nr_ulsch_compute_ML_llr()\n"); - printf("===============================\n"); - for (int k = 0; k < nb_re_pusch; k++) { - printf("[%3i] llr_layers0 = (%6i, %6i), llr_layers1 = (%6i, %6i)\n", - k, llr_layers0[k].r, llr_layers0[k].i, llr_layers1[k].r, llr_layers1[k].i); - } - printf("\n"); -#endif - } - stop_meas(&gNB->ulsch_llr_stats); - rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol]; } - } // symbol loop - if (!(frame % 128)) { - int num_llr = num_re_total*rel15_ul->qam_mod_order; - GnbScopeUpdate(gNB, puschLLRe, num_llr); - GnbScopeUpdate(gNB, puschIQe, num_re_total); } } + int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, @@ -3605,16 +2697,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, //---------------------------------------------------------- start_meas(&gNB->ulsch_channel_estimation_stats); int max_ch = 0; - for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) - { + uint32_t nvar = 0; + for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag); - if (dmrs_symbol_flag == 1) - { + + if (dmrs_symbol_flag == 1) { if (pusch_vars->dmrs_symbol == INVALID_VALUE) pusch_vars->dmrs_symbol = symbol; - for (int nl=0; nlnrOfLayers; nl++) - { + + for (int nl=0; nlnrOfLayers; nl++) { + uint32_t nvar_tmp = 0; nr_pusch_channel_estimation(gNB, slot, get_dmrs_port(nl,rel15_ul->dmrs_ports), @@ -3623,7 +2716,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, bwp_start_subcarrier, rel15_ul, &max_ch, - 0 /* nvar*/); + &nvar_tmp); + nvar += nvar_tmp; } // measure the SNR from the channel estimation nr_gnb_measurements(gNB, @@ -3656,6 +2750,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, } } + nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx); + // averaging time domain channel estimates if (gNB->chest_time == 1) { @@ -3778,7 +2874,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, { union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}}; id.p=1+symbol; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, gNB->respPuschSymb, &nr_pusch_symbol_processing_noprecoding); // create a job for Tpool + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing_noprecoding); // create a job for Tpool puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job rdata->gNB = gNB; @@ -3791,6 +2887,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rdata->llr = pusch_vars->llr; rdata->llr_layers = pusch_vars->llr_layers; rdata->s = &s[pusch_vars->llr_offset[symbol]*rel15_ul->nrOfLayers]; + rdata->nvar = nvar; pushTpool(&gNB->threadPool, req); gNB->nbSymb++; @@ -3801,7 +2898,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, while (gNB->nbSymb > 0) { - notifiedFIFO_elt_t *req=pullTpool(gNB->respPuschSymb, &gNB->threadPool); + notifiedFIFO_elt_t *req=pullTpool(&gNB->respPuschSymb, &gNB->threadPool); gNB->nbSymb--; delNotifiedFIFO_elt(req); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index f4d526960e..ddbec269b3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -70,68 +70,28 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol) { + simde__m256i *rxF_256 = (simde__m256i*)rxdataF_comp; + simde__m256i *ch_mag = (simde__m256i*)ul_ch_mag; + simde__m64 *llr_64 = (simde__m64*)ulsch_llr; - simde__m256i *rxF = (simde__m256i*)rxdataF_comp; - simde__m256i *ch_mag; - simde__m256i llr256[2]; - register simde__m256i xmm0; - uint32_t *llr32; - int i; + simde__m256i xmm0, xmm1, xmm2; - int off = ((nb_rb&1) == 1)? 4:0; - - llr32 = (uint32_t*)ulsch_llr; - - ch_mag = (simde__m256i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - unsigned char len_mod8 = nb_re&7; - nb_re >>= 3; // length in quad words (4 REs) - nb_re += (len_mod8 == 0 ? 0 : 1); - - for (i=0; i |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + for (int i = 0; i < ((nb_re>>3) + ((nb_re&7) ? 1 : 0)); i++) { + xmm0 = simde_mm256_abs_epi16(rxF_256[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm256_subs_epi16(ch_mag[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - llr256[0] = simde_mm256_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs - llr256[1] = simde_mm256_unpackhi_epi32(rxF[i],xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + xmm1 = simde_mm256_unpacklo_epi32(rxF_256[i], xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs + xmm2 = simde_mm256_unpackhi_epi32(rxF_256[i], xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs - // 1st RE - llr32[0] = simde_mm256_extract_epi32(llr256[0],0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I - llr32[1] = simde_mm256_extract_epi32(llr256[0],1); // llr32[1] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 2nd RE - llr32[2] = simde_mm256_extract_epi32(llr256[0],2); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I - llr32[3] = simde_mm256_extract_epi32(llr256[0],3); // llr32[3] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 3rd RE - llr32[4] = simde_mm256_extract_epi32(llr256[1],0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I - llr32[5] = simde_mm256_extract_epi32(llr256[1],1); // llr32[5] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 4th RE - llr32[6] = simde_mm256_extract_epi32(llr256[1],2); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I - llr32[7] = simde_mm256_extract_epi32(llr256[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 5th RE - llr32[8] = simde_mm256_extract_epi32(llr256[0],4); // llr32[8] low 16 bits-> y_R , high 16 bits-> y_I - llr32[9] = simde_mm256_extract_epi32(llr256[0],5); // llr32[9] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 6th RE - llr32[10] = simde_mm256_extract_epi32(llr256[0],6); // llr32[10] low 16 bits-> y_R , high 16 bits-> y_I - llr32[11] = simde_mm256_extract_epi32(llr256[0],7); // llr32[11] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 7th RE - llr32[12] = simde_mm256_extract_epi32(llr256[1],4); // llr32[12] low 16 bits-> y_R , high 16 bits-> y_I - llr32[13] = simde_mm256_extract_epi32(llr256[1],5); // llr32[13] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 8th RE - llr32[14] = simde_mm256_extract_epi32(llr256[1],6); // llr32[14] low 16 bits-> y_R , high 16 bits-> y_I - llr32[15] = simde_mm256_extract_epi32(llr256[1],7); // llr32[15] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - llr32+=16; - + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 0); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 1); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 0); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 1); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 2); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 3); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 2); + *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 3); } - - simde_mm_empty(); - simde_m_empty(); } //---------------------------------------------------------------------------------------------- @@ -146,112 +106,53 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol) { - int off = ((nb_rb&1) == 1)? 4:0; - simde__m256i *rxF = (simde__m256i*)rxdataF_comp; - simde__m256i *ch_mag,*ch_magb; - register simde__m256i xmm0,xmm1,xmm2; + simde__m256i xmm0, xmm1, xmm2; - int i; + simde__m256i *ch_maga = (simde__m256i*)ul_ch_mag; + simde__m256i *ch_magb = (simde__m256i*)ul_ch_magb; - ch_mag = (simde__m256i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - ch_magb = (simde__m256i*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; + int32_t *llr_32 = (int32_t *)ulsch_llr; - int len_mod8 = nb_re&7; - nb_re = nb_re>>3; // length in quad words (4 REs) - nb_re += ((len_mod8 == 0) ? 0 : 1); - - for (i=0; i>3) + ((nb_re&7) ? 1 : 0)); i++) { xmm0 = rxF[i]; xmm1 = simde_mm256_abs_epi16(xmm0); - xmm1 = simde_mm256_subs_epi16(ch_mag[i],xmm1); + xmm1 = simde_mm256_subs_epi16(ch_maga[i], xmm1); xmm2 = simde_mm256_abs_epi16(xmm1); - xmm2 = simde_mm256_subs_epi16(ch_magb[i],xmm2); + xmm2 = simde_mm256_subs_epi16(ch_magb[i], xmm2); - // --------------------------------------- - // 1st RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,0); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,1); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,0); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,1); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,0); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,1); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,0); + *llr_32++ = simde_mm256_extract_epi32(xmm1,0); + *llr_32++ = simde_mm256_extract_epi32(xmm2,0); - ulsch_llr+=6; - - // --------------------------------------- - // 2nd RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,2); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,3); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,2); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,3); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,2); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,3); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,1); + *llr_32++ = simde_mm256_extract_epi32(xmm1,1); + *llr_32++ = simde_mm256_extract_epi32(xmm2,1); - ulsch_llr+=6; - - // --------------------------------------- - // 3rd RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,4); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,5); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,4); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,5); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,4); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,5); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,2); + *llr_32++ = simde_mm256_extract_epi32(xmm1,2); + *llr_32++ = simde_mm256_extract_epi32(xmm2,2); - ulsch_llr+=6; - - // --------------------------------------- - // 4th RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,6); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,7); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,6); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,7); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,6); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,7); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,3); + *llr_32++ = simde_mm256_extract_epi32(xmm1,3); + *llr_32++ = simde_mm256_extract_epi32(xmm2,3); - ulsch_llr+=6; - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,8); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,9); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,8); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,9); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,8); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,9); + *llr_32++ = simde_mm256_extract_epi32(xmm0,4); + *llr_32++ = simde_mm256_extract_epi32(xmm1,4); + *llr_32++ = simde_mm256_extract_epi32(xmm2,4); - ulsch_llr[6] = simde_mm256_extract_epi16(xmm0,10); - ulsch_llr[7] = simde_mm256_extract_epi16(xmm0,11); - ulsch_llr[8] = simde_mm256_extract_epi16(xmm1,10); - ulsch_llr[9] = simde_mm256_extract_epi16(xmm1,11); - ulsch_llr[10] = simde_mm256_extract_epi16(xmm2,10); - ulsch_llr[11] = simde_mm256_extract_epi16(xmm2,11); + *llr_32++ = simde_mm256_extract_epi32(xmm0,5); + *llr_32++ = simde_mm256_extract_epi32(xmm1,5); + *llr_32++ = simde_mm256_extract_epi32(xmm2,5); - ulsch_llr[12] = simde_mm256_extract_epi16(xmm0,12); - ulsch_llr[13] = simde_mm256_extract_epi16(xmm0,13); - ulsch_llr[14] = simde_mm256_extract_epi16(xmm1,12); - ulsch_llr[15] = simde_mm256_extract_epi16(xmm1,13); - ulsch_llr[16] = simde_mm256_extract_epi16(xmm2,12); - ulsch_llr[17] = simde_mm256_extract_epi16(xmm2,13); + *llr_32++ = simde_mm256_extract_epi32(xmm0,6); + *llr_32++ = simde_mm256_extract_epi32(xmm1,6); + *llr_32++ = simde_mm256_extract_epi32(xmm2,6); - ulsch_llr[18] = simde_mm256_extract_epi16(xmm0,14); - ulsch_llr[19] = simde_mm256_extract_epi16(xmm0,15); - ulsch_llr[20] = simde_mm256_extract_epi16(xmm1,14); - ulsch_llr[21] = simde_mm256_extract_epi16(xmm1,15); - ulsch_llr[22] = simde_mm256_extract_epi16(xmm2,14); - ulsch_llr[23] = simde_mm256_extract_epi16(xmm2,15); - - ulsch_llr+=24; + *llr_32++ = simde_mm256_extract_epi32(xmm0,7); + *llr_32++ = simde_mm256_extract_epi32(xmm1,7); + *llr_32++ = simde_mm256_extract_epi32(xmm2,7); } - - simde_mm_empty(); - simde_m_empty(); } void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, @@ -263,105 +164,42 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol) { - int off = ((nb_rb&1) == 1)? 4:0; - simde__m256i *rxF = (simde__m256i*)rxdataF_comp; - simde__m256i *ch_mag,*ch_magb,*ch_magc; - register simde__m256i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; + simde__m256i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; simde__m256i *llr256=(simde__m256i*)ulsch_llr; - ch_mag = (simde__m256i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - ch_magb = (simde__m256i*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; - ch_magc = (simde__m256i*)&ul_ch_magc[(symbol*(off+(nb_rb*12)))]; - int len_mod8 = nb_re&7; - int nb_re256 = nb_re>>3; // length in 256-bit words (8 REs) + simde__m256i* ch_maga = (simde__m256i*)ul_ch_mag; + simde__m256i* ch_magb = (simde__m256i*)ul_ch_magb; + simde__m256i* ch_magc = (simde__m256i*)ul_ch_magc; - for (int i=0; i |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmtmpD2 contains 16 LLRs - xmm1 = simde_mm256_abs_epi16(xmm0); - xmm1 = simde_mm256_subs_epi16(ch_magb[i],xmm1); // contains 16 LLRs - xmm2 = simde_mm256_abs_epi16(xmm1); - xmm2 = simde_mm256_subs_epi16(ch_magc[i],xmm2); // contains 16 LLRs - // rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6 - // xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4 - // xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2 - // xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0 - xmm3 = simde_mm256_unpacklo_epi32(rxF[i],xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 - xmm4 = simde_mm256_unpackhi_epi32(rxF[i],xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 - xmm5 = simde_mm256_unpacklo_epi32(xmm1,xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 - xmm6 = simde_mm256_unpackhi_epi32(xmm1,xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 - - xmm0 = simde_mm256_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0 A4 B4 C4 D4 - xmm1 = simde_mm256_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1 A5 B5 C5 D5 - xmm2 = simde_mm256_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2 A6 B6 C6 D6 - xmm3 = simde_mm256_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3 A7 B7 C7 D7 - llr256[0] = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1 - llr256[1] = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3 - llr256[2] = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5 - llr256[3] = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7 - llr256+=4; + for (int i = 0; i < ((nb_re>>3) + ((nb_re&7) ? 1 : 0)); i++) { + xmm0 = simde_mm256_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm256_subs_epi16(ch_maga[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + // xmmtmpD2 contains 16 LLRs + xmm1 = simde_mm256_abs_epi16(xmm0); + xmm1 = simde_mm256_subs_epi16(ch_magb[i], xmm1); // contains 16 LLRs + xmm2 = simde_mm256_abs_epi16(xmm1); + xmm2 = simde_mm256_subs_epi16(ch_magc[i], xmm2); // contains 16 LLRs + // rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6 + // xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4 + // xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2 + // xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0 + xmm3 = simde_mm256_unpacklo_epi32(rxF[i], xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 + xmm4 = simde_mm256_unpackhi_epi32(rxF[i], xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 + xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 + xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 + xmm0 = simde_mm256_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 A4 B4 C4 D4 + xmm1 = simde_mm256_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 A5 B5 C5 D5 + xmm2 = simde_mm256_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2 A6 B6 C6 D6 + xmm3 = simde_mm256_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3 A7 B7 C7 D7 + *llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1 + *llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3 + *llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5 + *llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7 } - simde__m128i *llr128 = (simde__m128i*)llr256; - if (len_mod8 >= 4) { - int nb_re128 = nb_re>>2; - simde__m128i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; - simde__m128i *rxF = (simde__m128i*)rxdataF_comp; - simde__m128i *ch_mag = (simde__m128i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - simde__m128i *ch_magb = (simde__m128i*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; - simde__m128i *ch_magc = (simde__m128i*)&ul_ch_magc[(symbol*(off+(nb_rb*12)))]; - - xmm0 = simde_mm_abs_epi16(rxF[nb_re128-1]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_epi16(ch_mag[nb_re128-1],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmtmpD2 contains 8 LLRs - xmm1 = simde_mm_abs_epi16(xmm0); - xmm1 = simde_mm_subs_epi16(ch_magb[nb_re128-1],xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_epi16(xmm1); - xmm2 = simde_mm_subs_epi16(ch_magc[nb_re128-1],xmm2); // contains 8 LLRs - // rxF[i] A0 A1 A2 A3 - // xmm0 B0 B1 B2 B3 - // xmm1 C0 C1 C2 C3 - // xmm2 D0 D1 D2 D3 - xmm3 = simde_mm_unpacklo_epi32(rxF[nb_re128-1],xmm0); // A0 B0 A1 B1 - xmm4 = simde_mm_unpackhi_epi32(rxF[nb_re128-1],xmm0); // A2 B2 A3 B3 - xmm5 = simde_mm_unpacklo_epi32(xmm1,xmm2); // C0 D0 C1 D1 - xmm6 = simde_mm_unpackhi_epi32(xmm1,xmm2); // C2 D2 C3 D3 - - llr128[0] = simde_mm_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0 - llr128[1] = simde_mm_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1 - llr128[2] = simde_mm_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2 - llr128[3] = simde_mm_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3 - llr128+=4; - } - if (len_mod8 == 6) { - int nb_re64 = nb_re>>1; - simde__m64 *llr64 = (simde__m64 *)llr128; - simde__m64 xmm0,xmm1,xmm2; - simde__m64 *rxF = (simde__m64*)rxdataF_comp; - simde__m64 *ch_mag = (simde__m64*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - simde__m64 *ch_magb = (simde__m64*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; - simde__m64 *ch_magc = (simde__m64*)&ul_ch_magc[(symbol*(off+(nb_rb*12)))]; - - xmm0 = simde_mm_abs_pi16(rxF[nb_re64-1]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_pi16(ch_mag[nb_re-1],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmtmpD2 contains 4 LLRs - xmm1 = simde_mm_abs_pi16(xmm0); - xmm1 = simde_mm_subs_pi16(ch_magb[nb_re64-1],xmm1); // contains 4 LLRs - xmm2 = simde_mm_abs_pi16(xmm1); - xmm2 = simde_mm_subs_pi16(ch_magc[nb_re64-1],xmm2); // contains 4 LLRs - // rxF[i] A0 A1 - // xmm0 B0 B1 - // xmm1 C0 C1 - // xmm2 D0 D1 - llr64[0] = simde_m_punpckldq(rxF[nb_re64-1],xmm0); // A0 B0 - llr64[2] = simde_m_punpckhdq(rxF[nb_re64-1],xmm0); // A1 B1 - llr64[1] = simde_m_punpckldq(xmm1,xmm2); // C0 D0 - llr64[3] = simde_m_punpckhdq(xmm1,xmm2); // C1 D1 - } - } + void nr_ulsch_compute_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int32_t *ul_ch_magb, diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index f1f931e1f4..88367741d4 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -760,7 +760,7 @@ typedef struct PHY_VARS_gNB_s { time_stats_t rx_dft_stats; time_stats_t ulsch_freq_offset_estimation_stats; */ - notifiedFIFO_t *respPuschSymb; + notifiedFIFO_t respPuschSymb; notifiedFIFO_t respDecode; notifiedFIFO_t resp_L1; notifiedFIFO_t L1_tx_free; @@ -769,7 +769,6 @@ typedef struct PHY_VARS_gNB_s { notifiedFIFO_t resp_RU_tx; tpool_t threadPool; int nbSymb; - int use_pusch_tp; int num_pusch_symbols_per_thread; pthread_t L1_rx_thread; int L1_rx_thread_core; @@ -792,6 +791,7 @@ typedef struct puschSymbolProc_s { int16_t *llr; int16_t **llr_layers; int16_t *s; + uint32_t nvar; } puschSymbolProc_t; struct puschSymbolReqId { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 35afb44fe1..64eae8422c 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -398,20 +398,20 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - if (gNB->use_pusch_tp == 0 ) - { - nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, - pusch_pdu->nrOfLayers, - pusch_pdu->qam_mod_order, - G, - gNB->pusch_vars[ULSCH_id].llr_layers); - //---------------------------------------------------------- - //------------------- ULSCH unscrambling ------------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_unscrambling_stats); - nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); - stop_meas(&gNB->ulsch_unscrambling_stats); - } + + + // nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, + // pusch_pdu->nrOfLayers, + // pusch_pdu->qam_mod_order, + // G, + // gNB->pusch_vars[ULSCH_id].llr_layers); + // //---------------------------------------------------------- + // //------------------- ULSCH unscrambling ------------------- + // //---------------------------------------------------------- + // start_meas(&gNB->ulsch_unscrambling_stats); + // nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); + // stop_meas(&gNB->ulsch_unscrambling_stats); + //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- @@ -902,8 +902,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); start_meas(&gNB->rx_pusch_stats); - if (gNB->use_pusch_tp) nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); - else nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + // if (gNB->use_pusch_tp) nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + // else nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; pusch_vars->ulsch_power_tot = 0; pusch_vars->ulsch_noise_power_tot = 0; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 879d6deda1..5c3abe09be 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -222,7 +222,6 @@ int main(int argc, char *argv[]) int ibwp_rboffset=41; int params_from_file = 0; int threadCnt=0; - int use_tpool = 0; int max_ldpc_iterations = 5; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) { exit_fun("[NR_ULSIM] Error, configuration module init failed\n"); @@ -364,7 +363,6 @@ int main(int argc, char *argv[]) case 'C': threadCnt = atoi(optarg); - use_tpool = 1; break; case 'u': @@ -563,14 +561,12 @@ int main(int argc, char *argv[]) RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; gNB->ofdm_offset_divisor = UINT_MAX; - initNotifiedFIFO(&gNB->respDecode); - gNB->use_pusch_tp = use_tpool; gNB->num_pusch_symbols_per_thread = 1; initFloatingCoresTpool(threadCnt, &gNB->threadPool, false, "gNB-tpool"); initNotifiedFIFO(&gNB->respDecode); - gNB->respPuschSymb = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); - initNotifiedFIFO(gNB->respPuschSymb); + + initNotifiedFIFO(&gNB->respPuschSymb); initNotifiedFIFO(&gNB->L1_tx_free); initNotifiedFIFO(&gNB->L1_tx_filled); initNotifiedFIFO(&gNB->L1_tx_out); @@ -1602,20 +1598,16 @@ int main(int argc, char *argv[]) printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time"); printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); - if (use_tpool == 1) - { - printStatIndent2(&gNB->rx_pusch_init_stats,"RX PUSCH Initialization time"); - printStatIndent2(&gNB->rx_pusch_symbol_processing_stats,"RX PUSCH Symbol Processing time"); - } - else - { - printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); - printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); - printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); - printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); - printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); - printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); - } + printStatIndent2(&gNB->rx_pusch_init_stats,"RX PUSCH Initialization time"); + printStatIndent2(&gNB->rx_pusch_symbol_processing_stats,"RX PUSCH Symbol Processing time"); + + // printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); + // printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); + // printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); + // printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); + // printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); + // printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); + printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); // printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); // printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); From e51d8a9bc9e4b35d6e1a7d52f900a96d7c78120f Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Tue, 5 Sep 2023 21:09:34 +0200 Subject: [PATCH 07/43] feat / compact the code - merge the inner_rx - rewrite the ulsch channel compensation --- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 47 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 1442 +++-------------- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 85 +- 3 files changed, 283 insertions(+), 1291 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 97d32232cf..5d25f623df 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -179,35 +179,6 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, uint8_t nrOfLayers, unsigned short nb_rb); -/** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation. In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation) - @param rxdataF_ext Frequency-domain received signal in RBs to be demodulated - @param ul_ch_estimates_ext Frequency-domain channel estimates in RBs to be demodulated - @param ul_ch_mag First Channel magnitudes (16QAM/64QAM/256QAM) - @param ul_ch_magb Second weighted Channel magnitudes (64QAM/256QAM) - @param ul_ch_magc Third weighted Channel magnitudes (256QAM) - @param rxdataF_comp Compensated received waveform - @param frame_parms Pointer to frame descriptor - @param symbol Symbol on which to operate - @param Qm Modulation order of allocation - @param nb_rb Number of RBs in allocation - @param output_shift Rescaling for compensated output (should be energy-normalizing) -*/ -void nr_ulsch_channel_compensation(int **rxdataF_ext, - int **ul_ch_estimates_ext, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int **rxdataF_comp, - int ***rho, - NR_DL_FRAME_PARMS *frame_parms, - unsigned char symbol, - int length, - uint8_t is_dmrs_symbol, - unsigned char mod_order, - uint8_t nrOfLayers, - unsigned short nb_rb, - unsigned char output_shift); - /*! \brief This function implements the idft transform precoding in PUSCH \param z Pointer to input in frequnecy domain, and it is also the output in time domain @@ -316,15 +287,17 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, void reset_active_stats(PHY_VARS_gNB *gNB, int frame); void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); -void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, - int32_t **ul_ch_mag, - int32_t ***rho, - int16_t **llr_layers, - uint8_t nb_antennas_rx, - uint32_t rb_size, +void nr_ulsch_compute_ML_llr(NR_gNB_PUSCH *pusch_vars, + uint32_t symbol, + c16_t* rxdataF_comp0, + c16_t* rxdataF_comp1, + c16_t* ul_ch_mag0, + c16_t* ul_ch_mag1, + c16_t* llr_layers0, + c16_t* llr_layers1, + c16_t* rho0, + c16_t* rho1, uint32_t nb_re, - uint8_t symbol, - uint32_t rxdataF_ext_offset, uint8_t mod_order); void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 3e0b3506b1..e3dec33a0d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -598,279 +598,110 @@ static simde__m128i a_mult_conjb(__m128i a, __m128i b, unsigned char output_shif return _mm_packs_epi32(mmtmpD2, mmtmpD3); } -//============================================================================================== -// Pre-processing for LLR computation -//============================================================================================== -void nr_ulsch_channel_compensation(int **rxdataF_ext, - int **ul_ch_estimates_ext, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int **rxdataF_comp, - int ***rho, + +void nr_ulsch_channel_compensation(c16_t *rxFext, + c16_t *chFext, + c16_t *ul_ch_maga, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, + c16_t *rxComp, + c16_t *rho, NR_DL_FRAME_PARMS *frame_parms, - unsigned char symbol, - int length, - uint8_t is_dmrs_symbol, - unsigned char mod_order, + uint32_t symbol, + uint32_t length, + uint32_t mod_order, uint8_t nrOfLayers, - unsigned short nb_rb, - unsigned char output_shift) { + uint8_t nb_rx_ant, + uint32_t nb_rb, + uint32_t output_shift) +{ + simde__m256i QAM_ampa_256, QAM_ampb_256, QAM_ampc_256; - int off = ((nb_rb&1) == 1)? 4:0; + if (mod_order == 4) { + QAM_ampa_256 = simde_mm256_set1_epi16(QAM16_n1); + QAM_ampb_256 = simde_mm256_setzero_si256(); + QAM_ampc_256 = simde_mm256_setzero_si256(); + } + else if (mod_order == 6) { + QAM_ampa_256 = simde_mm256_set1_epi16(QAM64_n1); + QAM_ampb_256 = simde_mm256_set1_epi16(QAM64_n2); + QAM_ampc_256 = simde_mm256_setzero_si256(); + } + else if (mod_order == 8) { + QAM_ampa_256 = simde_mm256_set1_epi16(QAM256_n1); + QAM_ampb_256 = simde_mm256_set1_epi16(QAM256_n2); + QAM_ampc_256 = simde_mm256_set1_epi16(QAM256_n3); + } -#ifdef DEBUG_CH_COMP - int16_t *rxF, *ul_ch; - int prnt_idx; - for (int nl=0; nlnb_antennas_rx; aarx++) { - rxF = (int16_t *) &rxdataF_ext[aarx][symbol * (off + (nb_rb * 12))]; - ul_ch = (int16_t *) &ul_ch_estimates_ext[nl * frame_parms->nb_antennas_rx + aarx][symbol * (off + (nb_rb * 12))]; + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - printf("--------symbol = %d, mod_order = %d, output_shift = %d, layer %i, antenna rx = %d -----------\n", - symbol, mod_order, output_shift, nl, aarx); - printf("----------------Before compensation------------------\n"); + int length_aligned = (length % 8) ? (8 - length % 8) : 0; + + for (int aatx = 0; aatx < nrOfLayers; aatx++) { + simde__m256i *rxComp_256 = (simde__m256i*) &rxComp[aatx * (length + length_aligned)]; + simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * (length + length_aligned)]; + simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * (length + length_aligned)]; + simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * (length + length_aligned)]; + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + simde__m256i *rxF_256 = (simde__m256i*) &rxFext[aarx * (length + length_aligned)]; + simde__m256i *chF_256 = (simde__m256i*) &chFext[(aatx * nb_rx_ant + aarx) * (length + length_aligned)]; - for (prnt_idx = 0; prnt_idx < 12 * 5 * 2; prnt_idx += 2) { - printf("rxF[%d] = (%d,%d)\n", prnt_idx >> 1, rxF[prnt_idx], rxF[prnt_idx + 1]); - printf("ul_ch[%d] = (%d,%d)\n", prnt_idx >> 1, ul_ch[prnt_idx], ul_ch[prnt_idx + 1]); + for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + + xmmp2 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampa_256); + xmmp3 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampb_256); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampc_256); + + // MRC + rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); + if (mod_order > 2) + rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp2); + if (mod_order > 4) + rxF_ch_magb_256[i] = simde_mm256_add_epi16(rxF_ch_magb_256[i], xmmp3); + if (mod_order > 6) + rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], xmmp1); } - } - } -#endif - -#ifdef DEBUG_CH_MAG - int16_t *ch_mag; - int print_idx; - - - for (int ant=0; antnb_antennas_rx; ant++) { - ch_mag = (int16_t *)&ul_ch_mag[ant][symbol*(off+(nb_rb*12))]; - - printf("--------------------symbol = %d, mod_order = %d-----------------------\n", symbol, mod_order); - printf("----------------Before computation------------------\n"); - - for (print_idx=0;print_idx<5;print_idx++){ - - printf("ch_mag[%d] = %d\n", print_idx, ch_mag[print_idx]); - - } - } - -#endif - -#if defined(__i386) || defined(__x86_64__) - - unsigned short rb; - unsigned char aatx,aarx; - __m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*ul_ch_mag128c,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128c={0}; - QAM_amp128b = _mm_setzero_si128(); - - uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); - for (aatx=0; aatxnb_antennas_rx; aarx++) { - ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128 = (simde__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128b = (simde__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128c = (simde__m128i *)&ul_ch_magc[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - rxdataF128 = (simde__m128i *)&rxdataF_ext[aarx][symbol*(off+(nb_rb*12))]; - rxdataF_comp128 = (simde__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - - - for (rb=0; rb2) { - // get channel amplitude if not QPSK - - //print_shorts("ch:",(int16_t*)&ul_ch128[0]); - - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[0],ul_ch128[0]); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - - mmtmpD1 = simde_mm_madd_epi16(ul_ch128[1],ul_ch128[1]); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - - mmtmpD0 = simde_mm_packs_epi32(mmtmpD0,mmtmpD1); - - // store channel magnitude here in a new field of ulsch - - ul_ch_mag128[0] = simde_mm_unpacklo_epi16(mmtmpD0,mmtmpD0); - ul_ch_mag128b[0] = ul_ch_mag128[0]; - ul_ch_mag128c[0] = ul_ch_mag128[0]; - ul_ch_mag128[0] = simde_mm_mulhrs_epi16(ul_ch_mag128[0],QAM_amp128); - ul_ch_mag128b[0] = simde_mm_mulhrs_epi16(ul_ch_mag128b[0],QAM_amp128b); - ul_ch_mag128c[0] = simde_mm_mulhrs_epi16(ul_ch_mag128c[0],QAM_amp128c); - - ul_ch_mag128[1] = simde_mm_unpackhi_epi16(mmtmpD0,mmtmpD0); - ul_ch_mag128b[1] = ul_ch_mag128[1]; - ul_ch_mag128c[1] = ul_ch_mag128[1]; - ul_ch_mag128[1] = simde_mm_mulhrs_epi16(ul_ch_mag128[1],QAM_amp128); - ul_ch_mag128b[1] = simde_mm_mulhrs_epi16(ul_ch_mag128b[1],QAM_amp128b); - ul_ch_mag128c[1] = simde_mm_mulhrs_epi16(ul_ch_mag128c[1],QAM_amp128c); - - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[2],ul_ch128[2]); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_packs_epi32(mmtmpD0,mmtmpD0); - - ul_ch_mag128[2] = simde_mm_unpacklo_epi16(mmtmpD1,mmtmpD1); - ul_ch_mag128b[2] = ul_ch_mag128[2]; - ul_ch_mag128c[2] = ul_ch_mag128[2]; - - ul_ch_mag128[2] = simde_mm_mulhrs_epi16(ul_ch_mag128[2],QAM_amp128); - ul_ch_mag128b[2] = simde_mm_mulhrs_epi16(ul_ch_mag128b[2],QAM_amp128b); - ul_ch_mag128c[2] = simde_mm_mulhrs_epi16(ul_ch_mag128c[2],QAM_amp128c); - } - - // Multiply received data by conjugated channel - rxdataF_comp128[0] = a_mult_conjb(rxdataF128[0], ul_ch128[0], output_shift); - rxdataF_comp128[1] = a_mult_conjb(rxdataF128[1], ul_ch128[1], output_shift); - rxdataF_comp128[2] = a_mult_conjb(rxdataF128[2], ul_ch128[2], output_shift); - - ul_ch128 += 3; - ul_ch_mag128 += 3; - ul_ch_mag128b += 3; - ul_ch_mag128c += 3; - rxdataF128 += 3; - rxdataF_comp128 += 3; - } - } - } - - if (rho) { - //we compute the Tx correlation matrix for each Rx antenna - //As an example the 2x2 MIMO case requires - //rho[aarx][nb_aatx*nb_aatx] = [cov(H_aarx_0,H_aarx_0) cov(H_aarx_0,H_aarx_1) - // cov(H_aarx_1,H_aarx_0) cov(H_aarx_1,H_aarx_1)], aarx=0,...,nb_antennas_rx-1 - - int avg_rho_re[frame_parms->nb_antennas_rx][nrOfLayers*nrOfLayers]; - int avg_rho_im[frame_parms->nb_antennas_rx][nrOfLayers*nrOfLayers]; - - for (aarx=0; aarx < frame_parms->nb_antennas_rx; aarx++) { - for (aatx=0; aatx < nrOfLayers; aatx++) { - for (int atx=0; atx< nrOfLayers; atx++) { - - avg_rho_re[aarx][aatx*nrOfLayers+atx] = 0; - avg_rho_im[aarx][aatx*nrOfLayers+atx] = 0; - rho128 = (simde__m128i *)&rho[aarx][aatx*nrOfLayers+atx][symbol*(off+(nb_rb*12))]; - ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch128_2 = (simde__m128i *)&ul_ch_estimates_ext[atx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - - for (rb=0; rb> 3)+((length&7)?1:0); i++) + { // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[0],ul_ch128_2[0]); - // print_ints("re",&mmtmpD0); - + mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[0], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)&conjugate[0]); - // print_ints("im",&mmtmpD1); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,ul_ch128_2[0]); + mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); + mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - // print_ints("re(shift)",&mmtmpD0); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - // print_ints("im(shift)",&mmtmpD1); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - // print_ints("c0",&mmtmpD2); - // print_ints("c1",&mmtmpD3); - rho128[0] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); + mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); + mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - //print_shorts("rx:",ul_ch128_2); - //print_shorts("ch:",ul_ch128); - //print_shorts("pack:",rho128); - - avg_rho_re[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[0])[0]+ - ((int16_t*)&rho128[0])[2] + - ((int16_t*)&rho128[0])[4] + - ((int16_t*)&rho128[0])[6])/16;// - - avg_rho_im[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[0])[1]+ - ((int16_t*)&rho128[0])[3] + - ((int16_t*)&rho128[0])[5] + - ((int16_t*)&rho128[0])[7])/16;// - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[1],ul_ch128_2[1]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[1], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)conjugate); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,ul_ch128_2[1]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - rho128[1] =simde_mm_packs_epi32(mmtmpD2,mmtmpD3); - //print_shorts("rx:",ul_ch128_2+1); - //print_shorts("ch:",ul_ch128+1); - //print_shorts("pack:",rho128+1); - - // multiply by conjugated channel - avg_rho_re[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[1])[0]+ - ((int16_t*)&rho128[1])[2] + - ((int16_t*)&rho128[1])[4] + - ((int16_t*)&rho128[1])[6])/16; - - avg_rho_im[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[1])[1]+ - ((int16_t*)&rho128[1])[3] + - ((int16_t*)&rho128[1])[5] + - ((int16_t*)&rho128[1])[7])/16; - - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[2],ul_ch128_2[2]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[2], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)conjugate); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,ul_ch128_2[2]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - - rho128[2] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); - //print_shorts("rx:",ul_ch128_2+2); - //print_shorts("ch:",ul_ch128+2); - //print_shorts("pack:",rho128+2); - avg_rho_re[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[2])[0]+ - ((int16_t*)&rho128[2])[2] + - ((int16_t*)&rho128[2])[4] + - ((int16_t*)&rho128[2])[6])/16; - - avg_rho_im[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[2])[1]+ - ((int16_t*)&rho128[2])[3] + - ((int16_t*)&rho128[2])[5] + - ((int16_t*)&rho128[2])[7])/16; - - ul_ch128+=3; - ul_ch128_2+=3; - rho128+=3; - } - if (is_dmrs_symbol==1) { - //measurements->rx_correlation[0][0][aarx] = signal_energy(&rho[aarx][aatx*nb_aatx+atx][symbol*nb_rb*12],rb*12); - avg_rho_re[aarx][aatx*nrOfLayers+atx] = 16*avg_rho_re[aarx][aatx*nrOfLayers+atx]/(nb_rb*12); - avg_rho_im[aarx][aatx*nrOfLayers+atx] = 16*avg_rho_im[aarx][aatx*nrOfLayers+atx]/(nb_rb*12); - //printf("rho[rx]%d tx%d tx%d = Re: %d Im: %d\n",aarx, aatx,atx, avg_rho_re[aarx][aatx*nb_aatx+atx], avg_rho_im[aarx][aatx*nb_aatx+atx]); + rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); } } } @@ -879,39 +710,6 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, simde_mm_empty(); simde_m_empty(); - - -#ifdef DEBUG_CH_COMP - for (int nl2=0; nl2nb_antennas_rx; aarx2++) { - rxF = (int16_t *)&rxdataF_comp[nl2*frame_parms->nb_antennas_rx+aarx2][(symbol*(off+(nb_rb*12)))]; - - printf("--------After compansation, layer %i, antenna rx %i----------\n", nl2, aarx2); - - for (prnt_idx=0;prnt_idx<12*5*2;prnt_idx+=2){ - printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]); - } - } - } -#endif - -#ifdef DEBUG_CH_MAG - - - for (int ant=0; antnb_antennas_rx; ant++) { - ch_mag = (int16_t *)&ul_ch_mag[ant][(symbol*(off+(nb_rb*12)))]; - - printf("----------------After computation------------------\n"); - - for (print_idx=0;print_idx<12*5*2;print_idx+=2){ - - printf("ch_mag[%d] = (%d,%d)\n", print_idx>>1, ch_mag[print_idx],ch_mag[print_idx+1]); - - } - } - -#endif - } void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, @@ -1696,245 +1494,72 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, return(0); } -void inner_rx_qpsk (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t *llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) +void inner_rx (PHY_VARS_gNB *gNB, + int ulsch_id, + int slot, + NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift, + uint32_t nvar) { int length_aligned = (length % 8) ? (8 - length % 8) : 0; - + c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t*)pusch_vars->ul_ch_estimates[aarx], - rxFext[aarx], - chFext[aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - - simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *ulch256 = (simde__m256i*)chFext[aarx]; - simde__m256i *llr256 = (simde__m256i *)llr; - for (int i = 0; i < ((length>>3) + ((length&7) > 0 ? 1:0)); i++) - { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); - - // MRC & LLR - llr256[i] = simde_mm256_add_epi16(llr256[i], xmmp4); + c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int aatx = 0; aatx < nb_layer; aatx++) { + nr_ulsch_extract_rbs0(rxF[aarx], + (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx][aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); } } - // Perform IDFT if transform precoding is enabled - if(rel15_ul->transform_precoding == transformPrecoder_enabled) - nr_idft((int32_t *)llr, length); -} + c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rxComp [nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rxF_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); -void inner_rx_16qam (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t *llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); + memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(rxF_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(rxF_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(rxF_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t rxComp[length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_maga[length + length_aligned] __attribute__((aligned(32))); + nr_ulsch_channel_compensation((c16_t*)rxFext, + (c16_t*)chFext, + (c16_t*)rxF_ch_maga, + (c16_t*)rxF_ch_magb, + (c16_t*)rxF_ch_magc, + (c16_t*)rxComp, + (nb_layer == 1) ? NULL : (c16_t*)rho, + frame_parms, + symbol, + length, + rel15_ul->qam_mod_order, + rel15_ul->nrOfLayers, + nb_rx_ant, + rel15_ul->rb_size, + output_shift); - memset(rxComp, 0, sizeof(c16_t) * (length + length_aligned)); - memset(rxF_ch_maga, 0, sizeof(c16_t) * (length + length_aligned)); - - simde__m256i *rxComp_256 = (simde__m256i *)rxComp; - simde__m256i *rxF_ch_maga_256 = (simde__m256i *)rxF_ch_maga; - - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t*)pusch_vars->ul_ch_estimates[aarx], - rxFext[aarx], - chFext[aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); - - simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *chF_256 = (simde__m256i*)chFext[aarx]; - for (int i = 0; i < ((length>>3) + ((length&7) > 0 ? 1:0)); i++) - { - xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); - - xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp0 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - - xmmp1 = simde_mm256_mulhrs_epi16(xmmp0, QAM_amp256); - - // MRC - rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp1); - rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); - } - } - - if (rel15_ul->transform_precoding == transformPrecoder_enabled) - { - nr_freq_equalization(frame_parms, - (int *)rxComp, - (int *)rxF_ch_maga, - (int *)rxF_ch_maga, - symbol, - length, - rel15_ul->qam_mod_order); - nr_idft((int32_t*)rxComp, length); - } - nr_ulsch_compute_llr((int32_t *)rxComp, - (int32_t *)rxF_ch_maga, - NULL, - NULL, - llr, - rel15_ul->rb_size, - length, - symbol, - rel15_ul->qam_mod_order); -} - -void inner_rx_64qam (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t *llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - - c16_t rxComp[length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_maga[length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_magb[length + length_aligned] __attribute__((aligned(32))); - - memset(rxComp, 0, sizeof(c16_t) * (length + length_aligned)); - memset(rxF_ch_maga, 0, sizeof(c16_t) * (length + length_aligned)); - memset(rxF_ch_magb, 0, sizeof(c16_t) * (length + length_aligned)); - - simde__m256i *rxComp_256 = (simde__m256i *)rxComp; - simde__m256i *rxF_ch_maga_256 = (simde__m256i *)rxF_ch_maga; - simde__m256i *rxF_ch_magb_256 = (simde__m256i *)rxF_ch_magb; - - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t*)pusch_vars->ul_ch_estimates[aarx], - rxFext[aarx], - chFext[aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) - simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM64_n2); - - simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *chF_256 = (simde__m256i*)chFext[aarx]; - for (int i = 0; i < ((length>>3) + ((length&7) > 0 ? 1:0)); i++) - { - xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2,xmmp3); - - xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp0 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - - xmmp1 = simde_mm256_mulhrs_epi16(xmmp0, QAM_amp256); - xmmp2 = simde_mm256_mulhrs_epi16(xmmp0, QAM_amp256b); - - // MRC - rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); - rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp1); - rxF_ch_magb_256[i] = simde_mm256_add_epi16(rxF_ch_magb_256[i], xmmp2); - } - } - - if (rel15_ul->transform_precoding == transformPrecoder_enabled) { + if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { nr_freq_equalization(frame_parms, (int *)rxComp, (int *)rxF_ch_maga, @@ -1944,597 +1569,68 @@ void inner_rx_64qam (NR_DL_FRAME_PARMS *frame_parms, rel15_ul->qam_mod_order); nr_idft((int32_t*)rxComp, length); } - nr_ulsch_compute_llr((int32_t*)rxComp, - (int32_t*)rxF_ch_maga, - (int32_t*)rxF_ch_magb, - NULL, - llr, - rel15_ul->rb_size, - length, - symbol, - rel15_ul->qam_mod_order); -} + // if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + // nr_pusch_ptrs_processing(gNB, + // frame_parms, + // rel15_ul, + // ulsch_id, + // slot, + // symbol, + // length); + // // Subtract total PTRS RE's in the symbol from PUSCH RE's + // length -= pusch_vars->ptrs_re_per_slot; + // } -void inner_rx_256qam (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t *llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t rxComp[length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_maga[length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_magb[length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_magc[length + length_aligned] __attribute__((aligned(32))); - - memset(rxComp, 0, sizeof(c16_t) * (length + length_aligned)); - memset(rxF_ch_maga, 0, sizeof(c16_t) * (length + length_aligned)); - memset(rxF_ch_magb, 0, sizeof(c16_t) * (length + length_aligned)); - memset(rxF_ch_magc, 0, sizeof(c16_t) * (length + length_aligned)); - - simde__m256i *rxComp_256 = (simde__m256i *)rxComp; - simde__m256i *rxF_ch_maga_256 = (simde__m256i *)rxF_ch_maga; - simde__m256i *rxF_ch_magb_256 = (simde__m256i *)rxF_ch_magb; - simde__m256i *rxF_ch_magc_256 = (simde__m256i *)rxF_ch_magc; - - for (int aarx = 0; aarx < nb_rx_ant; aarx++) + if (nb_layer == 2) { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t*)pusch_vars->ul_ch_estimates[aarx], - rxFext[aarx], - chFext[aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - - simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM256_n1); - simde__m256i QAM_amp256b = simde_mm256_set1_epi16(QAM256_n2); - simde__m256i QAM_amp256c = simde_mm256_set1_epi16(QAM256_n3); - - simde__m256i *rxF256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *ulch256 = (simde__m256i*)chFext[aarx]; - for (int i = 0; i < ((length >> 3) + (( length & 7) > 0 ? 1 : 0)); i++) + if (rel15_ul->qam_mod_order < 6) { + c16_t *rho0 = rho[0][1]; + c16_t *rho1 = rho[1][0]; + c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; + c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; + c16_t *ul_ch_mag0 = rxF_ch_maga[0]; + c16_t *ul_ch_mag1 = rxF_ch_maga[1]; + nr_ulsch_compute_ML_llr(pusch_vars, + symbol, + rxComp[0], + rxComp[1], + ul_ch_mag0, + ul_ch_mag1, + llr_0, + llr_1, + rho0, + rho1, + length, + rel15_ul->qam_mod_order); + } + else { - xmmp0 = simde_mm256_madd_epi16(ulch256[i], rxF256[i]); - // xmmp0 contains real part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(ulch256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF256[i]); - // xmmp1 contains imag part of 8 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - // compute channel amplitude for LLR - xmmp0 = simde_mm256_madd_epi16(ulch256[i], ulch256[i]); - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); // contains 16 LLRs - xmmp2 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - xmmp0 = simde_mm256_mulhrs_epi16(xmmp2, QAM_amp256); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp2, QAM_amp256b); - xmmp2 = simde_mm256_mulhrs_epi16(xmmp2, QAM_amp256c); - - // MRC - rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); - rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp0); - rxF_ch_magb_256[i] = simde_mm256_add_epi16(rxF_ch_magb_256[i], xmmp1); - rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], xmmp2); + nr_ulsch_mmse_2layers(frame_parms, + (int **)rxComp, + (int **)rxF_ch_maga, + (int **)rxF_ch_magb, + (int **)rxF_ch_magc, + (int **)chFext, + rel15_ul->rb_size, + frame_parms->nb_antennas_rx, + rel15_ul->qam_mod_order, + pusch_vars->log2_maxh, + symbol, + length, + nvar); } } - nr_ulsch_compute_llr((int32_t*)rxComp, - (int32_t*)rxF_ch_maga, - (int32_t*)rxF_ch_magb, - (int32_t*)rxF_ch_magc, - llr, - rel15_ul->rb_size, - length, - symbol, - rel15_ul->qam_mod_order); -} - -void inner_rx_qpsk_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift, - uint32_t nvar) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) - { + if (nb_layer != 2 || rel15_ul->qam_mod_order >= 6) for (int aatx = 0; aatx < nb_layer; aatx++) - { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t*)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx][aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); - - memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer * (length + length_aligned)); - - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - for (int aatx = 0; aatx < nb_layer; aatx++) { - for (int atx = 0; atx < nb_layer; atx++) { - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, mmtmpD4; - simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; - simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; - simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - for (int i = 0; i < ((length >> 3)+((length&7)?1:0)); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - mmtmpD4 = simde_mm256_packs_epi32(mmtmpD2, mmtmpD3); - - rho_256[i] = simde_mm256_adds_epi16(rho_256[i], mmtmpD4); - } - } - // compensation - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; - simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); - } - } - } - c16_t *rho0 = rho[0][1]; - c16_t *rho1 = rho[1][0]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - - nr_ulsch_qpsk_qpsk(rxComp[0], rxComp[1], llr_0, rho0, length); - nr_ulsch_qpsk_qpsk(rxComp[1], rxComp[0], llr_1, rho1, length); - - nr_ulsch_shift_llr(pusch_vars->llr_layers, length, pusch_vars->llr_offset[symbol] >> 1, 2, 4); -} - - -void inner_rx_16qam_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift, - uint32_t nvar) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - for (int aatx = 0; aatx < nb_layer; aatx++) { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t*)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx][aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - - c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); - - memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer * (length + length_aligned)); - memset(ul_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - - for (int aatx = 0; aatx < nb_layer; aatx++) { - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - for (int atx = 0; atx < nb_layer; atx++) { - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; - simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; - simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; - for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - - rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); - } - } - // compensation - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i QAM_amp256 = simde_mm256_set1_epi16(QAM16_n1); // 2/sqrt(10) - simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; - simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; - simde__m256i *ul_ch_maga_256 = (simde__m256i*)ul_ch_maga[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_amp256); - - rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); - ul_ch_maga_256[i] = simde_mm256_adds_epi16(ul_ch_maga_256[i], xmmp1); - } - } - } - c16_t *rho0 = rho[0][1]; - c16_t *rho1 = rho[1][0]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - c16_t *ul_ch_mag0 = ul_ch_maga[0]; - c16_t *ul_ch_mag1 = ul_ch_maga[1]; - nr_ulsch_qam16_qam16(rxComp[0], rxComp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); - nr_ulsch_qam16_qam16(rxComp[1], rxComp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); -} - -void inner_rx_64qam_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift, - uint32_t nvar) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - for (int aatx = 0; aatx < nb_layer; aatx++) { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx][aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); - - memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); - memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(ul_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(ul_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(ul_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - - for (int aatx = 0; aatx < nb_layer; aatx++) { - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { -#ifdef USE_ML - for (int atx = 0; atx < nb_layer; atx++) { - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; - simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; - simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) - { - // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); - - rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); - } - } -#endif - // compensation - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i QAM_ampa_256 = simde_mm256_set1_epi16(QAM64_n1); // 2/sqrt(10) - simde__m256i QAM_ampb_256 = simde_mm256_set1_epi16(QAM64_n2); // 2/sqrt(10) - simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; - simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; - simde__m256i *ul_ch_maga_256 = (simde__m256i*)ul_ch_maga[aatx]; - simde__m256i *ul_ch_magb_256 = (simde__m256i*)ul_ch_magb[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - - xmmp2 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampa_256); - xmmp3 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampb_256); - - rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); - ul_ch_maga_256[i] = simde_mm256_adds_epi16(ul_ch_maga_256[i], xmmp2); - ul_ch_magb_256[i] = simde_mm256_adds_epi16(ul_ch_magb_256[i], xmmp3); - } - } - } -#ifdef USE_ML - c16_t *rho0 = rho[0][1]; - c16_t *rho1 = rho[1][0]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - c16_t *ul_ch_mag0 = ul_ch_maga[0]; - c16_t *ul_ch_mag1 = ul_ch_maga[1]; - nr_ulsch_qam64_qam64(rxComp[0], rxComp[1], ul_ch_mag0, ul_ch_mag1, llr_0, rho0, length); - nr_ulsch_qam64_qam64(rxComp[1], rxComp[0], ul_ch_mag1, ul_ch_mag0, llr_1, rho1, length); -#else - nr_ulsch_mmse_2layers(frame_parms, - (int **)rxComp, - (int **)ul_ch_maga, - (int **)ul_ch_magb, - (int **)ul_ch_magc, - (int **)chFext, - rel15_ul->rb_size, - frame_parms->nb_antennas_rx, - rel15_ul->qam_mod_order, - pusch_vars->log2_maxh, - symbol, - length, - nvar); - for (int aatx = 0; aatx < nb_layer; aatx++) - nr_ulsch_compute_llr((int32_t*)rxComp[aatx], - (int32_t*)ul_ch_maga[aatx], - (int32_t*)ul_ch_magb[aatx], - (int32_t*)ul_ch_magc[aatx], - &llr[aatx][pusch_vars->llr_offset[symbol]], - rel15_ul->rb_size, - length, - symbol, - rel15_ul->qam_mod_order); -#endif -} - -void inner_rx_256qam_2layer (NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift, - uint32_t nvar) -{ - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - for (int aatx = 0; aatx < nb_layer; aatx++) { - nr_ulsch_extract_rbs0(rxF[aarx], - (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], - rxFext[aarx], - chFext[aatx][aarx], - soffset+(symbol * frame_parms->ofdm_symbol_size), - pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, - aarx, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - } - } - c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rxComp[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t ul_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); - - memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); - memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(ul_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(ul_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(ul_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - - // compensation - for (int aatx = 0; aatx < nb_layer; aatx++) { - for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; - simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); - simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - simde__m256i QAM_ampa_256 = simde_mm256_set1_epi16(QAM256_n1); // 2/sqrt(10) - simde__m256i QAM_ampb_256 = simde_mm256_set1_epi16(QAM256_n2); // 2/sqrt(10) - simde__m256i QAM_ampc_256 = simde_mm256_set1_epi16(QAM256_n3); // 2/sqrt(10) - simde__m256i *rxF_256 = (simde__m256i*)rxFext[aarx]; - simde__m256i *chF_256 = (simde__m256i*)chFext[aatx][aarx]; - simde__m256i *rxComp_256 = (simde__m256i*)rxComp[aatx]; - simde__m256i *ul_ch_maga_256 = (simde__m256i*)ul_ch_maga[aatx]; - simde__m256i *ul_ch_magb_256 = (simde__m256i*)ul_ch_magb[aatx]; - simde__m256i *ul_ch_magc_256 = (simde__m256i*)ul_ch_magc[aatx]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) - { - xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); - // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); - xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); - // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); - xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); - xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); - - xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 - xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); - xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); - xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); - - xmmp2 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampa_256); - xmmp3 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampb_256); - xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampc_256); - - rxComp_256[i] = simde_mm256_adds_epi16(rxComp_256[i], xmmp4); - ul_ch_maga_256[i] = simde_mm256_adds_epi16(ul_ch_maga_256[i], xmmp2); - ul_ch_magb_256[i] = simde_mm256_adds_epi16(ul_ch_magb_256[i], xmmp3); - ul_ch_magc_256[i] = simde_mm256_adds_epi16(ul_ch_magc_256[i], xmmp1); - } - } - } - - nr_ulsch_mmse_2layers(frame_parms, - (int **)rxComp, - (int **)ul_ch_maga, - (int **)ul_ch_magb, - (int **)ul_ch_magc, - (int **)chFext, - rel15_ul->rb_size, - frame_parms->nb_antennas_rx, - rel15_ul->qam_mod_order, - pusch_vars->log2_maxh, - symbol, - length, - nvar); - for (int aatx = 0; aatx < nb_layer; aatx++) - nr_ulsch_compute_llr((int32_t*)rxComp[aatx], - (int32_t*)ul_ch_maga[aatx], - (int32_t*)ul_ch_magb[aatx], - (int32_t*)ul_ch_magc[aatx], - &llr[aatx][pusch_vars->llr_offset[symbol]], - rel15_ul->rb_size, - length, - symbol, - rel15_ul->qam_mod_order); + nr_ulsch_compute_llr((int32_t*)rxComp[aatx], + (int32_t*)rxF_ch_maga[aatx], + (int32_t*)rxF_ch_magb[aatx], + (int32_t*)rxF_ch_magc[aatx], + &llr[aatx][pusch_vars->llr_offset[symbol]], + rel15_ul->rb_size, + length, + symbol, + rel15_ul->qam_mod_order); } void nr_pusch_symbol_processing_noprecoding(void *arg) @@ -2564,109 +1660,45 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) LOG_I(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id].dmrs_symbol); - if (nb_re_pusch == 0) continue; + if (nb_re_pusch == 0) + continue; + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + inner_rx(gNB, + ulsch_id, + slot, + frame_parms, + pusch_vars, + rel15_ul, + gNB->common_vars.rxdataF, + (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, + rdata->llr_layers, + rel15_ul->nrOfLayers, + frame_parms->nb_antennas_rx, + soffset, + nb_re_pusch, // length + symbol, // symbol index + rel15_ul->rb_size, // ofdm size + dmrs_symbol_flag, + gNB->pusch_vars[ulsch_id].log2_maxh, + rdata->nvar); + + simde__m64 *llr_ptr_64; if (rel15_ul->nrOfLayers == 1) + llr_ptr_64 = (simde__m64 *)&rdata->llr_layers[0][pusch_vars->llr_offset[symbol]]; + else { - void (*inner_rx)(NR_DL_FRAME_PARMS *, - NR_gNB_PUSCH *, - nfapi_nr_pusch_pdu_t *, - c16_t **, - c16_t **, - int16_t *, - int32_t, - int32_t, - int32_t, - int32_t, - int32_t, - int16_t, - int32_t, - int32_t); - - if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk; - else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam; - else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam; - else if (rel15_ul->qam_mod_order == 8) inner_rx = inner_rx_256qam; - else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", - rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); - - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - int16_t llr_tmp[(nb_re_pusch + 8) * rel15_ul->qam_mod_order] __attribute__((aligned(32))); - memset(llr_tmp, 0, sizeof(int16_t) * (nb_re_pusch + 8) * rel15_ul->qam_mod_order); - inner_rx(frame_parms, - pusch_vars, - rel15_ul, - gNB->common_vars.rxdataF, - (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, - llr_tmp, - rel15_ul->nrOfLayers, - frame_parms->nb_antennas_rx, - soffset, - nb_re_pusch, // length - symbol, // symbol index - rel15_ul->rb_size, // ofdm size - dmrs_symbol_flag, - gNB->pusch_vars[ulsch_id].log2_maxh); - - // unscrambling - simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol]]; - for (int i = 0; i < nb_re_pusch*rel15_ul->qam_mod_order >> 2; i++) - llr64[i] = simde_mm_mullo_pi16(((simde__m64 *)llr_tmp)[i], s[i]); - - } - else // MIMO for 2x2 - { - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - void (*inner_rx)(NR_DL_FRAME_PARMS *, - NR_gNB_PUSCH *, - nfapi_nr_pusch_pdu_t *, - c16_t **, - c16_t **, - int16_t **, - int32_t, - int32_t, - int32_t, - int32_t, - int32_t, - int16_t, - int32_t, - int32_t, - uint32_t); - if (rel15_ul->qam_mod_order == 2) inner_rx = inner_rx_qpsk_2layer; - else if (rel15_ul->qam_mod_order == 4) inner_rx = inner_rx_16qam_2layer; - else if (rel15_ul->qam_mod_order == 6) inner_rx = inner_rx_64qam_2layer; - else if (rel15_ul->qam_mod_order == 8) inner_rx = inner_rx_256qam_2layer; - else AssertFatal(1==0,"rel15_ul->qam_mod_order %d, pusch_pdu->dmrs_config_type %d\n", - rel15_ul->qam_mod_order,rel15_ul->dmrs_config_type); - - inner_rx(frame_parms, - pusch_vars, - rel15_ul, - gNB->common_vars.rxdataF, - (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, - rdata->llr_layers, - rel15_ul->nrOfLayers, - frame_parms->nb_antennas_rx, - soffset, - nb_re_pusch, // length - symbol, // symbol index - rel15_ul->rb_size, // ofdm size - dmrs_symbol_flag, - gNB->pusch_vars[ulsch_id].log2_maxh, - rdata->nvar); - // layer de-mapping int16_t* llr_cw = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; for (int i = 0; i < (nb_re_pusch); i++) for (int l = 0; l < rel15_ul->nrOfLayers; l++) for (int m = 0; m < rel15_ul->qam_mod_order; m++) llr_cw[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; - - // unscrambling - simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; - for (int i = 0; i < (nb_re_pusch*rel15_ul->qam_mod_order * rel15_ul->nrOfLayers) >> 2; i++) - llr64[i] = simde_mm_mullo_pi16(llr64[i], s[i]); - + llr_ptr_64 = (simde__m64 *)llr_cw; } + // unscrambling + simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers) >> 2; i++) + llr64[i] = simde_mm_mullo_pi16(llr_ptr_64[i], s[i]); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index ddbec269b3..476c9d07bf 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -30,6 +30,7 @@ * \warning */ +#include "PHY/defs_gNB.h" #include "PHY/defs_nr_common.h" #include "PHY/sse_intrin.h" #include "PHY/impl_defs_top.h" @@ -46,16 +47,9 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, { c16_t *rxF = (c16_t *)rxdataF_comp; c16_t *llr32 = (c16_t *)ulsch_llr; - - if (!llr32) { - LOG_E(PHY,"nr_ulsch_qpsk_llr: llr is null, symbol %d, llr32 = %p\n",symbol, llr32); - } for (int i = 0; i < nb_re; i++) { - //*llr32 = *rxF; - llr32->r = rxF->r >> 3; - llr32->i = rxF->i >> 3; - rxF++; - llr32++; + llr32[i].r = rxF[i].r >> 3; + llr32[i].i = rxF[i].i >> 3; } } @@ -3624,46 +3618,7 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, simde_m_empty(); } -void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, - int32_t **ul_ch_mag, - int32_t ***rho, - int16_t **llr_layers, - uint8_t nb_antennas_rx, - uint32_t rb_size, - uint32_t nb_re, - uint8_t symbol, - uint32_t rxdataF_ext_offset, - uint8_t mod_order) -{ - int off = ((rb_size & 1) == 1) ? 4 : 0; - c16_t *rxdataF_comp0 = (c16_t *)&rxdataF_comp[0][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; - c16_t *rxdataF_comp1 = (c16_t *)&rxdataF_comp[nb_antennas_rx][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; - c16_t *ul_ch_mag0 = (c16_t *)&ul_ch_mag[0][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; - c16_t *ul_ch_mag1 = (c16_t *)&ul_ch_mag[nb_antennas_rx][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; - c16_t *llr_layers0 = (c16_t *)&llr_layers[0][rxdataF_ext_offset * mod_order]; - c16_t *llr_layers1 = (c16_t *)&llr_layers[1][rxdataF_ext_offset * mod_order]; - c16_t *rho0 = (c16_t *)&rho[0][1][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; - c16_t *rho1 = (c16_t *)&rho[0][2][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; - - switch (mod_order) { - case 2: - nr_ulsch_qpsk_qpsk(rxdataF_comp0, rxdataF_comp1, llr_layers0, rho0, nb_re); - nr_ulsch_qpsk_qpsk(rxdataF_comp1, rxdataF_comp0, llr_layers1, rho1, nb_re); - break; - case 4: - nr_ulsch_qam16_qam16(rxdataF_comp0, rxdataF_comp1, ul_ch_mag0, ul_ch_mag1, llr_layers0, rho0, nb_re); - nr_ulsch_qam16_qam16(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); - break; - case 6: - nr_ulsch_qam64_qam64(rxdataF_comp0, rxdataF_comp1, ul_ch_mag0, ul_ch_mag1, llr_layers0, rho0, nb_re); - nr_ulsch_qam64_qam64(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); - break; - default: - AssertFatal(1 == 0, "nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d\n", symbol, mod_order); - } -} - -void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift) +static void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift) { simde__m128i *llr_layers0 = (simde__m128i *)&llr_layers[0][rxdataF_ext_offset * mod_order]; simde__m128i *llr_layers1 = (simde__m128i *)&llr_layers[1][rxdataF_ext_offset * mod_order]; @@ -3686,3 +3641,35 @@ void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_e llr_layers1[i] = simde_mm_srai_epi16(llr_layers1[i], shift); } } + +void nr_ulsch_compute_ML_llr(NR_gNB_PUSCH *pusch_vars, + uint32_t symbol, + c16_t* rxdataF_comp0, + c16_t* rxdataF_comp1, + c16_t* ul_ch_mag0, + c16_t* ul_ch_mag1, + c16_t* llr_layers0, + c16_t* llr_layers1, + c16_t* rho0, + c16_t* rho1, + uint32_t nb_re, + uint8_t mod_order) +{ + switch (mod_order) { + case 2: + nr_ulsch_qpsk_qpsk(rxdataF_comp0, rxdataF_comp1, llr_layers0, rho0, nb_re); + nr_ulsch_qpsk_qpsk(rxdataF_comp1, rxdataF_comp0, llr_layers1, rho1, nb_re); + nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re, pusch_vars->llr_offset[symbol] >> 1, 2, 4); + break; + case 4: + nr_ulsch_qam16_qam16(rxdataF_comp0, rxdataF_comp1, ul_ch_mag0, ul_ch_mag1, llr_layers0, rho0, nb_re); + nr_ulsch_qam16_qam16(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); + break; + case 6: + nr_ulsch_qam64_qam64(rxdataF_comp0, rxdataF_comp1, ul_ch_mag0, ul_ch_mag1, llr_layers0, rho0, nb_re); + nr_ulsch_qam64_qam64(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); + break; + default: + AssertFatal(1 == 0, "nr_ulsch_compute_llr: invalid Qm value, Qm = %d\n", mod_order); + } +} From 428af852a0b7947d2d301c842cbf4f37d98cb272 Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Tue, 5 Sep 2023 21:35:03 +0200 Subject: [PATCH 08/43] fix / clean the unused variable --- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 5 ----- openair1/PHY/defs_gNB.h | 4 ---- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 15 --------------- 3 files changed, 24 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index e3dec33a0d..5a079a476a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1717,8 +1717,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; pusch_vars->dmrs_symbol = INVALID_VALUE; - pusch_vars->cl_done = 0; - memset(pusch_vars->extraction_done,0,14*sizeof(int)); gNB->nbSymb=0; bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); @@ -1881,9 +1879,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, else pusch_vars->log2_maxh = (log2_approx(avgs) >> 1); - pusch_vars->cl_done = 1; - pusch_vars->extraction_done[meas_symbol] = 1; - stop_meas(&gNB->rx_pusch_init_stats); start_meas(&gNB->rx_pusch_symbol_processing_stats); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 88367741d4..a28e4a30f4 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -411,10 +411,6 @@ typedef struct { int16_t *ul_valid_re_per_slot; /// \brief offset for llr corresponding to each symbol int llr_offset[14]; - /// flag to verify if channel level computation is done - uint8_t cl_done; - /// flag to indicate if channel extraction is done - int extraction_done[14]; /// flag to indicate DTX on reception int DTX; } NR_gNB_PUSCH; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 64eae8422c..6c4fdd4c05 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -397,21 +397,6 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - - - - // nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, - // pusch_pdu->nrOfLayers, - // pusch_pdu->qam_mod_order, - // G, - // gNB->pusch_vars[ULSCH_id].llr_layers); - // //---------------------------------------------------------- - // //------------------- ULSCH unscrambling ------------------- - // //---------------------------------------------------------- - // start_meas(&gNB->ulsch_unscrambling_stats); - // nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); - // stop_meas(&gNB->ulsch_unscrambling_stats); - //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- From e54d4a98b6bc4cc4a811158d19a00a1e14917afc Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Wed, 6 Sep 2023 17:17:27 +0200 Subject: [PATCH 09/43] fix / fix the log2_maxh for llr - init the variable for simde_m256i avoid error in ubuntu --- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 5a079a476a..309aab6256 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -615,7 +615,9 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, uint32_t nb_rb, uint32_t output_shift) { - simde__m256i QAM_ampa_256, QAM_ampb_256, QAM_ampc_256; + simde__m256i QAM_ampa_256 = simde_mm256_setzero_si256(); + simde__m256i QAM_ampb_256 = simde_mm256_setzero_si256(); + simde__m256i QAM_ampc_256 = simde_mm256_setzero_si256(); if (mod_order == 4) { QAM_ampa_256 = simde_mm256_set1_epi16(QAM16_n1); @@ -1874,10 +1876,14 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avg[aatx*frame_parms->nb_antennas_rx+aarx]); - if (rel15_ul->nrOfLayers == 1) - pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + 2; - else - pusch_vars->log2_maxh = (log2_approx(avgs) >> 1); + + if (rel15_ul->nrOfLayers == 2 && rel15_ul->qam_mod_order < 6) + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) - 3; // for MMSE + else + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); + + if (pusch_vars->log2_maxh < 0) + pusch_vars->log2_maxh = 0; stop_meas(&gNB->rx_pusch_init_stats); From 090ac4870df34d420261173c9fe9ba25c6fed465 Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Wed, 13 Sep 2023 14:15:29 +0200 Subject: [PATCH 10/43] fix / init the variable init the PUSCH symbols per thread to avoid for stucking --- executables/nr-gnb.c | 3 ++- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index d436828294..e4a9e4e5e6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -475,7 +475,8 @@ void init_gNB_Tpool(int inst) { PHY_VARS_gNB *gNB; gNB = RC.gNB[inst]; gNB_L1_proc_t *proc = &gNB->proc; - + // PUSCH symbols per thread need to be calculated by how many threads we have + gNB->num_pusch_symbols_per_thread = 1; // ULSCH decoding threadpool initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE)); // ULSCH decoder result FIFO diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 309aab6256..3fa192f7cb 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1931,7 +1931,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, while (gNB->nbSymb > 0) { - notifiedFIFO_elt_t *req=pullTpool(&gNB->respPuschSymb, &gNB->threadPool); + notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool); gNB->nbSymb--; delNotifiedFIFO_elt(req); } From 39e7e091520afe4fdadb50e69941741f98da62bb Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Wed, 13 Sep 2023 16:12:44 +0200 Subject: [PATCH 11/43] fix / set the output shift to correct value --- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 3fa192f7cb..e03d9cc198 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1876,10 +1876,11 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avg[aatx*frame_parms->nb_antennas_rx+aarx]); + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1); - if (rel15_ul->nrOfLayers == 2 && rel15_ul->qam_mod_order < 6) + if (rel15_ul->nrOfLayers == 2 && rel15_ul->qam_mod_order >= 6) pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) - 3; // for MMSE - else + else if (rel15_ul->nrOfLayers == 1) pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); if (pusch_vars->log2_maxh < 0) From 9db99b2fd2d06afd513564b30327e9b83577e99b Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Thu, 14 Sep 2023 01:02:37 +0200 Subject: [PATCH 12/43] feat / add ptrs module --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 21 ++-- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 103 +++++++++--------- 2 files changed, 61 insertions(+), 63 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 98606e7f3c..11a316d77e 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -486,6 +486,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, * 2) Interpolate PTRS estimated value in TD after all PTRS symbols * 3) Compensated DMRS based estimated signal with PTRS estimation for slot *********************************************************************/ +// #define DEBUG_UL_PTRS void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul, @@ -495,7 +496,6 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint32_t nb_re_pusch) { NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; - //#define DEBUG_UL_PTRS 1 int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; @@ -573,13 +573,6 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, } } -#ifdef DEBUG_UL_PTRS - LOG_M("ptrsEstUl.m", "est", pusch_vars->ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1); - LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp", - &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size], - rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1); -#endif - /*------------------------------------------------------------------------------------------------------- */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */ /*--------------------------------------------------------------------------------------------------------*/ @@ -590,15 +583,15 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, #ifdef DEBUG_UL_PTRS printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); #endif - rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], &phase_per_symbol[i], - (c16_t *)&pusch_vars->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + (c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], ((*nb_rb) * NR_NB_SC_PER_RB), 15); - }// if not DMRS Symbol - }// symbol loop - }// last symbol check - }//Antenna loop + } // if not DMRS Symbol + } // symbol loop + } // last symbol check + } // Antenna loop } uint32_t calc_power(const int16_t *x, const uint32_t size) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index e03d9cc198..ad4d696d4d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -604,7 +604,7 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, c16_t *ul_ch_maga, c16_t *ul_ch_magb, c16_t *ul_ch_magc, - c16_t *rxComp, + int32_t **rxComp, c16_t *rho, NR_DL_FRAME_PARMS *frame_parms, uint32_t symbol, @@ -640,9 +640,9 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); int length_aligned = (length % 8) ? (8 - length % 8) : 0; - + int rxComp_aligned = ((nb_rb * 12) % 8) ? (8 - (nb_rb * 12) % 8) : 0; for (int aatx = 0; aatx < nrOfLayers; aatx++) { - simde__m256i *rxComp_256 = (simde__m256i*) &rxComp[aatx * (length + length_aligned)]; + simde__m256i *rxComp_256 = (simde__m256i*) &rxComp[aatx * nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)]; simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * (length + length_aligned)]; simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * (length + length_aligned)]; simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * (length + length_aligned)]; @@ -1382,13 +1382,14 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, simde__m128i *determ_fin_128 = (simde__m128i *)&determ_fin[0]; - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)&((int *)rxdataF_comp)[0 * (length + length_aligned)]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&((int *)rxdataF_comp)[1 * (length + length_aligned)]; simde__m128i *after_mf_a_128 = (simde__m128i *)af_mf_00; simde__m128i *after_mf_b_128 = (simde__m128i *)af_mf_01; simde__m128i *after_mf_c_128 = (simde__m128i *)af_mf_10; simde__m128i *after_mf_d_128 = (simde__m128i *)af_mf_11; - + + int rxComp_aligned = ((nb_rb * 12) % 8) ? (8 - (nb_rb * 12) % 8) : 0; + simde__m128i *rxdataF_comp128_0 = (simde__m128i *)&rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[n_rx][symbol * (nb_rb * 12 + rxComp_aligned)]; if (mod_order > 2) { if (mod_order == 4) { @@ -1496,24 +1497,24 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, return(0); } -void inner_rx (PHY_VARS_gNB *gNB, - int ulsch_id, - int slot, - NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, - c16_t **rxF, - c16_t **ul_ch, - int16_t **llr, - int nb_layer, - int nb_rx_ant, - int soffset, - int length, - int symbol, - int short nb_rb, - int dmrs_symbol_flag, - int output_shift, - uint32_t nvar) +static void inner_rx (PHY_VARS_gNB *gNB, + int ulsch_id, + int slot, + NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int nb_layer, + int nb_rx_ant, + int soffset, + int length, + int symbol, + int short nb_rb, + int dmrs_symbol_flag, + int output_shift, + uint32_t nvar) { int length_aligned = (length % 8) ? (8 - length % 8) : 0; @@ -1539,18 +1540,21 @@ void inner_rx (PHY_VARS_gNB *gNB, c16_t rxF_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); c16_t rxF_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); + int rxComp_aligned = ((nb_rb * 12) % 8) ? (8 - (nb_rb * 12) % 8) : 0; memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); memset(rxF_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); memset(rxF_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); memset(rxF_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + for (int i = 0; i < nb_layer; i++) + memset(&pusch_vars->rxdataF_comp[i*nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)], 0, sizeof(int32_t) * (nb_rb * 12 + rxComp_aligned)); nr_ulsch_channel_compensation((c16_t*)rxFext, (c16_t*)chFext, (c16_t*)rxF_ch_maga, (c16_t*)rxF_ch_magb, (c16_t*)rxF_ch_magc, - (c16_t*)rxComp, + pusch_vars->rxdataF_comp, // (c16_t*)rxComp, (nb_layer == 1) ? NULL : (c16_t*)rho, frame_parms, symbol, @@ -1563,25 +1567,26 @@ void inner_rx (PHY_VARS_gNB *gNB, if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { nr_freq_equalization(frame_parms, - (int *)rxComp, + (int *)&pusch_vars->rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)], (int *)rxF_ch_maga, (int *)rxF_ch_magb, symbol, length, rel15_ul->qam_mod_order); - nr_idft((int32_t*)rxComp, length); + nr_idft((int32_t*)&pusch_vars->rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)], length); + } + if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + nr_pusch_ptrs_processing(gNB, + frame_parms, + rel15_ul, + ulsch_id, + slot, + symbol, + nb_rb * 12 + rxComp_aligned); + // Subtract total PTRS RE's in the symbol from PUSCH RE's + length -= pusch_vars->ptrs_re_per_slot; + pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot; } - // if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - // nr_pusch_ptrs_processing(gNB, - // frame_parms, - // rel15_ul, - // ulsch_id, - // slot, - // symbol, - // length); - // // Subtract total PTRS RE's in the symbol from PUSCH RE's - // length -= pusch_vars->ptrs_re_per_slot; - // } if (nb_layer == 2) { @@ -1594,8 +1599,8 @@ void inner_rx (PHY_VARS_gNB *gNB, c16_t *ul_ch_mag1 = rxF_ch_maga[1]; nr_ulsch_compute_ML_llr(pusch_vars, symbol, - rxComp[0], - rxComp[1], + (c16_t*)&pusch_vars->rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)], + (c16_t*)&pusch_vars->rxdataF_comp[nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)], ul_ch_mag0, ul_ch_mag1, llr_0, @@ -1608,7 +1613,7 @@ void inner_rx (PHY_VARS_gNB *gNB, else { nr_ulsch_mmse_2layers(frame_parms, - (int **)rxComp, + (int32_t **)pusch_vars->rxdataF_comp, (int **)rxF_ch_maga, (int **)rxF_ch_magb, (int **)rxF_ch_magc, @@ -1624,7 +1629,7 @@ void inner_rx (PHY_VARS_gNB *gNB, } if (nb_layer != 2 || rel15_ul->qam_mod_order >= 6) for (int aatx = 0; aatx < nb_layer; aatx++) - nr_ulsch_compute_llr((int32_t*)rxComp[aatx], + nr_ulsch_compute_llr((int32_t*)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)], (int32_t*)rxF_ch_maga[aatx], (int32_t*)rxF_ch_magb[aatx], (int32_t*)rxF_ch_magc[aatx], @@ -1646,7 +1651,6 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) int ulsch_id = rdata->ulsch_id; int slot = rdata->slot; NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; - simde__m64 *s = (simde__m64 *)rdata->s; for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) { int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; @@ -1684,21 +1688,22 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) gNB->pusch_vars[ulsch_id].log2_maxh, rdata->nvar); - simde__m64 *llr_ptr_64; + simde__m64 *s = (simde__m64*)rdata->s; + int16_t *llr_ptr; if (rel15_ul->nrOfLayers == 1) - llr_ptr_64 = (simde__m64 *)&rdata->llr_layers[0][pusch_vars->llr_offset[symbol]]; + llr_ptr = &rdata->llr_layers[0][pusch_vars->llr_offset[symbol]]; else { // layer de-mapping - int16_t* llr_cw = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + llr_ptr = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; for (int i = 0; i < (nb_re_pusch); i++) for (int l = 0; l < rel15_ul->nrOfLayers; l++) for (int m = 0; m < rel15_ul->qam_mod_order; m++) - llr_cw[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; - llr_ptr_64 = (simde__m64 *)llr_cw; + llr_ptr[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; } // unscrambling - simde__m64 *llr64 = (simde__m64 *) &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + simde__m64* llr_ptr_64 = (simde__m64*)llr_ptr; + simde__m64 *llr64 = (simde__m64*)&rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; for (int i = 0; i < (nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers) >> 2; i++) llr64[i] = simde_mm_mullo_pi16(llr_ptr_64[i], s[i]); } From f4beb879cc75f77dae8cf71e9cc0e5d7883fab31 Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Fri, 15 Sep 2023 16:33:55 +0200 Subject: [PATCH 13/43] fix / unscrambling runtime error - fix the unscrambling runtime error - avoid to many variables pass by function --- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 38 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 474 ++++++------------ .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 15 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 - 4 files changed, 158 insertions(+), 371 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 5d25f623df..ab25bd7744 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -125,40 +125,17 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM @param slot Slot number @param harq_pid HARQ process ID */ -void nr_rx_pusch(PHY_VARS_gNB *gNB, - uint8_t UE_id, - uint32_t frame, - uint8_t slot, - unsigned char harq_pid); - int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t slot, 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_rb_pusch The number of RBs allocated (used for Resource Allocation Type 1 in NR) - @param frame_parms, Pointer to frame descriptor structure -*/ -void nr_ulsch_extract_rbs(c16_t **rxdataF, - NR_gNB_PUSCH *pusch_vars, - int slot, - unsigned char symbol, - uint8_t is_dmrs_symbol, - nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_DL_FRAME_PARMS *frame_parms); - void nr_ulsch_scale_channel(int32_t **ul_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, NR_gNB_ULSCH_t *ulsch_gNB, uint8_t symbol, - uint8_t is_dmrs_symbol, + uint8_t is_dmrs_symbol, uint32_t len, uint8_t nrOfLayers, uint16_t nb_rb, @@ -186,7 +163,11 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, */ void nr_idft(int32_t *z, uint32_t Msc_PUSCH); -void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, c16_t *stream1_in, c16_t *stream0_out, c16_t *rho01, uint32_t length); +void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, + c16_t *stream1_in, + c16_t *stream0_out, + c16_t *rho01, + uint32_t length); void nr_ulsch_qam16_qam16(c16_t *stream0_in, c16_t *stream1_in, @@ -211,7 +192,7 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, @param symbol OFDM symbol index in sub-frame */ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, - int16_t *ulsch_llr, + int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol); @@ -226,11 +207,9 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int32_t **ul_ch_mag, int16_t *ulsch_llr, - uint32_t nb_rb, 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 @@ -243,7 +222,6 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, int32_t **ul_ch_mag, int32_t **ul_ch_magb, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol); @@ -261,7 +239,6 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, int32_t **ul_ch_magb, int32_t **ul_ch_magc, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol); @@ -279,7 +256,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, int32_t *ul_ch_magb, int32_t *ul_ch_magc, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol, uint8_t mod_order); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index ad4d696d4d..d22ad70ee5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -11,11 +11,6 @@ #include #include "PHY/sse_intrin.h" -//#define DEBUG_CH_COMP -//#define DEBUG_RB_EXT -//#define DEBUG_CH_MAG -//#define ML_DEBUG - #define INVALID_VALUE 255 void nr_idft(int32_t *z, uint32_t Msc_PUSCH) @@ -281,7 +276,7 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) } -static void nr_ulsch_extract_rbs0 (c16_t* const rxdataF, +static void nr_ulsch_extract_rbs (c16_t* const rxdataF, c16_t* const chF, c16_t *rxFext, c16_t *chFext, @@ -385,99 +380,6 @@ static void nr_ulsch_extract_rbs0 (c16_t* const rxdataF, } } -void nr_ulsch_extract_rbs(c16_t **rxdataF, - NR_gNB_PUSCH *pusch_vars, - int slot, - unsigned char symbol, - uint8_t is_dmrs_symbol, - nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_DL_FRAME_PARMS *frame_parms) { - - unsigned short start_re, re, nb_re_pusch; - unsigned char aarx, aatx; - uint32_t rxF_ext_index = 0; - uint32_t ul_ch0_ext_index = 0; - uint32_t ul_ch0_index = 0; - int16_t *rxF,*rxF_ext; - int *ul_ch0,*ul_ch0_ext; - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - -#ifdef DEBUG_RB_EXT - printf("--------------------symbol = %d-----------------------\n", symbol); - printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size); -#endif - - uint8_t is_data_re; - start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size; - nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; - - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); - - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol * frame_parms->ofdm_symbol_size)]; - rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch2]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 - - if (is_dmrs_symbol == 0) { - if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) { - memcpy((void*)rxF_ext, (void*)&rxF[start_re*2], nb_re_pusch*sizeof(int32_t)); - } else { - int neg_length = frame_parms->ofdm_symbol_size-start_re; - int pos_length = nb_re_pusch-neg_length; - memcpy((void*)rxF_ext,(void*)&rxF[start_re*2],neg_length*sizeof(int32_t)); - memcpy((void*)&rxF_ext[2*neg_length],(void*)rxF,pos_length*sizeof(int32_t)); - } - - for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) { - ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2]; - memcpy((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t)); - } - - } else { - - for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) { - ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2]; - - rxF_ext_index = 0; - ul_ch0_ext_index = 0; - ul_ch0_index = 0; - for (re = 0; re < nb_re_pusch; re++) { - uint16_t k = start_re + re; - is_data_re = allowed_xlsch_re_in_dmrs_symbol(k, start_re, frame_parms->ofdm_symbol_size, pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dmrs_config_type); - if (++k >= frame_parms->ofdm_symbol_size) { - k -= frame_parms->ofdm_symbol_size; - } - - #ifdef DEBUG_RB_EXT - printf("re = %d, is_dmrs_symbol = %d, symbol = %d\n", re, is_dmrs_symbol, symbol); - #endif - - // save only data and respective channel estimates - if (is_data_re == 1) { - if (aatx == 0) { - rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); - rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); - rxF_ext_index +=2; - } - - ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index]; - ul_ch0_ext_index++; - - #ifdef DEBUG_RB_EXT - printf("dmrs symb %d: rxF_ext[%u] = (%d,%d), ul_ch0_ext[%u] = (%d,%d)\n", - is_dmrs_symbol,rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1], - ul_ch0_ext_index, ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[0], ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[1]); - #endif - } - ul_ch0_index++; - } - } - } - } -} - void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, NR_gNB_ULSCH_t *ulsch_gNB, @@ -607,14 +509,15 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, int32_t **rxComp, c16_t *rho, NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t* rel15_ul, uint32_t symbol, - uint32_t length, - uint32_t mod_order, - uint8_t nrOfLayers, - uint8_t nb_rx_ant, - uint32_t nb_rb, - uint32_t output_shift) + uint32_t buffer_length, + uint32_t output_shift) { + int mod_order = rel15_ul->qam_mod_order; + int nrOfLayers = rel15_ul->nrOfLayers; + int nb_rx_ant = frame_parms->nb_antennas_rx; + simde__m256i QAM_ampa_256 = simde_mm256_setzero_si256(); simde__m256i QAM_ampb_256 = simde_mm256_setzero_si256(); simde__m256i QAM_ampc_256 = simde_mm256_setzero_si256(); @@ -639,18 +542,16 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - int length_aligned = (length % 8) ? (8 - length % 8) : 0; - int rxComp_aligned = ((nb_rb * 12) % 8) ? (8 - (nb_rb * 12) % 8) : 0; for (int aatx = 0; aatx < nrOfLayers; aatx++) { - simde__m256i *rxComp_256 = (simde__m256i*) &rxComp[aatx * nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)]; - simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * (length + length_aligned)]; - simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * (length + length_aligned)]; - simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * (length + length_aligned)]; + simde__m256i *rxComp_256 = (simde__m256i*) &rxComp[aatx * nb_rx_ant][symbol * buffer_length]; + simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * buffer_length]; + simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * buffer_length]; + simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * buffer_length]; for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - simde__m256i *rxF_256 = (simde__m256i*) &rxFext[aarx * (length + length_aligned)]; - simde__m256i *chF_256 = (simde__m256i*) &chFext[(aatx * nb_rx_ant + aarx) * (length + length_aligned)]; + simde__m256i *rxF_256 = (simde__m256i*) &rxFext[aarx * buffer_length]; + simde__m256i *chF_256 = (simde__m256i*) &chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; - for (int i = 0; i < (length>>3) + ((length&7)?1:0); i++) + for (int i = 0; i < buffer_length >> 3; i++) { xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] @@ -682,28 +583,25 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, if (mod_order > 6) rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], xmmp1); } - if (rho != NULL) - { + if (rho != NULL) { for (int atx = 0; atx < nrOfLayers; atx++) { - simde__m256i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; - simde__m256i *rho_256 = (simde__m256i * )&rho[(aatx * nrOfLayers + atx) * (length + length_aligned)]; - simde__m256i *chF_256 = (simde__m256i *)&chFext[(aatx * nb_rx_ant + aarx) * (length + length_aligned)]; - simde__m256i *chF2_256 = (simde__m256i *)&chFext[ (atx * nb_rx_ant + aarx) * (length + length_aligned)]; - for (int i = 0; i < (length >> 3)+((length&7)?1:0); i++) - { + simde__m256i *rho_256 = (simde__m256i * )&rho[(aatx * nrOfLayers + atx) * buffer_length]; + simde__m256i *chF_256 = (simde__m256i *)&chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; + simde__m256i *chF2_256 = (simde__m256i *)&chFext[ (atx * nb_rx_ant + aarx) * buffer_length]; + for (int i = 0; i < buffer_length >> 3; i++) { // multiply by conjugated channel - mmtmpD0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); - mmtmpD1 = simde_mm256_sign_epi16(mmtmpD1, conj256); - mmtmpD1 = simde_mm256_madd_epi16(mmtmpD1, chF2_256[i]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm256_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm256_srai_epi32(mmtmpD1, output_shift); - mmtmpD2 = simde_mm256_unpacklo_epi32(mmtmpD0, mmtmpD1); - mmtmpD3 = simde_mm256_unpackhi_epi32(mmtmpD0, mmtmpD1); + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, chF2_256[i]); + // xmmp0 contains imag part of 4 consecutive outputs (32-bit) + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(mmtmpD2, mmtmpD3)); + rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(xmmp2, xmmp3)); } } } @@ -714,79 +612,15 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, simde_m_empty(); } -void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, - int32_t **ul_ch_mag, - int32_t **ul_ch_magb, - int32_t **ul_ch_magc, - int32_t ***rho, - uint8_t nrOfLayers, - uint8_t symbol, - uint16_t nb_rb, - int length) { - int n_rx = frame_parms->nb_antennas_rx; - simde__m128i *rxdataF_comp128[2],*ul_ch_mag128[2],*ul_ch_mag128b[2],*ul_ch_mag128c[2]; - int32_t i; - uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); - - int off = ((nb_rb&1) == 1)? 4:0; - - if (n_rx > 1) { - - int nb_re = nb_rb * 12; - - for (int aatx = 0; aatx < nrOfLayers; aatx++) { - - rxdataF_comp128[0] = (simde__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - ul_ch_mag128[0] = (simde__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - ul_ch_mag128b[0] = (simde__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - ul_ch_mag128c[0] = (simde__m128i *)&ul_ch_magc[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - - for (int aa=1;aa < n_rx;aa++) { - rxdataF_comp128[1] = (simde__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - ul_ch_mag128[1] = (simde__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - ul_ch_mag128b[1] = (simde__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - ul_ch_mag128c[1] = (simde__m128i *)&ul_ch_magc[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - - // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) - for (i=0; inrOfLayers; + int nb_rx_ant = frame_parms->nb_antennas_rx; + int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + + int buffer_length = rel15_ul->rb_size * NR_NB_SC_PER_RB; + if (buffer_length & 7) + buffer_length += (8 - buffer_length%8); - c16_t rxFext[nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); - c16_t chFext[nb_layer][nb_rx_ant][length + length_aligned] __attribute__((aligned(32))); + c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32))); + c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32))); + + memset(rxFext, 0, sizeof(c16_t) * nb_rx_ant * buffer_length); + memset(chFext, 0, sizeof(c16_t) * nb_layer * nb_rx_ant* buffer_length); + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { for (int aatx = 0; aatx < nb_layer; aatx++) { - nr_ulsch_extract_rbs0(rxF[aarx], + nr_ulsch_extract_rbs(rxF[aarx], (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], rxFext[aarx], chFext[aatx][aarx], @@ -1534,46 +1376,40 @@ static void inner_rx (PHY_VARS_gNB *gNB, frame_parms); } } - c16_t rho[nb_layer][nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rxComp [nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_maga[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_magb[nb_layer][length + length_aligned] __attribute__((aligned(32))); - c16_t rxF_ch_magc[nb_layer][length + length_aligned] __attribute__((aligned(32))); + c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(32))); + c16_t rxF_ch_maga [nb_layer][buffer_length] __attribute__((aligned(32))); + c16_t rxF_ch_magb [nb_layer][buffer_length] __attribute__((aligned(32))); + c16_t rxF_ch_magc [nb_layer][buffer_length] __attribute__((aligned(32))); - int rxComp_aligned = ((nb_rb * 12) % 8) ? (8 - (nb_rb * 12) % 8) : 0; - memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* (length + length_aligned)); - memset(rxComp, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(rxF_ch_maga, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(rxF_ch_magb, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); - memset(rxF_ch_magc, 0, sizeof(c16_t) * nb_layer * (length + length_aligned)); + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* buffer_length); + memset(rxF_ch_maga, 0, sizeof(c16_t) * nb_layer * buffer_length); + memset(rxF_ch_magb, 0, sizeof(c16_t) * nb_layer * buffer_length); + memset(rxF_ch_magc, 0, sizeof(c16_t) * nb_layer * buffer_length); for (int i = 0; i < nb_layer; i++) - memset(&pusch_vars->rxdataF_comp[i*nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)], 0, sizeof(int32_t) * (nb_rb * 12 + rxComp_aligned)); + memset(&pusch_vars->rxdataF_comp[i*nb_rx_ant][symbol * buffer_length], 0, sizeof(int32_t) * buffer_length); nr_ulsch_channel_compensation((c16_t*)rxFext, (c16_t*)chFext, (c16_t*)rxF_ch_maga, (c16_t*)rxF_ch_magb, (c16_t*)rxF_ch_magc, - pusch_vars->rxdataF_comp, // (c16_t*)rxComp, + pusch_vars->rxdataF_comp, (nb_layer == 1) ? NULL : (c16_t*)rho, frame_parms, + rel15_ul, symbol, - length, - rel15_ul->qam_mod_order, - rel15_ul->nrOfLayers, - nb_rx_ant, - rel15_ul->rb_size, + buffer_length, output_shift); if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { nr_freq_equalization(frame_parms, - (int *)&pusch_vars->rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)], - (int *)rxF_ch_maga, - (int *)rxF_ch_magb, - symbol, - length, - rel15_ul->qam_mod_order); - nr_idft((int32_t*)&pusch_vars->rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)], length); + &pusch_vars->rxdataF_comp[0][symbol * buffer_length], + (int *)rxF_ch_maga, + (int *)rxF_ch_magb, + symbol, + pusch_vars->ul_valid_re_per_slot[symbol], + rel15_ul->qam_mod_order); + nr_idft(&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]); } if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { nr_pusch_ptrs_processing(gNB, @@ -1582,36 +1418,26 @@ static void inner_rx (PHY_VARS_gNB *gNB, ulsch_id, slot, symbol, - nb_rb * 12 + rxComp_aligned); - // Subtract total PTRS RE's in the symbol from PUSCH RE's - length -= pusch_vars->ptrs_re_per_slot; + buffer_length); pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot; } - if (nb_layer == 2) - { + if (nb_layer == 2) { if (rel15_ul->qam_mod_order < 6) { - c16_t *rho0 = rho[0][1]; - c16_t *rho1 = rho[1][0]; - c16_t *llr_0 = (c16_t *)&llr[0][pusch_vars->llr_offset[symbol]]; - c16_t *llr_1 = (c16_t *)&llr[1][pusch_vars->llr_offset[symbol]]; - c16_t *ul_ch_mag0 = rxF_ch_maga[0]; - c16_t *ul_ch_mag1 = rxF_ch_maga[1]; nr_ulsch_compute_ML_llr(pusch_vars, symbol, - (c16_t*)&pusch_vars->rxdataF_comp[0][symbol * (nb_rb * 12 + rxComp_aligned)], - (c16_t*)&pusch_vars->rxdataF_comp[nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)], - ul_ch_mag0, - ul_ch_mag1, - llr_0, - llr_1, - rho0, - rho1, - length, + (c16_t*)&pusch_vars->rxdataF_comp[0][symbol * buffer_length], + (c16_t*)&pusch_vars->rxdataF_comp[nb_rx_ant][symbol * buffer_length], + rxF_ch_maga[0], + rxF_ch_maga[1], + (c16_t*)&llr[0][pusch_vars->llr_offset[symbol]], + (c16_t*)&llr[1][pusch_vars->llr_offset[symbol]], + rho[0][1], + rho[1][0], + pusch_vars->ul_valid_re_per_slot[symbol], rel15_ul->qam_mod_order); } - else - { + else { nr_ulsch_mmse_2layers(frame_parms, (int32_t **)pusch_vars->rxdataF_comp, (int **)rxF_ch_maga, @@ -1623,26 +1449,25 @@ static void inner_rx (PHY_VARS_gNB *gNB, rel15_ul->qam_mod_order, pusch_vars->log2_maxh, symbol, - length, - nvar); + pusch_vars->ul_valid_re_per_slot[symbol], + nvar, + buffer_length); } } if (nb_layer != 2 || rel15_ul->qam_mod_order >= 6) for (int aatx = 0; aatx < nb_layer; aatx++) - nr_ulsch_compute_llr((int32_t*)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * (nb_rb * 12 + rxComp_aligned)], + nr_ulsch_compute_llr((int32_t*)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * buffer_length], (int32_t*)rxF_ch_maga[aatx], (int32_t*)rxF_ch_magb[aatx], (int32_t*)rxF_ch_magc[aatx], &llr[aatx][pusch_vars->llr_offset[symbol]], - rel15_ul->rb_size, - length, + pusch_vars->ul_valid_re_per_slot[symbol], symbol, rel15_ul->qam_mod_order); } -void nr_pusch_symbol_processing_noprecoding(void *arg) +void nr_pusch_symbol_processing(void *arg) { - puschSymbolProc_t *rdata=(puschSymbolProc_t*)arg; PHY_VARS_gNB *gNB = rdata->gNB; @@ -1651,12 +1476,8 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) int ulsch_id = rdata->ulsch_id; int slot = rdata->slot; NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; - for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) - { + for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) { int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; - // this needs to be reworded for parrellization, we need a table which give dmrs symbol location - // used for chennel estimate, they are being run in parallel! if (dmrs_symbol_flag == 1) { if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) @@ -1664,9 +1485,7 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) gNB->pusch_vars[ulsch_id].dmrs_symbol = symbol; } - LOG_I(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id].dmrs_symbol); - - if (nb_re_pusch == 0) + if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0) continue; int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; inner_rx(gNB, @@ -1678,23 +1497,16 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) gNB->common_vars.rxdataF, (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, rdata->llr_layers, - rel15_ul->nrOfLayers, - frame_parms->nb_antennas_rx, soffset, - nb_re_pusch, // length - symbol, // symbol index - rel15_ul->rb_size, // ofdm size - dmrs_symbol_flag, + gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol], + symbol, gNB->pusch_vars[ulsch_id].log2_maxh, rdata->nvar); - simde__m64 *s = (simde__m64*)rdata->s; - int16_t *llr_ptr; - if (rel15_ul->nrOfLayers == 1) - llr_ptr = &rdata->llr_layers[0][pusch_vars->llr_offset[symbol]]; - else - { - // layer de-mapping + int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; + // layer de-mapping + int16_t* llr_ptr = &rdata->llr_layers[0][pusch_vars->llr_offset[symbol]]; + if (rel15_ul->nrOfLayers != 1) { llr_ptr = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; for (int i = 0; i < (nb_re_pusch); i++) for (int l = 0; l < rel15_ul->nrOfLayers; l++) @@ -1702,10 +1514,9 @@ void nr_pusch_symbol_processing_noprecoding(void *arg) llr_ptr[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; } // unscrambling - simde__m64* llr_ptr_64 = (simde__m64*)llr_ptr; - simde__m64 *llr64 = (simde__m64*)&rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; - for (int i = 0; i < (nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers) >> 2; i++) - llr64[i] = simde_mm_mullo_pi16(llr_ptr_64[i], s[i]); + int16_t *llr16 = (int16_t*)&rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers); i++) + llr16[i] = llr_ptr[i] * rdata->s[i]; } } @@ -1843,13 +1654,21 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, start_meas(&gNB->ulsch_rbs_extraction_stats); // extract the first dmrs for the channel level computation // extract the data in the OFDM frame, to the start of the array - nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, - pusch_vars, - slot, - meas_symbol, - (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, - rel15_ul, - frame_parms); + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) + nr_ulsch_extract_rbs(gNB->common_vars.rxdataF[aarx], + (c16_t *)pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx], + (c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch2], + (c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][meas_symbol*nb_re_pusch2], + soffset + meas_symbol * frame_parms->ofdm_symbol_size, + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, + rel15_ul, + frame_parms); + stop_meas(&gNB->ulsch_rbs_extraction_stats); int avgs = 0; @@ -1901,19 +1720,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, symbol += numSymbols) { int total_res = 0; - for (int s = 0; s < numSymbols;s++) - { + for (int s = 0; s < numSymbols;s++) { pusch_vars->ul_valid_re_per_slot[symbol+s] = get_nb_re_pusch(frame_parms,rel15_ul,symbol+s); pusch_vars->llr_offset[symbol+s] = ((symbol+s) == rel15_ul->start_symbol_index) ? 0 : pusch_vars->llr_offset[symbol+s-1] + pusch_vars->ul_valid_re_per_slot[symbol+s-1] * rel15_ul->qam_mod_order; total_res+=pusch_vars->ul_valid_re_per_slot[symbol+s]; } - if (total_res > 0) - { + if (total_res > 0) { union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}}; id.p=1+symbol; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing_noprecoding); // create a job for Tpool + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing); // create a job for Tpool puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job rdata->gNB = gNB; @@ -1928,15 +1745,18 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rdata->s = &s[pusch_vars->llr_offset[symbol]*rel15_ul->nrOfLayers]; rdata->nvar = nvar; - pushTpool(&gNB->threadPool, req); - gNB->nbSymb++; + if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + nr_pusch_symbol_processing(rdata); + } else { + pushTpool(&gNB->threadPool, req); + gNB->nbSymb++; + } LOG_D(PHY,"%d.%d Added symbol %d (count %d) to process, in pipe\n",frame,slot,symbol,gNB->nbSymb); } } // symbol loop - while (gNB->nbSymb > 0) - { + while (gNB->nbSymb > 0 && !(rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS)) { notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool); gNB->nbSymb--; delNotifiedFIFO_elt(req); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 476c9d07bf..a5f4a84a90 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -60,7 +60,6 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol) { @@ -96,7 +95,6 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int32_t *ul_ch_magb, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol) { @@ -152,11 +150,10 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int32_t *ul_ch_magb, - int32_t *ul_ch_magc, - int16_t *ulsch_llr, - uint32_t nb_rb, - uint32_t nb_re, - uint8_t symbol) + int32_t *ul_ch_magc, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol) { simde__m256i *rxF = (simde__m256i*)rxdataF_comp; simde__m256i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; @@ -199,7 +196,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, int32_t *ul_ch_magb, int32_t *ul_ch_magc, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol, uint8_t mod_order) @@ -215,7 +211,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, nr_ulsch_16qam_llr(rxdataF_comp, ul_ch_mag, ulsch_llr, - nb_rb, nb_re, symbol); break; @@ -224,7 +219,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, ul_ch_mag, ul_ch_magb, ulsch_llr, - nb_rb, nb_re, symbol); break; @@ -234,7 +228,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, ul_ch_magb, ul_ch_magc, ulsch_llr, - nb_rb, nb_re, symbol); break; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 6c4fdd4c05..f1c20ff2df 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -887,8 +887,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); start_meas(&gNB->rx_pusch_stats); - // if (gNB->use_pusch_tp) nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); - // else nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; pusch_vars->ulsch_power_tot = 0; From 62ad185df9f771918878a3a25f6265fbc667f163 Mon Sep 17 00:00:00 2001 From: Tsung-Yu Chan Date: Mon, 18 Sep 2023 16:10:28 +0200 Subject: [PATCH 14/43] fix / fix the length of ce estimation buffer --- openair1/PHY/INIT/nr_init.c | 4 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 14 +--- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 70 +++++-------------- 3 files changed, 22 insertions(+), 66 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 09898d383b..01e332ecf2 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -686,7 +686,9 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) int n_buf = Prx*max_ul_mimo_layers; int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB; - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); + int nb_re_pusch2 = nb_re_pusch; + if (nb_re_pusch & 7) + nb_re_pusch2 += 8 - (nb_re_pusch & 7); gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index ab25bd7744..2c7d7a7d3e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -131,30 +131,18 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t slot, unsigned char harq_pid); -void nr_ulsch_scale_channel(int32_t **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_ULSCH_t *ulsch_gNB, - uint8_t symbol, - uint8_t is_dmrs_symbol, - uint32_t len, - uint8_t nrOfLayers, - uint16_t nb_rb, - int shift_ch_ext); - /** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal @param ul_ch_estimates_ext Channel estimates in allocated RBs @param frame_parms Pointer to frame descriptor @param avg Pointer to average signal strength @param pilots_flag Flag to indicate pilots in symbol - @param nb_rb Number of allocated RBs */ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, int32_t *avg, uint8_t symbol, uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb); + uint8_t nrOfLayers); /*! \brief This function implements the idft transform precoding in PUSCH diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index d22ad70ee5..2dc8741227 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -382,7 +382,6 @@ static void nr_ulsch_extract_rbs (c16_t* const rxdataF, void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_ULSCH_t *ulsch_gNB, uint8_t symbol, uint8_t is_dmrs_symbol, uint32_t len, @@ -405,21 +404,12 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, simde__m128i ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 LOG_D(PHY, "Scaling PUSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n", symbol, ch_amp, is_dmrs_symbol, nb_rb, frame_parms->Ncp, symbol); - uint32_t nb_rb_0 = len / 12 + ((len % 12) ? 1 : 0); - int off = ((nb_rb & 1) == 1) ? 4 : 0; for (int aatx = 0; aatx < nrOfLayers; aatx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * (off + (nb_rb * NR_NB_SC_PER_RB))]; - for (int rb = 0; rb < nb_rb_0; rb++) { - ul_ch128[0] = simde_mm_mulhi_epi16(ul_ch128[0], ch_amp128); - ul_ch128[0] = simde_mm_slli_epi16(ul_ch128[0], b); - - ul_ch128[1] = simde_mm_mulhi_epi16(ul_ch128[1], ch_amp128); - ul_ch128[1] = simde_mm_slli_epi16(ul_ch128[1], b); - - ul_ch128[2] = simde_mm_mulhi_epi16(ul_ch128[2], ch_amp128); - ul_ch128[2] = simde_mm_slli_epi16(ul_ch128[2], b); - ul_ch128 += 3; + simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len]; + for (int i = 0; i < len >> 2; i++) { + ul_ch128[i] = simde_mm_mulhi_epi16(ul_ch128[i], ch_amp128); + ul_ch128[i] = simde_mm_slli_epi16(ul_ch128[i], b); } } } @@ -447,32 +437,22 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int32_t *avg, uint8_t symbol, uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb) + uint8_t nrOfLayers) { - short rb; - unsigned char aatx, aarx; simde__m128i *ul_ch128, avg128U; int16_t x = factor2(len); int16_t y = (len)>>x; - - uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); - int off = ((nb_rb&1) == 1)? 4:0; - - for (aatx = 0; aatx < nrOfLayers; aatx++) { - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + for (int aatx = 0; aatx < nrOfLayers; aatx++) { + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128U = simde_mm_setzero_si128(); - ul_ch128=(simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol * len]; - for (rb = 0; rb < nb_rb_0; rb++) { - avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[0], ul_ch128[0]), x)); - avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[1], ul_ch128[1]), x)); - avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[2], ul_ch128[2]), x)); - ul_ch128+=3; + for (int i = 0; i < len >> 2; i++) { + avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[i], ul_ch128[i]), x)); } avg[aatx*frame_parms->nb_antennas_rx+aarx] = (((int32_t*)&avg128U)[0] + @@ -486,21 +466,6 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, simde_m_empty(); } -static simde__m128i a_mult_conjb(__m128i a, __m128i b, unsigned char output_shift) -{ - simde__m128i mmtmpD0 = simde_mm_madd_epi16(b, a); - simde__m128i mmtmpD1 = simde_mm_shufflelo_epi16(b, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i *)&conjugate[0]); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, a); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); - simde__m128i mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); - simde__m128i mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - return _mm_packs_epi32(mmtmpD2, mmtmpD3); -} - - void nr_ulsch_channel_compensation(c16_t *rxFext, c16_t *chFext, c16_t *ul_ch_maga, @@ -1354,7 +1319,7 @@ static void inner_rx (PHY_VARS_gNB *gNB, int buffer_length = rel15_ul->rb_size * NR_NB_SC_PER_RB; if (buffer_length & 7) - buffer_length += (8 - buffer_length%8); + buffer_length += (8 - (buffer_length & 7)); c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32))); c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32))); @@ -1655,13 +1620,16 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, // extract the first dmrs for the channel level computation // extract the data in the OFDM frame, to the start of the array int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); + + if (nb_re_pusch & 7) + nb_re_pusch += 8 - (nb_re_pusch & 7); + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) nr_ulsch_extract_rbs(gNB->common_vars.rxdataF[aarx], (c16_t *)pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx], - (c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch2], - (c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][meas_symbol*nb_re_pusch2], + (c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch], + (c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][meas_symbol * nb_re_pusch], soffset + meas_symbol * frame_parms->ofdm_symbol_size, pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, aarx, @@ -1680,7 +1648,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, //---------------------------------------------------------- nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext, frame_parms, - &gNB->ulsch[ulsch_id], meas_symbol, (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, nb_re_pusch, @@ -1693,8 +1660,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, avg, meas_symbol, // index of the start symbol nb_re_pusch, // number of the re in pusch - rel15_ul->nrOfLayers, - rel15_ul->rb_size); + rel15_ul->nrOfLayers); for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) From 5231a3ab74dd5296249053367a72c7d40333e30a Mon Sep 17 00:00:00 2001 From: Tsung Yu Chan Date: Tue, 19 Sep 2023 12:33:09 +0200 Subject: [PATCH 15/43] fix / fix the transfrom precoding error when qpsk - avoid the nr_freq_equalization when qpsk - do the stop_meas when use the lepc offload --- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 15 ++++++++------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 2dc8741227..45070b47dd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1367,13 +1367,14 @@ static void inner_rx (PHY_VARS_gNB *gNB, output_shift); if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { - nr_freq_equalization(frame_parms, - &pusch_vars->rxdataF_comp[0][symbol * buffer_length], - (int *)rxF_ch_maga, - (int *)rxF_ch_magb, - symbol, - pusch_vars->ul_valid_re_per_slot[symbol], - rel15_ul->qam_mod_order); + if (rel15_ul->qam_mod_order > 2) + nr_freq_equalization(frame_parms, + &pusch_vars->rxdataF_comp[0][symbol * buffer_length], + (int *)rxF_ch_maga, + (int *)rxF_ch_magb, + symbol, + pusch_vars->ul_valid_re_per_slot[symbol], + rel15_ul->qam_mod_order); nr_idft(&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]); } if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index f1c20ff2df..f00ac5c2d4 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -950,8 +950,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) delNotifiedFIFO_elt(req); totalDecode--; } - stop_meas(&gNB->ulsch_decoding_stats); } + stop_meas(&gNB->ulsch_decoding_stats); for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; if (srs) { From 0263b4a807f24ce67ab4420534fd19c1621456dc Mon Sep 17 00:00:00 2001 From: Tsung Yu Chan Date: Tue, 19 Sep 2023 17:35:38 +0200 Subject: [PATCH 16/43] chore / remove the unused variable --- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 13 -- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 10 - .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 216 +++++++----------- openair1/PHY/defs_gNB.h | 5 - openair1/SIMULATION/NR_PHY/ulsim.c | 30 +-- 5 files changed, 93 insertions(+), 181 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 2c7d7a7d3e..2583996b95 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -131,19 +131,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t slot, unsigned char harq_pid); -/** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal - @param ul_ch_estimates_ext Channel estimates in allocated RBs - @param frame_parms Pointer to frame descriptor - @param avg Pointer to average signal strength - @param pilots_flag Flag to indicate pilots in symbol -*/ -void nr_ulsch_channel_level(int **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t symbol, - uint32_t len, - uint8_t nrOfLayers); - /*! \brief This function implements the idft transform precoding in PUSCH \param z Pointer to input in frequnecy domain, and it is also the output in time domain diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 69015660d8..99218749a4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -122,7 +122,6 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) static void nr_processULSegment(void *arg) { ldpcDecode_t *rdata = (ldpcDecode_t *)arg; - PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; int length_dec; @@ -156,8 +155,6 @@ static void nr_processULSegment(void *arg) t_nrLDPC_time_stats procTime = {0}; t_nrLDPC_time_stats *p_procTime = &procTime; - // start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// @@ -172,7 +169,6 @@ static void nr_processULSegment(void *arg) // for (int i =0; i<16; i++) // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset); - stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); ////////////////////////////////////////////////////////////////////////////////////////// @@ -182,7 +178,6 @@ static void nr_processULSegment(void *arg) ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// - // start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); if (nr_rate_matching_ldpc_rx(rdata->tbslbrm, p_decoderParms->BG, @@ -196,13 +191,10 @@ static void nr_processULSegment(void *arg) ulsch_harq->F, Kr - ulsch_harq->F - 2 * (p_decoderParms->Z)) == -1) { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); rdata->decodeIterations = max_ldpc_iterations + 1; return; - } else { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); } ulsch_harq->d_to_be_cleared[r] = false; @@ -221,7 +213,6 @@ static void nr_processULSegment(void *arg) length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; } - // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); // set first 2*Z_c bits to zeros memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t)); @@ -248,7 +239,6 @@ static void nr_processULSegment(void *arg) if (rdata->decodeIterations <= p_decoderParms->numMaxIter) memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); - //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); } int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 45070b47dd..22f3fd4a51 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -287,7 +287,6 @@ static void nr_ulsch_extract_rbs (c16_t* const rxdataF, nfapi_nr_pusch_pdu_t *pusch_pdu, NR_DL_FRAME_PARMS *frame_parms) { - uint8_t delta = 0; int start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size; @@ -380,14 +379,14 @@ static void nr_ulsch_extract_rbs (c16_t* const rxdataF, } } -void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t symbol, - uint8_t is_dmrs_symbol, - uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb, - int shift_ch_ext) +static void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + uint8_t is_dmrs_symbol, + uint32_t len, + uint8_t nrOfLayers, + unsigned short nb_rb, + int shift_ch_ext) { // Determine scaling amplitude based the symbol int b = 3; @@ -415,7 +414,7 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, } } -int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol) +static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol) { uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; if (dmrs_symbol_flag == 1) { @@ -431,13 +430,13 @@ int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15 } else return(rel15_ul->rb_size * NR_NB_SC_PER_RB); } -//compute average channel_level on each (TX,RX) antenna pair -void nr_ulsch_channel_level(int **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t symbol, - uint32_t len, - uint8_t nrOfLayers) +// compute average channel_level on each (TX,RX) antenna pair +static void nr_ulsch_channel_level(int **ul_ch_estimates_ext, + NR_DL_FRAME_PARMS *frame_parms, + int32_t *avg, + uint8_t symbol, + uint32_t len, + uint8_t nrOfLayers) { simde__m128i *ul_ch128, avg128U; @@ -466,18 +465,18 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, simde_m_empty(); } -void nr_ulsch_channel_compensation(c16_t *rxFext, - c16_t *chFext, - c16_t *ul_ch_maga, - c16_t *ul_ch_magb, - c16_t *ul_ch_magc, - int32_t **rxComp, - c16_t *rho, - NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t* rel15_ul, - uint32_t symbol, - uint32_t buffer_length, - uint32_t output_shift) +static void nr_ulsch_channel_compensation(c16_t *rxFext, + c16_t *chFext, + c16_t *ul_ch_maga, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, + int32_t **rxComp, + c16_t *rho, + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t* rel15_ul, + uint32_t symbol, + uint32_t buffer_length, + uint32_t output_shift) { int mod_order = rel15_ul->qam_mod_order; int nrOfLayers = rel15_ul->nrOfLayers; @@ -578,14 +577,14 @@ void nr_ulsch_channel_compensation(c16_t *rxFext, } // Zero Forcing Rx function: nr_det_HhH() -void nr_ulsch_det_HhH (int32_t *after_mf_00,//a - int32_t *after_mf_01,//b - int32_t *after_mf_10,//c - int32_t *after_mf_11,//d - int32_t *det_fin,//1/ad-bc - unsigned short nb_rb, - unsigned char symbol, - int32_t shift) +static void nr_ulsch_det_HhH (int32_t *after_mf_00,//a + int32_t *after_mf_01,//b + int32_t *after_mf_10,//c + int32_t *after_mf_11,//d + int32_t *det_fin,//1/ad-bc + unsigned short nb_rb, + unsigned char symbol, + int32_t shift) { int16_t nr_conjug2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ; unsigned short rb; @@ -640,53 +639,15 @@ void nr_ulsch_det_HhH (int32_t *after_mf_00,//a simde_m_empty(); } -/* Zero Forcing Rx function: nr_inv_comp_muli - * Complex number multi: z = x*y - * = (x_re*y_re - x_im*y_im) + j(x_im*y_re + x_re*y_im) - * */ -simde__m128i nr_ulsch_inv_comp_muli(simde__m128i input_x, - simde__m128i input_y) -{ - int16_t nr_conjug2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ; - - simde__m128i xy_re_128, xy_im_128; - simde__m128i output_z, tmp_z0, tmp_z1; - - // complex multiplication (x_re + jx_im)*(y_re + jy_im) = (x_re*y_re - x_im*y_im) + j(x_im*y_re + x_re*y_im) - - // the real part - xy_re_128 = simde_mm_sign_epi16(input_x,*(simde__m128i*)&nr_conjug2[0]); - xy_re_128 = simde_mm_madd_epi16(xy_re_128,input_y); //Re: (x_re*y_re - x_im*y_im) - - // the imag part - xy_im_128 = simde_mm_shufflelo_epi16(input_x, SIMDE_MM_SHUFFLE(2,3,0,1));//permutes IQs for the low 64 bits as [I_a0 Q_a1 I_a2 Q_a3]_64bits to [Q_a1 I_a0 Q_a3 I_a2]_64bits - xy_im_128 = simde_mm_shufflehi_epi16(xy_im_128, SIMDE_MM_SHUFFLE(2,3,0,1));//permutes IQs for the high 64 bits as [I_a0 Q_a1 I_a2 Q_a3]_64bits to [Q_a1 I_a0 Q_a3 I_a2]_64bits - xy_im_128 = simde_mm_madd_epi16(xy_im_128,input_y);//Im: (x_im*y_re + x_re*y_im) - - //convert back to Q15 before packing - xy_re_128 = simde_mm_srai_epi32(xy_re_128,4);//(2^15/64*2*16) - xy_im_128 = simde_mm_srai_epi32(xy_im_128,4); - - tmp_z0 = simde_mm_unpacklo_epi32(xy_re_128,xy_im_128); - //print_ints("unpack lo:",&tmp_z0[0]); - tmp_z1 = simde_mm_unpackhi_epi32(xy_re_128,xy_im_128); - //print_ints("unpack hi:",&tmp_z1[0]); - output_z = simde_mm_packs_epi32(tmp_z0,tmp_z1); - - simde_mm_empty(); - simde_m_empty(); - return(output_z); -} - /* Zero Forcing Rx function: nr_conjch0_mult_ch1() * * * */ -void nr_ulsch_conjch0_mult_ch1(int *ch0, - int *ch1, - int32_t *ch0conj_ch1, - unsigned short nb_rb, - unsigned char output_shift0) +static void nr_ulsch_conjch0_mult_ch1(int *ch0, + int *ch1, + int32_t *ch0conj_ch1, + unsigned short nb_rb, + unsigned char output_shift0) { //This function is used to compute multiplications in H_hermitian * H matrix short nr_conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; @@ -724,11 +685,12 @@ void nr_ulsch_conjch0_mult_ch1(int *ch0, simde_mm_empty(); simde_m_empty(); } -simde__m128i nr_ulsch_comp_muli_sum(simde__m128i input_x, - simde__m128i input_y, - simde__m128i input_w, - simde__m128i input_z, - simde__m128i det) + +static simde__m128i nr_ulsch_comp_muli_sum(simde__m128i input_x, + simde__m128i input_y, + simde__m128i input_w, + simde__m128i input_z, + simde__m128i det) { int16_t nr_conjug2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ; @@ -786,32 +748,33 @@ simde__m128i nr_ulsch_comp_muli_sum(simde__m128i input_x, simde_m_empty(); return(output); } + /* Zero Forcing Rx function: nr_construct_HhH_elements() * * * */ -void nr_ulsch_construct_HhH_elements(int *conjch00_ch00, - int *conjch01_ch01, - int *conjch11_ch11, - int *conjch10_ch10,// - int *conjch20_ch20, - int *conjch21_ch21, - int *conjch30_ch30, - int *conjch31_ch31, - int *conjch00_ch01,//00_01 - int *conjch01_ch00,//01_00 - int *conjch10_ch11,//10_11 - int *conjch11_ch10,//11_10 - int *conjch20_ch21, - int *conjch21_ch20, - int *conjch30_ch31, - int *conjch31_ch30, - int32_t *after_mf_00, - int32_t *after_mf_01, - int32_t *after_mf_10, - int32_t *after_mf_11, - unsigned short nb_rb, - unsigned char symbol) +static void nr_ulsch_construct_HhH_elements(int *conjch00_ch00, + int *conjch01_ch01, + int *conjch11_ch11, + int *conjch10_ch10,// + int *conjch20_ch20, + int *conjch21_ch21, + int *conjch30_ch30, + int *conjch31_ch31, + int *conjch00_ch01,//00_01 + int *conjch01_ch00,//01_00 + int *conjch10_ch11,//10_11 + int *conjch11_ch10,//11_10 + int *conjch20_ch21, + int *conjch21_ch20, + int *conjch30_ch31, + int *conjch31_ch30, + int32_t *after_mf_00, + int32_t *after_mf_01, + int32_t *after_mf_10, + int32_t *after_mf_11, + unsigned short nb_rb, + unsigned char symbol) { //This function is used to construct the (H_hermitian * H matrix) matrix elements unsigned short rb; @@ -903,23 +866,21 @@ void nr_ulsch_construct_HhH_elements(int *conjch00_ch00, simde_m_empty(); } -/* - * MMSE Rx function: nr_ulsch_mmse_2layers() - */ -uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, - int **rxdataF_comp, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int **ul_ch_estimates_ext, - unsigned short nb_rb, - unsigned char n_rx, - unsigned char mod_order, - int shift, - unsigned char symbol, - int length, - uint32_t noise_var, - uint32_t buffer_length) +// MMSE Rx function: nr_ulsch_mmse_2layers() +static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, + int **rxdataF_comp, + int **ul_ch_mag, + int **ul_ch_magb, + int **ul_ch_magc, + int **ul_ch_estimates_ext, + unsigned short nb_rb, + unsigned char n_rx, + unsigned char mod_order, + int shift, + unsigned char symbol, + int length, + uint32_t noise_var, + uint32_t buffer_length) { int *ch00, *ch01, *ch10, *ch11; int *ch20, *ch30, *ch21, *ch31; @@ -1432,7 +1393,7 @@ static void inner_rx (PHY_VARS_gNB *gNB, rel15_ul->qam_mod_order); } -void nr_pusch_symbol_processing(void *arg) +static void nr_pusch_symbol_processing(void *arg) { puschSymbolProc_t *rdata=(puschSymbolProc_t*)arg; @@ -1617,7 +1578,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, AssertFatal(nb_re_pusch>0 && meas_symbol>=0,"nb_re_pusch %d cannot be 0 or meas_symbol %d cannot be negative here\n",nb_re_pusch,meas_symbol); - start_meas(&gNB->ulsch_rbs_extraction_stats); // extract the first dmrs for the channel level computation // extract the data in the OFDM frame, to the start of the array int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; @@ -1638,8 +1598,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rel15_ul, frame_parms); - stop_meas(&gNB->ulsch_rbs_extraction_stats); - int avgs = 0; int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0; @@ -1723,7 +1681,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, } } // symbol loop - while (gNB->nbSymb > 0 && !(rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS)) { + while (gNB->nbSymb > 0) { notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool); gNB->nbSymb--; delNotifiedFIFO_elt(req); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index a28e4a30f4..83040cb0e0 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -736,12 +736,7 @@ typedef struct PHY_VARS_gNB_s { time_stats_t ulsch_rate_unmatching_stats; time_stats_t ulsch_ldpc_decoding_stats; time_stats_t ulsch_deinterleaving_stats; - time_stats_t ulsch_unscrambling_stats; time_stats_t ulsch_channel_estimation_stats; - time_stats_t ulsch_ptrs_processing_stats; - time_stats_t ulsch_channel_compensation_stats; - time_stats_t ulsch_rbs_extraction_stats; - time_stats_t ulsch_mrc_stats; time_stats_t ulsch_llr_stats; time_stats_t rx_srs_stats; time_stats_t generate_srs_stats; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 5c3abe09be..762487c759 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -721,7 +721,6 @@ int main(int argc, char *argv[]) NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; - // nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_process->ulsch_pdu; NR_Sched_Rsp_t *Sched_INFO = malloc(sizeof(*Sched_INFO)); memset((void*)Sched_INFO,0,sizeof(*Sched_INFO)); nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; @@ -932,14 +931,7 @@ int main(int argc, char *argv[]) reset_meas(&gNB->rx_pusch_init_stats); reset_meas(&gNB->rx_pusch_symbol_processing_stats); reset_meas(&gNB->ulsch_decoding_stats); - reset_meas(&gNB->ulsch_deinterleaving_stats); - reset_meas(&gNB->ulsch_rate_unmatching_stats); - reset_meas(&gNB->ulsch_ldpc_decoding_stats); - reset_meas(&gNB->ulsch_unscrambling_stats); reset_meas(&gNB->ulsch_channel_estimation_stats); - reset_meas(&gNB->ulsch_llr_stats); - reset_meas(&gNB->ulsch_channel_compensation_stats); - reset_meas(&gNB->ulsch_rbs_extraction_stats); reset_meas(&UE->ulsch_ldpc_encoding_stats); reset_meas(&UE->ulsch_rate_matching_stats); reset_meas(&UE->ulsch_interleaving_stats); @@ -1595,23 +1587,13 @@ int main(int argc, char *argv[]) if (print_perf==1) { printf("gNB RX\n"); - printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); - printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time"); - printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); - printStatIndent2(&gNB->rx_pusch_init_stats,"RX PUSCH Initialization time"); - printStatIndent2(&gNB->rx_pusch_symbol_processing_stats,"RX PUSCH Symbol Processing time"); - - // printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); - // printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); - // printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); - // printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); - // printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); - // printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); - + printDistribution(&gNB->phy_proc_rx,table_rx, "Total PHY proc rx"); + printStatIndent(&gNB->rx_pusch_stats, "RX PUSCH time"); + printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time"); + printStatIndent2(&gNB->rx_pusch_init_stats, "RX PUSCH Initialization time"); + printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time"); printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); - // printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); - // printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); - // printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); + printf("\nUE TX\n"); printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time"); printStatIndent2(&UE->ulsch_segmentation_stats,"ULSCH segmentation time"); From fc2432e93bc60addfdda96b9c7d0b2f0e39e45be Mon Sep 17 00:00:00 2001 From: Tsung Yu Chan Date: Mon, 25 Sep 2023 12:45:39 +0200 Subject: [PATCH 17/43] chore / simplify the code and add the comment - simplify the buffer alignment - add the comment for llr - clean unused variable --- openair1/PHY/INIT/nr_init.c | 4 +- .../PHY/NR_ESTIMATION/nr_freq_equalization.c | 11 ++--- openair1/PHY/NR_TRANSPORT/nr_scrambling.c | 17 ++++---- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 6 +-- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 42 +++++++++++-------- openair1/PHY/defs_gNB.h | 1 - 6 files changed, 38 insertions(+), 43 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 01e332ecf2..9cf5e26cc7 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -686,9 +686,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) int n_buf = Prx*max_ul_mimo_layers; int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB; - int nb_re_pusch2 = nb_re_pusch; - if (nb_re_pusch & 7) - nb_re_pusch2 += 8 - (nb_re_pusch & 7); + int nb_re_pusch2 = (nb_re_pusch + 7) & ~7; gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c index e73ac48fab..c593c04cc5 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c +++ b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c @@ -26,7 +26,7 @@ // Reference of openair1/PHY/LTE_ESTIMATION/freq_equalization.c // This is 4096/(1:4096) in simde__m128i format -simde__m128i nr_inv_ch[4096];/* = {0, 4096/1, 4096/2, 4096/3, 4096/4...}*/ +static simde__m128i nr_inv_ch[4096]; /* = {0, 4096/1, 4096/2, 4096/3, 4096/4...}*/ void nr_init_fde() { @@ -51,8 +51,7 @@ void nr_freq_equalization (NR_DL_FRAME_PARMS *frame_parms, AssertFatal(Msc_RS <= frame_parms->N_RB_UL*12, "Msc_RS %d >= %d\n", Msc_RS, frame_parms->N_RB_UL*12); - for (uint16_t re = 0; re < (Msc_RS >> 2); re++) - { + for (uint16_t re = 0; re < (Msc_RS >> 2); re++) { int16_t amp = (*((int16_t*)&ul_ch_mag128[re])); if (amp > 4095) @@ -62,12 +61,10 @@ void nr_freq_equalization (NR_DL_FRAME_PARMS *frame_parms, if (Qm == 4) ul_ch_mag128[re] = simde_mm_set1_epi16(324); // this is 512*2/sqrt(10) - else if (Qm == 6) - { + else if (Qm == 6) { ul_ch_mag128[re] = simde_mm_set1_epi16(316); // this is 512*4/sqrt(42) ul_ch_magb128[re] = simde_mm_set1_epi16(158); // this is 512*2/sqrt(42) - } - else if(Qm != 2) + } else if(Qm != 2) AssertFatal(1, "nr_freq_equalization(), Qm = %d, should be 2, 4 or 6. symbol=%d, Msc_RS=%d\n", Qm, symbol, Msc_RS); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c index fd0da127c8..b54a5c2c0c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c +++ b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c @@ -81,17 +81,16 @@ void nr_codeword_unscrambling_init(int16_t *s2, uint32_t size, uint8_t q, uint32 { uint32_t x1; uint32_t x2 = (n_RNTI << 15) + (q << 14) + Nid; - uint32_t s = 0; - - uint8_t *s8=(uint8_t *)&s; - s = lte_gold_generic(&x1, &x2, 1); simde__m128i *s128=(simde__m128i *)s2; - for (int i = 0, j = 0; i < ((size >> 5) + ((size & 0x1f) > 0 ? 1 : 0)); i++, j += 4) { - s128[j] = byte2m128i[s8[0]]; - s128[j+1] = byte2m128i[s8[1]]; - s128[j+2] = byte2m128i[s8[2]]; - s128[j+3] = byte2m128i[s8[3]]; + uint32_t s = lte_gold_generic(&x1, &x2, 1); + uint8_t *s8=(uint8_t *)&s; + + for (int i = 0; i < (size +31) >> 5; i++) { + *s128++ = byte2m128i[s8[0]]; + *s128++ = byte2m128i[s8[1]]; + *s128++ = byte2m128i[s8[2]]; + *s128++ = byte2m128i[s8[3]]; s = lte_gold_generic(&x1, &x2, 0); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 22f3fd4a51..18aea849f7 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1277,11 +1277,7 @@ static void inner_rx (PHY_VARS_gNB *gNB, int nb_layer = rel15_ul->nrOfLayers; int nb_rx_ant = frame_parms->nb_antennas_rx; int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - - int buffer_length = rel15_ul->rb_size * NR_NB_SC_PER_RB; - if (buffer_length & 7) - buffer_length += (8 - (buffer_length & 7)); - + int buffer_length = (rel15_ul->rb_size * NR_NB_SC_PER_RB + 7) & ~7; c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32))); c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32))); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index a5f4a84a90..1649f57878 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -65,25 +65,28 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, { simde__m256i *rxF_256 = (simde__m256i*)rxdataF_comp; simde__m256i *ch_mag = (simde__m256i*)ul_ch_mag; - simde__m64 *llr_64 = (simde__m64*)ulsch_llr; + int64_t *llr_64 = (int64_t*)ulsch_llr; simde__m256i xmm0, xmm1, xmm2; - for (int i = 0; i < ((nb_re>>3) + ((nb_re&7) ? 1 : 0)); i++) { - xmm0 = simde_mm256_abs_epi16(rxF_256[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + for (int i = 0; i < ((nb_re + 7) >> 3); i++) { + xmm0 = simde_mm256_abs_epi16(rxF_256[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| xmm0 = simde_mm256_subs_epi16(ch_mag[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmm1 = simde_mm256_unpacklo_epi32(rxF_256[i], xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs - xmm2 = simde_mm256_unpackhi_epi32(rxF_256[i], xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + xmm1 = simde_mm256_unpacklo_epi32(rxF_256[i], xmm0); + xmm2 = simde_mm256_unpackhi_epi32(rxF_256[i], xmm0); + + // xmm1 |1st 2ed 3rd 4th 9th 10th 13rd 14th| + // xmm2 |5th 6th 7th 8th 11st 12ed 15th 16th| - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 0); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 1); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 0); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 1); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 2); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm1, 3); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 2); - *llr_64++ = (simde__m64)simde_mm256_extract_epi64(xmm2, 3); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 0); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 1); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 0); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 1); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 2); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 3); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 2); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 3); } } @@ -106,13 +109,16 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, int32_t *llr_32 = (int32_t *)ulsch_llr; - for (int i = 0; i < ((nb_re>>3) + ((nb_re&7) ? 1 : 0)); i++) { + for (int i = 0; i < ((nb_re + 7) >> 3); i++) { xmm0 = rxF[i]; - xmm1 = simde_mm256_abs_epi16(xmm0); - xmm1 = simde_mm256_subs_epi16(ch_maga[i], xmm1); + xmm1 = simde_mm256_abs_epi16(xmm0); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm1 = simde_mm256_subs_epi16(ch_maga[i], xmm1); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm2 = simde_mm256_abs_epi16(xmm1); xmm2 = simde_mm256_subs_epi16(ch_magb[i], xmm2); - + // xmm0 |1st 4th 7th 10th 13th 16th 19th 22ed| + // xmm1 |2ed 5th 8th 11th 14th 17th 20th 23rd| + // xmm2 |3rd 6th 9th 12th 15th 18th 21st 24th| + *llr_32++ = simde_mm256_extract_epi32(xmm0,0); *llr_32++ = simde_mm256_extract_epi32(xmm1,0); *llr_32++ = simde_mm256_extract_epi32(xmm2,0); @@ -163,7 +169,7 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, simde__m256i* ch_magb = (simde__m256i*)ul_ch_magb; simde__m256i* ch_magc = (simde__m256i*)ul_ch_magc; - for (int i = 0; i < ((nb_re>>3) + ((nb_re&7) ? 1 : 0)); i++) { + for (int i = 0; i < ((nb_re + 7) >> 3); i++) { xmm0 = simde_mm256_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| xmm0 = simde_mm256_subs_epi16(ch_maga[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 // xmmtmpD2 contains 16 LLRs diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 83040cb0e0..0a070eb67b 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -733,7 +733,6 @@ typedef struct PHY_VARS_gNB_s { time_stats_t ul_indication_stats; time_stats_t schedule_response_stats; time_stats_t ulsch_decoding_stats; - time_stats_t ulsch_rate_unmatching_stats; time_stats_t ulsch_ldpc_decoding_stats; time_stats_t ulsch_deinterleaving_stats; time_stats_t ulsch_channel_estimation_stats; From fab0a3de3e7659e91f3b26f205c79e590a1be227 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 20 Sep 2023 09:44:09 +0200 Subject: [PATCH 18/43] increase CI time to 'deploy' --- ci-scripts/cls_physim1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_physim1.py b/ci-scripts/cls_physim1.py index b0c9012d7d..70f8729764 100644 --- a/ci-scripts/cls_physim1.py +++ b/ci-scripts/cls_physim1.py @@ -161,7 +161,7 @@ class PhySim: isRunning = False count = 0 # Check whether the containers are in Running state or not under 2 mins - while(count < 2 and isRunning == False): + while(count < 5 and isRunning == False): time.sleep(60) mySSH.command('oc get pods -o wide -l app=physim | tee -a cmake_targets/log/physim_pods_summary.txt', '\$', 30, resync=True) running_count = mySSH.getBefore().count('Running') From 91497ece942beecff7ddd44c89f895fd2b664535 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 25 Aug 2023 14:13:36 +0200 Subject: [PATCH 19/43] Reduce ITTI log verbosity Only print messages when queue grows by 10%, and add log if message queue size shrinks --- common/utils/ocp_itti/intertask_interface.cpp | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index b0d05c6aca..a68ed93cab 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -49,6 +49,7 @@ extern "C" { int nb_fd_epoll=0; int epoll_fd=-1; int sem_fd=-1; + size_t last_log_size = 0; } task_list_t; int timer_expired(int fd); @@ -131,11 +132,26 @@ extern "C" { int message_id = message->ittiMsgHeader.messageId; size_t s=t->message_queue.size(); - if ( s > t->admin.queue_size ) - LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s ); + if (s > t->last_log_size * 1.1) { + // to reduce the number of logs, we give a message each increase of 10% + if (s > t->admin.queue_size) + LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); - if ( s > 50 ) - LOG_I(ITTI,"Queue for %s task size: %ld (last message %s)\n",itti_get_task_name(destination_task_id), s+1,ITTI_MSG_NAME(message)); + if (s > t->admin.queue_size / 10) + LOG_I(ITTI, + "Queue for %s task size: %ld (last message %s)\n", + itti_get_task_name(destination_task_id), + s + 1, + ITTI_MSG_NAME(message)); + + t->last_log_size = s; + } + + if (t->last_log_size && t->last_log_size < t->admin.queue_size / 10) { + // Inform when the queue decreases + LOG_I(ITTI, "Queue for %s task size is back under 10%% of max size\n", itti_get_task_name(destination_task_id)); + t->last_log_size = 0; + } t->message_queue.insert(t->message_queue.begin(), message); eventfd_t sem_counter = 1; From d19302fb40fe3be22e574748b9acf50b9e6d2013 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 25 Sep 2023 15:21:21 +0200 Subject: [PATCH 20/43] revert last change --- common/utils/ocp_itti/intertask_interface.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index a68ed93cab..f6cd1f71ca 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -132,17 +132,17 @@ extern "C" { int message_id = message->ittiMsgHeader.messageId; size_t s=t->message_queue.size(); - if (s > t->last_log_size * 1.1) { // to reduce the number of logs, we give a message each increase of 10% - if (s > t->admin.queue_size) - LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); + if (s > t->last_log_size * 1.1 && s > t->admin.queue_size) { + LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); + t->last_log_size = s; - if (s > t->admin.queue_size / 10) - LOG_I(ITTI, - "Queue for %s task size: %ld (last message %s)\n", - itti_get_task_name(destination_task_id), - s + 1, - ITTI_MSG_NAME(message)); + } else if (s > t->last_log_size * 1.1 && s > t->admin.queue_size / 10) { + LOG_I(ITTI, + "Queue for %s task size: %ld (last message %s)\n", + itti_get_task_name(destination_task_id), + s + 1, + ITTI_MSG_NAME(message)); t->last_log_size = s; } From 7cb8988372bc985c271ee700bcdef75c143f40e2 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 30 Aug 2023 10:52:56 +0200 Subject: [PATCH 21/43] one-step-cleaning-gNB-ulsch-decoding --- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 528 +++++++++--------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 - 2 files changed, 261 insertions(+), 269 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 69015660d8..9d003b9ff5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -125,34 +125,20 @@ static void nr_processULSegment(void *arg) PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int length_dec; - int Kr; - int Kr_bytes; - int K_bits_F; - uint8_t crc_type; - int i; - int j; - int r = rdata->segment_r; - int A = rdata->A; - int E = rdata->E; - int Qm = rdata->Qm; - int rv_index = rdata->rv_index; - int r_offset = rdata->r_offset; - uint8_t kc = rdata->Kc; + const int Kr = ulsch_harq->K; + const int Kr_bytes = Kr >> 3; + const int K_bits_F = Kr - ulsch_harq->F; + const int r = rdata->segment_r; + const int A = rdata->A; + const int E = rdata->E; + const int Qm = rdata->Qm; + const int rv_index = rdata->rv_index; + const int r_offset = rdata->r_offset; + const uint8_t kc = rdata->Kc; short *ulsch_llr = rdata->ulsch_llr; - int max_ldpc_iterations = p_decoderParms->numMaxIter; + const int max_ldpc_iterations = p_decoderParms->numMaxIter; int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); - int16_t z[68 * 384 + 16] __attribute__((aligned(16))); - int8_t l[68 * 384 + 16] __attribute__((aligned(16))); - - simde__m128i *pv = (simde__m128i *)&z; - simde__m128i *pl = (simde__m128i *)&l; - - Kr = ulsch_harq->K; - Kr_bytes = Kr >> 3; - K_bits_F = Kr - ulsch_harq->F; - t_nrLDPC_time_stats procTime = {0}; t_nrLDPC_time_stats *p_procTime = &procTime; @@ -211,28 +197,33 @@ static void nr_processULSegment(void *arg) if (ulsch_harq->C == 1) { if (A > 3824) - crc_type = CRC24_A; + p_decoderParms->crc_type = CRC24_A; else - crc_type = CRC16; - - length_dec = ulsch_harq->B; + p_decoderParms->crc_type = CRC16; + p_decoderParms->block_length = ulsch_harq->B; } else { - crc_type = CRC24_B; - length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; + p_decoderParms->crc_type = CRC24_B; + p_decoderParms->block_length = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; } // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); // set first 2*Z_c bits to zeros - memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t)); + + int16_t z[68 * 384 + 16] __attribute__((aligned(16))); + + memset(z, 0, 2 * ulsch_harq->Z * sizeof(*z)); // set Filler bits - memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t)); + memset(z + K_bits_F, 127, ulsch_harq->F * sizeof(*z)); // Move coded bits before filler bits - memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t)); + memcpy(z + 2 * ulsch_harq->Z, ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(*z)); // skip filler bits - memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t)); + memcpy(z + Kr, ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(*z)); // Saturate coded bits before decoding into 8 bits values - for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { + simde__m128i *pv = (simde__m128i *)&z; + int8_t l[68 * 384 + 16] __attribute__((aligned(16))); + simde__m128i *pl = (simde__m128i *)&l; + for (int i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -242,73 +233,194 @@ static void nr_processULSegment(void *arg) ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - p_decoderParms->block_length = length_dec; - p_decoderParms->crc_type = crc_type; - rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)pl, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); + rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); if (rdata->decodeIterations <= p_decoderParms->numMaxIter) memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); } -int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, - uint8_t ULSCH_id, - short *ulsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *pusch_pdu, - uint32_t frame, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint32_t G) - { - if (!ulsch_llr) { - LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); - return -1; - } +int decode_offload(PHY_VARS_gNB *phy_vars_gNB, + uint8_t ULSCH_id, + short *ulsch_llr, + nfapi_nr_pusch_pdu_t *pusch_pdu, + t_nrLDPC_dec_params *decParams, + uint8_t harq_pid, + uint32_t G) +{ + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + int8_t llrProcBuf[22 * 384] __attribute__((aligned(32))); + int16_t z_ol[68 * 384] __attribute__((aligned(32))); + int8_t l_ol[68 * 384] __attribute__((aligned(32))); + int crc_type; + int length_dec; + uint8_t Qm = pusch_pdu->qam_mod_order; + uint8_t n_layers = pusch_pdu->nrOfLayers; + const int Kr = harq_process->K; + const int Kr_bytes = Kr >> 3; + const int kc = decParams->BG == 2 ? 52 : 68; + const uint32_t A = (harq_process->TBS) << 3; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1); + if (harq_process->C == 1) { + if (A > 3824) + crc_type = CRC24_A; + else + crc_type = CRC16; - NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; - NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; - - if (!harq_process) { - LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); - return -1; + length_dec = harq_process->B; + } else { + crc_type = CRC24_B; + length_dec = (harq_process->B + 24 * harq_process->C) / harq_process->C; } - uint8_t dtx_det = 0; + int decodeIterations = 2; + int dtx_det = 0; + int r_offset = 0, offset = 0; + for (int r = 0; r < harq_process->C; r++) { + int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); + memset(harq_process->c[r], 0, Kr_bytes); - int Kr; - int Kr_bytes; + decParams->R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, + E, + decParams->BG, + decParams->Z, + &harq_process->llrLen, + harq_process->round); + + if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) { + memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short)); + simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; + simde__m128i *pl_ol128 = (simde__m128i *)&l_ol; + for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { + pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); + } + + int ret = nrLDPC_decoder_offload(decParams, + harq_pid, + ULSCH_id, + r, + pusch_pdu->pusch_data.rv_index, + harq_process->F, + E, + Qm, + (int8_t *)&pl_ol128[0], + llrProcBuf, + 1); + if (ret < 0) { + LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); + + decodeIterations = ulsch->max_ldpc_iterations + 1; + return -1; + } + for (int m = 0; m < Kr >> 3; m++) { + harq_process->c[r][m] = (uint8_t)llrProcBuf[m]; + } + + if (check_crc((uint8_t *)llrProcBuf, length_dec, crc_type)) { + PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); + decodeIterations = 2; + } else { + PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); + decodeIterations = ulsch->max_ldpc_iterations + 1; + } + //} + + r_offset += E; + + /*for (int k=0;k<8;k++) + { + printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); + printf("llrprocbuf [%d] = %x adr %p\n", k, llrProcBuf[k], llrProcBuf+k); + } + */ + } else { + dtx_det = 0; + decodeIterations = ulsch->max_ldpc_iterations + 1; + } + bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations); + if (decodeSuccess) { + memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + harq_process->processedSegments++; + } else { + LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); + LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); + break; // don't even attempt to decode other segments + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0); + + if (harq_process->processedSegments == harq_process->C) { + LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS); + ulsch->active = false; + harq_process->round = 0; + + LOG_D(PHY, "ULSCH received ok \n"); + nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); + + } else { + LOG_D(PHY, + "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", + phy_vars_gNB->Mod_id, + ulsch->frame, + ulsch->slot, + harq_pid, + ulsch->active, + harq_process->round, + harq_process->TBS); + ulsch->handled = 1; + decodeIterations = ulsch->max_ldpc_iterations + 1; + LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); + nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); + } + ulsch->last_iteration_cnt = decodeIterations; + return 0; +} + +int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, + uint8_t ULSCH_id, + short *ulsch_llr, + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t *pusch_pdu, + uint32_t frame, + uint8_t nr_tti_rx, + uint8_t harq_pid, + uint32_t G) +{ + if (!ulsch_llr) { + LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); + return -1; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1); + + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + + if (!harq_process) { + LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); + return -1; + } + + // ------------------------------------------------------------------ + const uint16_t nb_rb = pusch_pdu->rb_size; + const uint8_t Qm = pusch_pdu->qam_mod_order; + const uint8_t mcs = pusch_pdu->mcs_index; + const uint8_t n_layers = pusch_pdu->nrOfLayers; + // ------------------------------------------------------------------ harq_process->processedSegments = 0; - - // ------------------------------------------------------------------ - uint16_t nb_rb = pusch_pdu->rb_size; - uint8_t Qm = pusch_pdu->qam_mod_order; - uint8_t mcs = pusch_pdu->mcs_index; - uint8_t n_layers = pusch_pdu->nrOfLayers; - // ------------------------------------------------------------------ - harq_process->TBS = pusch_pdu->pusch_data.tb_size; - dtx_det = 0; - - uint32_t A = (harq_process->TBS) << 3; - - // target_code_rate is in 0.1 units - float Coderate = (float) pusch_pdu->target_code_rate / 10240.0f; - - LOG_D(PHY,"ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", - harq_pid, ulsch->rnti, A, G, mcs, n_layers, nb_rb, Qm, Coderate, pusch_pdu->pusch_data.rv_index, harq_process->round, harq_process->harq_to_be_cleared); t_nrLDPC_dec_params decParams = {0}; decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; - int kc; - if (decParams.BG == 2) { - kc = 52; - } else { - kc = 68; - } + const uint32_t A = (harq_process->TBS) << 3; + if (A > 3824) + harq_process->B = A + 24; + else + harq_process->B = A + 16; NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); if (stats) { @@ -324,10 +436,21 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, stats->ulsch_stats.total_bytes_tx += harq_process->TBS; } } - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; + + LOG_D(PHY, + "ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", + harq_pid, + ulsch->rnti, + A, + G, + mcs, + n_layers, + nb_rb, + Qm, + pusch_pdu->target_code_rate / 10240.0f, + pusch_pdu->pusch_data.rv_index, + harq_process->round, + harq_process->harq_to_be_cleared); // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) nr_segmentation(NULL, @@ -339,204 +462,75 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, &harq_process->F, decParams.BG); - if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*n_layers) { + uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * n_layers; // number of segments to be allocated + if (harq_process->C > a_segments) { LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); return(-1); } - - -#ifdef DEBUG_ULSCH_DECODING - printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); - if (!frame%100) - printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); -#endif - decParams.Z = harq_process->Z; - - decParams.numMaxIter = ulsch->max_ldpc_iterations; - decParams.outMode = 0; - - uint32_t r_offset = 0; - - uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*n_layers; //number of segments to be allocated - if (nb_rb != 273) { a_segments = a_segments*nb_rb; a_segments = a_segments/273 +1; } - if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); return -1; } + #ifdef DEBUG_ULSCH_DECODING + printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); + if (!frame % 100) + printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); #endif + decParams.Z = harq_process->Z; + decParams.numMaxIter = ulsch->max_ldpc_iterations; + decParams.outMode = 0; + if (harq_process->harq_to_be_cleared) { for (int r = 0; r < harq_process->C; r++) harq_process->d_to_be_cleared[r] = true; harq_process->harq_to_be_cleared = false; } - Kr = harq_process->K; - Kr_bytes = Kr >> 3; + if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) + return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G); - uint32_t offset = 0; - if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) { - int8_t llrProcBuf[22 * 384]; - // if (dtx_det==0) { - int16_t z_ol[68 * 384]; - int8_t l_ol[68 * 384]; - int crc_type; - int length_dec; - - if (harq_process->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } else { - crc_type = CRC24_B; - length_dec = (harq_process->B + 24 * harq_process->C) / harq_process->C; - } - int decodeIterations = 2; - for (int r = 0; r < harq_process->C; r++) { - int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); - memset(harq_process->c[r], 0, Kr_bytes); - - decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round); - - if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) { - // if (dtx_det==0){ - memcpy((&z_ol[0]), ulsch_llr + r_offset, E * sizeof(short)); - simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; - simde__m128i *pl_ol128 = (simde__m128i *)&l_ol; - for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { - pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); - } - - int ret = nrLDPC_decoder_offload(&decParams, harq_pid, ULSCH_id, r, pusch_pdu->pusch_data.rv_index, harq_process->F, E, Qm, (int8_t *)&pl_ol128[0], llrProcBuf, 1); - if (ret < 0) { - LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); - - decodeIterations = ulsch->max_ldpc_iterations + 1; - return -1; - } - for (int m = 0; m < Kr >> 3; m++) { - harq_process->c[r][m] = (uint8_t)llrProcBuf[m]; - } - - if (check_crc((uint8_t *)llrProcBuf, length_dec, crc_type)) { - PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); - decodeIterations = 2; - } else { - PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); - decodeIterations = ulsch->max_ldpc_iterations + 1; - } - //} - - r_offset += E; - - /*for (int k=0;k<8;k++) - { - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - printf("llrprocbuf [%d] = %x adr %p\n", k, llrProcBuf[k], llrProcBuf+k); - } - */ - } else { - dtx_det = 0; - decodeIterations = ulsch->max_ldpc_iterations + 1; - } - bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations); - if (decodeSuccess) { - memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - harq_process->processedSegments++; - } else { - LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); - LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - break; // don't even attempt to decode other segments - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0); - - bool crc_valid = false; - if (harq_process->processedSegments == harq_process->C) { - // When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the - // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block - crc_valid = true; - if (harq_process->C > 1) { - // Check ULSCH transport block CRC - crc_type = CRC16; - if (A > 3824) { - crc_type = CRC24_A; - } - crc_valid = check_crc(harq_process->b, harq_process->B, crc_type); - } - } - - if (crc_valid) { - LOG_D(PHY, "[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB->Mod_id, ulsch->slot, harq_process->TBS); - ulsch->active = false; - harq_process->round = 0; - - LOG_D(PHY, "ULSCH received ok \n"); - nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); - - } else { - LOG_D(PHY, - "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", - phy_vars_gNB->Mod_id, - ulsch->frame, - ulsch->slot, - harq_pid, - ulsch->active, - harq_process->round, - harq_process->TBS); - ulsch->handled = 1; - decodeIterations = ulsch->max_ldpc_iterations + 1; - LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); - } - ulsch->last_iteration_cnt = decodeIterations; - } - - else { - dtx_det = 0; - set_abort(&harq_process->abort_decode, false); - for (int r = 0; r < harq_process->C; r++) { - int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); - union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}}; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment); - ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req); - decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round); - rdata->gNB = phy_vars_gNB; - rdata->ulsch_harq = harq_process; - rdata->decoderParms = decParams; - rdata->ulsch_llr = ulsch_llr; - rdata->Kc = kc; - rdata->harq_pid = harq_pid; - rdata->segment_r = r; - rdata->nbSegments = harq_process->C; - rdata->E = E; - rdata->A = A; - rdata->Qm = Qm; - rdata->r_offset = r_offset; - rdata->Kr_bytes = Kr_bytes; - rdata->rv_index = pusch_pdu->pusch_data.rv_index; - rdata->offset = offset; - rdata->ulsch = ulsch; - rdata->ulsch_id = ULSCH_id; - rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; - pushTpool(&phy_vars_gNB->threadPool, req); - LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); - r_offset += E; - offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - ////////////////////////////////////////////////////////////////////////////////////////// - } + uint32_t offset = 0, r_offset = 0; + set_abort(&harq_process->abort_decode, false); + for (int r = 0; r < harq_process->C; r++) { + int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); + union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}}; + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment); + ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req); + decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, + E, + decParams.BG, + decParams.Z, + &harq_process->llrLen, + harq_process->round); + rdata->gNB = phy_vars_gNB; + rdata->ulsch_harq = harq_process; + rdata->decoderParms = decParams; + rdata->ulsch_llr = ulsch_llr; + rdata->Kc = decParams.BG == 2 ? 52 : 68; + rdata->harq_pid = harq_pid; + rdata->segment_r = r; + rdata->nbSegments = harq_process->C; + rdata->E = E; + rdata->A = A; + rdata->Qm = Qm; + rdata->r_offset = r_offset; + rdata->Kr_bytes = harq_process->K >> 3; + rdata->rv_index = pusch_pdu->pusch_data.rv_index; + rdata->offset = offset; + rdata->ulsch = ulsch; + rdata->ulsch_id = ULSCH_id; + rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; + pushTpool(&phy_vars_gNB->threadPool, req); + LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); + r_offset += E; + offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); } return harq_process->C; } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 184e3ec63b..6ad14f1836 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -953,7 +953,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } - if (totalDecode > 0 && gNB->ldpc_offload_flag == 0) { while (totalDecode > 0) { notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); if (req == NULL) @@ -962,7 +961,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) delNotifiedFIFO_elt(req); totalDecode--; } - } for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; if (srs) { From 58f6cb2af9f2bbcc427e0061d4b17ef296961d4c Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Tue, 26 Sep 2023 20:26:06 +0100 Subject: [PATCH 22/43] Implement function for reversing bits with better performance --- common/utils/nr/nr_common.c | 40 +++++++++++++++++++++++++++++++ common/utils/nr/nr_common.h | 2 ++ openair1/PHY/CODING/coding_defs.h | 1 - 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 64f7a4772c..da4d4ccaa1 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -37,6 +37,46 @@ const char *duplex_mode[]={"FDD","TDD"}; +static const uint8_t bit_reverse_table_256[] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, + 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, + 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, + 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, + 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, + 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, + 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; + +// Reverse bits implementation based on http://graphics.stanford.edu/~seander/bithacks.html +uint64_t reverse_bits(uint64_t in, int n_bits) +{ + // Reverse n_bits in uint64_t variable, example: + // n_bits: 10 + // in: 10 0000 1111 + // return: 11 1100 0001 + + AssertFatal(n_bits <= 64, "Maximum bits to reverse is 64, impossible to reverse %d bits!\n", n_bits); + uint64_t rev_bits = 0; + uint8_t *p = (uint8_t *)∈ + uint8_t *q = (uint8_t *)&rev_bits; + int n_bytes = n_bits >> 3; + for (int n = 0; n < n_bytes; n++) { + q[n_bytes - 1 - n] = bit_reverse_table_256[p[n]]; + } + + // Reverse remaining bits (not aligned with 8-bit) + rev_bits = rev_bits << (n_bits % 8); + for (int i = n_bytes * 8; i < n_bits; i++) { + rev_bits |= ((in >> i) & 0x1) << (n_bits - i - 1); + } + return rev_bits; +} + static const int tables_5_3_2[5][12] = { {25, 52, 79, 106, 133, 160, 216, 270, -1, -1, -1, -1}, // 15 FR1 {11, 24, 38, 51, 65, 78, 106, 133, 162, 217, 245, 273}, // 30 FR1 diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index d9ac675493..ea879e93b4 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -90,6 +90,8 @@ static inline int get_num_dmrs(uint16_t dmrs_mask ) { return(num_dmrs); } +uint64_t reverse_bits(uint64_t in, int n_bits); + int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols); int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 0b4e12ad5d..69070c5544 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -456,7 +456,6 @@ int32_t rate_matching_lte(uint32_t N_coded, unsigned int crcbit (unsigned char * inputptr, int octetlen, unsigned int poly); -int16_t reverseBits(int32_t ,int32_t); void phy_viterbi_dot11(int8_t *,uint8_t *,uint16_t); int32_t nr_segmentation(unsigned char *input_buffer, From 2360925e29aa63b8e8e4a8b152c2630d25e95e9f Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Tue, 26 Sep 2023 20:27:00 +0100 Subject: [PATCH 23/43] Reverse bits in UCI message when using polar encoder/decoder --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 8 ++++++-- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 305a90d819..de3555bf29 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1693,12 +1693,16 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // run polar decoder on llrs decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size); - LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]); + // Decoder reversal + decodedPayload[0] = reverse_bits(decodedPayload[0], nb_bit); + if (decoderState>0) decoderState=1; corr_dB = dB_fixed64(corr); LOG_D(PHY,"metric %d dB\n",corr_dB); } + LOG_D(PHY, "UCI decoderState %d, payload[0] %llu\n", decoderState, (unsigned long long)decodedPayload[0]); + // estimate CQI for MAC (from antenna port 0 only) // TODO this computation is wrong -> to be ignored at MAC for now int SNRtimes10 = dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[0]], @@ -1761,7 +1765,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3); uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<bit_len_csi_part1 < 64 ? decodedPayload[0] >> pucch_pdu->bit_len_csi_part1 : 0; + decodedPayload[0] = pucch_pdu->bit_len_csi_part1 < 64 ? decodedPayload[0] >> bit_left : 0; } if (pucch_pdu->bit_len_csi_part2>0) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index d59da8be97..f5c4276562 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -644,7 +644,9 @@ static void nr_uci_encoding(uint64_t payload, b[7] = b[0]; AssertFatal(nrofPRB<=16,"Number of PRB >16\n"); } else if (A>=12) { - AssertFatal(A<65,"Polar encoding not supported yet for UCI with more than 64 bits\n"); + // Encoder reversal + payload = reverse_bits(payload, A); + polar_encoder_fast(&payload, b, 0,0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, A, From debd35a877a80db5c60e7dc0d1bcea1f5b422125 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Tue, 26 Sep 2023 20:45:14 +0100 Subject: [PATCH 24/43] Apply function with better performance to reverse bits for polar encoder/decoder in PBCH --- openair1/PHY/NR_TRANSPORT/nr_pbch.c | 4 +--- openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 6 +----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 692776b8cb..dd2493984e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -236,7 +236,6 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, uint16_t M; uint8_t nushift; uint32_t unscrambling_mask; - uint64_t a_reversed=0; LOG_D(PHY, "PBCH generation started\n"); ///Payload generation NR_gNB_PBCH m_pbch; @@ -298,8 +297,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, #endif // Encoder reversal - for (int i=0; ipbch_a_prime>>i)&1)<<(31-i); + uint64_t a_reversed = reverse_bits((uint64_t)pbch->pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS); /// CRC, coding and rate matching polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, 0, 0, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index ee79bdc47b..c7d10b69f4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -493,12 +493,8 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, } // printf("polar decoder output 0x%08x\n",pbch_a_prime); // Decoder reversal - uint32_t a_reversed=0; + pbch_a_prime = (uint32_t)reverse_bits(pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS); - for (int i=0; i>i)&1)<<(31-i); - - pbch_a_prime = a_reversed; //payload un-scrambling M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1); From cf36c6d893cde76dd2533bc050a805a8bd11b331 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 27 Sep 2023 15:59:08 +0100 Subject: [PATCH 25/43] Improvements to reduce ITTI log message volume when queues full --- common/utils/ocp_itti/intertask_interface.cpp | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index f6cd1f71ca..11a18794e6 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -132,22 +132,19 @@ extern "C" { int message_id = message->ittiMsgHeader.messageId; size_t s=t->message_queue.size(); - // to reduce the number of logs, we give a message each increase of 10% - if (s > t->last_log_size * 1.1 && s > t->admin.queue_size) { - LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); + // to reduce the number of logs, we give a message each increase of 10% + if ((s > t->last_log_size * 1.25) && (s > t->admin.queue_size / 10)) { + if (s > t->admin.queue_size) { + LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); + } else { + LOG_I(ITTI, + "Queue for %s task size: %ld (last message %s)\n", + itti_get_task_name(destination_task_id), + s + 1, + ITTI_MSG_NAME(message)); + } t->last_log_size = s; - - } else if (s > t->last_log_size * 1.1 && s > t->admin.queue_size / 10) { - LOG_I(ITTI, - "Queue for %s task size: %ld (last message %s)\n", - itti_get_task_name(destination_task_id), - s + 1, - ITTI_MSG_NAME(message)); - - t->last_log_size = s; - } - - if (t->last_log_size && t->last_log_size < t->admin.queue_size / 10) { + } else if (t->last_log_size && s < t->admin.queue_size / 10) { // Inform when the queue decreases LOG_I(ITTI, "Queue for %s task size is back under 10%% of max size\n", itti_get_task_name(destination_task_id)); t->last_log_size = 0; From dbdfe06d1e9434af687be0583ef178c3c9ba9813 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 27 Sep 2023 16:01:26 +0100 Subject: [PATCH 26/43] Fix comment from 10% to 25% --- common/utils/ocp_itti/intertask_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 11a18794e6..941e4de6ef 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -132,7 +132,7 @@ extern "C" { int message_id = message->ittiMsgHeader.messageId; size_t s=t->message_queue.size(); - // to reduce the number of logs, we give a message each increase of 10% + // to reduce the number of logs, we give a message each increase of 25% if ((s > t->last_log_size * 1.25) && (s > t->admin.queue_size / 10)) { if (s > t->admin.queue_size) { LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); From 8e59ef77db4f9398e9ba87dd8dba051792a0eb74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20da=20Silva?= Date: Mon, 13 Feb 2023 10:42:40 +0000 Subject: [PATCH 27/43] Fix Packing and Unpacking procedures for FAPI P7 messages Creation and usage of packing/unpacking functions for DCI payload Update Proxy commit id for CI Apply formatting on changed functions and fix pull/push return value checking --- .../xml_files/container_4g_l2sim_proxy.xml | 2 +- .../xml_files/container_l2sim_proxy.xml | 2 +- nfapi/oai_integration/nfapi_vnf.c | 1 + nfapi/open-nFAPI/nfapi/inc/nfapi.h | 3 + .../nfapi/public_inc/nfapi_nr_interface_scf.h | 2 + nfapi/open-nFAPI/nfapi/src/nfapi.c | 38 + nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 2598 ++++++++++------- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 15 +- 8 files changed, 1515 insertions(+), 1146 deletions(-) diff --git a/ci-scripts/xml_files/container_4g_l2sim_proxy.xml b/ci-scripts/xml_files/container_4g_l2sim_proxy.xml index 4c8f9ae019..795bce6bef 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_proxy.xml @@ -36,7 +36,7 @@ 1 1 True - f390610304baf6b66e4ec8cc00bf91398a651172 + b64d9bce986b38ca59e8582864ade3fcdd05c0dc diff --git a/ci-scripts/xml_files/container_l2sim_proxy.xml b/ci-scripts/xml_files/container_l2sim_proxy.xml index 8a8dbd05c2..81ee7c1bfa 100644 --- a/ci-scripts/xml_files/container_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_l2sim_proxy.xml @@ -36,7 +36,7 @@ 1 1 True - f390610304baf6b66e4ec8cc00bf91398a651172 + b64d9bce986b38ca59e8582864ade3fcdd05c0dc diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 97f73ef880..67f6c346c7 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1070,6 +1070,7 @@ int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { rx_ind->pdu_list[j].rnti = ind->pdu_list[j].rnti; rx_ind->pdu_list[j].timing_advance = ind->pdu_list[j].timing_advance; rx_ind->pdu_list[j].ul_cqi = ind->pdu_list[j].ul_cqi; + rx_ind->pdu_list[j].rssi = ind->pdu_list[j].rssi; } if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { diff --git a/nfapi/open-nFAPI/nfapi/inc/nfapi.h b/nfapi/open-nFAPI/nfapi/inc/nfapi.h index e1a0ec4f4e..dc2d3d3ec0 100644 --- a/nfapi/open-nFAPI/nfapi/inc/nfapi.h +++ b/nfapi/open-nFAPI/nfapi/inc/nfapi.h @@ -77,6 +77,9 @@ uint8_t unpackarray(uint8_t **ppReadPackedMsg, uint8_t *end, unpack_array_elem_fn fn); +uint32_t pack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **out, uint8_t *end); +uint32_t unpack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **in, uint8_t *end); + uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end); uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index a9338cf3ca..21c9558653 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -932,6 +932,8 @@ typedef struct typedef struct { + uint16_t bwp_size; // Needed for SCF222 10.02 + uint16_t bwp_start; // Needed for SCF222 10.02 uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4 uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274 diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index ef80c86849..62d79bb511 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -544,6 +545,43 @@ uint8_t unpackarray(uint8_t **ppReadPackedMsg, void *array, uint16_t array_eleme return 1; } +uint32_t pack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **out, uint8_t *end) +{ + // Helper vars for DCI Payload + uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN]; + uint8_t dci_byte_len = (payloadSizeBits + 7) / 8; + // Align the dci payload bits to the left on the payload buffer + uint64_t *dci_pdu = (uint64_t *)payload; + if (payloadSizeBits % 8 != 0) { + uint8_t rotation_bits = 8 - (payloadSizeBits % 8); + *dci_pdu = (*dci_pdu << rotation_bits); + } + // Invert the byte order of the DCI Payload + for (int j = 0; j < dci_byte_len; j++) { + dci_bytes_inverted[j] = payload[(dci_byte_len - 1) - j]; + } + return pusharray8(dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, out, end); +} + +uint32_t unpack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **in, uint8_t *end) +{ + // Pull the inverted DCI and invert it back + // Helper vars for DCI Payload + uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN]; + uint8_t dci_byte_len = (payloadSizeBits + 7) / 8; + // Get DCI array inverted + uint32_t pullresult = pullarray8(in, dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, end); + uint64_t *dci_pdu = (uint64_t *)payload; + // Reversing the byte order of the inverted DCI payload + for (uint16_t j = 0; j < dci_byte_len; j++) { + payload[j] = dci_bytes_inverted[(dci_byte_len - 1) - j]; + } + if (payloadSizeBits % 8 != 0) { + uint8_t rotation_bits = 8 - (payloadSizeBits % 8); + *dci_pdu = (*dci_pdu >> rotation_bits); + } + return pullresult; +} uint32_t pack_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { if(ve != 0 && config != 0) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index f5a05d0d71..8f7a7c2804 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -196,124 +196,176 @@ static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t *value, uint8_t **ppW return 1; } - -static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; - return( - push8(value->subcarrier_spacing, ppWritePackedMsg, end) && - push8(value->cyclic_prefix, ppWritePackedMsg, end) && - push16(value->start_rb, ppWritePackedMsg, end) && - push16(value->nr_of_rbs, ppWritePackedMsg, end) && - push8(value->csi_type, ppWritePackedMsg, end) && - push8(value->row, ppWritePackedMsg, end) && - push16(value->freq_domain, ppWritePackedMsg, end) && - push8(value->symb_l0, ppWritePackedMsg, end) && - push8(value->symb_l1, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - push8(value->freq_density, ppWritePackedMsg, end) && - push16(value->scramb_id, ppWritePackedMsg, end) && - push8(value->power_control_offset, ppWritePackedMsg, end) && - push8(value->power_control_offset_ss, ppWritePackedMsg, end) - ); + return (push16(value->bwp_size, ppWritePackedMsg, end) && push16(value->bwp_start, ppWritePackedMsg, end) + && push8(value->subcarrier_spacing, ppWritePackedMsg, end) && push8(value->cyclic_prefix, ppWritePackedMsg, end) + && push16(value->start_rb, ppWritePackedMsg, end) && push16(value->nr_of_rbs, ppWritePackedMsg, end) + && push8(value->csi_type, ppWritePackedMsg, end) && push8(value->row, ppWritePackedMsg, end) + && push16(value->freq_domain, ppWritePackedMsg, end) && push8(value->symb_l0, ppWritePackedMsg, end) + && push8(value->symb_l1, ppWritePackedMsg, end) && push8(value->cdm_type, ppWritePackedMsg, end) + && push8(value->freq_density, ppWritePackedMsg, end) && push16(value->scramb_id, ppWritePackedMsg, end) + && push8(value->power_control_offset, ppWritePackedMsg, end) + && push8(value->power_control_offset_ss, ppWritePackedMsg, end) && + // TODO Add Precoding and Beamforming, hardcoded for now + push16(0, ppWritePackedMsg, end) && push16(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end)); } +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; -static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + if (!(push16(value->BWPSize, ppWritePackedMsg, end) && push16(value->BWPStart, ppWritePackedMsg, end) + && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && push8(value->CyclicPrefix, ppWritePackedMsg, end) + && push8(value->StartSymbolIndex, ppWritePackedMsg, end) && push8(value->DurationSymbols, ppWritePackedMsg, end) + && pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) + && push8(value->CceRegMappingType, ppWritePackedMsg, end) && push8(value->RegBundleSize, ppWritePackedMsg, end) + && push8(value->InterleaverSize, ppWritePackedMsg, end) && push8(value->CoreSetType, ppWritePackedMsg, end) + && push16(value->ShiftIndex, ppWritePackedMsg, end) && push8(value->precoderGranularity, ppWritePackedMsg, end) + && push16(value->numDlDci, ppWritePackedMsg, end))) { + return 0; + } - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - return 0; - } - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->CceRegMappingType, ppWritePackedMsg, end) && - push8(value->RegBundleSize, ppWritePackedMsg, end) && - push8(value->InterleaverSize, ppWritePackedMsg, end) && - push8(value->CoreSetType, ppWritePackedMsg, end) && - push16(value->ShiftIndex, ppWritePackedMsg, end) && - push8(value->precoderGranularity, ppWritePackedMsg, end) && - push16(value->numDlDci, ppWritePackedMsg, end)); + for (uint16_t i = 0; i < value->numDlDci; ++i) { + if (!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) + && push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and beamforming + // TODO get these values from elsewhere and delete the hardcoded ones + value->dci_pdu[i].precodingAndBeamforming.num_prgs = 0; + value->dci_pdu[i].precodingAndBeamforming.prg_size = 0; // 1 PRG of max size for analogue beamforming + value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces = 0; + value->dci_pdu[i].precodingAndBeamforming.prgs_list[0].pm_idx = 0; + value->dci_pdu[i].precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; + if (!(push16(value->dci_pdu[i].precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->dci_pdu[i].precodingAndBeamforming.prg_size, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < value->dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!push16(value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int digInt = 0; digInt < value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; digInt++) { + if (!push16(value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, + ppWritePackedMsg, + end)) { + return 0; + } + } + } + // TX Power info + if (!(push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + // DCI Payload fields + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + // Pack DCI Payload + pack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) { + return 0; + } + } + return 1; } - -static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->pduBitmap, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->pduIndex, ppWritePackedMsg, end) && - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->NrOfCodewords, ppWritePackedMsg, end) && - pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && - pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && - push16(value->dataScramblingId, ppWritePackedMsg, end) && - push8(value->nrOfLayers, ppWritePackedMsg, end) && - push8(value->transmissionScheme, ppWritePackedMsg, end) && - push8(value->refPoint, ppWritePackedMsg, end) && - push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && - push8(value->dmrsConfigType, ppWritePackedMsg, end) && - push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && - push8(value->SCID, ppWritePackedMsg, end) && - push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && - push16(value->dmrsPorts, ppWritePackedMsg, end) && - push8(value->resourceAlloc, ppWritePackedMsg, end) && - push16(value->rbStart, ppWritePackedMsg, end) && - push16(value->rbSize, ppWritePackedMsg, end) && - push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->NrOfSymbols, ppWritePackedMsg, end) && - push8(value->PTRSPortIndex, ppWritePackedMsg, end) && - push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && - push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && - push8(value->PTRSReOffset, ppWritePackedMsg, end) - ); + + if (!(push16(value->pduBitmap, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push16(value->pduIndex, ppWritePackedMsg, end) && push16(value->BWPSize, ppWritePackedMsg, end) + && push16(value->BWPStart, ppWritePackedMsg, end) && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) + && push8(value->CyclicPrefix, ppWritePackedMsg, end) && push8(value->NrOfCodewords, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->NrOfCodewords; ++i) { + if (!(push16(value->targetCodeRate[i], ppWritePackedMsg, end) && push8(value->qamModOrder[i], ppWritePackedMsg, end) + && push8(value->mcsIndex[i], ppWritePackedMsg, end) && push8(value->mcsTable[i], ppWritePackedMsg, end) + && push8(value->rvIndex[i], ppWritePackedMsg, end) && push32(value->TBSize[i], ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push16(value->dataScramblingId, ppWritePackedMsg, end) && push8(value->nrOfLayers, ppWritePackedMsg, end) + && push8(value->transmissionScheme, ppWritePackedMsg, end) && push8(value->refPoint, ppWritePackedMsg, end) + && push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && push8(value->dmrsConfigType, ppWritePackedMsg, end) + && push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && push8(value->SCID, ppWritePackedMsg, end) + && push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && push16(value->dmrsPorts, ppWritePackedMsg, end) + && push8(value->resourceAlloc, ppWritePackedMsg, end) && (int)pusharray8(value->rbBitmap, 36, 36, ppWritePackedMsg, end) + && push16(value->rbStart, ppWritePackedMsg, end) && push16(value->rbSize, ppWritePackedMsg, end) + && push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && push8(value->StartSymbolIndex, ppWritePackedMsg, end) + && push8(value->NrOfSymbols, ppWritePackedMsg, end))) { + return 0; + } + + // Check pduBitMap bit 1 to add or not PTRS parameters + if (value->pduBitmap & 0b1) { + if (!(push8(value->PTRSPortIndex, ppWritePackedMsg, end) && push8(value->PTRSTimeDensity, ppWritePackedMsg, end) + && push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && push8(value->PTRSReOffset, ppWritePackedMsg, end) + && push8(value->nEpreRatioOfPDSCHToPTRS, ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push16(value->precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->precodingAndBeamforming.prg_size, ppWritePackedMsg, end) + && push8(value->precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->precodingAndBeamforming.num_prgs; ++i) { + if (!push16(value->precodingAndBeamforming.prgs_list[i].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int k = 0; k < value->precodingAndBeamforming.dig_bf_interfaces; ++k) { + if (!push16(value->precodingAndBeamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + // TODO Add TX power info + // Hardcoded values that represent 0db + if (!(push8(8, ppWritePackedMsg, end) && // powerControlOffset + push8(1, ppWritePackedMsg, end))) { // powerControlOffsetSS + return 0; + } + // TODO Add CBG Fields + return 1; } +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing ssb. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; -static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing ssb. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - push16(value->PhysCellId, ppWritePackedMsg, end) && - push8(value->BetaPss, ppWritePackedMsg, end) && - push8(value->SsbBlockIndex, ppWritePackedMsg, end) && - push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && - push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && - push8(value->bchPayloadFlag, ppWritePackedMsg, end) && - push32(value->bchPayload, ppWritePackedMsg, end) && - push8(value->ssbRsrp, ppWritePackedMsg, end) - // TODO: pack precoding_and_beamforming too - ); - + if (!(push16(value->PhysCellId, ppWritePackedMsg, end) && push8(value->BetaPss, ppWritePackedMsg, end) + && push8(value->SsbBlockIndex, ppWritePackedMsg, end) && push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) + && push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && push8(value->bchPayloadFlag, ppWritePackedMsg, end) + && push8((value->bchPayload >> 16) & 0xff, ppWritePackedMsg, end) + && push8((value->bchPayload >> 8) & 0xff, ppWritePackedMsg, end) && push8(value->bchPayload & 0xff, ppWritePackedMsg, end) + && push8(0, ppWritePackedMsg, end) && + // TODO add Tx Power Info + push8(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end) + && push16(value->precoding_and_beamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->precoding_and_beamforming.prg_size, ppWritePackedMsg, end) + && push8(value->precoding_and_beamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->precoding_and_beamforming.num_prgs; ++i) { + if (!push16(value->precoding_and_beamforming.prgs_list[i].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int k = 0; k < value->precoding_and_beamforming.dig_bf_interfaces; ++k) { + if (!push16(value->precoding_and_beamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + return 1; } - static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_dl_config_dci_dl_pdu_rel13_t *value = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && @@ -594,47 +646,47 @@ static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppWrit push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); } - -static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)tlv; - - if(!(push32(value->PDUSize, ppWritePackedMsg, end) && - push16(value->PDUType, ppWritePackedMsg, end) )) + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->PDUType, ppWritePackedMsg, end)) + return 0; + uint8_t *pPackedLengthField = *ppWritePackedMsg; + if (!push16(value->PDUSize, ppWritePackedMsg, end)) return 0; // first match the pdu type, then call the respective function - switch(value->PDUType) { + switch (value->PDUType) { case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { - if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { - if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { - if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType); + } break; } - - return 1; + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->PDUSize = packedMsgLen; + return push16(value->PDUSize, &pPackedLengthField, end); } static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { @@ -777,42 +829,34 @@ static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePac return 1; } - -static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && - pusharray8(pNfapiMsg->dl_tti_request_body.nUe, 256, pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push8(pNfapiMsg->dl_tti_request_body.nPDUs, ppWritePackedMsg, end) + && push8(pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { + if (!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pusharrays32(arr, 12, pNfapiMsg->dl_tti_request_body.nUe[i], ppWritePackedMsg, end))) - return 0; - } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { + if (!push8(pNfapiMsg->dl_tti_request_body.nUe[i], ppWritePackedMsg, end)) + return 0; + for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { + if (!(push32(pNfapiMsg->dl_tti_request_body.PduIdx[i][j], ppWritePackedMsg, end))) { + return 0; + } + } + return 0; + } - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) - return 0; - } - -return 1; + return 1; } - - static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -882,148 +926,178 @@ static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppW //Pack fns for ul_tti PDUS - -static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - return( - push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && - push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && - push8(prach_pdu->prach_format, ppWritePackedMsg, end) && - push8(prach_pdu->num_ra, ppWritePackedMsg, end) && - push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && - push16(prach_pdu->num_cs, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); -} - -static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - return( - push16(pucch_pdu->rnti, ppWritePackedMsg, end) && - push32(pucch_pdu->handle, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(pucch_pdu->format_type, ppWritePackedMsg, end) && - push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && - push8(pucch_pdu->pi_2bpsk, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && - push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && - push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && - push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && - push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && - push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && - push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && - push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - if (!( - push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && - push16(pusch_pdu->rnti, ppWritePackedMsg, end) && - push32(pusch_pdu->handle, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && - push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && - push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && - push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && - push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->scid, ppWritePackedMsg, end) && - push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && - push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && - push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && - push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && - push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && - push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )) +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) + && push8(prach_pdu->prach_format, ppWritePackedMsg, end) && push8(prach_pdu->num_ra, ppWritePackedMsg, end) + && push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && push16(prach_pdu->num_cs, ppWritePackedMsg, end))) { return 0; - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map) { - case PUSCH_PDU_BITMAP_PUSCH_DATA: { - // pack optional TLVs - return( - push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && - push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && - pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: { - return( - push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: { - return( - push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: { - return( - push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && - push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) - ); - } - break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } } + // TODO: put these hardoded values elsewhere + // Beamforming + prach_pdu->beamforming.num_prgs = 0; + prach_pdu->beamforming.prg_size = 0; + prach_pdu->beamforming.dig_bf_interface = 0; + + if (prach_pdu->beamforming.prgs_list == NULL) { + prach_pdu->beamforming.prgs_list = calloc(prach_pdu->beamforming.num_prgs, sizeof(*prach_pdu->beamforming.prgs_list)); + } + if (prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list == NULL) { + prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list = + calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list)); + } + prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; + + // Pack RX Beamforming PDU + if (!(push16(prach_pdu->beamforming.num_prgs, ppWritePackedMsg, end) + && push16(prach_pdu->beamforming.prg_size, ppWritePackedMsg, end) + && push8(prach_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) + return 0; + + for (int prg = 0; prg < prach_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < prach_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!push16(prach_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) + return 0; + } + } + return 1; +} + +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(pucch_pdu->rnti, ppWritePackedMsg, end) && push32(pucch_pdu->handle, ppWritePackedMsg, end) + && push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) + && push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) + && push8(pucch_pdu->format_type, ppWritePackedMsg, end) && push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) + && push8(pucch_pdu->pi_2bpsk, ppWritePackedMsg, end) && push16(pucch_pdu->prb_start, ppWritePackedMsg, end) + && push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) + && push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) + && push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) + && push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) + && push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) + && push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) + && push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) + && push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) + && push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // Pack RX Beamforming PDU + && push16(pucch_pdu->beamforming.num_prgs, ppWritePackedMsg, end) + && push16(pucch_pdu->beamforming.prg_size, ppWritePackedMsg, end) + && push8(pucch_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) { + return 0; + } + + for (int prg = 0; prg < pucch_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < pucch_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!push16(pucch_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) + return 0; + } + } + return 1; +} + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && push16(pusch_pdu->rnti, ppWritePackedMsg, end) + && push32(pusch_pdu->handle, ppWritePackedMsg, end) && push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) + && push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) + && push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) + && push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) + && push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) + && push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) + && push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) + && push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_identity, ppWritePackedMsg, end) && push8(pusch_pdu->scid, ppWritePackedMsg, end) + && push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) + && push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) + && pusharray8(pusch_pdu->rb_bitmap, 36, 36, ppWritePackedMsg, end) && push16(pusch_pdu->rb_start, ppWritePackedMsg, end) + && push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) + && push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) + && push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) + && push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) + && push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) { + return 0; + } + // Pack Optional Data only included if indicated in pduBitmap + switch (pusch_pdu->pdu_bit_map) { + case PUSCH_PDU_BITMAP_PUSCH_DATA: { + // pack optional TLVs + if (!(push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_data.new_data_indicator, ppWritePackedMsg, end) + && push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) + && pusharray8(pusch_pdu->pusch_data.cb_present_and_position, + (pusch_pdu->pusch_data.num_cb + 7) / 8, + (pusch_pdu->pusch_data.num_cb + 7) / 8, + ppWritePackedMsg, + end))) { + return 0; + } + } break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: { + if (!(push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end))) { + return 0; + } + } break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: { + if (!push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end)) { + return 0; + } + for (int i = 0; i < pusch_pdu->pusch_ptrs.num_ptrs_ports; ++i) { + if (!(push16(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_port_index, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_dmrs_port, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_re_offset, ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end))) { + return 0; + } + } break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: { + if (!(push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) + && push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) + && push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) + && push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end))) { + return 0; + } + } break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map); + } + } + // Pack RX Beamforming PDU + if (!(push16(pusch_pdu->beamforming.num_prgs, ppWritePackedMsg, end) + && push16(pusch_pdu->beamforming.prg_size, ppWritePackedMsg, end) + && push8(pusch_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < pusch_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < pusch_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!push16(pusch_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } return 1; } @@ -1346,48 +1420,50 @@ static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t * push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); } - - -static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_ul_tti_request_number_of_pdus_t *value = (nfapi_nr_ul_tti_request_number_of_pdus_t *)tlv; - - if(!(push16(value->pdu_size, ppWritePackedMsg, end) && - push16(value->pdu_type, ppWritePackedMsg, end) )) + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->pdu_type, ppWritePackedMsg, end)) { return 0; + } + uint8_t *pPackedLengthField = *ppWritePackedMsg; - // first match the pdu type, then call the respective function - switch(value->pdu_type) { + if (!push16(value->pdu_size, ppWritePackedMsg, end)) + return 0; + // pack PDUs + // first match the pdu type, then call the respective function + switch (value->pdu_type) { case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { - if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { - if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { - if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { - if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); - } - break; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type); + } break; } - return 1; + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->pdu_size = packedMsgLen; + return push16(value->pdu_size, &pPackedLengthField, end); } static uint8_t pack_ul_tti_groups_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { @@ -1577,9 +1653,23 @@ static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePac return 1; } - -static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + pNfapiMsg->n_ulcch = 0; + pNfapiMsg->n_ulsch = 0; + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + switch ((&pNfapiMsg->pdus_list[i])->pdu_type) { + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + pNfapiMsg->n_ulcch++; + } break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + pNfapiMsg->n_ulsch++; + } break; + default: + break; + } + } if (!push16(pNfapiMsg->SFN, ppWritePackedMsg, end)) return 0; @@ -1587,29 +1677,28 @@ static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ return 0; if (!push8(pNfapiMsg->n_pdus, ppWritePackedMsg, end)) return 0; - if (!push8(pNfapiMsg->n_group, ppWritePackedMsg, end)) - return 0; if (!push8(pNfapiMsg->rach_present, ppWritePackedMsg, end)) return 0; if (!push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end)) return 0; if (!push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end)) return 0; + if (!push8(pNfapiMsg->n_group, ppWritePackedMsg, end)) + return 0; - for(int i=0; in_pdus; i++) { - if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + if (!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) return 0; } - for(int i=0; in_group; i++) { - if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + for (int i = 0; i < pNfapiMsg->n_group; i++) { + if (!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) return 0; } return 1; } - static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -1810,45 +1899,87 @@ static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePacke return 1; } -static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)tlv; + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->PDUType, ppWritePackedMsg, end)) { + return 0; + } + uint8_t *pPackedLengthField = *ppWritePackedMsg; + if (!(push16(value->PDUSize, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) + && pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { + if (!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and Beamforming + // TODO get these values from elsewhere and delete the hardcoded ones + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[0].pm_idx = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - - return 0; - } - - return (push16(value->PDUType, ppWritePackedMsg, end) && - push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); + if (!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, + ppWritePackedMsg, + end)) { + return 0; + } + for (int digInt = 0; digInt < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; + digInt++) { + if (!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i] + .precodingAndBeamforming.prgs_list[prg] + .dig_bf_interface_list[digInt] + .beam_idx, + ppWritePackedMsg, + end)) { + return 0; + } + } + } + if (!(push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + // DCI Payload fields + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + // Pack DCI Payload + pack_dci_payload(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, + ppWritePackedMsg, + end))) { + return 0; + } + } + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->PDUSize = packedMsgLen; + return push16(value->PDUSize, &pPackedLengthField, end); } static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { @@ -1878,40 +2009,32 @@ static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8 } //pack_tx_data_pdu_list_value -static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; - - if(!(push32(value->num_TLV, ppWritePackedMsg, end) && - push16(value->PDU_index, ppWritePackedMsg, end) && - push16(value->PDU_length, ppWritePackedMsg, end) - )) + if (!(push16(value->PDU_length, ppWritePackedMsg, end) && push16(value->PDU_index, ppWritePackedMsg, end) + && push32(value->num_TLV, ppWritePackedMsg, end))) return 0; uint16_t i = 0; uint16_t total_number_of_tlvs = value->num_TLV; - for(; i < total_number_of_tlvs; ++i) { - if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && - push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + for (; i < total_number_of_tlvs; ++i) { + if (!(push16(value->TLVs[i].tag, ppWritePackedMsg, end) && push16(value->TLVs[i].length, ppWritePackedMsg, end))) return 0; - switch(value->TLVs[i].tag) { + switch (value->TLVs[i].tag) { case 0: { - if (!pusharray32(value->TLVs[i].value.direct, sizeof(value->TLVs[i].value.direct) / sizeof(uint32_t), - value->TLVs[i].length / sizeof(uint32_t), ppWritePackedMsg, end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", - __FUNCTION__, __LINE__, value->TLVs[i].length); + if (!pusharray32(value->TLVs[i].value.direct, 16384, (value->TLVs[i].length + 3) / 4, ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); return 0; } - break; } case 1: { - if (!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length / sizeof(uint32_t), - value->TLVs[i].length / sizeof(uint32_t), ppWritePackedMsg, end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", - __FUNCTION__, __LINE__, value->TLVs[i].length); + if (!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length, value->TLVs[i].length, ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); return 0; } @@ -1919,7 +2042,7 @@ static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg } default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag); break; } } @@ -1971,19 +2094,25 @@ static uint8_t pack_tx_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, return 1; } -static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - if (!( - push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) - )) + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end))) return 0; - for(int i=0; iNumber_of_PDUs; i++) { - if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { + if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", + __FUNCTION__, + __LINE__, + i, + pNfapiMsg->pdu_list[i].PDU_length, + pNfapiMsg->pdu_list[i].PDU_index); return 0; + } } return 1; @@ -3034,79 +3163,84 @@ return 1; static uint8_t pack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push16(value->pdu_length, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; - if(pusharray8(value->pdu, value->pdu_length, value->pdu_length, ppWritePackedMsg, end) == 0) - return 0; + if(pusharray8(value->pdu, value->pdu_length, value->pdu_length, ppWritePackedMsg, end) == 0) + return 0; - return 1; + return 1; } static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) - return 0; - } + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) + { + if(!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) + return 0; + } - return 1; + return 1; } //NR CRC INDICATION -static uint8_t pack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) +static uint8_t pack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push8(value->tb_crc_status, ppWritePackedMsg, end) && - push16(value->num_cb, ppWritePackedMsg, end) && - //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - return 1; + if (!(push32(value->handle, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push8(value->harq_id, ppWritePackedMsg, end) && push8(value->tb_crc_status, ppWritePackedMsg, end) + && push16(value->num_cb, ppWritePackedMsg, end))) { + return 0; + } + if (value->num_cb != 0) { + if (!pusharray8(value->cb_crc_status, + (int)(value->num_cb / 8) + 1, + (int)(value->num_cb / 8) + 1, + ppWritePackedMsg, + end)) { // length is ceil(NumCb/8) + return 0; + } + } + if (!(push8(value->ul_cqi, ppWritePackedMsg, end) && push16(value->timing_advance, ppWritePackedMsg, end) + && push16(value->rssi, ppWritePackedMsg, end))) { + return 0; + } + return 1; } static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) - )) - return 0; + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; - for (int i = 0; i < pNfapiMsg->number_crcs; i++) - { - if(!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end)) - return 0; - } + for (int i = 0; i < pNfapiMsg->number_crcs; i++) + { + if(!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end)) + return 0; + } -return 1; + return 1; } //SRS INDICATION @@ -3287,7 +3421,7 @@ return 1; //UCI INDICATION static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; if (!push8(value->pduBitmap, ppWritePackedMsg, end)) return 0; @@ -3322,123 +3456,192 @@ static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint } } - return 1; + return 1; } static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; - if (!push8(value->pduBitmap, ppWritePackedMsg, end)) - return 0; - if (!push32(value->handle, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rnti, ppWritePackedMsg, end)) - return 0; - if (!push8(value->pucch_format, ppWritePackedMsg, end)) - return 0; - if (!push8(value->ul_cqi, ppWritePackedMsg, end)) - return 0; - if (!push16(value->timing_advance, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rssi, ppWritePackedMsg, end)) - return 0; + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->pucch_format-2, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; - if (value->pduBitmap & 0x01) { //SR - if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->sr.sr_payload, - (int)((value->sr.sr_bit_len / 8) + 1), - (int)((value->sr.sr_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if (value->pduBitmap & 0x01) { //SR + if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->sr.sr_payload, + (int)((value->sr.sr_bit_len / 8) + 1), + (int)((value->sr.sr_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - if ((value->pduBitmap >> 1) & 0x01) { //HARQ - if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->harq.harq_payload, - (int)((value->harq.harq_bit_len / 8) + 1), - (int)((value->harq.harq_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if ((value->pduBitmap >> 1) & 0x01) { //HARQ + if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->harq.harq_payload, + (int)((value->harq.harq_bit_len / 8) + 1), + (int)((value->harq.harq_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - if ((value->pduBitmap >> 2) & 0x01) { //CSI-1 - if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->csi_part1.csi_part1_payload, - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if ((value->pduBitmap >> 2) & 0x01) { //CSI-1 + if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->csi_part1.csi_part1_payload, + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - if ((value->pduBitmap >> 3) & 0x01) { //CSI-2 - if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->csi_part2.csi_part2_payload, - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if ((value->pduBitmap >> 3) & 0x01) { //CSI-2 + if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->csi_part2.csi_part2_payload, + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - return 1; + return 1; +} + +static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_pusch_pdu_t *value = (nfapi_nr_uci_pusch_pdu_t *)tlv; + + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; + + // Bit 0 not used in PUSCH PDU + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) + return 0; + + if (!pusharray8(value->harq.harq_payload, + (int)((value->harq.harq_bit_len / 8) + 1), + (int)((value->harq.harq_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) + return 0; + + if (!pusharray8(value->csi_part1.csi_part1_payload, + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) + return 0; + + if (!pusharray8(value->csi_part2.csi_part2_payload, + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } + + return 1; } static uint8_t pack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) { - if (!push16(value->pdu_type, ppWritePackedMsg, end)) - return 0; - if (!push16(value->pdu_size, ppWritePackedMsg, end)) - return 0; + if (!push16(value->pdu_type, ppWritePackedMsg, end)) + return 0; + if (!push16(value->pdu_size, ppWritePackedMsg, end)) + return 0; - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + if(!pack_nr_uci_pusch(&value->pusch_pdu, ppWritePackedMsg, end)){ + return 0; + } + break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: - pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); - break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + if(!pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end)){ + return 0; + } + break; - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: - pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end); - break; - } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + if(!pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end)){ + return 0; + } + break; + } - return 1; + return 1; } static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; - if (!push16(pNfapiMsg->sfn , ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->slot , ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)) - return 0; + if (!push16(pNfapiMsg->sfn , ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->slot , ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)) + return 0; - for (int i = 0; i < pNfapiMsg->num_ucis; i++) - { - if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end)) - return 0; + for (int i = 0; i < pNfapiMsg->num_ucis; i++) + { + if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end)) + return 0; - } + } -return 1; + return 1; } @@ -3446,95 +3649,95 @@ return 1; int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { -nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; -uint8_t *pWritePackedMessage = pPackedBuf; -uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; -if (pMessageBuf == NULL || pPackedBuf == NULL) { + if (pMessageBuf == NULL || pPackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); return -1; -} + } -uint8_t *end = (uint8_t *)pPackedBuf + packedBufLen; + uint8_t *end = (uint8_t *)pPackedBuf + packedBufLen; -// process the header -if (!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) - && push16(0 /*pMessageHeader->message_length*/, &pWritePackedMessage, end) - && push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) - && push32(0 /*pMessageHeader->checksum*/, &pWritePackedMessage, end) - && push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { + // process the header + if (!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) + && push16(0 /*pMessageHeader->message_length*/, &pWritePackedMessage, end) + && push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) + && push32(0 /*pMessageHeader->checksum*/, &pWritePackedMessage, end) + && push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); return -1; -} + } -if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, // pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); -} -// look for the specific message -uint8_t result = 0; -switch (pMessageHeader->message_id) { + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_UE_RELEASE_REQUEST: - result = pack_nr_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_UE_RELEASE_RESPONSE: - result = pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; default: { - if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { if (config && config->pack_p7_vendor_extension) { result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); } else { @@ -3543,47 +3746,47 @@ switch (pMessageHeader->message_id) { __FUNCTION__, pMessageHeader->message_id); } - } else { + } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } + } } break; -} + } -if (result == 0) { + if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); return -1; -} + } -// check for a valid message length -uintptr_t msgHead = (uintptr_t)pPackedBuf; -uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; -uint32_t packedMsgLen = msgEnd - msgHead; -uint16_t packedMsgLen16; -if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); return -1; -} else { + } else { packedMsgLen16 = (uint16_t)packedMsgLen; -} + } -// Update the message length in the header -pMessageHeader->message_length = packedMsgLen16; + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; -if (!push16(packedMsgLen16, &pPackedLengthField, end)) + if (!push16(packedMsgLen16, &pPackedLengthField, end)) return -1; -if (1) { + if (1) { // quick test if (pMessageHeader->message_length != packedMsgLen) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, - "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", - packedMsgLen, - pMessageHeader->message_length, - pMessageHeader->message_id); + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", + packedMsgLen, + pMessageHeader->message_length, + pMessageHeader->message_id); } -} + } -return (packedMsgLen); + return (packedMsgLen); } int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { @@ -3751,122 +3954,179 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu // Unpack routines // NR: -static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; - return( - pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &value->start_rb, end) && - pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && - pull8(ppReadPackedMsg, &value->csi_type, end) && - pull8(ppReadPackedMsg, &value->row, end) && - pull16(ppReadPackedMsg, &value->freq_domain, end) && - pull8(ppReadPackedMsg, &value->symb_l0, end) && - pull8(ppReadPackedMsg, &value->symb_l1, end) && - pull8(ppReadPackedMsg, &value->cdm_type, end) && - pull8(ppReadPackedMsg, &value->freq_density, end) && - pull16(ppReadPackedMsg, &value->scramb_id, end) && - pull8(ppReadPackedMsg, &value->power_control_offset, end) && - pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) - ); + uint16_t num_prgs = 0, prg_size = 0; + uint8_t dig_bf_interfaces = 0; + return (pull16(ppReadPackedMsg, &value->bwp_size, end) && pull16(ppReadPackedMsg, &value->bwp_start, end) + && pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &value->cyclic_prefix, end) + && pull16(ppReadPackedMsg, &value->start_rb, end) && pull16(ppReadPackedMsg, &value->nr_of_rbs, end) + && pull8(ppReadPackedMsg, &value->csi_type, end) && pull8(ppReadPackedMsg, &value->row, end) + && pull16(ppReadPackedMsg, &value->freq_domain, end) && pull8(ppReadPackedMsg, &value->symb_l0, end) + && pull8(ppReadPackedMsg, &value->symb_l1, end) && pull8(ppReadPackedMsg, &value->cdm_type, end) + && pull8(ppReadPackedMsg, &value->freq_density, end) && pull16(ppReadPackedMsg, &value->scramb_id, end) + && pull8(ppReadPackedMsg, &value->power_control_offset, end) + && pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) && + // Precoding and Beamforming hardcoded to 0 + pull16(ppReadPackedMsg, &num_prgs, end) && pull16(ppReadPackedMsg, &prg_size, end) + && pull8(ppReadPackedMsg, &dig_bf_interfaces, end)); } +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; -static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + if (!(pull16(ppReadPackedMsg, &value->BWPSize, end) && pull16(ppReadPackedMsg, &value->BWPStart, end) + && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) + && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && pull8(ppReadPackedMsg, &value->DurationSymbols, end) + && pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) + && pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && pull8(ppReadPackedMsg, &value->RegBundleSize, end) + && pull8(ppReadPackedMsg, &value->InterleaverSize, end) && pull8(ppReadPackedMsg, &value->CoreSetType, end) + && pull16(ppReadPackedMsg, &value->ShiftIndex, end) && pull8(ppReadPackedMsg, &value->precoderGranularity, end) + && pull16(ppReadPackedMsg, &value->numDlDci, end))) { + return 0; + } - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && - pull8(ppReadPackedMsg, &value->RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->CoreSetType, end) && - pull16(ppReadPackedMsg, &value->ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->numDlDci, end)); + for (uint16_t i = 0; i < value->numDlDci; ++i) { + if (!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, end))) { + return 0; + } + for (int prg = 0; prg < value->dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, end)) { + return 0; + } + for (int digInt = 0; digInt < value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; digInt++) { + if (!pull16(ppReadPackedMsg, + &value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, + end)) { + return 0; + } + } + } + if (!(pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) + && unpack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppReadPackedMsg, end))) { + return 0; + } + } + // TODO: resolve the packaging of array (currently sending a single element) + return 1; } - - -static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->pduBitmap, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->pduIndex, end) && - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && - pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && - pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && - pull16(ppReadPackedMsg, &value->dataScramblingId, end) && - pull8(ppReadPackedMsg, &value->nrOfLayers, end) && - pull8(ppReadPackedMsg, &value->transmissionScheme, end) && - pull8(ppReadPackedMsg, &value->refPoint, end) && - pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && - pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && - pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && - pull8(ppReadPackedMsg, &value->SCID, end) && - pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && - pull16(ppReadPackedMsg, &value->dmrsPorts, end) && - pull8(ppReadPackedMsg, &value->resourceAlloc, end) && - pull16(ppReadPackedMsg, &value->rbStart, end) && - pull16(ppReadPackedMsg, &value->rbSize, end) && - pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && - pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && - pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSReOffset, end) - ); + uint8_t powerControlOffset = 0, powerControlOffsetSS = 0; + + if (!(pull16(ppReadPackedMsg, &value->pduBitmap, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull16(ppReadPackedMsg, &value->pduIndex, end) && pull16(ppReadPackedMsg, &value->BWPSize, end) + && pull16(ppReadPackedMsg, &value->BWPStart, end) && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) + && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && pull8(ppReadPackedMsg, &value->NrOfCodewords, end))) { + return 0; + } + for (int i = 0; i < value->NrOfCodewords; ++i) { + if (!(pull16(ppReadPackedMsg, &value->targetCodeRate[i], end) && pull8(ppReadPackedMsg, &value->qamModOrder[i], end) + && pull8(ppReadPackedMsg, &value->mcsIndex[i], end) && pull8(ppReadPackedMsg, &value->mcsTable[i], end) + && pull8(ppReadPackedMsg, &value->rvIndex[i], end) && pull32(ppReadPackedMsg, &value->TBSize[i], end))) { + return 0; + } + } + + if (!(pull16(ppReadPackedMsg, &value->dataScramblingId, end) && pull8(ppReadPackedMsg, &value->nrOfLayers, end) + && pull8(ppReadPackedMsg, &value->transmissionScheme, end) && pull8(ppReadPackedMsg, &value->refPoint, end) + && pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && pull8(ppReadPackedMsg, &value->dmrsConfigType, end) + && pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && pull8(ppReadPackedMsg, &value->SCID, end) + && pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && pull16(ppReadPackedMsg, &value->dmrsPorts, end) + && pull8(ppReadPackedMsg, &value->resourceAlloc, end) && pullarray8(ppReadPackedMsg, &value->rbBitmap[0], 36, 36, end) + && pull16(ppReadPackedMsg, &value->rbStart, end) && pull16(ppReadPackedMsg, &value->rbSize, end) + && pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) + && pull8(ppReadPackedMsg, &value->NrOfSymbols, end))) { + return 0; + } + // Check pduBitMap bit 1 to pull PTRS parameters or not + if (value->pduBitmap & 0b1) { + if (!(pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) + && pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + && pull8(ppReadPackedMsg, &value->nEpreRatioOfPDSCHToPTRS, end))) { + return 0; + } + } + + if (!(pull16(ppReadPackedMsg, &value->precodingAndBeamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->precodingAndBeamforming.dig_bf_interfaces, end))) { + return 0; + } + + for (int i = 0; i < value->precodingAndBeamforming.num_prgs; ++i) { + if (!pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prgs_list[i].pm_idx, end)) { + return 0; + } + for (int k = 0; k < value->precodingAndBeamforming.dig_bf_interfaces; ++k) { + if (!pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, end)) { + return 0; + } + } + } + // TODO Add TX power info + // Hardcoded values that represent 0db + + if (!(pull8(ppReadPackedMsg, &powerControlOffset, end) && // powerControlOffset + pull8(ppReadPackedMsg, &powerControlOffsetSS, end))) { // powerControlOffsetSS + return 0; + } + // TODO Add CBG Fields + return 1; } - -static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Unpacking ssb. \n"); + uint8_t byte3, byte2, byte1, byte0; nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; - return( - pull16(ppReadPackedMsg, &value->PhysCellId, end) && - pull8(ppReadPackedMsg, &value->BetaPss, end) && - pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && - pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && - pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && - pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && - pull32(ppReadPackedMsg, &value->bchPayload, end) && - pull8(ppReadPackedMsg, &value->ssbRsrp, end) - // TODO: pack precoding_and_beamforming too - ); -} + if (!(pull16(ppReadPackedMsg, &value->PhysCellId, end) && pull8(ppReadPackedMsg, &value->BetaPss, end) + && pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) + && pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) + && pull8(ppReadPackedMsg, &byte3, end) && pull8(ppReadPackedMsg, &byte2, end) && pull8(ppReadPackedMsg, &byte1, end) + && pull8(ppReadPackedMsg, &byte0, end))) { // this should be always 0, bchpayload is 24 bits + return 0; + } + // rebuild the bchpayload + value->bchPayload = byte3; + value->bchPayload = value->bchPayload << 8; + value->bchPayload |= byte2; + value->bchPayload = value->bchPayload << 8; + value->bchPayload |= byte1; + // TODO add Tx Power Info + if (!(pull8(ppReadPackedMsg, &byte1, end) && pull8(ppReadPackedMsg, &byte0, end) + && pull16(ppReadPackedMsg, &value->precoding_and_beamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->precoding_and_beamforming.dig_bf_interfaces, end))) { + return 0; + } + + for (int i = 0; i < value->precoding_and_beamforming.num_prgs; ++i) { + if (!pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prgs_list[i].pm_idx, end)) { + return 0; + } + for (int k = 0; k < value->precoding_and_beamforming.dig_bf_interfaces; ++k) { + if (!pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, end)) { + return 0; + } + } + } + return 1; +} // LTE: static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { @@ -4260,8 +4520,8 @@ static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppRe static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)msg; - if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->PDUType, end) )) + if(!(pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, (uint16_t *) &value->PDUSize, end))) return 0; // first match the pdu type, then call the respective function @@ -4470,189 +4730,180 @@ static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPa return 1; } - -static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && - pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe,256,pNfapiMsg->dl_tti_request_body.nGroup, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end))) { return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { + if (!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } int arr[12]; - - for(int i=0; idl_tti_request_body.nGroup; i++) { - for(int j=0; jdl_tti_request_body.nUe[i]; j++) { + if (!pullarray8(ppReadPackedMsg, pNfapiMsg->dl_tti_request_body.nUe, 256, pNfapiMsg->dl_tti_request_body.nGroup, end)) { + return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { + for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; } - if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) - return 0; - } - - for(int i=0; idl_tti_request_body.nPDUs; i++) { - if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + if (!(pullarrays32(ppReadPackedMsg, arr, 12, pNfapiMsg->dl_tti_request_body.nUe[i], end))) return 0; } return 1; } - -static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_prach_pdu_t *prach_pdu = (nfapi_nr_prach_pdu_t *)tlv; - return( - pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && - pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) - // TODO: ignoring beamforming tlv for now - ); + + if (!(pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) + && pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) + && pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && pull16(ppReadPackedMsg, &prach_pdu->num_cs, end))) { + return 0; + } + // TODO: ignoring beamforming tlv for now + if (prach_pdu->beamforming.prgs_list == NULL) { + prach_pdu->beamforming.prgs_list = calloc(prach_pdu->beamforming.num_prgs, sizeof(*prach_pdu->beamforming.prgs_list)); + } + if (prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list == NULL) { + prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list = + calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list)); + } + // Pack RX Beamforming PDU + if (!(pull16(ppReadPackedMsg, &prach_pdu->beamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &prach_pdu->beamforming.prg_size, end) + && pull8(ppReadPackedMsg, &prach_pdu->beamforming.dig_bf_interface, end))) { + return 0; + } + for (int prg = 0; prg < prach_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < prach_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!pull16(ppReadPackedMsg, &prach_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, end)) { + return 0; + } + } + } + + return 1; } - -static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_pucch_pdu_t *pucch_pdu = (nfapi_nr_pucch_pdu_t *)tlv; - return( - pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && - pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pi_2bpsk, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && - pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && - pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && - pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && - pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && - pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && - pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + uint16_t dummy16 = 0; + uint8_t dummy8 = 0; + return (pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && pull32(ppReadPackedMsg, &pucch_pdu->handle, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) + && pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) + && pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) + && pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && pull8(ppReadPackedMsg, &pucch_pdu->pi_2bpsk, end) + && pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) + && pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) + && pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) + && pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) + && pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) + && pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) + && pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) + && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) + && pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) + && pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) + && pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) && // TODO: ignoring beamforming tlv for now - ); + pull16(ppReadPackedMsg, &dummy16, end) && pull16(ppReadPackedMsg, &dummy16, end) && pull8(ppReadPackedMsg, &dummy8, end)); } - -static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_pusch_pdu_t *pusch_pdu = (nfapi_nr_pusch_pdu_t *)tlv; - if (!( - pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && - pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && - pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && - pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && - pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && - pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && - pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && - pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && - pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && - pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) + && pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) + && pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) + && pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) + && pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) + && pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) + && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) + && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->scid, end) + && pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) + && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) + && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) + && pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) + && pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) + && pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) + && pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) + && pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) // TODO: ignoring beamforming tlv for now - )) + )) return 0; - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map) { + // Pack Optional Data only included if indicated in pduBitmap + switch (pusch_pdu->pdu_bit_map) { case PUSCH_PDU_BITMAP_PUSCH_DATA: { // pack optional TLVs - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && - pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && - pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) - ); - } - break; + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) + && pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) + && pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position, 1, 1, end))) { + return 0; + } + } break; case PUSCH_PDU_BITMAP_PUSCH_UCI: { - return( - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) - ); - } - break; + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end))) { + return 0; + } + } break; case PUSCH_PDU_BITMAP_PUSCH_PTRS: { - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) - ); - } - break; + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end))) { + return 0; + } + } break; case PUSCH_PDU_BITMAP_DFTS_OFDM: { - return( - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) - ); - } - break; + if (!(pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) + && pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) + && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end))) { + return 0; + } + } break; default: { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map); } } + uint16_t dummy16 = 0; + uint8_t dummy8 = 0; + if (!(pull16(ppReadPackedMsg, &dummy16, end) && pull16(ppReadPackedMsg, &dummy16, end) && pull8(ppReadPackedMsg, &dummy8, end))) { + return 0; + } return 1; } - static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_srs_pdu_t *srs_pdu = (nfapi_nr_srs_pdu_t *)tlv; return( @@ -4687,8 +4938,8 @@ static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMs static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_ul_tti_request_number_of_pdus_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t *)msg; - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) )) return 0; // first natch the pdu type, then call the respective function @@ -4741,8 +4992,8 @@ static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_ return 1; } - -static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; if (!pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end)) @@ -4751,21 +5002,20 @@ static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end)) return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end)) - return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end)) return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end)) return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end)) return 0; - - for(int i=0; i< pNfapiMsg->n_pdus; i++) { + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end)) + return 0; + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) return 0; } - for(int i=0; i< pNfapiMsg->n_group; i++) { + for (int i = 0; i < pNfapiMsg->n_group; i++) { if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) return 0; } @@ -4773,8 +5023,6 @@ static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo return 1; } - - static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; unpack_p7_tlv_t unpack_fns[] = { @@ -5557,43 +5805,66 @@ static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPack static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)msg; - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + if (!(pull16(ppReadPackedMsg, &value->PDUType, end) && pull16(ppReadPackedMsg, &value->PDUSize, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) + && pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end))) { + return 0; + } - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - - return (pull16(ppReadPackedMsg, &value->PDUType, end) && - pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); + for (uint16_t i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { + if (!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, end))) { + return 0; + } + for (int prg = 0; prg < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!pull16(ppReadPackedMsg, + &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, + end)) { + return 0; + } + for (int digInt = 0; digInt < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; + digInt++) { + if (!pull16(ppReadPackedMsg, + &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i] + .precodingAndBeamforming.prgs_list[prg] + .dig_bf_interface_list[digInt] + .beam_idx, + end)) { + return 0; + } + } + } + if (!(pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) + && unpack_dci_payload(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, + ppReadPackedMsg, + end))) { + return 0; + } + } + return 1; } static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { @@ -5624,25 +5895,25 @@ static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, v static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_pdu_t *pNfapiMsg = (nfapi_nr_pdu_t *)msg; - if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) && pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) - )) + pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) + )) return 0; uint16_t i = 0; uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; for(; i < total_number_of_tlvs; ++i) { - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end))) return 0; switch(pNfapiMsg->TLVs[i].tag) { case 0: { if (!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, - sizeof(pNfapiMsg->TLVs[i].value.direct) / sizeof(uint32_t), - pNfapiMsg->TLVs[i].length / sizeof(uint32_t), end)) + sizeof(pNfapiMsg->TLVs[i].value.direct) / sizeof(uint32_t), + (pNfapiMsg->TLVs[i].length+3)/4, end)) return 0; break; @@ -5650,8 +5921,8 @@ static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t case 1: { if (!pullarray32(ppReadPackedMsg,pNfapiMsg->TLVs[i].value.ptr, - pNfapiMsg->TLVs[i].length / sizeof(uint32_t), - pNfapiMsg->TLVs[i].length / sizeof(uint32_t), end)) + pNfapiMsg->TLVs[i].length, + pNfapiMsg->TLVs[i].length, end)) return 0; break; @@ -5667,17 +5938,25 @@ static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t return 1; } -static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) return 0; - for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) { - if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) { + printf("%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", + __FUNCTION__, + __LINE__, + i, + pNfapiMsg->pdu_list[i].PDU_length, + pNfapiMsg->pdu_list[i].PDU_index); + return 0; + } } return 1; @@ -5787,101 +6066,102 @@ static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end return 1; } -//RX DATA INDICATION +//RX DATA INDICATION -static uint8_t unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t* value, +static uint8_t unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, - nfapi_p7_codec_config_t* config) + nfapi_p7_codec_config_t *config) { - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull16(ppReadPackedMsg, &value->pdu_length, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; +if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull8(ppReadPackedMsg, &value->harq_id, end) && pull16(ppReadPackedMsg, &value->pdu_length, end) + && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) + return 0; - uint16_t length = value->pdu_length; - value->pdu = nfapi_p7_allocate(sizeof(*value->pdu) * length, config); - - if (pullarray8(ppReadPackedMsg, value->pdu, length, length, end) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pullarray8 failure\n", __FUNCTION__); - return 0; - } - return 1; +uint32_t length = value->pdu_length; +value->pdu = nfapi_p7_allocate(sizeof(*value->pdu) * length, config); +if (pullarray8(ppReadPackedMsg, value->pdu, length, length, end) == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pullarray8 failure\n", __FUNCTION__); + return 0; +} +return 1; } - static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) { - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - if (pNfapiMsg->number_of_pdus > 0) - { - pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); - } + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) - return 0; - } + if (pNfapiMsg->number_of_pdus > 0) + { + pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); + } -return 1; + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) + { + if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) + return 0; + } + + return 1; } //NR CRC INDICATION -static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) { - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull8(ppReadPackedMsg, &value->tb_crc_status, end) && - pull16(ppReadPackedMsg, &value->num_cb, end) && - //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; + if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull8(ppReadPackedMsg, &value->harq_id, end) && pull8(ppReadPackedMsg, &value->tb_crc_status, end) + && pull16(ppReadPackedMsg, &value->num_cb, end))) { + return 0; + } + if (value->num_cb != 0) { + if (!pullarray8(ppReadPackedMsg, + value->cb_crc_status, + (int)(value->num_cb / 8) + 1, + (int)(value->num_cb / 8) + 1, + end)) { // length is ceil(NumCb/8) + return 0; + } + } + if (!(pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) { + return 0; + } - //memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); + // memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); - return 1; + return 1; } static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t* config) { - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) - )) - return 0; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; - if (pNfapiMsg->number_crcs > 0) - { - pNfapiMsg->crc_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->crc_list) * pNfapiMsg->number_crcs, config); - } + if (pNfapiMsg->number_crcs > 0) + { + pNfapiMsg->crc_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->crc_list) * pNfapiMsg->number_crcs, config); + } - for (int i = 0; i < pNfapiMsg->number_crcs; i++) - { - if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end)) - return 0; - } + for (int i = 0; i < pNfapiMsg->number_crcs; i++) + { + if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end)) + return 0; + } -return 1; + return 1; } //SRS INDICATION @@ -6009,100 +6289,86 @@ static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, //NR RACH -static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t* value, +static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, - nfapi_p7_codec_config_t* config) + nfapi_p7_codec_config_t *config) { + if (!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && pull8(ppReadPackedMsg, &value->symbol_index, end) + && pull8(ppReadPackedMsg, &value->slot_index, end) && pull8(ppReadPackedMsg, &value->freq_index, end) + && pull8(ppReadPackedMsg, &value->avg_rssi, end) && pull8(ppReadPackedMsg, &value->avg_snr, end) + && pull8(ppReadPackedMsg, &value->num_preamble, end))) { + return 0; + } - if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && - pull8(ppReadPackedMsg, &value->symbol_index, end) && - pull8(ppReadPackedMsg, &value->slot_index, end) && - pull8(ppReadPackedMsg, &value->freq_index, end) && - pull8(ppReadPackedMsg, &value->avg_rssi, end) && - pull8(ppReadPackedMsg, &value->avg_snr, end) && - pull8(ppReadPackedMsg, &value->num_preamble, end) - )) - return 0; - - if (value->num_preamble > 0) { - value->preamble_list = nfapi_p7_allocate(sizeof(*value->preamble_list) * value->num_preamble, config); - for(int i = 0; i < value->num_preamble; i++) - { - if(!(pull8(ppReadPackedMsg, &value->preamble_list[i].preamble_index, end) && - pull16(ppReadPackedMsg, &value->preamble_list[i].timing_advance, end) && - pull32(ppReadPackedMsg, &value->preamble_list[i].preamble_pwr, end) - )) - return 0; - } - } - return 1; + if (value->num_preamble > 0) { + value->preamble_list = nfapi_p7_allocate(sizeof(*value->preamble_list) * value->num_preamble, config); + for (int i = 0; i < value->num_preamble; i++) { + nfapi_nr_prach_indication_preamble_t *preamble = &(value->preamble_list[i]); + if (!(pull8(ppReadPackedMsg, &preamble->preamble_index, end) && pull16(ppReadPackedMsg, &preamble->timing_advance, end) + && pull32(ppReadPackedMsg, &preamble->preamble_pwr, end))) { + return 0; + } + } + } + return 1; } -static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rach_indication_t* msg, nfapi_p7_codec_config_t* config) { +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_nr_rach_indication_t *msg, + nfapi_p7_codec_config_t *config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg; - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) { + return 0; + } - if (pNfapiMsg->number_of_pdus > 0) { - pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); - for(int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) - return 0; - } - } - return 1; + if (pNfapiMsg->number_of_pdus > 0) { + pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!unpack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppReadPackedMsg, end, config)) + return 0; + } + } + return 1; } -//NR UCI +//NR UCI static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, - nfapi_p7_codec_config_t *config) { + nfapi_p7_codec_config_t *config) +{ + if (!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && pull32(ppReadPackedMsg, &value->handle, end) + && pull16(ppReadPackedMsg, &value->rnti, end) && pull8(ppReadPackedMsg, &value->pucch_format, end) + && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) + return 0; + if (value->pduBitmap & 0x01) { // SR + if (!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end))) + return 0; + } - if (!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && - pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->pucch_format, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && - pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end) - )) - return 0; - } + if (((value->pduBitmap >> 1) & 0x01)) { // HARQ - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end))) + return 0; + if (value->harq.num_harq > 0) { + for (int i = 0; i < value->harq.num_harq; i++) { + if (!pull8(ppReadPackedMsg, &value->harq.harq_list[i].harq_value, end)) { + return 0; + } + } + } + } - - if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && - pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end) - )) - return 0; - if (value->harq.num_harq > 0) { - - for (int i = 0; i < value->harq.num_harq; i++) { - if (!pull8(ppReadPackedMsg, &value->harq.harq_list[i].harq_value, end)) { - return 0; - } - } - } - } - - return 1; + return 1; } - static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value, uint8_t **ppReadPackedMsg, uint8_t *end, @@ -6123,6 +6389,7 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* if (!pull16(ppReadPackedMsg, &value->rssi, end)) return 0; + value->pucch_format += 2; if (value->pduBitmap & 0x01) { //SR if (!pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end)) return 0; @@ -6214,60 +6481,148 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* return 1; } +static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!pull8(ppReadPackedMsg, &value->pduBitmap, end)) + return 0; + if (!pull32(ppReadPackedMsg, &value->handle, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rnti, end)) + return 0; + if (!pull8(ppReadPackedMsg, &value->ul_cqi, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->timing_advance, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rssi, end)) + return 0; + + // Bit 0 not used in PUSCH PDU + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end)) + return 0; + + value->harq.harq_payload = + nfapi_p7_allocate(sizeof(*value->harq.harq_payload) * (int)((value->harq.harq_bit_len / 8) + 1), config); + if (value->harq.harq_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->harq.harq_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, + value->harq.harq_payload, + (int)((value->harq.harq_bit_len / 8) + 1), + (int)((value->harq.harq_bit_len / 8) + 1), + end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end)) + return 0; + + value->csi_part1.csi_part1_payload = + nfapi_p7_allocate(sizeof(*value->csi_part1.csi_part1_payload) * (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + config); + if (value->csi_part1.csi_part1_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part1.csi_part1_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, + value->csi_part1.csi_part1_payload, + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end)) + return 0; + + value->csi_part2.csi_part2_payload = + nfapi_p7_allocate(sizeof(*value->csi_part2.csi_part2_payload) * (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + config); + if (value->csi_part2.csi_part2_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part2.csi_part2_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, + value->csi_part2.csi_part2_payload, + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + end)) + return 0; + } + + return 1; +} + static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { - if (!pull16(ppReadPackedMsg, &value->pdu_type, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->pdu_size, end)) - return 0; + if (!pull16(ppReadPackedMsg, &value->pdu_type, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->pdu_size, end)) + return 0; - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *uci_pdu = &value->pusch_pdu; + if (!unpack_nr_uci_pusch(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + if (!unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + if (!unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + default: + NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected pdu type %d\n", value->pdu_type); + break; + } - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - if (!unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - if (!unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; - } - default: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected pdu type %d\n", value->pdu_type); - break; - } - - return 1; + return 1; } -static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->slot , end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)) - return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)) + return 0; - pNfapiMsg->uci_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->uci_list) * pNfapiMsg->num_ucis, config); - for (int i = 0; i < pNfapiMsg->num_ucis; i++) - { - if (!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppReadPackedMsg, end, config)) - return 0; - } + pNfapiMsg->uci_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->uci_list) * pNfapiMsg->num_ucis, config); + for (int i = 0; i < pNfapiMsg->num_ucis; i++) { + if (!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppReadPackedMsg, end, config)) + return 0; + } - return 1; + return 1; } static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { @@ -8093,41 +8448,29 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_UE_RELEASE_REQUEST: if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)){ nfapi_nr_slot_indication_scf_t* msg = (nfapi_nr_slot_indication_scf_t*) pMessageHeader; result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: @@ -8137,8 +8480,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->pdu_list->pdu = (uint8_t *) malloc(sizeof(uint8_t)); result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: @@ -8148,8 +8489,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->crc_list = (nfapi_nr_crc_t*) malloc(sizeof(nfapi_nr_crc_t)); result = unpack_nr_crc_indication(&pReadPackedMessage,end , msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: @@ -8158,8 +8497,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->uci_list = (nfapi_nr_uci_t*) malloc(sizeof(nfapi_nr_uci_t)); result = unpack_nr_uci_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: @@ -8168,8 +8505,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->pdu_list = (nfapi_nr_srs_indication_pdu_t*) malloc(sizeof(nfapi_nr_srs_indication_pdu_t)); result = unpack_nr_srs_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: @@ -8177,36 +8512,26 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * nfapi_nr_rach_indication_t* msg = (nfapi_nr_rach_indication_t*) pMessageHeader; result = unpack_nr_rach_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; break; case NFAPI_TIMING_INFO: if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_UE_RELEASE_RESPONSE: if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; default: @@ -8230,8 +8555,9 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * break; } - if(result == 0) - return -1; - else - return 0; + if (result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + return 0; } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index a1be4d0edc..dd91d2fc71 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -249,18 +249,17 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } -//NR UPLINK INDICATION +//NR UPLINK INDICATION int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind) { - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } + if (config == NULL || ind == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); } int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) From 82e83bc6a61363ebab3bc5444c3d0397f17e381c Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 28 Sep 2023 10:40:11 +0200 Subject: [PATCH 28/43] nr rlc am: bugfix: correc usage of tx_next tx_next was increased only when all segments of an SDU were sent to lower layers. This may lead to a situation where the receive entity transmits a control PDU that is rejected because it sets its ACK to tx_next+1 (if all segments were not transmitted when the control PDU is sent). What is done now is to increase tx_next as soon as we send the first segment of an SDU to lower layers. A control PDU received from the receive entity is now accepted and processed. Specifications (38.322 5.2.3.1.1) say to increase tx_next when the RLC entity receives an SDU from upper layers. But for us, since the buffering of SDUs is done in the RLC layer and since the buffer size may be big, we may increase tx_next too much. The choice has been made to increase it only when we transmit an SDU to lower layers. We may change this logic if needed. (But it won't be simple.) --- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index c2d41cedb4..91985393cb 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -1638,7 +1638,10 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) entity->common.bstatus.tx_size -= pdu_size; /* assign SN to SDU */ - sdu->sdu->sn = entity->tx_next; + if (sdu->sdu->sn == -1) { + sdu->sdu->sn = entity->tx_next; + entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus; + } /* segment if necessary */ if (pdu_size > size) { @@ -1656,10 +1659,6 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) + next_sdu->size; } - /* update tx_next if the SDU segment is the last */ - if (sdu->is_last) - entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus; - /* put SDU/SDU segment in the wait list */ /* speedup: check end of wait list, probably the new sdu comes after */ if (entity->wait_end == NULL From 8aea710a6cc899d2501ac9b25f427c54977d6176 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 28 Sep 2023 10:52:55 +0200 Subject: [PATCH 29/43] nr rlc: minor: fix tests delete() has changed its name --- openair2/LAYER2/nr_rlc/tests/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/tests/test.c b/openair2/LAYER2/nr_rlc/tests/test.c index 716a6aef11..2086dba3c6 100644 --- a/openair2/LAYER2/nr_rlc/tests/test.c +++ b/openair2/LAYER2/nr_rlc/tests/test.c @@ -426,8 +426,8 @@ int test_main(void) } } - gnb->delete(gnb); - ue->delete(ue); + gnb->delete_entity(gnb); + ue->delete_entity(ue); free(sdu); free(pdu); From c4f3d6d7fe8ecba5aa06c2359d9fdc02d31d17c7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 12:11:10 +0200 Subject: [PATCH 30/43] ue_context_modification_request(): check if UE exists --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 0e383e4eaf..42803b0ff1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -287,6 +287,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) NR_SCHED_LOCK(&mac->sched_lock); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->gNB_DU_ue_id); + if (!UE) { + LOG_E(NR_MAC, "could not find UE with RNTI %04x\n", req->gNB_DU_ue_id); + NR_SCHED_UNLOCK(&mac->sched_lock); + return; + } NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); From d448b5e54974b8898863fa6a91adf87e312aaf86 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 27 Sep 2023 10:31:00 +0200 Subject: [PATCH 31/43] remove 'B' from persisted data, replace 3824 hardcoded by it's existing define --- CMakeLists.txt | 1 + openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 11 ++-- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 49 +++-------------- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 52 +++++-------------- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 4 -- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 36 ++++++------- openair1/PHY/defs_gNB.h | 16 ++++-- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 7 +-- .../NR_MAC_COMMON/nr_compute_tbs_common.c | 8 +-- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 3 +- 10 files changed, 61 insertions(+), 126 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec60df8b35..08a75e378e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1144,6 +1144,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) add_library(PHY_NR ${PHY_NR_SRC}) add_library(PHY_NR_UE ${PHY_NR_UE_SRC}) +target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs) add_library(PHY_RU ${PHY_SRC_RU}) target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index d244881c32..5f5a9260cd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -297,7 +297,8 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056; - if (A > 3824) { + int B; + if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload crc = crc24a(a,A)>>8; a[A>>3] = ((uint8_t *)&crc)[2]; @@ -305,7 +306,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, a[2+(A>>3)] = ((uint8_t *)&crc)[0]; //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - harq->B = A+24; + B = A + 24; // harq->b = a; AssertFatal((A / 8) + 4 <= max_bytes, "A %d is too big (A/8+4 = %d > %d)\n", @@ -320,7 +321,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, a[1+(A>>3)] = ((uint8_t *)&crc)[0]; //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - harq->B = A+16; + B = A + 16; // harq->b = a; AssertFatal((A / 8) + 3 <= max_bytes, "A %d is too big (A/8+3 = %d > %d)\n", @@ -333,11 +334,11 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; start_meas(dlsch_segmentation_stats); - impp.Kb = nr_segmentation(harq->b, harq->c, harq->B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); + impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); stop_meas(dlsch_segmentation_stats); if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",impp.n_segments,harq->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); return(-1); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 9d003b9ff5..01d428038c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -194,18 +194,8 @@ static void nr_processULSegment(void *arg) ulsch_harq->d_to_be_cleared[r] = false; memset(ulsch_harq->c[r], 0, Kr_bytes); - - if (ulsch_harq->C == 1) { - if (A > 3824) - p_decoderParms->crc_type = CRC24_A; - else - p_decoderParms->crc_type = CRC16; - p_decoderParms->block_length = ulsch_harq->B; - } else { - p_decoderParms->crc_type = CRC24_B; - p_decoderParms->block_length = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; - } - + p_decoderParms->crc_type = crcType(ulsch_harq->C, A); + p_decoderParms->block_length = lenWithCrc(ulsch_harq->C, A); // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); // set first 2*Z_c bits to zeros @@ -253,26 +243,12 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, int8_t llrProcBuf[22 * 384] __attribute__((aligned(32))); int16_t z_ol[68 * 384] __attribute__((aligned(32))); int8_t l_ol[68 * 384] __attribute__((aligned(32))); - int crc_type; - int length_dec; uint8_t Qm = pusch_pdu->qam_mod_order; uint8_t n_layers = pusch_pdu->nrOfLayers; const int Kr = harq_process->K; const int Kr_bytes = Kr >> 3; const int kc = decParams->BG == 2 ? 52 : 68; const uint32_t A = (harq_process->TBS) << 3; - - if (harq_process->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } else { - crc_type = CRC24_B; - length_dec = (harq_process->B + 24 * harq_process->C) / harq_process->C; - } int decodeIterations = 2; int dtx_det = 0; int r_offset = 0, offset = 0; @@ -316,23 +292,15 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, harq_process->c[r][m] = (uint8_t)llrProcBuf[m]; } - if (check_crc((uint8_t *)llrProcBuf, length_dec, crc_type)) { + if (check_crc((uint8_t *)llrProcBuf, lenWithCrc(harq_process->C, A), crcType(harq_process->C, A))) { PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); decodeIterations = 2; } else { PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); decodeIterations = ulsch->max_ldpc_iterations + 1; } - //} r_offset += E; - - /*for (int k=0;k<8;k++) - { - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - printf("llrprocbuf [%d] = %x adr %p\n", k, llrProcBuf[k], llrProcBuf+k); - } - */ } else { dtx_det = 0; decodeIterations = ulsch->max_ldpc_iterations + 1; @@ -417,11 +385,6 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, t_nrLDPC_dec_params decParams = {0}; decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; const uint32_t A = (harq_process->TBS) << 3; - if (A > 3824) - harq_process->B = A + 24; - else - harq_process->B = A + 16; - NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); if (stats) { stats->frame = frame; @@ -452,10 +415,10 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, harq_process->round, harq_process->harq_to_be_cleared); - // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) + // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F) nr_segmentation(NULL, NULL, - harq_process->B, + lenWithCrc(1, A), // size in case of 1 segment &harq_process->C, &harq_process->K, &harq_process->Z, // [hna] Z is Zc @@ -464,7 +427,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * n_layers; // number of segments to be allocated if (harq_process->C > a_segments) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); return(-1); } if (nb_rb != 273) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index f3ee7b0e7b..c993ec3709 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -44,6 +44,7 @@ #include "executables/nr-uesoftmodem.h" #include "PHY/CODING/nrLDPC_extern.h" #include "common/utils/nr/nr_common.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "openair1/PHY/TOOLS/phy_scope_interface.h" //#define ENABLE_PHY_PAYLOAD_DEBUG 1 @@ -116,10 +117,8 @@ static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, if (*num_seg_ok == harq_process->C) { if (harq_process->C > 1) { /* check global CRC */ - int A = tbs; - int crc_length = A > 3824 ? 3 : 2; - int crc_type = A > 3824 ? CRC24_A : CRC16; - if (!check_crc(b, A + crc_length * 8, crc_type)) { + // we have regrouped the transport block, so it is "1" segment + if (!check_crc(b, lenWithCrc(1, tbs), crcType(1, tbs))) { harq_process->ack = 0; dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; LOG_E(PHY, " Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n", proc->frame_rx, proc->nr_slot_rx, harq_process->C); @@ -166,10 +165,8 @@ static void nr_processDLSegment(void *arg) NR_UE_DLSCH_t *dlsch = rdata->dlsch; NR_DL_UE_HARQ_t *harq_process= rdata->harq_process; t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int length_dec; int Kr; int K_bits_F; - uint8_t crc_type; int r = rdata->segment_r; int A = rdata->A; int E = rdata->E; @@ -240,19 +237,6 @@ static void nr_processDLSegment(void *arg) LOG_D(PHY,"\n"); } - - if (harq_process->C == 1) { - if (A > NR_MAX_PDSCH_TBS) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } else { - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - { start_meas(&rdata->ts_ldpc_decode); //set first 2*Z_c bits to zeros @@ -272,9 +256,9 @@ static void nr_processDLSegment(void *arg) } //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); - p_decoderParms->block_length=length_dec; - nrLDPC_initcall(p_decoderParms, (int8_t*)&pl[0], LDPCoutput); - p_decoderParms->crc_type = crc_type; + p_decoderParms->block_length = lenWithCrc(harq_process->C, A); + p_decoderParms->crc_type = crcType(harq_process->C, A); + nrLDPC_initcall(p_decoderParms, (int8_t *)&pl[0], LDPCoutput); rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], LDPCoutput, &procTime, &harq_process->abort_decode); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); @@ -311,8 +295,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // HARQ stats phy_vars_ue->dl_stats[harq_process->DLround]++; - LOG_D(PHY,"Round %d RV idx %d\n",harq_process->DLround,dlsch->dlsch_config.rv); - uint8_t kc; + LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv); uint16_t nb_rb;// = 30; uint8_t dmrs_Type = dlsch->dlsch_config.dmrsConfigType; AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); @@ -377,33 +360,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d Coderate %f\n", frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, dlsch->dlsch_config.mcs, dlsch->Nl, nb_symb_sch, nb_rb, dlsch->dlsch_config.qamModOrder, Coderate); - - if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { - p_decParams->BG = 2; - kc = 52; - } else { - p_decParams->BG = 1; - kc = 68; - } + p_decParams->BG = get_BG(A, dlsch->dlsch_config.targetCodeRate); + unsigned int kc = p_decParams->BG == 2 ? 52 : 68; if (harq_process->first_rx == 1) { // This is a new packet, so compute quantities regarding segmentation - if (A > NR_MAX_PDSCH_TBS) - harq_process->B = A+24; - else - harq_process->B = A+16; - nr_segmentation(NULL, NULL, - harq_process->B, + lenWithCrc(1, A), // We give a max size in case of 1 segment &harq_process->C, &harq_process->K, &harq_process->Z, // [hna] Z is Zc &harq_process->F, p_decParams->BG); - + if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); return(-1); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 9f9b123781..b0ea45b7ec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -53,8 +53,6 @@ typedef struct { SCH_status_t status; /// Last TPC command uint8_t TPC; - /// The payload + CRC size in bits, "B" from 36-212 - uint32_t B; /// Length of ACK information (bits) uint8_t O_ACK; /// Index of current HARQ round for this ULSCH @@ -117,8 +115,6 @@ typedef struct { uint8_t Ndi; /// DLSCH status flag indicating SCH_status_t status; - /// The payload + CRC size in bits - uint32_t B; /// Pointers to transport block segments uint8_t **c; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 42fe941848..1c4d7c0fec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -92,8 +92,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, */ int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056; - - if (A > 3824) { + int B; + if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload crc = crc24a(harq_process->a,A)>>8; harq_process->a[A>>3] = ((uint8_t*)&crc)[2]; @@ -102,13 +102,12 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - harq_process->B = A+24; + B = A + 24; AssertFatal((A/8)+4 <= max_payload_bytes,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,max_payload_bytes); memcpy(harq_process->b,harq_process->a,(A/8)+4); - } - else { + } else { // Add 16-bit crc (polynomial A) to payload crc = crc16(harq_process->a,A)>>16; harq_process->a[A>>3] = ((uint8_t*)&crc)[1]; @@ -116,7 +115,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - harq_process->B = A+16; + B = A + 16; AssertFatal((A/8)+3 <= max_payload_bytes,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,max_payload_bytes); @@ -128,26 +127,25 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ///////////////////////// b---->| block segmentation |---->c ///////////////////////// /////////// - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { harq_process->BG = 2; - } - else{ + } else { harq_process->BG = 1; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); start_meas(&ue->ulsch_segmentation_stats); - uint32_t Kb=nr_segmentation(harq_process->b, - harq_process->c, - harq_process->B, - &harq_process->C, - &harq_process->K, - pz, - &harq_process->F, - harq_process->BG); + uint32_t Kb = nr_segmentation(harq_process->b, + harq_process->c, + B, + &harq_process->C, + &harq_process->K, + pz, + &harq_process->F, + harq_process->BG); if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", harq_process->C, B); return(-1); } stop_meas(&ue->ulsch_segmentation_stats); @@ -169,7 +167,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, for (int r=0; rC; r++) { //channel_input[r] = &harq_process->d[r][0]; #ifdef DEBUG_ULSCH_CODING - printf("Encoder: B %d F %d \n",harq_process->B, harq_process->F); + printf("Encoder: B %d F %d \n", B, harq_process->F); printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); for (int cnt =0 ; cnt < 22*(*pz)/8; cnt ++){ diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index c2e6dfba75..d212f0c46d 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -75,8 +75,6 @@ typedef struct { nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu; /// pointer to pdu from MAC interface (this is "a" in 36.212) uint8_t *pdu; - /// The payload + CRC size in bits, "B" from 36-212 - uint32_t B; /// Pointer to the payload uint8_t *b; /// Pointers to transport block segments @@ -199,8 +197,6 @@ typedef struct { uint32_t TBS; /// Pointer to the payload (38.212 V15.4.0 section 5.1) uint8_t *b; - /// The payload + CRC (24 bits) in bits (38.212 V15.4.0 section 5.1) - uint32_t B; /// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2) uint8_t **c; /// Number of bits in each code block (38.212 V15.4.0 section 5.2.2) @@ -227,6 +223,18 @@ typedef struct { int llrLen; ////////////////////////////////////////////////////////////// } NR_UL_gNB_HARQ_t; +static inline int lenWithCrc(int nbSeg, int len) +{ + if (nbSeg > 1) + return (len + 24 + 24 * nbSeg) / nbSeg; + return len + (len > NR_MAX_PDSCH_TBS ? 24 : 16); +} +static inline int crcType(int nbSeg, int len) +{ + if (nbSeg > 1) + return CRC24_B; + return len > NR_MAX_PDSCH_TBS ? CRC24_A : CRC16; +} typedef struct { //! estimated received spatial signal power (linear) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 6ad14f1836..c29cc92795 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -266,12 +266,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block bool crc_valid = true; if (ulsch_harq->C > 1) { - // Check ULSCH transport block CRC - int crc_type = CRC16; - if (rdata->A > 3824) { - crc_type = CRC24_A; - } - crc_valid = check_crc(ulsch_harq->b, ulsch_harq->B, crc_type); + crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, rdata->A), crcType(1, rdata->A)); } if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c index 7ea6df92fc..aa1042491b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c @@ -26,6 +26,7 @@ #define INDEX_MAX_TBS_TABLE (93) #include "common/utils/nr/nr_common.h" +#include "openair1/PHY/defs_nr_common.h" #include //Table 5.1.2.2-2 @@ -64,7 +65,7 @@ uint32_t nr_compute_tbs(uint16_t Qm, uint32_t nr_tbs=0; uint32_t Np_info, C, n; - if (Ninfo <=3824) { + if (Ninfo <= NR_MAX_PDSCH_TBS) { n = max(3, floor(log2(Ninfo)) - 6); Np_info = max(24, (Ninfo>>n)<>10; - if (Ninfo <=3824) { + if (Ninfo <= NR_MAX_PDSCH_TBS) { n = max(3, floor(log2(Ninfo)) - 6); Np_info = max(24, (Ninfo>>n)< #include @@ -4080,7 +4081,7 @@ void csi_period_offset(NR_CSI_ReportConfig_t *csirep, uint8_t get_BG(uint32_t A, uint16_t R) { float code_rate = (float) R / 10240.0f; - if ((A <=292) || ((A<=3824) && (code_rate <= 0.6667)) || code_rate <= 0.25) + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (code_rate <= 0.6667)) || code_rate <= 0.25) return 2; else return 1; From b07e9f32c4fb732084a9ee8a86c3326ef3324864 Mon Sep 17 00:00:00 2001 From: mir Date: Fri, 22 Sep 2023 17:36:11 +0200 Subject: [PATCH 32/43] Remove return const values --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 4 ++-- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 2 +- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 00fefe3b31..43cb8f850e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -53,7 +53,7 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { +int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { /* we assume that this function is mutex-protected from outside */ const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 692e1b681c..174a50bead 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -39,7 +39,7 @@ //#define SRS_IND_DEBUG -const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) +int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) { /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 15d823aaf2..71b85d6577 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -396,8 +396,8 @@ void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, const NR_UE_UL_BWP_t *ul_bwp, const NR_ServingCellConfigCommon_t *scc); -const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); -const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot); +int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); +int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index be22753026..ce1403ade3 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1226,7 +1226,7 @@ nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager() { } /* returns false in case of error, true if everything ok */ -const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out) +bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out) { nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index f00ab98422..d25f052fe3 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -103,6 +103,6 @@ void nr_pdcp_tick(int frame, int subframe); nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager(); -const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out); +bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out); #endif /* NR_PDCP_OAI_API_H */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 17fa07da7b..f53daf7410 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -1046,7 +1046,7 @@ void nr_rlc_activate_avg_time_to_tx( } /* returns false in case of error, true if everything ok */ -const bool nr_rlc_get_statistics( +bool nr_rlc_get_statistics( int rnti, int srb_flag, int rb_id, diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index feeb371244..53ac1b0a30 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -70,4 +70,4 @@ void nr_rlc_activate_srb0(int rnti, struct gNB_MAC_INST_s *mac, void *rawUE, sdu_size_t sdu_len, void *rawUE)); -const bool nr_rlc_get_statistics(int rnti, int srb_flag, int rb_id, nr_rlc_statistics_t *out); +bool nr_rlc_get_statistics(int rnti, int srb_flag, int rb_id, nr_rlc_statistics_t *out); From 41ea99c5d1077a91bb2debff6b3ed16242b9aad1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 20:18:52 +0200 Subject: [PATCH 33/43] Adapt timing thresholds after merge of !2253 --- ci-scripts/datalog_rt_stats.1x1.60.yaml | 2 +- ci-scripts/datalog_rt_stats.60.2x2.yaml | 2 +- ci-scripts/datalog_rt_stats.default.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index c65c4614d2..dca2b28901 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -15,7 +15,7 @@ Ref : DLSCH encoding : 137.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 210.0 - PUSCH decoding : 210.0 + PUSCH decoding : 2200.0 Schedule Response : 48.0 DL & UL scheduling timing : 13.0 UL Indication : 60.0 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index 50444cc6b0..7d2ea1ef03 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -15,7 +15,7 @@ Ref : DLSCH encoding : 177.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 210.0 - PUSCH decoding : 210.0 + PUSCH decoding : 2200.0 Schedule Response : 111.0 DL & UL scheduling timing : 20.0 UL Indication : 127.0 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 6304404742..bbc5b2d016 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -15,7 +15,7 @@ Ref : DLSCH encoding : 118.0 L1 Rx processing : 305.0 PUSCH inner-receiver : 150.0 - PUSCH decoding : 210.0 + PUSCH decoding : 2200.0 Schedule Response : 30.0 DL & UL scheduling timing : 10.0 UL Indication : 40.0 From 6a076c849039778c3d739c02daeaf551e2983283 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 14:55:58 +0200 Subject: [PATCH 34/43] F1 UE Context Modif Req: Implement DRB Release - Add necessary fields to F1 message - Add F1AP encoding/decoding of UE Ctxt Modif Req DRB Release --- openair2/COMMON/f1ap_messages_types.h | 6 ++++++ openair2/F1AP/f1ap_cu_ue_context_management.c | 6 +++--- openair2/F1AP/f1ap_du_ue_context_management.c | 17 +++++++++++++++++ openair2/RRC/NR/mac_rrc_dl_f1ap.c | 7 +++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index b47a763089..8f8a047ee5 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -301,6 +301,10 @@ typedef struct f1ap_rb_failed_to_be_setup_s { long rb_id; } f1ap_rb_failed_to_be_setup_t; +typedef struct f1ap_drb_to_be_released_t { + long rb_id; +} f1ap_drb_to_be_released_t; + typedef struct cu_to_du_rrc_information_s { uint8_t * cG_ConfigInfo; uint32_t cG_ConfigInfo_length; @@ -354,6 +358,8 @@ typedef struct f1ap_ue_context_setup_s { f1ap_srb_to_be_setup_t *srbs_to_be_setup; uint8_t srbs_to_be_setup_length; uint8_t srbs_failed_to_be_setup_length; + uint8_t drbs_to_be_released_length; + f1ap_drb_to_be_released_t *drbs_to_be_released; f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup; ReconfigurationCompl_t ReconfigComplOutcome; uint8_t *rrc_container; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 9e9a85d9e5..32f95333bb 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -1531,14 +1531,14 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context } /* optional */ - if(0){ + if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) { /* c15. DRBs_ToBeReleased_List */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; ie15->criticality = F1AP_Criticality_reject; ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; - for (int i=0; i<1; i++) { + for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) { // asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list, F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies); @@ -1549,7 +1549,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item= &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; /* dRBID */ - drbs_toBeReleased_item->dRBID = 30L; + drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; } } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index f3ee222bea..74d0c702fe 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -881,6 +881,23 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t } } } + + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, + F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false); + if (ieDrb != NULL) { + f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count; + f1ap_ue_context_modification_req->drbs_to_be_released = + calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t)); + AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released, + "could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n"); + for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) { + F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i]; + DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); + DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); + f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; + } + } + /* RRC Reconfiguration Complete indicator */ F1AP_UEContextModificationRequestIEs_t *ieReconf; F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container, diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 88c5ad125e..6ead51e3da 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -94,6 +94,13 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); } + if (req->drbs_to_be_released_length > 0) { + int n = req->drbs_to_be_released_length; + f1ap_msg->drbs_to_be_released_length = n; + f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released)); + AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n"); + memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released)); + } if (req->rrc_container_length > 0) { f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); From 67eadd4d5343fd9f6f201dadd3cba34604bab64a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 12 Jun 2023 18:08:10 +0200 Subject: [PATCH 35/43] Add newGtpuDeleteOneTunnel() to remove one GTP tunnel --- openair2/F1AP/f1ap_cu_ue_context_management.c | 3 +++ openair2/F1AP/f1ap_du_ue_context_management.c | 1 + openair3/ocp-gtpu/gtp_itf.cpp | 26 +++++++++++++++++++ openair3/ocp-gtpu/gtp_itf.h | 1 + 4 files changed, 31 insertions(+) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 32f95333bb..1fb4981330 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -1550,6 +1550,9 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; /* dRBID */ drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; + newGtpuDeleteOneTunnel(getCxt(instance)->gtpInst, + f1ap_ue_context_modification_req->gNB_CU_ue_id, + f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id); } } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 74d0c702fe..b9d29303f0 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -895,6 +895,7 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; + newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->gNB_DU_ue_id, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id); } } diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index b1920b6522..20e9c8c127 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -803,6 +803,32 @@ int gtpv1u_create_x2u_tunnel( AssertFatal( false, "to be developped\n"); } +int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) +{ + pthread_mutex_lock(&globGtp.gtp_lock); + getInstRetInt(compatInst(instance)); + map::iterator ue_it = inst->ue2te_mapping.find(ue_id); + if (ue_it == inst->ue2te_mapping.end()) { + LOG_E(GTPU, "%s() no such UE %ld\n", __func__, ue_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return !GTPNOK; + } + map::iterator rb_it = ue_it->second.bearers.find(rb_id); + if (rb_it == ue_it->second.bearers.end()) { + LOG_E(GTPU, "%s() UE %ld has no bearer %d, available\n", __func__, ue_id, rb_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return !GTPNOK; + } + int teid = rb_it->second.teid_incoming; + globGtp.te2ue_mapping.erase(teid); + ue_it->second.bearers.erase(rb_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id); + for (auto b: ue_it->second.bearers) + LOG_I(GTPU, "bearer %ld\n", b.first); + return !GTPNOK; +} + int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index d57769c509..7ac025f14a 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -98,6 +98,7 @@ extern "C" { in_addr_t newOutgoingAddr, teid_t newOutgoingTeid); + int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id); int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id); int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id); instance_t gtpv1Init(openAddr_t context); From 51862543e41ebba89f1753e3cdb013f695c48376 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 21:14:04 +0200 Subject: [PATCH 36/43] Rename to nr_pdcp_release_{d,s}rb() for consistency Most functions start with nr_pdcp_*(), so do the same for release. --- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 4 ++-- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h | 4 ++-- openair2/RRC/NR_UE/rrc_UE.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index f19ae36819..5fb33e151e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1081,7 +1081,7 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_release_srb(ue_id_t ue_id, int srb_id) +void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); @@ -1094,7 +1094,7 @@ void nr_release_srb(ue_id_t ue_id, int srb_id) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_release_drb(ue_id_t ue_id, int drb_id) +void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index e6e7ca9273..83afa212a0 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -68,8 +68,8 @@ void nr_pdcp_reestablishment(ue_id_t ue_id); void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering); void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering); -void nr_release_srb(ue_id_t ue_id, int srb_id); -void nr_release_drb(ue_id_t ue_id, int drb_id); +void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id); +void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id); void add_srb(int is_gnb, ue_id_t rntiMaybeUEid, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 17bfc108ea..4482651d4c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1460,7 +1460,7 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB NR_UE_RRC_INST_t *ue_rrc = &NR_UE_rrc_inst[ctxt_pP->module_id]; if (radioBearerConfig->srb3_ToRelease) - nr_release_srb(ctxt_pP->rntiMaybeUEid, 3); + nr_pdcp_release_srb(ctxt_pP->rntiMaybeUEid, 3); uint8_t kRRCenc[16] = {0}; uint8_t kRRCint[16] = {0}; @@ -1514,7 +1514,7 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) { NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt]; if (DRB_id) - nr_release_drb(ctxt_pP->rntiMaybeUEid, *DRB_id); + nr_pdcp_release_drb(ctxt_pP->rntiMaybeUEid, *DRB_id); } } From dc64ac3ab34cdb3a34a0d8ef535bb24a6fe8785f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 21:09:11 +0200 Subject: [PATCH 37/43] Rename nr_rlc_release_entity() for consistency Most functions start with nr_rlc_*(), so do the same for release --- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 04c1186f6e..02002e31c0 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -100,7 +100,7 @@ static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_i } } -void nr_release_rlc_entity(int rnti, logical_chan_id_t channel_id) +void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id) { nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index c40e5c923a..1583d2203b 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -51,7 +51,7 @@ bool nr_rlc_update_rnti(int from_rnti, int to_rnti); /* test function for CI to trigger reestablishments */ void nr_rlc_test_trigger_reestablishment(int rnti); -void nr_release_rlc_entity(int rnti, logical_chan_id_t channel_id); +void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id); void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Config, struct NR_LogicalChannelConfig *lc_Config); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 4482651d4c..a6a0d9dd07 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -759,7 +759,7 @@ void nr_rrc_manage_rlc_bearers(const NR_CellGroupConfig_t *cellGroupConfig, for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i]; AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n"); - nr_release_rlc_entity(rnti, *lcid); + nr_rlc_release_entity(rnti, *lcid); } } From 3b936c9a506f058d6beafcc2e5837de4e6f2eee0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 14:56:13 +0200 Subject: [PATCH 38/43] Handle DRB release at MAC --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 8 ++++ .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 43 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b1b60a9816..b9bb149310 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2750,6 +2750,14 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup); + + /* remove the rlc_BearerToReleaseList, we don't need it anymore */ + if (UE->CellGroup->rlc_BearerToReleaseList != NULL) { + struct NR_CellGroupConfig__rlc_BearerToReleaseList *l = UE->CellGroup->rlc_BearerToReleaseList; + asn_sequence_del(&l->list, l->list.count, /* free */1); + free(UE->CellGroup->rlc_BearerToReleaseList); + UE->CellGroup->rlc_BearerToReleaseList = NULL; + } } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 42803b0ff1..e18c9ea5b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -138,6 +138,42 @@ static int handle_ue_context_drbs_setup(int rnti, return drbs_len; } +static int handle_ue_context_drbs_release(int rnti, + int drbs_len, + const f1ap_drb_to_be_released_t *req_drbs, + NR_CellGroupConfig_t *cellGroupConfig) +{ + DevAssert(req_drbs != NULL && cellGroupConfig != NULL); + + cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList)); + AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n"); + + /* Note: the actual GTP tunnels are already removed in the F1AP message + * decoding */ + for (int i = 0; i < drbs_len; i++) { + const f1ap_drb_to_be_released_t *drb = &req_drbs[i]; + + long lcid = drb->rb_id + 3; /* LCID is DRB + 3 */ + int idx = 0; + while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { + const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx]; + if (bc->logicalChannelIdentity == lcid) + break; + ++idx; + } + if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { + nr_rlc_release_entity(rnti, lcid); + asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); + long *plcid = malloc(sizeof(*plcid)); + AssertFatal(plcid != NULL, "out of memory\n"); + *plcid = lcid; + int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToReleaseList->list, plcid); + DevAssert(ret == 0); + } + } + return drbs_len; +} + static NR_UE_NR_Capability_t *get_ue_nr_cap(int rnti, uint8_t *buf, uint32_t len) { if (buf == NULL || len == 0) @@ -311,6 +347,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) new_CellGroup); } + if (req->drbs_to_be_released_length > 0) { + resp.drbs_to_be_released_length = + handle_ue_context_drbs_release(req->gNB_DU_ue_id, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); + } + if (req->rrc_container != NULL) nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, DCCH, req->rrc_container, req->rrc_container_length); @@ -328,7 +369,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || ue_cap != NULL) { + if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0) { resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); From 203df298a825b84751c0740f97f0d982471d11c4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 14:56:27 +0200 Subject: [PATCH 39/43] Provide possibility to release DRBs in RRC - Currently no fields to store DRB release: need persist in ASN structure - This will be revisited once there is E1 bearer release release --- openair2/RRC/NR/nr_rrc_defs.h | 1 + openair2/RRC/NR/rrc_gNB.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 215fc9851d..c37979598a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -238,6 +238,7 @@ typedef enum { typedef struct gNB_RRC_UE_s { drb_t established_drbs[MAX_DRBS_PER_UE]; uint8_t DRB_active[MAX_DRBS_PER_UE]; + NR_DRB_ToReleaseList_t *DRB_ReleaseList; NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity NR_MeasConfig_t *measConfig; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 9160d7213e..df7f71b23b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -672,7 +672,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c xid, SRBs, DRBs, - NULL, + ue_p->DRB_ReleaseList, NULL, NULL, dedicatedNAS_MessageList, @@ -680,6 +680,9 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); freeSRBlist(SRBs); freeDRBlist(DRBs); + ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList); + ue_p->DRB_ReleaseList = NULL; + LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); LOG_D(NR_RRC, "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", From 6a7d7e18441fb92396cfab49fc000917724c3092 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 31 May 2023 15:45:43 +0200 Subject: [PATCH 40/43] Telnet module to manually/release DRBs of UE --- common/utils/telnetsrv/CMakeLists.txt | 7 +- common/utils/telnetsrv/telnetsrv_bearer.c | 121 ++++++++++++++++++ openair2/RRC/NR/rrc_gNB.c | 142 ++++++++++++++++++++++ 3 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 common/utils/telnetsrv/telnetsrv_bearer.c diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index d310e1162c..d7b9b3cf9d 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -59,8 +59,13 @@ add_library(telnetsrv_ci MODULE telnetsrv_ci.c) target_link_libraries(telnetsrv_ci PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_dependencies(telnetsrv telnetsrv_ci) +message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so") +add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c) +target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +add_dependencies(telnetsrv telnetsrv_bearer) + # all libraries should be written to root build dir -set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci +set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../.. ) diff --git a/common/utils/telnetsrv/telnetsrv_bearer.c b/common/utils/telnetsrv/telnetsrv_bearer.c new file mode 100644 index 0000000000..f019d3d48b --- /dev/null +++ b/common/utils/telnetsrv/telnetsrv_bearer.c @@ -0,0 +1,121 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "openair2/RRC/NR/rrc_gNB_UE_context.h" + +#define TELNETSERVERCODE +#include "telnetsrv.h" + +#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0) + +static int get_single_ue_rnti(void) +{ + rrc_gNB_ue_context_t *ue_context_p = NULL; + RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) { + return ue_context_p->ue_context.rnti; + } + return -1; +} + +int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (buf) + ERROR_MSG_RET("no parameter allowed\n"); + + int rnti = get_single_ue_rnti(); + if (rnti < 1) + ERROR_MSG_RET("different number of UEs\n"); + + prnt("single UE RNTI %04x\n", rnti); + return 0; +} + +void rrc_gNB_trigger_new_bearer(int rnti); +int add_bearer(char *buf, int debug, telnet_printfunc_t prnt) +{ + int rnti = -1; + if (!buf) { + rnti = get_single_ue_rnti(); + if (rnti < 1) + ERROR_MSG_RET("no UE found\n"); + } else { + rnti = strtol(buf, NULL, 16); + if (rnti < 1 || rnti >= 0xfffe) + ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n"); + } + + // verify it exists in RRC as well + rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti); + if (!rrcue) + ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti); + + rrc_gNB_trigger_new_bearer(rnti); + prnt("called rrc_gNB_trigger_new_bearer(%04x)\n", rnti); + return 0; +} + +void rrc_gNB_trigger_release_bearer(int rnti); +int release_bearer(char *buf, int debug, telnet_printfunc_t prnt) +{ + int rnti = -1; + if (!buf) { + rnti = get_single_ue_rnti(); + if (rnti < 1) + ERROR_MSG_RET("no UE found\n"); + } else { + rnti = strtol(buf, NULL, 16); + if (rnti < 1 || rnti >= 0xfffe) + ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n"); + } + + // verify it exists in RRC as well + rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti); + if (!rrcue) + ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti); + + rrc_gNB_trigger_release_bearer(rnti); + prnt("called rrc_gNB_trigger_release_bearer(%04x)\n", rnti); + return 0; +} + +static telnetshell_cmddef_t bearercmds[] = { + {"get_single_rnti", "", get_single_rnti}, + {"add_bearer", "[rnti(hex,opt)]", add_bearer}, + {"release_bearer", "[rnti(hex,opt)]", release_bearer}, + {"", "", NULL}, +}; + +static telnetshell_vardef_t bearervars[] = { + + {"", 0, 0, NULL} +}; + +void add_bearer_cmds(void) { + add_telnetcmd("bearer", bearervars, bearercmds); +} diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index df7f71b23b..a4809f3852 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -46,6 +46,7 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/utils/LOG/log.h" #include "RRC/NR/MESSAGES/asn1_msg.h" +#include "openair2/E1AP/e1ap_asnc.h" #include "NR_BCCH-BCH-Message.h" #include "NR_UL-DCCH-Message.h" @@ -2858,6 +2859,147 @@ rrc_gNB_generate_RRCRelease( /* UE will be freed after UE context release complete */ } +void rrc_gNB_trigger_new_bearer(int rnti) +{ + /* get RRC and UE */ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti); + if (ue_context_p == NULL) { + LOG_E(RRC, "unknown UE RNTI %04x\n", rnti); + return; + } + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; + + /* get the existing PDU sessoin */ + if (ue->nb_of_pdusessions < 1) { + LOG_E(RRC, "no PDU session set up yet, cannot create additional bearer\n"); + return; + } + + if (ue->established_drbs[0].status != DRB_INACTIVE + && ue->established_drbs[1].status != DRB_INACTIVE) { + LOG_E(RRC, "already have two established bearers, aborting\n"); + return; + } + + e1ap_bearer_setup_req_t bearer_req = {0}; + bearer_req.gNB_cu_cp_ue_id = ue->rrc_ue_id; + bearer_req.cipheringAlgorithm = ue->ciphering_algorithm; + memcpy(bearer_req.encryptionKey, ue->kgnb, sizeof(ue->kgnb)); + bearer_req.integrityProtectionAlgorithm = ue->integrity_algorithm; + memcpy(bearer_req.integrityProtectionKey, ue->kgnb, sizeof(ue->kgnb)); + bearer_req.ueDlAggMaxBitRate = 10000; /* probably does not matter */ + + pdu_session_to_setup_t *pdu = &bearer_req.pduSession[0]; + //bearer_req.numPDUSessions++; + bearer_req.numPDUSessions = 1; + //pdu->sessionId = session->pdusession_id; + //pdu->sst = msg->allowed_nssai[i].sST; + //pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed; + + //pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed; + //pdu->teId = session->gtp_teid; + pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding + DRB_nGRAN_to_setup_t *drb = &pdu->DRBnGRanList[0]; + int drb_id = 2; + drb->id = drb_id; + + drb->defaultDRB = E1AP_DefaultDRB_false; + drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap); + drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap); + + drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18; + drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18; + + drb->discardTimer = E1AP_DiscardTimer_infinity; + drb->reorderingTimer = E1AP_T_Reordering_ms0; + + drb->rLC_Mode = E1AP_RLC_Mode_rlc_am; + + drb->numCellGroups = 1; // assume one cell group associated with a DRB + + for (int k=0; k < drb->numCellGroups; k++) { + cell_group_t *cellGroup = drb->cellGroupList + k; + cellGroup->id = 0; // MCG + } + + int xid = rrc_gNB_get_next_transaction_identifier(0); + /* generate a new bearer, it will be put into internal RRC state and picked + * up later */ + generateDRB(ue, + drb_id, + &ue->pduSession[0], + rrc->configuration.enable_sdap, + rrc->security.do_drb_integrity, + rrc->security.do_drb_ciphering); + + /* associate the new bearer to it */ + ue->xids[xid] = RRC_PDUSESSION_MODIFY; + ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session + LOG_W(RRC, "trigger new bearer %ld for UE %04x xid %d\n", drb->id, ue->rnti, xid); + rrc->cucp_cuup.bearer_context_setup(&bearer_req, 0); +} + +void rrc_gNB_trigger_release_bearer(int rnti) +{ + /* get RRC and UE */ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti); + if (ue_context_p == NULL) { + LOG_E(RRC, "unknown UE RNTI %04x\n", rnti); + return; + } + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; + + if (ue->established_drbs[1].status == DRB_INACTIVE) { + LOG_E(RRC, "no second bearer, aborting\n"); + return; + } + + // don't use E1: bearer release is not implemented, call directly + // into PDCP/SDAP and then send corresponding message via F1 + + int drb_id = 2; + ue->established_drbs[1].status = DRB_INACTIVE; + ue->DRB_ReleaseList = calloc(1, sizeof(*ue->DRB_ReleaseList)); + AssertFatal(ue->DRB_ReleaseList != NULL, "out of memory\n"); + NR_DRB_Identity_t *asn1_drb = malloc(sizeof(*asn1_drb)); + AssertFatal(asn1_drb != NULL, "out of memory\n"); + int idx = 0; + NR_DRB_ToAddModList_t *drb_list = createDRBlist(ue, false); + while (idx < drb_list->list.count) { + const NR_DRB_ToAddMod_t *drbc = drb_list->list.array[idx]; + if (drbc->drb_Identity == drb_id) + break; + ++idx; + } + if (idx < drb_list->list.count) { + nr_pdcp_release_drb(rnti, drb_id); + asn_sequence_del(&drb_list->list, idx, 1); + } + *asn1_drb = drb_id; + asn1cSeqAdd(&ue->DRB_ReleaseList->list, asn1_drb); + + f1ap_drb_to_be_released_t drbs_to_be_released[1] = {{.rb_id = drb_id}}; + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id); + f1ap_ue_context_modif_req_t ue_context_modif_req = { + .gNB_CU_ue_id = ue->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .plmn.mcc = rrc->configuration.mcc[0], + .plmn.mnc = rrc->configuration.mnc[0], + .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, /* TODO: correct value? */ + .srbs_to_be_setup_length = 0, + .srbs_to_be_setup = NULL, + .drbs_to_be_setup_length = 0, + .drbs_to_be_setup = NULL, + .drbs_to_be_released_length = 1, + .drbs_to_be_released = drbs_to_be_released, + }; + rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req); +} + int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t instance, uint8_t CC_id){ const unsigned int Ttab[4] = {32,64,128,256}; uint8_t Tc; From c6e9992e81ca77f5eba49f4921927d05ed2328c8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Sep 2023 14:55:05 +0200 Subject: [PATCH 41/43] Make LCID output nicer --- openair2/LAYER2/NR_MAC_gNB/main.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 14c75deb26..5aa4f10a8c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -166,21 +166,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset UE->rnti, stats->ulsch_total_bytes_scheduled, stats->ul.total_bytes); - for (int lc_id = 0; lc_id < 63; lc_id++) { - if (stats->dl.lc_bytes[lc_id] > 0) - output += snprintf(output, - end - output, - "UE %04x: LCID %d: %"PRIu64" bytes TX\n", - UE->rnti, - lc_id, - stats->dl.lc_bytes[lc_id]); - if (stats->ul.lc_bytes[lc_id] > 0) - output += snprintf(output, - end - output, - "UE %04x: LCID %d: %"PRIu64" bytes RX\n", - UE->rnti, - lc_id, - stats->ul.lc_bytes[lc_id]); + for (int i = 0; i < sched_ctrl->dl_lc_num; i++) { + int lc_id = sched_ctrl->dl_lc_ids[i]; + output += snprintf(output, + end - output, + "UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n", + UE->rnti, + lc_id, + stats->dl.lc_bytes[lc_id], + stats->ul.lc_bytes[lc_id]); } } NR_SCHED_UNLOCK(&gNB->UE_info.mutex); From 2eaac0351dc943e0f0e2e66cbd75a996a12a308f Mon Sep 17 00:00:00 2001 From: Teodora Date: Tue, 26 Sep 2023 18:13:01 +0200 Subject: [PATCH 42/43] Fix compile error when --build-e2 option included - modify byte_array.h in order to avoid conflict for same file names --- common/utils/ds/byte_array.c | 17 +++++++++++++++++ common/utils/ds/byte_array.h | 8 ++++++-- executables/nr-softmodem.c | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/common/utils/ds/byte_array.c b/common/utils/ds/byte_array.c index dfc8872662..c3281ffa27 100644 --- a/common/utils/ds/byte_array.c +++ b/common/utils/ds/byte_array.c @@ -22,6 +22,7 @@ #include "byte_array.h" #include "common/utils/assertions.h" +#include #include byte_array_t copy_byte_array(byte_array_t src) @@ -56,3 +57,19 @@ bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1) return true; } + +byte_array_t cp_str_to_ba(const char* str) +{ + assert(str != NULL); + + const size_t sz = strlen(str); + + byte_array_t dst = {.len = sz}; + + dst.buf = calloc(sz,sizeof(uint8_t)); + assert(dst.buf != NULL && "Memory exhausted"); + + memcpy(dst.buf, str, sz); + + return dst; +} diff --git a/common/utils/ds/byte_array.h b/common/utils/ds/byte_array.h index f16fd7c01d..236f3e683f 100644 --- a/common/utils/ds/byte_array.h +++ b/common/utils/ds/byte_array.h @@ -19,8 +19,10 @@ * contact@openairinterface.org */ -#ifndef BYTE_ARRAY_H_OAI -#define BYTE_ARRAY_H_OAI +#ifndef BYTE_ARRAY_H +#define BYTE_ARRAY_H + +/* WARNING: This file is also defined at XXXXX. Both files need to be completely equal. Same applies for *.c */ #include #include @@ -39,4 +41,6 @@ byte_array_t copy_byte_array(byte_array_t src); void free_byte_array(byte_array_t ba); bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1); +byte_array_t cp_str_to_ba(const char* str); + #endif diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 8bffda8f61..31bde16b97 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -709,7 +709,7 @@ int main( int argc, char **argv ) { const int mcc = rrc->configuration.mcc[0]; const int mnc = rrc->configuration.mnc[0]; const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; - const ngran_node_t node_type = rrc->node_type; + // const ngran_node_t node_type = rrc->node_type; int nb_id = 0; int cu_du_id = 0; if (node_type == ngran_gNB) { From f3910e77076caa902ba3a29fef98b533b20f1111 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 3 Oct 2023 10:41:24 +0200 Subject: [PATCH 43/43] MeasConfig: give SSB ARFCN, not Point A The UE should measure on the SSB, otherwise it does not see anything. Hence, this commit fixes the meas-config to request the UE to measure on the right frequency. --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 4 ++-- openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 4f042d4f05..2e3e00f12d 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1125,7 +1125,7 @@ int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t r return((enc_rval.encoded+7)/8); } -NR_MeasConfig_t *get_defaultMeasConfig(int arfcn, int band, int scs) +NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs) { NR_MeasConfig_t *mc = calloc(1, sizeof(*mc)); mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList)); @@ -1137,7 +1137,7 @@ NR_MeasConfig_t *get_defaultMeasConfig(int arfcn, int band, int scs) mo1->measObjectId = 1; mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR; NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1)); - asn1cCallocOne(monr1->ssbFrequency, arfcn); + asn1cCallocOne(monr1->ssbFrequency, ssb_arfcn); asn1cCallocOne(monr1->ssbSubcarrierSpacing, scs); monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility)); monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 5dcff1501a..5bd932ffd4 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -150,7 +150,7 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP, int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier); -NR_MeasConfig_t *get_defaultMeasConfig(int absFreqSSB, int band, int scs); +NR_MeasConfig_t *get_defaultMeasConfig(uint32_t absFreqSSB, int band, int scs); void free_defaultMeasConfig(NR_MeasConfig_t *mc); uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a4809f3852..e5dcc79dfd 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -559,8 +559,8 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); - int arfcn = get_dl_arfcn(cell_info); - NR_MeasConfig_t *measconfig = get_defaultMeasConfig(arfcn, band, scs); + uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1); + NR_MeasConfig_t *measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs); uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ue_p,