diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index abbfa05df1..1b27b2e4e6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -161,7 +161,12 @@ static void rx_func(processingData_L1_t *info) NR_UL_IND_t UL_INFO = {.frame = frame_rx, .slot = slot_rx, .module_id = gNB->Mod_id, .CC_id = gNB->CC_id}; // Do PRACH RU processing UL_INFO.rach_ind.pdu_list = UL_INFO.prach_pdu_indication_list; - L1_nr_prach_procedures(gNB, frame_rx, slot_rx, &UL_INFO.rach_ind); + UL_INFO.rach_ind.number_of_pdus = 0; + // even if processing is late, we might collect all PRACH + // the last PRACH's frame/slot is when all UE's appear to have accessed + prach_item_t p; + while (spsc_q_get(&gNB->prach_l1rx_queue, &p, sizeof(p))) + L1_nr_prach_procedures(gNB, &p, &UL_INFO.rach_ind); //WA: comment rotation in tx/rx if (gNB->phase_comp) { diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 7554c8a9a6..a0bc7c2b5d 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -15,6 +15,7 @@ #include "common/utils/nr/nr_common.h" #include "common/utils/assertions.h" #include "common/utils/system.h" +#include "common/utils/fsn.h" #include "common/ran_context.h" #include "radio/COMMON/common_lib.h" @@ -980,11 +981,16 @@ void *ru_thread(void *param) proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); // Do PRACH RU processing - prach_item_t *p = - find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST); - if (p) { + fsn_t now = {.f = proc->frame_rx, .s = proc->tti_rx, .mu = fp->numerology_index}; + prach_item_t p; + while (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { // need to extract RACH data for later processing by rx_nr_prach() - rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); + rx_nr_prach_ru(&p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); + bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p)); + // assume prach_l1rx_queue never full: prach_ru_queue filled at + // constant pace, but prach_l1rx_queue emptied as fast as possible, + // see rx_func() + DevAssert(success); } // end if (prach_id >= 0) } // end if (ru->feprx) } // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index a007bbd6d7..35b27468f6 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -166,7 +166,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) common_vars->debugBuff_sample_offset = 0; // PRACH - init_prach_list(&gNB->prach_list); + init_nr_prach(gNB); 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; @@ -208,6 +208,7 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_gnb_lowpapr_sequences(); reset_nr_transport(gNB); + reset_nr_prach(gNB); destroy_DLSCH_struct(gNB); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index c54c9ccc29..dc3cb1950d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -12,72 +12,73 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "openair1/PHY/NR_TRANSPORT/nr_prach.h" -void init_prach_list(prach_list_t *l) +void init_nr_prach(PHY_VARS_gNB *gNB) { - pthread_mutex_init(&l->prach_list_mutex, NULL); - memset(l->list, 0, sizeof(l->list)); + int num_prach = 8; + gNB->prach_ru_queue = spsc_q_alloc(num_prach, sizeof(prach_item_t)); + gNB->prach_l1rx_queue = spsc_q_alloc(num_prach, sizeof(prach_item_t)); } -void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) +void reset_nr_prach(PHY_VARS_gNB *gNB) { - pthread_mutex_lock(&l->prach_list_mutex); - if (p->frame == -1) - LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n"); - *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1, .nb_rx = p->nb_rx, .prach_buf = (void *)(p + 1)}; - pthread_mutex_unlock(&l->prach_list_mutex); + spsc_q_free(&gNB->prach_ru_queue); + spsc_q_free(&gNB->prach_l1rx_queue); } -prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, int nb_rx, nr_find_type_t type) +void free_nr_prach_entry(prach_item_t *p) { - pthread_mutex_lock(&l->prach_list_mutex); - AssertFatal(nb_rx, "Error! Number of antennas set to 0.\n"); - prach_item_t **p = l->list; - prach_item_t **end = p + NUMBER_OF_NR_PRACH_MAX; - for (; p < end; p++) - if ((*p) && (*p)->frame == frame && ((*p)->slot + (*p)->num_slots - 1) == slot) - break; - if (p == end) { - if (type == NR_SEARCH_EXIST) { - pthread_mutex_unlock(&l->prach_list_mutex); - return NULL; - } - for (p = l->list; p < end; p++) - if (!(*p) || ((*p)->frame == -1 && (*p)->slot == -1)) - break; - } - if (p == end) { - pthread_mutex_unlock(&l->prach_list_mutex); - return NULL; - } - // mark it used, it will be filled later - if (*p && (*p)->nb_rx != nb_rx) { - LOG_W(PHY, "rach procedure nb_rx ant changed from %d to %d\n", (*p)->nb_rx, nb_rx); - free(*p); - *p = NULL; - } - if (!(*p)) { - *p = calloc(1, sizeof(prach_item_t) + sizeof(c16_t) * nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L); - (*p)->prach_buf = (void *)((*p) + 1); - } - (*p)->nb_rx = nb_rx; - (*p)->frame = frame; - pthread_mutex_unlock(&l->prach_list_mutex); - return (*p); + free(p->prach_buf); } -prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) +static bool drop_old_prach(const void *data, void *user) +{ + const prach_item_t *p = data; + const fsn_t *now = user; + const fsn_t t = {p->frame, p->slot, now->mu}; + bool drop = fsn_in_the_past(t, *now); + if (drop) + LOG_E(NR_PHY, "%4d.%2d PRACH job is in the past (%4d.%2d)\n", now->f, now->s, t.f, t.s); + return drop; +} + +static bool get_current_prach(const void *data, void *user) +{ + const prach_item_t *p = data; + const fsn_t *now = user; + const fsn_t t = {p->frame, p->slot, now->mu}; + return fsn_equal(t, *now); +} + +bool get_next_nr_prach(spsc_q_t *q, const fsn_t *now, prach_item_t *p) +{ + spsc_q_drop_while(q, drop_old_prach, (void *)now); + return spsc_q_get_if(q, get_current_prach, (void *)now, p, sizeof(*p)); +} + +void nr_schedule_rx_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_list, SFN, Slot, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST_OR_FREE); - if (!prach) { - LOG_W(PHY, "no free space for a new detected rach, discarding\n"); - return NULL; - } const int fmt = prach_pdu->prach_format; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - // we set only elements as the whole structure has been cleaned when we release it - prach->frame = SFN; - prach->slot = Slot; - prach->num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1; + const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + const nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; + const nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; + prach_item_t prach = { + .frame = SFN, + .slot = Slot, + .num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1, + .pdu = *prach_pdu, + .rootSequenceIndex = occ->prach_root_sequence_index.value, + .numrootSequenceIndex = occ->num_root_sequences.value, + .msg1_frequencystart = occ->k1.value, + .mu = cfg->prach_sub_c_spacing.value, + .prach_sequence_length = cfg->prach_sequence_length.value, + .restricted_set = cfg->restricted_set_config.value, + .numerology_index = fp->numerology_index, + .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value, + .Xu = gNB->X_u, + .rx_prach = &gNB->rx_prach, + // TODO can be made permanently allocated? + .prach_buf = calloc_or_fail(1, sizeof(c16_t) * prach.nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L), + }; if (gNB->common_vars.beam_id) { int n_symb = get_nr_prach_duration(prach_pdu->prach_format); AssertFatal(prach_pdu->beamforming.dig_bf_interface < NFAPI_MAX_NUM_BG_IF, @@ -87,7 +88,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx; int start_symb = prach_pdu->prach_start_symbol + i * n_symb; int bitmap = SL_to_bitmap(start_symb, n_symb); - prach->beams[i] = beam_index_allocation(gNB->enable_analog_das, + prach.beams[i] = beam_index_allocation(gNB->enable_analog_das, fapi_beam_idx, &gNB->common_vars, Slot, @@ -95,20 +96,9 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n bitmap); } } - prach->pdu = *prach_pdu; - nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; - nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; - prach->rootSequenceIndex = occ->prach_root_sequence_index.value; - prach->numrootSequenceIndex = occ->num_root_sequences.value; - prach->msg1_frequencystart = occ->k1.value; - prach->mu = cfg->prach_sub_c_spacing.value; - prach->prach_sequence_length = cfg->prach_sequence_length.value; - prach->restricted_set = cfg->restricted_set_config.value; - prach->numerology_index = fp->numerology_index; - prach->nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value; - prach->Xu = gNB->X_u; - prach->rx_prach = &gNB->rx_prach; - return prach; + bool found = spsc_q_put(&gNB->prach_ru_queue, &prach, sizeof(prach)); + if (!found) + LOG_W(NR_PHY, "%4d.%2d PRACH occ queue is full: dropping PRACH request\n", SFN, Slot); } static void rx_nr_prach_ru_internal(prach_item_t *p, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 32efa979cc..863903c242 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -11,6 +11,7 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_gNB.h" +#include "common/utils/fsn.h" #define NR_PBCH_PDU_BITS 24 @@ -167,7 +168,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu); -prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); +void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); typedef struct rx_prach_out { uint16_t max_preamble; @@ -178,12 +179,6 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion); void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset); -typedef enum { - NR_SEARCH_EXIST = 0, - NR_SEARCH_EXIST_OR_FREE -} nr_find_type_t; - -prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, int nb_rx, nr_find_type_t type); void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -219,7 +214,10 @@ nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB, int get_nr_prach_duration(uint8_t prach_format); -void free_nr_prach_entry(prach_list_t *, prach_item_t *); +void init_nr_prach(PHY_VARS_gNB *gNB); +void reset_nr_prach(PHY_VARS_gNB *gNB); +void free_nr_prach_entry(prach_item_t *); +bool get_next_nr_prach(spsc_q_t *q, const fsn_t *now, prach_item_t *p); void nr_decode_pucch1(PHY_VARS_gNB *gNB, c16_t **rxdataF, diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 479a214418..3e627c38cd 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -46,14 +46,6 @@ typedef struct { c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L]; } prach_item_t; -typedef struct { - /// prach commands - prach_item_t *list[NUMBER_OF_NR_PRACH_MAX]; - /// mutex for prach_list access - pthread_mutex_t prach_list_mutex; -} prach_list_t; -void init_prach_list(prach_list_t *); - typedef struct { int nb_id; int Nid[MAX_PUCCH0_NID]; @@ -378,7 +370,8 @@ typedef struct PHY_VARS_gNB_s { int max_nb_pusch; NR_gNB_COMMON common_vars; - prach_list_t prach_list; + spsc_q_t prach_ru_queue; + spsc_q_t prach_l1rx_queue; // TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack? NR_gNB_DLSCH_t *dlsch; NR_gNB_PRS prs_vars; diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index fcaf2f1c1b..929bf476f3 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -21,20 +21,14 @@ int get_nr_prach_duration(uint8_t prach_format) return val[prach_format]; } -void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind) +void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind) { + const frame_t frame = prach_id->frame; + const slot_t slot = prach_id->slot; rach_ind->sfn = frame; rach_ind->slot = slot; - rach_ind->number_of_pdus = 0; - - prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST); - if (!prach_id) { - return; - } - nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu; LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas); - const int prach_start_slot = prach_id->slot; 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++) { @@ -63,7 +57,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac "[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol " "%u freq index %u\n", frame, - prach_start_slot, + slot, res.max_preamble, res.max_preamble_energy / 10, res.max_preamble_energy % 10, @@ -100,7 +94,6 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) gNB->prach_energy_counter++; } // if prach_id>0 - rach_ind->slot = prach_start_slot; LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n"); - free_nr_prach_entry(&gNB->prach_list, prach_id); + free_nr_prach_entry(prach_id); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 686f88a5fa..33ee17f374 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -1330,9 +1330,7 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req break; case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - if (!prach) - LOG_W(NR_PHY_RACH, "Error in scheduling rach\n"); + nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); } break; case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 7ff044b46c..ba1d00457b 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -18,7 +18,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int slot); void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req); int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO); -void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind); +void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind); void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 6e29abd9a5..b47b35b470 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -547,12 +547,10 @@ int main(int argc, char **argv){ phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); - prach_item_t *prach_data = calloc(1,sizeof(prach_item_t)); - gNB->prach_list.list[0] = prach_data; - nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->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; + nfapi_nr_prach_pdu_t prach_pdu = {0}; + 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; // Configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -749,14 +747,14 @@ int main(int argc, char **argv){ } nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; - nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; - prach_pdu->num_prach_ocas=1; + nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu.num_ra]; + prach_pdu.num_prach_ocas=1; prach_item_t *in = malloc(sizeof(prach_item_t) + sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L); *in = (prach_item_t){.frame = frame, .slot = slot, - .pdu = *prach_pdu, + .pdu = prach_pdu, .rootSequenceIndex = occ->prach_root_sequence_index.value, .numrootSequenceIndex = occ->num_root_sequences.value, .msg1_frequencystart = occ->k1.value, @@ -772,7 +770,7 @@ int main(int argc, char **argv){ if (n_frames == 1) LOG_I(PHY, "ncs %d,num_seq %d\n", - prach_pdu->num_cs, + prach_pdu.num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); rx_prach_out_t out = rx_nr_prach(in, prachOccasion); @@ -823,7 +821,6 @@ int main(int argc, char **argv){ nr_phy_free_RU(ru); free(RC.ru[0]); free(RC.ru); - free(prach_data); phy_free_nr_gNB(gNB); // allocated in set_tdd_config_nr() int nb_slots_to_set = (1<gNB_list[0]->prach_list, *frame, *slot, ru->nr_frame_parms->nb_antennas_rx, SEARCH_EXIST); - if (prach_id) { + prach_item_t p; + PHY_VARS_gNB *gNB = ru->gNB_list[0]; + fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index}; + if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { struct xran_fh_config *fh_cfg = get_xran_fh_config(0); int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received // PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4 nr_prach_info_t prach_info = get_prach_info(0); bool is_prach_frame = (*frame % prach_info.x == prach_info.y); - bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)); // `prach_id->slot` = slot in which PRACH is scheduled + bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)); // `p.slot` = slot in which PRACH is scheduled if (is_prach_slot) { - ru_info.prach_buf = prach_id->prach_buf; + ru_info.prach_buf = p.prach_buf; } else { - LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot); + LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot); } } @@ -232,6 +235,15 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl); } + if (ru_info.prach_buf) { + // xran_fh_rx_read_slot() should have read PRACH, write back to queue + bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p)); + // assume prach_l1rx_queue never full: prach_ru_queue filled at + // constant pace, but prach_l1rx_queue emptied as fast as possible, + // see rx_func() + DevAssert(success); + } + int slots_per_frame = 10 << (ru->openair0_cfg.nr_scs_for_raster); proc->tti_rx = sl; proc->frame_rx = f;