X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=blobdiff_plain;f=fhi_lib%2Fapp%2Fsrc%2Fapp_bbu_main.c;fp=fhi_lib%2Fapp%2Fsrc%2Fapp_bbu_main.c;h=93d2897865856a8fbd0b3c9074e00a33e79a29fe;hp=0000000000000000000000000000000000000000;hb=892daba4c616407f16506415d5a69549519ef11d;hpb=76b4495d593ccf45d712db1a3ec96fa9d2d8f5f5 diff --git a/fhi_lib/app/src/app_bbu_main.c b/fhi_lib/app/src/app_bbu_main.c new file mode 100644 index 0000000..93d2897 --- /dev/null +++ b/fhi_lib/app/src/app_bbu_main.c @@ -0,0 +1,562 @@ +/****************************************************************************** +* +* Copyright (c) 2020 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @brief This module provides implementation of BBU tasks for sample app + * @file app_bbu_main.c + * @ingroup xran + * @author Intel Corporation + * + **/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "app_bbu_pool.h" +#include "app_io_fh_xran.h" +#include "xran_mlog_task_id.h" + +/** + * @file app_bbu_main.c + * @brief example pipeline code to use Enhanced BBUPool Framework +*/ + +uint32_t gRunCount = 0; +volatile uint32_t nStopFlag = 1; +int32_t gQueueCtxNum = 1; + +int32_t nSplitNumCell[EBBU_POOL_MAX_TEST_CELL]; + +int32_t nTestCell = 0; +int32_t nTestCore = 0; +volatile uint64_t ttistart = 0; +int32_t dl_ul_count, dl_count, ul_count; + +uint32_t gMaxSlotNum[MAX_PHY_INSTANCES]; +uint32_t gNumDLCtx[MAX_PHY_INSTANCES]; +uint32_t gNumULCtx[MAX_PHY_INSTANCES]; +uint32_t gNumDLBufferCtx[MAX_PHY_INSTANCES]; +uint32_t gNumULBufferCtx[MAX_PHY_INSTANCES]; +uint32_t gDLProcAdvance[MAX_PHY_INSTANCES]; +int32_t gULProcAdvance[MAX_PHY_INSTANCES]; + + +#define EX_FUNC_NUM 9 +int32_t exGenDlFunc[EX_FUNC_NUM] = +{ + DL_CONFIG, + DL_PDSCH_SCRM, +}; +int32_t exGenUlFunc[EX_FUNC_NUM] = +{ + UL_CONFIG, + UL_IQ_DECOMP2, + UL_IQ_DECOMP6, + UL_IQ_DECOMP11, + UL_IQ_DECOMP13, + UL_PRACH, + UL_PUSCH_TB +}; + +int32_t exGenAllFunc[EX_FUNC_NUM] = +{ + DL_CONFIG, + UL_CONFIG, + DL_PDSCH_SCRM, + UL_IQ_DECOMP2, + UL_IQ_DECOMP6, + UL_IQ_DECOMP11, + UL_IQ_DECOMP13, + UL_PRACH, + UL_PUSCH_TB +}; + +peBbuPoolCfgVarsStruct pCfg; +pthread_t tCtrlThread; +eBbuPoolHandler pHandler = NULL; +clock_t tStart, tEnd; +uint32_t ttiCell[EBBU_POOL_MAX_TEST_CELL] = {0}; +uint64_t ttiCountCell[EBBU_POOL_MAX_TEST_CELL] = {0UL}; +uint32_t frameFormatCell[EBBU_POOL_MAX_TEST_CELL] = {0}; +uint64_t tTTI = 0; + + +eBbuPoolHandler app_get_ebbu_pool_handler(void) +{ + return pHandler; +} + + +int32_t +app_bbu_dl_tti_call_back(void * param) +{ + int32_t ret = 0; + uint64_t t1 = MLogTick(); + int32_t iCell = 0; + int32_t nCtx[EBBU_POOL_MAX_TEST_CELL] = {0}, iExFunc = 0, eventId = 0; + int32_t *exGenFuncDl = NULL, *exGenFuncUl = NULL; + int32_t nFuncNumDl = 0, nFuncNumUl = 0; + uint8_t Numerlogy = app_io_xran_fh_config[0].frame_conf.nNumerology; + uint8_t nNrOfSlotInSf = 1<testCellNum; + + for (i = 0; i < p_use_cfg->oXuNum; i++) + nFh_cell += p_o_xu_cfg[i]->numCC; + + if (nFh_cell != nTestCell) { + rte_panic("WARNING: miss match between BBU Cells (%d) and O-RAN FH Cells (%d)", nTestCell, nFh_cell); + } + + if(nTestCell > EBBU_POOL_MAX_TEST_CELL || nTestCell <= 0) + { + printf("Wrong cell num %d\n",nTestCell); + nTestCell = 0; + } + nTestCore = pCfg->testCoreNum; + if(nTestCore > EBBU_POOL_MAX_TEST_CORE || nTestCore <= 0) + { + printf("Wrong core num %d\n",nTestCore); + nTestCore = 0; + } + + gRunCount = 0; + + printf("Test cell %d, test total core num %d, test slots %d\n", nTestCell, nTestCore, gRunCount); + + // Step 1: create Framework handler + ebbu_pool_create_handler(&pHandler, 1, pCfg->mainThreadCoreId); + if(NULL == pHandler) + { + printf("\nFail to init Framework!"); + exit(-1); + } + + // Step 2: create priority queues + // Assume 3 queues + uint32_t nPrioQueue = pCfg->queueNum; + uint32_t nQueueSize = pCfg->queueDepth; + uint32_t pPrioQueueSize[8] = {nQueueSize, nQueueSize, nQueueSize, nQueueSize,nQueueSize, nQueueSize, nQueueSize, nQueueSize}; + QueueConfigStruct sQueueConfig; + sQueueConfig.pQueueDepth = pPrioQueueSize; + sQueueConfig.nPriQueueNum = nPrioQueue; + sQueueConfig.nPriQueueCtxNum = pCfg->ququeCtxNum; + sQueueConfig.nPriQueueCtxMaxFetch = pCfg->ququeCtxNum; + + ebbu_pool_create_queues(pHandler, sQueueConfig); + + ebbu_pool_queue_ctx_set_threshold(pHandler, 2*nTestCell); + + // Step 3: create one report for Framework + ReportCfg sReport; + sReport.nEventHoldNum = 2000; + sReport.pHandler = (void *)pHandler; + ebbu_pool_create_report(sReport); + + // Step 4: start control thread + // pthread_create(&tCtrlThread, NULL, controlThread, (void *)pHandler); + + peBbuPoolCfgVarsStruct pCfg = ebbu_pool_cfg_get_ctx(); + int32_t iCell = 0; + int32_t iCtx = 0; + uint32_t xran_timer = (1000/(1 << p_o_xu_cfg[0]->mu_number)); /* base on O-RU 0 */ + + printf("xran_timer for TTI [%d] us\n", xran_timer); + // Init base timing as per xran_timer + uint64_t tStart = ebbu_pool_tick(); + usleep(xran_timer); + tTTI = ebbu_pool_tick() - tStart; + + // cell specific TTI init + // create cell and create consumer thread + // set events num per cell + for(iCell = 0; iCell < nTestCell; iCell ++) + { + ttiCell[iCell] = pCfg->sTestCell[iCell].tti/xran_timer; + printf("\nttiCell[%d] %d", iCell, ttiCell[iCell]); + + frameFormatCell[iCell] = pCfg->sTestCell[iCell].frameFormat; + if(frameFormatCell[iCell] >= EBBU_POOL_MAX_FRAME_FORMAT) + frameFormatCell[iCell] = 0; + + for(iCtx = 0; iCtx < MAX_TEST_CTX; iCtx ++) + { + event_chain_gen(&gEventChain[iCell][iCtx]); + } + nSplitNumCell[iCell] = 1;//((pCfg->sTestCell[iCell].eventPerTti)-11)/18; //current event chain has 29 events, 19 of them can be split + printf("\nnSplitNumCell[%d] %d", iCell, nSplitNumCell[iCell]); + if(nSplitNumCell[iCell] > MAX_TEST_SPLIT_NUM) + nSplitNumCell[iCell] = MAX_TEST_SPLIT_NUM; + + } + test_buffer_create(); + + // add consumer thread + + /*int32_t corePool[EBBU_POOL_MAX_TEST_CORE] = {4,24,5,25,6,26,7,27, + 8,28,9,29,10,30,11,31, + 12,32,13,33,14,34,15,35, + 16,36,17,37,18,38,19,39, + 2,22,3,23}; + */ + + int32_t iCore = 0; + uint64_t nMask0 = 0UL, nMask1 = 0UL; + uint32_t iCoreIdx = 0; + uint64_t nCoreMask[EBBUPOOL_MAX_CORE_MASK]; + + for(; iCore < nTestCore; iCore ++) + { + iCoreIdx = pCfg->testCoreList[iCore]; + if(iCoreIdx < 64) + nMask0 |= 1UL << iCoreIdx; + else + nMask1 |= 1UL << iCoreIdx; + + } + //printf("\nnStartMask %016lx\n", nStartMask); + + nActiveCoreMask[0] = nCoreMask[0] = nMask0; + nActiveCoreMask[0] = nCoreMask[1] = nMask1; + nActiveCoreMask[0] = nCoreMask[2] = 0; + nActiveCoreMask[0] = nCoreMask[3] = 0; + + ebbu_pool_consumer_set_thread_params(pHandler, 55, SCHED_FIFO, pCfg->sleepFlag); + ebbu_pool_consumer_set_thread_mask(pHandler, nCoreMask); + + usleep(100000); + + /* mMIMO with 64TRX */ + for(iCell = 0; iCell < nTestCell; iCell ++) { + + gDLProcAdvance[iCell] = DL_PROC_ADVANCE_MU1; + gULProcAdvance[iCell] = UL_PROC_ADVANCE_MU1; + gNumDLCtx[iCell] = 5; + gNumDLBufferCtx[iCell] = 3; + gNumULCtx[iCell] = 8; + gNumULBufferCtx[iCell] = 2; + gMaxSlotNum[iCell] = 10240 * (1 << p_o_xu_cfg[0]->mu_number); + } + + return 0; +} + +int32_t app_bbu_close(void) +{ + // Close Mlog Buffer and write to File + // if(pCfg->mlogEnable) + // MLogPrint(NULL); + + // Step 5: release all the threads + ebbu_pool_release_threads(pHandler); + + // Step 6: get report for Framework + int32_t testResult = ebbu_pool_status_report(pHandler); + // Save the test status, 0 means pass, other means fail + char resultString[8] = {'\0'}; + if(testResult == 0) + sprintf(resultString, "PASS"); + else + sprintf(resultString, "FAIL"); + + tEnd = clock(); + + char fResultName[64] = {"sample-app_bbu_pool_test_results.txt"}; + FILE *pFile = fopen(fResultName, "a"); + if(pFile != NULL) + { + fprintf(pFile, "sample-app test case\n"); + fprintf(pFile, "Execution time: %.3f second\n", (double)(tEnd - tStart)/1000000); + fprintf(pFile, "Result: %s\n\n", resultString); + fclose(pFile); + } + + // Step 7: release report for Framework + ebbu_pool_release_report(pHandler); + + // Step 8: release all allocated queues + ebbu_pool_release_queues(pHandler); + + // Step 9: release handler for Framework + ebbu_pool_release_handler(&pHandler); + printf("\n"); + + return 0; +} + +void +app_io_xran_fh_bbu_rx_callback(void *pCallbackTag, xran_status_t status) +{ + eBbuPoolHandler pHandler = app_get_ebbu_pool_handler(); + uint64_t t1 = MLogTick(); + uint32_t mlogVar[10]; + uint32_t mlogVarCnt = 0; + int32_t nCellIdx; + int32_t nCcIdx; + int32_t sym, nSlotIdx, ntti; + uint64_t mlog_start; + struct xran_cb_tag *pTag = (struct xran_cb_tag *) pCallbackTag; + int32_t o_xu_id = pTag->oXuId; + struct xran_io_shared_ctrl *psIoCtrl = app_io_xran_if_ctrl_get(o_xu_id); + struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); + struct xran_fh_config *pXranConf = &app_io_xran_fh_config[o_xu_id]; + uint32_t xran_max_antenna_nr = RTE_MAX(pXranConf->neAxc, pXranConf->neAxcUl); + uint32_t ant_id, sym_id, idxElm; + struct xran_prb_map *pRbMap = NULL; + struct xran_prb_elm *pRbElm = NULL; + + mlog_start = MLogTick(); + nCcIdx = pTag->cellId; + nCellIdx = psXranIoIf->map_cell_id2port[o_xu_id][nCcIdx]; + nSlotIdx = pTag->slotiId; ///((status >> 16) & 0xFFFF); /** TTI aka slotIdx */ + sym = pTag->symbol & 0xFF; /* sym */ + ntti = (nSlotIdx + XRAN_N_FE_BUF_LEN-1) % XRAN_N_FE_BUF_LEN; + + { + mlogVar[mlogVarCnt++] = 0xbcbcbcbc; + mlogVar[mlogVarCnt++] = o_xu_id; + mlogVar[mlogVarCnt++] = nCellIdx; + mlogVar[mlogVarCnt++] = sym; + mlogVar[mlogVarCnt++] = nSlotIdx; + mlogVar[mlogVarCnt++] = ntti; + //mlogVar[mlogVarCnt++] = nSlotIdx % gNumSlotPerSfn[nCellIdx]; + //mlogVar[mlogVarCnt++] = get_slot_type(nCellIdx, nSlotIdx, SLOT_TYPE_UL); + + MLogAddVariables(mlogVarCnt, mlogVar, mlog_start); + } + + if(psIoCtrl == NULL) + { + printf("psIoCtrl NULL! o_xu_id= %d\n", o_xu_id); + return; + } + + if (sym == XRAN_ONE_FOURTHS_CB_SYM) { + // 1/4 of slot + test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM2_WAKE_UP); + } else if (sym == XRAN_HALF_CB_SYM) { + // First Half + test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM6_WAKE_UP); + } else if (sym == XRAN_THREE_FOURTHS_CB_SYM) { + // 2/4 of slot + test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM11_WAKE_UP); + } else if (sym == XRAN_FULL_CB_SYM) { + // Second Half + test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM13_WAKE_UP); + } else { + /* error */ + MLogTask(PID_GNB_SYM_CB, t1, MLogTick()); + + rte_panic("app_io_xran_fh_bbu_rx_callback: sym\n"); + return; + } + + if(sym == XRAN_FULL_CB_SYM) //full slot callback only + { + for(ant_id = 0; ant_id < xran_max_antenna_nr; ant_id++) { + pRbMap = (struct xran_prb_map *) psIoCtrl->sFrontHaulRxPrbMapBbuIoBufCtrl[ntti][nCcIdx][ant_id].sBufferList.pBuffers->pData; + if(pRbMap == NULL){ + printf("(%d:%d:%d)pRbMap == NULL\n", nCcIdx, ntti, ant_id); + exit(-1); + } + for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { + for(idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) { + pRbElm = &pRbMap->prbMap[idxElm]; + pRbElm->nSecDesc[sym_id] = 0; + } + } + } + } + + rte_pause(); + + MLogTask(PCID_GNB_FH_RX_DATA_CC0+nCellIdx, mlog_start, MLogTick()); + return; +} + +void +app_io_xran_fh_bbu_rx_prach_callback(void *pCallbackTag, xran_status_t status) +{ + eBbuPoolHandler pHandler = app_get_ebbu_pool_handler(); + int32_t nCellIdx, nCcIdx; + int32_t sym, nSlotIdx, ntti; + struct xran_cb_tag *pTag = (struct xran_cb_tag *) pCallbackTag; + int32_t o_xu_id = pTag->oXuId; + uint64_t mlog_start = MLogTick(); + uint32_t mlogVar[10]; + struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); + struct xran_io_shared_ctrl *psIoCtrl = app_io_xran_if_ctrl_get(o_xu_id); + uint32_t mlogVarCnt = 0; + + if(psIoCtrl == NULL || psXranIoIf == NULL) + { + printf("psIoCtrl NULL! o_xu_id= %d\n", o_xu_id); + return; + } + + nCcIdx = pTag->cellId; + nCellIdx = psXranIoIf->map_cell_id2port[o_xu_id][nCcIdx]; + nSlotIdx = pTag->slotiId; ///((status >> 16) & 0xFFFF); /** TTI aka slotIdx */ + sym = pTag->symbol & 0xFF; /* sym */ + ntti = (nSlotIdx + XRAN_N_FE_BUF_LEN-1) % XRAN_N_FE_BUF_LEN; + + mlogVar[mlogVarCnt++] = 0xDDDDDDDD; + mlogVar[mlogVarCnt++] = o_xu_id; + mlogVar[mlogVarCnt++] = nCellIdx; + mlogVar[mlogVarCnt++] = sym; + mlogVar[mlogVarCnt++] = nSlotIdx; + mlogVar[mlogVarCnt++] = ntti; + MLogAddVariables(mlogVarCnt, mlogVar, MLogTick()); + test_func_gen(pHandler, nCellIdx, nSlotIdx, PRACH_WAKE_UP); + + MLogTask(PCID_GNB_FH_RX_PRACH_CC0+nCellIdx, mlog_start, MLogTick()); +} + +void +app_io_xran_fh_bbu_rx_srs_callback(void *pCallbackTag, xran_status_t status) +{ + eBbuPoolHandler pHandler = app_get_ebbu_pool_handler(); + int32_t nCellIdx; + int32_t nCcIdx; + int32_t sym, nSlotIdx, ntti; + struct xran_cb_tag *pTag = (struct xran_cb_tag *) pCallbackTag; + int32_t o_xu_id = pTag->oXuId; + struct xran_io_shared_ctrl *psIoCtrl = app_io_xran_if_ctrl_get(o_xu_id); + struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); + struct xran_fh_config *pXranConf = &app_io_xran_fh_config[o_xu_id]; + uint32_t xran_max_antenna_nr = RTE_MAX(pXranConf->neAxc, pXranConf->neAxcUl); + uint32_t xran_max_ant_array_elm_nr = RTE_MAX(pXranConf->nAntElmTRx, xran_max_antenna_nr); + uint32_t ant_id, sym_id, idxElm; + struct xran_prb_map *pRbMap = NULL; + struct xran_prb_elm *pRbElm = NULL; + uint64_t mlog_start = MLogTick(); + uint32_t mlogVar[10]; + uint32_t mlogVarCnt = 0; + + if(psIoCtrl == NULL || psXranIoIf == NULL) + { + printf("psIoCtrl NULL! o_xu_id= %d\n", o_xu_id); + return; + } + nCcIdx = pTag->cellId; + nCellIdx = psXranIoIf->map_cell_id2port[o_xu_id][nCcIdx]; + nSlotIdx = pTag->slotiId; ///((status >> 16) & 0xFFFF); /** TTI aka slotIdx */ + sym = pTag->symbol & 0xFF; /* sym */ + ntti = (nSlotIdx + XRAN_N_FE_BUF_LEN-1) % XRAN_N_FE_BUF_LEN; + + mlogVar[mlogVarCnt++] = 0xCCCCCCCC; + mlogVar[mlogVarCnt++] = o_xu_id; + mlogVar[mlogVarCnt++] = nCellIdx; + mlogVar[mlogVarCnt++] = sym; + mlogVar[mlogVarCnt++] = nSlotIdx; + mlogVar[mlogVarCnt++] = ntti; + MLogAddVariables(mlogVarCnt, mlogVar, MLogTick()); + test_func_gen(pHandler, nCellIdx, nSlotIdx, SRS_WAKE_UP); + + if(sym == XRAN_FULL_CB_SYM) //full slot callback only + { + for(ant_id = 0; ant_id < xran_max_ant_array_elm_nr; ant_id++) { + pRbMap = (struct xran_prb_map *) psIoCtrl->sFHSrsRxPrbMapBbuIoBufCtrl[ntti][nCcIdx][ant_id].sBufferList.pBuffers->pData; + if(pRbMap == NULL){ + printf("(%d:%d:%d)pRbMap == NULL\n", nCcIdx, ntti, ant_id); + exit(-1); + } + for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { + for(idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) { + pRbElm = &pRbMap->prbMap[idxElm]; + pRbElm->nSecDesc[sym_id] = 0; + } + } + } + } + MLogTask(PCID_GNB_FH_RX_SRS_CC0+nCellIdx, mlog_start, MLogTick()); +}