/****************************************************************************** * * 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.c * @ingroup xran * @author Intel Corporation * **/ #include #include #include #include #include #include #include #include "common.h" #include "app_bbu_pool.h" #include "app_io_fh_xran.h" #include "xran_compression.h" #include "xran_cp_api.h" #include "xran_fh_o_du.h" #include "xran_mlog_task_id.h" extern RuntimeConfig* p_startupConfiguration[XRAN_PORTS_NUM]; static SampleSplitStruct gsDlPostSymbolTaskSplit[MAX_PHY_INSTANCES][MAX_NUM_OF_SF_5G_CTX][MAX_TEST_SPLIT_NUM]; static SampleSplitStruct gsDlCfgAxCTaskSplit[MAX_PHY_INSTANCES][MAX_NUM_OF_SF_5G_CTX][MAX_TEST_SPLIT_NUM]; void app_bbu_pool_pre_task_dl_post(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara) { int32_t nSplitGroup = 0; int32_t iTask = 0; uint32_t nSfIdx = get_dl_sf_idx(nSubframe, nCellIdx); uint32_t nCtxNum = get_dl_sf_ctx(nSfIdx, nCellIdx); SampleSplitStruct *pTaskSplitPara; int32_t nGroupNum = 0; int32_t nSymbStart = 0, nSymbPerSplit = 0; int32_t nTotalLayers = 0, nLayerStart = 0, nLayerPerSplit = 0; struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); struct xran_fh_config* pXranConf = NULL; // struct xran_io_shared_ctrl *psIoCtrl = NULL; uint32_t nRuCcidx = 0; int32_t xran_port = 0; if(psXranIoIf == NULL) rte_panic("psXranIoIf == NULL"); if(nCellIdx >= MAX_PHY_INSTANCES) rte_panic("nCellIdx >= MAX_PHY_INSTANCES"); xran_port = app_io_xran_map_cellid_to_port(psXranIoIf, nCellIdx, &nRuCcidx); if(xran_port < 0) { printf("incorrect xran_port\n"); return /*EBBUPOOL_CORRECT*/; } // psIoCtrl = app_io_xran_if_ctrl_get(xran_port); pXranConf = &app_io_xran_fh_config[xran_port]; if(pXranConf == NULL) rte_panic("pXranConf"); nTotalLayers = pXranConf->neAxc; nSplitGroup = pXranConf->neAxc; /* all symp per eAxC */ nSymbStart = 0; // nTotalSymb = XRAN_NUM_OF_SYMBOL_PER_SLOT; nSymbPerSplit = XRAN_NUM_OF_SYMBOL_PER_SLOT; nLayerPerSplit = nTotalLayers/nSplitGroup; pPara->nTaskNum = nSplitGroup; for (iTask = 0; iTask < (nSplitGroup-1) && iTask < (MAX_TEST_SPLIT_NUM-1); iTask ++) { pTaskSplitPara = &(gsDlPostSymbolTaskSplit[nCellIdx][nCtxNum][iTask]); pTaskSplitPara->nSymbStart = nSymbStart; pTaskSplitPara->nSymbNum = nSymbPerSplit; pTaskSplitPara->eSplitType = LAYER_SPLIT; pTaskSplitPara->nSplitIndex = iTask; pTaskSplitPara->nGroupStart = 0; pTaskSplitPara->nGroupNum = nGroupNum; pTaskSplitPara->nLayerStart = nLayerStart; pTaskSplitPara->nLayerNum = nLayerPerSplit; pPara->pTaskExePara[iTask] = pTaskSplitPara; //nSymbStart += nSymbPerSplit; nLayerStart += nLayerPerSplit; } pTaskSplitPara = &(gsDlPostSymbolTaskSplit[nCellIdx][nCtxNum][iTask]); pTaskSplitPara->nSymbStart = nSymbStart; pTaskSplitPara->nSymbNum = nSymbPerSplit; pTaskSplitPara->eSplitType = LAYER_SPLIT; pTaskSplitPara->nSplitIndex = iTask; pTaskSplitPara->nGroupStart = 0; pTaskSplitPara->nGroupNum = nGroupNum; pTaskSplitPara->nLayerStart = nLayerStart; pTaskSplitPara->nLayerNum = nTotalLayers - nLayerStart; pPara->pTaskExePara[iTask] = pTaskSplitPara; return; } void app_bbu_pool_pre_task_dl_cfg(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara) { int32_t nSplitGroup = 0; int32_t iTask = 0; uint32_t nSfIdx = get_dl_sf_idx(nSubframe, nCellIdx); uint32_t nCtxNum = get_dl_sf_ctx(nSfIdx, nCellIdx); SampleSplitStruct *pTaskSplitPara; int32_t nGroupNum = 0; int32_t nSymbStart = 0, nSymbPerSplit = 0; int32_t nTotalLayers = 0, nLayerStart = 0, nLayerPerSplit = 0; struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); struct xran_fh_config* pXranConf = NULL; // struct xran_io_shared_ctrl *psIoCtrl = NULL; uint32_t nRuCcidx = 0; int32_t xran_port = 0; uint32_t neAxc = 0; if(psXranIoIf == NULL) rte_panic("psXranIoIf == NULL"); if(nCellIdx >= MAX_PHY_INSTANCES) rte_panic("nCellIdx >= MAX_PHY_INSTANCES"); xran_port = app_io_xran_map_cellid_to_port(psXranIoIf, nCellIdx, &nRuCcidx); if(xran_port < 0) { printf("incorrect xran_port\n"); return /*EBBUPOOL_CORRECT*/; } // psIoCtrl = app_io_xran_if_ctrl_get(xran_port); pXranConf = &app_io_xran_fh_config[xran_port]; if(pXranConf == NULL) rte_panic("pXranConf"); pXranConf = &app_io_xran_fh_config[xran_port]; if(pXranConf == NULL) rte_panic("pXranConf"); if(pXranConf->ru_conf.xranCat == XRAN_CATEGORY_A){ neAxc = pXranConf->neAxc; nSplitGroup = 1; } else if (pXranConf->ru_conf.xranCat == XRAN_CATEGORY_B) { neAxc = pXranConf->neAxc; nSplitGroup = neAxc; } else rte_panic("neAxc"); nTotalLayers = neAxc; /* all symb per eAxC */ nSymbStart = 0; nSymbPerSplit = XRAN_NUM_OF_SYMBOL_PER_SLOT; nLayerPerSplit = nTotalLayers/nSplitGroup; pPara->nTaskNum = nSplitGroup; for (iTask = 0; iTask < (nSplitGroup-1) && iTask < (MAX_TEST_SPLIT_NUM-1); iTask ++) { pTaskSplitPara = &(gsDlCfgAxCTaskSplit[nCellIdx][nCtxNum][iTask]); pTaskSplitPara->nSymbStart = nSymbStart; pTaskSplitPara->nSymbNum = nSymbPerSplit; pTaskSplitPara->eSplitType = LAYER_SPLIT; pTaskSplitPara->nSplitIndex = iTask; pTaskSplitPara->nGroupStart = 0; pTaskSplitPara->nGroupNum = nGroupNum; pTaskSplitPara->nLayerStart = nLayerStart; pTaskSplitPara->nLayerNum = nLayerPerSplit; pPara->pTaskExePara[iTask] = pTaskSplitPara; //nSymbStart += nSymbPerSplit; nLayerStart += nLayerPerSplit; } pTaskSplitPara = &(gsDlCfgAxCTaskSplit[nCellIdx][nCtxNum][iTask]); pTaskSplitPara->nSymbStart = nSymbStart; pTaskSplitPara->nSymbNum = nSymbPerSplit; pTaskSplitPara->eSplitType = LAYER_SPLIT; pTaskSplitPara->nSplitIndex = iTask; pTaskSplitPara->nGroupStart = 0; pTaskSplitPara->nGroupNum = nGroupNum; pTaskSplitPara->nLayerStart = nLayerStart; pTaskSplitPara->nLayerNum = nTotalLayers - nLayerStart; pPara->pTaskExePara[iTask] = pTaskSplitPara; return; } //------------------------------------------------------------------------------------------- /** @ingroup xran * * @param[in] pCookies task input parameter * @return 0 if SUCCESS * * @description * This function takes the DL Config from MAC and stores it into PHY Internal structures. * and initials the parameter of UL DCI. * **/ //------------------------------------------------------------------------------------------- int32_t app_bbu_pool_task_dl_config(void *pCookies) { EventCtrlStruct *pEventCtrl = (EventCtrlStruct *)pCookies; uint16_t nCellIdx = pEventCtrl->nCellIdx; uint32_t nSfIdx = get_dl_sf_idx(pEventCtrl->nSlotIdx, nCellIdx); uint32_t nCtxNum = get_dl_sf_ctx(nSfIdx, nCellIdx); uint32_t mlogVariablesCnt, mlogVariables[50]; uint64_t mlog_start = MLogTick(); uint32_t nRuCcidx = 0; int32_t xran_port = 0; SampleSplitStruct *pTaskPara = (SampleSplitStruct*)pEventCtrl->pTaskPara; struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); struct xran_fh_config* pXranConf = NULL; xran_status_t status; struct xran_io_shared_ctrl *psIoCtrl = NULL; int32_t cc_id, ant_id, sym_id, tti; int32_t flowId; struct o_xu_buffers * p_iq = NULL; int32_t nSymbMask = 0b11111111111111; RuntimeConfig *p_o_xu_cfg = NULL; uint16_t nLayerStart = 0, nLayer = 0; if(psXranIoIf == NULL) rte_panic("psXranIoIf == NULL"); xran_port = app_io_xran_map_cellid_to_port(psXranIoIf, nCellIdx, &nRuCcidx); if(xran_port < 0) { printf("incorrect xran_port\n"); return EBBUPOOL_CORRECT; } psIoCtrl = app_io_xran_if_ctrl_get(xran_port); pXranConf = &app_io_xran_fh_config[xran_port]; if(pXranConf == NULL) rte_panic("pXranConf"); mlogVariablesCnt = 0; mlogVariables[mlogVariablesCnt++] = 0xCCBBCCBB; mlogVariables[mlogVariablesCnt++] = pEventCtrl->nSlotIdx; mlogVariables[mlogVariablesCnt++] = 0; mlogVariables[mlogVariablesCnt++] = nCellIdx; mlogVariables[mlogVariablesCnt++] = nSfIdx; mlogVariables[mlogVariablesCnt++] = nCtxNum; mlogVariables[mlogVariablesCnt++] = xran_port; mlogVariables[mlogVariablesCnt++] = nRuCcidx; p_o_xu_cfg = p_startupConfiguration[xran_port]; mlog_start = MLogTick(); if(LAYER_SPLIT == pTaskPara->eSplitType) { // iSplit = pTaskPara->nSplitIndex; nLayerStart = pTaskPara->nLayerStart; nLayer = pTaskPara->nLayerNum; //printf("\nsf %d nSymbStart %d nSymb %d iSplit %d", nSfIdx, nSymbStart, nSymb, iSplit); } else { rte_panic("LAYER_SPLIT == pTaskPara->eSplitType"); } if(p_o_xu_cfg->p_buff) { p_iq = p_o_xu_cfg->p_buff; } else { rte_panic("Error p_o_xu_cfg->p_buff\n"); } tti = nSfIdx; for(cc_id = nRuCcidx; cc_id < psXranIoIf->num_cc_per_port[xran_port]; cc_id++) { if (cc_id >= XRAN_MAX_SECTOR_NR) { rte_panic("cell id %d exceeding max number", cc_id); } for(ant_id = nLayerStart; ant_id < (nLayerStart + nLayer); ant_id++) { if(p_o_xu_cfg->appMode == APP_O_DU) { flowId = p_o_xu_cfg->numAxc * cc_id + ant_id; } else { flowId = p_o_xu_cfg->numUlAxc * cc_id + ant_id; } for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { if(((1 << sym_id) & nSymbMask)) { if ((status = app_io_xran_iq_content_init_cp_tx(p_o_xu_cfg->appMode, pXranConf, psXranIoIf, psIoCtrl, p_iq, cc_id, ant_id, sym_id, tti, flowId)) != 0) { rte_panic("app_io_xran_iq_content_init_cp_tx"); } } } } } xran_prepare_cp_dl_slot(xran_port, nSfIdx, nRuCcidx, /*psXranIoIf->num_cc_per_port[xran_port]*/ 1, nSymbMask, nLayerStart, nLayer, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT); if (mlogVariablesCnt) MLogAddVariables((uint32_t)mlogVariablesCnt, (uint32_t *)mlogVariables, mlog_start); //unlock the next task next_event_unlock(pCookies); MLogTask(PCID_GNB_DL_CFG_CC0+nCellIdx, mlog_start, MLogTick()); return EBBUPOOL_CORRECT; } int32_t app_io_xran_dl_pack_func(uint16_t nCellIdx, uint32_t nSfIdx, uint32_t nSymMask, uint32_t nAntStart, uint32_t nAntNum, uint32_t nSymStart, uint32_t nSymNum) { xran_status_t status; uint32_t nSlotIdx = get_dl_sf_idx(nSfIdx, nCellIdx); // struct xran_io_shared_ctrl * psBbuXranIo = NULL; struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); int32_t xran_port = 0; uint32_t nRuCcidx = 0; struct o_xu_buffers * p_iq = NULL; RuntimeConfig *p_o_xu_cfg = NULL; int32_t flowId = 0; struct xran_fh_config *pXranConf = NULL; int32_t cc_id, ant_id, sym_id, tti; struct xran_io_shared_ctrl *psIoCtrl = NULL; xran_port = app_io_xran_map_cellid_to_port(psXranIoIf, nCellIdx, &nRuCcidx); if(xran_port < 0) { printf("incorrect xran_port\n"); return FAILURE; } psIoCtrl = app_io_xran_if_ctrl_get(xran_port); if(psIoCtrl == NULL) { printf("psIoCtrl == NULL\n"); return FAILURE; } p_o_xu_cfg = p_startupConfiguration[xran_port]; if(p_o_xu_cfg == NULL) { printf("p_o_xu_cfg == NULL\n"); return FAILURE; } if(p_o_xu_cfg->p_buff) { p_iq = p_o_xu_cfg->p_buff; } else { rte_panic("Error p_o_xu_cfg->p_buff\n"); } pXranConf = &app_io_xran_fh_config[xran_port]; tti = nSlotIdx; for(cc_id = nRuCcidx; cc_id < psXranIoIf->num_cc_per_port[xran_port]; cc_id++) { for(ant_id = nAntStart; ant_id < (nAntStart + nAntNum) && ant_id < pXranConf->neAxc; ant_id++) { if(p_o_xu_cfg->appMode == APP_O_DU) { flowId = p_o_xu_cfg->numAxc * cc_id + ant_id; } else { flowId = p_o_xu_cfg->numUlAxc * cc_id + ant_id; } for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { if(((1 << sym_id) & nSymMask)) { if ((status = app_io_xran_iq_content_init_up_tx(p_o_xu_cfg->appMode, pXranConf, psXranIoIf, psIoCtrl, p_iq, cc_id, ant_id, sym_id, tti, flowId)) != 0) { rte_panic("app_io_xran_iq_content_init_up_tx"); } } } } } xran_prepare_up_dl_sym(xran_port, nSlotIdx, nRuCcidx, 1, nSymMask, nAntStart, nAntNum, nSymStart, nSymNum); return SUCCESS; } int32_t app_io_xran_dl_post_func(uint16_t nCellIdx, uint32_t nSfIdx, uint32_t nSymMask, uint32_t nAntStart, uint32_t nAntNum) { uint16_t phyInstance = nCellIdx; // uint32_t Ntx_antennas; uint16_t nOranCellIdx; uint64_t tTotal = MLogTick(); // struct xran_io_shared_ctrl * psBbuXranIo = NULL; struct bbu_xran_io_if *psXranIoIf = app_io_xran_if_get(); int32_t xran_port = 0; uint32_t nRuCcidx = 0; // struct xran_fh_config *pXranConf = NULL; nSymMask = nSymMask + 0; nOranCellIdx = nCellIdx; xran_port = app_io_xran_map_cellid_to_port(psXranIoIf, nOranCellIdx, &nRuCcidx); if(xran_port < 0) { printf("incorrect xran_port\n"); return FAILURE; } // pXranConf = &app_io_xran_fh_config[xran_port]; // Ntx_antennas = pXranConf->neAxc; app_io_xran_dl_pack_func(nCellIdx, nSfIdx, nSymMask, nAntStart, nAntNum, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT); MLogTask(PCID_GNB_DL_IQ_COMPRESS_CC0 + phyInstance, tTotal, MLogTick()); return SUCCESS; } //------------------------------------------------------------------------------------------- /** @ingroup group_nr5g_source_phy_pdsch * * @param[in] pCookies task input parameter * @return 0 if SUCCESS * * @description * This function will reset phy dl buffers. * **/ //------------------------------------------------------------------------------------------- int32_t app_bbu_pool_task_dl_post(void *pCookies) { EventCtrlStruct *pEventCtrl = (EventCtrlStruct *)pCookies; uint16_t nCellIdx = pEventCtrl->nCellIdx; uint32_t nSfIdx = get_dl_sf_idx(pEventCtrl->nSlotIdx, nCellIdx); SampleSplitStruct *pTaskPara = (SampleSplitStruct*)pEventCtrl->pTaskPara; uint16_t nSymbStart = 0, nSymb = 0, iOfdmSymb = 0, iSplit = 0; uint32_t nSymMask = 0; uint64_t mlog_start; uint32_t mlogVar[10]; uint32_t mlogVarCnt = 0; uint16_t nLayerStart = 0, nLayer = 0; mlog_start = MLogTick(); if(LAYER_SPLIT == pTaskPara->eSplitType) { nSymbStart = pTaskPara->nSymbStart; nSymb = pTaskPara->nSymbNum; iSplit = pTaskPara->nSplitIndex; nLayerStart = pTaskPara->nLayerStart; nLayer = pTaskPara->nLayerNum; //printf("\nsf %d nSymbStart %d nSymb %d iSplit %d", nSfIdx, nSymbStart, nSymb, iSplit); } else if(OFDM_SYMB_SPLIT == pTaskPara->eSplitType) { nSymbStart = pTaskPara->nSymbStart; nSymb = pTaskPara->nSymbNum; iSplit = pTaskPara->nSplitIndex; rte_panic("\nsf %d nSymbStart %d nSymb %d iSplit %d", nSfIdx, nSymbStart, nSymb, iSplit); } else { rte_panic("OFDM_SYMB_SPLIT == pTaskPara->eSplitType"); } // This is the loop of real OFDM symbol index for(iOfdmSymb = nSymbStart; iOfdmSymb < (nSymbStart + nSymb); iOfdmSymb ++) nSymMask |= (1 << iOfdmSymb); app_io_xran_dl_post_func(pEventCtrl->nCellIdx, pEventCtrl->nSlotIdx, /*0x3FFF*/ nSymMask, nLayerStart, nLayer); #if 1 { mlogVar[mlogVarCnt++] = 0xefefefef; mlogVar[mlogVarCnt++] = nCellIdx; mlogVar[mlogVarCnt++] = nSfIdx; mlogVar[mlogVarCnt++] = nSymbStart; mlogVar[mlogVarCnt++] = nSymb; mlogVar[mlogVarCnt++] = nLayerStart; mlogVar[mlogVarCnt++] = nLayer; mlogVar[mlogVarCnt++] = iSplit; MLogAddVariables(mlogVarCnt, mlogVar, mlog_start); } #endif //unlock the next task next_event_unlock(pCookies); MLogTask(PCID_GNB_DL_POST_CC0+nCellIdx, mlog_start, MLogTick()); return EBBUPOOL_CORRECT; }