Separate PRACH and PUSCH packet processing

* rename read_prach_data() to xran_rx_prach_read_slot()
* in F release, there is no PRACH queue so `frame` and `slot` are
  passed as input; in K release, `frame` and `slot` are taken from the PRACH
queue

Note: since the PUSCH callback is the called before PRACH callback, this
commit is correct but the timing for PRACH processing is just a little
bit late. In previous state, PRACH processing was done inside the
function of PUSCH processing.
=> next commit will just reverse the order.

Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
This commit is contained in:
Teodora Vladić
2026-04-23 18:42:25 +02:00
committed by Romain Beurdouche
parent 1bc8e64641
commit d06bd3d49f
3 changed files with 65 additions and 53 deletions
+43 -15
View File
@@ -25,6 +25,7 @@
#include "oran-config.h" // for g_kbar
#include "common/utils/threadPool/notified_fifo.h"
#include "common/utils/fsn.h"
#define N_SC_PER_PRB 12
@@ -314,7 +315,7 @@ int oai_physide_dl_tti_call_back(void *param
* Function is blocking and waits for next frame/slot combination. It is unblocked
* by oai_xran_fh_rx_prach_callback(). If K_RELEASE, it writes the current slot into parameters
* frame/slot. If F_RELEASE, it takes the frame/slot. */
int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *frame, int *slot)
int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int *slot)
{
#if defined K_RELEASE
#ifndef USE_POLLING
@@ -340,8 +341,8 @@ int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *fra
DevAssert(xran_queue_prach_length == 0);
}
int slot = info->sl;
int frame = info->f;
*slot = info->sl;
*frame = info->f;
uint8_t mu = info->mu;
delNotifiedFIFO_elt(res);
#else
@@ -351,8 +352,8 @@ int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *fra
} else {
prach_rx_awaiting = false;
}
int slot = oran_sync_info_prach.sl;
int frame = oran_sync_info_prach.f;
*slot = oran_sync_info_prach.sl;
*frame = oran_sync_info_prach.f;
uint8_t mu = oran_sync_info_prach.mu;
uint32_t tti_in = oran_sync_info_prach.tti;
@@ -368,6 +369,35 @@ int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *fra
last_slot = *slot;
#endif
#endif
prach_item_t p;
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);
#if defined F_RELEASE
uint8_t mu = fh_cfg->frame_conf.nNumerology;
#elif defined K_RELEASE
uint8_t mu = fh_cfg->nNumerology[0];
#endif
int slots_per_subframe = 1 << mu;
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, (p.slot % slots_per_subframe)
#if defined K_RELEASE
, mu
#endif
); // `p.slot` = slot in which PRACH is scheduled
if (is_prach_slot) {
ru->prach_buf = p.prach_buf;
} else {
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot);
}
} else {
return (0);
}
/* calculate tti and subframe_id from frame, slot num */
int sym_idx = 0;
@@ -395,12 +425,10 @@ int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *fra
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
#endif
int tti = slots_per_frame * (frame) + (slot);
int tti = slots_per_frame * (*frame) + (*slot);
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
/* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */
if (ru->prach_buf) {
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet.
for (int aa = 0; aa < ru->nb_rx; aa++) {
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
@@ -481,7 +509,13 @@ int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *fra
} // sym_idx
} // aa
} // cc_id
} // ru->prach_buf
// after reading 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);
return (0);
}
@@ -614,12 +648,6 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
int tti = slots_per_frame * (*frame) + (*slot);
read_prach_data(ru
#if defined F_RELEASE
, *frame, *slot
#endif
);
const struct xran_fh_init *fh_init = get_xran_fh_init();
#if defined K_RELEASE
int fftsize = 1 << fh_cfg->perMu[mu].nULFftSize;
+13 -37
View File
@@ -12,9 +12,7 @@
#include "xran_sync_api.h"
#include "common/utils/LOG/log.h"
#include "common/utils/fsn.h"
#include "openair1/PHY/defs_gNB.h"
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "oaioran.h"
#include "oran-config.h"
@@ -268,6 +266,8 @@ int trx_oran_ctlrecv(openair0_device_t *device, void *msg, ssize_t msg_len)
void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
{
int ret = 0; // return code for PUSCH/PRACH processing
ru_info_t ru_info = {
.nb_rx = ru->nb_rx * ru->num_beams_period,
.nb_tx = ru->nb_tx * ru->num_beams_period,
@@ -277,54 +277,30 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
.prach_buf = NULL,
};
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);
/* Firstly, process PRACH packets */
int f_prach, sl_prach;
#if defined F_RELEASE
uint8_t mu = fh_cfg->frame_conf.nNumerology;
#elif defined K_RELEASE
uint8_t mu = fh_cfg->nNumerology[0];
// no PRACH callback (no queue) in F release so use the expected combination
f_prach = *frame;
sl_prach = *slot;
#endif
int slots_per_subframe = 1 << mu;
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, (p.slot % slots_per_subframe)
#if defined K_RELEASE
, mu
#endif
); // `p.slot` = slot in which PRACH is scheduled
bool is_prach_slot = is_prach_frame && check_xran_prach_slot;
if (is_prach_slot) {
ru_info.prach_buf = p.prach_buf;
} else {
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot);
}
ret = xran_fh_rx_prach_read_slot(ru->gNB_list[0], &ru_info, &f_prach, &sl_prach);
if (ret != 0) {
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX PRACH function \n", f_prach, sl_prach);
}
RU_proc_t *proc = &ru->proc;
/* Secondly, process PUSCH packets */
RU_proc_t *proc = &ru->proc; // to check if (frame,slot) combination corresponds to the expected PUSCH one
int f, sl;
LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
start_meas(&ru->rx_fhaul);
int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
stop_meas(&ru->rx_fhaul);
LOG_D(HW, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]);
if (ret != 0) {
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;
+9 -1
View File
@@ -14,6 +14,8 @@
#include "openair1/PHY/impl_defs_nr.h"
#include "openair1/PHY/TOOLS/tools_defs.h"
#include "openair1/PHY/defs_nr_common.h"
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
/*
* Structure added to bear the information needed from OAI RU
*/
@@ -38,12 +40,18 @@ typedef struct ru_info_s {
c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L];
} ru_info_t;
/** @brief Reads RX data (PRACH/PUSCH) of next slot.
/** @brief Reads RX data PUSCH of next slot.
*
* @param ru pointer to structure keeping pointers to OAI data.
* @param frame output of the frame which has been read.
* @param slot output of the slot which has been read. */
int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot);
/** @brief Reads RX data PRACH of next slot.
*
* @param ru pointer to structure keeping pointers to OAI data.
* @param frame input for F_RELEASE, output for K_RELEASE.
* @param slot input for F_RELEASE, output for K_RELEASE. */
int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int *slot);
/** @brief Writes TX data (PDSCH) of given slot. */
int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp);