OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [or1ksim/] [mprofiler.c] - Blame information for rev 168

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

Line No. Rev Author Line
1 19 jeremybenn
/* mprofiler.c -- memory profiling utility
2
 
3
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
4
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
5
   Copyright (C) 2008 Embecosm Limited
6
 
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
23
 
24
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26
 
27
 
28
/* Autoconf and/or portability configuration */
29
#include "config.h"
30
#include "port.h"
31
 
32
/* System includes */
33
#include <stdlib.h>
34
#include <regex.h>
35
 
36
/* Package includes */
37
#include "mprofiler.h"
38
#include "sim-config.h"
39
#include "argtable2.h"
40
#include "support/profile.h"
41
 
42
/* output modes */
43
#define MODE_DETAIL     0
44
#define MODE_PRETTY     1
45
#define MODE_ACCESS     2
46
#define MODE_WIDTH      3
47
 
48
/* Input buffer size */
49
#define BUF_SIZE        256
50
 
51
/* HASH */
52
#define HASH_SIZE       0x10000
53
#define HASH_FUNC(x)    ((x) & 0xffff)
54
 
55
/*! Hash table data structure */
56
static struct memory_hash
57
{
58
  struct memory_hash *next;
59
  oraddr_t            addr;
60
  unsigned long       cnt[3];           /* Various counters */
61
} *hash[HASH_SIZE];
62
 
63
/*! Groups size -- how much addresses should be joined together */
64
static int  group_bits = 2;
65
 
66
/*! Start address */
67
static oraddr_t  start_addr = 0;
68
 
69
/*! End address */
70
static oraddr_t  end_addr = 0xffffffff;
71
 
72
/* File to read from */
73
static FILE *fprof = 0;
74
 
75
static void
76
hash_add (oraddr_t addr, int index)
77
{
78
  struct memory_hash *h = hash[HASH_FUNC (addr)];
79
  while (h && h->addr != addr)
80
    h = h->next;
81
 
82
  if (!h)
83
    {
84
      h = (struct memory_hash *) malloc (sizeof (struct memory_hash));
85
      h->next = hash[HASH_FUNC (addr)];
86
      hash[HASH_FUNC (addr)] = h;
87
      h->addr = addr;
88
      h->cnt[0] = h->cnt[1] = h->cnt[2] = 0;
89
    }
90
  h->cnt[index]++;
91
}
92
 
93
 
94
static unsigned long
95
hash_get (oraddr_t addr, int index)
96
{
97
  struct memory_hash *h = hash[HASH_FUNC (addr)];
98
  while (h && h->addr != addr)
99
    h = h->next;
100
 
101
  if (!h)
102
    return 0;
103
  return h->cnt[index];
104
}
105
 
106
static void
107
init ()
108
{
109
  int i;
110
  for (i = 0; i < HASH_SIZE; i++)
111
    hash[i] = NULL;
112
}
113
 
114
static void
115
read_file (FILE * f, int mode)
116
{
117
  struct mprofentry_struct buf[BUF_SIZE];
118
  int num_read;
119
  do
120
    {
121
      int i;
122
      num_read = fread (buf, sizeof (struct mprofentry_struct), BUF_SIZE, f);
123
      for (i = 0; i < num_read; i++)
124
        if (buf[i].addr >= start_addr && buf[i].addr <= end_addr)
125
          {
126
            int index;
127
            unsigned t = buf[i].type;
128
            if (t > 64)
129
              {
130
                PRINTF ("!");
131
                t = 0;
132
              }
133
            if (mode == MODE_WIDTH)
134
              t >>= 3;
135
            else
136
              t &= 0x7;
137
 
138
            switch (t)
139
              {
140
              case 1:
141
                index = 0;
142
                break;
143
              case 2:
144
                index = 1;
145
                break;
146
              case 4:
147
                index = 2;
148
                break;
149
              default:
150
                index = 0;
151
                PRINTF ("!!!!");
152
                break;
153
              }
154
            hash_add (buf[i].addr >> group_bits, index);
155
          }
156
    }
157
  while (num_read > 0);
158
}
159
 
160
static int
161
nbits (unsigned long a)
162
{
163
  int cnt = 0;
164
  int b = a;
165
  if (!a)
166
    return 0;
167
 
168
  while (a)
169
    a >>= 1, cnt++;
170
  if (cnt > 1 && ((b >> (cnt - 2)) & 1))
171
    cnt = cnt * 2 + 1;
172
  else
173
    cnt *= 2;
174
 
175
  return cnt - 1;
176
}
177
 
178
static void
179
printout (int mode)
180
{
181
  oraddr_t addr = start_addr & ~((1 << group_bits) - 1);
182
  PRINTF ("start = %" PRIxADDR " (%" PRIxADDR "); end = %" PRIxADDR
183
          "; group_bits = %08x\n", start_addr, addr, end_addr,
184
          (1 << group_bits) - 1);
185
  for (; addr <= end_addr; addr += (1 << group_bits))
186
    {
187
      int i;
188
      unsigned long a = hash_get (addr >> group_bits, 0);
189
      unsigned long b = hash_get (addr >> group_bits, 1);
190
      unsigned long c = hash_get (addr >> group_bits, 2);
191
      PRINTF ("%" PRIxADDR ":", addr);
192
      switch (mode)
193
        {
194
        case MODE_DETAIL:
195
          if (a)
196
            PRINTF (" %10li R", a);
197
          else
198
            PRINTF ("            R");
199
          if (b)
200
            PRINTF (" %10li W", b);
201
          else
202
            PRINTF ("            W");
203
          if (c)
204
            PRINTF (" %10li F", c);
205
          else
206
            PRINTF ("            F");
207
          break;
208
        case MODE_ACCESS:
209
          PRINTF (" %10li", a + b + c);
210
          break;
211
        case MODE_PRETTY:
212
          PRINTF (" %10li ", a + b + c);
213
          for (i = 0; i < nbits (a + b + c); i++)
214
            PRINTF ("#");
215
          break;
216
        case MODE_WIDTH:
217
          if (a)
218
            PRINTF (" %10li B", a);
219
          else
220
            PRINTF ("            B");
221
          if (b)
222
            PRINTF (" %10li H", b);
223
          else
224
            PRINTF ("            H");
225
          if (c)
226
            PRINTF (" %10li W", c);
227
          else
228
            PRINTF ("            W");
229
          break;
230
        }
231
      PRINTF ("\n");
232
      if (addr >= addr + (1 << group_bits))
233
        break;                  /* Overflow? */
234
    }
235
}
236
 
237
/*---------------------------------------------------------------------------*/
238
/*! Parse the arguments for the profiling utility
239
 
240
    Updated by Jeremy Bennett to use argtable2. Also has an option just to
241
    print help, for use with the CLI.
242
 
243
    @param[in] argc       Number of command args
244
    @param[in] argv       Vector of the command args
245
    @param[in] just_help  If 1 (true), ignore argc & argv and just print out
246
                          the help message without parsing args
247
 
248
    @return  0 on success, 1 on failure                                      */
249
/*---------------------------------------------------------------------------*/
250
int
251
main_mprofiler (int argc, char *argv[], int just_help)
252
{
253
  struct arg_lit *vercop;
254
  struct arg_lit *help;
255
  struct arg_rex *mode_arg;
256
  struct arg_int *group;
257
  struct arg_file *prof_file;
258
  struct arg_int *from;
259
  struct arg_int *to;
260
  struct arg_end *end;
261
 
262
  void *argtab[8];
263
  int nerrors;
264
 
265
  int mode = MODE_DETAIL;
266
 
267 88 jeremybenn
  /* Specify each argument, with fallback values.
268
 
269
     Bug 1710 (Vinay Patil) fixed. mode should allow REG_EXTENDED. */
270 19 jeremybenn
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
271
  help = arg_lit0 ("h", "help", "print this help message");
272
  mode_arg = arg_rex0 ("m", "mode",
273
                       "(detailed|d)|(pretty|p)|(access|a)|"
274 88 jeremybenn
                       "(width|w)", "<m>", REG_ICASE | REG_EXTENDED,
275 19 jeremybenn
                       "Output mode (detailed, pretty, access " "or width)");
276
  mode_arg->sval[0] = "detailed";
277
  group = arg_int0 ("g", "group", "<n>",
278
                    "group 2^n bits successive addresses " "together");
279
  group->ival[0] = 0;
280
  prof_file = arg_file0 ("f", "filename", "<file>",
281
                         "data file to analyse (default " "sim.mprofile)");
282
  prof_file->filename[0] = "sim.mprofile";
283
  from = arg_int1 (NULL, NULL, "<from>", "start address");
284
  to = arg_int1 (NULL, NULL, "<to>", "end address");
285
  end = arg_end (20);
286
 
287
  /* Set up the argument table */
288
  argtab[0] = vercop;
289
  argtab[1] = help;
290
  argtab[2] = mode_arg;
291
  argtab[3] = group;
292
  argtab[4] = prof_file;
293
  argtab[5] = from;
294
  argtab[6] = to;
295
  argtab[7] = end;
296
 
297
  /* If we are just asked for a help message, then we don't parse the
298
     args. This is used to implement the help function from the CLI. */
299
  if (just_help)
300
    {
301
      printf ("mprofile");
302
      arg_print_syntax (stdout, argtab, "\n");
303
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
304
 
305
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
306
      return 0;
307
    }
308
 
309
  /* Parse */
310
  nerrors = arg_parse (argc, argv, argtab);
311
 
312
  /* Special case here is if help or version is specified, we ignore any other
313
     errors and just print the help or version information and then give up. */
314
  if (vercop->count > 0)
315
    {
316
      PRINTF ("OpenRISC 1000 Memory Profiling Utility, version %s\n",
317
              PACKAGE_VERSION);
318
 
319
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
320
      return 0;
321
    }
322
 
323
  if (help->count > 0)
324
    {
325
      printf ("Usage: %s ", argv[0]);
326
      arg_print_syntax (stdout, argtab, "\n");
327
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
328
 
329
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
330
      return 0;
331
    }
332
 
333
  /* Deal with any errors */
334
  if (0 != nerrors)
335
    {
336
      arg_print_errors (stderr, end, "mprofile");
337
      fprintf (stderr, "Usage: %s ", argv[0]);
338
      arg_print_syntaxv (stderr, argtab, "\n");
339
 
340
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
341
      return 1;
342
    }
343
 
344 88 jeremybenn
  /* If version or help is requested, that is all that is printed out
345
     Sort out the mode.
346
 
347
     Bug 1710 fixed (Vinay Patil). Modes now set correctly (were all set to
348
     detail). */
349 19 jeremybenn
  if ((0 == strcmp (mode_arg->sval[0], "detail")) ||
350
      (0 == strcmp (mode_arg->sval[0], "d")))
351
    {
352
      mode = MODE_DETAIL;
353
    }
354
  else if ((0 == strcmp (mode_arg->sval[0], "pretty")) ||
355
           (0 == strcmp (mode_arg->sval[0], "p")))
356
    {
357 88 jeremybenn
      mode = MODE_PRETTY;
358 19 jeremybenn
    }
359
  else if ((0 == strcmp (mode_arg->sval[0], "access")) ||
360
           (0 == strcmp (mode_arg->sval[0], "a")))
361
    {
362 88 jeremybenn
      mode = MODE_ACCESS;
363 19 jeremybenn
    }
364
  else if ((0 == strcmp (mode_arg->sval[0], "width")) ||
365
           (0 == strcmp (mode_arg->sval[0], "w")))
366
    {
367 88 jeremybenn
      mode = MODE_WIDTH;
368 19 jeremybenn
    }
369
  else
370
    {
371
      fprintf (stderr, "Impossible mode: %s\n", mode_arg->sval[0]);
372
    }
373
 
374
  /* Group bits */
375
  group_bits = group->ival[0];
376
 
377
  /* Start and end addresses */
378
  start_addr = from->ival[0];
379
  end_addr = to->ival[0];
380
 
381
  /* Get the profile */
382
  fprof = fopen (prof_file->filename[0], "rm");
383
 
384
  if (!fprof)
385
    {
386
      fprintf (stderr, "Cannot open profile file: %s\n",
387
               prof_file->filename[0]);
388
 
389
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
390
      return 1;
391
    }
392
 
393
  /* Finished with the args */
394
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
395
 
396
  init ();
397
  read_file (fprof, mode);
398
  fclose (fprof);
399
  printout (mode);
400
  return 0;
401
 
402
}       /* main_mprofiler () */

powered by: WebSVN 2.1.0

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