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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [mprofiler.c] - Diff between revs 19 and 88

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

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