1 /******************************************************************************
3 * Copyright (c) 2020 Intel.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 *******************************************************************************/
20 * @brief This module provides implementation of BBU tasks for sample app
21 * @file app_bbu_main.c
23 * @author Intel Corporation
38 #include "app_bbu_pool.h"
39 #include "app_io_fh_xran.h"
40 #include "xran_mlog_task_id.h"
43 * @file app_bbu_main.c
44 * @brief example pipeline code to use Enhanced BBUPool Framework
47 uint32_t gRunCount = 0;
48 volatile uint32_t nStopFlag = 1;
49 int32_t gQueueCtxNum = 1;
51 int32_t nSplitNumCell[EBBU_POOL_MAX_TEST_CELL];
53 int32_t nTestCell = 0;
54 int32_t nTestCore = 0;
55 volatile uint64_t ttistart = 0;
56 int32_t dl_ul_count, dl_count, ul_count;
58 uint32_t gMaxSlotNum[MAX_PHY_INSTANCES];
59 uint32_t gNumDLCtx[MAX_PHY_INSTANCES];
60 uint32_t gNumULCtx[MAX_PHY_INSTANCES];
61 uint32_t gNumDLBufferCtx[MAX_PHY_INSTANCES];
62 uint32_t gNumULBufferCtx[MAX_PHY_INSTANCES];
63 uint32_t gDLProcAdvance[MAX_PHY_INSTANCES];
64 int32_t gULProcAdvance[MAX_PHY_INSTANCES];
68 int32_t exGenDlFunc[EX_FUNC_NUM] =
73 int32_t exGenUlFunc[EX_FUNC_NUM] =
84 int32_t exGenAllFunc[EX_FUNC_NUM] =
97 peBbuPoolCfgVarsStruct pCfg;
98 pthread_t tCtrlThread;
99 eBbuPoolHandler pHandler = NULL;
100 clock_t tStart, tEnd;
101 uint32_t ttiCell[EBBU_POOL_MAX_TEST_CELL] = {0};
102 uint64_t ttiCountCell[EBBU_POOL_MAX_TEST_CELL] = {0UL};
103 uint32_t frameFormatCell[EBBU_POOL_MAX_TEST_CELL] = {0};
107 eBbuPoolHandler app_get_ebbu_pool_handler(void)
114 app_bbu_dl_tti_call_back(void * param)
117 uint64_t t1 = MLogTick();
119 int32_t nCtx[EBBU_POOL_MAX_TEST_CELL] = {0}, iExFunc = 0, eventId = 0;
120 int32_t *exGenFuncDl = NULL, *exGenFuncUl = NULL;
121 int32_t nFuncNumDl = 0, nFuncNumUl = 0;
122 uint8_t Numerlogy = app_io_xran_fh_config[0].frame_conf.nNumerology;
123 uint8_t nNrOfSlotInSf = 1<<Numerlogy;
124 int32_t sfIdx = app_io_xran_sfidx_get(nNrOfSlotInSf);
125 uint64_t t = MLogTick();
126 uint32_t mlogVars[10], mlogVarsCnt = 0;
128 exGenFuncDl = exGenDlFunc;
130 exGenFuncUl = exGenUlFunc;
133 mlogVars[mlogVarsCnt++] = 0x99999999;
134 mlogVars[mlogVarsCnt++] = sfIdx % gMaxSlotNum[0];
135 MLogAddVariables(mlogVarsCnt, mlogVars, t);
137 for(iCell = 0; iCell < nTestCell ; iCell ++)
139 //check is it a tti for this cell
140 if(sfIdx % ttiCell[iCell] == 0)
142 ttistart = MLogTick();
143 dl_ul_count = nTestCell;
144 dl_ul_count += nTestCell;
145 ttiCountCell[iCell] = sfIdx;
146 nCtx[iCell] = ttiCountCell[iCell] % MAX_TEST_CTX;
148 event_chain_reset(&gEventChain[iCell][nCtx[iCell]]);
150 //if(nD2USwitch[frameFormatCell[iCell]][ttiCountCell[iCell]%EBBU_POOL_TDD_PERIOD] & EBBU_POOL_TEST_DL)
152 //printf("\ncell %d dl", iCell);
153 for(iExFunc = 0; iExFunc < nFuncNumDl; iExFunc ++)
155 eventId = exGenFuncDl[iExFunc];
156 ret = test_func_gen(pHandler, iCell, ttiCountCell[iCell], eventId);
160 //if(nD2USwitch[frameFormatCell[iCell]][ttiCountCell[iCell]%EBBU_POOL_TDD_PERIOD] & EBBU_POOL_TEST_UL)
162 //printf("\ncell %d ul", iCell);
163 for(iExFunc = 0; iExFunc < nFuncNumUl; iExFunc ++)
165 eventId = exGenFuncUl[iExFunc];
166 ret = test_func_gen(pHandler, iCell, ttiCountCell[iCell], eventId);
171 if(EBBUPOOL_ERROR == ret)
173 printf("\nFail to send cell %d, sf %lu, tsc %llu", iCell, ttiCountCell[iCell], ebbu_pool_tick()/tTTI/2);
176 MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
180 int32_t app_bbu_init(int argc, char *argv[], char cfgName[512], UsecaseConfig* p_use_cfg, RuntimeConfig* p_o_xu_cfg[], uint64_t nActiveCoreMask[EBBUPOOL_MAX_CORE_MASK])
183 uint32_t nFh_cell = 0;
186 ebbu_pool_cfg_set_cfg_filename(argc, argv, cfgName);
188 ebbu_pool_cfg_init_from_xml();
189 pCfg = ebbu_pool_cfg_get_ctx();
191 nTestCell = pCfg->testCellNum;
193 for (i = 0; i < p_use_cfg->oXuNum; i++)
194 nFh_cell += p_o_xu_cfg[i]->numCC;
196 if (nFh_cell != nTestCell) {
197 rte_panic("WARNING: miss match between BBU Cells (%d) and O-RAN FH Cells (%d)", nTestCell, nFh_cell);
200 if(nTestCell > EBBU_POOL_MAX_TEST_CELL || nTestCell <= 0)
202 printf("Wrong cell num %d\n",nTestCell);
205 nTestCore = pCfg->testCoreNum;
206 if(nTestCore > EBBU_POOL_MAX_TEST_CORE || nTestCore <= 0)
208 printf("Wrong core num %d\n",nTestCore);
214 printf("Test cell %d, test total core num %d, test slots %d\n", nTestCell, nTestCore, gRunCount);
216 // Step 1: create Framework handler
217 ebbu_pool_create_handler(&pHandler, 1, pCfg->mainThreadCoreId);
220 printf("\nFail to init Framework!");
224 // Step 2: create priority queues
226 uint32_t nPrioQueue = pCfg->queueNum;
227 uint32_t nQueueSize = pCfg->queueDepth;
228 uint32_t pPrioQueueSize[8] = {nQueueSize, nQueueSize, nQueueSize, nQueueSize,nQueueSize, nQueueSize, nQueueSize, nQueueSize};
229 QueueConfigStruct sQueueConfig;
230 sQueueConfig.pQueueDepth = pPrioQueueSize;
231 sQueueConfig.nPriQueueNum = nPrioQueue;
232 sQueueConfig.nPriQueueCtxNum = pCfg->ququeCtxNum;
233 sQueueConfig.nPriQueueCtxMaxFetch = pCfg->ququeCtxNum;
235 ebbu_pool_create_queues(pHandler, sQueueConfig);
237 ebbu_pool_queue_ctx_set_threshold(pHandler, 2*nTestCell);
239 // Step 3: create one report for Framework
241 sReport.nEventHoldNum = 2000;
242 sReport.pHandler = (void *)pHandler;
243 ebbu_pool_create_report(sReport);
245 // Step 4: start control thread
246 // pthread_create(&tCtrlThread, NULL, controlThread, (void *)pHandler);
248 peBbuPoolCfgVarsStruct pCfg = ebbu_pool_cfg_get_ctx();
251 uint32_t xran_timer = (1000/(1 << p_o_xu_cfg[0]->mu_number)); /* base on O-RU 0 */
253 printf("xran_timer for TTI [%d] us\n", xran_timer);
254 // Init base timing as per xran_timer
255 uint64_t tStart = ebbu_pool_tick();
257 tTTI = ebbu_pool_tick() - tStart;
259 // cell specific TTI init
260 // create cell and create consumer thread
261 // set events num per cell
262 for(iCell = 0; iCell < nTestCell; iCell ++)
264 ttiCell[iCell] = pCfg->sTestCell[iCell].tti/xran_timer;
265 printf("\nttiCell[%d] %d", iCell, ttiCell[iCell]);
267 frameFormatCell[iCell] = pCfg->sTestCell[iCell].frameFormat;
268 if(frameFormatCell[iCell] >= EBBU_POOL_MAX_FRAME_FORMAT)
269 frameFormatCell[iCell] = 0;
271 for(iCtx = 0; iCtx < MAX_TEST_CTX; iCtx ++)
273 event_chain_gen(&gEventChain[iCell][iCtx]);
275 nSplitNumCell[iCell] = 1;//((pCfg->sTestCell[iCell].eventPerTti)-11)/18; //current event chain has 29 events, 19 of them can be split
276 printf("\nnSplitNumCell[%d] %d", iCell, nSplitNumCell[iCell]);
277 if(nSplitNumCell[iCell] > MAX_TEST_SPLIT_NUM)
278 nSplitNumCell[iCell] = MAX_TEST_SPLIT_NUM;
281 test_buffer_create();
283 // add consumer thread
285 /*int32_t corePool[EBBU_POOL_MAX_TEST_CORE] = {4,24,5,25,6,26,7,27,
286 8,28,9,29,10,30,11,31,
287 12,32,13,33,14,34,15,35,
288 16,36,17,37,18,38,19,39,
293 uint64_t nMask0 = 0UL, nMask1 = 0UL;
294 uint32_t iCoreIdx = 0;
295 uint64_t nCoreMask[EBBUPOOL_MAX_CORE_MASK];
297 for(; iCore < nTestCore; iCore ++)
299 iCoreIdx = pCfg->testCoreList[iCore];
301 nMask0 |= 1UL << iCoreIdx;
303 nMask1 |= 1UL << iCoreIdx;
306 //printf("\nnStartMask %016lx\n", nStartMask);
308 nActiveCoreMask[0] = nCoreMask[0] = nMask0;
309 nActiveCoreMask[0] = nCoreMask[1] = nMask1;
310 nActiveCoreMask[0] = nCoreMask[2] = 0;
311 nActiveCoreMask[0] = nCoreMask[3] = 0;
313 ebbu_pool_consumer_set_thread_params(pHandler, 55, SCHED_FIFO, pCfg->sleepFlag);
314 ebbu_pool_consumer_set_thread_mask(pHandler, nCoreMask);
318 /* mMIMO with 64TRX */
319 for(iCell = 0; iCell < nTestCell; iCell ++) {
321 gDLProcAdvance[iCell] = DL_PROC_ADVANCE_MU1;
322 gULProcAdvance[iCell] = UL_PROC_ADVANCE_MU1;
323 gNumDLCtx[iCell] = 5;
324 gNumDLBufferCtx[iCell] = 3;
325 gNumULCtx[iCell] = 8;
326 gNumULBufferCtx[iCell] = 2;
327 gMaxSlotNum[iCell] = 10240 * (1 << p_o_xu_cfg[0]->mu_number);
333 int32_t app_bbu_close(void)
335 // Close Mlog Buffer and write to File
336 // if(pCfg->mlogEnable)
339 // Step 5: release all the threads
340 ebbu_pool_release_threads(pHandler);
342 // Step 6: get report for Framework
343 int32_t testResult = ebbu_pool_status_report(pHandler);
344 // Save the test status, 0 means pass, other means fail
345 char resultString[8] = {'\0'};
347 sprintf(resultString, "PASS");
349 sprintf(resultString, "FAIL");
353 char fResultName[64] = {"sample-app_bbu_pool_test_results.txt"};
354 FILE *pFile = fopen(fResultName, "a");
357 fprintf(pFile, "sample-app test case\n");
358 fprintf(pFile, "Execution time: %.3f second\n", (double)(tEnd - tStart)/1000000);
359 fprintf(pFile, "Result: %s\n\n", resultString);
363 // Step 7: release report for Framework
364 ebbu_pool_release_report(pHandler);
366 // Step 8: release all allocated queues
367 ebbu_pool_release_queues(pHandler);
369 // Step 9: release handler for Framework
370 ebbu_pool_release_handler(&pHandler);
377 app_io_xran_fh_bbu_rx_callback(void *pCallbackTag, xran_status_t status)
379 eBbuPoolHandler pHandler = app_get_ebbu_pool_handler();
380 uint64_t t1 = MLogTick();
381 uint32_t mlogVar[10];
382 uint32_t mlogVarCnt = 0;
385 int32_t sym, nSlotIdx, ntti;
387 struct xran_cb_tag *pTag = (struct xran_cb_tag *) pCallbackTag;
388 int32_t o_xu_id = pTag->oXuId;
389 struct xran_io_shared_ctrl *psIoCtrl = app_io_xran_if_ctrl_get(o_xu_id);
390 struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get();
391 struct xran_fh_config *pXranConf = &app_io_xran_fh_config[o_xu_id];
392 uint32_t xran_max_antenna_nr = RTE_MAX(pXranConf->neAxc, pXranConf->neAxcUl);
393 uint32_t ant_id, sym_id, idxElm;
394 struct xran_prb_map *pRbMap = NULL;
395 struct xran_prb_elm *pRbElm = NULL;
397 mlog_start = MLogTick();
398 nCcIdx = pTag->cellId;
399 nCellIdx = psXranIoIf->map_cell_id2port[o_xu_id][nCcIdx];
400 nSlotIdx = pTag->slotiId; ///((status >> 16) & 0xFFFF); /** TTI aka slotIdx */
401 sym = pTag->symbol & 0xFF; /* sym */
402 ntti = (nSlotIdx + XRAN_N_FE_BUF_LEN-1) % XRAN_N_FE_BUF_LEN;
405 mlogVar[mlogVarCnt++] = 0xbcbcbcbc;
406 mlogVar[mlogVarCnt++] = o_xu_id;
407 mlogVar[mlogVarCnt++] = nCellIdx;
408 mlogVar[mlogVarCnt++] = sym;
409 mlogVar[mlogVarCnt++] = nSlotIdx;
410 mlogVar[mlogVarCnt++] = ntti;
411 //mlogVar[mlogVarCnt++] = nSlotIdx % gNumSlotPerSfn[nCellIdx];
412 //mlogVar[mlogVarCnt++] = get_slot_type(nCellIdx, nSlotIdx, SLOT_TYPE_UL);
414 MLogAddVariables(mlogVarCnt, mlogVar, mlog_start);
419 printf("psIoCtrl NULL! o_xu_id= %d\n", o_xu_id);
423 if (sym == XRAN_ONE_FOURTHS_CB_SYM) {
425 test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM2_WAKE_UP);
426 } else if (sym == XRAN_HALF_CB_SYM) {
428 test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM6_WAKE_UP);
429 } else if (sym == XRAN_THREE_FOURTHS_CB_SYM) {
431 test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM11_WAKE_UP);
432 } else if (sym == XRAN_FULL_CB_SYM) {
434 test_func_gen(pHandler, nCellIdx, nSlotIdx, SYM13_WAKE_UP);
437 MLogTask(PID_GNB_SYM_CB, t1, MLogTick());
439 rte_panic("app_io_xran_fh_bbu_rx_callback: sym\n");
443 if(sym == XRAN_FULL_CB_SYM) //full slot callback only
445 for(ant_id = 0; ant_id < xran_max_antenna_nr; ant_id++) {
446 pRbMap = (struct xran_prb_map *) psIoCtrl->sFrontHaulRxPrbMapBbuIoBufCtrl[ntti][nCcIdx][ant_id].sBufferList.pBuffers->pData;
448 printf("(%d:%d:%d)pRbMap == NULL\n", nCcIdx, ntti, ant_id);
451 for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
452 for(idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) {
453 pRbElm = &pRbMap->prbMap[idxElm];
454 pRbElm->nSecDesc[sym_id] = 0;
462 MLogTask(PCID_GNB_FH_RX_DATA_CC0+nCellIdx, mlog_start, MLogTick());
467 app_io_xran_fh_bbu_rx_prach_callback(void *pCallbackTag, xran_status_t status)
469 eBbuPoolHandler pHandler = app_get_ebbu_pool_handler();
470 int32_t nCellIdx, nCcIdx;
471 int32_t sym, nSlotIdx, ntti;
472 struct xran_cb_tag *pTag = (struct xran_cb_tag *) pCallbackTag;
473 int32_t o_xu_id = pTag->oXuId;
474 uint64_t mlog_start = MLogTick();
475 uint32_t mlogVar[10];
476 struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get();
477 struct xran_io_shared_ctrl *psIoCtrl = app_io_xran_if_ctrl_get(o_xu_id);
478 uint32_t mlogVarCnt = 0;
480 if(psIoCtrl == NULL || psXranIoIf == NULL)
482 printf("psIoCtrl NULL! o_xu_id= %d\n", o_xu_id);
486 nCcIdx = pTag->cellId;
487 nCellIdx = psXranIoIf->map_cell_id2port[o_xu_id][nCcIdx];
488 nSlotIdx = pTag->slotiId; ///((status >> 16) & 0xFFFF); /** TTI aka slotIdx */
489 sym = pTag->symbol & 0xFF; /* sym */
490 ntti = (nSlotIdx + XRAN_N_FE_BUF_LEN-1) % XRAN_N_FE_BUF_LEN;
492 mlogVar[mlogVarCnt++] = 0xDDDDDDDD;
493 mlogVar[mlogVarCnt++] = o_xu_id;
494 mlogVar[mlogVarCnt++] = nCellIdx;
495 mlogVar[mlogVarCnt++] = sym;
496 mlogVar[mlogVarCnt++] = nSlotIdx;
497 mlogVar[mlogVarCnt++] = ntti;
498 MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
499 test_func_gen(pHandler, nCellIdx, nSlotIdx, PRACH_WAKE_UP);
501 MLogTask(PCID_GNB_FH_RX_PRACH_CC0+nCellIdx, mlog_start, MLogTick());
505 app_io_xran_fh_bbu_rx_srs_callback(void *pCallbackTag, xran_status_t status)
507 eBbuPoolHandler pHandler = app_get_ebbu_pool_handler();
510 int32_t sym, nSlotIdx, ntti;
511 struct xran_cb_tag *pTag = (struct xran_cb_tag *) pCallbackTag;
512 int32_t o_xu_id = pTag->oXuId;
513 struct xran_io_shared_ctrl *psIoCtrl = app_io_xran_if_ctrl_get(o_xu_id);
514 struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get();
515 struct xran_fh_config *pXranConf = &app_io_xran_fh_config[o_xu_id];
516 uint32_t xran_max_antenna_nr = RTE_MAX(pXranConf->neAxc, pXranConf->neAxcUl);
517 uint32_t xran_max_ant_array_elm_nr = RTE_MAX(pXranConf->nAntElmTRx, xran_max_antenna_nr);
518 uint32_t ant_id, sym_id, idxElm;
519 struct xran_prb_map *pRbMap = NULL;
520 struct xran_prb_elm *pRbElm = NULL;
521 uint64_t mlog_start = MLogTick();
522 uint32_t mlogVar[10];
523 uint32_t mlogVarCnt = 0;
525 if(psIoCtrl == NULL || psXranIoIf == NULL)
527 printf("psIoCtrl NULL! o_xu_id= %d\n", o_xu_id);
530 nCcIdx = pTag->cellId;
531 nCellIdx = psXranIoIf->map_cell_id2port[o_xu_id][nCcIdx];
532 nSlotIdx = pTag->slotiId; ///((status >> 16) & 0xFFFF); /** TTI aka slotIdx */
533 sym = pTag->symbol & 0xFF; /* sym */
534 ntti = (nSlotIdx + XRAN_N_FE_BUF_LEN-1) % XRAN_N_FE_BUF_LEN;
536 mlogVar[mlogVarCnt++] = 0xCCCCCCCC;
537 mlogVar[mlogVarCnt++] = o_xu_id;
538 mlogVar[mlogVarCnt++] = nCellIdx;
539 mlogVar[mlogVarCnt++] = sym;
540 mlogVar[mlogVarCnt++] = nSlotIdx;
541 mlogVar[mlogVarCnt++] = ntti;
542 MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
543 test_func_gen(pHandler, nCellIdx, nSlotIdx, SRS_WAKE_UP);
545 if(sym == XRAN_FULL_CB_SYM) //full slot callback only
547 for(ant_id = 0; ant_id < xran_max_ant_array_elm_nr; ant_id++) {
548 pRbMap = (struct xran_prb_map *) psIoCtrl->sFHSrsRxPrbMapBbuIoBufCtrl[ntti][nCcIdx][ant_id].sBufferList.pBuffers->pData;
550 printf("(%d:%d:%d)pRbMap == NULL\n", nCcIdx, ntti, ant_id);
553 for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
554 for(idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) {
555 pRbElm = &pRbMap->prbMap[idxElm];
556 pRbElm->nSecDesc[sym_id] = 0;
561 MLogTask(PCID_GNB_FH_RX_SRS_CC0+nCellIdx, mlog_start, MLogTick());