Process PRACH packets

* Move PRACH callback in the oaioran.h/c since now used in K release.
* Reset the number of PRACH packets.
* Handle PRACH queue in the same manner as for PUSCH (95c8fa46).

Co-authored-by: Romain Beurdouche <romain.beurdouche@eurecom.fr>
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
co-authored by Romain Beurdouche
parent 6b665a851e
commit 1bc8e64641
6 changed files with 301 additions and 45 deletions
+7 -5
View File
@@ -28,7 +28,8 @@ It calls various helper function in the same file to set up DPDK memory buffer
- `oai_xran_fh_rx_prach_callback()` through `xran_5g_prach_req()`: callback for - `oai_xran_fh_rx_prach_callback()` through `xran_5g_prach_req()`: callback for
PRACH data; not currently used and implemented in PUSCH data callback. PRACH data; not currently used and implemented in PUSCH data callback.
- `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used - `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used
to unblock timing in `oai_xran_fh_rx_callback()` upon first xran call. to unblock timing in `oai_xran_fh_rx_callback()` and `oai_xran_fh_rx_prach_callback()`
upon first xran call.
More detailed information about the xran callbacks can be taken from the xran More detailed information about the xran callbacks can be taken from the xran
documentation. documentation.
@@ -40,9 +41,10 @@ PDSCH.
For PDSCH, `oran_fh_if4p5_south_out()` calls `xran_fh_tx_send_slot()` that For PDSCH, `oran_fh_if4p5_south_out()` calls `xran_fh_tx_send_slot()` that
optionally compresses IQ data, then writes it into IQ buffers of xran. optionally compresses IQ data, then writes it into IQ buffers of xran.
For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()` that For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()`/
blocks and waits for the next slot. This is done through either a message `xran_fh_rx_prach_read_slot()` that blocks and waits for the next slot.
queue, or through polling, which in both cases depends on xran calling the This is done through either a message queue, or through polling, which in both
callback `oai_xran_fh_rx_callback()` as installed during xran initialization. cases depends on xran calling the callbacks `oai_xran_fh_rx_callback()`/
`oai_xran_fh_rx_prach_callback()` as installed during xran initialization.
Once unblocked, it reads first PRACH data, then PUSCH data, before returning to Once unblocked, it reads first PRACH data, then PUSCH data, before returning to
OAI. OAI.
+211 -20
View File
@@ -46,8 +46,16 @@ int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id
extern notifiedFIFO_t oran_sync_fifo; extern notifiedFIFO_t oran_sync_fifo;
#define MAX_QUEUE_LENGTH_NO_JUMP 3 #define MAX_QUEUE_LENGTH_NO_JUMP 3
atomic_int xran_queue_length = 0; atomic_int xran_queue_length = 0;
atomic_int xran_queue_prach_length = 0;
#if defined K_RELEASE
extern notifiedFIFO_t oran_sync_fifo_prach;
#endif
#else #else
volatile oran_sync_info_t oran_sync_info = {0}; volatile oran_sync_info_t oran_sync_info = {0};
#if defined K_RELEASE
volatile oran_sync_info_t oran_sync_info_prach = {0};
volatile bool prach_rx_awaiting = false;
#endif
#endif #endif
/** @details xran-specific callback, called when all packets for given CC and /** @details xran-specific callback, called when all packets for given CC and
@@ -184,8 +192,109 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
} // rx_sym == 7 } // rx_sym == 7
} }
/** @details Only used to unblock timing in oai_xran_fh_rx_callback() on first void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
* call. */ #if defined K_RELEASE
, uint8_t mu
#endif
)
{
#if defined K_RELEASE
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
static int32_t last_slot = -1;
// static int32_t last_frame = -1;
const struct xran_fh_init *fh_init = get_xran_fh_init();
int num_ports = fh_init->xran_ports;
const int slots_in_sf = 1 << mu;
const int sf_in_frame = 10;
static int rx_RU[XRAN_PORTS_NUM][160] = {0};
uint32_t tti = callback_tag->slotiId;
uint32_t frame = XranGetFrameNum(tti, 0, sf_in_frame, slots_in_sf);
uint32_t subframe = XranGetSubFrameNum(tti, slots_in_sf, sf_in_frame);
uint32_t slot = XranGetSlotNum(tti, slots_in_sf);
uint32_t rx_sym = callback_tag->symbol & 0xFF;
uint32_t ru_id = callback_tag->oXuId;
LOG_D(HW, "prach_rx_callback at %4d.%3d (subframe %d), rx_sym %d ru_id %d\n", frame, slot, subframe, rx_sym, ru_id);
if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7))
// if xran did not call xran_physide_dl_tti callback, it's not ready yet.
// wait till first callback to advance counters, because otherwise users
// would see periodic output with only "0" in stats counters
if (!first_call_set)
return;
uint32_t slot2 = slot + (subframe * slots_in_sf);
rx_RU[ru_id][slot2] = 1;
// if (last_frame > 0 && frame > 0
// && ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023))))
// LOG_E(HW, "Jump in frame counter last_frame %d => %d, slot %d\n", last_frame, frame, slot2);
for (int i = 0; i < num_ports; i++) {
if (rx_RU[i][slot2] == 0)
return;
}
for (int i = 0; i < num_ports; i++)
rx_RU[i][slot2] = 0;
if (last_slot == -1 || slot2 != last_slot) {
#ifndef USE_POLLING
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(oran_sync_info_t), 0, &oran_sync_fifo_prach, NULL);
oran_sync_info_t *info = NotifiedFifoData(req);
info->tti = tti;
info->sl = slot2;
info->f = frame;
info->mu = mu;
#else
LOG_D(HW, "Writing PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
oran_sync_info_prach.tti = tti;
oran_sync_info_prach.sl = slot2;
oran_sync_info_prach.f = frame;
oran_sync_info_prach.mu = mu;
#endif
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
uint32_t tti = callback_tag->slotiId;
uint32_t ru_id = callback_tag->oXuId;
for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) {
oran_buf_list_t *bufs = get_xran_buffers(ru_idx);
struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx);
for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet.
for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) {
struct xran_prb_map *pRbMap = (struct xran_prb_map *)bufs->prachdstdecomp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMapPrach == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id);
for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
AssertFatal(pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt <= 1, "PRACH segmentation is not supported\n");
#ifndef USE_POLLING
info->nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt;
#else
oran_sync_info_prach.nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt;
#endif
pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt = 0;
}
}
}
}
#ifndef USE_POLLING
LOG_D(HW, "Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
atomic_fetch_add(&xran_queue_prach_length, 1);
pushNotifiedFIFO(&oran_sync_fifo_prach, req);
#else
prach_rx_awaiting = true;
#endif
} else
LOG_E(HW, "Cannot Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
last_slot = slot2;
// last_frame = frame;
} // rx_sym == 7
#elif defined F_RELEASE
rte_pause();
#endif
}
/** @details Only used to unblock timing in oai_xran_fh_rx_callback()/oai_xran_fh_rx_prach_callback()
* on first call. */
int oai_physide_dl_tti_call_back(void *param int oai_physide_dl_tti_call_back(void *param
#if defined K_RELEASE #if defined K_RELEASE
, uint8_t mu , uint8_t mu
@@ -198,17 +307,67 @@ int oai_physide_dl_tti_call_back(void *param
return 0; return 0;
} }
/** @brief Reads PRACH data from xran buffers. /** @details Read PRACH data from xran buffers.
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
* before writing.
* *
* @details Reads PRACH data from xran-specific buffers and, if I/Q compression * Function is blocking and waits for next frame/slot combination. It is unblocked
* (bitwidth < 16 bits) is configured, uncompresses the data. Places PRACH data * by oai_xran_fh_rx_prach_callback(). If K_RELEASE, it writes the current slot into parameters
* in OAI buffer. */ * frame/slot. If F_RELEASE, it takes the frame/slot. */
static int read_prach_data(ru_info_t *ru, int frame, int slot int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *frame, int *slot)
#if defined K_RELEASE
, uint8_t mu
#endif
)
{ {
#if defined K_RELEASE
#ifndef USE_POLLING
// pull next even from oran_sync_fifo_prach if any
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo_prach);
atomic_fetch_sub(&xran_queue_prach_length, 1);
oran_sync_info_t *info = NotifiedFifoData(res);
if (xran_queue_prach_length > 0 && xran_queue_prach_length < MAX_QUEUE_LENGTH_NO_JUMP) {
LOG_D(HW, "%4d.%2d TTI processing delay detected\n", info->f, info->sl);
} else if (xran_queue_prach_length >= MAX_QUEUE_LENGTH_NO_JUMP) {
uint32_t old_f = info->f;
uint32_t old_sl = info->sl;
// set the frame/slot info to what is in the last message
notifiedFIFO_elt_t *f;
while ((f = pollNotifiedFIFO(&oran_sync_fifo_prach)) != NULL) {
atomic_fetch_sub(&xran_queue_prach_length, 1);
delNotifiedFIFO_elt(res);
res = f;
}
info = NotifiedFifoData(res);
LOG_W(HW, "PRACH TTI processing delay detected, skipping %4d.%2d => %4d.%2d\n", old_f, old_sl, info->f, info->sl);
DevAssert(xran_queue_prach_length == 0);
}
int slot = info->sl;
int frame = info->f;
uint8_t mu = info->mu;
delNotifiedFIFO_elt(res);
#else
#error "POLLING is not supported for K release unless you know how to fix the race condition on prach_rx_awaiting"
if (!prach_rx_awaiting) {
return (0);
} else {
prach_rx_awaiting = false;
}
int slot = oran_sync_info_prach.sl;
int frame = oran_sync_info_prach.f;
uint8_t mu = oran_sync_info_prach.mu;
uint32_t tti_in = oran_sync_info_prach.tti;
static int last_slot = -1;
LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot);
int cnt = 0;
// while (*slot == last_slot) {
while (tti_in == oran_sync_info_prach.tti) {
//*slot = oran_sync_info.sl;
cnt++;
}
LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot);
last_slot = *slot;
#endif
#endif
/* calculate tti and subframe_id from frame, slot num */ /* calculate tti and subframe_id from frame, slot num */
int sym_idx = 0; int sym_idx = 0;
@@ -235,19 +394,49 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot
#elif defined F_RELEASE #elif defined F_RELEASE
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
#endif #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; 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 it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */
if (ru->prach_buf) { if (ru->prach_buf) {
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) { 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 (int aa = 0; aa < ru->nb_rx; aa++) {
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
int16_t *dst, *src; int16_t *dst, *src;
int idx = 0; int idx = 0;
oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru);
// hardcoded to use only first prach occasion // hardcoded to use only first prach occasion
dst = (int16_t *)ru->prach_buf[aa][0]; dst = (int16_t *)ru->prach_buf[aa][0];
#if defined K_RELEASE
struct xran_prb_map * pPrbMap = (struct xran_prb_map *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
struct xran_rx_packet_ctl *p_rx_packet_ctl = &pPrbMap->sFrontHaulRxPacketCtrl[sym_idx];
#ifndef USE_POLLING
int32_t nRxPkt = info->nRxPkt[cc_id][aa][sym_idx];
#else
int32_t nRxPkt = oran_sync_info.nRxPkt[cc_id][aa][sym_idx];
#endif
if (nRxPkt == 0) {
LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = 0!\n", *frame, *slot, sym_idx, aa);
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
continue;
} else if (nRxPkt > 1) { // protection
LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = %d!\n", *frame, *slot, sym_idx, aa, nRxPkt);
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
continue;
} else {
src = (int16_t *)p_rx_packet_ctl->pData[0];
if (src == NULL) { // protection
LOG_E(HW, "read_prach %d.%d.%d saa = %d: src = NULL!!\n", *frame, *slot, sym_idx, aa);
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
continue;
}
}
num_prbu = p_rx_packet_ctl->nRBSize[0];
#elif defined F_RELEASE
src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData;
#endif
/* convert Network order to host order */ /* convert Network order to host order */
if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) {
if (sym_idx == prach_start_sym) { if (sym_idx == prach_start_sym) {
@@ -289,9 +478,11 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot
for (idx = 0; idx < (N_ZC * 2); idx++) for (idx = 0; idx < (N_ZC * 2); idx++)
dst[idx] += (local_dst[idx + g_kbar]); dst[idx] += (local_dst[idx + g_kbar]);
} // COMPMETHOD_BLKFLOAT } // COMPMETHOD_BLKFLOAT
} // aa } // sym_idx
} // symb_indx } // aa
} // cc_id
} // ru->prach_buf } // ru->prach_buf
return (0); return (0);
} }
@@ -347,8 +538,8 @@ static bool is_tdd_ul_guard_slot(const struct xran_frame_config *frame_conf, int
return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1); return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1);
} }
/** @details Read PRACH and PUSCH data from xran buffers. If /** @details Read PUSCH data from xran buffers.
* I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data * If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
* before writing. Prints ON TIME counters every 128 frames. * before writing. Prints ON TIME counters every 128 frames.
* *
* Function is blocking and waits for next frame/slot combination. It is unblocked * Function is blocking and waits for next frame/slot combination. It is unblocked
@@ -423,9 +614,9 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
int tti = slots_per_frame * (*frame) + (*slot); int tti = slots_per_frame * (*frame) + (*slot);
read_prach_data(ru, *frame, *slot read_prach_data(ru
#if defined K_RELEASE #if defined F_RELEASE
, mu , *frame, *slot
#endif #endif
); );
+6
View File
@@ -21,6 +21,12 @@ typedef struct {
/** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */ /** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
);
/** @brief xran callback for fronthaul PRACH RX, see xran_5g_prach_req(). */
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE #if defined K_RELEASE
, uint8_t mu , uint8_t mu
#endif #endif
+58 -17
View File
@@ -100,6 +100,31 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons
return prbmap; return prbmap;
} }
#if defined K_RELEASE
static struct xran_prb_map get_xran_prb_map_prach(const struct xran_fh_config *f)
{
struct xran_prb_map prbmap = {
.dir = XRAN_DIR_UL,
.xran_port = 0,
.band_id = 0,
.cc_id = 0,
.ru_port_id = 0,
.tti_id = 0,
.nPrbElm = 1,
};
struct xran_prb_elm *e = &prbmap.prbMap[0];
e->nStartSymb = 0;
e->numSymb = 14;
e->nRBStart = 0;
e->nRBSize = 12;
e->nBeamIndex = 0;
e->compMethod = f->ru_conf.compMeth;
e->iqWidth = f->ru_conf.iqWidth;
memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl));
return prbmap;
}
#endif
static uint32_t next_power_2(uint32_t num) static uint32_t next_power_2(uint32_t num)
{ {
uint32_t power = 2; uint32_t power = 2;
@@ -244,16 +269,6 @@ static void oran_allocate_cplane_buffers(void *instHandle,
printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolPrb, count1); printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolPrb, count1);
} }
/* callback not actively used */
static void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
)
{
rte_pause();
}
static void oran_allocate_buffers(void *handle, static void oran_allocate_buffers(void *handle,
int xran_inst, int xran_inst,
int num_sectors, int num_sectors,
@@ -287,6 +302,9 @@ static void oran_allocate_buffers(void *handle,
// DL/UL PRB mapping depending on the duplex mode // DL/UL PRB mapping depending on the duplex mode
struct xran_prb_map dlPm = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, 14); struct xran_prb_map dlPm = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, 14);
struct xran_prb_map ulPm = get_xran_prb_map(fh_config, XRAN_DIR_UL, 0, 14); struct xran_prb_map ulPm = get_xran_prb_map(fh_config, XRAN_DIR_UL, 0, 14);
#if defined K_RELEASE
struct xran_prb_map prachPm = get_xran_prb_map_prach(fh_config);
#endif
struct xran_prb_map dlPmMixed = {0}; struct xran_prb_map dlPmMixed = {0};
struct xran_prb_map ulPmMixed = {0}; struct xran_prb_map ulPmMixed = {0};
uint32_t idx = 0; uint32_t idx = 0;
@@ -314,6 +332,17 @@ static void oran_allocate_buffers(void *handle,
uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu); uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu);
uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm); uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm);
#if defined K_RELEASE
oran_cplane_prb_config prachConf = {
.nTddPeriod = fh_config->frame_conf.nTddPeriod,
.mixed_slot_index = idx,
.slotMap = prachPm,
.mixedSlotMap = prachPm,
};
uint32_t numPrbElmPrach = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&prachPm, mtu);
uint32_t size_of_prb_map_prach = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElmPrach);
#endif
// PDSCH // PDSCH
#if defined K_RELEASE #if defined K_RELEASE
@@ -352,41 +381,53 @@ static void oran_allocate_buffers(void *handle,
// PRACH // PRACH
const uint32_t prachBufSize = PRACH_PLAYBACK_BUFFER_BYTES; const uint32_t prachBufSize = PRACH_PLAYBACK_BUFFER_BYTES;
oran_allocate_uplane_buffers(pi->instanceHandle, bl->prachdst, bl->bufs.prach, xran_max_antenna_nr, prachBufSize); oran_allocate_uplane_buffers(pi->instanceHandle, bl->prachdst, bl->bufs.prach, xran_max_antenna_nr, prachBufSize);
#if defined K_RELEASE
oran_allocate_cplane_buffers(pi->instanceHandle,
bl->prachdstdecomp,
bl->bufs.prachdecomp,
xran_max_antenna_nr,
xran_max_sections_per_slot,
mtu,
fh_config,
size_of_prb_map_prach,
&prachConf);
#elif defined F_RELEASE
// PRACH decomp buffer does not have separate DPDK-allocated memory pool // PRACH decomp buffer does not have separate DPDK-allocated memory pool
// bufs, it points to the same pool as the prach buffer. Unclear to me why // bufs, it points to the same pool as the prach buffer. Unclear to me why
for (uint32_t a = 0; a < xran_max_antenna_nr; ++a) { for (uint32_t a = 0; a < xran_max_antenna_nr; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) { for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j][0]; bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j];
for (uint32_t k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++k) { for (uint32_t k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++k) {
struct xran_flat_buffer *fb = &bl->prachdstdecomp[a][j].pBuffers[k]; struct xran_flat_buffer *fb = &bl->prachdstdecomp[a][j].pBuffers[k];
fb->pData = bl->prachdst[a][j].pBuffers[k].pData; fb->pData = bl->prachdst[a][j].pBuffers[k].pData;
} }
} }
} }
#endif
struct xran_buffer_list *src[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *src[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *srccp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *srccp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *dst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *dst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *dstcp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *dstcp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *prachdst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_buffer_list *prachdstdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
for (uint32_t a = 0; a < XRAN_MAX_ANTENNA_NR; ++a) { for (uint32_t a = 0; a < XRAN_MAX_ANTENNA_NR; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) { for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
src[a][j] = &bl->src[a][j]; src[a][j] = &bl->src[a][j];
srccp[a][j] = &bl->srccp[a][j]; srccp[a][j] = &bl->srccp[a][j];
dst[a][j] = &bl->dst[a][j]; dst[a][j] = &bl->dst[a][j];
dstcp[a][j] = &bl->dstcp[a][j]; dstcp[a][j] = &bl->dstcp[a][j];
prach[a][j] = &bl->prachdst[a][j]; prachdst[a][j] = &bl->prachdst[a][j];
prachdecomp[a][j] = &bl->prachdstdecomp[a][j]; prachdstdecomp[a][j] = &bl->prachdstdecomp[a][j];
} }
} }
#if defined K_RELEASE #if defined K_RELEASE
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag, fh_config->nNumerology[0]); xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag, fh_config->nNumerology[0]);
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]); xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
#elif defined F_RELEASE #elif defined F_RELEASE
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag); xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag);
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag); xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
#endif #endif
} }
+1 -1
View File
@@ -15,7 +15,7 @@ typedef struct oran_bufs {
struct xran_flat_buffer rx_prbmap[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; struct xran_flat_buffer rx_prbmap[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_flat_buffer prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT]; struct xran_flat_buffer prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT];
struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT]; struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
} oran_bufs_t; } oran_bufs_t;
typedef struct oran_buf_list { typedef struct oran_buf_list {
+18 -2
View File
@@ -39,6 +39,9 @@ typedef struct {
} oran_eth_state_t; } oran_eth_state_t;
notifiedFIFO_t oran_sync_fifo; notifiedFIFO_t oran_sync_fifo;
#if defined K_RELEASE
notifiedFIFO_t oran_sync_fifo_prach;
#endif
int trx_oran_start(openair0_device_t *device) int trx_oran_start(openair0_device_t *device)
{ {
@@ -279,12 +282,22 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index}; fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index};
if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
struct xran_fh_config *fh_cfg = get_xran_fh_config(0); struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; #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 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 // 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); nr_prach_info_t prach_info = get_prach_info(0);
bool is_prach_frame = (*frame % prach_info.x == prach_info.y); 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)); // `p.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)
#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) { if (is_prach_slot) {
ru_info.prach_buf = p.prach_buf; ru_info.prach_buf = p.prach_buf;
} else { } else {
@@ -458,6 +471,9 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device_t
// create message queues for ORAN sync // create message queues for ORAN sync
initNotifiedFIFO(&oran_sync_fifo); initNotifiedFIFO(&oran_sync_fifo);
#if defined K_RELEASE
initNotifiedFIFO(&oran_sync_fifo_prach);
#endif
eth->e.flags = ETH_RAW_IF4p5_MODE; eth->e.flags = ETH_RAW_IF4p5_MODE;
eth->e.compression = NO_COMPRESS; eth->e.compression = NO_COMPRESS;