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

Subversion Repositories openrisc

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

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
  /* Specify each argument, with fallback values */
268
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
269
  help = arg_lit0 ("h", "help", "print this help message");
270
  mode_arg = arg_rex0 ("m", "mode",
271
                       "(detailed|d)|(pretty|p)|(access|a)|"
272
                       "(width|w)", "<m>", REG_ICASE,
273
                       "Output mode (detailed, pretty, access " "or width)");
274
  mode_arg->sval[0] = "detailed";
275
  group = arg_int0 ("g", "group", "<n>",
276
                    "group 2^n bits successive addresses " "together");
277
  group->ival[0] = 0;
278
  prof_file = arg_file0 ("f", "filename", "<file>",
279
                         "data file to analyse (default " "sim.mprofile)");
280
  prof_file->filename[0] = "sim.mprofile";
281
  from = arg_int1 (NULL, NULL, "<from>", "start address");
282
  to = arg_int1 (NULL, NULL, "<to>", "end address");
283
  end = arg_end (20);
284
 
285
  /* Set up the argument table */
286
  argtab[0] = vercop;
287
  argtab[1] = help;
288
  argtab[2] = mode_arg;
289
  argtab[3] = group;
290
  argtab[4] = prof_file;
291
  argtab[5] = from;
292
  argtab[6] = to;
293
  argtab[7] = end;
294
 
295
  /* If we are just asked for a help message, then we don't parse the
296
     args. This is used to implement the help function from the CLI. */
297
  if (just_help)
298
    {
299
      printf ("mprofile");
300
      arg_print_syntax (stdout, argtab, "\n");
301
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
302
 
303
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
304
      return 0;
305
    }
306
 
307
  /* Parse */
308
  nerrors = arg_parse (argc, argv, argtab);
309
 
310
  /* Special case here is if help or version is specified, we ignore any other
311
     errors and just print the help or version information and then give up. */
312
  if (vercop->count > 0)
313
    {
314
      PRINTF ("OpenRISC 1000 Memory Profiling Utility, version %s\n",
315
              PACKAGE_VERSION);
316
 
317
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
318
      return 0;
319
    }
320
 
321
  if (help->count > 0)
322
    {
323
      printf ("Usage: %s ", argv[0]);
324
      arg_print_syntax (stdout, argtab, "\n");
325
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
326
 
327
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
328
      return 0;
329
    }
330
 
331
  /* Deal with any errors */
332
  if (0 != nerrors)
333
    {
334
      arg_print_errors (stderr, end, "mprofile");
335
      fprintf (stderr, "Usage: %s ", argv[0]);
336
      arg_print_syntaxv (stderr, argtab, "\n");
337
 
338
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
339
      return 1;
340
    }
341
 
342
  /* If version or help is requested, that is all that is printed out */
343
  /* Sort out the mode */
344
  if ((0 == strcmp (mode_arg->sval[0], "detail")) ||
345
      (0 == strcmp (mode_arg->sval[0], "d")))
346
    {
347
      mode = MODE_DETAIL;
348
    }
349
  else if ((0 == strcmp (mode_arg->sval[0], "pretty")) ||
350
           (0 == strcmp (mode_arg->sval[0], "p")))
351
    {
352
      mode = MODE_DETAIL;
353
    }
354
  else if ((0 == strcmp (mode_arg->sval[0], "access")) ||
355
           (0 == strcmp (mode_arg->sval[0], "a")))
356
    {
357
      mode = MODE_DETAIL;
358
    }
359
  else if ((0 == strcmp (mode_arg->sval[0], "width")) ||
360
           (0 == strcmp (mode_arg->sval[0], "w")))
361
    {
362
      mode = MODE_DETAIL;
363
    }
364
  else
365
    {
366
      fprintf (stderr, "Impossible mode: %s\n", mode_arg->sval[0]);
367
    }
368
 
369
  /* Group bits */
370
  group_bits = group->ival[0];
371
 
372
  /* Start and end addresses */
373
  start_addr = from->ival[0];
374
  end_addr = to->ival[0];
375
 
376
  /* Get the profile */
377
  fprof = fopen (prof_file->filename[0], "rm");
378
 
379
  if (!fprof)
380
    {
381
      fprintf (stderr, "Cannot open profile file: %s\n",
382
               prof_file->filename[0]);
383
 
384
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
385
      return 1;
386
    }
387
 
388
  /* Finished with the args */
389
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
390
 
391
  init ();
392
  read_file (fprof, mode);
393
  fclose (fprof);
394
  printout (mode);
395
  return 0;
396
 
397
}       /* main_mprofiler () */

powered by: WebSVN 2.1.0

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