diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index 3f953b36d9..6d68225bbf 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index ac5f471..b0f7ed1 100644 +index ac5f471..94c2d7c 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,7 +7,7 @@ index ac5f471..b0f7ed1 100644 #include -#define VERSIONX "oran_f_release_v1.0" -+#define VERSIONX "oran_f_release_v1.5" ++#define VERSIONX "oran_f_release_v1.6" #define APP_O_DU 0 #define APP_O_RU 1 @@ -173,18 +173,20 @@ index eccc4ae..a97fdc6 100644 CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF) CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF) diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h -index bacf597..1dd6d66 100644 +index bacf597..2aeaaae 100644 --- a/fhi_lib/lib/api/xran_fh_o_du.h +++ b/fhi_lib/lib/api/xran_fh_o_du.h -@@ -141,7 +141,7 @@ extern "C" { +@@ -141,8 +141,8 @@ extern "C" { #define XRAN_MAX_SECTIONS_PER_SYM (XRAN_MAX_SECTIONS_PER_SLOT) /**< Max number of different sections in single slot (section may be equal to RB allocation for UE) */ #define XRAN_MIN_SECTIONS_PER_SYM (XRAN_MIN_SECTIONS_PER_SLOT) /**< Min number of different sections in single slot (section may be equal to RB allocation for UE) */ -#define XRAN_MAX_FRAGMENT (4) /**< Max number of fragmentations in single symbol */ +-#define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ +#define XRAN_MAX_FRAGMENT (6) /**< Max number of fragmentations in single symbol */ - #define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ ++#define XRAN_MAX_SET_BFWS (1) //(64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ #define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */ + #define XRAN_N_MAX_BUFFER_SEGMENT XRAN_MAX_PKT_BURST /**< Max number of segments per ms */ @@ -419,6 +419,7 @@ struct xran_io_cfg { uint16_t num_rxq; /**< number of RX queues per VF */ char *dpdk_dev[XRAN_VF_MAX]; /**< VFs devices */ @@ -193,7 +195,15 @@ index bacf597..1dd6d66 100644 int32_t bbdev_mode; /**< DPDK for BBDev */ uint32_t dpdkIoVaMode; /**< IOVA Mode */ uint32_t dpdkMemorySize; /**< DPDK max memory allocation */ -@@ -1193,6 +1194,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, +@@ -713,6 +714,7 @@ struct xran_fh_config { + uint16_t max_sections_per_slot; /**< M-Plane settings for section */ + uint16_t max_sections_per_symbol; /**< M-Plane settings for section */ + int32_t RunSlotPrbMapBySymbolEnable; /**< enable prb mapping by symbol with multisection*/ ++ uint8_t LiteOnIgnoreUPSectionIdEnable; /**< handle LiteOn issue where section id on UP packet is wrongly set to 13. */ + + uint8_t dssEnable; /**< enable DSS (extension-9) */ + uint8_t dssPeriod; /**< DSS pattern period for LTE/NR */ +@@ -1193,6 +1195,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, */ int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); @@ -535,7 +545,7 @@ index 08660f3..2bb5187 100644 #include #include diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c -index dc40ad9..5968d01 100644 +index dc40ad9..1b88013 100644 --- a/fhi_lib/lib/src/xran_common.c +++ b/fhi_lib/lib/src/xran_common.c @@ -31,7 +31,10 @@ @@ -549,7 +559,110 @@ index dc40ad9..5968d01 100644 #include #include #include -@@ -714,11 +717,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -49,6 +52,8 @@ + #include "xran_printf.h" + #include "xran_mlog_lnx.h" + ++#include "xran_frame_struct.h" ++ + static struct timespec sleeptime = {.tv_nsec = 1E3 }; /* 1 us */ + + extern int32_t first_call; +@@ -529,13 +534,30 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru + if (pRbMap) + { + /** Get the prb_elem_id */ ++ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ if(0 == p_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { ++ section_id_tmp = prb_elem_id_tmp = sect_id[i]; ++ } else { ++ u_int8_t mixed_ul_sym_start = 0; ++ if (xran_fs_get_slot_type(xran_port, CC_ID[i], tti, XRAN_SLOT_TYPE_SP)) { ++ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID[i], tti); ++ } ++ u_int8_t section_id_tmp = symb_id[i] - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ //Note for future reference when using MTU 1500 ++ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ } ++ + total_sections=0; + if(pRbMap->prbMap[0].bf_weight.extType == 1) + { + for(idxElm=0 ; idxElm < pRbMap->nPrbElm ; idxElm++) + { + total_sections += pRbMap->prbMap[idxElm].bf_weight.numSetBFWs; +- if(total_sections >= (sect_id[i] + 1)) ++ if(total_sections >= (/*sect_id[i]*/ prb_elem_id_tmp + 1)) + { + prb_elem_id[i] = idxElm; + break; +@@ -544,12 +566,12 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru + } + else + { +- prb_elem_id[i] = sect_id[i]; ++ prb_elem_id[i] = prb_elem_id_tmp; /*sect_id[i];*/ + } + + if (prb_elem_id[i] >= pRbMap->nPrbElm) + { +- print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", sect_id[i], prb_elem_id[i], pRbMap->nPrbElm); ++ print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", /*sect_id[i]*/ section_id_tmp, prb_elem_id[i], pRbMap->nPrbElm); + ret_data[i] = MBUF_FREE; + continue; + } +@@ -615,13 +637,30 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru + if (pRbMap) + { + /** Get the prb_elem_id */ ++ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ if(0 == p_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { ++ section_id_tmp = prb_elem_id_tmp = sect_id[i]; ++ } else { ++ u_int8_t mixed_ul_sym_start = 0; ++ if (xran_fs_get_slot_type(xran_port, CC_ID[i], tti, XRAN_SLOT_TYPE_SP)) { ++ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID[i], tti); ++ } ++ u_int8_t section_id_tmp = symb_id[i] - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ //Note for future reference when using MTU 1500 ++ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ } ++ + total_sections=0; + if(pRbMap->prbMap[0].bf_weight.extType == 1) + { + for(idxElm=0 ; idxElm < pRbMap->nPrbElm ; idxElm++) + { + total_sections += pRbMap->prbMap[idxElm].bf_weight.numSetBFWs; +- if(total_sections >= (sect_id[i] + 1)) ++ if(total_sections >= (/*sect_id[i]*/ prb_elem_id_tmp + 1)) + { + prb_elem_id[i] = idxElm; + break; +@@ -630,12 +669,12 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru + } + else + { +- prb_elem_id[i] = sect_id[i]; ++ prb_elem_id[i] = prb_elem_id_tmp; /*sect_id[i];*/ + } + + if (prb_elem_id[i] >= pRbMap->nPrbElm) + { +- print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", sect_id[i], prb_elem_id[i], pRbMap->nPrbElm); ++ print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", /*sect_id[i]*/ section_id_tmp, prb_elem_id[i], pRbMap->nPrbElm); + ret_data[i] = MBUF_FREE; + continue; + } +@@ -714,11 +753,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) uint8_t compMeth = 0; uint8_t iqWidth = 0; @@ -564,7 +677,7 @@ index dc40ad9..5968d01 100644 if(first_call == 0) return ret; -@@ -733,9 +739,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -733,9 +775,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) return MBUF_FREE; num_bytes = xran_extract_iq_samples(pkt, &iq_samp_buf, @@ -576,7 +689,7 @@ index dc40ad9..5968d01 100644 if (num_bytes <= 0) { print_err("num_bytes is wrong [%d]\n", num_bytes); -@@ -781,10 +787,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -781,10 +823,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) else { @@ -590,7 +703,7 @@ index dc40ad9..5968d01 100644 #ifndef FCN_ADAPT if(valid_res != 0) { -@@ -807,8 +812,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -807,8 +848,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) PrachCfg = &(p_dev_ctx->PrachCPConfig); } @@ -600,7 +713,7 @@ index dc40ad9..5968d01 100644 /* PRACH packet has ruportid = num_eAxc + ant_id */ Ant_ID -= PrachCfg->eAxC_offset; symbol_total_bytes[p_dev_ctx->xran_port_id][CC_ID][Ant_ID] += num_bytes; -@@ -1412,7 +1416,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc +@@ -1412,7 +1452,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc if(XRAN_FILTERINDEX_PRACH_ABC == pPrachCPConfig->filterIdx) { timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu @@ -609,7 +722,7 @@ index dc40ad9..5968d01 100644 timeOffset += 16; } else -@@ -1547,8 +1551,7 @@ int32_t ring_processing_func(void* args) +@@ -1547,8 +1587,7 @@ int32_t ring_processing_func(void* args) for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i++){ for(qi = 0; qi < ctx->rxq_per_port[i]; qi++) { @@ -918,8 +1031,58 @@ index 4acade1..c939edc 100644 if(pCtx){ for(i = 0; i < xran_ports_num; i++){ g_xran_dev_ctx[i] = pCtx; +diff --git a/fhi_lib/lib/src/xran_dev.h b/fhi_lib/lib/src/xran_dev.h +index 0371a53..dd76b49 100644 +--- a/fhi_lib/lib/src/xran_dev.h ++++ b/fhi_lib/lib/src/xran_dev.h +@@ -201,6 +201,7 @@ struct __rte_cache_aligned xran_device_ctx + + int32_t DynamicSectionEna; + int32_t RunSlotPrbMapBySymbolEnable; ++ uint8_t LiteOnIgnoreUPSectionIdEnable; /**< handle LiteOn issue where section id on UP packet is wrongly set to 13. */ + int64_t offset_sec; + int64_t offset_nsec; //offset to GPS time calcuated based on alpha and beta + uint32_t interval_us_local; +diff --git a/fhi_lib/lib/src/xran_frame_struct.c b/fhi_lib/lib/src/xran_frame_struct.c +index fbb1298..44aaf92 100644 +--- a/fhi_lib/lib/src/xran_frame_struct.c ++++ b/fhi_lib/lib/src/xran_frame_struct.c +@@ -519,4 +519,20 @@ int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlot + return xran_fs_slot_symb_type[PortId][nCellIdx][nSfIdxMod][nSymbIdx]; + } + ++uint32_t xran_fs_get_num_dl_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx) ++{ ++ int32_t nSfIdxMod; ++ ++ nSfIdxMod = xran_fs_slot_limit(PortId, nSlotdx) % ((xran_fs_num_slot_tdd_loop[PortId][nCellIdx] > 0) ? xran_fs_num_slot_tdd_loop[PortId][nCellIdx]: 1); ++ ++ return xran_fs_num_dl_sym_sp[PortId][nCellIdx][nSfIdxMod]; ++} + ++uint32_t xran_fs_get_num_ul_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx) ++{ ++ int32_t nSfIdxMod; ++ ++ nSfIdxMod = xran_fs_slot_limit(PortId, nSlotdx) % ((xran_fs_num_slot_tdd_loop[PortId][nCellIdx] > 0) ? xran_fs_num_slot_tdd_loop[PortId][nCellIdx]: 1); ++ ++ return xran_fs_num_ul_sym_sp[PortId][nCellIdx][nSfIdxMod]; ++} +diff --git a/fhi_lib/lib/src/xran_frame_struct.h b/fhi_lib/lib/src/xran_frame_struct.h +index 7ed0a3a..8e66945 100644 +--- a/fhi_lib/lib/src/xran_frame_struct.h ++++ b/fhi_lib/lib/src/xran_frame_struct.h +@@ -75,6 +75,8 @@ uint32_t xran_fs_slot_limit_init(uint32_t PortId, int32_t tti_interval_us); + uint32_t xran_fs_get_max_slot(uint32_t PortId); + uint32_t xran_fs_get_max_slot_SFN(uint32_t PortId); + int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx, int32_t nSymbIdx); ++uint32_t xran_fs_get_num_dl_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx); ++uint32_t xran_fs_get_num_ul_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx); + + #ifdef __cplusplus + } diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c -index 7c472d7..9da3621 100644 +index 7c472d7..7c7cf91 100644 --- a/fhi_lib/lib/src/xran_main.c +++ b/fhi_lib/lib/src/xran_main.c @@ -35,7 +35,11 @@ @@ -974,7 +1137,7 @@ index 7c472d7..9da3621 100644 beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, port_id, slot_id); + pBufList = &(p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList); -+ struct xran_prb_map *prbMap = pBufList->pBuffers->pData; ++ struct xran_prb_map *prbMap = (struct xran_prb_map *)pBufList->pBuffers->pData; + struct xran_prb_elm *pPrbElm = &prbMap->prbMap[0]; //mjoang + beam_id = pPrbElm->nBeamIndex; ret = generate_cpmsg_prach(pHandle, ¶ms, sect_geninfo, mbuf, p_xran_dev_ctx, @@ -985,7 +1148,7 @@ index 7c472d7..9da3621 100644 beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, port_id, slot_id); + pBufList = &(p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList); -+ struct xran_prb_map *prbMap = pBufList->pBuffers->pData; ++ struct xran_prb_map *prbMap = (struct xran_prb_map *)pBufList->pBuffers->pData; + struct xran_prb_elm *pPrbElm = &prbMap->prbMap[0]; //mjoang + beam_id = pPrbElm->nBeamIndex; ret = generate_cpmsg_prach(pHandle, ¶ms, sect_geninfo, mbuf, p_xran_dev_ctx, @@ -1550,7 +1713,15 @@ index 7c472d7..9da3621 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -4034,6 +4062,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, +@@ -3754,6 +3782,7 @@ xran_open(void *pHandle, struct xran_fh_config* pConf) + p_xran_dev_ctx->puschMaskSlot = pConf->puschMaskSlot; + p_xran_dev_ctx->DynamicSectionEna = pConf->DynamicSectionEna; + p_xran_dev_ctx->RunSlotPrbMapBySymbolEnable = pConf->RunSlotPrbMapBySymbolEnable; ++ p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable = pConf->LiteOnIgnoreUPSectionIdEnable; + p_xran_dev_ctx->dssEnable = pConf->dssEnable; + p_xran_dev_ctx->dssPeriod = pConf->dssPeriod; + for(i=0; idssPeriod; i++) { +@@ -4034,6 +4063,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, return tti; } @@ -1575,6 +1746,73 @@ index 7c472d7..9da3621 100644 int32_t xran_set_debug_stop(int32_t value, int32_t count) { +@@ -4208,7 +4255,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str + int32_t i = 0, j = 0, nPrbElm = 0; + int16_t iqwidth = p_PrbMapIn->prbMap[0].iqWidth; + struct xran_prb_elm *p_prb_elm_src, *p_prb_elm_dst; +- struct xran_prb_elm prbMapTemp[XRAN_NUM_OF_SYMBOL_PER_SLOT]; ++ struct xran_prb_elm prbMapTemp[XRAN_NUM_OF_SYMBOL_PER_SLOT] = {0} ; // Need to initialize to zero for field sec_desc. + int32_t nRBStart_tmp, nRBremain, nStartSymb, nEndSymb, nRBStart, nRBEnd, nRBSize; + // int32_t eth_xran_up_headers_sz = sizeof(struct eth_xran_up_pkt_hdr); + // int32_t nmaxRB = (mtu - eth_xran_up_headers_sz - RTE_PKTMBUF_HEADROOM)/XRAN_PAYLOAD_1_RB_SZ(iqwidth); +@@ -4217,7 +4264,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str + if (mtu==9600) + nmaxRB--; //for some reason when mtu is 9600, only 195 RB can be sent, not 196 + +- + memcpy(p_PrbMapOut, p_PrbMapIn, sizeof(struct xran_prb_map)); + for(i = 0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) + { +@@ -4292,26 +4338,30 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str + + for(; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) + { +- if((nRBStart == prbMapTemp[i].nRBStart) && (nRBSize == prbMapTemp[i].nRBSize)) +- { +- prbMapTemp[nPrbElm].numSymb++; +- } +- else ++ if((prbMapTemp[i].nRBSize != 0)) + { +- nPrbElm++; +- prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; +- prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; +- prbMapTemp[nPrbElm].nRBSize = prbMapTemp[i].nRBSize; +- prbMapTemp[nPrbElm].nBeamIndex = prbMapTemp[i].nBeamIndex; +- prbMapTemp[nPrbElm].bf_weight_update = prbMapTemp[i].bf_weight_update; +- prbMapTemp[nPrbElm].compMethod = prbMapTemp[i].compMethod; +- prbMapTemp[nPrbElm].iqWidth = prbMapTemp[i].iqWidth; +- prbMapTemp[nPrbElm].ScaleFactor = prbMapTemp[i].ScaleFactor; +- prbMapTemp[nPrbElm].reMask = prbMapTemp[i].reMask; +- prbMapTemp[nPrbElm].BeamFormingType = prbMapTemp[i].BeamFormingType; +- +- nRBStart = prbMapTemp[i].nRBStart; +- nRBSize = prbMapTemp[i].nRBSize; ++ if (false) // Force it to generate multiple prbMapElm, one for each symbol even if they are of the same RBs ++ //if((nRBStart == prbMapTemp[i].nRBStart) && (nRBSize == prbMapTemp[i].nRBSize)) ++ { ++ prbMapTemp[nPrbElm].numSymb++; ++ } ++ else ++ { ++ nPrbElm++; ++ prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; ++ prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; ++ prbMapTemp[nPrbElm].nRBSize = prbMapTemp[i].nRBSize; ++ prbMapTemp[nPrbElm].nBeamIndex = prbMapTemp[i].nBeamIndex; ++ prbMapTemp[nPrbElm].bf_weight_update = prbMapTemp[i].bf_weight_update; ++ prbMapTemp[nPrbElm].compMethod = prbMapTemp[i].compMethod; ++ prbMapTemp[nPrbElm].iqWidth = prbMapTemp[i].iqWidth; ++ prbMapTemp[nPrbElm].ScaleFactor = prbMapTemp[i].ScaleFactor; ++ prbMapTemp[nPrbElm].reMask = prbMapTemp[i].reMask; ++ prbMapTemp[nPrbElm].BeamFormingType = prbMapTemp[i].BeamFormingType; ++ ++ nRBStart = prbMapTemp[i].nRBStart; ++ nRBSize = prbMapTemp[i].nRBSize; ++ } + } + } + diff --git a/fhi_lib/lib/src/xran_mem_mgr.c b/fhi_lib/lib/src/xran_mem_mgr.c index e1dcb6c..b3c3fae 100644 --- a/fhi_lib/lib/src/xran_mem_mgr.c @@ -1608,7 +1846,7 @@ index 7d4a5d0..b9b44ac 100644 #endif } diff --git a/fhi_lib/lib/src/xran_rx_proc.c b/fhi_lib/lib/src/xran_rx_proc.c -index e7056f4..0d3d8ac 100644 +index e7056f4..34b6d3b 100644 --- a/fhi_lib/lib/src/xran_rx_proc.c +++ b/fhi_lib/lib/src/xran_rx_proc.c @@ -35,7 +35,11 @@ @@ -1623,6 +1861,127 @@ index e7056f4..0d3d8ac 100644 #include #include +@@ -339,13 +343,33 @@ int32_t xran_process_srs_sym(void *arg, + pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFHSrsRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData; + if(pRbMap) + { +- prbMapElm = &pRbMap->prbMap[sect_id]; +- if(sect_id >= pRbMap->nPrbElm) ++ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { ++ section_id_tmp = prb_elem_id_tmp = sect_id; ++ } else { ++ /** Get the prb_elem_id */ ++ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx); ++ u_int8_t mixed_ul_sym_start = 0; ++ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) { ++ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti); ++ } ++ ++ section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ //Note for future reference when using MTU 1500 ++ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ } ++ ++ prbMapElm = &pRbMap->prbMap[prb_elem_id_tmp /*sect_id*/]; ++ if(/*sect_id*/ prb_elem_id_tmp >= pRbMap->nPrbElm) + { +- print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm); +- *mb_free = MBUF_FREE; +- return size; +- } ++ print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm); ++ *mb_free = MBUF_FREE; ++ return size; ++ } + } + else + { +@@ -397,7 +421,25 @@ int32_t xran_process_srs_sym(void *arg, + else */ + { + struct xran_section_desc *p_sec_desc = NULL; +- prbMapElm = &pRbMap->prbMap[sect_id]; ++ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { ++ section_id_tmp = prb_elem_id_tmp = sect_id; ++ } else { ++ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx); ++ u_int8_t mixed_ul_sym_start = 0; ++ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) { ++ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti); ++ } ++ u_int8_t section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ //Note for future reference when using MTU 1500 ++ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ } ++ ++ prbMapElm = &pRbMap->prbMap[prb_elem_id_tmp /*sect_id*/]; + // sec_desc_idx = 0;//prbMapElm->nSecDesc[symb_id]; + sec_desc_idx = prbMapElm->nSecDesc[symb_id]; + +@@ -537,14 +579,33 @@ int32_t xran_process_rx_sym(void *arg, + pos = (char*) p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData; + pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData; + if(pRbMap){ +- /** Get the prb_elem_id */ ++ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 ++ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { ++ section_id_tmp = prb_elem_id_tmp = sect_id; ++ } else { ++ /** Get the prb_elem_id */ ++ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx); ++ u_int8_t mixed_ul_sym_start = 0; ++ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) { ++ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti); ++ } ++ ++ section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 ++ //Note for future reference when using MTU 1500 ++ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ } ++ + total_sections=0; + if(pRbMap->prbMap[0].bf_weight.extType == 1) + { + for(i=0 ; i < pRbMap->nPrbElm ; i++) + { + total_sections += pRbMap->prbMap[i].bf_weight.numSetBFWs; +- if(total_sections >= (sect_id + 1)) ++ if(total_sections >= (/*sect_id*/ section_id_tmp + 1)) + { + prb_elem_id = i; + break; +@@ -553,7 +614,7 @@ int32_t xran_process_rx_sym(void *arg, + } + else + { +- prb_elem_id = sect_id; ++ prb_elem_id = prb_elem_id_tmp; /*sect_id*/; + } + + prbMapElm = &pRbMap->prbMap[prb_elem_id]; +@@ -597,7 +658,7 @@ int32_t xran_process_rx_sym(void *arg, + if(p_sec_desc){ + mb = p_sec_desc->pCtrl; + if(mb){ +- rte_pktmbuf_free(mb); ++ rte_pktmbuf_free(mb); + } + p_sec_desc->pData = iq_data_start; + p_sec_desc->pCtrl = mbuf; diff --git a/fhi_lib/lib/src/xran_timer.c b/fhi_lib/lib/src/xran_timer.c index 14a6a41..55182d8 100644 --- a/fhi_lib/lib/src/xran_timer.c diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index fb40852ebb..6e918650e5 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(oran_fhlib_5g MODULE ) set(E_VERSION 5.1.6) -set(F_VERSION 6.1.5) +set(F_VERSION 6.1.6) find_package(xran REQUIRED) if(xran_VERSION VERSION_EQUAL E_VERSION) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index b0ed41decb..149f492e6a 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -102,6 +102,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMap == 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++) { + LOG_D(HW, "cb pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) { struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; pRbElm->nSecDesc[sym_id] = 0; // number of section descriptors per symbol; M-plane info @@ -265,6 +266,28 @@ static bool is_tdd_ul_symbol(const struct xran_frame_config *frame_conf, int slo return frame_conf->sSlotConfig[slot_in_period].nSymbolType[sym_idx] == 1 /* UL */; } +/** @brief Check if symbol in slot is DL. + * + * @param frame_conf xran frame configuration + * @param slot the current (absolute) slot (number) + * @param sym_idx the current symbol index */ +static bool is_tdd_dl_symbol(const struct xran_frame_config *frame_conf, int slot, int sym_idx) +{ + /* in FDD, every symbol is also UL */ + if (frame_conf->nFrameDuplexType == XRAN_FDD) + return true; + int tdd_period = frame_conf->nTddPeriod; + int slot_in_period = slot % tdd_period; + /* check if symbol is UL */ + return frame_conf->sSlotConfig[slot_in_period].nSymbolType[sym_idx] == 0 /* DL */; +} + +/** @brief Check if current slot is guard/mixed */ +static bool is_tdd_guard_slot(const struct xran_frame_config *frame_conf, int slot) +{ + return (is_tdd_dl_symbol(frame_conf, slot, 0) && is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1)); +} + /** @brief Check if current slot is DL or guard/mixed without UL (i.e., current * slot is not UL). */ static bool is_tdd_dl_guard_slot(const struct xran_frame_config *frame_conf, int slot) @@ -678,3 +701,470 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) } return (0); } + +/** @details Read PRACH and PUSCH data from xran buffers. If + * I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data + * before writing. Prints ON TIME counters every 128 frames. + * + * Function is blocking and waits for next frame/slot combination. It is unblocked + * by oai_xran_fh_rx_callback(). It writes the current slot into parameters + * frame/slot. */ +int xran_fh_rx_read_slot_BySymbol(ru_info_t *ru, int *frame, int *slot) +{ + void *ptr = NULL; + int32_t *pos = NULL; + int idx = 0; + + static int64_t old_rx_counter[XRAN_PORTS_NUM] = {0}; + static int64_t old_tx_counter[XRAN_PORTS_NUM] = {0}; + struct xran_common_counters x_counters[XRAN_PORTS_NUM]; + static int outcnt = 0; + #ifndef USE_POLLING + // pull next even from oran_sync_fifo + notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo); + + notifiedFIFO_elt_t *f; + while ((f = pollNotifiedFIFO(&oran_sync_fifo)) != NULL) { + oran_sync_info_t *old_info = NotifiedFifoData(res); + oran_sync_info_t *new_info = NotifiedFifoData(f); + LOG_E(HW, "Detected double sync message %d.%d => %d.%d\n", old_info->f, old_info->sl, new_info->f, new_info->sl); + delNotifiedFIFO_elt(res); + res = f; + } + + oran_sync_info_t *info = NotifiedFifoData(res); + + *slot = info->sl; + *frame = info->f; + delNotifiedFIFO_elt(res); +#else + *slot = oran_sync_info.sl; + *frame = oran_sync_info.f; + uint32_t tti_in = oran_sync_info.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.tti) { + //*slot = oran_sync_info.sl; + cnt++; + } + LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot); + last_slot = *slot; +#endif + // return(0); + + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; + + int tti = slots_per_frame * (*frame) + (*slot); + + read_prach_data(ru, *frame, *slot); + + const struct xran_fh_init *fh_init = get_xran_fh_init(); + int nPRBs = fh_cfg->nULRBs; + int fftsize = 1 << fh_cfg->ru_conf.fftSize; + + int slot_offset_rxdata = 3 & (*slot); + uint32_t slot_size = 4 * 14 * fftsize; + uint8_t *rx_data = (uint8_t *)ru->rxdataF[0]; + uint8_t *start_ptr = NULL; + int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; + for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. + for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { + rx_data = (uint8_t *)ru->rxdataF[ant_id]; + start_ptr = rx_data + (slot_size * slot_offset_rxdata); + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; + // skip processing this slot is TX (no RX in this slot) + if (!is_tdd_ul_guard_slot(frame_conf, *slot)) + continue; + bool sym_start_found = false; + int32_t sym_start = 0; + // This loop would better be more inner to avoid confusion and maybe also errors. + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + /* the callback is for mixed and UL slots. In mixed, we have to + * skip DL and guard symbols. */ + if (!is_tdd_ul_symbol(frame_conf, *slot, sym_idx)) + continue; + if (!sym_start_found) { + sym_start = sym_idx; + sym_start_found = true; + } + + uint8_t *pData; + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); + uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + + struct xran_prb_map *pRbMap = pPrbMap; + for (int idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { + struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; +#ifdef E_RELEASE + struct xran_section_desc *p_sec_desc = pRbElm->p_sec_desc[sym_idx][0]; + uint32_t one_rb_size = + (((pRbElm->iqWidth == 0) || (pRbElm->iqWidth == 16)) ? (N_SC_PER_PRB * 2 * 2) : (3 * pRbElm->iqWidth + 1)); + if (fh_init->mtu < pRbElm->nRBSize * one_rb_size) + pData = bufs->dst[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN] + .pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT] + .pData; + else + pData = p_sec_desc->pData; +#elif defined F_RELEASE + struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0]; + pData = p_sec_desc->pData; +#endif + ptr = pData; + pos = (int32_t *)(start_ptr + (4 * sym_idx * fftsize)); + if (ptr == NULL || pos == NULL) + continue; + + uint8_t *src = (uint8_t *)ptr; + + LOG_D(HW, "rx pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + u_int8_t section_id_tmp = pPrbMap->nPrbElm < XRAN_NUM_OF_SYMBOL_PER_SLOT ? sym_idx - sym_start: sym_idx; + if (section_id_tmp != pRbElm->nSectId) { + LOG_D(HW, + "rx prbMap[%d] : PRBstart %d nPRBs %d nSectId %d != sym_idx %d:%d\n", + idxElm, + pRbMap->prbMap[idxElm].nRBStart, + pRbMap->prbMap[idxElm].nRBSize, + pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp + ); + continue; + } + LOG_D(HW, + "rx prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d sym_idx %d:%d\n", + idxElm, + pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, + pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, + pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp + ); + + int pos_len = 0; + int neg_len = 0; + int num_prbu = p_sec_desc->num_prbu; + int start_prbu = p_sec_desc->start_prbu; + if (start_prbu < (nPRBs >> 1)) // there are PRBs left of DC + neg_len = min((nPRBs * 6) - (start_prbu * 12), num_prbu * N_SC_PER_PRB); + pos_len = (num_prbu * N_SC_PER_PRB) - neg_len; + + src = pData; + // Calculation of the pointer for the section in the buffer. + // positive half + uint8_t *dst1 = (uint8_t *)(pos + (neg_len == 0 ? ((start_prbu * N_SC_PER_PRB) - (nPRBs * 6)) : 0)); + // negative half + uint8_t *dst2 = (uint8_t *)(pos + (start_prbu * N_SC_PER_PRB) + fftsize - (nPRBs * 6)); + int32_t local_dst[num_prbu * N_SC_PER_PRB] __attribute__((aligned(64))); + if (pRbElm->compMethod == XRAN_COMPMETHOD_NONE) { + // NOTE: gcc 11 knows how to generate AVX2 for this! + for (idx = 0; idx < num_prbu * N_SC_PER_PRB * 2; idx++) + ((int16_t *)local_dst)[idx] = ((int16_t)ntohs(((uint16_t *)src)[idx])) >> 2; + memcpy((void *)dst2, (void *)local_dst, neg_len * 4); + memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); + } else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { +#if defined(__i386__) || defined(__x86_64__) + struct xranlib_decompress_request bfp_decom_req = {}; + struct xranlib_decompress_response bfp_decom_rsp = {}; + + int16_t payload_len = (3 * pRbElm->iqWidth + 1) * num_prbu; + + bfp_decom_req.data_in = (int8_t *)src; + bfp_decom_req.numRBs = num_prbu; + bfp_decom_req.len = payload_len; + bfp_decom_req.compMethod = pRbElm->compMethod; + bfp_decom_req.iqWidth = pRbElm->iqWidth; + + bfp_decom_rsp.data_out = (int16_t *)local_dst; + bfp_decom_rsp.len = 0; + + xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp); +#elif defined(__arm__) || defined(__aarch64__) + armral_bfp_decompression(pRbElm->iqWidth, num_prbu, (int8_t *)src, (int16_t *)local_dst); +#else + AssertFatal(1 == 0, "BFP compression not supported on this architecture"); +#endif + memcpy((void *)dst2, (void *)local_dst, neg_len * 4); + memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); + outcnt++; + } else { + printf("pRbElm->compMethod == %d is not supported\n", pRbElm->compMethod); + exit(-1); + } + } + } // sym_ind + } // ant_ind + } // vv_inf + if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) { + for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) { + LOG_I(HW, + "[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n", + "o-du ", + o_xu_id, + x_counters[o_xu_id].rx_counter, + x_counters[o_xu_id].rx_counter - old_rx_counter[o_xu_id], + x_counters[o_xu_id].rx_bytes_per_sec * 8 / 1000L, + x_counters[o_xu_id].tx_counter, + x_counters[o_xu_id].tx_counter - old_tx_counter[o_xu_id], + x_counters[o_xu_id].tx_bytes_per_sec * 8 / 1000L, + x_counters[o_xu_id].Total_msgs_rcvd); + for (int rxant = 0; rxant < ru->nb_rx / fh_init->xran_ports; rxant++) + LOG_I(HW, + "[%s%d][pusch%d %7ld prach%d %7ld]\n", + "o_du", + o_xu_id, + rxant, + x_counters[o_xu_id].rx_pusch_packets[rxant], + rxant, + x_counters[o_xu_id].rx_prach_packets[rxant]); + if (x_counters[o_xu_id].rx_counter > old_rx_counter[o_xu_id]) + old_rx_counter[o_xu_id] = x_counters[o_xu_id].rx_counter; + if (x_counters[o_xu_id].tx_counter > old_tx_counter[o_xu_id]) + old_tx_counter[o_xu_id] = x_counters[o_xu_id].tx_counter; + } + } + return (0); +} + +/** @details Write PDSCH IQ-data from OAI txdataF_BF buffer to xran buffers. If + * I/Q compression (bitwidth < 16 bits) is configured, compresses the data + * before writing. */ +int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t timestamp) +{ + int tti = /*frame*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME+*/ 20 * frame + + slot; // commented out temporarily to check that compilation of oran 5g is working. + + void *ptr = NULL; + int32_t *pos = NULL; + int idx = 0; + + const struct xran_fh_init *fh_init = get_xran_fh_init(); + const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int nPRBs = fh_cfg->nDLRBs; + int fftsize = 1 << fh_cfg->ru_conf.fftSize; + int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; + int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; + + // Handle CP UL packet here instead of at xran_fh_rx_read_slot() as oran_fh_if4p5_south_in() lags behind + // oran_fh_if4p5_south_out() (which is invoked at the right time slot) by 4 slots. + // Need to use --continuous-tx so that this routine will be triggered in RX slot. + for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. + for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; + // skip processing this slot is TX (no RX in this slot) + if (!is_tdd_ul_guard_slot(frame_conf, slot)) { + continue; + } + bool sym_start_found = false; + int32_t sym_start = 0; + // This loop would better be more inner to avoid confusion and maybe also errors. + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + /* the callback is for mixed and UL slots. In mixed, we have to + * skip DL and guard symbols. */ + if (!is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { + continue; + } + if (!sym_start_found) { + sym_start = sym_idx; + sym_start_found = true; + } + + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); + uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + + struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; + + struct xran_prb_map *pRbMap = pPrbMap; + uint32_t idxElm = 0; + + LOG_D(HW, "tx0 pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); + for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { + LOG_D(HW, "prbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].nRBSize); + pRbElm = &pRbMap->prbMap[idxElm]; + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + u_int8_t section_id_tmp = pPrbMap->nPrbElm < XRAN_NUM_OF_SYMBOL_PER_SLOT ? sym_idx - sym_start: sym_idx; + if (section_id_tmp != pRbElm->nSectId) { + LOG_D(HW, + "tx0 prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d != sym_idx %d:%d\n", + idxElm, + pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, + pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, + pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp + ); + continue; + } + LOG_D(HW, + "tx0 prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d sym_idx %d:%d\n", + idxElm, + pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, + pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, + pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp + ); + + // ant_id / no of antenna per beam gives the beam_nb + pRbElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (pRbElm->nBeamIndex == -1) + pRbElm->nBeamIndex = 0; + } + } + } + } + + for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. + for (uint8_t ant_id = 0; ant_id < ru->nb_tx; ant_id++) { + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru); + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_tx_per_ru)->frame_conf; + // skip processing this slot is TX (no TX in this slot) + if (!is_tdd_dl_guard_slot(frame_conf, slot)) { + continue; + } + + // Set nPrbElm if beam_id = -1 for all downlink symbols + bool beam_used = false; + uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + struct xran_prb_map *pRbMap = pPrbMap; + int32_t dl_sym_end = 0; + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + if (is_tdd_dl_symbol(frame_conf, slot, sym_idx)) { + if (ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx] != -1) + beam_used |= true; + } + else { + dl_sym_end = sym_idx; + break; + } + } + if (is_tdd_guard_slot(frame_conf, slot)) + pRbMap->nPrbElm = dl_sym_end; + else + pRbMap->nPrbElm = XRAN_NUM_OF_SYMBOL_PER_SLOT; + if (!beam_used) { + pRbMap->nPrbElm = 0; + continue; + } + + // This loop would better be more inner to avoid confusion and maybe also errors. + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + /* the callback is for mixed and UL slots. In mixed, we have to + * skip UL and guard symbols. */ + if (is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { + continue; + } + uint8_t *pData = + bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData; + uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + ptr = pData; + pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize]; + + uint8_t *u8dptr; + struct xran_prb_map *pRbMap = pPrbMap; + int32_t sym_id = sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT; + if (ptr && pos) { + uint32_t idxElm = 0; + u8dptr = (uint8_t *)ptr; + int16_t payload_len = 0; + + uint8_t *dst = (uint8_t *)u8dptr; + + struct xran_prb_elm *p_prbMapElm = &pRbMap->prbMap[idxElm]; + LOG_D(HW, "tx1 pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); + for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + struct xran_section_desc *p_sec_desc = NULL; + p_prbMapElm = &pRbMap->prbMap[idxElm]; + if (sym_idx != p_prbMapElm->nSectId) + continue; + // ant_id / no of antenna per beam gives the beam_nb + p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (p_prbMapElm->nBeamIndex == -1) + p_prbMapElm->nBeamIndex = 0; + + // assumes one fragment per symbol +#ifdef E_RELEASE + p_sec_desc = p_prbMapElm->p_sec_desc[sym_id][0]; +#elif F_RELEASE + p_sec_desc = &p_prbMapElm->sec_desc[sym_id][0]; +#endif + + dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); + + if (p_sec_desc == NULL) { + printf("p_sec_desc == NULL\n"); + exit(-1); + } + uint16_t *dst16 = (uint16_t *)dst; + + int pos_len = 0; + int neg_len = 0; + + if (p_prbMapElm->UP_nRBStart < (nPRBs >> 1)) // there are PRBs left of DC + neg_len = min((nPRBs * 6) - (p_prbMapElm->UP_nRBStart * 12), p_prbMapElm->UP_nRBSize * N_SC_PER_PRB); + pos_len = (p_prbMapElm->UP_nRBSize * N_SC_PER_PRB) - neg_len; + // Calculation of the pointer for the section in the buffer. + // start of positive frequency component + uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0]; + // start of negative frequency component + uint16_t *src2 = (uint16_t *)&pos[(p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6)]; + + uint32_t local_src[p_prbMapElm->UP_nRBSize * N_SC_PER_PRB] __attribute__((aligned(64))); + memcpy((void *)local_src, (void *)src2, neg_len * 4); + memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); + if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { + payload_len = p_prbMapElm->UP_nRBSize * N_SC_PER_PRB * 4L; + /* convert to Network order */ + // NOTE: ggc 11 knows how to generate AVX2 for this! + for (idx = 0; idx < (pos_len + neg_len) * 2; idx++) + ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]); + } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { + payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->UP_nRBSize; + +#if defined(__i386__) || defined(__x86_64__) + struct xranlib_compress_request bfp_com_req = {}; + struct xranlib_compress_response bfp_com_rsp = {}; + + bfp_com_req.data_in = (int16_t *)local_src; + bfp_com_req.numRBs = p_prbMapElm->UP_nRBSize; + bfp_com_req.len = payload_len; + bfp_com_req.compMethod = p_prbMapElm->compMethod; + bfp_com_req.iqWidth = p_prbMapElm->iqWidth; + + bfp_com_rsp.data_out = (int8_t *)dst; + bfp_com_rsp.len = 0; + + xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); +#elif defined(__arm__) || defined(__aarch64__) + armral_bfp_compression(p_prbMapElm->iqWidth, p_prbMapElm->UP_nRBSize, (int16_t *)local_src, (int8_t *)dst); +#else + AssertFatal(1 == 0, "BFP compression not supported on this architecture"); +#endif + + } else { + printf("p_prbMapElm->compMethod == %d is not supported\n", p_prbMapElm->compMethod); + exit(-1); + } + + p_sec_desc->iq_buffer_offset = RTE_PTR_DIFF(dst, u8dptr); + p_sec_desc->iq_buffer_len = payload_len; + + dst += payload_len; + dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); + } + + // The tti should be updated as it increased. + pRbMap->tti_id = tti; + + } else { + printf("ptr ==NULL\n"); + exit(-1); // fails here?? + } + } + } + } + return (0); +} diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 3a8e60ebdb..00c13bc64d 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -431,10 +431,12 @@ void print_fh_config(const struct xran_fh_config *fh_config) #ifdef F_RELEASE printf("\ RunSlotPrbMapBySymbolEnable %d\n\ + LiteOnIgnoreUPSectionIdEnable %d\n\ dssEnable %d\n\ dssPeriod %d\n\ technology[XRAN_MAX_DSS_PERIODICITY] (not filled as DSS disabled)\n", fh_config->RunSlotPrbMapBySymbolEnable, + fh_config->LiteOnIgnoreUPSectionIdEnable, fh_config->dssEnable, fh_config->dssPeriod); #endif @@ -754,7 +756,8 @@ static bool set_fh_prach_config(void *mplane_api, const uint32_t max_num_ant, const paramdef_t *prachp, int nprach, - struct xran_prach_config *prach_config) + struct xran_prach_config *prach_config, + bool liteon_prach_eAxC_offset) { const split7_config_t *s7cfg = &oai0->split7; @@ -791,7 +794,10 @@ static bool set_fh_prach_config(void *mplane_api, prach_config->eAxC_offset = xran_mplane->prach_offset; #else uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr; - prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant; + if (liteon_prach_eAxC_offset) + prach_config->eAxC_offset = offset; + else + prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant; #endif g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr; @@ -937,9 +943,14 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->enableCP = 1; // enable C-plane fh_config->prachEnable = 1; // enable PRACH fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B + // For LiteOn E release, no need to take care of prach eAxC_offset. xran lib is hacked to handle it. + bool liteon_prach_eAxC_offset = false; #ifdef F_RELEASE fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B + fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_RunSlotPrbMapBySymbol)->uptr; // enable RunSlotPrbMapBySymbol + fh_config->LiteOnIgnoreUPSectionIdEnable = *gpd(fhp, nfh, ORAN_CONFIG_LiteOnIgnoreUPSectionId)->uptr; // enable LiteOnIgnoreUPSectionId + liteon_prach_eAxC_offset = fh_config->LiteOnIgnoreUPSectionIdEnable; #endif 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 @@ -951,7 +962,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100 - if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf)) + if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf, liteon_prach_eAxC_offset)) return false; /* SRS only used if XRAN_CATEGORY_B Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */ @@ -983,8 +994,6 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->max_sections_per_symbol = 0; // not used in xran #ifdef F_RELEASE - fh_config->RunSlotPrbMapBySymbolEnable = 0; // enable PRB mapping by symbol with multisection - fh_config->dssEnable = 0; // enable DSS (extension-9) fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR // fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 516c2795fe..9707084a2f 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -333,6 +333,7 @@ static void oran_allocate_buffers(void *handle, struct xran_prb_map dlPmMixed = {0}; struct xran_prb_map ulPmMixed = {0}; uint32_t idx = 0; + if (fh_config->frame_conf.nFrameDuplexType == XRAN_TDD) { oran_mixed_slot_t info = get_mixed_slot_info(&fh_config->frame_conf); dlPmMixed = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, info.num_dlsym); @@ -357,8 +358,16 @@ static void oran_allocate_buffers(void *handle, #ifdef E_RELEASE uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (xran_max_sections_per_slot - 1); #elif defined F_RELEASE - uint32_t numPrbElm = 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; + if (fh_config->RunSlotPrbMapBySymbolEnable) { + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable, xran_prb_map will have xran_prb_elm prbMap[14] + size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (XRAN_NUM_OF_SYMBOL_PER_SLOT); + } + else { + // For non-Liteon w/o RunSlotPrbMapBySymbolEnable, xran_prb_map will have xran_prb_elm prbMap[1] + uint32_t numPrbElm = xran_get_num_prb_elm(&dlPm, mtu); + size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm); + } #endif // PDSCH diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index baeefbc68d..9f12418909 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -95,6 +95,8 @@ #define CONFIG_STRING_ORAN_FH "fh_config" +#define ORAN_CONFIG_RunSlotPrbMapBySymbol "RunSlotPrbMapBySymbol" +#define ORAN_CONFIG_LiteOnIgnoreUPSectionId "LiteOnIgnoreUPSectionId" #define ORAN_FH_CONFIG_T1A_CP_DL "T1a_cp_dl" #define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul" #define ORAN_FH_CONFIG_T1A_UP "T1a_up" @@ -104,10 +106,12 @@ // clang-format off #define ORAN_FH_DESC { \ - {ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ - {ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ - {ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ - {ORAN_FH_CONFIG_TA4, "Ta4" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {ORAN_CONFIG_RunSlotPrbMapBySymbol, "RunSlotPrbMapBySymbol\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ + {ORAN_CONFIG_LiteOnIgnoreUPSectionId, "Liteon Ignore Section Id\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ + {ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {ORAN_FH_CONFIG_TA4, "Ta4" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ } // clang-format on diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 679936d9c9..9b97b58390 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -228,7 +228,12 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) 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); + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int ret = 0; + if (fh_cfg->RunSlotPrbMapBySymbolEnable) + ret = xran_fh_rx_read_slot_BySymbol(&ru_info, &f, &sl); + else + 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) { @@ -283,7 +288,12 @@ void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) // printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp); - int ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int ret = 0; + if (fh_cfg->RunSlotPrbMapBySymbolEnable) + ret = xran_fh_tx_send_slot_BySymbol(&ru_info, frame, slot, timestamp); + else + ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); if (ret != 0) { printf("ORAN: ORAN_fh_if4p5_south_out ERROR in TX function \n"); } diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 6ec011a24b..bb3f17d42b 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -60,7 +60,9 @@ typedef struct ru_info_s { * @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); +int xran_fh_rx_read_slot_BySymbol(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); +int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t timestamp); #endif /* _ORAN_ISOLATE_H_ */