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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [common/] [stats.c] - Blame information for rev 857

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

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

powered by: WebSVN 2.1.0

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