1 /******************************************************************************
3 * Copyright (c) 2020 Intel.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 *******************************************************************************/
21 #include <arpa/inet.h>
24 #include <immintrin.h>
27 #include "xran_fh_o_du.h"
29 #include "xran_pkt_up.h"
30 #include "xran_cp_api.h"
31 #include "xran_up_api.h"
33 #include "xran_mlog_lnx.h"
34 #include "app_profile_xran.h"
35 #include "xran_timer.h"
36 #include "xran_lib_mlog_tasks_id.h"
37 #include "xran_mlog_task_id.h"
39 #define XRAN_REPORT_FILE "xran_mlog_stats"
41 int32_t xran_init_mlog_stats(char *file, uint64_t nTscFreq);
42 int32_t xran_get_mlog_stats(char *, UsecaseConfig *, RuntimeConfig *[], struct xran_mlog_times *);
44 struct xran_mlog_times mlog_times = {0};
45 struct xran_mlog_stats tmp;
46 uint64_t xran_total_ticks = 0, xran_mlog_time;
47 uint64_t tWake, tWakePrev = 0;
49 extern UsecaseConfig* p_usecaseConfiguration;
50 extern RuntimeConfig* p_startupConfiguration[XRAN_PORTS_NUM];
54 * Covert a test case path into a test case name
55 * with the last two basenames in the path.
58 test_path_to_name(char *path, char *name)
60 if (path == NULL || name == NULL)
62 print_err("Null path(%#p) or name(%#p)", path, name);
66 char *dir, *base, *np = strdup(path);
75 *--base = '\0'; /* trim the last basename */
80 sprintf(name, "%s-%s-%d", basename(dir), base, num);
91 //-------------------------------------------------------------------------------------------
92 /** @ingroup group_source_flexran_xran
94 * @param[in] nTscFreq Frequency of the Time Stamp Counter (TSC) that the CPU currently is
96 * @return 0 if SUCCESS
99 * This function dumps current CPU information onto the XRAN_REPORT_FILE file which is used
100 * for automation of report generation
103 //-------------------------------------------------------------------------------------------
105 xran_init_mlog_stats(char *file, uint64_t nTscFreq)
110 pFile = fopen(file, "w");
113 printf("1: Cannot open %s to write in phydi_init_mlog_stats\n", file);
116 fprintf(pFile, "------------------------------------------------------------------------------------------------------------\n");
117 fprintf(pFile, "SYSTEM_PARAMS:\n");
118 fprintf(pFile, "TSC_FREQ: %ld\n", nTscFreq);
120 #ifdef BBDEV_FEC_ACCL_NR5G
121 PPHYCFG_VARS pPhyCfgVars = phycfg_get_ctx();
123 if (pPhyCfgVars->dpdkBasebandFecMode == 0)
125 fprintf(pFile, "FEC_OFFLOAD: SOFT_LDPC\n");
129 uint32_t nRet = phy_gnb_check_bbdev_hw_type();
131 if (nRet == BBDEV_DEV_NAME_MOUNT_BRYCE)
132 fprintf(pFile, "FEC_OFFLOAD: MOUNT_BRYCE\n");
133 else if (nRet == BBDEV_DEV_NAME_VISTA_CREEK)
134 fprintf(pFile, "FEC_OFFLOAD: VISTA_CREEK\n");
135 else if (nRet == BBDEV_DEV_NAME_SW_LDPC)
136 fprintf(pFile, "FEC_OFFLOAD: SOFT_LDPC\n");
138 fprintf(pFile, "FEC_OFFLOAD: UNKNOWN\n");
141 fprintf(pFile, "FEC_OFFLOAD: TERASIC\n");
147 sprintf(command, "lscpu >> %s", file);
151 pFile = fopen(file, "a");
154 printf("2: Cannot open %s to write in %s\n", file, __FUNCTION__);
157 fprintf(pFile, "------------------------------------------------------------------------------------------------------------\n");
158 fprintf(pFile, "COMMAND_LINE:\n");
162 sprintf(command, "cat /proc/cmdline >> %s", file);
166 pFile = fopen(file, "a");
169 printf("3: Cannot open %s to write in %s\n", file, __FUNCTION__);
172 fprintf(pFile, "------------------------------------------------------------------------------------------------------------\n");
173 fprintf(pFile, "MEMORY_INFO:\n");
178 sprintf(command, "dmidecode -t memory >> %s", file);
182 pFile = fopen(file, "a");
185 printf("4: Cannot open %s to write in %s\n", file, __FUNCTION__);
188 fprintf(pFile, "------------------------------------------------------------------------------------------------------------\n");
189 fprintf(pFile, "TURBOSTAT_INFO:\n");
193 sprintf(command, "turbostat --num_iterations 1 --interval 1 -q >> %s", file);
198 pFile = fopen(file, "a");
201 printf("5: Cannot open %s to write in %s\n", file, __FUNCTION__);
204 fprintf(pFile, "---------------------------------------------------------------------------\n");
212 xran_get_mlog_stats(char *usecase, UsecaseConfig *puConf, RuntimeConfig *psConf[], struct xran_mlog_times *mlog_times_p)
216 char stats_file[512]={0};
217 struct xran_mlog_stats tti, tmp;
218 uint32_t ttiDuration = 1000;
220 printf("%s: Usecase: %s\n", __FUNCTION__, usecase);
221 if (puConf == NULL || psConf == NULL || mlog_times_p == NULL) {
222 print_err("Null puConf(%p), psConf(%p), or mlog_times(%p)!",
223 puConf, psConf, mlog_times_p);
228 MLogPrint((char *)MLogGetFileName());
230 MLogGetStats(PID_TTI_TIMER, &tti.cnt, &tti.max, &tti.min, &tti.avg);
232 sprintf(stats_file, "%s-%s-%s", XRAN_REPORT_FILE, (puConf->appMode == APP_O_DU)? "o-du" : "o-ru", usecase);
233 printf("xran report file: %s\n", stats_file);
234 ret = xran_init_mlog_stats(stats_file, mlog_times_p->ticks_per_usec);
237 print_err("xran_init_mlog_stats(%s) returned %d!!", stats_file, ret);
242 pFile = fopen(stats_file, "a");
245 print_err("Cannot create %s!!", stats_file);
250 for (i = 0; i < psConf[0]->mu_number; i++)
251 ttiDuration = ttiDuration >> 1;
253 fprintf(pFile, "All data in this sheet are presented in usecs\n");
254 fprintf(pFile, "ORANTest: %s-%s (Num Cells: %d) (Num TTI: %d) (nNumerology: %d) (ttiDuration: %d usecs) (testStats: %d %ld %ld)\n",
255 (puConf->appMode == APP_O_DU)? "O-DU" : "O-RU", usecase, puConf->oXuNum * psConf[0]->numCC, tti.cnt, psConf[0]->mu_number, ttiDuration, puConf->appMode, mlog_times_p->xran_total_time, mlog_times_p->mlog_total_time);
257 double xran_task_type_sum[XRAN_TASK_TYPE_MAX] = {0, 0, 0, 0, 0, 0};
258 char * xran_task_type_name[XRAN_TASK_TYPE_MAX] =
259 { "GNB", "BBDEV", "Timer", "Radio", "CP", "UP" };
260 #define NUM_GNB_TASKS (5)
261 #define NUM_BBDEV_TASKS (4)
262 #define NUM_TIMER_TASKS (7)
263 #define NUM_RADIO_TASKS (2)
264 #define NUM_CP_TASKS (7)
265 #define NUM_UP_TASKS (5)
266 #define NUM_ALL_TASKS (NUM_GNB_TASKS+NUM_BBDEV_TASKS+NUM_TIMER_TASKS+NUM_RADIO_TASKS+NUM_CP_TASKS+NUM_UP_TASKS)
267 struct xran_mlog_taskid xranTasks[NUM_ALL_TASKS] = {
268 {PID_GNB_PROC_TIMING, XRAN_TASK_TYPE_GNB, "GNB_PROCC_TIMING \0"},
269 {PID_GNB_PROC_TIMING_TIMEOUT, XRAN_TASK_TYPE_GNB, "GNB_PROCC_TIMING_TIMEOUT \0"},
270 {PID_GNB_SYM_CB, XRAN_TASK_TYPE_GNB, "GNB_SYM_CB \0"},
271 {PID_GNB_PRACH_CB, XRAN_TASK_TYPE_GNB, "GNB_PRACH_CB \0"},
272 {PID_GNB_SRS_CB, XRAN_TASK_TYPE_GNB, "GNB_SRS_CB \0"},
274 {PID_XRAN_BBDEV_DL_POLL, XRAN_TASK_TYPE_BBDEV, "BBDEV_DL_POLL \0"},
275 {PID_XRAN_BBDEV_DL_POLL_DISPATCH, XRAN_TASK_TYPE_BBDEV,"BBDEV_DL_POLL_DISPATCH \0"},
276 {PID_XRAN_BBDEV_UL_POLL, XRAN_TASK_TYPE_BBDEV, "BBDEV_UL_POLL \0"},
277 {PID_XRAN_BBDEV_UL_POLL_DISPATCH, XRAN_TASK_TYPE_BBDEV,"BBDEV_UL_POLL_DISPATCH \0"},
279 {PID_TTI_TIMER, XRAN_TASK_TYPE_TIMER, "TTI_TIMER \0"},
280 {PID_TTI_CB, XRAN_TASK_TYPE_TIMER, "TTI_CB \0"},
281 {PID_TIME_SYSTIME_POLL, XRAN_TASK_TYPE_TIMER, "TIME_SYSTIME_POLL \0"},
282 {PID_TIME_SYSTIME_STOP, XRAN_TASK_TYPE_TIMER, "TIME_SYSTIME_STOP \0"},
283 {PID_TIME_ARM_TIMER, XRAN_TASK_TYPE_TIMER, "TIME_ARM_TIMER \0"},
284 {PID_TIME_ARM_TIMER_DEADLINE, XRAN_TASK_TYPE_TIMER, "TIME_ARM_TIMER_DEADLINE \0"},
285 {PID_TIME_ARM_USER_TIMER_DEADLINE, XRAN_TASK_TYPE_TIMER,"TIME_ARM_USER_TIMER_DEADLINE \0"},
287 {PID_RADIO_ETH_TX_BURST, XRAN_TASK_TYPE_RADIO, "RADIO_ETH_TX_BURST \0"},
288 {PID_RADIO_RX_VALIDATE, XRAN_TASK_TYPE_RADIO, "RADIO_RX_VALIDATE \0"},
290 {PID_PROCESS_TX_SYM, XRAN_TASK_TYPE_CP, "PROCESS_TX_SYM \0"},
291 {PID_DISPATCH_TX_SYM, XRAN_TASK_TYPE_CP, "PID_DISPATCH_TX_SYM \0"},
292 {PID_CP_DL_CB, XRAN_TASK_TYPE_CP, "PID_CP_DL_CB \0"},
293 {PID_CP_UL_CB, XRAN_TASK_TYPE_CP, "PID_CP_UL_CB \0"},
294 {PID_SYM_OTA_CB, XRAN_TASK_TYPE_CP, "SYM_OTA_CB \0"},
295 {PID_TTI_CB_TO_PHY, XRAN_TASK_TYPE_CP, "TTI_CB_TO_PHY \0"},
296 {PID_PROCESS_CP_PKT, XRAN_TASK_TYPE_CP, "PROCESS_CP_PKT \0"},
298 {PID_UP_UL_HALF_DEAD_LINE_CB, XRAN_TASK_TYPE_UP, "UP_UL_HALF_DEAD_LINE_CB \0"},
299 {PID_UP_UL_FULL_DEAD_LINE_CB, XRAN_TASK_TYPE_UP, "UP_UL_FULL_DEAD_LINE_CB \0"},
300 {PID_UP_UL_USER_DEAD_LINE_CB, XRAN_TASK_TYPE_UP, "UP_UL_USER_DEAD_LINE_CB \0"},
301 {PID_PROCESS_UP_PKT, XRAN_TASK_TYPE_UP, "PROCESS_UP_PKT \0"},
302 {PID_PROCESS_UP_PKT_SRS, XRAN_TASK_TYPE_UP, "PROCESS_UP_PKT_SRS \0"},
306 fprintf(pFile, "mlog_times: core used/total %lu/%lu, xran %lu(us)\n",
307 mlog_times_p->core_used_time, mlog_times_p->core_total_time,
308 mlog_times_p->xran_total_time);
311 fprintf(pFile, "---------------------------------------------------------------------------\n");
312 fprintf(pFile, "All task breakdown\n");
313 for (i=0; i < NUM_ALL_TASKS; i++) {
314 struct xran_mlog_taskid *p;
317 MLogGetStats(p->taskId, &tmp.cnt, &tmp.max, &tmp.min, &tmp.avg);
318 fprintf(pFile, "%4u:%s\t\t:\t%5.2f\n",
319 p->taskId, p->taskName, tmp.avg);
320 if (p->taskId != PID_TIME_SYSTIME_POLL) /* Skip TIME_SYSTIME_POLL */
321 xran_task_type_sum[p->taskType] += tmp.avg * tmp.cnt;
323 fprintf(pFile, "---------------------------------------------------------------------------\n");
324 fprintf(pFile, "Task type breakdown:\t\ttotal time\t(busy %%)\n");
325 for (i=0; i < XRAN_TASK_TYPE_MAX; i++) {
326 char name[32] ={' '};
328 sprintf(name,"%5s tasks", xran_task_type_name[i]);
330 fprintf(pFile, "%s:\t\t\t\t\t%7.2f\t(%5.2f%%)\n",
331 name, xran_task_type_sum[i] / tti.cnt,
332 xran_task_type_sum[i] * 100 / mlog_times_p->xran_total_time);
334 fprintf(pFile, "---------------------------------------------------------------------------\n\n");
335 fprintf(pFile, "====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~====~~~~~~~~====~~~~====~~~~");
342 printf("Closing [%s] ...\n", stats_file);
346 printf("%s: exit: %d\n", __FUNCTION__, ret);
351 app_profile_xran_print_mlog_stats(char *usecase_file)
356 printf("core_total_time\t\t%lu,\tcore_used_time\t\t%lu,\t%5.2f%% busy\n",
357 mlog_times.core_total_time, mlog_times.core_used_time,
358 ((float)mlog_times.core_used_time * 100.0) / (float)mlog_times.core_total_time);
359 mlog_times.xran_total_time = xran_total_ticks / MLogGetFreq();
360 printf("xran_total_ticks %lu (%lu usec)\n", xran_total_ticks, mlog_times.xran_total_time);
362 MLogGetStats(PID_XRAN_MAIN, &tmp.cnt, &tmp.max, &tmp.min, &tmp.avg);
363 mlog_times.mlog_total_time = tmp.cnt * (uint64_t)tmp.avg;
364 printf("xran_mlog_time: %lu usec\n", mlog_times.mlog_total_time);
366 MLogSetMask(0); /* Turned off MLOG */
367 test_path_to_name(usecase_file, filename);
368 printf("test cases: %s\n", filename);
369 ret = xran_get_mlog_stats(filename, p_usecaseConfiguration, p_startupConfiguration, &mlog_times);
374 #endif /* MLOG_ENABLED */