From cffb07d798c3b3d466d269cd6d0ecd0d2d2296d0 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 14 Aug 2025 15:17:13 +0200 Subject: [PATCH] remove permanent prach rxsigF in gNB and simplify the data structure --- executables/nr-gnb.c | 3 +- openair1/PHY/INIT/nr_init.c | 8 ++--- openair1/PHY/INIT/nr_init_ru.c | 8 ++--- openair1/PHY/NR_TRANSPORT/nr_prach.c | 28 ++++++++------- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 3 +- openair1/PHY/defs_RU.h | 2 +- openair1/PHY/defs_gNB.h | 10 +----- openair1/SCHED_NR/nr_prach_procedures.c | 17 ++++----- openair1/SIMULATION/NR_PHY/prachsim.c | 36 ++++++++++--------- 9 files changed, 51 insertions(+), 64 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 16ad366a0e..0e4fba9812 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -389,8 +389,7 @@ void init_eNB_afterRU(void) AssertFatal(gNB->RU_list[ru_id]->common.rxdataF != NULL, "RU %d : common.rxdataF is NULL\n", gNB->RU_list[ru_id]->idx); AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF != NULL, "RU %d : prach_rxsigF is NULL\n", gNB->RU_list[ru_id]->idx); for (int i = 0; i < gNB->RU_list[ru_id]->nb_rx; aa++, i++) { - LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa); - gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i]; + LOG_I(PHY, "Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa); for (int b = 0; b < gNB->RU_list[ru_id]->num_beams_period; b++) { int idx = i + b * gNB->RU_list[ru_id]->nb_rx; gNB->common_vars.rxdataF[b][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[idx]; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 75145c78a4..88c539ccd3 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -104,9 +104,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) // shortcuts NR_DL_FRAME_PARMS *const fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - NR_gNB_COMMON *const common_vars = &gNB->common_vars; - NR_gNB_PRACH *const prach_vars = &gNB->prach_vars; - + NR_gNB_COMMON *const common_vars = &gNB->common_vars; common_vars->analog_bf = cfg->analog_beamforming_ve.analog_bf_vendor_ext.value; LOG_I(PHY, "L1 configured with%s analog beamforming\n", common_vars->analog_bf ? "" : "out"); if (common_vars->analog_bf) { @@ -190,9 +188,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) common_vars->debugBuff_sample_offset = 0; // PRACH - prach_vars->rxsigF = (int16_t **)malloc16_clear(Prx * sizeof(int16_t *)); - - init_prach_list(&gNB->prach_vars.list, prach_upper); + init_prach_list(&gNB->prach_list, prach_upper); int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; int n_buf = Prx*max_ul_mimo_layers; diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 6ad085eb4c..d485e4977d 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -116,12 +116,12 @@ void nr_phy_init_RU(RU_t *ru) // AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]), // "nb_antennas_rx too large"); for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) { - ru->prach_rxsigF[j] = (int16_t**)malloc(nb_rx_streams * sizeof(int16_t*)); - + ru->prach_rxsigF[j] = malloc(nb_rx_streams * sizeof(*ru->prach_rxsigF)); + for (int i = 0; i < nb_rx_streams; i++) { // largest size for PRACH FFT is 4x98304 (16*24576) - ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear(4 * 98304 * 2 * sizeof(int16_t)); - LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n", i, ru->prach_rxsigF[j][i]); + ru->prach_rxsigF[j][i] = malloc16_clear(4 * 98304 * 2 * sizeof(**ru->prach_rxsigF)); + LOG_D(PHY, "[INIT] prach_vars->rxsigF[%d] = %p\n", i, ru->prach_rxsigF[j][i]); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 9fab6254ca..371160437a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -81,7 +81,7 @@ prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t ty prach_item_t *nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) { - prach_item_t *prach = find_nr_prach(&gNB->prach_vars.list, SFN, Slot, SEARCH_EXIST_OR_FREE); + prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, SEARCH_EXIST_OR_FREE); if (!prach) { LOG_W(PHY, "no free space for a new detected rach, discarding\n"); return NULL; @@ -171,7 +171,7 @@ void rx_nr_prach_ru(RU_t *ru, prachStartSymbol, prachOccasion); - int16_t **rxsigF = ru->prach_rxsigF[prachOccasion]; + c16_t **rxsigF = (c16_t **)ru->prach_rxsigF[prachOccasion]; AssertFatal(ru->if_south == LOCAL_RF || ru->if_south == REMOTE_IF5, "we shouldn't call this if if_south != LOCAL_RF or REMOTE_IF5\n"); @@ -392,23 +392,25 @@ void rx_nr_prach_ru(RU_t *ru, // do DFT int16_t *prach2 = prach[aa] + (2*Ncp); // times 2 for complex samples for (int i = 0; i < reps; i++) - dft(dftsize, prach2 + 2*dftlen*i, rxsigF[aa] + 2*dftlen*i, 1); + dft(dftsize, prach2 + 2 * dftlen * i, (int16_t *)rxsigF[aa] + 2 * dftlen * i, 1); //LOG_M("ru_rxsigF_tmp.m","rxsFtmp", rxsigF[aa], dftlen*2*reps, 1, 1); //Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH) LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC); - int16_t rxsigF_tmp[N_ZC<<1]; - // if (k+N_ZC > dftlen) { // PRACH signal is split around DC - int16_t *rxsigF2=rxsigF[aa]; - int k2=k<<1; + c16_t rxsigF_tmp[N_ZC]; + // if (k+N_ZC > dftlen) { // PRACH signal is split around DC + c16_t *rxsigF2 = rxsigF[aa]; + int k2 = k; - for (int j=0;jgNB_config.prach_config; - c16_t **rxsigF = (c16_t **)gNB->prach_vars.rxsigF; uint16_t preamble_index0 = 0; uint16_t numshift = 0; int first_nonzero_root_idx = 0; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index f43e4cdcdb..db391dacc0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -209,7 +209,8 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, int subframe, uint16_t *max_preamble, uint16_t *max_preamble_energy, - uint16_t *max_preamble_delay); + uint16_t *max_preamble_delay, + c16_t **rxsigF); void rx_nr_prach_ru(RU_t *ru, int prach_fmt, diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 3d85c96af8..b94d0b1c56 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -593,7 +593,7 @@ typedef struct RU_t_s { /// beamforming weight vectors int32_t **beam_weights[NUMBER_OF_eNB_MAX+1][15]; prach_list_t prach_list; - /// received frequency-domain signal for PRACH (IF4p5 RRU) + /// received frequency-domain signal for PRACH (IF4p5 RRU) int16_t **prach_rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX]; /// received frequency-domain signal for PRACH BR (IF4p5 RRU) int16_t **prach_rxsigF_br[4]; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index da3b4bcb01..ad08cc1df1 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -134,14 +134,6 @@ typedef struct { nfapi_nr_dl_tti_ssb_pdu ssb_pdu; } NR_gNB_SSB_t; -typedef struct { - /// \brief ?. - /// second index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. - /// third index: frequency-domain sample [0..ofdm_symbol_size*12[ - int16_t **rxsigF; - prach_list_t list; -} NR_gNB_PRACH; - typedef struct { uint8_t NumPRSResources; prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET]; @@ -416,7 +408,7 @@ typedef struct PHY_VARS_gNB_s { int max_nb_pusch; NR_gNB_COMMON common_vars; - NR_gNB_PRACH prach_vars; + prach_list_t prach_list; NR_gNB_PRS prs_vars; NR_gNB_PUSCH *pusch_vars; NR_gNB_PUCCH_t *pucch; diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index b649398456..74a98dc7f7 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -52,10 +52,6 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0}; RU_t *ru; - int aa=0; - int ru_aa; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); rach_ind->sfn = frame; rach_ind->slot = slot; @@ -63,7 +59,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac ru=gNB->RU_list[0]; - prach_item_t *prach_id = find_nr_prach(&gNB->prach_vars.list, frame, slot, SEARCH_EXIST); + prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, SEARCH_EXIST); if (!prach_id) { return; } @@ -75,16 +71,15 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac int N_dur = get_nr_prach_duration(prach_pdu->prach_format); for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) { - for (ru_aa = 0, aa = 0; ru_aa < ru->nb_rx; ru_aa++, aa++) { - gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa]; - } - prachStartSymbol = prach_pdu->prach_start_symbol + prach_oc * N_dur; // comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is // given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots // where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. - rx_nr_prach(gNB, prach_pdu, prach_oc, frame, slot, &max_preamble[0], &max_preamble_energy[0], &max_preamble_delay[0]); + c16_t *rxsigF[ru->nb_rx]; + for (int i = 0; i < ru->nb_rx; ++i) + rxsigF[i] = (c16_t *)ru->prach_rxsigF[prach_oc][i]; + rx_nr_prach(gNB, prach_pdu, prach_oc, frame, slot, &max_preamble[0], &max_preamble_energy[0], &max_preamble_delay[0], rxsigF); LOG_D(NR_PHY, "[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d " "(prach_energy counter %d)\n", @@ -145,6 +140,6 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac } // if prach_id>0 rach_ind->slot = prach_start_slot; LOG_D(NR_PHY, "Freeing PRACH entry\n"); - free_nr_prach_entry(&gNB->prach_vars.list, prach_id); + free_nr_prach_entry(&gNB->prach_list, prach_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 3eda15fc6f..9f2e06762c 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -567,7 +567,7 @@ int main(int argc, char **argv){ phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); - nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list.list[0].pdu; + nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_list.list[0].pdu; prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); prach_pdu->prach_format = prach_format; @@ -769,25 +769,27 @@ int main(int argc, char **argv){ nr_slot_fep_ul(frame_parms, ru->common.rxdata[aa], ru->common.rxdataF[aa], l, slot, ru->N_TA_offset); } } + rx_nr_prach_ru(ru, prach_format, numRA, 0, prachStartSymbol, slot, prachOccasion, frame, slot); + c16_t *rxsigF[ru->nb_rx]; + for (int i = 0; i < ru->nb_rx; ++i) + rxsigF[i] = (c16_t *)ru->prach_rxsigF[prachOccasion][i]; + if (n_frames == 1) + printf("ncs %d,num_seq %d\n", + prach_pdu->num_cs, + prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); + rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay, rxsigF); - rx_nr_prach_ru(ru, prach_format, numRA, 0, prachStartSymbol, slot, prachOccasion, frame, slot); + // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); - for (int i = 0; i < ru->nb_rx; ++i) - gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i]; - if (n_frames == 1) printf("ncs %d,num_seq %d\n",prach_pdu->num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); - rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay); + if (preamble_rx != preamble_tx) + prach_errors++; + else + delay_avg += (double)preamble_delay; - // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); + N_ZC = (prach_sequence_length) ? 139 : 839; - if (preamble_rx != preamble_tx) - prach_errors++; - else - delay_avg += (double)preamble_delay; - - N_ZC = (prach_sequence_length) ? 139 : 839; - - if (n_frames==1) { - printf("preamble %d (tx %d) : energy %d, delay %d\n",preamble_rx,preamble_tx,preamble_energy,preamble_delay); + if (n_frames == 1) { + printf("preamble %d (tx %d) : energy %d, delay %d\n", preamble_rx, preamble_tx, preamble_energy, preamble_delay); #ifdef NR_PRACH_DEBUG LOG_M("prach0.m","prach0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1); LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); @@ -797,7 +799,7 @@ int main(int argc, char **argv){ LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1); LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1); #endif - } + } } printf("SNR %f dB, UE Speed %f km/h: errors %u/%d (delay %f)\n", SNR, ue_speed, prach_errors, n_frames, delay_avg/(double)(n_frames-prach_errors));