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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [mprofiler.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 547 markom
/* mprofiler.c -- memory profiling utility
2 1748 jeremybenn
 
3 547 markom
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
4 1748 jeremybenn
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
5
   Copyright (C) 2008 Embecosm Limited
6 547 markom
 
7 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8 547 markom
 
9 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10 547 markom
 
11 1748 jeremybenn
   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 547 markom
 
16 1748 jeremybenn
   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 547 markom
 
21 1748 jeremybenn
   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 547 markom
 
24 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26 1242 hpanther
 
27 1748 jeremybenn
 
28
/* Autoconf and/or portability configuration */
29
#include "config.h"
30
#include "port.h"
31
 
32
/* System includes */
33 1308 phoenix
#include <stdlib.h>
34 1748 jeremybenn
#include <regex.h>
35 1350 nogj
 
36 1748 jeremybenn
/* Package includes */
37 632 ivang
#include "mprofiler.h"
38 997 markom
#include "sim-config.h"
39 1748 jeremybenn
#include "argtable2.h"
40
#include "support/profile.h"
41 547 markom
 
42 1748 jeremybenn
/* 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 547 markom
  struct memory_hash *next;
59 1748 jeremybenn
  oraddr_t            addr;
60
  unsigned long       cnt[3];           /* Various counters */
61 547 markom
} *hash[HASH_SIZE];
62
 
63 1748 jeremybenn
/*! Groups size -- how much addresses should be joined together */
64
static int  group_bits = 2;
65 547 markom
 
66 1748 jeremybenn
/*! Start address */
67
static oraddr_t  start_addr = 0;
68 547 markom
 
69 1748 jeremybenn
/*! End address */
70
static oraddr_t  end_addr = 0xffffffff;
71 547 markom
 
72
/* File to read from */
73
static FILE *fprof = 0;
74
 
75 1748 jeremybenn
static void
76
hash_add (oraddr_t addr, int index)
77 547 markom
{
78 1748 jeremybenn
  struct memory_hash *h = hash[HASH_FUNC (addr)];
79
  while (h && h->addr != addr)
80
    h = h->next;
81 547 markom
 
82 1748 jeremybenn
  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 547 markom
  h->cnt[index]++;
91
}
92
 
93 1748 jeremybenn
 
94
static unsigned long
95
hash_get (oraddr_t addr, int index)
96 547 markom
{
97 1748 jeremybenn
  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 547 markom
  return h->cnt[index];
104
}
105
 
106 1748 jeremybenn
static void
107
init ()
108 547 markom
{
109
  int i;
110
  for (i = 0; i < HASH_SIZE; i++)
111
    hash[i] = NULL;
112
}
113
 
114 1748 jeremybenn
static void
115
read_file (FILE * f, int mode)
116 547 markom
{
117
  struct mprofentry_struct buf[BUF_SIZE];
118
  int num_read;
119 1748 jeremybenn
  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 548 markom
 
138 1748 jeremybenn
            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 547 markom
    }
157 1748 jeremybenn
  while (num_read > 0);
158 547 markom
}
159
 
160 1748 jeremybenn
static int
161
nbits (unsigned long a)
162 547 markom
{
163
  int cnt = 0;
164
  int b = a;
165 1748 jeremybenn
  if (!a)
166
    return 0;
167
 
168
  while (a)
169
    a >>= 1, cnt++;
170 547 markom
  if (cnt > 1 && ((b >> (cnt - 2)) & 1))
171
    cnt = cnt * 2 + 1;
172
  else
173
    cnt *= 2;
174 1748 jeremybenn
 
175 547 markom
  return cnt - 1;
176
}
177
 
178 1748 jeremybenn
static void
179
printout (int mode)
180 547 markom
{
181 1350 nogj
  oraddr_t addr = start_addr & ~((1 << group_bits) - 1);
182 1748 jeremybenn
  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 547 markom
    }
235
}
236
 
237 1748 jeremybenn
/*---------------------------------------------------------------------------*/
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 547 markom
{
253 1748 jeremybenn
  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 847 markom
  int mode = MODE_DETAIL;
266 547 markom
 
267 1748 jeremybenn
  /* 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 847 markom
      return 0;
305 547 markom
    }
306
 
307 1748 jeremybenn
  /* Parse */
308
  nerrors = arg_parse (argc, argv, argtab);
309 547 markom
 
310 1748 jeremybenn
  /* 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 547 markom
  init ();
392
  read_file (fprof, mode);
393
  fclose (fprof);
394
  printout (mode);
395
  return 0;
396 1748 jeremybenn
 
397
}       /* main_mprofiler () */

powered by: WebSVN 2.1.0

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