* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / app / src / app_bbu_pool.c
diff --git a/fhi_lib/app/src/app_bbu_pool.c b/fhi_lib/app/src/app_bbu_pool.c
new file mode 100644 (file)
index 0000000..fd897c0
--- /dev/null
@@ -0,0 +1,625 @@
+/******************************************************************************
+*
+*   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 <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <pthread.h>
+#include <immintrin.h>
+
+#include "app_bbu_pool.h"
+
+/**
+  * @file   gnb_main_ebbu_pool.c
+  * @brief  example pipeline code to use Enhanced BBUPool Framework
+*/
+
+extern int32_t gQueueCtxNum;
+extern int32_t nSplitNumCell[EBBU_POOL_MAX_TEST_CELL];
+
+int32_t test_func_A(void *pCookies);
+int32_t test_func_B(void *pCookies);
+int32_t test_func_C(void *pCookies);
+
+void test_pre_func_A(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara);
+void test_pre_func_B(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara);
+
+int32_t test_func_gen(eBbuPoolHandler pHandler, int32_t nCell, int32_t nSlot, int32_t eventId);
+
+int32_t simulate_traffic(void *pCookies, int32_t testCount);
+
+typedef enum
+{
+    CAT_A = 0, //directly execute
+    CAT_B,     //highest priority
+    CAT_C,     //first priority
+    CAT_D,     //second priority
+    CAT_E,     //third priority
+    CAT_F,     //forth priority
+    CAT_G,     //fifth priority
+    CAT_H,     //sixth priority
+    CAT_I,     //seventh priority
+    CAT_NUM
+} EventCatEnum;
+
+static int32_t eventSendDic[CAT_NUM] =
+{
+    EBBUPOOL_PRIO_EXECUTE,
+    EBBUPOOL_PRIO_HIGHEST,
+    EBBUPOOL_PRIO_ONE,
+    EBBUPOOL_PRIO_TWO,
+    EBBUPOOL_PRIO_THREE,
+    EBBUPOOL_PRIO_FOUR,
+    EBBUPOOL_PRIO_FIVE,
+    EBBUPOOL_PRIO_SIX,
+    EBBUPOOL_PRIO_SEVEN
+};
+
+EventConfigStruct testEventTable[MAX_TASK_NUM_G_NB] =
+{
+    /* Event ID*/        /* Event Name*/           /* pri */   /* event function */  /* pre event function */   /* nExtEvent */  /*prefetch flag */  /*core mask type */   /* core affinity 0~63 */ /* core affinity 64~127 */
+    { TTI_START,        EVENT_NAME(TTI_START),       CAT_B,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { SYM2_WAKE_UP,     EVENT_NAME(SYM2_WAKE_UP),    CAT_B,  app_bbu_pool_task_sym2_wakeup,   NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { SYM6_WAKE_UP,     EVENT_NAME(SYM6_WAKE_UP),    CAT_B,  app_bbu_pool_task_sym6_wakeup,   NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { SYM11_WAKE_UP,    EVENT_NAME(SYM11_WAKE_UP),   CAT_B,  app_bbu_pool_task_sym11_wakeup,  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { SYM13_WAKE_UP,    EVENT_NAME(SYM13_WAKE_UP),   CAT_B,  app_bbu_pool_task_sym13_wakeup,  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { PRACH_WAKE_UP,    EVENT_NAME(PRACH_WAKE_UP),   CAT_B,  app_bbu_pool_task_prach_wakeup,  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { SRS_WAKE_UP,      EVENT_NAME(SRS_WAKE_UP),     CAT_B,  app_bbu_pool_task_srs_wakeup,    NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_CONFIG,        EVENT_NAME(DL_CONFIG),       CAT_B, app_bbu_pool_task_dl_config,app_bbu_pool_pre_task_dl_cfg, 0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_PDSCH_TB,      EVENT_NAME(DL_PDSCH_TB),     CAT_B,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
+    { DL_PDSCH_SCRM,    EVENT_NAME(DL_PDSCH_SCRM),   CAT_C,     test_func_A,                  NULL,                   0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
+    { DL_PDSCH_SYM,     EVENT_NAME(DL_PDSCH_SYM),    CAT_C,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_PDSCH_RS,      EVENT_NAME(DL_PDSCH_RS),     CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_CTRL,          EVENT_NAME(DL_CTRL),         CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_CONFIG,        EVENT_NAME(UL_CONFIG),       CAT_C, app_bbu_pool_task_ul_config,app_bbu_pool_pre_task_ul_cfg, 0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_IQ_DECOMP2,    EVENT_NAME(UL_IQ_DECOMP2),   CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_IQ_DECOMP6,    EVENT_NAME(UL_IQ_DECOMP6),   CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_IQ_DECOMP11,   EVENT_NAME(UL_IQ_DECOMP11),  CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_IQ_DECOMP13,   EVENT_NAME(UL_IQ_DECOMP13),  CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_CE0,     EVENT_NAME(UL_PUSCH_CE0),    CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_CE7,     EVENT_NAME(UL_PUSCH_CE7),    CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_EQL0,    EVENT_NAME(UL_PUSCH_EQL0),   CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_EQL7,    EVENT_NAME(UL_PUSCH_EQL7),   CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_LLR,     EVENT_NAME(UL_PUSCH_LLR),    CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_DEC,     EVENT_NAME(UL_PUSCH_DEC),    CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PUSCH_TB,      EVENT_NAME(UL_PUSCH_TB),     CAT_C,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PUCCH,         EVENT_NAME(UL_PUCCH),        CAT_E,     test_func_A,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_PRACH,         EVENT_NAME(UL_PRACH),        CAT_E,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_SRS_DECOMP,    EVENT_NAME(UL_SRS_DECOMP),   CAT_E,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_SRS_CE,        EVENT_NAME(UL_SRS_CE),       CAT_E,     test_func_B,             test_pre_func_B,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
+    { UL_SRS_POST,      EVENT_NAME(UL_SRS_POST),     CAT_E,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_POST,          EVENT_NAME(DL_POST),         CAT_B, app_bbu_pool_task_dl_post, app_bbu_pool_pre_task_dl_post, 0,           1,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_POST,          EVENT_NAME(UL_POST),         CAT_A,     test_func_C,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_BEAM_GEN,      EVENT_NAME(DL_BEAM_GEN),     CAT_D,     test_func_B,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { DL_BEAM_TX,       EVENT_NAME(DL_BEAM_TX),      CAT_D,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_BEAM_GEN,      EVENT_NAME(UL_BEAM_GEN),     CAT_D,     test_func_B,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+    { UL_BEAM_TX,       EVENT_NAME(UL_BEAM_TX),      CAT_D,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
+};
+
+int32_t gNBNextTaskMap[MAX_TASK_NUM_G_NB][MAX_NEXT_TASK_NUM] =
+{
+    // TTI_START
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // SYM2_WAKE_UP
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // SYM6_WAKE_UP
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // SYM11_WAKE_UP
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // SYM13_WAKE_UP
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // PRACH_WAKE_UP
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // SRS_WAKE_UP
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_CONFIG
+    {DL_PDSCH_TB,             DL_CTRL,         DL_PDSCH_RS,         DL_BEAM_GEN,                 -1,                  -1,                  -1,                  -1},
+
+    // DL_PDSCH_TB
+    {DL_PDSCH_SCRM,                -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_PDSCH_SCRM
+    {DL_PDSCH_SYM,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_PDSCH_SYM
+    {DL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_PDSCH_RS
+    {DL_PDSCH_SYM,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_CTRL
+    {DL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_CONFIG
+    {UL_IQ_DECOMP2,    UL_IQ_DECOMP6,      UL_IQ_DECOMP11,      UL_IQ_DECOMP13,            UL_PUCCH,            UL_PRACH,       UL_SRS_DECOMP,         UL_BEAM_GEN},
+
+    // UL_IQ_DECOMP2
+    {UL_PUSCH_CE0,       UL_PUSCH_CE7,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_IQ_DECOMP6
+    {UL_PUSCH_EQL0,     UL_PUSCH_EQL7,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_IQ_DECOMP11
+    {UL_PUSCH_CE7,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_IQ_DECOMP13
+    {UL_PUSCH_EQL7,          UL_PUCCH,      UL_SRS_DECOMP,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_CE0
+    {UL_PUSCH_EQL0,     UL_PUSCH_EQL7,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_CE7
+    {UL_PUSCH_EQL7,                -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_EQL0
+    {UL_PUSCH_LLR,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_EQL7
+    {UL_PUSCH_LLR,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_LLR
+    {UL_PUSCH_DEC,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_DEC
+    {UL_PUSCH_TB,                  -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUSCH_TB
+    {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PUCCH
+    {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_PRACH
+    {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_SRS_DECOMP
+    {UL_SRS_CE,                    -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_SRS_CE
+    {UL_SRS_POST,                  -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_SRS_POST
+    {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_POST
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_POST
+    {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_BEAM_GEN
+    {DL_BEAM_TX,                   -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // DL_BEAM_TX
+    {DL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_BEAM_GEN
+    {UL_BEAM_TX,                   -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+
+    // UL_BEAM_TX
+    {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
+};
+
+__attribute__((aligned(IA_ALIGN))) EventCtrlStruct gEventCtrl[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX][MAX_TASK_NUM_G_NB][MAX_TEST_SPLIT_NUM];
+static __attribute__((aligned(IA_ALIGN))) EventStruct gEvent[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX][MAX_TASK_NUM_G_NB][MAX_TEST_SPLIT_NUM];
+__attribute__((aligned(IA_ALIGN))) EventChainDescStruct gEventChain[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX];
+static SampleSplitStruct gsSampleSplit[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX][MAX_TEST_SPLIT_NUM];
+
+static uint64_t dl_start_mlog[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX];
+static uint64_t ul_start_mlog[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX];
+extern volatile uint64_t ttistart;
+extern int32_t dl_ul_count, dl_count, ul_count;
+int32_t test_buffer_create()
+{
+    int32_t iCell, iCtx, iTask, iSplit;
+    for(iCell = 0; iCell < EBBU_POOL_MAX_TEST_CELL; iCell ++)
+        for(iCtx = 0; iCtx < MAX_TEST_CTX; iCtx ++)
+            for(iTask = 0; iTask < MAX_TASK_NUM_G_NB; iTask ++)
+                for(iSplit = 0; iSplit < MAX_TEST_SPLIT_NUM; iSplit ++)
+                    gEventCtrl[iCell][iCtx][iTask][iSplit].dummy0 = (float *)_mm_malloc(sizeof(float), IA_ALIGN);
+    return 0;
+}
+
+int32_t event_chain_gen(EventChainDescStruct *psEventChain)
+{
+    /*Construct the next event chain by copying existing array */
+    psEventChain->eventChainDepth = MAX_TASK_NUM_G_NB;
+    memcpy((void *)psEventChain->nextEventChain, (void *)gNBNextTaskMap, sizeof(gNBNextTaskMap));
+    //printf("\nCopy gNBNextTaskMap with size %d", sizeof(gNBNextTaskMap));
+    memset((void *)&psEventChain->nextEventCount, 0 , sizeof(psEventChain->nextEventCount));
+    memset((void *)&psEventChain->preEventCount, 0 , sizeof(psEventChain->preEventCount));
+    memset((void *)&psEventChain->preEventStat, 0 , sizeof(psEventChain->preEventStat));
+
+    /*For each event, find all preceding dependent event */
+    int32_t iEvent = 0;
+    int32_t iNext = 0;
+
+    /* Set the external event Wakeup Dependencies (apart from Task Dependency) */
+    for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent++)
+    {
+        psEventChain->preEventCountSave[iEvent] = testEventTable[iEvent].nWakeOnExtrernalEvent;
+    }
+
+    for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent ++)
+    {
+        for(iNext = 0; iNext < MAX_NEXT_TASK_NUM; iNext ++)
+        {
+            if(psEventChain->nextEventChain[iEvent][iNext] != -1)
+            {
+                psEventChain->preEventCountSave[psEventChain->nextEventChain[iEvent][iNext]] ++;
+                psEventChain->nextEventCount[iEvent] ++;
+            }
+        }
+    }
+
+    /*
+    for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent ++)
+    {
+        printf("\nEvent %d preEvent %d",iEvent,psEventChain->preEventCount[iEvent]);
+    }
+    */
+    return 0;
+}
+
+int32_t event_chain_reset(EventChainDescStruct *psEventChain)
+{
+    memset((void *)&psEventChain->preEventStat, 0 , sizeof(psEventChain->preEventStat));
+
+    /*For each event, find all preceding dependent event */
+    int32_t iEvent = 0;
+
+    /* Set the external event Wakeup Dependencies (apart from Task Dependency) */
+    for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent++)
+    {
+        psEventChain->preEventCount[iEvent] = psEventChain->preEventCountSave[iEvent];
+    }
+    return 0;
+}
+
+static void set_event_info(EventCtrlStruct *pEvenCtrl, int32_t eventId,
+     int32_t iSplit, EventSendStruct *psEventSend)
+{
+    int32_t nCell = pEvenCtrl->nCellIdx;
+    int32_t nSlot = pEvenCtrl->nSlotIdx;
+    int32_t nCtx = nSlot % MAX_TEST_CTX;
+    int32_t nQueueCtxNum = nSlot % gQueueCtxNum;
+    EventStruct * pEvent = &gEvent[nCell][nCtx][eventId][iSplit];
+    pEvent->pEventFunc = testEventTable[eventId].pEventFunc;
+    pEvent->pEventArgs = pEvenCtrl;
+    pEvent->nEventId = eventId;
+    pEvent->nEventSentTime = ebbu_pool_tick();
+    pEvent->nEventSentTimeMlog = MLogTick();
+    pEvent->nEventAliveTime = 10000000;
+    pEvent->nCoreAffinityMask = _mm256_set_epi64x(0,0,testEventTable[eventId].nCoreMask1,testEventTable[eventId].nCoreMask0);
+    pEvent->nEventStatus = EBBUPOOL_EVENT_VALID;
+
+    psEventSend->eDisposFlag = EBBUPOOL_NON_DISPOSABLE;
+
+    psEventSend->ePrioCat = eventSendDic[testEventTable[eventId].nEventPrio];
+    psEventSend->nQueueCtx = 0;
+    if(gQueueCtxNum > 1)
+        psEventSend->nQueueCtx = nQueueCtxNum;
+
+    psEventSend->psEventStruct[0] = pEvent;
+    psEventSend->nEventNum = 1;
+
+    psEventSend->nPreFlag = testEventTable[eventId].nPrefetchFlag;
+
+    return;
+}
+
+static void set_split_event_info(EventCtrlStruct *pEvenCtrl, int32_t eventId,
+     int32_t nSplit, EventSendStruct *psEventSend)
+{
+    int32_t nCell = pEvenCtrl[0].nCellIdx;
+    int32_t nSlot = pEvenCtrl[0].nSlotIdx;
+    int32_t nCtx = nSlot % MAX_TEST_CTX;
+    int32_t nQueueCtxNum = nSlot % gQueueCtxNum;
+    int32_t iSplit = 0;
+    for(; iSplit < nSplit; iSplit ++)
+    {
+        EventStruct *pEvent = &gEvent[nCell][nCtx][eventId][iSplit];
+        pEvent->pEventFunc = testEventTable[eventId].pEventFunc;
+        pEvent->pEventArgs = &pEvenCtrl[iSplit];
+        pEvent->nEventId = eventId;
+        pEvent->nEventSentTime = ebbu_pool_tick();
+        pEvent->nEventSentTimeMlog = MLogTick();
+        pEvent->nEventAliveTime = 10000000;
+        pEvent->nCoreAffinityMask = _mm256_set_epi64x(0,0,testEventTable[eventId].nCoreMask1,testEventTable[eventId].nCoreMask0);
+        pEvent->nEventStatus = EBBUPOOL_EVENT_VALID;
+        psEventSend->psEventStruct[iSplit] = pEvent;
+    }
+    pEvenCtrl[0].tSendTime = MLogTick();
+    psEventSend->eDisposFlag = EBBUPOOL_DISPOSABLE;
+    psEventSend->ePrioCat = eventSendDic[testEventTable[eventId].nEventPrio];
+    psEventSend->nQueueCtx = 0;
+    if(gQueueCtxNum > 1)
+        psEventSend->nQueueCtx = nQueueCtxNum;
+    psEventSend->nEventNum = nSplit;
+    psEventSend->nPreFlag = testEventTable[eventId].nPrefetchFlag;
+
+    return;
+}
+
+int32_t next_event_unlock(void *pCookies)
+{
+    EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
+    eBbuPoolHandler pHandler = (eBbuPoolHandler)pEvenCtrl->pHandler;
+    int32_t nCell = pEvenCtrl->nCellIdx;
+    int32_t nSlot = pEvenCtrl->nSlotIdx;
+    int32_t nCtx = nSlot % MAX_TEST_CTX;
+    int32_t eventId = pEvenCtrl->nEventId;
+    EventChainDescStruct * pEventChain = &gEventChain[nCell][nCtx];
+
+    if(eventId == DL_POST||eventId == UL_POST)
+        ebbu_pool_queue_ctx_add(pHandler, nCtx);
+
+    /*Set and check the status of all next event */
+    /*Then decide whether to send next event or not */
+    int32_t iNext = 0;
+    int32_t nextEventId = 0;
+
+    for(iNext = 0; iNext < pEventChain->nextEventCount[eventId]; iNext++)
+    {
+        nextEventId = pEventChain->nextEventChain[eventId][iNext];
+        /*printf("\nnSlot %d event %d nextEventCount %d inext %d next %d next_pre_count %d next_pre_stat %d",
+            nSlotIdx, nTaskId, pEventChain->nextEventCount[nTaskId], iNext, nextEventId,
+            pEventChain->preEventCount[nextEventId], pEventChain->preEventStat[nextEventId]);
+        */
+
+        if(__atomic_add_fetch(&pEventChain->preEventStat[nextEventId], 1, __ATOMIC_ACQ_REL) ==
+           __atomic_load_n(&pEventChain->preEventCount[nextEventId], __ATOMIC_ACQUIRE))
+        {
+            test_func_gen(pHandler, nCell, nSlot, nextEventId);
+        }
+    }
+
+    return 0;
+}
+
+int32_t test_func_gen(eBbuPoolHandler pHandler, int32_t nCell, int32_t nSlot, int32_t eventId)
+{
+    int j;
+    if(eventId >= MAX_TASK_NUM_G_NB || nCell >= EBBU_POOL_MAX_TEST_CELL)
+    {
+        printf("\nError! Wrong eventId %d max %d nCell %d",eventId, MAX_TASK_NUM_G_NB, nCell);
+        exit(-1);
+    }
+
+    int32_t nCtx = nSlot % MAX_TEST_CTX;
+    int32_t iNext, iNextEventId, nSplitIdx;
+    EventChainDescStruct * pEventChain = &gEventChain[nCell][nCtx];
+    EventSendStruct sEventSend;
+    EventCtrlStruct *pEventCtrl;
+    TaskPreGen sPara;
+    int32_t nSplit = 1, ret = 0;
+
+    uint64_t t1 = MLogTick();
+
+    if(DL_CONFIG == eventId)
+        dl_start_mlog[nCell][nCtx] = t1;
+    else if(UL_CONFIG == eventId)
+        ul_start_mlog[nCell][nCtx] = t1;
+
+    // Klocwork check
+    for (j = 0; j < MAX_TEST_SPLIT_NUM; j++)
+        sPara.pTaskExePara[j] = (void *)&gsSampleSplit[nCell%EBBU_POOL_MAX_TEST_CELL][nSlot%MAX_TEST_CTX][j];
+
+    if (testEventTable[eventId].pPreEventFunc)
+    {
+        /* Run Pre Event and Find out how many split */
+        sPara.nTaskNum = 1;
+        testEventTable[eventId].pPreEventFunc(nSlot, nCell, &sPara);
+        nSplit = sPara.nTaskNum;
+        if(nSplit > 1)
+        {
+            /* Add the split to all the Nex Next Dependencies */
+            for(iNext = 0; iNext < pEventChain->nextEventCount[eventId]; iNext++)
+            {
+                iNextEventId = pEventChain->nextEventChain[eventId][iNext];
+                __atomic_add_fetch(&pEventChain->preEventCount[iNextEventId], nSplit - 1, __ATOMIC_ACQ_REL);
+            }
+        }
+    }
+
+    //send the splitted events together, save ebbupool internal overhead
+    for(nSplitIdx = 0; nSplitIdx < nSplit; nSplitIdx++)
+    {
+        pEventCtrl = &gEventCtrl[nCell][nCtx][eventId][nSplitIdx];
+        pEventCtrl->nEventId = eventId;
+        pEventCtrl->nSplitIdx = nSplitIdx;
+        pEventCtrl->nCellIdx = nCell;
+        pEventCtrl->nSlotIdx = nSlot;
+        pEventCtrl->pTaskPara = sPara.pTaskExePara[nSplitIdx];
+        pEventCtrl->pHandler = pHandler;
+    }
+
+    set_split_event_info(&gEventCtrl[nCell][nCtx][eventId][0], eventId, nSplit, &sEventSend);
+    ret = ebbu_pool_send_event(pHandler, sEventSend);
+
+    if(0 != ret)
+        printf("\nEvent %d gen failed!",eventId);
+
+    MLogTask(MAX_TASK_NUM_G_NB * nCell + eventId + 2000, t1, MLogTick());
+
+    return 0;
+}
+void test_pre_func_A(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara)
+{
+    // uint64_t t1 = MLogTick();
+    //printf("\nfunc pre A event %d",pEvenCtrl->nEventId);
+    // int32_t ret = 0;
+    //do some traffic
+    //ret = simulate_traffic(pCookies, 1000);
+
+    pPara->nTaskNum = nSplitNumCell[nCellIdx];
+    int32_t iSplit = 0;
+    for(iSplit = 0; iSplit < pPara->nTaskNum; iSplit ++)
+    {
+        pPara->pTaskExePara[iSplit] = (void *)&gsSampleSplit[nCellIdx%EBBU_POOL_MAX_TEST_CELL][nSubframe%MAX_TEST_CTX][iSplit];
+    }
+    return;
+    //MLogTask(MAX_TASK_NUM_G_NB * pInputPara->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
+}
+
+
+void test_pre_func_B(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara)
+{
+    // uint64_t t1 = MLogTick();
+    //printf("\nfunc pre A event %d",pEvenCtrl->nEventId);
+    // int32_t ret = 0;
+
+    //do some traffic
+    //ret = simulate_traffic(pCookies, 1000);
+    int32_t iSplit = 0;
+    for(iSplit = 0; iSplit < pPara->nTaskNum; iSplit ++)
+    {
+        pPara->pTaskExePara[iSplit] = (void *)&gsSampleSplit[nCellIdx%EBBU_POOL_MAX_TEST_CELL][nSubframe%MAX_TEST_CTX][iSplit];
+    }
+    return;
+
+    pPara->nTaskNum = nSplitNumCell[nCellIdx];
+
+    //MLogTask(MAX_TASK_NUM_G_NB * pInputPara->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
+}
+
+int32_t test_func_A(void *pCookies)
+{
+    EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
+
+    uint64_t t1 = MLogTick();
+#if 0
+    //printf("\nfunc A event %d",pEvenCtrl->nEventId);
+    if(DL_CONFIG == pEvenCtrl->nEventId)
+    {
+        app_bbu_pool_task_dl_config(pCookies);
+        MLogTask(pEvenCtrl->nCellIdx + 4000, pEvenCtrl->tSendTime, t1);
+    }
+
+    if(UL_CONFIG == pEvenCtrl->nEventId)
+    {
+        app_bbu_pool_task_ul_config(pCookies);
+        MLogTask(pEvenCtrl->nCellIdx + 5000, pEvenCtrl->tSendTime, t1);
+    }
+#endif
+    // int32_t ret = 0;
+
+    //do some traffic
+    //ret = simulate_traffic(pCookies, 3000);
+    //usleep(10);
+
+    //unlock the next task
+    next_event_unlock(pCookies);
+
+    MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
+    //printf("\nfunc a latency %llu",MLogTick()-t1);
+
+    return 0;
+
+}
+
+int32_t test_func_B(void *pCookies)
+{
+    EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
+
+    uint64_t t1 = MLogTick();
+    //printf("\nfunc B event %d",pEvenCtrl->nEventId);
+    // int32_t ret = 0;
+
+    //do some traffic
+    //ret = simulate_traffic(pCookies, 5000);
+    //usleep(10);
+
+    //unlock the next task
+    next_event_unlock(pCookies);
+
+    MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
+
+    return 0;
+}
+
+int32_t test_func_C(void *pCookies)
+{
+    EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
+
+    uint64_t t1 = MLogTick();
+    //printf("\nfunc B event %d",pEvenCtrl->nEventId);
+    int32_t ret = 0;
+
+    //do some traffic
+
+    MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
+
+    if(pEvenCtrl->nEventId == DL_POST || pEvenCtrl->nEventId == UL_POST)
+    {
+        if(__atomic_sub_fetch(&dl_ul_count, 1, __ATOMIC_ACQ_REL) == 0)
+        {
+            MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + 6000, ttistart, MLogTick());
+        }
+    }
+
+    MLogTask(77777, t1, MLogTick());
+    return ret;
+}
+
+#if 0
+int32_t simulate_traffic(void *pCookies, int32_t testCount)
+{
+    //printf("\ndo traffic!");
+    EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
+    __m256 sigma2 = _mm256_set1_ps(testCount/1234.5);
+    __m256 ftemp1, ftemp2;
+
+    int32_t m = testCount;
+    m = m/2;
+
+    while(m > 0)
+    {
+        ftemp1 = _mm256_rcp_ps(sigma2);
+        ftemp2 = _mm256_sub_ps(_mm256_set1_ps(0), sigma2);
+        ftemp2 = _mm256_fmadd_ps(ftemp1, sigma2, ftemp2);
+        sigma2 = _mm256_rcp_ps(ftemp2);
+        m --;
+    }
+
+    int32_t nfloat = 8; //256bits has eight 32bits
+    float *dummy = (float *)&sigma2;
+    *pEvenCtrl->dummy0 = 0;
+    for(m = 0; m < nfloat; m++)
+        *pEvenCtrl->dummy0 += dummy[m];
+
+    return 0;
+}
+#endif