OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [cpu/] [common/] [stats.c] - Blame information for rev 1748

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 cvs
/* stats.c -- Various statistics about instruction scheduling etc.
2 1748 jeremybenn
 
3 2 cvs
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
5 2 cvs
 
6 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7 2 cvs
 
8 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9 2 cvs
 
10 1748 jeremybenn
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14 2 cvs
 
15 1748 jeremybenn
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19 2 cvs
 
20 1748 jeremybenn
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22 2 cvs
 
23 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25 1350 nogj
 
26
 
27 1748 jeremybenn
/* Autoconf and/or portability configuration */
28
#include "config.h"
29 1350 nogj
#include "port.h"
30 1748 jeremybenn
 
31
/* Package includes */
32
#include "stats.h"
33 102 lampret
#include "sim-config.h"
34 1748 jeremybenn
#include "icache-model.h"
35
#include "spr-defs.h"
36 1308 phoenix
#include "execute.h"
37 30 lampret
 
38 1748 jeremybenn
 
39
#define DSTATS_LEN      3000
40
#define SSTATS_LEN      300
41
#define FSTATS_LEN      200
42
#define RAW_RANGE       1000
43
 
44
/* Used by safe division - increment divisor by one if it is zero */
45
#define SD(X) (X != 0 ? X : 1)
46
 
47
struct branchstat
48
{
49
  int taken;
50
  int nottaken;
51
  int forward;
52
  int backward;
53 535 markom
};
54 2 cvs
 
55 1748 jeremybenn
/*! @see also enum insn_type in abstract.h */
56
static const char func_unit_str[30][30] = {
57
  "unknown",
58
  "exception",
59
  "arith",
60
  "shift",
61
  "compare",
62
  "branch",
63
  "jump",
64
  "load",
65
  "store",
66
  "movimm",
67
  "move",
68
  "extend",
69
  "nop",
70
  "mac"
71
};
72 535 markom
 
73 1748 jeremybenn
struct dstats_entry
74
{
75
  int insn1;
76
  int insn2;
77
  int cnt_dynamic;
78
  int depend;
79
};                              /*!< double stats */
80 2 cvs
 
81 1748 jeremybenn
struct sstats_entry
82 2 cvs
{
83 1748 jeremybenn
  int insn;
84
  int cnt_dynamic;
85
};                              /*!< single stats */
86
 
87
struct fstats_entry
88
{
89
  enum insn_type insn1;
90
  enum insn_type insn2;
91
  int cnt_dynamic;
92
  int depend;
93
};                              /*!< functional units stats */
94
 
95
struct raw_stats
96
{
97
  int reg[64];
98
  int range[RAW_RANGE];
99
};                              /*!< RAW hazard stats */
100
 
101
/* Globally visible statistics data. Renamed mstats to or1k_mstats because Mac
102
   OS X has a lib function called mstats */
103
struct mstats_entry      or1k_mstats = { 0 };    /*!< misc units stats */
104
struct cachestats_entry  ic_stats    = { 0 };    /*!< instruction cache stats */
105
struct cachestats_entry  dc_stats    = { 0 };    /*!< data cache stats */
106
struct immustats_entry   immu_stats  = { 0 };    /*!< insn MMU stats */
107
struct dmmustats_entry   dmmu_stats  = { 0 };    /*!< data MMU stats */
108
 
109
/* Statistics data strutures used just here */
110
static struct dstats_entry  dstats[DSTATS_LEN]; /*!< dependency stats */
111
static struct sstats_entry  sstats[SSTATS_LEN]; /*!< single stats */
112
static struct fstats_entry  fstats[FSTATS_LEN]; /*!< func units stats */
113
static struct raw_stats     raw_stats;          /*!< RAW hazard stats */
114
 
115
 
116
void
117
addsstats (int item, int cnt_dynamic)
118
{
119 532 markom
  int i = 0;
120 2 cvs
 
121 1748 jeremybenn
  while (sstats[i].insn != item && sstats[i].insn >= 0 && i < SSTATS_LEN)
122
    i++;
123
 
124
  if (i >= SSTATS_LEN - 1)
125
    return;
126
 
127
  if (sstats[i].insn >= 0)
128
    {
129
      sstats[i].cnt_dynamic += cnt_dynamic;
130
    }
131
  else
132
    {
133
      sstats[i].insn = item;
134
      sstats[i].cnt_dynamic = cnt_dynamic;
135
    }
136 2 cvs
}
137
 
138 1748 jeremybenn
void
139
adddstats (int item1, int item2, int cnt_dynamic, int depend)
140 2 cvs
{
141 532 markom
  int i = 0;
142 2 cvs
 
143 1748 jeremybenn
  while ((dstats[i].insn1 != item1 || dstats[i].insn2 != item2)
144
         && (i < DSTATS_LEN) && dstats[i].insn1 >= 0)
145
    i++;
146
 
147
  if (i >= DSTATS_LEN - 1)
148
    return;
149
 
150
  if (dstats[i].insn1 >= 0)
151
    {
152
      dstats[i].cnt_dynamic += cnt_dynamic;
153
      dstats[i].depend += depend;
154
    }
155
  else
156
    {
157
      dstats[i].insn1 = item1;
158
      dstats[i].insn2 = item2;
159
      dstats[i].cnt_dynamic = cnt_dynamic;
160
      dstats[i].depend = depend;
161
    }
162 2 cvs
}
163
 
164 1748 jeremybenn
void
165
addfstats (enum insn_type item1, enum insn_type item2, int cnt_dynamic,
166
           int depend)
167 2 cvs
{
168 532 markom
  int i = 0;
169 1748 jeremybenn
 
170
  while (((fstats[i].insn1 != item1) || (fstats[i].insn2 != item2)) &&
171
         (fstats[i].insn1 != it_unknown) && (i < FSTATS_LEN))
172 532 markom
    i++;
173 2 cvs
 
174 1748 jeremybenn
  if (i >= FSTATS_LEN - 1)
175
    return;
176
 
177
  if ((fstats[i].insn1 == item1) && (fstats[i].insn2 == item2))
178
    {
179
      fstats[i].cnt_dynamic += cnt_dynamic;
180
      fstats[i].depend += depend;
181
    }
182
  else
183
    {
184
      fstats[i].insn1 = item1;
185
      fstats[i].insn2 = item2;
186
      fstats[i].cnt_dynamic = cnt_dynamic;
187
      fstats[i].depend = depend;
188
    }
189 2 cvs
}
190
 
191 1748 jeremybenn
void
192
initstats ()
193 2 cvs
{
194 535 markom
  int i;
195 1748 jeremybenn
  memset (sstats, 0, sizeof (sstats));
196 1323 phoenix
  for (i = 0; i < SSTATS_LEN; i++)
197 535 markom
    sstats[i].insn = -1;
198 1748 jeremybenn
  memset (dstats, 0, sizeof (dstats));
199 535 markom
  for (i = 0; i < DSTATS_LEN; i++)
200
    dstats[i].insn1 = dstats[i].insn2 = -1;
201 1748 jeremybenn
  memset (fstats, 0, sizeof (fstats));
202
  memset (&or1k_mstats, 0, sizeof (or1k_mstats));
203
  memset (&ic_stats, 0, sizeof (ic_stats));
204
  memset (&dc_stats, 0, sizeof (dc_stats));
205
  memset (&raw_stats, 0, sizeof (raw_stats));
206 2 cvs
}
207
 
208 1748 jeremybenn
static void
209
printotherstats (int which)
210 2 cvs
{
211 1748 jeremybenn
  PRINTF ("\n");
212
  if (config.bpb.enabled)
213
    {
214
      struct branchstat bf;
215
      struct branchstat bnf;
216
      long bf_all, bnf_all;
217
      bf.taken = or1k_mstats.bf[1][0] + or1k_mstats.bf[1][1];
218
      bf.nottaken = or1k_mstats.bf[0][0] + or1k_mstats.bf[0][1];
219
      bf.forward = or1k_mstats.bf[0][1] + or1k_mstats.bf[1][1];
220
      bf.backward = or1k_mstats.bf[0][0] + or1k_mstats.bf[1][0];
221
      bf_all = bf.forward + bf.backward;
222 102 lampret
 
223 1748 jeremybenn
      bnf.taken = or1k_mstats.bnf[1][0] + or1k_mstats.bf[1][1];
224
      bnf.nottaken = or1k_mstats.bnf[0][0] + or1k_mstats.bf[0][1];
225
      bnf.forward = or1k_mstats.bnf[0][1] + or1k_mstats.bf[1][1];
226
      bnf.backward = or1k_mstats.bnf[0][0] + or1k_mstats.bf[1][0];
227
      bnf_all = bnf.forward + bnf.backward;
228 556 markom
 
229 1748 jeremybenn
      PRINTF ("bnf: %d (%ld%%) taken,", bf.taken,
230
              (bf.taken * 100) / SD (bf_all));
231
      PRINTF (" %d (%ld%%) not taken,", bf.nottaken,
232
              (bf.nottaken * 100) / SD (bf_all));
233
      PRINTF (" %d (%ld%%) forward,", bf.forward,
234
              (bf.forward * 100) / SD (bf_all));
235
      PRINTF (" %d (%ld%%) backward\n", bf.backward,
236
              (bf.backward * 100) / SD (bf_all));
237
      PRINTF ("bf: %d (%ld%%) taken,", bnf.taken,
238
              (bnf.taken * 100) / SD (bnf_all));
239
      PRINTF (" %d (%ld%%) not taken,", bnf.nottaken,
240
              (bnf.nottaken * 100) / SD (bnf_all));
241
      PRINTF (" %d (%ld%%) forward,", bnf.forward,
242
              (bnf.forward * 100) / SD (bnf_all));
243
      PRINTF (" %d (%ld%%) backward\n", bnf.backward,
244
              (bnf.backward * 100) / SD (bnf_all));
245 102 lampret
 
246 1748 jeremybenn
      PRINTF ("StaticBP bnf(%s): correct %ld%%\n",
247
              config.bpb.sbp_bnf_fwd ? "forward" : "backward",
248
              (or1k_mstats.bnf[0][config.bpb.sbp_bnf_fwd] * 100) /
249
              SD (bnf_all));
250
      PRINTF ("StaticBP bf(%s): correct %ld%%\n",
251
              config.bpb.sbp_bf_fwd ? "forward" : "backward",
252
              (or1k_mstats.bnf[1][config.bpb.sbp_bf_fwd] * 100) /
253
              SD (bf_all));
254
      PRINTF ("BPB: hit %d (correct %d%%), miss %d\n", or1k_mstats.bpb.hit,
255
              (or1k_mstats.bpb.correct * 100) / SD (or1k_mstats.bpb.hit),
256
              or1k_mstats.bpb.miss);
257
    }
258
  else
259
    PRINTF ("BPB simulation disabled. Enable it to see BPB analysis\n");
260 102 lampret
 
261 1748 jeremybenn
  if (config.bpb.btic)
262
    {
263
      PRINTF ("BTIC: hit %d(%d%%), miss %d\n", or1k_mstats.btic.hit,
264
              (or1k_mstats.btic.hit * 100) / SD (or1k_mstats.btic.hit +
265
                                                 or1k_mstats.btic.miss),
266
              or1k_mstats.btic.miss);
267
    }
268
  else
269
    PRINTF ("BTIC simulation disabled. Enabled it to see BTIC analysis\n");
270
 
271
  if (ic_state->enabled)
272
    {
273
      PRINTF ("IC read:  hit %d(%d%%), miss %d\n", ic_stats.readhit,
274
              (ic_stats.readhit * 100) / SD (ic_stats.readhit +
275
                                             ic_stats.readmiss),
276
              ic_stats.readmiss);
277
    }
278
  else
279
    PRINTF ("No ICache. Enable it to see IC results.\n");
280
 
281
  if (config.dc.enabled)
282
    {
283
      PRINTF ("DC read:  hit %d(%d%%), miss %d\n", dc_stats.readhit,
284
              (dc_stats.readhit * 100) / SD (dc_stats.readhit +
285
                                             dc_stats.readmiss),
286
              dc_stats.readmiss);
287
      PRINTF ("DC write: hit %d(%d%%), miss %d\n", dc_stats.writehit,
288
              (dc_stats.writehit * 100) / SD (dc_stats.writehit +
289
                                              dc_stats.writemiss),
290
              dc_stats.writemiss);
291
    }
292
  else
293
    PRINTF ("No DCache. Enable it to see DC results.\n");
294
 
295
  if (cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)
296
    {
297
      PRINTF ("IMMU read:  hit %d(%d%%), miss %d\n", immu_stats.fetch_tlbhit,
298
              (immu_stats.fetch_tlbhit * 100) / SD (immu_stats.fetch_tlbhit +
299
                                                    immu_stats.fetch_tlbmiss),
300
              immu_stats.fetch_tlbmiss);
301
    }
302
  else
303
    PRINTF ("No IMMU. Set UPR[IMP]\n");
304
 
305
  if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DMP)
306
    {
307
      PRINTF ("DMMU read:  hit %d(%d%%), miss %d\n", dmmu_stats.loads_tlbhit,
308
              (dmmu_stats.loads_tlbhit * 100) / SD (dmmu_stats.loads_tlbhit +
309
                                                    dmmu_stats.loads_tlbmiss),
310
              dmmu_stats.loads_tlbmiss);
311
    }
312
  else
313
    PRINTF ("No DMMU. Set UPR[DMP]\n");
314
 
315
  PRINTF ("Additional LOAD CYCLES: %u  STORE CYCLES: %u\n",
316
          runtime.sim.loadcycles, runtime.sim.storecycles);
317 102 lampret
}
318
 
319 1748 jeremybenn
void
320
printstats (int which)
321 102 lampret
{
322 535 markom
  int i, all = 0, dependall = 0;
323
 
324 1748 jeremybenn
  if (which > 1 && which <= 5 && !config.cpu.dependstats)
325
    {
326
      PRINTF
327
        ("Hazard analysis disabled. Enable it to see analysis results.\n");
328
      return;
329
    }
330 535 markom
 
331 1748 jeremybenn
  switch (which)
332
    {
333
    case 1:
334
      PRINTF ("stats 1: Misc stats\n");
335
      printotherstats (which);
336
      break;
337
    case 2:
338
      PRINTF ("stats 2: Instruction usage\n");
339
      for (i = 0; i < SSTATS_LEN; i++)
340
        all += sstats[i].cnt_dynamic;
341
 
342
      for (i = 0; i < SSTATS_LEN; i++)
343
        if (sstats[i].cnt_dynamic)
344
          PRINTF ("  %-15s used %6dx (%5.1f%%)\n", insn_name (sstats[i].insn),
345
                  sstats[i].cnt_dynamic,
346
                  (sstats[i].cnt_dynamic * 100.) / SD (all));
347
 
348
      PRINTF ("%d instructions (dynamic, single stats)\n", all);
349
      break;
350
 
351
    case 3:
352
      PRINTF ("stats 3: Instruction dependencies\n");
353
      for (i = 0; i < DSTATS_LEN; i++)
354
        {
355
          all += dstats[i].cnt_dynamic;
356
          dependall += dstats[i].depend;
357
        }
358
 
359
      for (i = 0; i < DSTATS_LEN; i++)
360
        if (dstats[i].cnt_dynamic)
361
          {
362
            char temp[100];
363
            sprintf (temp, "%s, %s ", insn_name (dstats[i].insn1),
364
                     insn_name (dstats[i].insn2));
365
            PRINTF ("  %-30s %6dx (%5.1f%%)", temp, dstats[i].cnt_dynamic,
366
                    (dstats[i].cnt_dynamic * 100.) / SD (all));
367
            PRINTF ("   depend: %5.1f%%\n",
368
                    (dstats[i].depend * 100.) / dstats[i].cnt_dynamic);
369
          }
370
 
371
      PRINTF ("%d instructions (dynamic, dependency stats)  depend: %d%%\n",
372
              all, (dependall * 100) / SD (all));
373
      break;
374
 
375
    case 4:
376
      PRINTF ("stats 4: Functional units dependencies\n");
377
      for (i = 0; i < FSTATS_LEN; i++)
378
        {
379
          all += fstats[i].cnt_dynamic;
380
          dependall += fstats[i].depend;
381
        }
382
 
383
      for (i = 0; i < FSTATS_LEN; i++)
384
        if (fstats[i].cnt_dynamic)
385
          {
386
            char temp[100];
387
            sprintf (temp, "%s, %s", func_unit_str[fstats[i].insn1],
388
                     func_unit_str[fstats[i].insn2]);
389
            PRINTF ("  %-30s %6dx (%5.1f%%)", temp, fstats[i].cnt_dynamic,
390
                    (fstats[i].cnt_dynamic * 100.) / SD (all));
391
            PRINTF ("   depend: %5.1f%%\n",
392
                    (fstats[i].depend * 100.) / fstats[i].cnt_dynamic);
393
          }
394
      PRINTF
395
        ("%d instructions (dynamic, functional units stats)  depend: %d%%\n\n",
396
         all, (dependall * 100) / SD (all));
397
      break;
398
 
399
    case 5:
400
      PRINTF ("stats 5: Raw register usage over time\n");
401 713 markom
#if RAW_RANGE_STATS
402 1748 jeremybenn
      for (i = 0; (i < MAX_RANGE); i++)
403
        PRINTF ("  Register set and reused in %d. cycle: %d cases\n", i,
404
                raw_stats.range[i]);
405 713 markom
#endif
406 1748 jeremybenn
      break;
407
    case 6:
408
      if (config.cpu.sbuf_len)
409
        {
410
          extern int sbuf_total_cyc, sbuf_wait_cyc;
411
          PRINTF ("stats 6: Store buffer analysis\n");
412
          PRINTF ("Using store buffer of length %i.\n", config.cpu.sbuf_len);
413
          PRINTF ("Number of total memory store cycles: %i/%lli\n",
414
                  sbuf_total_cyc,
415
                  runtime.sim.cycles + sbuf_total_cyc - sbuf_wait_cyc);
416
          PRINTF ("Number of cycles waiting for memory stores: %i\n",
417
                  sbuf_wait_cyc);
418
          PRINTF ("Number of memory cycles spared: %i\n",
419
                  sbuf_total_cyc - sbuf_wait_cyc);
420
          PRINTF ("Store speedup %3.2f%%, total speedup %3.2f%%\n",
421
                  100. * (sbuf_total_cyc - sbuf_wait_cyc) / sbuf_total_cyc,
422
                  100. * (sbuf_total_cyc -
423
                          sbuf_wait_cyc) / (runtime.sim.cycles +
424
                                            sbuf_total_cyc - sbuf_wait_cyc));
425
        }
426
      else
427
        PRINTF
428
          ("Store buffer analysis disabled. Enable it to see analysis results.\n");
429
      break;
430
    default:
431
      PRINTF ("Please specify a stats group (1-6).\n");
432
      break;
433
    }
434 102 lampret
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.