From 0161a1c4fd39b41d9fb2de01187cecf1028ed500 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 20 Dec 2024 20:15:05 +0100 Subject: [PATCH] Optimization for unused symbols in NR UE After processing TX frequency domain data skip IFFT call for symbols that aren't used, the time domain buffer is memset instead. --- common/utils/nr/nr_common.h | 1 + openair1/PHY/MODULATION/modulation_common.h | 7 ++- openair1/PHY/MODULATION/ofdm_mod.c | 62 +++++++++++++------ .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 6 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 53 ++++++++++------ .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.c | 13 +++- .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.h | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 10 +-- .../SCHED_NR_UE/phy_procedures_nr_ue_sl.c | 5 +- openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 11 +++- openair1/SCHED_NR_UE/pucch_uci_ue_nr.h | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 7 ++- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- 13 files changed, 129 insertions(+), 52 deletions(-) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 4c1dfb619d..fdb3cc7ffc 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -84,6 +84,7 @@ static inline const char *rnti_types(nr_rnti_type_t rr) #define MU_SCS(m) (15 << m) #define MAX_GSCN_BAND 620 // n78 has the highest GSCN range of 619 #define NR_NUMBER_OF_SYMBOLS_PER_SLOT 14 +#define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12 #define NR_MAX_NB_LAYERS 4 // 8 // Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when diff --git a/openair1/PHY/MODULATION/modulation_common.h b/openair1/PHY/MODULATION/modulation_common.h index df521b10da..2973c36257 100644 --- a/openair1/PHY/MODULATION/modulation_common.h +++ b/openair1/PHY/MODULATION/modulation_common.h @@ -48,7 +48,12 @@ void PHY_ofdm_mod(const int *input, void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms); -void nr_normal_prefix_mod(c16_t *txdataF, c16_t *txdata, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot); +void nr_normal_prefix_mod(c16_t *txdataF, + c16_t *txdata, + uint8_t nsymb, + const NR_DL_FRAME_PARMS *frame_parms, + uint32_t slot, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms); diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index e25f7cd7f2..6cc8cbe7c5 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -67,31 +67,55 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA } -void nr_normal_prefix_mod(c16_t *txdataF, c16_t *txdata, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot) +void nr_normal_prefix_mod(c16_t *txdataF, + c16_t *txdata, + uint8_t nsymb, + const NR_DL_FRAME_PARMS *frame_parms, + uint32_t slot, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) { // This function works only slot wise. For more generic symbol generation refer nr_feptx0() if (frame_parms->numerology_index != 0) { // case where numerology != 0 if (!(slot%(frame_parms->slots_per_subframe/2))) { - PHY_ofdm_mod((int *)txdataF, - (int *)txdata, - frame_parms->ofdm_symbol_size, - 1, - frame_parms->nb_prefix_samples0, - CYCLIC_PREFIX); - PHY_ofdm_mod((int *)txdataF + frame_parms->ofdm_symbol_size, - (int *)txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, - frame_parms->ofdm_symbol_size, - nsymb - 1, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); + if (was_symbol_used[0]) { + PHY_ofdm_mod((int *)txdataF, + (int *)txdata, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + } else { + memset(txdata, 0, (frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size) * sizeof(c16_t)); + } + for (int i = 1; i < nsymb; i++) { + c16_t* tx_data_ptr = txdata + (i - 1) * (frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples) + + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0; + if (was_symbol_used[i]) { + PHY_ofdm_mod((int *)txdataF + frame_parms->ofdm_symbol_size * i, + (int *)tx_data_ptr, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { + memset(tx_data_ptr, 0, (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * sizeof(c16_t)); + } + } } else { - PHY_ofdm_mod((int *)txdataF, - (int *)txdata, - frame_parms->ofdm_symbol_size, - nsymb, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); + for (int i = 0; i < nsymb; i++) { + c16_t* tx_data_ptr = txdata + i * (frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); + if (was_symbol_used[i]) { + PHY_ofdm_mod((int *)txdataF + frame_parms->ofdm_symbol_size * i, + (int *)tx_data_ptr, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { + memset(tx_data_ptr, 0, (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * sizeof(c16_t)); + } + } } } else { // numerology = 0, longer CP for every 7th symbol diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index bb1a6c03df..dc075753ef 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -144,7 +144,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint32_t frame, const uint8_t slot, nr_phy_data_tx_t *phy_data, - c16_t **txdataF); + c16_t **txdataF, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); /** \brief This function does IFFT for PUSCH */ @@ -154,7 +155,8 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *frame_parms, const uint8_t n_antenna_ports, c16_t **txdataF, - uint32_t linktype); + uint32_t linktype, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); void clean_UE_harq(PHY_VARS_NR_UE *UE); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 646ac2dd94..bd4ea90df8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -465,7 +465,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint32_t frame, const uint8_t slot, nr_phy_data_tx_t *phy_data, - c16_t **txdataF) + c16_t **txdataF, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) { int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; @@ -500,6 +501,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint16_t rnti = pusch_pdu->rnti; for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) { + was_symbol_used[i] = true; if ((ul_dmrs_symb_pos >> i) & 0x01) number_dmrs_symbols += 1; } @@ -831,37 +833,52 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *frame_parms, const uint8_t n_antenna_ports, c16_t **txdataF, - uint32_t linktype) + uint32_t linktype, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) { const int tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); int N_RB = (linktype == link_type_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_UL; c16_t **txdata = UE->common_vars.txData; - for(int ap = 0; ap < n_antenna_ports; ap++) { - apply_nr_rotation_TX(frame_parms, - txdataF[ap], - frame_parms->symbol_rotation[linktype], - slot, - N_RB, - 0, - NR_NUMBER_OF_SYMBOLS_PER_SLOT); + for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { + if (was_symbol_used[i] == false) + continue; + for(int ap = 0; ap < n_antenna_ports; ap++) { + apply_nr_rotation_TX(frame_parms, + txdataF[ap], + frame_parms->symbol_rotation[linktype], + slot, + N_RB, + i, + 1); + } } + for (int ap = 0; ap < n_antenna_ports; ap++) { if (frame_parms->Ncp == 1) { // extended cyclic prefix - PHY_ofdm_mod((int *)txdataF[ap], - (int *)&txdata[ap][tx_offset], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); + for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP; i++) { + if (was_symbol_used[i] == false) { + memset(&txdata[ap][tx_offset + (frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples) * i], + 0, + (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * sizeof(int32_t)); + continue; + } + PHY_ofdm_mod((int *)&txdataF[ap][frame_parms->ofdm_symbol_size * i], + (int *)&txdata[ap][tx_offset + frame_parms->ofdm_symbol_size * i], + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } } else { // normal cyclic prefix nr_normal_prefix_mod(txdataF[ap], &txdata[ap][tx_offset], - 14, + NR_NUMBER_OF_SYMBOLS_PER_SLOT, frame_parms, - slot); + slot, + was_symbol_used); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c index f362e3f218..17dc69cd4f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c @@ -423,7 +423,10 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, * send srs according to current configuration * *********************************************************************/ -int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF) +int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t **txdataF, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) { if(!ue->srs_vars[0]->active) { return -1; @@ -432,6 +435,14 @@ int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_ nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t*)&ue->srs_vars[0]->srs_config_pdu; + int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position; + // Num consecutive SRS symbols according to 38.211 6.4.1.4.1 + int num_srs_symbols[] = {1, 2, 4, 8, 12}; + int last_srs_symbol = first_srs_symbol + num_srs_symbols[srs_config_pdu->num_symbols] - 1; + for (int i = first_srs_symbol; i <= last_srs_symbol; i++) { + was_symbol_used[i] = true; + } + #ifdef SRS_DEBUG LOG_I(NR_PHY,"Frame = %i, slot = %i\n", proc->frame_tx, proc->nr_slot_tx); LOG_I(NR_PHY,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h index dba339d14b..fc785c7aec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h @@ -79,6 +79,6 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, @param current gNB_id identifier @returns 0 if srs is transmitted -1 otherwise */ -int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF); +int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, bool was_symbol_used[14]); #endif /* SRS_MODULATION_NR_H */ diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 283673a6df..37593bb9a7 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -284,14 +284,15 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n txdataF[i] = &txdataF_buf[i * samplesF_per_slot]; LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; start_meas_nr_ue_phy(ue, PHY_PROC_TX); - nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF); + nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used); - ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF); + ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, was_symbol_used); - pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF); + pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used); LOG_D(PHY, "Sending Uplink data \n"); @@ -304,7 +305,8 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n &ue->frame_parms, ue->frame_parms.nb_antennas_tx, (c16_t **)txdataF, - link_type_ul); + link_type_ul, + was_symbol_used); stop_meas_nr_ue_phy(ue, OFDM_MOD_STATS); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index 5a7e9dddac..19a4449c11 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -308,9 +308,12 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc tx_action = 1; } + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]; + for (int i = 0; i < 14; i++) + was_symbol_used[i] = true; if (tx_action) { LOG_D(NR_PHY, "Sending Uplink data \n"); - nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, fp, fp->nb_antennas_tx, txdataF, link_type_sl); + nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, fp, fp->nb_antennas_tx, txdataF, link_type_sl, was_symbol_used); } LOG_D(NR_PHY, "****** end Sidelink TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index ef83d8013b..03c14af9b9 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -132,8 +132,11 @@ binary_search_float_nr( * TS 38.213 9 UE procedure for reporting control information * *********************************************************************/ - -void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txdataF) +void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + nr_phy_data_tx_t *phy_data, + c16_t **txdataF, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) { const int nr_slot_tx = proc->nr_slot_tx; NR_UE_PUCCH *pucch_vars = &phy_data->pucch_vars; @@ -141,6 +144,10 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n for (int i=0; i<2; i++) { if(pucch_vars->active[i]) { const fapi_nr_ul_config_pucch_pdu *pucch_pdu = &pucch_vars->pucch_pdu[i]; + for (int symb_idx = 0; symb_idx < pucch_pdu->nr_of_symbols; symb_idx++) { + int symb = pucch_pdu->start_symbol_index + symb_idx; + was_symbol_used[symb] = true; + } uint16_t nb_of_prbs = pucch_pdu->prb_size; /* Generate PUCCH signal according to its format and parameters */ diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h index 6c3cc3abd6..8b6ae46e3e 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h @@ -50,6 +50,6 @@ /*************** FUNCTIONS ****************************************/ -void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txdataF); +void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txdataF, bool was_symbol_used[14]); #endif /* PUCCH_UCI_UE_NR_H */ diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 398923b655..7b1b34c93f 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1091,11 +1091,16 @@ printf("%d\n", slot); frame_parms->nb_prefix_samples, CYCLIC_PREFIX); } else { + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]; + for (int i = 0; i < 14; i++) { + was_symbol_used[i] = true; + } nr_normal_prefix_mod(&gNB->common_vars.txdataF[0][aa][txdataF_offset], &txdata[aa][slot_offset], 14, frame_parms, - slot); + slot, + was_symbol_used); } } if (n_trials==1) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 1b26869568..599efbbd6b 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1525,7 +1525,7 @@ int main(int argc, char *argv[]) printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); printf("\nUE TX\n"); - for (int i = PHY_PROC_TX; i <= ULSCH_ENCODING_STATS; i++) { + for (int i = PHY_PROC_TX; i <= OFDM_MOD_STATS; i++) { printStatIndent(&UE->phy_cpu_stats.cpu_time_stats[i], UE->phy_cpu_stats.cpu_time_stats[i].meas_name); } printStatIndent(&gNB->rx_srs_stats,"RX SRS time");