1 /******************************************************************************
3 * Copyright (c) 2019 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 *******************************************************************************/
21 #include <sys/syscall.h>
36 #include "../../lib/src/mlog_lnx_xRAN.h"
42 #include "xran_fh_lls_cu.h"
43 //#include "xran_pkt.h"
44 //#include "xran_up_api.h"
45 #include "xran_cp_api.h"
46 #include "xran_sync_api.h"
47 #include "xran_mlog_task_id.h"
49 #define SW_FPGA_TOTAL_BUFFER_LEN 4*1024*1024*1024
50 #define SW_FPGA_SEGMENT_BUFFER_LEN 1*1024*1024*1024
51 #define SW_FPGA_FH_TOTAL_BUFFER_LEN 1*1024*1024*1024
52 #define FPGA_TO_SW_PRACH_RX_BUFFER_LEN (8192)
54 #define NSEC_PER_SEC 1000000000
56 #define MAX_PKT_BURST (448+4) // 4x14x8
57 #define N_MAX_BUFFER_SEGMENT MAX_PKT_BURST
59 #define MAIN_PRIORITY 98
60 #define NUM_OF_SUBFRAME_PER_FRAME (10)
64 uint64_t tick_per_usec;
65 static volatile uint64_t timer_last_irq_tick = 0;
66 static uint64_t tsc_resolution_hz = 0;
68 RuntimeConfig startupConfiguration = {0};
71 uint32_t nFpgaToSW_FTH_RxBufferLen;
72 uint32_t nFpgaToSW_PRACH_RxBufferLen;
73 uint32_t nSW_ToFpga_FTH_TxBufferLen;
75 static XRANFHINIT xranInit;
76 void * xranHandle = NULL;
78 XRANFHCONFIG xranConf;
79 PXRANFHCONFIG pXranConf = NULL;
83 uint32_t phaseFlag :1;
85 uint32_t SULFreShift :1;
90 typedef struct XranLibConfig
92 uint32_t nDriverCoreId;
93 uint32_t nTimingAdvance;
95 uint32_t nFhBufIntFlag;
97 uint32_t nNrOfSlotInSf;
98 uint32_t nNrofSfInFrame;
99 void * pFthInstanceHandles;
100 }XranLibConfigStruct;
105 MAX_SW_XRAN_INTERFACE_NUM
106 }SWXRANInterfaceTypeEnum;
109 * manage one cell's all Ethernet frames for one DL or UL LTE subframe
112 /* -1-this subframe is not used in current frame format
113 0-this subframe can be transmitted, i.e., data is ready
114 1-this subframe is waiting transmission, i.e., data is not ready
115 10 - DL transmission missing deadline. When FE needs this subframe data but bValid is still 1,
118 int32_t bValid ; // when UL rx, it is subframe index.
120 int32_t nSegGenerated; // how many date segment are generated by DL LTE processing or received from FE
121 // -1 means that DL packet to be transmitted is not ready in BS
122 int32_t nSegTransferred; // number of data segments has been transmitted or received
123 struct rte_mbuf *pData[N_MAX_BUFFER_SEGMENT]; // point to DPDK allocated memory pool
124 XRANBufferListStruct sBufferList;
125 } BbuIoBufCtrlStruct;
130 uint8_t nDriverCoreId;
133 struct rte_mempool *bbuio_buf_pool;
136 BbuIoBufCtrlStruct sFrontHaulTxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
137 BbuIoBufCtrlStruct sFrontHaulRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
138 BbuIoBufCtrlStruct sFHPrachRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
141 XRANFlatBufferStruct sFrontHaulTxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
142 XRANFlatBufferStruct sFrontHaulRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
143 XRANFlatBufferStruct sFHPrachRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
145 void* nInstanceHandle[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; // instance per sector
146 uint32_t nBufPoolIndex[XRAN_MAX_SECTOR_NR][MAX_SW_XRAN_INTERFACE_NUM]; // every api owns unique buffer pool
147 uint16_t nInstanceNum;
149 /*subframe type for this TTI:
150 0: DL control + DL data
151 1: DL control + DL data + UL control
152 2: DL control + UL data
153 3: DL control + UL data + UL control
155 uint8_t nSubframeType;
157 uint64_t nTscTiming[XRAN_N_FE_BUF_LEN]; // records the TSC when a timing packet is received.
160 static BbuXranIoIfStruct gsXranIoIf;
161 static XranLibConfigStruct *gpXranLibConfig = NULL;
163 #define CPU_HZ tick_per_usec //us
165 /* Application User space functions */
166 void xran_fh_rx_callback(void *pCallbackTag, int32_t status);
167 void xran_fh_rx_prach_callback(void *pCallbackTag, int32_t status);
169 static BbuXranIoIfStruct *xran_get_ctx(void)
174 static void print_menu()
176 puts("+---------------------------------------+");
177 puts("| Press 1 to start 5G NR XRAN traffic |");
178 puts("| Press 2 reserved for future use |");
179 puts("| Press 3 to quit |");
180 puts("+---------------------------------------+");
183 void xran_fh_rx_callback(void *pCallbackTag, XranStatusInt32 status)
185 uint64_t t1 = MLogTick();
186 uint32_t mlogVar[10];
187 uint32_t mlogVarCnt = 0;
189 mlogVar[mlogVarCnt++] = 0xCCCCCCCC;
190 mlogVar[mlogVarCnt++] = status >> 16; /* tti */
191 mlogVar[mlogVarCnt++] = status & 0xFF; /* sym */
192 MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
195 MLogTask(PID_GNB_SYM_CB, t1, MLogTick());
199 void xran_fh_rx_prach_callback(void *pCallbackTag, XranStatusInt32 status)
201 uint64_t t1 = MLogTick();
203 MLogTask(PID_GNB_PRACH_CB, t1, MLogTick());
206 //-------------------------------------------------------------------------------------------
207 /** @ingroup group_nbiot_source_auxlib_timer
214 * This function reads the rtdsc clock and returns the current value in there.
217 //-------------------------------------------------------------------------------------------
218 unsigned long timer_get_ticks(void)
223 unsigned long tsc_64;
231 __asm volatile("rdtsc" :
235 ret = ((unsigned long)tsc.tsc_64);
239 //-------------------------------------------------------------------------------------------
240 /** @ingroup group_lte_source_auxlib_timer
244 * @return 0 if SUCCESS
247 * This function gets the clock speed of the core and figures out number of ticks per usec.
248 * It is used by l1app and testmac applications to initialize the mlog utility
251 //-------------------------------------------------------------------------------------------
252 int timer_set_tsc_freq_from_clock(void)
254 #define NS_PER_SEC 1E9
255 struct timespec sleeptime = {.tv_nsec = 5E8 }; /* 1/2 second */
256 struct timespec t_start, t_end;
257 uint64_t tsc_resolution_hz = 0;
259 if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0)
261 unsigned long ns, end, start = timer_get_ticks();
262 nanosleep(&sleeptime,NULL);
263 clock_gettime(CLOCK_MONOTONIC_RAW, &t_end);
264 end = timer_get_ticks();
265 ns = ((t_end.tv_sec - t_start.tv_sec) * NS_PER_SEC);
266 ns += (t_end.tv_nsec - t_start.tv_nsec);
268 double secs = (double)ns/NS_PER_SEC;
269 tsc_resolution_hz = (unsigned long)((end - start)/secs);
271 tick_per_usec = (tsc_resolution_hz / 1000000);
272 printf("System clock (rdtsc) resolution %lu [Hz]\n", tsc_resolution_hz);
273 printf("Ticks per us %lu\n", tick_per_usec);
280 int physide_dl_tti_call_back(void * param)
282 uint64_t t1 = MLogTick();
284 MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
288 int physide_ul_half_slot_call_back(void * param)
290 uint64_t t1 = MLogTick();
292 MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
296 int physide_ul_full_slot_call_back(void * param)
298 uint64_t t1 = MLogTick();
300 MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
304 int32_t init_xran(void)
306 BbuXranIoIfStruct *psBbuIo = xran_get_ctx();
307 XranStatusInt32 status;
308 int32_t nSectorIndex[XRAN_MAX_SECTOR_NR];
317 SWXRANInterfaceTypeEnum eInterfaceType;
319 XranLibConfigStruct *ptrLibConfig;
321 XRANBufferListStruct *pFthTxBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
322 XRANBufferListStruct *pFthRxBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
323 XRANBufferListStruct *pFthRxRachBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
325 FPGAPhaseCompCfg *pPhaseCompDl = NULL;
326 FPGAPhaseCompCfg *pPhaseCompUl = NULL;
327 uint32_t nPhaseCompDl,nPhaseCompUl;
331 printf("init_xran: nFpgaProbe[%d] nSecNum[%d] nUENum[%d] nTimeAdvance[%d] nEthPorts[%d] nPhaseCompFlag[%d]\n",
332 psFPGAInitPara->nFpgaProbe, psFPGAInitPara->nSecNum, psFPGAInitPara->nUENum, psFPGAInitPara->nTimeAdvance, psFPGAInitPara->nEthPorts, psFPGAInitPara->nPhaseCompFlag);
333 for (i = 0; i < nSectorNum; i ++)
335 printf(" [%d]: nDlArfcn[%d] nUlArfcn[%d]\n", i, psFPGAInitPara->nDlArfcn[i], psFPGAInitPara->nUlArfcn[i]);
338 for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++)
340 nSectorIndex[nSectorNum] = nSectorNum;
343 nSectorNum = numCCPorts;
344 printf ("XRAN front haul xran_mm_init \n");
345 status = xran_mm_init (xranHandle, (uint64_t) SW_FPGA_FH_TOTAL_BUFFER_LEN, SW_FPGA_SEGMENT_BUFFER_LEN);
346 if (status != XRAN_STATUS_SUCCESS)
348 printf ("Failed at XRAN front haul xran_mm_init \n");
352 psBbuIo->nInstanceNum = numCCPorts;
354 for (k = 0; k < XRAN_PORTS_NUM; k++) {
355 status = xran_sector_get_instances (xranHandle, psBbuIo->nInstanceNum,psBbuIo->nInstanceHandle[k]);
356 if (status != XRAN_STATUS_SUCCESS)
358 printf ("get sector instance failed %d for XRAN nInstanceNum %d\n",k, psBbuIo->nInstanceNum);
363 printf("Sucess xran_mm_init \n");
364 gpXranLibConfig = (XranLibConfigStruct*)malloc(sizeof(XranLibConfigStruct));
365 ptrLibConfig = gpXranLibConfig;
369 ptrLibConfig->nDriverCoreId = psBbuIo->nDriverCoreId;
370 ptrLibConfig->pFecInstanceHandles = &(psBbuIo->nInstanceHandle[FPGA_FEC][0]);
371 ptrLibConfig->pFthInstanceHandles = &(psBbuIo->nInstanceHandle[FPGA_FRONTHAUL][0]);
372 ptrLibConfig->nTimingAdvance = psFPGAInitPara->nTimeAdvance;
373 ptrLibConfig->nFhConfig = psFPGAInitPara->nEthPorts;
374 ptrLibConfig->nFhBufIntFlag = 0; //need init fronthaul buffer, then set to 1.
375 ptrLibConfig->nNrofSfInFrame = NUM_OF_SUBFRAME_PER_FRAME;
376 ptrLibConfig->nNrOfSlotInSf = pConfigParams->nNumOfSlotPerSubframe;
377 if (pConfigParams->nNumerology < 3)
379 ptrLibConfig->nSectorNum = psFPGAInitPara->nSecNum;
385 printf ("could not allocate ptrLibConfig in init_xran\n");
389 printf("nSectorNum %d\n", nSectorNum);
392 for(i = 0; i<nSectorNum; i++)
394 eInterfaceType = XRANFTHTX_OUT;
395 status = xran_bm_init(xranHandle, &psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],
396 XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, nSW_ToFpga_FTH_TxBufferLen);
397 if(XRAN_STATUS_SUCCESS != status)
399 printf("Failed at xran_bm_init , status %d\n", status);
400 iAssert(status == XRAN_STATUS_SUCCESS);
402 for(j = 0; j < XRAN_N_FE_BUF_LEN; j++)
404 for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
405 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].bValid = 0;
406 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
407 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
408 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
409 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;
410 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFrontHaulTxBuffers[j][i][z][0];
412 for(k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; k++)
414 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = nSW_ToFpga_FTH_TxBufferLen; // 14 symbols 3200bytes/symbol
415 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1;
416 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0;
417 status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr);
418 if(XRAN_STATUS_SUCCESS != status)
420 printf("Failed at xran_bm_allocate_buffer , status %d\n",status);
421 iAssert(status == XRAN_STATUS_SUCCESS);
423 psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr;
426 u32dptr = (uint32_t*)(ptr);
427 uint8_t *ptr_temp = (uint8_t *)ptr;
428 memset(u32dptr, 0xCC, nSW_ToFpga_FTH_TxBufferLen);
429 ptr_temp[0] = j; // TTI
430 ptr_temp[1] = i; // Sec
431 ptr_temp[2] = z; // Ant
432 ptr_temp[3] = k; // sym
439 for(i = 0; i<nSectorNum; i++)
441 eInterfaceType = XRANFTHRX_IN;
442 status = xran_bm_init(xranHandle, &psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType], XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, nSW_ToFpga_FTH_TxBufferLen);
443 if(XRAN_STATUS_SUCCESS != status)
445 printf("Failed at xran_bm_init, status %d\n", status);
446 iAssert(status == XRAN_STATUS_SUCCESS);
449 for(j = 0;j < XRAN_N_FE_BUF_LEN; j++)
451 for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
452 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].bValid = 0;
453 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
454 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
455 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
456 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;
457 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFrontHaulRxBuffers[j][i][z][0];
458 for(k = 0; k< XRAN_NUM_OF_SYMBOL_PER_SLOT; k++)
460 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = nFpgaToSW_FTH_RxBufferLen; // 1 symbols 3200bytes
461 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1;
462 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0;
463 status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr);
464 if(XRAN_STATUS_SUCCESS != status)
466 printf("Failed at cpa_bb_bm_allocate_buffer , status %d\n",status);
467 iAssert(status == XRAN_STATUS_SUCCESS);
469 psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr;
471 u32dptr = (uint32_t*)(ptr);
472 uint8_t *ptr_temp = (uint8_t *)ptr;
473 memset(u32dptr, 0xCC, nFpgaToSW_FTH_RxBufferLen);
474 ptr_temp[0] = j; // TTI
475 ptr_temp[1] = i; // Sec
476 ptr_temp[2] = z; // Ant
477 ptr_temp[3] = k; // sym
484 // add prach rx buffer
485 for(i = 0; i<nSectorNum; i++)
487 eInterfaceType = XRANFTHRACH_IN;
488 status =xran_bm_init(xranHandle,&psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, FPGA_TO_SW_PRACH_RX_BUFFER_LEN);
489 if(XRAN_STATUS_SUCCESS != status)
491 printf("Failed at xran_bm_init, status %d\n", status);
492 iAssert(status == XRAN_STATUS_SUCCESS);
494 for(j = 0;j < XRAN_N_FE_BUF_LEN; j++)
496 for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
497 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].bValid = 0;
498 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
499 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
500 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
501 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANTENNA_NR; // ant number.
502 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFHPrachRxBuffers[j][i][z][0];
503 //for(k = 0; k< XRAN_NUM_OF_SYMBOL_PER_SLOT; k++)
504 k = 0; // one PRACH buffer per antenna per slot
506 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = FPGA_TO_SW_PRACH_RX_BUFFER_LEN;
507 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1;
508 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0;
509 status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr);
510 if(XRAN_STATUS_SUCCESS != status)
512 printf("Failed at xran_bm_allocate_buffer, status %d\n",status);
513 iAssert(status == XRAN_STATUS_SUCCESS);
515 psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr;
517 u32dptr = (uint32_t*)(ptr);
518 memset(u32dptr, 0xCC, FPGA_TO_SW_PRACH_RX_BUFFER_LEN);
525 for(i=0; i<nSectorNum; i++)
527 for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
529 for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
530 pFthTxBuffer[i][z][j] = &(psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList);
531 pFthRxBuffer[i][z][j] = &(psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList);
532 pFthRxRachBuffer[i][z][j] = &(psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList);
537 if(NULL != psBbuIo->nInstanceHandle[0])
539 for (i = 0; i<nSectorNum; i++)
541 xran_5g_fronthault_config (psBbuIo->nInstanceHandle[0][i],
544 xran_fh_rx_callback, &pFthRxBuffer[i][0]);
547 // add prach callback here
548 for (i = 0; i<nSectorNum; i++)
550 xran_5g_prach_req(psBbuIo->nInstanceHandle[0][i], pFthRxRachBuffer[i],
551 xran_fh_rx_prach_callback,&pFthRxRachBuffer[i][0]);
553 ptrLibConfig->nFhBufIntFlag = 1;
556 /*config phase compensation*/
557 /* TODO: add phase compensation handling */
558 for(i=0; i<nSectorNum; i++)
560 pPhaseCompDl = (FPGAPhaseCompCfg *)(&nPhaseCompDl);
561 pPhaseCompDl->NRARFCN = 0;//psFPGAInitPara->nDlArfcn[i];
562 pPhaseCompDl->phaseFlag = 0;//psFPGAInitPara->nPhaseCompFlag;
563 pPhaseCompDl->SULFlag = 0;
564 pPhaseCompDl->SULFreShift = 0;
565 pPhaseCompDl->rsv = 0;
567 pPhaseCompUl = (FPGAPhaseCompCfg *)(&nPhaseCompUl);
568 pPhaseCompUl->NRARFCN = 0;//psFPGAInitPara->nUlArfcn[i];
569 pPhaseCompUl->phaseFlag = 0;// psFPGAInitPara->nPhaseCompFlag;
570 pPhaseCompUl->SULFlag = 0;
571 pPhaseCompUl->SULFreShift = 0;
572 pPhaseCompUl->rsv = 0;
574 xran_5g_pre_compenstor_cfg(psBbuIo->nInstanceHandle[0][i],nPhaseCompDl,nPhaseCompUl,i);
576 printf("@@@ NB cell %d DL NR-ARFCN %d,DL phase comp flag %d UL NR-ARFCN %d,UL phase comp flag %d \n",
577 i,pPhaseCompDl->NRARFCN,pPhaseCompDl->phaseFlag,
578 pPhaseCompUl->NRARFCN,pPhaseCompUl->phaseFlag);
583 int init_xran_iq_content(void)
585 BbuXranIoIfStruct *psBbuIo = xran_get_ctx();
586 XranStatusInt32 status;
587 int32_t nSectorIndex[XRAN_MAX_SECTOR_NR];
589 int32_t cc_id, ant_id, sym_id, tti;
592 uint8_t frame_id = 0;
593 uint8_t subframe_id = 0;
604 for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++)
606 nSectorIndex[nSectorNum] = nSectorNum;
608 nSectorNum = numCCPorts;
609 printf ("init_xran_iq_content\n");
612 for(cc_id = 0; cc_id <nSectorNum; cc_id++)
614 for(tti = 0; tti < XRAN_N_FE_BUF_LEN; tti ++) {
615 for(ant_id = 0; ant_id < XRAN_MAX_ANTENNA_NR; ant_id++){
616 for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
617 flowId = nSectorNum * ant_id + cc_id;
619 if(p_tx_play_buffer[flowId]){
620 /* (0-79 slots) 10ms of IQs */
621 pos = ((char*)p_tx_play_buffer[flowId]) + tx_play_buffer_position[flowId];
623 ptr = psBbuIo->sFrontHaulTxBbuIoBufCtrl[tti][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;
626 u32dptr = (uint32_t*)(ptr);
627 rte_memcpy(u32dptr, pos, PDSCH_PAYLOAD_SIZE);
628 #ifdef DEBUG_XRAN_BUFFERS
629 uint8_t *ptr_temp = (uint8_t *)ptr;
630 ptr_temp[0] = tti; // TTI
631 ptr_temp[1] = cc_id; // Sec
632 ptr_temp[2] = ant_id; // Ant
633 ptr_temp[3] = sym_id; // sym
636 printf("ptr ==NULL\n");
638 tx_play_buffer_position[flowId] += PDSCH_PAYLOAD_SIZE;
640 if(tx_play_buffer_position[flowId] >= tx_play_buffer_size[flowId])
641 tx_play_buffer_position[flowId] = 0;
643 //printf("flowId %d\n", flowId);
656 XranStatusInt32 status = 0;
657 SWXRANInterfaceTypeEnum eInterfaceType;
659 free(gpXranLibConfig);
660 gpXranLibConfig = NULL;
662 status += xran_mm_destroy(xranHandle)*2;
664 if(XRAN_STATUS_SUCCESS != status)
666 printf("Failed at xran_mm_destroy, status %d\n",status);
667 iAssert(status == XRAN_STATUS_SUCCESS);
671 int32_t get_xran_sfidx(uint8_t nNrOfSlotInSf)
675 uint32_t nSubframeIdx;
679 uint32_t nXranTime = xran_get_slot_idx(&nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond);
680 nSfIdx = nFrameIdx*NUM_OF_SUBFRAME_PER_FRAME*nNrOfSlotInSf
681 + nSubframeIdx*nNrOfSlotInSf
684 printf("\nxranTime is %d, return is %d, radio frame is %d, subframe is %d slot is %d tsc is %llu us",
696 int get_xran_iq_content(void)
698 BbuXranIoIfStruct *psBbuIo = xran_get_ctx();
699 XranStatusInt32 status;
700 int32_t nSectorIndex[XRAN_MAX_SECTOR_NR];
702 int32_t cc_id, ant_id, sym_id, tti;
705 uint8_t frame_id = 0;
706 uint8_t subframe_id = 0;
717 for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++)
719 nSectorIndex[nSectorNum] = nSectorNum;
721 nSectorNum = numCCPorts;
722 printf ("get_xran_iq_content\n");
725 for(cc_id = 0; cc_id <nSectorNum; cc_id++)
727 for(tti = 0; tti < XRAN_N_FE_BUF_LEN; tti++) {
728 for(ant_id = 0; ant_id < XRAN_MAX_ANTENNA_NR; ant_id++){
729 for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
730 flowId = nSectorNum * ant_id + cc_id;
731 if(p_rx_log_buffer[flowId]){
732 /* (0-79 slots) 10ms of IQs */
733 pos = ((char*)p_rx_log_buffer[flowId]) + rx_log_buffer_position[flowId];
734 ptr = psBbuIo->sFrontHaulRxBbuIoBufCtrl[tti][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;
736 u32dptr = (uint32_t*)(ptr);
737 rte_memcpy(pos, u32dptr, PDSCH_PAYLOAD_SIZE);
738 #ifdef DEBUG_XRAN_BUFFERS
743 printf("[flowId %d] %d %d %d %d\n", flowId, pos[0], pos[1], pos[2], pos[3]);
747 printf("ptr ==NULL\n");
749 rx_log_buffer_position[flowId] += PDSCH_PAYLOAD_SIZE;
751 if(rx_log_buffer_position[flowId] >= rx_log_buffer_size[flowId])
752 rx_log_buffer_position[flowId] = 0;
754 //printf("flowId %d\n", flowId);
764 int main(int argc, char *argv[])
772 errx(2, "Need two argument - the PCI address of the network port");
774 if (xran_is_synchronized() != 0)
775 printf("Machine is not synchronized using PTP!\n");
777 printf("Machine is synchronized using PTP!\n");
779 memset(&startupConfiguration, 0, sizeof(RuntimeConfig));
781 if (parseConfigFile(argv[1], &startupConfiguration) != 0) {
782 printf("Configuration file error.\n");
786 if(startupConfiguration.ant_file[0] == NULL){
787 printf("it looks like test vector for antennas were not provided\n");
791 numCCPorts = startupConfiguration.numCC;
792 num_eAxc = startupConfiguration.numAxc;
794 printf("numCCPorts %d num_eAxc%d\n", numCCPorts, num_eAxc);
797 nFpgaToSW_FTH_RxBufferLen = 3328; //3200 * 14;
798 nFpgaToSW_PRACH_RxBufferLen = 8192;
799 nSW_ToFpga_FTH_TxBufferLen = 3328; //3200; * 14;
801 memset(&xranInit, 0, sizeof(XRANFHINIT));
803 if(startupConfiguration.appMode == APP_LLS_CU) {
804 printf("set lls-CU\n");
805 xranInit.io_cfg.id = 0;//ID_LLS_CU;
806 xranInit.io_cfg.core = 4+1;
807 xranInit.io_cfg.system_core = 0;
808 xranInit.io_cfg.pkt_proc_core = 4+2;
809 xranInit.io_cfg.pkt_aux_core = 0; /* do not start*/
810 xranInit.io_cfg.timing_core = 4+3;
813 xranInit.io_cfg.id = 1; /* ID_LLS_CU;*/
814 xranInit.io_cfg.core = 1;
815 xranInit.io_cfg.system_core = 0;
816 xranInit.io_cfg.pkt_proc_core = 2;
817 xranInit.io_cfg.pkt_aux_core = 0; /* do not start */
818 xranInit.io_cfg.timing_core = 3;
821 xranInit.llscuId = 0; // for ecpriRtcid/ecpriPcid
822 xranInit.nSec = 1; // shall be one
824 xranInit.eAxCId_conf.mask_cuPortId = 0xf000;
825 xranInit.eAxCId_conf.mask_bandSectorId = 0x0f00;
826 xranInit.eAxCId_conf.mask_ccId = 0x00f0;
827 xranInit.eAxCId_conf.mask_ruPortId = 0x000f;
828 xranInit.eAxCId_conf.bit_cuPortId = 12;
829 xranInit.eAxCId_conf.bit_bandSectorId = 8;
830 xranInit.eAxCId_conf.bit_ccId = 4;
831 xranInit.eAxCId_conf.bit_ruPortId = 0;
833 xranInit.io_cfg.dpdk_dev[XRAN_UP_VF] = argv[2];
834 xranInit.io_cfg.dpdk_dev[XRAN_CP_VF] = argv[3];
835 xranInit.p_lls_cu_addr = (int8_t*)&startupConfiguration.lls_cu_addr;
836 xranInit.p_ru_addr = (int8_t*)&startupConfiguration.ru_addr;
837 xranInit.ttiPeriod = startupConfiguration.ttiPeriod;
839 xranInit.Tadv_cp_dl = startupConfiguration.Tadv_cp_dl;
840 xranInit.T2a_min_cp_dl = startupConfiguration.T2a_min_cp_dl;
841 xranInit.T2a_max_cp_dl = startupConfiguration.T2a_max_cp_dl;
842 xranInit.T2a_min_cp_ul = startupConfiguration.T2a_min_cp_ul;
843 xranInit.T2a_max_cp_ul = startupConfiguration.T2a_max_cp_ul;
844 xranInit.T2a_min_up = startupConfiguration.T2a_min_up;
845 xranInit.T2a_max_up = startupConfiguration.T2a_max_up;
846 xranInit.Ta3_min = startupConfiguration.Ta3_min;
847 xranInit.Ta3_max = startupConfiguration.Ta3_max;
848 xranInit.T1a_min_cp_dl = startupConfiguration.T1a_min_cp_dl;
849 xranInit.T1a_max_cp_dl = startupConfiguration.T1a_max_cp_dl;
850 xranInit.T1a_min_cp_ul = startupConfiguration.T1a_min_cp_ul;
851 xranInit.T1a_max_cp_ul = startupConfiguration.T1a_max_cp_ul;
852 xranInit.T1a_min_up = startupConfiguration.T1a_min_up;
853 xranInit.T1a_max_up = startupConfiguration.T1a_max_up;
854 xranInit.Ta4_min = startupConfiguration.Ta4_min;
855 xranInit.Ta4_max = startupConfiguration.Ta4_max;
857 xranInit.enableCP = startupConfiguration.enableCP;
858 xranInit.debugStop = startupConfiguration.debugStop;
860 xranInit.cp_vlan_tag = startupConfiguration.cp_vlan_tag;
861 xranInit.up_vlan_tag = startupConfiguration.up_vlan_tag;
864 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
866 p_tx_play_buffer[i] = (int16_t*)malloc(IQ_PLAYBACK_BUFFER_BYTES);
867 tx_play_buffer_size[i] = (int32_t)IQ_PLAYBACK_BUFFER_BYTES;
869 if (p_tx_play_buffer[i] == NULL)
872 tx_play_buffer_size[i] = sys_load_file_to_buff(startupConfiguration.ant_file[i],
873 "DL IFFT IN IQ Samples in binary format",
874 (uint8_t*) p_tx_play_buffer[i],
875 tx_play_buffer_size[i],
877 tx_play_buffer_position[i] = 0;
881 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
883 p_rx_log_buffer[i] = (int16_t*)malloc(IQ_PLAYBACK_BUFFER_BYTES);
884 rx_log_buffer_size[i] = (int32_t)IQ_PLAYBACK_BUFFER_BYTES;
886 if (p_rx_log_buffer[i] == NULL)
889 rx_log_buffer_position[i] = 0;
891 memset(p_rx_log_buffer[i], 0, rx_log_buffer_size[i]);
895 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
897 p_prach_log_buffer[i] = (int16_t*)malloc(PRACH_PLAYBACK_BUFFER_BYTES);
898 prach_log_buffer_size[i] = (int32_t)PRACH_PLAYBACK_BUFFER_BYTES;
900 if (p_prach_log_buffer[i] == NULL)
903 memset(p_prach_log_buffer[i], 0, prach_log_buffer_size[i]);
904 prach_log_buffer_position[i] = 0;
907 for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
909 sprintf(filename, "%s-play_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
910 sys_save_buf_to_file_txt(filename,
911 "DL IFFT IN IQ Samples in human readable format",
912 (uint8_t*) p_tx_play_buffer[i],
913 tx_play_buffer_size[i],
916 sprintf(filename, "%s-play_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
917 sys_save_buf_to_file(filename,
918 "DL IFFT IN IQ Samples in binary format",
919 (uint8_t*) p_tx_play_buffer[i],
920 tx_play_buffer_size[i]/sizeof(short),
923 if (startupConfiguration.iqswap == 1){
924 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
925 printf("TX: Swap I and Q to match RU format: [%d]\n",i);
929 signed short *ptr = (signed short *) p_tx_play_buffer[i];
932 for (j = 0; j < (int32_t)(tx_play_buffer_size[i]/sizeof(short)) ; j = j + 2){
942 for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
944 sprintf(filename, "swap_IQ_play_ant%d.txt", i);
945 sys_save_buf_to_file_txt(filename,
946 "DL IFFT IN IQ Samples in human readable format",
947 (uint8_t*) p_tx_play_buffer[i],
948 tx_play_buffer_size[i],
952 if (startupConfiguration.nebyteorderswap == 1){
953 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
954 printf("TX: Convert S16 I and S16 Q to network byte order for XRAN Ant: [%d]\n",i);
955 for (j = 0; j < tx_play_buffer_size[i]/sizeof(short); j++){
956 p_tx_play_buffer[i][j] = rte_cpu_to_be_16(p_tx_play_buffer[i][j]);
962 for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
964 sprintf(filename, "swap_be_play_ant%d.txt", i);
965 sys_save_buf_to_file_txt(filename,
966 "DL IFFT IN IQ Samples in human readable format",
967 (uint8_t*) p_tx_play_buffer[i],
968 tx_play_buffer_size[i],
973 timer_set_tsc_freq_from_clock();
974 xran_init(argc, argv, &xranInit, argv[0], &xranHandle);
975 if(xranHandle == NULL)
978 memset(&xranConf, 0, sizeof(XRANFHCONFIG));
979 pXranConf = &xranConf;
981 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
982 pXranConf->playback_conf.TxPlayBufAddr[i] = (unsigned long)p_tx_play_buffer[i];
983 pXranConf->playback_conf.TxPlayBufSize = tx_play_buffer_size[i];
986 pXranConf->sector_id = 0;
987 pXranConf->nCC = numCCPorts;
988 pXranConf->neAxc = num_eAxc;
990 pXranConf->frame_conf.nFrameDuplexType = 1; // TDD
991 pXranConf->frame_conf.nNumerology = startupConfiguration.mu_number; // 120KHz; same as XRAN_SCS_120KHz?
992 // pXranConf->frame_conf.nTddPeriod = ;
994 pXranConf->prach_conf.nPrachSubcSpacing = XRAN_SCS_120KHZ;
995 pXranConf->prach_conf.nPrachFreqStart = 0;
996 pXranConf->prach_conf.nPrachFilterIdx = XRAN_FILTERINDEX_PRACH_ABC;
997 pXranConf->prach_conf.nPrachConfIdx = 81;
998 pXranConf->prach_conf.nPrachFreqOffset = -792;
1000 pXranConf->ru_conf.iqWidth = 16;
1001 pXranConf->ru_conf.compMeth = XRAN_COMPMETHOD_NONE;
1002 pXranConf->ru_conf.fftSize = XRAN_FFTSIZE_2048;
1005 if(init_xran() != 0)
1008 xran_reg_physide_cb(xranHandle, physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI);
1009 xran_reg_physide_cb(xranHandle, physide_ul_half_slot_call_back, NULL, 10, XRAN_CB_HALF_SLOT_RX);
1010 xran_reg_physide_cb(xranHandle, physide_ul_full_slot_call_back, NULL, 10, XRAN_CB_FULL_SLOT_RX);
1012 init_xran_iq_content();
1014 xran_open(xranHandle, pXranConf);
1016 sprintf(filename, "mlog-%s", startupConfiguration.appMode == 0 ? "lls-cu" : "ru");
1018 MLogOpen(0, 32, 0, 0xFFFFFFFF, filename);
1019 puts("----------------------------------------");
1020 printf("MLog Info: virt=0x%016lx size=%d\n", MLogGetFileLocation(), MLogGetFileSize());
1021 puts("----------------------------------------");
1023 state = APP_RUNNING;
1029 //#ifdef Nightly_build
1033 if (NULL == fgets(input, 10, stdin)) {
1034 state = APP_STOPPED;
1037 sel_opt = atoi(input);
1041 xran_start(xranHandle);
1042 printf("Start XRAN traffic\n");
1047 xran_stop(xranHandle);
1048 printf("Stop XRAN traffic\n");
1049 state = APP_STOPPED;
1052 // send_cpmsg_dlul(XRAN_DIR_DL, flowId,
1053 // frame_id, subframe_id, slot_id,
1054 // 0, XRAN_SYMBOLPERSLOT_MAX, NUM_OF_PRB_IN_FULL_BAND,
1055 // beam_id, cc_id, ant_id,
1056 // cp_seq_id_num[XRAN_DIR_DL][ant_id]++);
1059 puts("Wrong option passed!");
1063 if (APP_STOPPED == state)
1067 get_xran_iq_content();
1069 puts("Closing l1 app... Ending all threads...");
1070 xran_close(xranHandle);
1074 puts("Dump IQs...");
1076 if (startupConfiguration.iqswap == 1){
1077 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
1078 printf("RX: Swap I and Q to match CPU format: [%d]\n",i);
1082 signed short *ptr = (signed short *) p_rx_log_buffer[i];
1085 for (j = 0; j < (int32_t)(rx_log_buffer_size[i]/sizeof(short)) ; j = j + 2){
1087 ptr[j] = ptr[j + 1];
1094 if (startupConfiguration.nebyteorderswap == 1){
1095 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
1096 printf("RX: Convert S16 I and S16 Q to cpu byte order from XRAN Ant: [%d]\n",i);
1097 for (j = 0; j < rx_log_buffer_size[i]/sizeof(short); j++){
1098 p_rx_log_buffer[i][j] = rte_be_to_cpu_16(p_rx_log_buffer[i][j]);
1103 for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
1105 sprintf(filename, "%s-rx_log_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
1106 sys_save_buf_to_file_txt(filename,
1107 "UL FFT OUT IQ Samples in human readable format",
1108 (uint8_t*) p_rx_log_buffer[i],
1109 rx_log_buffer_size[i],
1112 sprintf(filename, "%s-rx_log_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
1113 sys_save_buf_to_file(filename,
1114 "UL FFT OUT IQ Samples in binary format",
1115 (uint8_t*) p_rx_log_buffer[i],
1116 rx_log_buffer_size[i]/sizeof(short),
1120 if (startupConfiguration.iqswap == 1){
1121 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
1122 printf("PRACH: Swap I and Q to match CPU format: [%d]\n",i);
1126 signed short *ptr = (signed short *) p_prach_log_buffer[i];
1129 for (j = 0; j < (int32_t)(prach_log_buffer_size[i]/sizeof(short)) ; j = j + 2){
1131 ptr[j] = ptr[j + 1];
1138 if (startupConfiguration.nebyteorderswap == 1){
1139 for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
1140 printf("PRACH: Convert S16 I and S16 Q to cpu byte order from XRAN Ant: [%d]\n",i);
1141 for (j = 0; j < prach_log_buffer_size[i]/sizeof(short); j++){
1142 p_prach_log_buffer[i][j] = rte_be_to_cpu_16(p_prach_log_buffer[i][j]);
1147 for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
1149 sprintf(filename, "%s-prach_log_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
1150 sys_save_buf_to_file_txt(filename,
1151 "PRACH FFT OUT IQ Samples in human readable format",
1152 (uint8_t*) p_prach_log_buffer[i],
1153 prach_log_buffer_size[i],
1156 sprintf(filename, "%s-prach_log_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
1157 sys_save_buf_to_file(filename,
1158 "PRACH FFT OUT IQ Samples in binary format",
1159 (uint8_t*) p_prach_log_buffer[i],
1160 prach_log_buffer_size[i]/sizeof(short),