[FHI72] Implement SRS eAxC IDs

Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
This commit is contained in:
Teodora Vladić
2026-06-03 16:26:39 +02:00
parent c86c218a1c
commit efbe35c8a0
8 changed files with 139 additions and 4 deletions

View File

@@ -1582,6 +1582,9 @@ Edit the sample OAI gNB configuration file and check following parameters:
* `prach_config`: PRACH-specific configuration
* `eAxC_offset`: PRACH antenna offset; if not set, default value of `N = max(Nrx,Ntx)` is used
* `kbar`: the PRACH guard interval, provided in RU
* `srs_config`: SRS-specific configuration
* `num_ant_elem`: number of Tx/Rx antenna elements; default is 0
* `srs_eAxC_offset`: SRS antenna offset; if not set, default value of `N = max(Nrx,Ntx) + Nrx` is used
* `app_id`: `DU` or `RU`. Sets the application `id` value in xRAN. Use the default value: `DU`.
Layer mapping (eAxC offsets) happens as follows:

View File

@@ -28,6 +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
PRACH data. For each TTI, OAI checks if PRACH is scheduled through `prach_ru_queue`.
If yes, then reads and stores IQ samples into the `prach_buf`.
- `oai_xran_fh_rx_srs_callback()` through `xran_5g_srs_req()`: callback for
SRS data if SRS configured on eAxC IDs other than for PUSCH. TODO later text
- `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used
to unblock timing in `oai_xran_fh_rx_callback()` and `oai_xran_fh_rx_prach_callback()`
upon first xran call.

View File

@@ -168,6 +168,44 @@ int oai_physide_dl_tti_call_back(void *param, uint8_t mu)
return 0;
}
/** @details Read SRS data from xran buffers for each RU (for each `port_id`).
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
* before writing. */
void oai_xran_fh_rx_srs_callback(void *pCallbackTag, xran_status_t status, uint8_t mu)
{
if (!first_call_set)
return;
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
uint32_t port_id = callback_tag->oXuId;
struct xran_fh_config *fh_cfg = get_xran_fh_config(port_id);
uint32_t num_ant_elem = fh_cfg->nAntElmTRx;
const int slots_in_sf = 1 << mu;
const int sf_in_frame = 10;
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 * sf_in_frame); // slot within a frame, not a subframe
uint32_t rx_sym = callback_tag->symbol & 0xFF; // rx_sym = 7 => cb full slot
LOG_D(HW, "[%d.%d] %s, tti %d rx_sym %d ru_id %d\n", frame, slot, __FUNCTION__, tti, rx_sym, port_id);
// TODO: reset the number of received packets for non SRS slots
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) {
oran_buf_list_t *bufs = get_xran_buffers(port_id);
for (int ant_id = 0; ant_id < num_ant_elem; ant_id++) {
for (int sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) {
struct xran_prb_map *pPrbMap = (struct xran_prb_map *)bufs->srsdstdecomp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
pPrbMap->sFrontHaulRxPacketCtrl[sym_idx].nRxPkt = 0;
}
}
}
// TODO: map SRS IQ data into OAI (new buffer or reuse rxdataF ?)
}
/** @details Read PRACH data from xran buffers for each RU (for each `port_id`).
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
* before writing. */

View File

@@ -21,6 +21,8 @@ typedef struct {
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status, uint8_t mu);
/** @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, uint8_t mu);
/** @brief xran callback for fronthaul SRS RX, see xran_5g_srs_req(). */
void oai_xran_fh_rx_srs_callback(void *pCallbackTag, xran_status_t status, uint8_t mu);
/** @brief xran callback for time alignment, see xran_reg_physide_cb(). */
int oai_physide_dl_tti_call_back(void *param, uint8_t mu);

View File

@@ -834,6 +834,36 @@ static bool set_fh_prach_config(void *mplane_api,
return true;
}
static bool set_fh_srs_config(void *mplane_api,
const openair0_config_t *oai0,
const uint32_t max_num_ant,
const paramdef_t *srsp,
int nsrs,
struct xran_srs_config *srs_config)
{
//const split7_config_t *s7cfg = &oai0->split7;
/* deprecated */
srs_config->symbMask = 0;
/**< SRS slot within TDD period (special slot), for O-RU emulation */
srs_config->slot = 0;
/**< tti offset to delay the transmission of NDM SRS UP, for O-RU emulation */
srs_config->ndm_offset = 0;
/**< symbol duration for NDM SRS UP transmisson, for O-RU emulation */
srs_config->ndm_txduration = 0;
/**< starting value of eAxC for SRS packets for this numerology (Absolute value). Should be unique across all numerologies for the RU */
#ifdef OAI_MPLANE
xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api;
// TODO
#else
const paramdef_t *pd = gpd(srsp, nsrs, ORAN_SRS_CONFIG_EAXC_OFFSET);
srs_config->srsEaxcOffset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant;
#endif
return true;
}
static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame_config *frame_config)
{
const split7_config_t *s7cfg = &oai0->split7;
@@ -1006,6 +1036,15 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
return false;
}
paramdef_t srsp[] = ORAN_SRS_DESC;
int nsrs = sizeofArray(srsp);
sprintf(aprefix, "%s.%s.[%d].%s", CONFIG_STRING_ORAN, CONFIG_STRING_ORAN_FH, ru_idx, CONFIG_STRING_ORAN_SRS);
ret = config_get(config_get_if(), srsp, nsrs, aprefix);
if (ret < 0) {
printf("No configuration section \"%s\": cannot initialize fhi_lib!\n", aprefix);
return false;
}
memset(fh_config, 0, sizeof(*fh_config));
fh_config->dpdk_port = ru_idx; // DPDK port number used for FH
@@ -1013,7 +1052,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->nCC = 1; // number of Component carriers supported on FH; M-plane info
fh_config->neAxc = RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH)
fh_config->neAxcUl = oai0->rx_num_channels / num_rus; // number of eAxc supported on one CC for UL direction = PUSCH
fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B
fh_config->nAntElmTRx = *gpd(srsp, nsrs, ORAN_SRS_CONFIG_NUM_ANT_ELEM)->uptr; // number of antenna elements for TX and RX = SRS; one tx/rx-array can have one or more antenna elements; XRAN_MAX_ANT_ARRAY_ELM_NR
fh_config->nDLAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
fh_config->nULAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
fh_config->nDLCenterFreqARFCN = 0; // center frequency for DL in NR-ARFCN; not used in xran
@@ -1026,7 +1065,9 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
return false;
fh_config->enableCP = 1; // enable C-plane
fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B
fh_config->srsEnable = srsp->paramflags & PARAMFLAG_PARAMSET ? 1 : 0; // enable SRS; can be used for XRAN_CATEGORY_A and XRAN_CATEGORY_B
fh_config->srsEnableCp = srsp->paramflags & PARAMFLAG_PARAMSET ? 1 : 0; // enable SRS C-plane
fh_config->SrsDelaySym = 0; // enable static SRS configuration (when srsEnableCp = 0)
fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU
fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU
fh_config->csirsEnable = 0; // enable CSI-RS (Cat B specific)
@@ -1039,9 +1080,10 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->mu_number[0] = mu_number; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz, 4 -> 240kHz */
fh_config->nNumerology[0] = mu_number; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz, 4 -> 240kHz */
/* SRS only used if XRAN_CATEGORY_B
/* SRS configuration
Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */
// fh_config->srs_conf = {0};
if (!set_fh_srs_config(mplane_api, oai0, RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus) + oai0->rx_num_channels / num_rus, srsp, nsrs, &fh_config->srs_conf))
return false;
if (!set_fh_frame_config(oai0, &fh_config->frame_conf))
return false;
if (!set_fh_ru_config(mplane_api, rup, oai0->split7.prach_fftSize, nru, xran_cat, mu_number, &fh_config->ru_conf))

View File

@@ -264,6 +264,7 @@ static void oran_allocate_buffers(void *handle,
oran_port_instance_t *pi = &portInstances[0];
AssertFatal(handle != NULL, "no handle provided\n");
uint32_t xran_max_antenna_nr = RTE_MAX(fh_config->neAxc, fh_config->neAxcUl);
uint32_t xran_max_ant_array_elm_nr = RTE_MAX(fh_config->nAntElmTRx, xran_max_antenna_nr);
uint32_t xran_max_sections_per_slot = RTE_MAX(fh_config->max_sections_per_slot, XRAN_MIN_SECTIONS_PER_SLOT);
#if defined(__arm__) || defined(__aarch64__)
@@ -363,12 +364,32 @@ static void oran_allocate_buffers(void *handle,
size_of_prb_map_prach,
&prachConf);
// SRS
oran_cplane_prb_config srsConf = {
.nTddPeriod = fh_config->frame_conf.nTddPeriod,
.mixed_slot_index = idx,
.slotMap = ulPm,
.mixedSlotMap = ulPmMixed,
};
oran_allocate_uplane_buffers(pi->instanceHandle, bl->srsdst, bl->bufs.srs, xran_max_ant_array_elm_nr, rxBufSize);
oran_allocate_cplane_buffers(pi->instanceHandle,
bl->srsdstdecomp,
bl->bufs.srsdecomp,
xran_max_ant_array_elm_nr,
xran_max_sections_per_slot,
mtu,
fh_config,
size_of_prb_map,
&srsConf);
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 *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 *prachdst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prachdstdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *srsdst[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *srsdstdecomp[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN];
for (uint32_t a = 0; a < XRAN_MAX_ANTENNA_NR; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
src[a][j] = &bl->src[a][j];
@@ -380,8 +401,15 @@ static void oran_allocate_buffers(void *handle,
}
}
for (uint32_t a = 0; a < XRAN_MAX_ANT_ARRAY_ELM_NR && xran_max_ant_array_elm_nr; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
srsdst[a][j] = &bl->srsdst[a][j];
srsdstdecomp[a][j] = &bl->srsdstdecomp[a][j];
}
}
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, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
xran_5g_srs_req(pi->instanceHandle, srsdst, srsdstdecomp, oai_xran_fh_rx_srs_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
}
void *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_config *xran_fh_config)
@@ -421,6 +449,7 @@ void *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_conf
struct xran_cb_tag tag = {.cellId = sector, .oXuId = o_xu_id};
pi->prach_tag = tag;
pi->pusch_tag = tag;
pi->srs_tag = tag;
oran_allocate_buffers(gxran_handle[0], o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
if ((xret = xran_timingsource_reg_tticb(NULL, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {

View File

@@ -16,6 +16,9 @@ typedef struct oran_bufs {
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];
struct xran_flat_buffer srs[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT];
struct xran_flat_buffer srsdecomp[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN];
} oran_bufs_t;
typedef struct oran_buf_list {
@@ -28,6 +31,9 @@ typedef struct oran_buf_list {
struct xran_buffer_list prachdst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list prachdstdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list srsdst[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list srsdstdecomp[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN];
oran_bufs_t bufs;
} oran_buf_list_t;
@@ -38,6 +44,7 @@ typedef struct oran_port_instance_t {
struct xran_cb_tag prach_tag;
struct xran_cb_tag pusch_tag;
struct xran_cb_tag srs_tag;
} oran_port_instance_t;
extern struct xran_fh_config gxran_fh_config[XRAN_PORTS_NUM];

View File

@@ -140,4 +140,16 @@
}
// clang-format on
#define CONFIG_STRING_ORAN_SRS "srs_config"
#define ORAN_SRS_CONFIG_NUM_ANT_ELEM "num_ant_elem"
#define ORAN_SRS_CONFIG_EAXC_OFFSET "srs_eAxC_offset"
// clang-format off
#define ORAN_SRS_DESC {\
{ORAN_SRS_CONFIG_NUM_ANT_ELEM, "Number of antenna elements\n", 0, .uptr=NULL, .defuintval=0, TYPE_UINT32, 0}, \
{ORAN_SRS_CONFIG_EAXC_OFFSET, "RU's eAxC offset for SRS\n", 0, .u8ptr=NULL, .defuintval=0, TYPE_UINT8, 0}, \
}
// clang-format on
#endif /* ORAN_PARAMS_H */