Use spsc_q for PUCCH processing
Use the spsc queue to pass jobs from TX thread (scheduler) to RX thread (handling those jobs), reducing the amount spent searching for PUCCH jobs in an array, clarifying the design, and making it thread-safe. Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
This commit is contained in:
+1
-1
@@ -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)
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user