* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / app / src / app_bbu_pool.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 Intel.
4 *
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
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief This module provides implementation of BBU tasks for sample app
21  * @file app_bbu.c
22  * @ingroup xran
23  * @author Intel Corporation
24  *
25  **/
26
27 #include <memory.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <assert.h>
32 #include <pthread.h>
33 #include <immintrin.h>
34
35 #include "app_bbu_pool.h"
36
37 /**
38   * @file   gnb_main_ebbu_pool.c
39   * @brief  example pipeline code to use Enhanced BBUPool Framework
40 */
41
42 extern int32_t gQueueCtxNum;
43 extern int32_t nSplitNumCell[EBBU_POOL_MAX_TEST_CELL];
44
45 int32_t test_func_A(void *pCookies);
46 int32_t test_func_B(void *pCookies);
47 int32_t test_func_C(void *pCookies);
48
49 void test_pre_func_A(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara);
50 void test_pre_func_B(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara);
51
52 int32_t test_func_gen(eBbuPoolHandler pHandler, int32_t nCell, int32_t nSlot, int32_t eventId);
53
54 int32_t simulate_traffic(void *pCookies, int32_t testCount);
55
56 typedef enum
57 {
58     CAT_A = 0, //directly execute
59     CAT_B,     //highest priority
60     CAT_C,     //first priority
61     CAT_D,     //second priority
62     CAT_E,     //third priority
63     CAT_F,     //forth priority
64     CAT_G,     //fifth priority
65     CAT_H,     //sixth priority
66     CAT_I,     //seventh priority
67     CAT_NUM
68 } EventCatEnum;
69
70 static int32_t eventSendDic[CAT_NUM] =
71 {
72     EBBUPOOL_PRIO_EXECUTE,
73     EBBUPOOL_PRIO_HIGHEST,
74     EBBUPOOL_PRIO_ONE,
75     EBBUPOOL_PRIO_TWO,
76     EBBUPOOL_PRIO_THREE,
77     EBBUPOOL_PRIO_FOUR,
78     EBBUPOOL_PRIO_FIVE,
79     EBBUPOOL_PRIO_SIX,
80     EBBUPOOL_PRIO_SEVEN
81 };
82
83 EventConfigStruct testEventTable[MAX_TASK_NUM_G_NB] =
84 {
85     /* Event ID*/        /* Event Name*/           /* pri */   /* event function */  /* pre event function */   /* nExtEvent */  /*prefetch flag */  /*core mask type */   /* core affinity 0~63 */ /* core affinity 64~127 */
86     { TTI_START,        EVENT_NAME(TTI_START),       CAT_B,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
87     { SYM2_WAKE_UP,     EVENT_NAME(SYM2_WAKE_UP),    CAT_B,  app_bbu_pool_task_sym2_wakeup,   NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
88     { SYM6_WAKE_UP,     EVENT_NAME(SYM6_WAKE_UP),    CAT_B,  app_bbu_pool_task_sym6_wakeup,   NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
89     { SYM11_WAKE_UP,    EVENT_NAME(SYM11_WAKE_UP),   CAT_B,  app_bbu_pool_task_sym11_wakeup,  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
90     { SYM13_WAKE_UP,    EVENT_NAME(SYM13_WAKE_UP),   CAT_B,  app_bbu_pool_task_sym13_wakeup,  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
91     { PRACH_WAKE_UP,    EVENT_NAME(PRACH_WAKE_UP),   CAT_B,  app_bbu_pool_task_prach_wakeup,  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
92     { SRS_WAKE_UP,      EVENT_NAME(SRS_WAKE_UP),     CAT_B,  app_bbu_pool_task_srs_wakeup,    NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
93     { 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},
94     { DL_PDSCH_TB,      EVENT_NAME(DL_PDSCH_TB),     CAT_B,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
95     { DL_PDSCH_SCRM,    EVENT_NAME(DL_PDSCH_SCRM),   CAT_C,     test_func_A,                  NULL,                   0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
96     { DL_PDSCH_SYM,     EVENT_NAME(DL_PDSCH_SYM),    CAT_C,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
97     { DL_PDSCH_RS,      EVENT_NAME(DL_PDSCH_RS),     CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
98     { DL_CTRL,          EVENT_NAME(DL_CTRL),         CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
99     { 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},
100     { UL_IQ_DECOMP2,    EVENT_NAME(UL_IQ_DECOMP2),   CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
101     { UL_IQ_DECOMP6,    EVENT_NAME(UL_IQ_DECOMP6),   CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
102     { UL_IQ_DECOMP11,   EVENT_NAME(UL_IQ_DECOMP11),  CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
103     { UL_IQ_DECOMP13,   EVENT_NAME(UL_IQ_DECOMP13),  CAT_D,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
104     { UL_PUSCH_CE0,     EVENT_NAME(UL_PUSCH_CE0),    CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
105     { UL_PUSCH_CE7,     EVENT_NAME(UL_PUSCH_CE7),    CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
106     { UL_PUSCH_EQL0,    EVENT_NAME(UL_PUSCH_EQL0),   CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
107     { UL_PUSCH_EQL7,    EVENT_NAME(UL_PUSCH_EQL7),   CAT_D,     test_func_B,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
108     { UL_PUSCH_LLR,     EVENT_NAME(UL_PUSCH_LLR),    CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
109     { UL_PUSCH_DEC,     EVENT_NAME(UL_PUSCH_DEC),    CAT_C,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
110     { UL_PUSCH_TB,      EVENT_NAME(UL_PUSCH_TB),     CAT_C,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
111     { UL_PUCCH,         EVENT_NAME(UL_PUCCH),        CAT_E,     test_func_A,             test_pre_func_A,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
112     { UL_PRACH,         EVENT_NAME(UL_PRACH),        CAT_E,     test_func_A,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
113     { UL_SRS_DECOMP,    EVENT_NAME(UL_SRS_DECOMP),   CAT_E,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
114     { UL_SRS_CE,        EVENT_NAME(UL_SRS_CE),       CAT_E,     test_func_B,             test_pre_func_B,             0,           0,                        0,            0x000000ffffffffff,          0xfffffffffffffff},
115     { UL_SRS_POST,      EVENT_NAME(UL_SRS_POST),     CAT_E,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
116     { 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},
117     { UL_POST,          EVENT_NAME(UL_POST),         CAT_A,     test_func_C,                  NULL,                   0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
118     { DL_BEAM_GEN,      EVENT_NAME(DL_BEAM_GEN),     CAT_D,     test_func_B,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
119     { DL_BEAM_TX,       EVENT_NAME(DL_BEAM_TX),      CAT_D,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
120     { UL_BEAM_GEN,      EVENT_NAME(UL_BEAM_GEN),     CAT_D,     test_func_B,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
121     { UL_BEAM_TX,       EVENT_NAME(UL_BEAM_TX),      CAT_D,     test_func_A,             test_pre_func_B,             0,           0,                        0,            0x00ffffffffffffff,          0xfffffffffffffff},
122 };
123
124 int32_t gNBNextTaskMap[MAX_TASK_NUM_G_NB][MAX_NEXT_TASK_NUM] =
125 {
126     // TTI_START
127     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
128
129     // SYM2_WAKE_UP
130     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
131
132     // SYM6_WAKE_UP
133     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
134
135     // SYM11_WAKE_UP
136     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
137
138     // SYM13_WAKE_UP
139     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
140
141     // PRACH_WAKE_UP
142     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
143
144     // SRS_WAKE_UP
145     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
146
147     // DL_CONFIG
148     {DL_PDSCH_TB,             DL_CTRL,         DL_PDSCH_RS,         DL_BEAM_GEN,                 -1,                  -1,                  -1,                  -1},
149
150     // DL_PDSCH_TB
151     {DL_PDSCH_SCRM,                -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
152
153     // DL_PDSCH_SCRM
154     {DL_PDSCH_SYM,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
155
156     // DL_PDSCH_SYM
157     {DL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
158
159     // DL_PDSCH_RS
160     {DL_PDSCH_SYM,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
161
162     // DL_CTRL
163     {DL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
164
165     // UL_CONFIG
166     {UL_IQ_DECOMP2,    UL_IQ_DECOMP6,      UL_IQ_DECOMP11,      UL_IQ_DECOMP13,            UL_PUCCH,            UL_PRACH,       UL_SRS_DECOMP,         UL_BEAM_GEN},
167
168     // UL_IQ_DECOMP2
169     {UL_PUSCH_CE0,       UL_PUSCH_CE7,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
170
171     // UL_IQ_DECOMP6
172     {UL_PUSCH_EQL0,     UL_PUSCH_EQL7,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
173
174     // UL_IQ_DECOMP11
175     {UL_PUSCH_CE7,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
176
177     // UL_IQ_DECOMP13
178     {UL_PUSCH_EQL7,          UL_PUCCH,      UL_SRS_DECOMP,                  -1,                  -1,                  -1,                  -1,                  -1},
179
180     // UL_PUSCH_CE0
181     {UL_PUSCH_EQL0,     UL_PUSCH_EQL7,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
182
183     // UL_PUSCH_CE7
184     {UL_PUSCH_EQL7,                -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
185
186     // UL_PUSCH_EQL0
187     {UL_PUSCH_LLR,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
188
189     // UL_PUSCH_EQL7
190     {UL_PUSCH_LLR,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
191
192     // UL_PUSCH_LLR
193     {UL_PUSCH_DEC,                 -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
194
195     // UL_PUSCH_DEC
196     {UL_PUSCH_TB,                  -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
197
198     // UL_PUSCH_TB
199     {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
200
201     // UL_PUCCH
202     {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
203
204     // UL_PRACH
205     {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
206
207     // UL_SRS_DECOMP
208     {UL_SRS_CE,                    -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
209
210     // UL_SRS_CE
211     {UL_SRS_POST,                  -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
212
213     // UL_SRS_POST
214     {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
215
216     // DL_POST
217     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
218
219     // UL_POST
220     {-1,                           -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
221
222     // DL_BEAM_GEN
223     {DL_BEAM_TX,                   -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
224
225     // DL_BEAM_TX
226     {DL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
227
228     // UL_BEAM_GEN
229     {UL_BEAM_TX,                   -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
230
231     // UL_BEAM_TX
232     {UL_POST,                      -1,                 -1,                  -1,                  -1,                  -1,                  -1,                  -1},
233 };
234
235 __attribute__((aligned(IA_ALIGN))) EventCtrlStruct gEventCtrl[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX][MAX_TASK_NUM_G_NB][MAX_TEST_SPLIT_NUM];
236 static __attribute__((aligned(IA_ALIGN))) EventStruct gEvent[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX][MAX_TASK_NUM_G_NB][MAX_TEST_SPLIT_NUM];
237 __attribute__((aligned(IA_ALIGN))) EventChainDescStruct gEventChain[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX];
238 static SampleSplitStruct gsSampleSplit[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX][MAX_TEST_SPLIT_NUM];
239
240 static uint64_t dl_start_mlog[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX];
241 static uint64_t ul_start_mlog[EBBU_POOL_MAX_TEST_CELL][MAX_TEST_CTX];
242 extern volatile uint64_t ttistart;
243 extern int32_t dl_ul_count, dl_count, ul_count;
244 int32_t test_buffer_create()
245 {
246     int32_t iCell, iCtx, iTask, iSplit;
247     for(iCell = 0; iCell < EBBU_POOL_MAX_TEST_CELL; iCell ++)
248         for(iCtx = 0; iCtx < MAX_TEST_CTX; iCtx ++)
249             for(iTask = 0; iTask < MAX_TASK_NUM_G_NB; iTask ++)
250                 for(iSplit = 0; iSplit < MAX_TEST_SPLIT_NUM; iSplit ++)
251                     gEventCtrl[iCell][iCtx][iTask][iSplit].dummy0 = (float *)_mm_malloc(sizeof(float), IA_ALIGN);
252     return 0;
253 }
254
255 int32_t event_chain_gen(EventChainDescStruct *psEventChain)
256 {
257     /*Construct the next event chain by copying existing array */
258     psEventChain->eventChainDepth = MAX_TASK_NUM_G_NB;
259     memcpy((void *)psEventChain->nextEventChain, (void *)gNBNextTaskMap, sizeof(gNBNextTaskMap));
260     //printf("\nCopy gNBNextTaskMap with size %d", sizeof(gNBNextTaskMap));
261     memset((void *)&psEventChain->nextEventCount, 0 , sizeof(psEventChain->nextEventCount));
262     memset((void *)&psEventChain->preEventCount, 0 , sizeof(psEventChain->preEventCount));
263     memset((void *)&psEventChain->preEventStat, 0 , sizeof(psEventChain->preEventStat));
264
265     /*For each event, find all preceding dependent event */
266     int32_t iEvent = 0;
267     int32_t iNext = 0;
268
269     /* Set the external event Wakeup Dependencies (apart from Task Dependency) */
270     for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent++)
271     {
272         psEventChain->preEventCountSave[iEvent] = testEventTable[iEvent].nWakeOnExtrernalEvent;
273     }
274
275     for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent ++)
276     {
277         for(iNext = 0; iNext < MAX_NEXT_TASK_NUM; iNext ++)
278         {
279             if(psEventChain->nextEventChain[iEvent][iNext] != -1)
280             {
281                 psEventChain->preEventCountSave[psEventChain->nextEventChain[iEvent][iNext]] ++;
282                 psEventChain->nextEventCount[iEvent] ++;
283             }
284         }
285     }
286
287     /*
288     for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent ++)
289     {
290         printf("\nEvent %d preEvent %d",iEvent,psEventChain->preEventCount[iEvent]);
291     }
292     */
293     return 0;
294 }
295
296 int32_t event_chain_reset(EventChainDescStruct *psEventChain)
297 {
298     memset((void *)&psEventChain->preEventStat, 0 , sizeof(psEventChain->preEventStat));
299
300     /*For each event, find all preceding dependent event */
301     int32_t iEvent = 0;
302
303     /* Set the external event Wakeup Dependencies (apart from Task Dependency) */
304     for(iEvent = 0; iEvent < MAX_TASK_NUM_G_NB; iEvent++)
305     {
306         psEventChain->preEventCount[iEvent] = psEventChain->preEventCountSave[iEvent];
307     }
308     return 0;
309 }
310
311 static void set_event_info(EventCtrlStruct *pEvenCtrl, int32_t eventId,
312      int32_t iSplit, EventSendStruct *psEventSend)
313 {
314     int32_t nCell = pEvenCtrl->nCellIdx;
315     int32_t nSlot = pEvenCtrl->nSlotIdx;
316     int32_t nCtx = nSlot % MAX_TEST_CTX;
317     int32_t nQueueCtxNum = nSlot % gQueueCtxNum;
318     EventStruct * pEvent = &gEvent[nCell][nCtx][eventId][iSplit];
319     pEvent->pEventFunc = testEventTable[eventId].pEventFunc;
320     pEvent->pEventArgs = pEvenCtrl;
321     pEvent->nEventId = eventId;
322     pEvent->nEventSentTime = ebbu_pool_tick();
323     pEvent->nEventSentTimeMlog = MLogTick();
324     pEvent->nEventAliveTime = 10000000;
325     pEvent->nCoreAffinityMask = _mm256_set_epi64x(0,0,testEventTable[eventId].nCoreMask1,testEventTable[eventId].nCoreMask0);
326     pEvent->nEventStatus = EBBUPOOL_EVENT_VALID;
327
328     psEventSend->eDisposFlag = EBBUPOOL_NON_DISPOSABLE;
329
330     psEventSend->ePrioCat = eventSendDic[testEventTable[eventId].nEventPrio];
331     psEventSend->nQueueCtx = 0;
332     if(gQueueCtxNum > 1)
333         psEventSend->nQueueCtx = nQueueCtxNum;
334
335     psEventSend->psEventStruct[0] = pEvent;
336     psEventSend->nEventNum = 1;
337
338     psEventSend->nPreFlag = testEventTable[eventId].nPrefetchFlag;
339
340     return;
341 }
342
343 static void set_split_event_info(EventCtrlStruct *pEvenCtrl, int32_t eventId,
344      int32_t nSplit, EventSendStruct *psEventSend)
345 {
346     int32_t nCell = pEvenCtrl[0].nCellIdx;
347     int32_t nSlot = pEvenCtrl[0].nSlotIdx;
348     int32_t nCtx = nSlot % MAX_TEST_CTX;
349     int32_t nQueueCtxNum = nSlot % gQueueCtxNum;
350     int32_t iSplit = 0;
351     for(; iSplit < nSplit; iSplit ++)
352     {
353         EventStruct *pEvent = &gEvent[nCell][nCtx][eventId][iSplit];
354         pEvent->pEventFunc = testEventTable[eventId].pEventFunc;
355         pEvent->pEventArgs = &pEvenCtrl[iSplit];
356         pEvent->nEventId = eventId;
357         pEvent->nEventSentTime = ebbu_pool_tick();
358         pEvent->nEventSentTimeMlog = MLogTick();
359         pEvent->nEventAliveTime = 10000000;
360         pEvent->nCoreAffinityMask = _mm256_set_epi64x(0,0,testEventTable[eventId].nCoreMask1,testEventTable[eventId].nCoreMask0);
361         pEvent->nEventStatus = EBBUPOOL_EVENT_VALID;
362         psEventSend->psEventStruct[iSplit] = pEvent;
363     }
364     pEvenCtrl[0].tSendTime = MLogTick();
365     psEventSend->eDisposFlag = EBBUPOOL_DISPOSABLE;
366     psEventSend->ePrioCat = eventSendDic[testEventTable[eventId].nEventPrio];
367     psEventSend->nQueueCtx = 0;
368     if(gQueueCtxNum > 1)
369         psEventSend->nQueueCtx = nQueueCtxNum;
370     psEventSend->nEventNum = nSplit;
371     psEventSend->nPreFlag = testEventTable[eventId].nPrefetchFlag;
372
373     return;
374 }
375
376 int32_t next_event_unlock(void *pCookies)
377 {
378     EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
379     eBbuPoolHandler pHandler = (eBbuPoolHandler)pEvenCtrl->pHandler;
380     int32_t nCell = pEvenCtrl->nCellIdx;
381     int32_t nSlot = pEvenCtrl->nSlotIdx;
382     int32_t nCtx = nSlot % MAX_TEST_CTX;
383     int32_t eventId = pEvenCtrl->nEventId;
384     EventChainDescStruct * pEventChain = &gEventChain[nCell][nCtx];
385
386     if(eventId == DL_POST||eventId == UL_POST)
387         ebbu_pool_queue_ctx_add(pHandler, nCtx);
388
389     /*Set and check the status of all next event */
390     /*Then decide whether to send next event or not */
391     int32_t iNext = 0;
392     int32_t nextEventId = 0;
393
394     for(iNext = 0; iNext < pEventChain->nextEventCount[eventId]; iNext++)
395     {
396         nextEventId = pEventChain->nextEventChain[eventId][iNext];
397         /*printf("\nnSlot %d event %d nextEventCount %d inext %d next %d next_pre_count %d next_pre_stat %d",
398             nSlotIdx, nTaskId, pEventChain->nextEventCount[nTaskId], iNext, nextEventId,
399             pEventChain->preEventCount[nextEventId], pEventChain->preEventStat[nextEventId]);
400         */
401
402         if(__atomic_add_fetch(&pEventChain->preEventStat[nextEventId], 1, __ATOMIC_ACQ_REL) ==
403            __atomic_load_n(&pEventChain->preEventCount[nextEventId], __ATOMIC_ACQUIRE))
404         {
405             test_func_gen(pHandler, nCell, nSlot, nextEventId);
406         }
407     }
408
409     return 0;
410 }
411
412 int32_t test_func_gen(eBbuPoolHandler pHandler, int32_t nCell, int32_t nSlot, int32_t eventId)
413 {
414     int j;
415     if(eventId >= MAX_TASK_NUM_G_NB || nCell >= EBBU_POOL_MAX_TEST_CELL)
416     {
417         printf("\nError! Wrong eventId %d max %d nCell %d",eventId, MAX_TASK_NUM_G_NB, nCell);
418         exit(-1);
419     }
420
421     int32_t nCtx = nSlot % MAX_TEST_CTX;
422     int32_t iNext, iNextEventId, nSplitIdx;
423     EventChainDescStruct * pEventChain = &gEventChain[nCell][nCtx];
424     EventSendStruct sEventSend;
425     EventCtrlStruct *pEventCtrl;
426     TaskPreGen sPara;
427     int32_t nSplit = 1, ret = 0;
428
429     uint64_t t1 = MLogTick();
430
431     if(DL_CONFIG == eventId)
432         dl_start_mlog[nCell][nCtx] = t1;
433     else if(UL_CONFIG == eventId)
434         ul_start_mlog[nCell][nCtx] = t1;
435
436     // Klocwork check
437     for (j = 0; j < MAX_TEST_SPLIT_NUM; j++)
438         sPara.pTaskExePara[j] = (void *)&gsSampleSplit[nCell%EBBU_POOL_MAX_TEST_CELL][nSlot%MAX_TEST_CTX][j];
439
440     if (testEventTable[eventId].pPreEventFunc)
441     {
442         /* Run Pre Event and Find out how many split */
443         sPara.nTaskNum = 1;
444         testEventTable[eventId].pPreEventFunc(nSlot, nCell, &sPara);
445         nSplit = sPara.nTaskNum;
446         if(nSplit > 1)
447         {
448             /* Add the split to all the Nex Next Dependencies */
449             for(iNext = 0; iNext < pEventChain->nextEventCount[eventId]; iNext++)
450             {
451                 iNextEventId = pEventChain->nextEventChain[eventId][iNext];
452                 __atomic_add_fetch(&pEventChain->preEventCount[iNextEventId], nSplit - 1, __ATOMIC_ACQ_REL);
453             }
454         }
455     }
456
457     //send the splitted events together, save ebbupool internal overhead
458     for(nSplitIdx = 0; nSplitIdx < nSplit; nSplitIdx++)
459     {
460         pEventCtrl = &gEventCtrl[nCell][nCtx][eventId][nSplitIdx];
461         pEventCtrl->nEventId = eventId;
462         pEventCtrl->nSplitIdx = nSplitIdx;
463         pEventCtrl->nCellIdx = nCell;
464         pEventCtrl->nSlotIdx = nSlot;
465         pEventCtrl->pTaskPara = sPara.pTaskExePara[nSplitIdx];
466         pEventCtrl->pHandler = pHandler;
467     }
468
469     set_split_event_info(&gEventCtrl[nCell][nCtx][eventId][0], eventId, nSplit, &sEventSend);
470     ret = ebbu_pool_send_event(pHandler, sEventSend);
471
472     if(0 != ret)
473         printf("\nEvent %d gen failed!",eventId);
474
475     MLogTask(MAX_TASK_NUM_G_NB * nCell + eventId + 2000, t1, MLogTick());
476
477     return 0;
478 }
479 void test_pre_func_A(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara)
480 {
481     // uint64_t t1 = MLogTick();
482     //printf("\nfunc pre A event %d",pEvenCtrl->nEventId);
483     // int32_t ret = 0;
484     //do some traffic
485     //ret = simulate_traffic(pCookies, 1000);
486
487     pPara->nTaskNum = nSplitNumCell[nCellIdx];
488     int32_t iSplit = 0;
489     for(iSplit = 0; iSplit < pPara->nTaskNum; iSplit ++)
490     {
491         pPara->pTaskExePara[iSplit] = (void *)&gsSampleSplit[nCellIdx%EBBU_POOL_MAX_TEST_CELL][nSubframe%MAX_TEST_CTX][iSplit];
492     }
493     return;
494     //MLogTask(MAX_TASK_NUM_G_NB * pInputPara->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
495 }
496
497
498 void test_pre_func_B(uint32_t nSubframe, uint16_t nCellIdx, TaskPreGen *pPara)
499 {
500     // uint64_t t1 = MLogTick();
501     //printf("\nfunc pre A event %d",pEvenCtrl->nEventId);
502     // int32_t ret = 0;
503
504     //do some traffic
505     //ret = simulate_traffic(pCookies, 1000);
506     int32_t iSplit = 0;
507     for(iSplit = 0; iSplit < pPara->nTaskNum; iSplit ++)
508     {
509         pPara->pTaskExePara[iSplit] = (void *)&gsSampleSplit[nCellIdx%EBBU_POOL_MAX_TEST_CELL][nSubframe%MAX_TEST_CTX][iSplit];
510     }
511     return;
512
513     pPara->nTaskNum = nSplitNumCell[nCellIdx];
514
515     //MLogTask(MAX_TASK_NUM_G_NB * pInputPara->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
516 }
517
518 int32_t test_func_A(void *pCookies)
519 {
520     EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
521
522     uint64_t t1 = MLogTick();
523 #if 0
524     //printf("\nfunc A event %d",pEvenCtrl->nEventId);
525     if(DL_CONFIG == pEvenCtrl->nEventId)
526     {
527         app_bbu_pool_task_dl_config(pCookies);
528         MLogTask(pEvenCtrl->nCellIdx + 4000, pEvenCtrl->tSendTime, t1);
529     }
530
531     if(UL_CONFIG == pEvenCtrl->nEventId)
532     {
533         app_bbu_pool_task_ul_config(pCookies);
534         MLogTask(pEvenCtrl->nCellIdx + 5000, pEvenCtrl->tSendTime, t1);
535     }
536 #endif
537     // int32_t ret = 0;
538
539     //do some traffic
540     //ret = simulate_traffic(pCookies, 3000);
541     //usleep(10);
542
543     //unlock the next task
544     next_event_unlock(pCookies);
545
546     MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
547     //printf("\nfunc a latency %llu",MLogTick()-t1);
548
549     return 0;
550
551 }
552
553 int32_t test_func_B(void *pCookies)
554 {
555     EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
556
557     uint64_t t1 = MLogTick();
558     //printf("\nfunc B event %d",pEvenCtrl->nEventId);
559     // int32_t ret = 0;
560
561     //do some traffic
562     //ret = simulate_traffic(pCookies, 5000);
563     //usleep(10);
564
565     //unlock the next task
566     next_event_unlock(pCookies);
567
568     MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
569
570     return 0;
571 }
572
573 int32_t test_func_C(void *pCookies)
574 {
575     EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
576
577     uint64_t t1 = MLogTick();
578     //printf("\nfunc B event %d",pEvenCtrl->nEventId);
579     int32_t ret = 0;
580
581     //do some traffic
582
583     MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + pEvenCtrl->nEventId, t1, MLogTick());
584
585     if(pEvenCtrl->nEventId == DL_POST || pEvenCtrl->nEventId == UL_POST)
586     {
587         if(__atomic_sub_fetch(&dl_ul_count, 1, __ATOMIC_ACQ_REL) == 0)
588         {
589             MLogTask(MAX_TASK_NUM_G_NB * pEvenCtrl->nCellIdx + 6000, ttistart, MLogTick());
590         }
591     }
592
593     MLogTask(77777, t1, MLogTick());
594     return ret;
595 }
596
597 #if 0
598 int32_t simulate_traffic(void *pCookies, int32_t testCount)
599 {
600     //printf("\ndo traffic!");
601     EventCtrlStruct *pEvenCtrl = (EventCtrlStruct *)pCookies;
602     __m256 sigma2 = _mm256_set1_ps(testCount/1234.5);
603     __m256 ftemp1, ftemp2;
604
605     int32_t m = testCount;
606     m = m/2;
607
608     while(m > 0)
609     {
610         ftemp1 = _mm256_rcp_ps(sigma2);
611         ftemp2 = _mm256_sub_ps(_mm256_set1_ps(0), sigma2);
612         ftemp2 = _mm256_fmadd_ps(ftemp1, sigma2, ftemp2);
613         sigma2 = _mm256_rcp_ps(ftemp2);
614         m --;
615     }
616
617     int32_t nfloat = 8; //256bits has eight 32bits
618     float *dummy = (float *)&sigma2;
619     *pEvenCtrl->dummy0 = 0;
620     for(m = 0; m < nfloat; m++)
621         *pEvenCtrl->dummy0 += dummy[m];
622
623     return 0;
624 }
625 #endif