From ae690217dd51a37b76fc0ee9e2433a0324c6b211 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Wed, 9 Apr 2025 11:05:54 -0400 Subject: [PATCH] Clean-up nr_slot_fep 1.Create new funtion nr_symbol_fep() to do OFDM demod of one symbol on all antennas. This is called by nr_slot_fep() for now. In the upcoming MR, this function will be called directly after reading each OFDM symbol from the radio. 2.Removed redundant memory alignment. DFT function performs memory alignment if the input memory is not aligned. --- executables/nr-gnb.c | 16 +- openair1/PHY/MODULATION/nr_modulation.h | 14 +- openair1/PHY/MODULATION/slot_fep_nr.c | 193 +++++++++++++----------- openair1/SIMULATION/NR_PHY/ulsim.c | 16 +- 4 files changed, 123 insertions(+), 116 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 505adf825c..a63c7984fb 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -193,14 +193,14 @@ static void rx_func(processingData_L1_t *info) int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; for (int bb = 0; bb < gNB->common_vars.num_beams_period; bb++) { for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { - apply_nr_rotation_RX(&gNB->frame_parms, - gNB->common_vars.rxdataF[bb][aa], - gNB->frame_parms.symbol_rotation[1], - slot_rx, - gNB->frame_parms.N_RB_UL, - soffset, - 0, - gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); + const uint max_symb = (gNB->frame_parms.Ncp == EXTENDED) ? 12 : 14; + for (int sym = 0; sym < max_symb; sym++) + apply_nr_rotation_symbol_RX(&gNB->frame_parms, + gNB->common_vars.rxdataF[bb][aa] + soffset + sym * gNB->frame_parms.ofdm_symbol_size, + gNB->frame_parms.symbol_rotation[1], + gNB->frame_parms.N_RB_UL, + slot_rx, + sym); } } } diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 64886a2809..996a66b343 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -117,14 +117,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp); -void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms, - c16_t *rxdataF, - const c16_t *rot, - int slot, - int nb_rb, - int soffset, - int first_symbol, - int nsymb); +void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxdataF, + const c16_t *rot, + int nb_rb, + int slot, + int symbol); /*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5 @param[in] datatx_F_precoding, Pointer to n_layers*re data array diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index cad3f92c33..50e19d8563 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -28,6 +28,36 @@ #include "PHY/nr_phy_common/inc/nr_phy_common.h" #include +/* rxdataF should be 16 bytes aligned */ +void nr_symbol_fep(const NR_DL_FRAME_PARMS *frame_parms, + const int slot, + const unsigned char symbol, + const int link_type, + c16_t *rxdata[frame_parms->nb_antennas_rx], + c16_t *rxdataF[frame_parms->nb_antennas_rx], + time_stats_t* dft_stats) +{ + AssertFatal(symbol < frame_parms->symbols_per_slot, + "slot_fep: symbol must be between 0 and %d\n", + frame_parms->symbols_per_slot - 1); + AssertFatal(slot < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1); + + dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size); + for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + if (dft_stats) start_meas(dft_stats); + dft(dftsize, (int16_t *)rxdata[aa], (int16_t *)rxdataF[aa], 1); + if (dft_stats) stop_meas(dft_stats); + + const bool is_sl = (link_type == link_type_sl); + apply_nr_rotation_symbol_RX(frame_parms, + rxdataF[aa], + frame_parms->symbol_rotation[link_type], + is_sl ? frame_parms->N_RB_SL : frame_parms->N_RB_DL, + slot, + symbol); + } +} + int nr_slot_fep(PHY_VARS_NR_UE *ue, const NR_DL_FRAME_PARMS *frame_parms, unsigned int slot, @@ -37,35 +67,23 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, uint32_t sample_offset, c16_t **rxdata) { - AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(symbol < frame_parms->symbols_per_slot, + "slot_fep: symbol must be between 0 and %d\n", + frame_parms->symbols_per_slot - 1); AssertFatal(slot < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1); - bool is_sl = (linktype == link_type_sl) ? true : false; + bool is_sl = (linktype == link_type_sl); bool is_synchronized = (ue) ? ue->is_synchronized : false; - unsigned int nb_prefix_samples; - unsigned int nb_prefix_samples0; + unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples; + unsigned int nb_prefix_samples0 = (is_synchronized || is_sl) ? frame_parms->nb_prefix_samples0 : nb_prefix_samples; + // For Sidelink 16 frames worth of samples is processed to find SSB, for 5G-NR 2. - unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame; - - int N_RB = (is_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_DL; - - if (is_synchronized || is_sl) { - nb_prefix_samples = frame_parms->nb_prefix_samples; - nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - } else { - nb_prefix_samples = frame_parms->nb_prefix_samples; - nb_prefix_samples0 = frame_parms->nb_prefix_samples; - AssertFatal(slot == 0, "Slot should be 0\n"); - } - - dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size); - // This is for misalignment issues - c16_t tmp_dft_in[frame_parms->ofdm_symbol_size] __attribute__ ((aligned (32))); + const unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame; unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); - unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol; + const unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol; for (int idx_symb = slot * frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) - rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += (idx_symb % (0x7 << frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; rx_offset += frame_parms->ofdm_symbol_size * symbol; rx_offset += sample_offset; @@ -73,48 +91,47 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, // use OFDM symbol from within 1/8th of the CP to avoid ISI rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); - rx_offset %= total_samples; - - for (unsigned char aa=0; aanb_antennas_rx; aa++) { - c16_t *rxdata_ptr = &rxdata[aa][rx_offset]; + LOG_D(PHY, + "slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n", + slot, + symbol, + nb_prefix_samples, + nb_prefix_samples0, + rx_offset, + dB_fixed(signal_energy((int32_t *)&rxdata[0][rx_offset], frame_parms->ofdm_symbol_size))); + c16_t tmp_dft_in[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + c16_t *rxdata_symb_ptr[frame_parms->nb_antennas_rx]; + c16_t *rxdataF_symb_ptr[frame_parms->nb_antennas_rx]; + for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + rxdataF_symb_ptr[aa] = &rxdataF[aa][frame_parms->ofdm_symbol_size * symbol]; // This happens only during initial sync if (rx_offset + frame_parms->ofdm_symbol_size > total_samples) { - // rxdata is 2 frames len // we have to wrap on the end - - memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], (total_samples - rx_offset) * sizeof(int32_t)); - memcpy((void *)&tmp_dft_in[total_samples - rx_offset], - (void *)&rxdata[aa][0], + memcpy(&tmp_dft_in[aa][0], &rxdata[aa][rx_offset], (total_samples - rx_offset) * sizeof(int32_t)); + memcpy(&tmp_dft_in[aa][total_samples - rx_offset], + &rxdata[aa][0], (frame_parms->ofdm_symbol_size - (total_samples - rx_offset)) * sizeof(int32_t)); - rxdata_ptr = tmp_dft_in; - - } else if ((rx_offset & 7) != 0) { // if input to dft is not 256-bit aligned - memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size * sizeof(int32_t)); - rxdata_ptr = tmp_dft_in; + rxdata_symb_ptr[aa] = tmp_dft_in[aa]; + } else { + rxdata_symb_ptr[aa] = &rxdata[aa][rx_offset]; } if (ue && ue->cont_fo_comp) { start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); - nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, rxdata_ptr, tmp_dft_in, frame_parms->ofdm_symbol_size); - rxdata_ptr = tmp_dft_in; + nr_fo_compensation(ue->freq_offset, + frame_parms->samples_per_subframe, + rx_offset, + rxdata_symb_ptr[aa], + tmp_dft_in[aa], + frame_parms->ofdm_symbol_size); stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); + rxdata_symb_ptr[aa] = tmp_dft_in[aa]; } - - if (ue) - start_meas_nr_ue_phy(ue, RX_DFT_STATS); - - dft(dftsize, - (int16_t *)rxdata_ptr, - (int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - 1); - - if (ue) - stop_meas_nr_ue_phy(ue, RX_DFT_STATS); - - apply_nr_rotation_RX(frame_parms, rxdataF[aa], frame_parms->symbol_rotation[linktype], slot, N_RB, 0, symbol, 1); } - + time_stats_t* dft_stats = NULL; + if (ue) dft_stats = &ue->phy_cpu_stats.cpu_time_stats[RX_DFT_STATS]; + nr_symbol_fep(frame_parms, slot, symbol, linktype, rxdata_symb_ptr, rxdataF_symb_ptr, dft_stats); return 0; } @@ -177,54 +194,46 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, return 0; } -void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms, - c16_t *rxdataF, - const c16_t *rot, - int slot, - int nb_rb, - int soffset, - int first_symbol, - int nsymb) +void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxdataF, + const c16_t *rot, + int nb_rb, + int slot, + int symbol) { - AssertFatal(first_symbol + nsymb <= NR_NUMBER_OF_SYMBOLS_PER_SLOT, - "First symbol %d and number of symbol %d not compatible with number of symbols in a slot %d\n", - first_symbol, nsymb, NR_NUMBER_OF_SYMBOLS_PER_SLOT); - int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; + const int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; - for (int symbol = first_symbol; symbol < first_symbol + nsymb; symbol++) { - - c16_t rot2 = rot[symbol + symb_offset]; - rot2.i = -rot2.i; - LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i); - const c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; - c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)]; + c16_t rot2 = rot[symbol + symb_offset]; + rot2.i = -rot2.i; + LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i); + const c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; + c16_t *this_symbol = rxdataF; - if (nb_rb & 1) { - rotate_cpx_vector(this_symbol, &rot2, this_symbol, - (nb_rb + 1) * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, - &rot2, - this_symbol + frame_parms->first_carrier_offset - 6, - (nb_rb + 1) * 6, 15); - mult_cpx_vector(this_symbol, shift_rot, this_symbol, (nb_rb + 1) * 6, 15); - mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, - shift_rot + frame_parms->first_carrier_offset - 6, + if (nb_rb & 1) { + rotate_cpx_vector(this_symbol, &rot2, this_symbol, (nb_rb + 1) * 6, 15); + rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, + &rot2, this_symbol + frame_parms->first_carrier_offset - 6, (nb_rb + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, &rot2, this_symbol, - nb_rb * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, - &rot2, - this_symbol + frame_parms->first_carrier_offset, - nb_rb * 6, 15); - mult_cpx_vector(this_symbol, shift_rot, this_symbol, nb_rb * 6, 15); - mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset, - shift_rot + frame_parms->first_carrier_offset, + mult_cpx_vector(this_symbol, shift_rot, this_symbol, (nb_rb + 1) * 6, 15); + mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, + shift_rot + frame_parms->first_carrier_offset - 6, + this_symbol + frame_parms->first_carrier_offset - 6, + (nb_rb + 1) * 6, + 15); + } else { + rotate_cpx_vector(this_symbol, &rot2, this_symbol, nb_rb * 6, 15); + rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, + &rot2, this_symbol + frame_parms->first_carrier_offset, nb_rb * 6, 15); - } + mult_cpx_vector(this_symbol, shift_rot, this_symbol, nb_rb * 6, 15); + mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset, + shift_rot + frame_parms->first_carrier_offset, + this_symbol + frame_parms->first_carrier_offset, + nb_rb * 6, + 15); } } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index c4b2f854c2..b7f93cdf3a 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1468,14 +1468,14 @@ int main(int argc, char *argv[]) } int offset = (slot & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { - apply_nr_rotation_RX(&gNB->frame_parms, - gNB->common_vars.rxdataF[0][aa], - gNB->frame_parms.symbol_rotation[1], - slot, - gNB->frame_parms.N_RB_UL, - offset, - 0, - gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); + const unsigned int max_symb = (gNB->frame_parms.Ncp == EXTENDED) ? 12 : 14; + for (int sym = 0; sym < max_symb; sym++) + apply_nr_rotation_symbol_RX(&gNB->frame_parms, + gNB->common_vars.rxdataF[0][aa] + offset + sym * gNB->frame_parms.ofdm_symbol_size, + gNB->frame_parms.symbol_rotation[1], + gNB->frame_parms.N_RB_UL, + slot, + sym); } ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO);