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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [mprofiler.c] - Diff between revs 1550 and 1748

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1550 Rev 1748
Line 1... Line 1...
/* mprofiler.c -- memory profiling utility
/* mprofiler.c -- memory profiling utility
 
 
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
 
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
   Copyright (C) 2008 Embecosm Limited
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
This program is free software; you can redistribute it and/or modify
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
it under the terms of the GNU General Public License as published by
 
the Free Software Foundation; either version 2 of the License, or
   This program is free software; you can redistribute it and/or modify it
(at your option) any later version.
   under the terms of the GNU General Public License as published by the Free
 
   Software Foundation; either version 3 of the License, or (at your option)
This program is distributed in the hope that it will be useful,
   any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   This program is distributed in the hope that it will be useful, but WITHOUT
GNU General Public License for more details.
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
You should have received a copy of the GNU General Public License
   more details.
along with this program; if not, write to the Free Software
 
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
   You should have received a copy of the GNU General Public License along
 
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
/* Command line utility, that displays profiling information, generated
 
   by or1ksim. (use --mprofile option at command line, when running or1ksim.  */
/* This program is commented throughout in a fashion suitable for processing
 
   with Doxygen. */
#if HAVE_CONFIG_H
 
#include <config.h>
 
#endif
 
 
 
#include <stdio.h>
 
#include <string.h>
 
#include <stdlib.h>
 
#if HAVE_MALLOC_H
 
#include <malloc.h>     /* calloc, free */
 
#endif
 
#ifdef HAVE_INTTYPES_H
 
#include <inttypes.h>
 
#endif
 
 
 
 
/* Autoconf and/or portability configuration */
 
#include "config.h"
#include "port.h"
#include "port.h"
#include "arch.h"
 
#include "support/profile.h"
/* System includes */
 
#include <stdlib.h>
 
#include <regex.h>
 
 
 
/* Package includes */
#include "mprofiler.h"
#include "mprofiler.h"
#include "sim-config.h"
#include "sim-config.h"
 
#include "argtable2.h"
 
#include "support/profile.h"
 
 
struct memory_hash {
/* output modes */
 
#define MODE_DETAIL     0
 
#define MODE_PRETTY     1
 
#define MODE_ACCESS     2
 
#define MODE_WIDTH      3
 
 
 
/* Input buffer size */
 
#define BUF_SIZE        256
 
 
 
/* HASH */
 
#define HASH_SIZE       0x10000
 
#define HASH_FUNC(x)    ((x) & 0xffff)
 
 
 
/*! Hash table data structure */
 
static struct memory_hash
 
{
  struct memory_hash *next;
  struct memory_hash *next;
  oraddr_t addr;
  oraddr_t addr;
  unsigned long cnt[3];    /* Various counters */
  unsigned long cnt[3];    /* Various counters */
} *hash[HASH_SIZE];
} *hash[HASH_SIZE];
 
 
/* Groups size -- how much addresses should be joined together */
/*! Groups size -- how much addresses should be joined together */
int group_bits = 2;
static int  group_bits = 2;
 
 
/* Start address */
/*! Start address */
oraddr_t start_addr = 0;
static oraddr_t  start_addr = 0;
 
 
/* End address */
/*! End address */
oraddr_t end_addr = 0xffffffff;
static oraddr_t  end_addr = 0xffffffff;
 
 
/* File to read from */
/* File to read from */
static FILE *fprof = 0;
static FILE *fprof = 0;
 
 
void mp_help (void)
static void
{
hash_add (oraddr_t addr, int index)
  PRINTF ("mprofiler <-d|-p|-a|-w> [-f filename] [-g group] from to\n");
 
  PRINTF ("\t-d\t--detail\t\tdetailed output\n");
 
  PRINTF ("\t-p\t--pretty\t\tpretty output\n");
 
  PRINTF ("\t-a\t--access\t\toutput accesses only\n");
 
  PRINTF ("\t-w\t--width\t\t\toutput by width\n");
 
  PRINTF ("\t-f\t--filename filename\tspecify mprofile file [sim.mprofile]\n");
 
  PRINTF ("\t-g\t--group bits\t\tgroup 2^bits successive\n");
 
  PRINTF ("\t\t\t\t\taddresses together [2]\n");
 
  PRINTF ("\t-h\t--help\t\t\toutput this screen\n");
 
}
 
 
 
void hash_add (oraddr_t addr, int index)
 
{
{
  struct memory_hash *h = hash[HASH_FUNC(addr)];
  struct memory_hash *h = hash[HASH_FUNC(addr)];
  while (h && h->addr != addr) h = h->next;
  while (h && h->addr != addr)
 
    h = h->next;
 
 
  if (!h) {
  if (!h)
 
    {
    h = (struct memory_hash *)malloc (sizeof (struct memory_hash));
    h = (struct memory_hash *)malloc (sizeof (struct memory_hash));
    h->next = hash[HASH_FUNC(addr)];
    h->next = hash[HASH_FUNC(addr)];
    hash[HASH_FUNC(addr)] = h;
    hash[HASH_FUNC(addr)] = h;
    h->addr = addr;
    h->addr = addr;
    h->cnt[0] = h->cnt[1] = h->cnt[2] = 0;
    h->cnt[0] = h->cnt[1] = h->cnt[2] = 0;
  }
  }
  h->cnt[index]++;
  h->cnt[index]++;
}
}
 
 
unsigned long hash_get (oraddr_t addr, int index)
 
 
static unsigned long
 
hash_get (oraddr_t addr, int index)
{
{
  struct memory_hash *h = hash[HASH_FUNC(addr)];
  struct memory_hash *h = hash[HASH_FUNC(addr)];
  while (h && h->addr != addr) h = h->next;
  while (h && h->addr != addr)
 
    h = h->next;
 
 
  if (!h) return 0;
  if (!h)
 
    return 0;
  return h->cnt[index];
  return h->cnt[index];
}
}
 
 
void init (void)
static void
 
init ()
{
{
  int i;
  int i;
  for (i = 0; i < HASH_SIZE; i++)
  for (i = 0; i < HASH_SIZE; i++)
    hash[i] = NULL;
    hash[i] = NULL;
}
}
 
 
void read_file (FILE *f, int mode)
static void
 
read_file (FILE * f, int mode)
{
{
  struct mprofentry_struct buf[BUF_SIZE];
  struct mprofentry_struct buf[BUF_SIZE];
  int num_read;
  int num_read;
  do {
  do
 
    {
    int i;
    int i;
    num_read = fread (buf, sizeof (struct mprofentry_struct), BUF_SIZE, f);
    num_read = fread (buf, sizeof (struct mprofentry_struct), BUF_SIZE, f);
    for (i = 0; i < num_read; i++) if (buf[i].addr >= start_addr && buf[i].addr <= end_addr) {
      for (i = 0; i < num_read; i++)
 
        if (buf[i].addr >= start_addr && buf[i].addr <= end_addr)
 
          {
      int index;
      int index;
      unsigned t = buf[i].type;
      unsigned t = buf[i].type;
      if (t > 64) {
            if (t > 64)
 
              {
        PRINTF ("!");
        PRINTF ("!");
        t = 0;
        t = 0;
      }
      }
      if (mode == MODE_WIDTH) t >>= 3;
            if (mode == MODE_WIDTH)
      else t &= 0x7;
              t >>= 3;
 
            else
 
              t &= 0x7;
 
 
      switch (t) {
            switch (t)
        case 1: index = 0; break;
              {
        case 2: index = 1; break;
              case 1:
        case 4: index = 2; break;
                index = 0;
 
                break;
 
              case 2:
 
                index = 1;
 
                break;
 
              case 4:
 
                index = 2;
 
                break;
        default:
        default:
          index = 0;
          index = 0;
          PRINTF ("!!!!");
          PRINTF ("!!!!");
          break;
          break;
      }
      }
      hash_add (buf[i].addr >> group_bits, index);
      hash_add (buf[i].addr >> group_bits, index);
    }
    }
  } while (num_read > 0);
    }
 
  while (num_read > 0);
}
}
 
 
static inline int nbits (unsigned long a)
static int
 
nbits (unsigned long a)
{
{
  int cnt = 0;
  int cnt = 0;
  int b = a;
  int b = a;
  if (!a) return 0;
  if (!a)
 
    return 0;
 
 
  while (a) a >>= 1, cnt++;
  while (a)
 
    a >>= 1, cnt++;
  if (cnt > 1 && ((b >> (cnt - 2)) & 1))
  if (cnt > 1 && ((b >> (cnt - 2)) & 1))
    cnt = cnt * 2 + 1;
    cnt = cnt * 2 + 1;
  else
  else
    cnt *= 2;
    cnt *= 2;
 
 
  return cnt - 1;
  return cnt - 1;
}
}
 
 
void printout (int mode)
static void
 
printout (int mode)
{
{
  oraddr_t addr = start_addr & ~((1 << group_bits) - 1);
  oraddr_t addr = start_addr & ~((1 << group_bits) - 1);
  PRINTF ("start = %"PRIxADDR" (%"PRIxADDR"); end = %"PRIxADDR"; group_bits = %08x\n", start_addr, addr, end_addr, (1 << group_bits) - 1);
  PRINTF ("start = %" PRIxADDR " (%" PRIxADDR "); end = %" PRIxADDR
  for (; addr <= end_addr; addr += (1 << group_bits)) {
          "; group_bits = %08x\n", start_addr, addr, end_addr,
 
          (1 << group_bits) - 1);
 
  for (; addr <= end_addr; addr += (1 << group_bits))
 
    {
    int i;
    int i;
    unsigned long a = hash_get (addr >> group_bits, 0);
    unsigned long a = hash_get (addr >> group_bits, 0);
    unsigned long b = hash_get (addr >> group_bits, 1);
    unsigned long b = hash_get (addr >> group_bits, 1);
    unsigned long c = hash_get (addr >> group_bits, 2);
    unsigned long c = hash_get (addr >> group_bits, 2);
    PRINTF ("%"PRIxADDR":", addr);
    PRINTF ("%"PRIxADDR":", addr);
    switch (mode) {
      switch (mode)
 
        {
      case MODE_DETAIL:
      case MODE_DETAIL:
        if (a) PRINTF (" %10li R", a);
          if (a)
        else PRINTF ("            R");
            PRINTF (" %10li R", a);
        if (b) PRINTF (" %10li W", b);
          else
        else PRINTF ("            W");
            PRINTF ("            R");
        if (c) PRINTF (" %10li F", c);
          if (b)
        else PRINTF ("            F");
            PRINTF (" %10li W", b);
 
          else
 
            PRINTF ("            W");
 
          if (c)
 
            PRINTF (" %10li F", c);
 
          else
 
            PRINTF ("            F");
        break;
        break;
      case MODE_ACCESS:
      case MODE_ACCESS:
        PRINTF (" %10li", a + b + c);
        PRINTF (" %10li", a + b + c);
        break;
        break;
      case MODE_PRETTY:
      case MODE_PRETTY:
        PRINTF (" %10li ", a + b + c);
        PRINTF (" %10li ", a + b + c);
        for (i = 0; i < nbits (a + b + c); i++)
        for (i = 0; i < nbits (a + b + c); i++)
          PRINTF ("#");
          PRINTF ("#");
#if 0
 
        for (; i < 64; i++)
 
          PRINTF (".");
 
#endif
 
        break;
        break;
      case MODE_WIDTH:
      case MODE_WIDTH:
        if (a) PRINTF (" %10li B", a);
          if (a)
        else PRINTF ("            B");
            PRINTF (" %10li B", a);
        if (b) PRINTF (" %10li H", b);
          else
        else PRINTF ("            H");
            PRINTF ("            B");
        if (c) PRINTF (" %10li W", c);
          if (b)
        else PRINTF ("            W");
            PRINTF (" %10li H", b);
 
          else
 
            PRINTF ("            H");
 
          if (c)
 
            PRINTF (" %10li W", c);
 
          else
 
            PRINTF ("            W");
        break;
        break;
    }
    }
    PRINTF ("\n");
    PRINTF ("\n");
    if (addr >= addr + (1 << group_bits)) break; /* Overflow? */
      if (addr >= addr + (1 << group_bits))
 
        break;                  /* Overflow? */
  }
  }
}
}
 
 
int main_mprofiler (int argc, char *argv[])
/*---------------------------------------------------------------------------*/
 
/*! Parse the arguments for the profiling utility
 
 
 
    Updated by Jeremy Bennett to use argtable2. Also has an option just to
 
    print help, for use with the CLI.
 
 
 
    @param[in] argc       Number of command args
 
    @param[in] argv       Vector of the command args
 
    @param[in] just_help  If 1 (true), ignore argc & argv and just print out
 
                          the help message without parsing args
 
 
 
    @return  0 on success, 1 on failure                                      */
 
/*---------------------------------------------------------------------------*/
 
int
 
main_mprofiler (int argc, char *argv[], int just_help)
{
{
  char fmprofname[50] = "sim.mprofile";
  struct arg_lit *vercop;
  int param = 0;
  struct arg_lit *help;
 
  struct arg_rex *mode_arg;
 
  struct arg_int *group;
 
  struct arg_file *prof_file;
 
  struct arg_int *from;
 
  struct arg_int *to;
 
  struct arg_end *end;
 
 
 
  void *argtab[8];
 
  int nerrors;
 
 
  int mode = MODE_DETAIL;
  int mode = MODE_DETAIL;
 
 
  argv++; argc--;
  /* Specify each argument, with fallback values */
  while (argc > 0) {
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
    if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "--detail")) {
  help = arg_lit0 ("h", "help", "print this help message");
      mode = MODE_DETAIL;
  mode_arg = arg_rex0 ("m", "mode",
      argv++; argc--;
                       "(detailed|d)|(pretty|p)|(access|a)|"
    } else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--pretty")) {
                       "(width|w)", "<m>", REG_ICASE,
      mode = MODE_PRETTY;
                       "Output mode (detailed, pretty, access " "or width)");
      argv++; argc--;
  mode_arg->sval[0] = "detailed";
    } else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--access")) {
  group = arg_int0 ("g", "group", "<n>",
      mode = MODE_ACCESS;
                    "group 2^n bits successive addresses " "together");
      argv++; argc--;
  group->ival[0] = 0;
    } else if (!strcmp(argv[0], "-w") || !strcmp(argv[0], "--width")) {
  prof_file = arg_file0 ("f", "filename", "<file>",
      mode = MODE_WIDTH;
                         "data file to analyse (default " "sim.mprofile)");
      argv++; argc--;
  prof_file->filename[0] = "sim.mprofile";
    } else if (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--group")) {
  from = arg_int1 (NULL, NULL, "<from>", "start address");
      argv++; argc--;
  to = arg_int1 (NULL, NULL, "<to>", "end address");
      group_bits = strtoul (argv[0], NULL, 0);
  end = arg_end (20);
      argv++; argc--;
 
    } else if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
  /* Set up the argument table */
      mp_help ();
  argtab[0] = vercop;
 
  argtab[1] = help;
 
  argtab[2] = mode_arg;
 
  argtab[3] = group;
 
  argtab[4] = prof_file;
 
  argtab[5] = from;
 
  argtab[6] = to;
 
  argtab[7] = end;
 
 
 
  /* If we are just asked for a help message, then we don't parse the
 
     args. This is used to implement the help function from the CLI. */
 
  if (just_help)
 
    {
 
      printf ("mprofile");
 
      arg_print_syntax (stdout, argtab, "\n");
 
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
 
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      return 0;
      return 0;
    } else if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--filename")) {
 
      argv++; argc--;
 
      strcpy (&fmprofname[0], argv[0]);
 
      argv++; argc--;
 
    } else {
 
      switch (param) {
 
        case 0:
 
          start_addr = strtoul (argv[0], NULL, 0);
 
          break;
 
        case 1:
 
          end_addr = strtoul (argv[0], NULL, 0);
 
          break;
 
        default:
 
          fprintf (stderr, "Invalid number of parameters.\n");
 
          return -1;
 
      }
      }
      argv++; argc--; param++;
 
 
  /* Parse */
 
  nerrors = arg_parse (argc, argv, argtab);
 
 
 
  /* Special case here is if help or version is specified, we ignore any other
 
     errors and just print the help or version information and then give up. */
 
  if (vercop->count > 0)
 
    {
 
      PRINTF ("OpenRISC 1000 Memory Profiling Utility, version %s\n",
 
              PACKAGE_VERSION);
 
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
 
      return 0;
 
    }
 
 
 
  if (help->count > 0)
 
    {
 
      printf ("Usage: %s ", argv[0]);
 
      arg_print_syntax (stdout, argtab, "\n");
 
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
 
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
 
      return 0;
 
    }
 
 
 
  /* Deal with any errors */
 
  if (0 != nerrors)
 
    {
 
      arg_print_errors (stderr, end, "mprofile");
 
      fprintf (stderr, "Usage: %s ", argv[0]);
 
      arg_print_syntaxv (stderr, argtab, "\n");
 
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
 
      return 1;
 
    }
 
 
 
  /* If version or help is requested, that is all that is printed out */
 
  /* Sort out the mode */
 
  if ((0 == strcmp (mode_arg->sval[0], "detail")) ||
 
      (0 == strcmp (mode_arg->sval[0], "d")))
 
    {
 
      mode = MODE_DETAIL;
 
    }
 
  else if ((0 == strcmp (mode_arg->sval[0], "pretty")) ||
 
           (0 == strcmp (mode_arg->sval[0], "p")))
 
    {
 
      mode = MODE_DETAIL;
 
    }
 
  else if ((0 == strcmp (mode_arg->sval[0], "access")) ||
 
           (0 == strcmp (mode_arg->sval[0], "a")))
 
    {
 
      mode = MODE_DETAIL;
 
    }
 
  else if ((0 == strcmp (mode_arg->sval[0], "width")) ||
 
           (0 == strcmp (mode_arg->sval[0], "w")))
 
    {
 
      mode = MODE_DETAIL;
    }
    }
 
  else
 
    {
 
      fprintf (stderr, "Impossible mode: %s\n", mode_arg->sval[0]);
  }
  }
 
 
  fprof = fopen (fmprofname, "rm");
  /* Group bits */
 
  group_bits = group->ival[0];
 
 
 
  /* Start and end addresses */
 
  start_addr = from->ival[0];
 
  end_addr = to->ival[0];
 
 
 
  /* Get the profile */
 
  fprof = fopen (prof_file->filename[0], "rm");
 
 
  if (!fprof) {
  if (!fprof)
    fprintf (stderr, "Cannot open profile file: %s\n", fmprofname);
    {
 
      fprintf (stderr, "Cannot open profile file: %s\n",
 
               prof_file->filename[0]);
 
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
    return 1;
    return 1;
  }
  }
 
 
 
  /* Finished with the args */
 
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
 
 
  init ();
  init ();
  read_file (fprof, mode);
  read_file (fprof, mode);
  fclose (fprof);
  fclose (fprof);
  printout (mode);
  printout (mode);
  return 0;
  return 0;
}
 
 
}       /* main_mprofiler () */
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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