~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/misc/gtracestat.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * gtracestat.c: list the statistics information for a dumped xentrace file.
 
3
 * Copyright (c) 2009, Intel Corporation.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms and conditions of the GNU General Public License,
 
7
 * version 2, as published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope it will be useful, but WITHOUT
 
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
12
 * more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along with
 
15
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
16
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 
17
 */
 
18
 
 
19
#include <stdio.h>
 
20
#include <stdlib.h>
 
21
#include <string.h>
 
22
#include <unistd.h>
 
23
#include <fcntl.h>
 
24
#include <getopt.h>
 
25
#include <inttypes.h>
 
26
#include <sys/time.h>
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
 
 
30
#include <xenctrl.h>
 
31
#include <xen/trace.h>
 
32
 
 
33
#define CHECK_DUP_CX 0
 
34
 
 
35
/********** MACROS **********/
 
36
#define MAX_CPU_NR  32
 
37
#define MAX_CX_NR   8
 
38
#define MAX_MODE_NR 16
 
39
#define MAX_PX_NR       100
 
40
 
 
41
/* simplified xentrace record */
 
42
struct rec {
 
43
    uint64_t tsc;
 
44
    int cpu;
 
45
    unsigned char cx;
 
46
    unsigned char irqs[4];
 
47
    unsigned int predicted;
 
48
    unsigned int expected;
 
49
    int px;
 
50
};
 
51
 
 
52
/********** FORWARD DECLARATION **********/
 
53
void show_help(void);
 
54
void show_version(void);
 
55
int load_file(char *fname);
 
56
void do_digest(uint64_t start, uint64_t end, uint64_t scale);
 
57
void do_breakevents(void);
 
58
void do_count(void);
 
59
void do_px_count(void);
 
60
void do_maxmin(void);
 
61
void do_average(void);
 
62
void do_cstate(uint64_t start, uint64_t end);
 
63
void do_exp_ratio(void);
 
64
void do_exp_pred(void);
 
65
 
 
66
/********** GLOBAL VARIABLES **********/
 
67
/* store simplified xentrace data */
 
68
struct rec *data;
 
69
int64_t data_nr, data_cur;
 
70
/* store max cx state number and cpu number */
 
71
int max_cx_num = -1, max_cpu_num = -1;
 
72
int px_freq_table[MAX_PX_NR];
 
73
int max_px_num = 0;
 
74
 
 
75
int is_menu_gov_enabled = 0;
 
76
 
 
77
/* user specified translation unit */
 
78
uint64_t tsc2ms = 2793000UL;
 
79
uint64_t tsc2us = 2793UL;
 
80
uint64_t tsc2phase = 55800000UL;
 
81
 
 
82
/* each cpu column width */
 
83
int width = 0;
 
84
 
 
85
/* digest mode variables */
 
86
struct rec *evt[MAX_CPU_NR];
 
87
int evt_len[MAX_CPU_NR];
 
88
 
 
89
/* hand-crafted min() */
 
90
static inline uint64_t min(uint64_t a, uint64_t b)
 
91
{
 
92
    return a < b ? a : b;
 
93
}
 
94
static inline uint64_t max(uint64_t a, uint64_t b)
 
95
{
 
96
    return a > b ? a : b;
 
97
}
 
98
 
 
99
int is_px = 0;
 
100
 
 
101
int main(int argc, char *argv[])
 
102
{
 
103
    char *fname = NULL;
 
104
    /* operation flags */
 
105
    int is_breakevents = 0;
 
106
    int is_count = 0;
 
107
    int is_maxmin = 0;
 
108
    int is_average = 0;
 
109
    int is_digest = 0;
 
110
    int is_exp_ratio = 0;
 
111
    int is_exp = 0;
 
112
    uint64_t start_time = 0;
 
113
    uint64_t time_scale = 0;
 
114
    uint64_t end_time = 0;
 
115
 
 
116
    struct option  long_options [] = {
 
117
        /* short options are listed correspondingly */
 
118
        { "version", 0, NULL, 'v' },
 
119
        { "help", 0, NULL, 'h' },
 
120
        /* list Cx entires one by one */
 
121
        { "digest", 0, NULL, 'd' },
 
122
        /* ignored when digest is disabled */
 
123
        { "start", 1, NULL, 's' },
 
124
        { "end", 1, NULL, 'e' },
 
125
        { "scale", 1, NULL, 'l' },
 
126
        /* give summary about breakevents info */
 
127
        { "breakevents", 0, NULL, 'b' },
 
128
        { "count", 0, NULL, 'c' },
 
129
        { "average", 0, NULL, 'a' },
 
130
        /* list max/min residency for each Cx */
 
131
        { "maxmin", 0, NULL, 'm' },
 
132
        { "tsc2us", 1, NULL, 'u' },
 
133
        { "px", 0, NULL, 'p' },
 
134
        { "tsc2phase", 1, NULL, 'n' },
 
135
        { "exp-ratio", 0, NULL, 'z' },
 
136
        { "exp-pred", 0, NULL, 'x' },
 
137
        { NULL, 0, NULL, 0 },
 
138
    };
 
139
 
 
140
    while (1) {
 
141
        int ch, opt_idx;
 
142
        ch = getopt_long(argc, argv, "vhds:e:l:bcmaupnzx",
 
143
                         long_options, &opt_idx);
 
144
        if (ch == -1)
 
145
            break;
 
146
        switch (ch) {
 
147
        case 'v':
 
148
            show_version();
 
149
            exit(EXIT_SUCCESS);
 
150
        case 'h':
 
151
            show_help();
 
152
            exit(EXIT_SUCCESS);
 
153
        case 'p':
 
154
            is_px = 1;
 
155
            break;
 
156
        case 'x':
 
157
            is_exp = 1;
 
158
            break;
 
159
        case 'z':
 
160
            is_exp_ratio = 1;
 
161
            break;
 
162
        case 'n':
 
163
            tsc2phase = atoll(optarg);
 
164
            if (tsc2phase <= 0)
 
165
                tsc2phase = 55800000UL;
 
166
        case 'd':
 
167
            is_digest = 1;
 
168
            break;
 
169
        case 's':
 
170
            start_time = atoll(optarg);
 
171
            break;
 
172
        case 'e':
 
173
            end_time = atoll(optarg);
 
174
            break;
 
175
        case 'l':
 
176
            time_scale = atoll(optarg);
 
177
            break;
 
178
        case 'b':
 
179
            is_breakevents = 1;
 
180
            break;
 
181
        case 'c':
 
182
            is_count = 1;
 
183
            break;
 
184
        case 'm':
 
185
            is_maxmin = 1;
 
186
            break;
 
187
        case 'a':
 
188
            is_average = 1;
 
189
            break;
 
190
        case 'u':
 
191
            tsc2us = atoll(optarg);
 
192
            tsc2ms = tsc2us * 1000UL;
 
193
            break;
 
194
        case '?':
 
195
        default:
 
196
            show_help();
 
197
            exit(EXIT_FAILURE);
 
198
        }
 
199
    }
 
200
 
 
201
    if (argc - optind > 1) {
 
202
        printf("Multiple file specified?\n");
 
203
        show_help();
 
204
        exit(EXIT_FAILURE);
 
205
    }
 
206
    fname = argv[optind];
 
207
 
 
208
    if (load_file(fname))
 
209
        exit(EXIT_FAILURE);
 
210
 
 
211
    width = 10;
 
212
    if (is_digest) {
 
213
        /* if people not specify the time related number,
 
214
         * use the default one from the record.
 
215
         */
 
216
        if (!start_time)
 
217
            start_time = data[0].tsc;
 
218
        if (!end_time)
 
219
            end_time = data[data_cur-1].tsc;
 
220
        if (!time_scale)
 
221
            time_scale = 10UL * tsc2ms; /* default: 10 ms */
 
222
        do_digest(start_time, end_time, time_scale);
 
223
    }
 
224
 
 
225
    if (is_breakevents)
 
226
        do_breakevents();
 
227
 
 
228
    if (is_count && !is_px)
 
229
        do_count();
 
230
    if (is_count && is_px)
 
231
        do_px_count();
 
232
 
 
233
    if (is_maxmin)
 
234
        do_maxmin();
 
235
 
 
236
    if (is_average)
 
237
        do_average();
 
238
 
 
239
    if (is_exp_ratio)
 
240
        do_exp_ratio();
 
241
 
 
242
    if (is_exp)
 
243
        do_exp_pred();
 
244
 
 
245
    exit(EXIT_SUCCESS);
 
246
}
 
247
 
 
248
/* used for qsort() */
 
249
/* sort by cpu first, then by tsc */
 
250
static int data_cmp(const void *_a, const void *_b)
 
251
{
 
252
    struct rec *a = (struct rec *)_a;
 
253
    struct rec *b = (struct rec *)_b;
 
254
    if (a->cpu == b->cpu)
 
255
        return a->tsc > b->tsc ? 1 : -1;
 
256
    return a->cpu > b->cpu ? 1 : -1;
 
257
}
 
258
 
 
259
/* load file and make them a list of records
 
260
 * update these following variables:
 
261
 *   data, data_cur, data_nr
 
262
 *   max_cpu_num, max_cx_num
 
263
 */
 
264
#define LIST_PX 0
 
265
int load_file(char *fname)
 
266
{
 
267
    /* file descriptor for raw xentrace file */
 
268
    int fd;
 
269
    /* current cpu during xentrace data parse */
 
270
    int cur_cpu = -1;
 
271
    int i;
 
272
 
 
273
    fd = open(fname, O_RDONLY);
 
274
    if (fd < 0) {
 
275
        fprintf(stderr, "file %s cannot open\n", fname);
 
276
        return 1;
 
277
    }
 
278
 
 
279
    /* the initial number is 1024,
 
280
     * and when it overflows, this number doubles.
 
281
     */
 
282
    data_nr = 1024;
 
283
    data_cur = 0;
 
284
    data = malloc(sizeof(struct rec) * data_nr);
 
285
    if (!data) {
 
286
        fprintf(stderr, "not enough memory\n");
 
287
        close(fd);
 
288
        return 1;
 
289
    }
 
290
 
 
291
    while (1) {
 
292
        struct t_rec rec;
 
293
        ssize_t ret, size;
 
294
 
 
295
        ret = read(fd, &rec, sizeof(uint32_t));
 
296
        if (!ret)
 
297
            break;
 
298
        if (ret != sizeof(uint32_t)) {
 
299
            fprintf(stderr, "reading header error\n");
 
300
            break;
 
301
        }
 
302
 
 
303
        size = 0;
 
304
        if (rec.cycles_included)
 
305
            size += sizeof(uint64_t);
 
306
        size += sizeof(uint32_t) * rec.extra_u32;
 
307
 
 
308
        ret = read(fd, (char *)&rec + sizeof(uint32_t), size);
 
309
        if (!ret && size)
 
310
            break;
 
311
        if (ret != size) {
 
312
            fprintf(stderr, "reading data error\n");
 
313
            break;
 
314
        }
 
315
 
 
316
        if (rec.event == 0x1f003) {
 
317
            /* cpu change event */
 
318
            cur_cpu = 0;
 
319
            if (rec.extra_u32 > 0)
 
320
                cur_cpu = rec.u.nocycles.extra_u32[0];
 
321
            continue;
 
322
        } else if (!rec.cycles_included ||
 
323
                   (rec.event != TRC_PM_IDLE_ENTRY &&
 
324
                    rec.event != TRC_PM_IDLE_EXIT &&
 
325
                    rec.event != TRC_PM_FREQ_CHANGE)) {
 
326
            /* we care about only idle events now */
 
327
            continue;
 
328
        }
 
329
 
 
330
        /* add one record */
 
331
        if (data_cur == data_nr) {
 
332
            data_nr <<= 1;
 
333
            if (data_nr < 0) {
 
334
                fprintf(stderr, "too many entries\n");
 
335
                close(fd);
 
336
                return 1;
 
337
            }
 
338
            data = realloc(data, sizeof(struct rec) * data_nr);
 
339
            if (!data) {
 
340
                fprintf(stderr, "not enough memory\n");
 
341
                close(fd);
 
342
                return 1;
 
343
            }
 
344
        }
 
345
        data[data_cur].tsc = rec.u.cycles.cycles_hi;
 
346
        data[data_cur].tsc <<= 32;
 
347
        data[data_cur].tsc |= rec.u.cycles.cycles_lo;
 
348
        data[data_cur].cpu = cur_cpu;
 
349
        if (is_px) {
 
350
            if (rec.event != TRC_PM_FREQ_CHANGE)
 
351
                continue;
 
352
            /* FREQ_CHANGE */
 
353
            if (rec.u.cycles.extra_u32[0] ==
 
354
                rec.u.cycles.extra_u32[1])
 
355
                continue;
 
356
            data[data_cur].px = rec.u.cycles.extra_u32[1];
 
357
            for (i = 0; i < max_px_num; i++)
 
358
                if (px_freq_table[i] == data[data_cur].px)
 
359
                    break;
 
360
            if (i == max_px_num)
 
361
                px_freq_table[max_px_num++] = data[data_cur].px;
 
362
        } else {
 
363
            if (rec.event == TRC_PM_IDLE_ENTRY) {
 
364
                data[data_cur].cx = rec.u.cycles.extra_u32[0];
 
365
                if (rec.extra_u32 >= 4) {
 
366
                    data[data_cur].expected = rec.u.cycles.extra_u32[2];
 
367
                    data[data_cur].predicted = rec.u.cycles.extra_u32[3];
 
368
                    is_menu_gov_enabled = 1;
 
369
                } else
 
370
                    is_menu_gov_enabled = 0;
 
371
            } else if (rec.event == TRC_PM_IDLE_EXIT) {
 
372
                /* IDLE_EXIT default to C0 */
 
373
                data[data_cur].cx = 0;
 
374
                /* store the reasons why it exits */
 
375
                data[data_cur].irqs[0] = rec.u.cycles.extra_u32[2];
 
376
                data[data_cur].irqs[1] = rec.u.cycles.extra_u32[3];
 
377
                data[data_cur].irqs[2] = rec.u.cycles.extra_u32[4];
 
378
                data[data_cur].irqs[3] = rec.u.cycles.extra_u32[5];
 
379
            } else
 
380
                continue;
 
381
            /* update max info */
 
382
            if (data[data_cur].cx > max_cx_num)
 
383
                max_cx_num = data[data_cur].cx;
 
384
        }
 
385
 
 
386
        if (data[data_cur].cpu > max_cpu_num)
 
387
            max_cpu_num = data[data_cur].cpu;
 
388
 
 
389
        data_cur++;
 
390
    }
 
391
    close(fd);
 
392
 
 
393
    /* sort data array according to TSC time line */
 
394
    qsort(data, data_cur, sizeof(struct rec), data_cmp);
 
395
 
 
396
    max_cpu_num++;
 
397
    max_cx_num++;
 
398
 
 
399
    for (i = 0; i < max_cpu_num; i++) {
 
400
        evt_len[i] = 0;
 
401
        evt[i] = NULL;
 
402
    }
 
403
    for (i = data_cur-1; i >= 0; i--) {
 
404
        evt[data[i].cpu] = data+i;
 
405
        evt_len[data[i].cpu]++;
 
406
    }
 
407
#if CHECK_DUP_CX
 
408
    int xx, yy;
 
409
    int err = 0;
 
410
    printf("Checking %s...\n", fname);
 
411
    for (xx = 0; xx < max_cpu_num; xx++) {
 
412
        //      printf("............ CPU %d .............\n", xx);
 
413
        for (yy = 0; yy+1 < evt_len[xx]; yy++)
 
414
            if ( evt[xx][yy].cx > 0 && evt[xx][yy+1].cx > 0) {
 
415
                printf("same witht next one %"PRIu64" %d %d\n",
 
416
                       evt[xx][yy].tsc, evt[xx][yy].cpu, evt[xx][yy].cx);
 
417
                err++;
 
418
            }
 
419
    }
 
420
    exit(err);
 
421
#endif
 
422
#if LIST_PX
 
423
    int x, y;
 
424
    for (x = 0; x < max_cpu_num; x++) {
 
425
        printf("CPU%d**************************************\n", x);
 
426
        for (y = 0; y+1 < evt_len[x]; y++) {
 
427
            printf("[%dHz]: phase: %d\n",
 
428
                   evt[x][y].px,
 
429
                   (int)((evt[x][y+1].tsc - evt[x][y].tsc)/tsc2phase));
 
430
        }
 
431
    }
 
432
#endif
 
433
    return 0;
 
434
}
 
435
 
 
436
void show_version(void)
 
437
{
 
438
    printf("gtracestat - (C) 2009 Intel Corporation\n");
 
439
}
 
440
 
 
441
void show_help(void)
 
442
{
 
443
    show_version();
 
444
    printf("tracestat <trace.data> [-vhdselbcmau]\n");
 
445
    printf("  trace.data       raw data got by 'xentrace -e 0x80f000 trace.dat'\n");
 
446
    printf("  -v / --version   show version message\n");
 
447
    printf("  -h / --help      show this message\n");
 
448
    printf("  -d / --digest    digest mode, more variables to specify.\n");
 
449
    printf("  -s / --start <start_time> specify start time (only in digest mode)\n");
 
450
    printf("  -e / --end <end_time>     specify end time (only in digest mode)\n");
 
451
    printf("  -l / --scale <scale>      specify time scale (only in digest mode)\n");
 
452
    printf("  -b / --breakevents give breakevents summary info\n");
 
453
    printf("  -c / --count       give count summary info\n");
 
454
    printf("  -a / --average     give total/average residency info\n");
 
455
    printf("  -m / --maxmin      show man/min residency summary info\n");
 
456
    printf("  -u / --tsc2us      specify how many tsc is a us unit\n");
 
457
    printf("  -p / --px          operate on Px entries\n");
 
458
    printf("  -n / --tsc2phase   specify how many tsc is a phase unit (only in px)\n");
 
459
    printf("  -z / --exp-ratio   show the ratio of early break events\n");
 
460
    printf("  -x / --exp-pred    show the ratio of expected / predicted in Cx entry\n");
 
461
}
 
462
 
 
463
static inline int len_of_number(uint64_t n)
 
464
{
 
465
    int l = 0;
 
466
    do {
 
467
        l++;
 
468
        n /= 10;
 
469
    } while (n);
 
470
    return l;
 
471
}
 
472
 
 
473
/* determine the cx at time t
 
474
 * take advantage of evt and evt_len.
 
475
 */
 
476
int determine_cx(int c, uint64_t t)
 
477
{
 
478
    int i;
 
479
 
 
480
    i = 0;
 
481
    while (i < evt_len[c] && evt[c][i].tsc <= t)
 
482
        i++;
 
483
    /* if there are any events happening,
 
484
     * it must be in a Cx state now.
 
485
     */
 
486
    if (i)
 
487
        return evt[c][i-1].cx;
 
488
    /* look forward to see whether it will enter
 
489
     * a Cx state, if so, it must be in C0 state.
 
490
     * we can't determine a Cx state from exit event.
 
491
     */
 
492
    if (i < evt_len[c] && evt[c][i].cx > 0)
 
493
        return 0;
 
494
    return -1;
 
495
}
 
496
 
 
497
/* c - cpu
 
498
 * t - start time
 
499
 * s - scale
 
500
 * cx_i - number of cx index
 
501
 * cx_r - residency of each cx entry
 
502
 */
 
503
int process(int c, uint64_t t, uint64_t s, int *cx_i, uint64_t *cx_r)
 
504
{
 
505
    int cx;
 
506
    uint64_t len;
 
507
    int i, n;
 
508
 
 
509
    cx = determine_cx(c, t);
 
510
    i = 0;
 
511
    while (i < evt_len[c] && evt[c][i].tsc < t)
 
512
        i++;
 
513
    n = 0;
 
514
    if (cx >= 0 && i < evt_len[c]) {
 
515
        cx_i[n] = cx;
 
516
        cx_r[n] = evt[c][i].tsc - t;
 
517
        if (cx_r[n])
 
518
            n++;
 
519
    }
 
520
    while (i < evt_len[c] && evt[c][i].tsc < t+s) {
 
521
        /* we are now at [t, t+s) */
 
522
        cx = evt[c][i].cx;
 
523
        len = min((i+1 < evt_len[c] ? evt[c][i+1].tsc : t+s), t+s)
 
524
            - evt[c][i].tsc;
 
525
 
 
526
        cx_i[n] = cx;
 
527
        cx_r[n] = len;
 
528
        n++;
 
529
 
 
530
        i++;
 
531
    }
 
532
 
 
533
    return n;
 
534
}
 
535
 
 
536
void nr_putchar(int nr, int ch)
 
537
{
 
538
    int i;
 
539
    for (i = 0; i < nr; i++)
 
540
        putchar(ch);
 
541
}
 
542
 
 
543
#define MAX_INTERVAL_ENTRY      1000
 
544
/* process period [start_time, start_time + time_scale) */
 
545
void single_digest(uint64_t start_time, uint64_t time_scale)
 
546
{
 
547
    int cpu;
 
548
    int cx_i[MAX_CPU_NR][MAX_INTERVAL_ENTRY];
 
549
    uint64_t cx_r[MAX_CPU_NR][MAX_INTERVAL_ENTRY];
 
550
    int cx_n[MAX_CPU_NR];
 
551
    int max_n;
 
552
 
 
553
    memset(cx_i, 0, sizeof(int) * MAX_CPU_NR * MAX_INTERVAL_ENTRY);
 
554
    memset(cx_r, 0, sizeof(uint64_t) * MAX_CPU_NR * MAX_INTERVAL_ENTRY);
 
555
    memset(cx_n, 0, sizeof(int) * MAX_CPU_NR);
 
556
 
 
557
    max_n = 0;
 
558
    for (cpu = 0; cpu < max_cpu_num; cpu++) {
 
559
        cx_n[cpu] = process(cpu, start_time, time_scale, cx_i[cpu], cx_r[cpu]);
 
560
        if (cx_n[cpu] > max_n)
 
561
            max_n = cx_n[cpu];
 
562
    }
 
563
 
 
564
    /* means how many lines will be consumed */
 
565
    while (--max_n >= 0) {
 
566
        for (cpu = 0; cpu < max_cpu_num; cpu++) {
 
567
            if (cx_n[cpu] > 0) {
 
568
                int i;
 
569
                /* find the available cx index */
 
570
                for (i = 0; i < MAX_INTERVAL_ENTRY && cx_i[cpu][i] == -1; i++)
 
571
                    ;
 
572
                if (i < MAX_INTERVAL_ENTRY) {
 
573
                    int len;
 
574
                    /* print it */
 
575
                    len= printf("C%d,%"PRIu64".%d", cx_i[cpu][i],
 
576
                                cx_r[cpu][i]/tsc2ms,
 
577
                                (unsigned int)(cx_r[cpu][i]/(tsc2ms/10))%10);
 
578
                    nr_putchar(width-len, ' ');
 
579
 
 
580
                    cx_i[cpu][i] = -1;
 
581
                } else
 
582
                    nr_putchar(width, ' ');
 
583
 
 
584
                cx_n[cpu]--;
 
585
            } else
 
586
                nr_putchar(width, ' ');
 
587
        }
 
588
        nr_putchar(1, '\n');
 
589
    }
 
590
}
 
591
 
 
592
void do_digest(uint64_t start, uint64_t end, uint64_t scale)
 
593
{
 
594
    int i;
 
595
    uint64_t ms = 0;
 
596
    uint64_t delta_ms = scale / tsc2ms;
 
597
 
 
598
    for (i = 0; i < max_cpu_num; i++) {
 
599
        int len = 0;
 
600
        len = printf("CPU%d", i);
 
601
        nr_putchar(width-len, ' ');
 
602
    }
 
603
    nr_putchar(1, '\n');
 
604
    while (start < end) {
 
605
        /* print --- xxx ms --- line */
 
606
        int off = (max_cpu_num * width - len_of_number(ms) - 2)/2;
 
607
        nr_putchar(off, '-');
 
608
        off += printf("%"PRIu64"ms", ms);
 
609
        off += printf(" (%"PRIu64")", start);
 
610
        nr_putchar(max_cpu_num * width-off, '-');
 
611
        nr_putchar(1, '\n');
 
612
        /* print each digest entries */
 
613
        single_digest(start, scale);
 
614
 
 
615
        start += scale;
 
616
        ms += delta_ms;
 
617
    }
 
618
}
 
619
 
 
620
/* [min, max) */
 
621
struct cond_rec {
 
622
    uint64_t min;
 
623
    uint64_t max;
 
624
    uint64_t cnt;
 
625
    uint64_t res;
 
626
};
 
627
 
 
628
void cond_rec_init(struct cond_rec *r, uint64_t min, uint64_t max)
 
629
{
 
630
    r->min = min;
 
631
    r->max = max;
 
632
    r->cnt = 0;
 
633
}
 
634
 
 
635
void cond_rec_inc(uint64_t cur, struct cond_rec *r)
 
636
{
 
637
    if (r->min <= cur && cur < r->max) {
 
638
        r->cnt++;
 
639
        r->res += cur;
 
640
    }
 
641
}
 
642
 
 
643
/* c    - current cpu to scan
 
644
 * cx   - cx state to track
 
645
 * a    - conditonal array
 
646
 * n    - how many entries there are
 
647
 */
 
648
void do_count_per_cpu(int c, int cx, struct cond_rec *a, int n)
 
649
{
 
650
    int i;
 
651
    /* find Cx entry first */
 
652
    i = 0;
 
653
    while (i < evt_len[c] && evt[c][i].cx == 0)
 
654
        i++;
 
655
    /* check evt[c][i] and evt[c][i+1] */
 
656
    while (i + 1 < evt_len[c]) {
 
657
        if (evt[c][i].cx == cx) {
 
658
            uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc;
 
659
            int j;
 
660
            /* check for each condition */
 
661
            for (j = 0; j < n; j++)
 
662
                cond_rec_inc(len, a+j);
 
663
        }
 
664
        i++;
 
665
    }
 
666
}
 
667
 
 
668
struct cond_rec *make_cond_rec(uint64_t *a, int n)
 
669
{
 
670
    int i;
 
671
    struct cond_rec *t = malloc(sizeof(struct cond_rec) * (n+1));
 
672
    if (!t)
 
673
        return NULL;
 
674
    for (i = 0; i < n; i++) {
 
675
        t[i].max = a[i];
 
676
        t[i+1].min = a[i];
 
677
        t[i].cnt = 0;
 
678
        t[i].res = 0;
 
679
    }
 
680
    t[0].min = 0;
 
681
    t[n].max = (uint64_t) -1;
 
682
    t[n].cnt = 0;
 
683
    t[n].res = 0;
 
684
 
 
685
    return t;
 
686
}
 
687
 
 
688
uint64_t max_res[MAX_CPU_NR][MAX_CX_NR];
 
689
uint64_t min_res[MAX_CPU_NR][MAX_CX_NR];
 
690
uint64_t max_tm[MAX_CPU_NR][MAX_CX_NR];
 
691
uint64_t min_tm[MAX_CPU_NR][MAX_CX_NR];
 
692
 
 
693
void do_maxmin_per_cpu(int c)
 
694
{
 
695
    int i;
 
696
    /* find Cx entry first */
 
697
    i = 0;
 
698
    while (i < evt_len[c] && evt[c][i].cx == 0)
 
699
        i++;
 
700
    /* check evt[c][i] and evt[c][i+1] */
 
701
    while (i + 1 < evt_len[c]) {
 
702
        int cx = evt[c][i].cx;
 
703
        uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc;
 
704
        if (len > max_res[c][cx]) {
 
705
            max_res[c][cx] = len;
 
706
            max_tm[c][cx] = evt[c][i].tsc;
 
707
        }
 
708
        if (len < min_res[c][cx]) {
 
709
            min_res[c][cx] = len;
 
710
            min_tm[c][cx] = evt[c][i].tsc;
 
711
        }
 
712
        i++;
 
713
    }
 
714
}
 
715
 
 
716
void do_maxmin(void)
 
717
{
 
718
    int i, j;
 
719
    /* init */
 
720
    for (i = 0; i < max_cpu_num; i++)
 
721
        for (j = 0; j < max_cx_num; j++) {
 
722
            max_res[i][j] = 0;
 
723
            min_res[i][j] = (uint64_t) -1;
 
724
        }
 
725
 
 
726
    for (i = 0; i < max_cpu_num; i++)
 
727
        do_maxmin_per_cpu(i);
 
728
 
 
729
    for (i = 0; i < max_cpu_num; i++) {
 
730
        printf("********* CPU%d *********\n", i);
 
731
        for (j = 0; j < max_cx_num; j++)
 
732
            if (max_res[i][j] == 0)
 
733
                printf("     not found                 ");
 
734
            else
 
735
                printf("%7"PRIu64"us (%15"PRIu64")    ", max_res[i][j]/tsc2us, max_tm[i][j]);
 
736
        printf("\n");
 
737
        for (j = 0; j < max_cx_num; j++)
 
738
            if (max_res[i][j] == 0)
 
739
                printf("     not found                 ");
 
740
            else
 
741
                printf("%7"PRIu64"us (%15"PRIu64")    ", min_res[i][j]/tsc2us, min_tm[i][j]);
 
742
        printf("\n\n");
 
743
    }
 
744
}
 
745
 
 
746
void do_count(void)
 
747
{
 
748
    uint64_t scale[100] = { 50000UL, 100000UL, 200000UL, 400000UL, 800000UL, 1000000UL };
 
749
    int a[100];
 
750
    int scale_len = 6;
 
751
    int len = 0;
 
752
    int i, j;
 
753
 
 
754
    printf("Please input the period:  (Ctrl+D to quit)\n");
 
755
    printf("The default is 50us, 100us, 200us, 400us, 800us, 1000us.\n(unit is us, you DO NOT need to add us and specify ZERO us and please be in INCREASING order.)\n");
 
756
    while (scanf("%d", &a[len]) == 1)
 
757
        len++;
 
758
    if (len) {
 
759
        for (i = 0; i < len; i++)
 
760
            scale[i] = a[i] * tsc2us;
 
761
        scale_len = len;
 
762
    }
 
763
    for (i = 0; i < max_cpu_num; i++) {
 
764
        struct cond_rec *r[MAX_CX_NR];
 
765
        uint64_t sum[MAX_CX_NR];
 
766
        int k;
 
767
 
 
768
        printf("********** CPU%d *********\n", i);
 
769
        for (j = 0; j < max_cx_num; j++) {
 
770
            r[j] = make_cond_rec(scale, scale_len);
 
771
            if (!r[j])
 
772
                continue;
 
773
            do_count_per_cpu(i, j, r[j], scale_len+1);
 
774
 
 
775
            /* print */
 
776
            sum[j] = 0;
 
777
            for (k = 0; k < scale_len+1; k++)
 
778
                sum[j] += r[j][k].cnt;
 
779
            if (sum[j] == 0)
 
780
                sum[j] = 1;
 
781
        }
 
782
        printf("                              ");
 
783
        for (j = 0; j < max_cx_num; j++)
 
784
            printf("         C%d          ", j);
 
785
        printf("\n");
 
786
        for (k = 0; k < scale_len+1; k++) {
 
787
            if (k == scale_len)
 
788
                printf("%5"PRIu64" us ->   MAX us:", r[0][k].min/tsc2us);
 
789
            else
 
790
                printf("%5"PRIu64" us -> %5"PRIu64" us:",
 
791
                       r[0][k].min/tsc2us, r[0][k].max/tsc2us);
 
792
            for (j = 0; j < max_cx_num; j++)
 
793
                printf("    %10"PRIu64" (%5.2f%%)",
 
794
                       r[j][k].cnt, 100.0 * (double) r[j][k].cnt / (double)sum[j]);
 
795
            printf("\n");
 
796
        }
 
797
        for (j = 0; j < max_cx_num; j++)
 
798
            free(r[j]);
 
799
    }
 
800
}
 
801
 
 
802
static void do_px_count_per_cpu(int c, int px, struct cond_rec *cond, int n)
 
803
{
 
804
    int i, j;
 
805
    uint64_t len;
 
806
 
 
807
    i = 0;
 
808
    while (i+1 < evt_len[c]) {
 
809
        if (evt[c][i].px == px) {
 
810
            len = evt[c][i+1].tsc - evt[c][i].tsc;
 
811
            /* check each condition */
 
812
            for (j = 0; j < n; j++)
 
813
                cond_rec_inc(len, cond+j);
 
814
        }
 
815
        i++;
 
816
    }
 
817
}
 
818
 
 
819
void do_px_count(void)
 
820
{
 
821
    int a[100];
 
822
    uint64_t scale[100];
 
823
    int n, i, c, j;
 
824
 
 
825
    printf("Please input phases series: (Ctrl+D to quit)\n");
 
826
    printf("The default is 1, 2, 4, 8, 16, 32.\n");
 
827
    printf("Please be in increasing order.\n");
 
828
    scale[0] = tsc2phase;
 
829
    scale[1] = 2 * tsc2phase;
 
830
    scale[2] = 4 * tsc2phase;
 
831
    scale[3] = 8 * tsc2phase;
 
832
    scale[4] = 16 * tsc2phase;
 
833
    scale[5] = 32 * tsc2phase;
 
834
    n = 0;
 
835
    while (scanf("%d", &a[n]) == 1)
 
836
        n++;
 
837
    if (n) {
 
838
        for (i = 0; i < n; i++)
 
839
            scale[i] = a[i] * tsc2phase;
 
840
    } else
 
841
        n = 6;
 
842
    for (c = 0; c < max_cpu_num; c++) {
 
843
        struct cond_rec *p[MAX_PX_NR];
 
844
        int k;
 
845
 
 
846
        printf("***** CPU%d *****\n", c);
 
847
        for (i = 0; i < max_px_num; i++) {
 
848
            p[i] = make_cond_rec(scale, n);
 
849
            if (!p[i])
 
850
                continue;
 
851
            do_px_count_per_cpu(c, px_freq_table[i], p[i], n+1);
 
852
        }
 
853
        /* print */
 
854
        nr_putchar(16, ' ');
 
855
        for (j = 0; j < max_px_num; j++)
 
856
            printf("P%d\t", px_freq_table[j]);
 
857
        printf("\n");
 
858
        for (k = 0; k < n+1; k++) {
 
859
            if (k == n)
 
860
                printf("%5"PRIu64" ->  MAX : ", p[0][k].min/tsc2phase);
 
861
            else
 
862
                printf("%5"PRIu64" -> %5"PRIu64": ",
 
863
                       p[0][k].min/tsc2phase, p[0][k].max/tsc2phase);
 
864
            for (j = 0; j < max_px_num; j++) {
 
865
                printf("%"PRIu64"\t", p[j][k].cnt);
 
866
            }
 
867
            printf("\n");
 
868
        }
 
869
        printf("---\n");
 
870
        printf("Count:          ");
 
871
        for (j = 0; j < max_px_num; j++) {
 
872
            int sum = 0;
 
873
            for (k = 0; k < n+1; k++) {
 
874
                sum += (int)p[j][k].cnt;
 
875
            }
 
876
            /* print count */
 
877
            printf("%d\t", sum);
 
878
        }
 
879
        printf("\nAverage:        ");
 
880
        for (j = 0; j < max_px_num; j++) {
 
881
            int sum = 0;
 
882
            int s_res = 0;
 
883
            for (k = 0; k < n+1; k++) {
 
884
                sum += (int)p[j][k].cnt;
 
885
                s_res += (int)(p[j][k].res/tsc2phase);
 
886
            }
 
887
            /* print average */
 
888
            if (sum == 0)
 
889
                sum = 1;
 
890
            printf("%.1f\t", (double)s_res/(double)sum);
 
891
        }
 
892
        printf("\nTotal:          ");
 
893
        for (j = 0; j < max_px_num; j++) {
 
894
            int s_res = 0;
 
895
            for (k = 0; k < n+1; k++) {
 
896
                s_res += (int)(p[j][k].res/tsc2phase);
 
897
            }
 
898
            /* print total */
 
899
            printf("%d\t", s_res);
 
900
        }
 
901
        printf("\n");
 
902
    }
 
903
}
 
904
 
 
905
void do_breakevents(void)
 
906
{
 
907
    int br[MAX_CPU_NR][257];
 
908
    float pc[MAX_CPU_NR][257];
 
909
    int i, j, k, l;
 
910
 
 
911
    memset(br, 0, sizeof(int) * MAX_CPU_NR * 257);
 
912
    memset(pc, 0, sizeof(int) * MAX_CPU_NR * 257);
 
913
 
 
914
    for (i = 0; i < max_cpu_num; i++) {
 
915
        int sum = 0;
 
916
        for (j = 0; j < evt_len[i]; j++) {
 
917
            if (evt[i][j].cx == 0) {
 
918
                /* EXIT */
 
919
                /* collect breakevents information */
 
920
                int xx = 0;
 
921
                for (k = 0; k < 4; k++) {
 
922
                    int irq = evt[i][j].irqs[k];
 
923
                    if (irq) {
 
924
                        br[i][irq]++;
 
925
                        sum++;
 
926
                        xx++;
 
927
                    }
 
928
                }
 
929
                if (!xx) {
 
930
                    br[i][256]++;
 
931
                    sum++;
 
932
                }
 
933
            }
 
934
        }
 
935
        for (j = 0; j < 257; j++)
 
936
            pc[i][j] = 100.0 * br[i][j]/sum;
 
937
    }
 
938
    /* print the results */
 
939
    width = 13;
 
940
    printf("      ");
 
941
    for (i = 0; i < max_cpu_num; i++) {
 
942
        l = 0;
 
943
        l += printf("CPU%d", i);
 
944
        nr_putchar(width-l, ' ');
 
945
    }
 
946
    printf("\n");
 
947
 
 
948
    for (j = 0; j < 257; j++) {
 
949
        int n = 0;
 
950
        for (i = 0; i < max_cpu_num; i++)
 
951
            if (br[i][j])
 
952
                n++;
 
953
        if (n) {
 
954
            if (j == 256)
 
955
                printf("[N/A] ");
 
956
            else
 
957
                printf("[%03x] ", j);
 
958
            for (i = 0; i < max_cpu_num; i++) {
 
959
                if (br[i][j]) {
 
960
                    l = 0;
 
961
                    l += printf("%.1f%%,%d ", pc[i][j], br[i][j]);
 
962
                    nr_putchar(width-l, ' ');
 
963
                } else {
 
964
                    nr_putchar(width, ' ');
 
965
                }
 
966
            }
 
967
            printf("\n");
 
968
        }
 
969
    }
 
970
}
 
971
 
 
972
void single_cstate(int c, uint64_t t, uint64_t e,
 
973
                   uint64_t *a,
 
974
                   uint64_t *max_res,
 
975
                   uint64_t *min_res,
 
976
                   uint64_t *num);
 
977
void do_cstate(uint64_t start, uint64_t end)
 
978
{
 
979
    uint64_t cxtime[MAX_CX_NR];
 
980
    uint64_t max_res[MAX_CX_NR];
 
981
    uint64_t min_res[MAX_CX_NR];
 
982
    uint64_t num[MAX_CX_NR];
 
983
    int i, j;
 
984
 
 
985
    width = 20;
 
986
    printf("       ");
 
987
    for (i = 0; i < max_cx_num; i++) {
 
988
        int l = printf("C%d", i);
 
989
        nr_putchar(width-l, ' ');
 
990
    }
 
991
    printf("\n");
 
992
 
 
993
    for (i = 0; i < max_cpu_num; i++) {
 
994
        uint64_t sum = 0;
 
995
        single_cstate(i, start, end, cxtime, max_res, min_res, num);
 
996
        printf("CPU%2d ", i);
 
997
        for (j = 0; j < max_cx_num; j++)
 
998
            sum += cxtime[i];
 
999
        for (j = 0; j < max_cx_num; j++) {
 
1000
            int l = printf("%.1f%%, %"PRIu64".%d, %"PRIu64".%d, %"PRIu64,
 
1001
                           100.0 * cxtime[j]/sum,
 
1002
                           max_res[j]/tsc2ms,
 
1003
                           (unsigned int)(max_res[j]/(tsc2ms/10))%10,
 
1004
                           min_res[j]/tsc2ms,
 
1005
                           (unsigned int)(min_res[j]/(tsc2ms/10))%10,
 
1006
                           cxtime[j]/num[j]/tsc2ms);
 
1007
            nr_putchar(width - l, ' ');
 
1008
        }
 
1009
    }
 
1010
}
 
1011
 
 
1012
void single_cstate(int c, uint64_t t, uint64_t e,
 
1013
                   uint64_t *a,
 
1014
                   uint64_t *max_res,
 
1015
                   uint64_t *min_res,
 
1016
                   uint64_t *num)
 
1017
{
 
1018
    int cx;
 
1019
    int i;
 
1020
    int first = 1;
 
1021
 
 
1022
    for (i = 0; i < max_cx_num; i++) {
 
1023
        a[i] = 0;
 
1024
        max_res[i] = 0;
 
1025
        min_res[i] = (uint64_t) -1;
 
1026
        num[i] = 0;
 
1027
    }
 
1028
 
 
1029
    cx = determine_cx(c, t);
 
1030
    i = 0;
 
1031
    while (i < evt_len[c] && evt[c][i].tsc <= t)
 
1032
        i++;
 
1033
    for (; i+1 < evt_len[c] && evt[c][i].tsc <= e; i++) {
 
1034
        int cxidx = evt[c][i].cx;
 
1035
        uint64_t delta;
 
1036
 
 
1037
        if (first && cx >= 0) {
 
1038
            /* Partial Cx, only once */
 
1039
            first = 0;
 
1040
 
 
1041
            cxidx = cx;
 
1042
            delta = evt[c][i].tsc - max(evt[c][i-1].tsc, t);
 
1043
            a[cxidx] += delta;
 
1044
            num[cxidx]++;
 
1045
 
 
1046
            /* update min and max residency */
 
1047
            if (delta > max_res[cxidx])
 
1048
                max_res[cxidx] = delta;
 
1049
            if (delta < min_res[cxidx])
 
1050
                min_res[cxidx] = delta;
 
1051
        }
 
1052
        delta = evt[c][i+1].tsc - evt[c][i].tsc;
 
1053
        a[cxidx] += delta;
 
1054
        num[cxidx]++;
 
1055
 
 
1056
        /* update min and max residency */
 
1057
        if (delta > max_res[cxidx])
 
1058
            max_res[cxidx] = delta;
 
1059
        if (delta < min_res[cxidx])
 
1060
            min_res[cxidx] = delta;
 
1061
    }
 
1062
}
 
1063
 
 
1064
void do_average_per_cpu(int c)
 
1065
{
 
1066
    int i;
 
1067
    uint64_t tot[MAX_CX_NR] = { 0 };
 
1068
    uint64_t cnt[MAX_CX_NR] = { 0 };
 
1069
    uint64_t sum = 0;
 
1070
 
 
1071
    /* find Cx entry first */
 
1072
    i = 0;
 
1073
    while (i < evt_len[c] && evt[c][i].cx == 0)
 
1074
        i++;
 
1075
    /* check evt[c][i] and evt[c][i+1] */
 
1076
    while (i + 1 < evt_len[c]) {
 
1077
        uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc;
 
1078
        int cx = evt[c][i].cx;
 
1079
        tot[cx] += len;
 
1080
        cnt[cx]++;
 
1081
        sum += len;
 
1082
        i++;
 
1083
    }
 
1084
    /* prevent divide zero error */
 
1085
    if (!sum)
 
1086
        sum = 1;
 
1087
    /* print */
 
1088
    printf("CPU%d:\tResidency(ms)\t\tAvg Res(ms)\n", c);
 
1089
    for (i = 0; i < max_cx_num; i++) {
 
1090
        /* prevent divide zero error */
 
1091
        if (!cnt[i])
 
1092
            cnt[i] = 1;
 
1093
        printf("  C%d\t%"PRIu64"\t(%6.2f%%)\t%.2f\n", i,
 
1094
               tot[i]/tsc2ms, 100.0 * tot[i] / (double)sum,
 
1095
               (double)tot[i]/cnt[i]/tsc2ms );
 
1096
    }
 
1097
    printf("\n");
 
1098
}
 
1099
 
 
1100
void do_average(void)
 
1101
{
 
1102
    int i;
 
1103
 
 
1104
    for (i = 0; i < max_cpu_num; i++)
 
1105
        do_average_per_cpu(i);
 
1106
}
 
1107
 
 
1108
static void do_exp_ratio_per_cpu(int c)
 
1109
{
 
1110
    int i;
 
1111
    uint64_t expected[MAX_CX_NR] = { 0 }, sum[MAX_CX_NR] = { 0 };
 
1112
 
 
1113
    i = 0;
 
1114
    while (i < evt_len[c] && evt[c][i].cx == 0)
 
1115
        i++;
 
1116
    /* check evt[c][i] and evt[c][i+1] */
 
1117
    while (i + 1 < evt_len[c]) {
 
1118
        uint64_t len;
 
1119
        int cx;
 
1120
 
 
1121
        if ((evt[c][i].cx == 0 && evt[c][i+1].cx == 0) ||
 
1122
            (evt[c][i].cx > 0 && evt[c][i+1].cx > 0)) {
 
1123
            i++;
 
1124
            continue;
 
1125
        }
 
1126
        len = evt[c][i+1].tsc - evt[c][i].tsc;
 
1127
        cx = evt[c][i].cx;
 
1128
        if (cx > 0) {
 
1129
            if ((len/tsc2us) <= evt[c][i].expected)
 
1130
                expected[cx]++;
 
1131
            sum[cx]++;
 
1132
        }
 
1133
 
 
1134
        i++;
 
1135
    }
 
1136
    printf("********** CPU%d **********\n", c);
 
1137
    for (i = 1; i < max_cx_num; i++) {
 
1138
        if (sum[i] == 0)
 
1139
            printf("C%d\t0\t0\t00.00%%\n", i);
 
1140
        else
 
1141
            printf("C%d\t%"PRIu64"\t%"PRIu64"\t%4.2f%%\n",
 
1142
                   i, expected[i], sum[i], 100.0 * (double)expected[i]/(double)sum[i]);
 
1143
    }
 
1144
}
 
1145
 
 
1146
void do_exp_ratio(void)
 
1147
{
 
1148
    int i;
 
1149
 
 
1150
    if (!is_menu_gov_enabled) {
 
1151
        printf("The file seems doesn't consists the expected/predicted information.\n");
 
1152
        return;
 
1153
    }
 
1154
 
 
1155
    printf("Cx\tearly\ttot\tratio(%%)\n");
 
1156
    for (i = 0; i < max_cpu_num; i++)
 
1157
        do_exp_ratio_per_cpu(i);
 
1158
}
 
1159
 
 
1160
static void do_exp_pred_per_cpu(int c)
 
1161
{
 
1162
    int i;
 
1163
    uint64_t expected[MAX_CX_NR] = { 0 }, sum[MAX_CX_NR] = { 0 };
 
1164
 
 
1165
    i = 0;
 
1166
    while (i < evt_len[c] && evt[c][i].cx == 0)
 
1167
        i++;
 
1168
    /* check evt[c][i] and evt[c][i+1] */
 
1169
    while (i + 1 < evt_len[c]) {
 
1170
        int cx;
 
1171
 
 
1172
        if ((evt[c][i].cx == 0 && evt[c][i+1].cx == 0) ||
 
1173
            (evt[c][i].cx > 0 && evt[c][i+1].cx > 0)) {
 
1174
            i++;
 
1175
            continue;
 
1176
        }
 
1177
        cx = evt[c][i].cx;
 
1178
        if (cx > 0) {
 
1179
            if (evt[c][i].expected <= evt[c][i].predicted)
 
1180
                expected[cx]++;
 
1181
            sum[cx]++;
 
1182
        }
 
1183
 
 
1184
        i++;
 
1185
    }
 
1186
    printf("********** CPU%d **********\n", c);
 
1187
    for (i = 1; i < max_cx_num; i++) {
 
1188
        if (sum[i] == 0)
 
1189
            printf("C%d\t0\t0\t00.00%%\n", i);
 
1190
        else
 
1191
            printf("C%d\t%"PRIu64"\t%"PRIu64"\t%4.2f%%\n",
 
1192
                   i, expected[i], sum[i], 100.0 * (double)expected[i]/(double)sum[i]);
 
1193
    }
 
1194
}
 
1195
 
 
1196
void do_exp_pred(void)
 
1197
{
 
1198
    int i;
 
1199
 
 
1200
    if (!is_menu_gov_enabled) {
 
1201
        printf("The file seems doesn't consists the expected/predicted information.\n");
 
1202
        return;
 
1203
    }
 
1204
 
 
1205
    printf("Cx\texp\ttot\tratio(%%)\n");
 
1206
    for (i = 0; i < max_cpu_num; i++)
 
1207
        do_exp_pred_per_cpu(i);
 
1208
}
 
1209