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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [sim/] [common/] [sim-profile.c] - Blame information for rev 107

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

Line No. Rev Author Line
1 106 markom
/* Default profiling support.
2
   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3
   Contributed by Cygnus Support.
4
 
5
This file is part of GDB, the GNU debugger.
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License along
18
with this program; if not, write to the Free Software Foundation, Inc.,
19
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include "sim-main.h"
22
#include "sim-io.h"
23
#include "sim-options.h"
24
#include "sim-assert.h"
25
 
26
#ifdef HAVE_STDLIB_H
27
#include <stdlib.h>
28
#endif
29
 
30
#ifdef HAVE_STRING_H
31
#include <string.h>
32
#else
33
#ifdef HAVE_STRINGS_H
34
#include <strings.h>
35
#endif
36
#endif
37
 
38
#define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
39
 
40
static MODULE_INIT_FN profile_init;
41
static MODULE_UNINSTALL_FN profile_uninstall;
42
 
43
static DECLARE_OPTION_HANDLER (profile_option_handler);
44
 
45
enum {
46
  OPTION_PROFILE_INSN = OPTION_START,
47
  OPTION_PROFILE_MEMORY,
48
  OPTION_PROFILE_MODEL,
49
  OPTION_PROFILE_FILE,
50
  OPTION_PROFILE_CORE,
51
  OPTION_PROFILE_PC,
52
  OPTION_PROFILE_PC_RANGE,
53
  OPTION_PROFILE_PC_GRANULARITY,
54
  OPTION_PROFILE_RANGE,
55
  OPTION_PROFILE_FUNCTION
56
};
57
 
58
static const OPTION profile_options[] = {
59
  { {"profile", optional_argument, NULL, 'p'},
60
      'p', "on|off", "Perform profiling",
61
      profile_option_handler },
62
  { {"profile-insn", optional_argument, NULL, OPTION_PROFILE_INSN},
63
      '\0', "on|off", "Perform instruction profiling",
64
      profile_option_handler },
65
  { {"profile-memory", optional_argument, NULL, OPTION_PROFILE_MEMORY},
66
      '\0', "on|off", "Perform memory profiling",
67
      profile_option_handler },
68
  { {"profile-core", optional_argument, NULL, OPTION_PROFILE_CORE},
69
      '\0', "on|off", "Perform CORE profiling",
70
      profile_option_handler },
71
  { {"profile-model", optional_argument, NULL, OPTION_PROFILE_MODEL},
72
      '\0', "on|off", "Perform model profiling",
73
      profile_option_handler },
74
 
75
  { {"profile-file", required_argument, NULL, OPTION_PROFILE_FILE},
76
      '\0', "FILE NAME", "Specify profile output file",
77
      profile_option_handler },
78
 
79
  { {"profile-pc", optional_argument, NULL, OPTION_PROFILE_PC},
80
      '\0', "on|off", "Perform PC profiling",
81
      profile_option_handler },
82
  { {"profile-pc-frequency", required_argument, NULL, 'F'},
83
      'F', "PC PROFILE FREQUENCY", "Specified PC profiling frequency",
84
      profile_option_handler },
85
  { {"profile-pc-size", required_argument, NULL, 'S'},
86
      'S', "PC PROFILE SIZE", "Specify PC profiling size",
87
      profile_option_handler },
88
  { {"profile-pc-granularity", required_argument, NULL, OPTION_PROFILE_PC_GRANULARITY},
89
      '\0', "PC PROFILE GRANULARITY", "Specify PC profiling sample coverage",
90
      profile_option_handler },
91
  { {"profile-pc-range", required_argument, NULL, OPTION_PROFILE_PC_RANGE},
92
      '\0', "BASE,BOUND", "Specify PC profiling address range",
93
      profile_option_handler },
94
 
95
#ifdef SIM_HAVE_ADDR_RANGE
96
  { {"profile-range", required_argument, NULL, OPTION_PROFILE_RANGE},
97
      '\0', "START,END", "Specify range of addresses for instruction and model profiling",
98
      profile_option_handler },
99
#if 0 /*wip*/
100
  { {"profile-function", required_argument, NULL, OPTION_PROFILE_FUNCTION},
101
      '\0', "FUNCTION", "Specify function to profile",
102
      profile_option_handler },
103
#endif
104
#endif
105
 
106
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
107
};
108
 
109
/* Set/reset the profile options indicated in MASK.  */
110
 
111
SIM_RC
112
set_profile_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg)
113
{
114
  int profile_nr;
115
  int cpu_nr;
116
  int profile_val = 1;
117
 
118
  if (arg != NULL)
119
    {
120
      if (strcmp (arg, "yes") == 0
121
          || strcmp (arg, "on") == 0
122
          || strcmp (arg, "1") == 0)
123
        profile_val = 1;
124
      else if (strcmp (arg, "no") == 0
125
               || strcmp (arg, "off") == 0
126
               || strcmp (arg, "0") == 0)
127
        profile_val = 0;
128
      else
129
        {
130
          sim_io_eprintf (sd, "Argument `%s' for `--profile%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name);
131
          return SIM_RC_FAIL;
132
        }
133
    }
134
 
135
  /* update applicable profile bits */
136
  for (profile_nr = 0; profile_nr < MAX_PROFILE_VALUES; ++profile_nr)
137
    {
138
      if ((mask & (1 << profile_nr)) == 0)
139
        continue;
140
 
141
#if 0 /* see sim-trace.c, set flags in STATE here if/when there are any */
142
      /* Set non-cpu specific values.  */
143
      switch (profile_nr)
144
        {
145
        case ??? :
146
          break;
147
        }
148
#endif
149
 
150
      /* Set cpu values.  */
151
      for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
152
        {
153
          CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[profile_nr] = profile_val;
154
        }
155
    }
156
 
157
  /* Re-compute the cpu profile summary.  */
158
  if (profile_val)
159
    {
160
      for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
161
        CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1;
162
    }
163
  else
164
    {
165
      for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
166
        {
167
          CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 0;
168
          for (profile_nr = 0; profile_nr < MAX_PROFILE_VALUES; ++profile_nr)
169
            {
170
              if (CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[profile_nr])
171
                {
172
                  CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1;
173
                  break;
174
                }
175
            }
176
        }
177
    }
178
 
179
  return SIM_RC_OK;
180
}
181
 
182
/* Set one profile option based on its IDX value.
183
   Not static as cgen-scache.c uses it.  */
184
 
185
SIM_RC
186
sim_profile_set_option (SIM_DESC sd, const char *name, int idx, const char *arg)
187
{
188
  return set_profile_option_mask (sd, name, 1 << idx, arg);
189
}
190
 
191
static SIM_RC
192
profile_option_handler (SIM_DESC sd,
193
                        sim_cpu *cpu,
194
                        int opt,
195
                        char *arg,
196
                        int is_command)
197
{
198
  int cpu_nr,prof_nr;
199
 
200
  /* FIXME: Need to handle `cpu' arg.  */
201
 
202
  switch (opt)
203
    {
204
    case 'p' :
205
      if (! WITH_PROFILE)
206
        sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n");
207
      else
208
        return set_profile_option_mask (sd, "profile", PROFILE_USEFUL_MASK,
209
                                        arg);
210
      break;
211
 
212
    case OPTION_PROFILE_INSN :
213
      if (WITH_PROFILE_INSN_P)
214
        return sim_profile_set_option (sd, "-insn", PROFILE_INSN_IDX, arg);
215
      else
216
        sim_io_eprintf (sd, "Instruction profiling not compiled in, `--profile-insn' ignored\n");
217
      break;
218
 
219
    case OPTION_PROFILE_MEMORY :
220
      if (WITH_PROFILE_MEMORY_P)
221
        return sim_profile_set_option (sd, "-memory", PROFILE_MEMORY_IDX, arg);
222
      else
223
        sim_io_eprintf (sd, "Memory profiling not compiled in, `--profile-memory' ignored\n");
224
      break;
225
 
226
    case OPTION_PROFILE_CORE :
227
      if (WITH_PROFILE_CORE_P)
228
        return sim_profile_set_option (sd, "-core", PROFILE_CORE_IDX, arg);
229
      else
230
        sim_io_eprintf (sd, "CORE profiling not compiled in, `--profile-core' ignored\n");
231
      break;
232
 
233
    case OPTION_PROFILE_MODEL :
234
      if (WITH_PROFILE_MODEL_P)
235
        return sim_profile_set_option (sd, "-model", PROFILE_MODEL_IDX, arg);
236
      else
237
        sim_io_eprintf (sd, "Model profiling not compiled in, `--profile-model' ignored\n");
238
      break;
239
 
240
    case OPTION_PROFILE_FILE :
241
      /* FIXME: Might want this to apply to pc profiling only,
242
         or have two profile file options.  */
243
      if (! WITH_PROFILE)
244
        sim_io_eprintf (sd, "Profiling not compiled in, `--profile-file' ignored\n");
245
      else
246
        {
247
          FILE *f = fopen (arg, "w");
248
 
249
          if (f == NULL)
250
            {
251
              sim_io_eprintf (sd, "Unable to open profile output file `%s'\n", arg);
252
              return SIM_RC_FAIL;
253
            }
254
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
255
            PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = f;
256
        }
257
      break;
258
 
259
    case OPTION_PROFILE_PC:
260
      if (WITH_PROFILE_PC_P)
261
        return sim_profile_set_option (sd, "-pc", PROFILE_PC_IDX, arg);
262
      else
263
        sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc' ignored\n");
264
      break;
265
 
266
    case 'F' :
267
      if (WITH_PROFILE_PC_P)
268
        {
269
          /* FIXME: Validate arg.  */
270
          int val = atoi (arg);
271
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
272
            PROFILE_PC_FREQ (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = val;
273
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
274
            CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1;
275
        }
276
      else
277
        sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-frequency' ignored\n");
278
      break;
279
 
280
    case 'S' :
281
      if (WITH_PROFILE_PC_P)
282
        {
283
          /* FIXME: Validate arg.  */
284
          int val = atoi (arg);
285
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
286
            PROFILE_PC_NR_BUCKETS (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = val;
287
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
288
            CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1;
289
        }
290
      else
291
        sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-size' ignored\n");
292
      break;
293
 
294
    case OPTION_PROFILE_PC_GRANULARITY:
295
      if (WITH_PROFILE_PC_P)
296
        {
297
          int shift;
298
          int val = atoi (arg);
299
          /* check that the granularity is a power of two */
300
          shift = 0;
301
          while (val > (1 << shift))
302
            {
303
              shift += 1;
304
            }
305
          if (val != (1 << shift))
306
            {
307
              sim_io_eprintf (sd, "PC profiling granularity not a power of two\n");
308
              return SIM_RC_FAIL;
309
            }
310
          if (shift == 0)
311
            {
312
              sim_io_eprintf (sd, "PC profiling granularity too small");
313
              return SIM_RC_FAIL;
314
            }
315
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
316
            PROFILE_PC_SHIFT (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = shift;
317
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
318
            CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1;
319
        }
320
      else
321
        sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-granularity' ignored\n");
322
      break;
323
 
324
    case OPTION_PROFILE_PC_RANGE:
325
      if (WITH_PROFILE_PC_P)
326
        {
327
          /* FIXME: Validate args */
328
          char *chp = arg;
329
          unsigned long base;
330
          unsigned long bound;
331
          base = strtoul (chp, &chp, 0);
332
          if (*chp != ',')
333
            {
334
              sim_io_eprintf (sd, "--profile-pc-range missing BOUND argument\n");
335
              return SIM_RC_FAIL;
336
            }
337
          bound = strtoul (chp + 1, NULL, 0);
338
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
339
            {
340
              PROFILE_PC_START (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = base;
341
              PROFILE_PC_END (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = bound;
342
            }
343
          for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
344
            CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1;
345
        }
346
      else
347
        sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-range' ignored\n");
348
      break;
349
 
350
#ifdef SIM_HAVE_ADDR_RANGE
351
    case OPTION_PROFILE_RANGE :
352
      if (WITH_PROFILE)
353
        {
354
          char *chp = arg;
355
          unsigned long start,end;
356
          start = strtoul (chp, &chp, 0);
357
          if (*chp != ',')
358
            {
359
              sim_io_eprintf (sd, "--profile-range missing END argument\n");
360
              return SIM_RC_FAIL;
361
            }
362
          end = strtoul (chp + 1, NULL, 0);
363
          /* FIXME: Argument validation.  */
364
          if (cpu != NULL)
365
            sim_addr_range_add (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)),
366
                                start, end);
367
          else
368
            for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
369
              sim_addr_range_add (PROFILE_RANGE (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))),
370
                                  start, end);
371
        }
372
      else
373
        sim_io_eprintf (sd, "Profiling not compiled in, `--profile-range' ignored\n");
374
      break;
375
 
376
    case OPTION_PROFILE_FUNCTION :
377
      if (WITH_PROFILE)
378
        {
379
          /*wip: need to compute function range given name*/
380
        }
381
      else
382
        sim_io_eprintf (sd, "Profiling not compiled in, `--profile-function' ignored\n");
383
      break;
384
#endif /* SIM_HAVE_ADDR_RANGE */
385
    }
386
 
387
  return SIM_RC_OK;
388
}
389
 
390
/* PC profiling support */
391
 
392
#if WITH_PROFILE_PC_P
393
 
394
static void
395
profile_pc_cleanup (SIM_DESC sd)
396
{
397
  int n;
398
  for (n = 0; n < MAX_NR_PROCESSORS; n++)
399
    {
400
      sim_cpu *cpu = STATE_CPU (sd, n);
401
      PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
402
      if (PROFILE_PC_COUNT (data) != NULL)
403
        zfree (PROFILE_PC_COUNT (data));
404
      PROFILE_PC_COUNT (data) = NULL;
405
      if (PROFILE_PC_EVENT (data) != NULL)
406
        sim_events_deschedule (sd, PROFILE_PC_EVENT (data));
407
      PROFILE_PC_EVENT (data) = NULL;
408
    }
409
}
410
 
411
 
412
static void
413
profile_pc_uninstall (SIM_DESC sd)
414
{
415
  profile_pc_cleanup (sd);
416
}
417
 
418
static void
419
profile_pc_event (SIM_DESC sd,
420
                  void *data)
421
{
422
  sim_cpu *cpu = (sim_cpu*) data;
423
  PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu);
424
  address_word pc;
425
  unsigned i;
426
  switch (STATE_WATCHPOINTS (sd)->sizeof_pc)
427
    {
428
    case 2: pc = *(unsigned_2*)(STATE_WATCHPOINTS (sd)->pc) ; break;
429
    case 4: pc = *(unsigned_4*)(STATE_WATCHPOINTS (sd)->pc) ; break;
430
    case 8: pc = *(unsigned_8*)(STATE_WATCHPOINTS (sd)->pc) ; break;
431
    default: pc = 0;
432
    }
433
  i = (pc - PROFILE_PC_START (profile)) >> PROFILE_PC_SHIFT (profile);
434
  if (i < PROFILE_PC_NR_BUCKETS (profile))
435
    PROFILE_PC_COUNT (profile) [i] += 1; /* Overflow? */
436
  else
437
    PROFILE_PC_COUNT (profile) [PROFILE_PC_NR_BUCKETS (profile)] += 1;
438
  PROFILE_PC_EVENT (profile) =
439
    sim_events_schedule (sd, PROFILE_PC_FREQ (profile), profile_pc_event, cpu);
440
}
441
 
442
static SIM_RC
443
profile_pc_init (SIM_DESC sd)
444
{
445
  int n;
446
  profile_pc_cleanup (sd);
447
  for (n = 0; n < MAX_NR_PROCESSORS; n++)
448
    {
449
      sim_cpu *cpu = STATE_CPU (sd, n);
450
      PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
451
      if (CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_PC_IDX]
452
          && STATE_WATCHPOINTS (sd)->pc != NULL)
453
        {
454
          int bucket_size;
455
          /* fill in the frequency if not specified */
456
          if (PROFILE_PC_FREQ (data) == 0)
457
            PROFILE_PC_FREQ (data) = 256;
458
          /* fill in the start/end if not specified */
459
          if (PROFILE_PC_END (data) == 0)
460
            {
461
              PROFILE_PC_START (data) = STATE_TEXT_START (sd);
462
              PROFILE_PC_END (data) = STATE_TEXT_END (sd);
463
            }
464
          /* Compute the number of buckets if not specified. */
465
          if (PROFILE_PC_NR_BUCKETS (data) == 0)
466
            {
467
              if (PROFILE_PC_BUCKET_SIZE (data) == 0)
468
                PROFILE_PC_NR_BUCKETS (data) = 16;
469
              else
470
                {
471
                  if (PROFILE_PC_END (data) == 0)
472
                    {
473
                      /* nr_buckets = (full-address-range / 2) / (bucket_size / 2) */
474
                      PROFILE_PC_NR_BUCKETS (data) =
475
                        ((1 << (STATE_WATCHPOINTS (sd)->sizeof_pc) * (8 - 1))
476
                         / (PROFILE_PC_BUCKET_SIZE (data) / 2));
477
                    }
478
                  else
479
                    {
480
                      PROFILE_PC_NR_BUCKETS (data) =
481
                        ((PROFILE_PC_END (data)
482
                          - PROFILE_PC_START (data)
483
                          + PROFILE_PC_BUCKET_SIZE (data) - 1)
484
                         / PROFILE_PC_BUCKET_SIZE (data));
485
                    }
486
                }
487
            }
488
          /* Compute the bucket size if not specified.  Ensure that it
489
             is rounded up to the next power of two */
490
          if (PROFILE_PC_BUCKET_SIZE (data) == 0)
491
            {
492
              if (PROFILE_PC_END (data) == 0)
493
                /* bucket_size = (full-address-range / 2) / (nr_buckets / 2) */
494
                bucket_size = ((1 << ((STATE_WATCHPOINTS (sd)->sizeof_pc * 8) - 1))
495
                               / (PROFILE_PC_NR_BUCKETS (data) / 2));
496
              else
497
                bucket_size = ((PROFILE_PC_END (data)
498
                                - PROFILE_PC_START (data)
499
                                + PROFILE_PC_NR_BUCKETS (data) - 1)
500
                               / PROFILE_PC_NR_BUCKETS (data));
501
              PROFILE_PC_SHIFT (data) = 0;
502
              while (bucket_size < PROFILE_PC_BUCKET_SIZE (data))
503
                {
504
                  PROFILE_PC_SHIFT (data) += 1;
505
                }
506
            }
507
          /* Align the end address with bucket size */
508
          if (PROFILE_PC_END (data) != 0)
509
            PROFILE_PC_END (data) = (PROFILE_PC_START (data)
510
                                     + (PROFILE_PC_BUCKET_SIZE (data)
511
                                        * PROFILE_PC_NR_BUCKETS (data)));
512
          /* create the relevant buffers */
513
          PROFILE_PC_COUNT (data) =
514
            NZALLOC (unsigned, PROFILE_PC_NR_BUCKETS (data) + 1);
515
          PROFILE_PC_EVENT (data) =
516
            sim_events_schedule (sd,
517
                                 PROFILE_PC_FREQ (data),
518
                                 profile_pc_event,
519
                                 cpu);
520
        }
521
    }
522
  return SIM_RC_OK;
523
}
524
 
525
static void
526
profile_print_pc (sim_cpu *cpu, int verbose)
527
{
528
  SIM_DESC sd = CPU_STATE (cpu);
529
  PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu);
530
  char comma_buf[20];
531
  unsigned max_val;
532
  unsigned total;
533
  unsigned i;
534
 
535
  if (PROFILE_PC_COUNT (profile) == 0)
536
    return;
537
 
538
  sim_io_printf (sd, "Program Counter Statistics:\n\n");
539
 
540
  /* First pass over data computes various things.  */
541
  max_val = 0;
542
  total = 0;
543
  for (i = 0; i <= PROFILE_PC_NR_BUCKETS (profile); ++i)
544
    {
545
      total += PROFILE_PC_COUNT (profile) [i];
546
      if (PROFILE_PC_COUNT (profile) [i] > max_val)
547
        max_val = PROFILE_PC_COUNT (profile) [i];
548
    }
549
 
550
  sim_io_printf (sd, "  Total samples: %s\n",
551
                 COMMAS (total));
552
  sim_io_printf (sd, "  Granularity: %s bytes per bucket\n",
553
                 COMMAS (PROFILE_PC_BUCKET_SIZE (profile)));
554
  sim_io_printf (sd, "  Size: %s buckets\n",
555
                 COMMAS (PROFILE_PC_NR_BUCKETS (profile)));
556
  sim_io_printf (sd, "  Frequency: %s cycles per sample\n",
557
                 COMMAS (PROFILE_PC_FREQ (profile)));
558
 
559
  if (PROFILE_PC_END (profile) != 0)
560
    sim_io_printf (sd, "  Range: 0x%lx 0x%lx\n",
561
                   (long) PROFILE_PC_START (profile),
562
                   (long) PROFILE_PC_END (profile));
563
 
564
  if (verbose && max_val != 0)
565
    {
566
      /* Now we can print the histogram.  */
567
      sim_io_printf (sd, "\n");
568
      for (i = 0; i <= PROFILE_PC_NR_BUCKETS (profile); ++i)
569
        {
570
          if (PROFILE_PC_COUNT (profile) [i] != 0)
571
            {
572
              sim_io_printf (sd, "  ");
573
              if (i == PROFILE_PC_NR_BUCKETS (profile))
574
                sim_io_printf (sd, "%10s:", "overflow");
575
              else
576
                sim_io_printf (sd, "0x%08lx:",
577
                               (long) (PROFILE_PC_START (profile)
578
                                       + (i * PROFILE_PC_BUCKET_SIZE (profile))));
579
              sim_io_printf (sd, " %*s",
580
                             max_val < 10000 ? 5 : 10,
581
                             COMMAS (PROFILE_PC_COUNT (profile) [i]));
582
              sim_io_printf (sd, " %4.1f",
583
                             (PROFILE_PC_COUNT (profile) [i] * 100.0) / total);
584
              sim_io_printf (sd, ": ");
585
              sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
586
                                     PROFILE_PC_COUNT (profile) [i],
587
                                     max_val);
588
              sim_io_printf (sd, "\n");
589
            }
590
        }
591
    }
592
 
593
  /* dump the histogram to the file "gmon.out" using BSD's gprof file
594
     format */
595
  /* Since a profile data file is in the native format of the host on
596
     which the profile is being, endian issues are not considered in
597
     the code below. */
598
  /* FIXME: Is this the best place for this code? */
599
  {
600
    FILE *pf = fopen ("gmon.out", "wb");
601
 
602
    if (pf == NULL)
603
      sim_io_eprintf (sd, "Failed to open \"gmon.out\" profile file\n");
604
    else
605
      {
606
        int ok;
607
        /* FIXME: what if the target has a 64 bit PC? */
608
        unsigned32 header[3];
609
        unsigned loop;
610
        if (PROFILE_PC_END (profile) != 0)
611
          {
612
            header[0] = PROFILE_PC_START (profile);
613
            header[1] = PROFILE_PC_END (profile);
614
          }
615
        else
616
          {
617
            header[0] = 0;
618
            header[1] = 0;
619
          }
620
        /* size of sample buffer (+ header) */
621
        header[2] = PROFILE_PC_NR_BUCKETS (profile) * 2 + sizeof (header);
622
        ok = fwrite (&header, sizeof (header), 1, pf);
623
        for (loop = 0;
624
             ok && (loop < PROFILE_PC_NR_BUCKETS (profile));
625
             loop++)
626
          {
627
            signed16 sample;
628
            if (PROFILE_PC_COUNT (profile) [loop] >= 0xffff)
629
              sample = 0xffff;
630
            else
631
              sample = PROFILE_PC_COUNT (profile) [loop];
632
            ok = fwrite (&sample, sizeof (sample), 1, pf);
633
          }
634
        if (ok == 0)
635
          sim_io_eprintf (sd, "Failed to write to \"gmon.out\" profile file\n");
636
        fclose(pf);
637
      }
638
  }
639
 
640
  sim_io_printf (sd, "\n");
641
}
642
 
643
#endif
644
 
645
/* Summary printing support.  */
646
 
647
#if WITH_PROFILE_INSN_P
648
 
649
static SIM_RC
650
profile_insn_init (SIM_DESC sd)
651
{
652
  int c;
653
 
654
  for (c = 0; c < MAX_NR_PROCESSORS; ++c)
655
    {
656
      sim_cpu *cpu = STATE_CPU (sd, c);
657
 
658
      if (CPU_MAX_INSNS (cpu) > 0)
659
        PROFILE_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = NZALLOC (unsigned int, CPU_MAX_INSNS (cpu));
660
    }
661
 
662
  return SIM_RC_OK;
663
}
664
 
665
static void
666
profile_print_insn (sim_cpu *cpu, int verbose)
667
{
668
  unsigned int i, n, total, max_val, max_name_len;
669
  SIM_DESC sd = CPU_STATE (cpu);
670
  PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
671
  char comma_buf[20];
672
 
673
  /* If MAX_INSNS not set, insn profiling isn't supported.  */
674
  if (CPU_MAX_INSNS (cpu) == 0)
675
    return;
676
 
677
  sim_io_printf (sd, "Instruction Statistics");
678
#ifdef SIM_HAVE_ADDR_RANGE
679
  if (PROFILE_RANGE (data)->ranges)
680
    sim_io_printf (sd, " (for selected address range(s))");
681
#endif
682
  sim_io_printf (sd, "\n\n");
683
 
684
  /* First pass over data computes various things.  */
685
  max_val = 0;
686
  total = 0;
687
  max_name_len = 0;
688
  for (i = 0; i < CPU_MAX_INSNS (cpu); ++i)
689
    {
690
      const char *name = (*CPU_INSN_NAME (cpu)) (cpu, i);
691
 
692
      if (name == NULL)
693
        continue;
694
      total += PROFILE_INSN_COUNT (data) [i];
695
      if (PROFILE_INSN_COUNT (data) [i] > max_val)
696
        max_val = PROFILE_INSN_COUNT (data) [i];
697
      n = strlen (name);
698
      if (n > max_name_len)
699
        max_name_len = n;
700
    }
701
  /* set the total insn count, in case client is being lazy */
702
  if (! PROFILE_TOTAL_INSN_COUNT (data))
703
    PROFILE_TOTAL_INSN_COUNT (data) = total;
704
 
705
  sim_io_printf (sd, "  Total: %s insns\n", COMMAS (total));
706
 
707
  if (verbose && max_val != 0)
708
    {
709
      /* Now we can print the histogram.  */
710
      sim_io_printf (sd, "\n");
711
      for (i = 0; i < CPU_MAX_INSNS (cpu); ++i)
712
        {
713
          const char *name = (*CPU_INSN_NAME (cpu)) (cpu, i);
714
 
715
          if (name == NULL)
716
            continue;
717
          if (PROFILE_INSN_COUNT (data) [i] != 0)
718
            {
719
              sim_io_printf (sd, "   %*s: %*s: ",
720
                             max_name_len, name,
721
                             max_val < 10000 ? 5 : 10,
722
                             COMMAS (PROFILE_INSN_COUNT (data) [i]));
723
              sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
724
                                     PROFILE_INSN_COUNT (data) [i],
725
                                     max_val);
726
              sim_io_printf (sd, "\n");
727
            }
728
        }
729
    }
730
 
731
  sim_io_printf (sd, "\n");
732
}
733
 
734
#endif
735
 
736
#if WITH_PROFILE_MEMORY_P
737
 
738
static void
739
profile_print_memory (sim_cpu *cpu, int verbose)
740
{
741
  unsigned int i, n;
742
  unsigned int total_read, total_write;
743
  unsigned int max_val, max_name_len;
744
  /* FIXME: Need to add smp support.  */
745
  SIM_DESC sd = CPU_STATE (cpu);
746
  PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
747
  char comma_buf[20];
748
 
749
  sim_io_printf (sd, "Memory Access Statistics\n\n");
750
 
751
  /* First pass over data computes various things.  */
752
  max_val = total_read = total_write = max_name_len = 0;
753
  for (i = 0; i < MODE_TARGET_MAX; ++i)
754
    {
755
      total_read += PROFILE_READ_COUNT (data) [i];
756
      total_write += PROFILE_WRITE_COUNT (data) [i];
757
      if (PROFILE_READ_COUNT (data) [i] > max_val)
758
        max_val = PROFILE_READ_COUNT (data) [i];
759
      if (PROFILE_WRITE_COUNT (data) [i] > max_val)
760
        max_val = PROFILE_WRITE_COUNT (data) [i];
761
      n = strlen (MODE_NAME (i));
762
      if (n > max_name_len)
763
        max_name_len = n;
764
    }
765
 
766
  /* One could use PROFILE_LABEL_WIDTH here.  I chose not to.  */
767
  sim_io_printf (sd, "  Total read:  %s accesses\n",
768
                 COMMAS (total_read));
769
  sim_io_printf (sd, "  Total write: %s accesses\n",
770
                 COMMAS (total_write));
771
 
772
  if (verbose && max_val != 0)
773
    {
774
      /* FIXME: Need to separate instruction fetches from data fetches
775
         as the former swamps the latter.  */
776
      /* Now we can print the histogram.  */
777
      sim_io_printf (sd, "\n");
778
      for (i = 0; i < MODE_TARGET_MAX; ++i)
779
        {
780
          if (PROFILE_READ_COUNT (data) [i] != 0)
781
            {
782
              sim_io_printf (sd, "   %*s read:  %*s: ",
783
                             max_name_len, MODE_NAME (i),
784
                             max_val < 10000 ? 5 : 10,
785
                             COMMAS (PROFILE_READ_COUNT (data) [i]));
786
              sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
787
                                     PROFILE_READ_COUNT (data) [i],
788
                                     max_val);
789
              sim_io_printf (sd, "\n");
790
            }
791
          if (PROFILE_WRITE_COUNT (data) [i] != 0)
792
            {
793
              sim_io_printf (sd, "   %*s write: %*s: ",
794
                             max_name_len, MODE_NAME (i),
795
                             max_val < 10000 ? 5 : 10,
796
                             COMMAS (PROFILE_WRITE_COUNT (data) [i]));
797
              sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
798
                                     PROFILE_WRITE_COUNT (data) [i],
799
                                     max_val);
800
              sim_io_printf (sd, "\n");
801
            }
802
        }
803
    }
804
 
805
  sim_io_printf (sd, "\n");
806
}
807
 
808
#endif
809
 
810
#if WITH_PROFILE_CORE_P
811
 
812
static void
813
profile_print_core (sim_cpu *cpu, int verbose)
814
{
815
  unsigned int total;
816
  unsigned int max_val;
817
  /* FIXME: Need to add smp support.  */
818
  SIM_DESC sd = CPU_STATE (cpu);
819
  PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
820
  char comma_buf[20];
821
 
822
  sim_io_printf (sd, "CORE Statistics\n\n");
823
 
824
  /* First pass over data computes various things.  */
825
  {
826
    unsigned map;
827
    total = 0;
828
    max_val = 0;
829
    for (map = 0; map < nr_maps; map++)
830
      {
831
        total += PROFILE_CORE_COUNT (data) [map];
832
        if (PROFILE_CORE_COUNT (data) [map] > max_val)
833
          max_val = PROFILE_CORE_COUNT (data) [map];
834
      }
835
  }
836
 
837
  /* One could use PROFILE_LABEL_WIDTH here.  I chose not to.  */
838
  sim_io_printf (sd, "  Total:  %s accesses\n",
839
                 COMMAS (total));
840
 
841
  if (verbose && max_val != 0)
842
    {
843
      unsigned map;
844
      /* Now we can print the histogram.  */
845
      sim_io_printf (sd, "\n");
846
      for (map = 0; map < nr_maps; map++)
847
        {
848
          if (PROFILE_CORE_COUNT (data) [map] != 0)
849
            {
850
              sim_io_printf (sd, "%10s:", map_to_str (map));
851
              sim_io_printf (sd, "%*s: ",
852
                             max_val < 10000 ? 5 : 10,
853
                             COMMAS (PROFILE_CORE_COUNT (data) [map]));
854
              sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
855
                                     PROFILE_CORE_COUNT (data) [map],
856
                                     max_val);
857
              sim_io_printf (sd, "\n");
858
            }
859
        }
860
    }
861
 
862
  sim_io_printf (sd, "\n");
863
}
864
 
865
#endif
866
 
867
#if WITH_PROFILE_MODEL_P
868
 
869
static void
870
profile_print_model (sim_cpu *cpu, int verbose)
871
{
872
  SIM_DESC sd = CPU_STATE (cpu);
873
  PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
874
  unsigned long cti_stall_cycles = PROFILE_MODEL_CTI_STALL_CYCLES (data);
875
  unsigned long load_stall_cycles = PROFILE_MODEL_LOAD_STALL_CYCLES (data);
876
  unsigned long total_cycles = PROFILE_MODEL_TOTAL_CYCLES (data);
877
  char comma_buf[20];
878
 
879
  sim_io_printf (sd, "Model %s Timing Information",
880
                 MODEL_NAME (CPU_MODEL (cpu)));
881
#ifdef SIM_HAVE_ADDR_RANGE
882
  if (PROFILE_RANGE (data)->ranges)
883
    sim_io_printf (sd, " (for selected address range(s))");
884
#endif
885
  sim_io_printf (sd, "\n\n");
886
  sim_io_printf (sd, "  %-*s %s\n",
887
                 PROFILE_LABEL_WIDTH, "Taken branches:",
888
                 COMMAS (PROFILE_MODEL_TAKEN_COUNT (data)));
889
  sim_io_printf (sd, "  %-*s %s\n",
890
                 PROFILE_LABEL_WIDTH, "Untaken branches:",
891
                 COMMAS (PROFILE_MODEL_UNTAKEN_COUNT (data)));
892
  sim_io_printf (sd, "  %-*s %s\n",
893
                 PROFILE_LABEL_WIDTH, "Cycles stalled due to branches:",
894
                 COMMAS (cti_stall_cycles));
895
  sim_io_printf (sd, "  %-*s %s\n",
896
                 PROFILE_LABEL_WIDTH, "Cycles stalled due to loads:",
897
                 COMMAS (load_stall_cycles));
898
  sim_io_printf (sd, "  %-*s %s\n",
899
                 PROFILE_LABEL_WIDTH, "Total cycles (*approximate*):",
900
                 COMMAS (total_cycles));
901
  sim_io_printf (sd, "\n");
902
}
903
 
904
#endif
905
 
906
void
907
sim_profile_print_bar (SIM_DESC sd, unsigned int width,
908
                       unsigned int val, unsigned int max_val)
909
{
910
  unsigned int i, count;
911
 
912
  count = ((double) val / (double) max_val) * (double) width;
913
 
914
  for (i = 0; i < count; ++i)
915
    sim_io_printf (sd, "*");
916
}
917
 
918
/* Print the simulator's execution speed for CPU.  */
919
 
920
static void
921
profile_print_speed (sim_cpu *cpu)
922
{
923
  SIM_DESC sd = CPU_STATE (cpu);
924
  PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
925
  unsigned long milliseconds = sim_events_elapsed_time (sd);
926
  unsigned long total = PROFILE_TOTAL_INSN_COUNT (data);
927
  char comma_buf[20];
928
 
929
  sim_io_printf (sd, "Simulator Execution Speed\n\n");
930
 
931
  if (total != 0)
932
    sim_io_printf (sd, "  Total instructions:   %s\n", COMMAS (total));
933
 
934
  if (milliseconds < 1000)
935
    sim_io_printf (sd, "  Total execution time: < 1 second\n\n");
936
  else
937
    {
938
      /* The printing of the time rounded to 2 decimal places makes the speed
939
         calculation seem incorrect [even though it is correct].  So round
940
         MILLISECONDS first. This can marginally affect the result, but it's
941
         better that the user not perceive there's a math error.  */
942
      double secs = (double) milliseconds / 1000;
943
      secs = ((double) (unsigned long) (secs * 100 + .5)) / 100;
944
      sim_io_printf (sd, "  Total execution time: %.2f seconds\n", secs);
945
      /* Don't confuse things with data that isn't useful.
946
         If we ran for less than 2 seconds, only use the data if we
947
         executed more than 100,000 insns.  */
948
      if (secs >= 2 || total >= 100000)
949
        sim_io_printf (sd, "  Simulator speed:      %s insns/second\n\n",
950
                       COMMAS ((unsigned long) ((double) total / secs)));
951
    }
952
}
953
 
954
/* Print selected address ranges.  */
955
 
956
static void
957
profile_print_addr_ranges (sim_cpu *cpu)
958
{
959
  ADDR_SUBRANGE *asr = PROFILE_RANGE (CPU_PROFILE_DATA (cpu))->ranges;
960
  SIM_DESC sd = CPU_STATE (cpu);
961
 
962
  if (asr)
963
    {
964
      sim_io_printf (sd, "Selected address ranges\n\n");
965
      while (asr != NULL)
966
        {
967
          sim_io_printf (sd, "  0x%lx - 0x%lx\n",
968
                         (long) asr->start, (long) asr->end);
969
          asr = asr->next;
970
        }
971
      sim_io_printf (sd, "\n");
972
    }
973
}
974
 
975
/* Top level function to print all summary profile information.
976
   It is [currently] intended that all such data is printed by this function.
977
   I'd rather keep it all in one place for now.  To that end, MISC_CPU and
978
   MISC are callbacks used to print any miscellaneous data.
979
 
980
   One might want to add a user option that allows printing by type or by cpu
981
   (i.e. print all insn data for each cpu first, or print data cpu by cpu).
982
   This may be a case of featuritis so it's currently left out.
983
 
984
   Note that results are indented two spaces to distinguish them from
985
   section titles.  */
986
 
987
static void
988
profile_info (SIM_DESC sd, int verbose)
989
{
990
  int i,c;
991
  int print_title_p = 0;
992
 
993
  /* Only print the title if some data has been collected.  */
994
  /* ??? Why don't we just exit if no data collected?  */
995
  /* FIXME: If the number of processors can be selected on the command line,
996
     then MAX_NR_PROCESSORS will need to take an argument of `sd'.  */
997
 
998
  for (c = 0; c < MAX_NR_PROCESSORS; ++c)
999
    {
1000
      sim_cpu *cpu = STATE_CPU (sd, c);
1001
      PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
1002
 
1003
      for (i = 0; i < MAX_PROFILE_VALUES; ++i)
1004
        if (PROFILE_FLAGS (data) [i])
1005
          print_title_p = 1;
1006
      /* One could break out early if print_title_p is set.  */
1007
    }
1008
  if (print_title_p)
1009
    sim_io_printf (sd, "Summary profiling results:\n\n");
1010
 
1011
  /* Loop, cpu by cpu, printing results.  */
1012
 
1013
  for (c = 0; c < MAX_NR_PROCESSORS; ++c)
1014
    {
1015
      sim_cpu *cpu = STATE_CPU (sd, c);
1016
      PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
1017
 
1018
      if (MAX_NR_PROCESSORS > 1
1019
          && (0
1020
#if WITH_PROFILE_INSN_P
1021
              || PROFILE_FLAGS (data) [PROFILE_INSN_IDX]
1022
#endif
1023
#if WITH_PROFILE_MEMORY_P
1024
              || PROFILE_FLAGS (data) [PROFILE_MEMORY_IDX]
1025
#endif
1026
#if WITH_PROFILE_CORE_P
1027
              || PROFILE_FLAGS (data) [PROFILE_CORE_IDX]
1028
#endif
1029
#if WITH_PROFILE_MODEL_P
1030
              || PROFILE_FLAGS (data) [PROFILE_MODEL_IDX]
1031
#endif
1032
#if WITH_PROFILE_SCACHE_P && WITH_SCACHE
1033
              || PROFILE_FLAGS (data) [PROFILE_SCACHE_IDX]
1034
#endif
1035
#if WITH_PROFILE_PC_P
1036
              || PROFILE_FLAGS (data) [PROFILE_PC_IDX]
1037
#endif
1038
              ))
1039
        {
1040
          sim_io_printf (sd, "CPU %d\n\n", c);
1041
        }
1042
 
1043
#ifdef SIM_HAVE_ADDR_RANGE
1044
      if (print_title_p
1045
          && (PROFILE_INSN_P (cpu)
1046
              || PROFILE_MODEL_P (cpu)))
1047
        profile_print_addr_ranges (cpu);
1048
#endif
1049
 
1050
#if WITH_PROFILE_INSN_P
1051
      if (PROFILE_FLAGS (data) [PROFILE_INSN_IDX])
1052
        profile_print_insn (cpu, verbose);
1053
#endif
1054
 
1055
#if WITH_PROFILE_MEMORY_P
1056
      if (PROFILE_FLAGS (data) [PROFILE_MEMORY_IDX])
1057
        profile_print_memory (cpu, verbose);
1058
#endif
1059
 
1060
#if WITH_PROFILE_CORE_P
1061
      if (PROFILE_FLAGS (data) [PROFILE_CORE_IDX])
1062
        profile_print_core (cpu, verbose);
1063
#endif
1064
 
1065
#if WITH_PROFILE_MODEL_P
1066
      if (PROFILE_FLAGS (data) [PROFILE_MODEL_IDX])
1067
        profile_print_model (cpu, verbose);
1068
#endif
1069
 
1070
#if WITH_PROFILE_SCACHE_P && WITH_SCACHE
1071
      if (PROFILE_FLAGS (data) [PROFILE_SCACHE_IDX])
1072
        scache_print_profile (cpu, verbose);
1073
#endif
1074
 
1075
#if WITH_PROFILE_PC_P
1076
      if (PROFILE_FLAGS (data) [PROFILE_PC_IDX])
1077
        profile_print_pc (cpu, verbose);
1078
#endif
1079
 
1080
      /* Print cpu-specific data before the execution speed.  */
1081
      if (PROFILE_INFO_CPU_CALLBACK (data) != NULL)
1082
        PROFILE_INFO_CPU_CALLBACK (data) (cpu, verbose);
1083
 
1084
      /* Always try to print execution time and speed.  */
1085
      if (verbose
1086
          || PROFILE_FLAGS (data) [PROFILE_INSN_IDX])
1087
        profile_print_speed (cpu);
1088
    }
1089
 
1090
  /* Finally print non-cpu specific miscellaneous data.  */
1091
  if (STATE_PROFILE_INFO_CALLBACK (sd))
1092
    STATE_PROFILE_INFO_CALLBACK (sd) (sd, verbose);
1093
 
1094
}
1095
 
1096
/* Install profiling support in the simulator.  */
1097
 
1098
SIM_RC
1099
profile_install (SIM_DESC sd)
1100
{
1101
  int i;
1102
 
1103
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1104
  sim_add_option_table (sd, NULL, profile_options);
1105
  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1106
    memset (CPU_PROFILE_DATA (STATE_CPU (sd, i)), 0,
1107
            sizeof (* CPU_PROFILE_DATA (STATE_CPU (sd, i))));
1108
#if WITH_PROFILE_INSN_P
1109
  sim_module_add_init_fn (sd, profile_insn_init);
1110
#endif
1111
#if WITH_PROFILE_PC_P
1112
  sim_module_add_uninstall_fn (sd, profile_pc_uninstall);
1113
  sim_module_add_init_fn (sd, profile_pc_init);
1114
#endif
1115
  sim_module_add_init_fn (sd, profile_init);
1116
  sim_module_add_uninstall_fn (sd, profile_uninstall);
1117
  sim_module_add_info_fn (sd, profile_info);
1118
  return SIM_RC_OK;
1119
}
1120
 
1121
static SIM_RC
1122
profile_init (SIM_DESC sd)
1123
{
1124
#ifdef SIM_HAVE_ADDR_RANGE
1125
  /* Check if a range has been specified without specifying what to
1126
     collect.  */
1127
  {
1128
    int i;
1129
 
1130
    for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1131
      {
1132
        sim_cpu *cpu = STATE_CPU (sd, i);
1133
 
1134
        if (ADDR_RANGE_RANGES (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)))
1135
            && ! (PROFILE_INSN_P (cpu)
1136
                  || PROFILE_MODEL_P (cpu)))
1137
          {
1138
            sim_io_eprintf_cpu (cpu, "Profiling address range specified without --profile-insn or --profile-model.\n");
1139
            sim_io_eprintf_cpu (cpu, "Address range ignored.\n");
1140
            sim_addr_range_delete (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)),
1141
                                   0, ~ (address_word) 0);
1142
          }
1143
      }
1144
  }
1145
#endif
1146
 
1147
  return SIM_RC_OK;
1148
}
1149
 
1150
static void
1151
profile_uninstall (SIM_DESC sd)
1152
{
1153
  int i,j;
1154
 
1155
  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1156
    {
1157
      sim_cpu *cpu = STATE_CPU (sd, i);
1158
      PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
1159
 
1160
      if (PROFILE_FILE (data) != NULL)
1161
        {
1162
          /* If output from different cpus is going to the same file,
1163
             avoid closing the file twice.  */
1164
          for (j = 0; j < i; ++j)
1165
            if (PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, j)))
1166
                == PROFILE_FILE (data))
1167
              break;
1168
          if (i == j)
1169
            fclose (PROFILE_FILE (data));
1170
        }
1171
 
1172
      if (PROFILE_INSN_COUNT (data) != NULL)
1173
        zfree (PROFILE_INSN_COUNT (data));
1174
    }
1175
}

powered by: WebSVN 2.1.0

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