diff --git a/CMakeLists.txt b/CMakeLists.txt index 665904c53f..6d15f78a29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1070,7 +1070,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) target_link_libraries(PHY_NR_COMMON PUBLIC UTIL) add_library(PHY_NR ${PHY_NR_SRC}) -target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock) +target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock ds) add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC}) target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 59bdd7012d..8a2a794fbd 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -437,14 +437,11 @@ void init_nr_transport(PHY_VARS_gNB *gNB) else buffer_ul_slots = (nb_ul_slots_period < slot_ahead) ? nb_ul_slots_period : slot_ahead; - gNB->max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; gNB->max_nb_pusch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; gNB->max_nb_srs = buffer_ul_slots ? buffer_ul_slots << 1 : 1; // assuming at most 2 SRS per slot - gNB->pucch = (NR_gNB_PUCCH_t *)malloc16(gNB->max_nb_pucch * sizeof(NR_gNB_PUCCH_t)); - for (int i = 0; i < gNB->max_nb_pucch; i++) { - memset(&gNB->pucch[i], 0, sizeof(gNB->pucch[i])); - } + int max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; + gNB->pucch_queue = spsc_q_alloc(max_nb_pucch, sizeof(NR_gNB_PUCCH_job_t)); gNB->srs = (NR_gNB_SRS_t *)malloc16(gNB->max_nb_srs * sizeof(NR_gNB_SRS_t)); for (int i = 0; i < gNB->max_nb_srs; i++) @@ -465,7 +462,7 @@ void reset_nr_transport(PHY_VARS_gNB *gNB) { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - free(gNB->pucch); + spsc_q_free(&gNB->pucch_queue); free(gNB->srs); for (int i = 0; i < gNB->max_nb_pusch; i++) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 09af58141e..fd6bd8ea42 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -33,37 +33,29 @@ //#define DEBUG_NR_PUCCH_RX 1 void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - for (int i = 0; i < gNB->max_nb_pucch; i++) { - NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (pucch->active == false) { - pucch->frame = frame; - pucch->slot = slot; - pucch->active = true; - pucch->beam_nb = 0; - if (gNB->common_vars.beam_id) { - int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; - int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); - pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das, - fapi_beam_idx, - &gNB->common_vars, - slot, - gNB->frame_parms.symbols_per_slot, - bitmap); - } - memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); - LOG_D(PHY, - "Programming PUCCH[%d] for %d.%d, format %d, nb_harq %d, nb_sr %d, nb_csi %d\n", - i, - pucch->frame, - pucch->slot, - pucch->pucch_pdu.format_type, - pucch->pucch_pdu.bit_len_harq, - pucch->pucch_pdu.sr_flag, - pucch->pucch_pdu.bit_len_csi_part1); - return; - } + LOG_D(PHY, + "%4d.%2d UE %04x Programming PUCCH format %d, nb_harq %d, nb_sr %d, nb_csi %d\n", + frame, + slot, + pucch_pdu->rnti, + pucch_pdu->format_type, + pucch_pdu->bit_len_harq, + pucch_pdu->sr_flag, + pucch_pdu->bit_len_csi_part1); + NR_gNB_PUCCH_job_t pucch = {.frame = frame, .slot = slot, .pucch_pdu = *pucch_pdu}; + if (gNB->common_vars.beam_id) { + int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; + int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); + pucch.beam_nb = beam_index_allocation(gNB->enable_analog_das, + fapi_beam_idx, + &gNB->common_vars, + slot, + gNB->frame_parms.symbols_per_slot, + bitmap); } - LOG_W(PHY, "PUCCH list is full\n"); + bool found = spsc_q_put(&gNB->pucch_queue, &pucch, sizeof(pucch)); + if (!found) + LOG_W(NR_PHY, "PUCCH list is full: dropping PUCCH UE %04x\n", pucch_pdu->rnti); } int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB, const nfapi_nr_pucch_pdu_t *pucch_pdu) diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index a6fb9d8890..9657cef20d 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -19,6 +19,7 @@ #include "nfapi_nr_interface_scf.h" #include "common/utils/threadPool/task_ans.h" #include "openair1/PHY/defs_RU.h" +#include "common/utils/ds/spsc_q.h" #define MAX_NUM_RU_PER_gNB 8 #define MAX_PUCCH0_NID 8 @@ -190,7 +191,6 @@ typedef struct { } NR_gNB_ULSCH_t; typedef struct { - bool active; // identifier for concurrent beams int beam_nb; /// Frame where current PUCCH pdu was sent @@ -199,7 +199,7 @@ typedef struct { uint32_t slot; /// ULSCH PDU nfapi_nr_pucch_pdu_t pucch_pdu; -} NR_gNB_PUCCH_t; +} NR_gNB_PUCCH_job_t; typedef struct { bool active; @@ -369,7 +369,6 @@ typedef struct PHY_VARS_gNB_s { nfapi_nr_ul_tti_request_t UL_tti_req; - int max_nb_pucch; int max_nb_srs; int max_nb_pdsch; int max_nb_pusch; @@ -380,7 +379,7 @@ typedef struct PHY_VARS_gNB_s { NR_gNB_DLSCH_t *dlsch; NR_gNB_PRS prs_vars; NR_gNB_PUSCH *pusch_vars; - NR_gNB_PUCCH_t *pucch; + spsc_q_t pucch_queue; NR_gNB_SRS_t *srs; NR_gNB_ULSCH_t *ulsch; NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB]; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 11b8da6b73..1f28622231 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -2,6 +2,7 @@ * SPDX-License-Identifier: LicenseRef-CSSL-1.0 */ +#include "common/utils/fsn.h" #include "PHY/defs_gNB.h" #include "sched_nr.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" @@ -613,10 +614,11 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB, // Function to fill UL RB mask to be used for N0 measurements static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, - int frame_rx, - int slot_rx, + fsn_t now, uint32_t rb_mask_ul[14][9], - nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf) + nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf, + const NR_gNB_PUCCH_job_t *pucch, + int n_pucch) { for (int symbol = 0; symbol < 14; symbol++) { for (int m = 0; m < 9; m++) { @@ -630,20 +632,9 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, } } - for (int i = 0; i < gNB->max_nb_pucch; i++){ - const NR_gNB_PUCCH_t *pucch = gNB->pucch + i; - if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) - continue; - const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + for (int i = 0; i < n_pucch; ++i) { + const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch[i].pucch_pdu; const int start = pucch_pdu->start_symbol_index; - LOG_D(PHY, - "%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n", - frame_rx, - slot_rx, - i, - start, - pucch_pdu->nr_of_symbols, - pucch_pdu->prb_size); for (int symbol = start; symbol < (start + pucch_pdu->nr_of_symbols); symbol++) { if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { for (int rb = 0; rb < pucch_pdu->prb_size; rb++) { @@ -661,7 +652,7 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) + if (!(ulsch->active && ulsch->frame == now.f && ulsch->slot == now.s && !ulsch->handled)) continue; uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; @@ -678,7 +669,7 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) + if (!(srs && srs->active && srs->frame == now.f && srs->slot == now.s)) continue; nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position; @@ -989,7 +980,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, } } -static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_t *pucch, nfapi_nr_uci_t *uci) +static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_job_t *pucch, nfapi_nr_uci_t *uci) { const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; @@ -1011,16 +1002,41 @@ static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_ } } +static bool drop_old_pucch(const void *data, void *user) +{ + const NR_gNB_PUCCH_job_t *pucch = data; + const fsn_t *now = user; + const fsn_t t = {pucch->frame, pucch->slot, now->mu}; + bool drop = fsn_in_the_past(t, *now); + if (drop) + LOG_E(NR_PHY, "%4d.%2d PUCCH job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, pucch->pucch_pdu.rnti, t.f, t.s); + return drop; +} + +static bool get_current_pucch(const void *data, void *user) +{ + const NR_gNB_PUCCH_job_t *pucch = data; + const fsn_t *now = user; + const fsn_t t = {pucch->frame, pucch->slot, now->mu}; + return fsn_equal(t, *now); +} + int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO) { /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ - int pucch_decode_done = 0; int pusch_decode_done = 0; int pusch_DTX = 0; const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size; const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; + + fsn_t now = {frame_rx, slot_rx, frame_parms->numerology_index}; + + spsc_q_drop_while(&gNB->pucch_queue, drop_old_pucch, &now); + NR_gNB_PUCCH_job_t pucch[MAX_NUM_NR_UCI_PDUS]; + int n_pucch = spsc_q_get_while(&gNB->pucch_queue, get_current_pucch, &now, pucch, sizeof(*pucch), MAX_NUM_NR_UCI_PDUS); + LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); { // Mask of occupied RBs, per symbol and PRB @@ -1028,7 +1044,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = NULL; if (frame_parms->frame_type == TDD) slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list; - fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul, slot_conf); + fill_ul_rb_mask(gNB, now, rb_mask_ul, slot_conf, pucch, n_pucch); int first_symb = 0, num_symb = 0; if (frame_parms->frame_type == TDD) @@ -1045,19 +1061,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N } start_meas(&gNB->phy_proc_rx); - for (int i = 0; i < gNB->max_nb_pucch; i++) { - NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) - continue; + UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; + UL_INFO->uci_ind.sfn = frame_rx; + UL_INFO->uci_ind.slot = slot_rx; + UL_INFO->uci_ind.num_ucis = n_pucch; + nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list; + for (int i = 0; i < n_pucch; ++i) { c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb]; - pucch_decode_done = 1; - UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; - UL_INFO->uci_ind.sfn = frame_rx; - UL_INFO->uci_ind.slot = slot_rx; - nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis; - handle_pucch(gNB, rxdataF, pucch, uci); - UL_INFO->uci_ind.num_ucis += 1; - pucch->active = false; + handle_pucch(gNB, rxdataF, &pucch[i], uci++); } UL_INFO->crc_ind.sfn = frame_rx; @@ -1377,7 +1388,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N stop_meas(&gNB->phy_proc_rx); - if (pucch_decode_done || pusch_decode_done) { + if (n_pucch > 0 || pusch_decode_done) { T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx),