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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_67/] [or1ksim/] [mprofiler.c] - Diff between revs 1460 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1460 Rev 1765
/* 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
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
This file is part of OpenRISC 1000 Architectural Simulator.
 
 
This program is free software; you can redistribute it and/or modify
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
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
/* Command line utility, that displays profiling information, generated
/* Command line utility, that displays profiling information, generated
   by or1ksim. (use --mprofile option at command line, when running or1ksim.  */
   by or1ksim. (use --mprofile option at command line, when running or1ksim.  */
 
 
#if HAVE_CONFIG_H
#if HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#endif
 
 
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#if HAVE_MALLOC_H
#if HAVE_MALLOC_H
#include <malloc.h>     /* calloc, free */
#include <malloc.h>     /* calloc, free */
#endif
#endif
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "support/profile.h"
#include "support/profile.h"
#include "mprofiler.h"
#include "mprofiler.h"
#include "sim-config.h"
#include "sim-config.h"
 
 
struct memory_hash {
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;
int group_bits = 2;
 
 
/* Start address */
/* Start address */
oraddr_t start_addr = 0;
oraddr_t start_addr = 0;
 
 
/* End address */
/* End address */
oraddr_t end_addr = 0xffffffff;
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 mp_help ()
{
{
  PRINTF ("mprofiler <-d|-p|-a|-w> [-f filename] [-g group] from to\n");
  PRINTF ("mprofiler <-d|-p|-a|-w> [-f filename] [-g group] from to\n");
  PRINTF ("\t-d\t--detail\t\tdetailed output\n");
  PRINTF ("\t-d\t--detail\t\tdetailed output\n");
  PRINTF ("\t-p\t--pretty\t\tpretty output\n");
  PRINTF ("\t-p\t--pretty\t\tpretty output\n");
  PRINTF ("\t-a\t--access\t\toutput accesses only\n");
  PRINTF ("\t-a\t--access\t\toutput accesses only\n");
  PRINTF ("\t-w\t--width\t\t\toutput by width\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-f\t--filename filename\tspecify mprofile file [sim.mprofile]\n");
  PRINTF ("\t-g\t--group bits\t\tgroup 2^bits successive\n");
  PRINTF ("\t-g\t--group bits\t\tgroup 2^bits successive\n");
  PRINTF ("\t\t\t\t\taddresses together [2]\n");
  PRINTF ("\t\t\t\t\taddresses together [2]\n");
  PRINTF ("\t-h\t--help\t\t\toutput this screen\n");
  PRINTF ("\t-h\t--help\t\t\toutput this screen\n");
}
}
 
 
void hash_add (oraddr_t addr, int index)
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)
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 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)
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) t >>= 3;
      else t &= 0x7;
      else t &= 0x7;
 
 
      switch (t) {
      switch (t) {
        case 1: index = 0; break;
        case 1: index = 0; break;
        case 2: index = 1; break;
        case 2: index = 1; break;
        case 4: index = 2; 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 inline 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)
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"; group_bits = %08x\n", start_addr, addr, end_addr, (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) PRINTF (" %10li R", a);
        if (a) PRINTF (" %10li R", a);
        else PRINTF ("            R");
        else PRINTF ("            R");
        if (b) PRINTF (" %10li W", b);
        if (b) PRINTF (" %10li W", b);
        else PRINTF ("            W");
        else PRINTF ("            W");
        if (c) PRINTF (" %10li F", c);
        if (c) PRINTF (" %10li F", c);
        else PRINTF ("            F");
        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
#if 0
        for (; i < 64; i++)
        for (; i < 64; i++)
          PRINTF (".");
          PRINTF (".");
#endif
#endif
        break;
        break;
      case MODE_WIDTH:
      case MODE_WIDTH:
        if (a) PRINTF (" %10li B", a);
        if (a) PRINTF (" %10li B", a);
        else PRINTF ("            B");
        else PRINTF ("            B");
        if (b) PRINTF (" %10li H", b);
        if (b) PRINTF (" %10li H", b);
        else PRINTF ("            H");
        else PRINTF ("            H");
        if (c) PRINTF (" %10li W", c);
        if (c) PRINTF (" %10li W", c);
        else PRINTF ("            W");
        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[])
int main_mprofiler (int argc, char *argv[])
{
{
  char fmprofname[50] = "sim.mprofile";
  char fmprofname[50] = "sim.mprofile";
  int param = 0;
  int param = 0;
  int mode = MODE_DETAIL;
  int mode = MODE_DETAIL;
 
 
  argv++; argc--;
  argv++; argc--;
  while (argc > 0) {
  while (argc > 0) {
    if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "--detail")) {
    if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "--detail")) {
      mode = MODE_DETAIL;
      mode = MODE_DETAIL;
      argv++; argc--;
      argv++; argc--;
    } else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--pretty")) {
    } else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--pretty")) {
      mode = MODE_PRETTY;
      mode = MODE_PRETTY;
      argv++; argc--;
      argv++; argc--;
    } else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--access")) {
    } else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--access")) {
      mode = MODE_ACCESS;
      mode = MODE_ACCESS;
      argv++; argc--;
      argv++; argc--;
    } else if (!strcmp(argv[0], "-w") || !strcmp(argv[0], "--width")) {
    } else if (!strcmp(argv[0], "-w") || !strcmp(argv[0], "--width")) {
      mode = MODE_WIDTH;
      mode = MODE_WIDTH;
      argv++; argc--;
      argv++; argc--;
    } else if (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--group")) {
    } else if (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--group")) {
      argv++; argc--;
      argv++; argc--;
      group_bits = strtoul (argv[0], NULL, 0);
      group_bits = strtoul (argv[0], NULL, 0);
      argv++; argc--;
      argv++; argc--;
    } else if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
    } else if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
      mp_help ();
      mp_help ();
      return 0;
      return 0;
    } else if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--filename")) {
    } else if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--filename")) {
      argv++; argc--;
      argv++; argc--;
      strcpy (&fmprofname[0], argv[0]);
      strcpy (&fmprofname[0], argv[0]);
      argv++; argc--;
      argv++; argc--;
    } else {
    } else {
      switch (param) {
      switch (param) {
        case 0:
        case 0:
          start_addr = strtoul (argv[0], NULL, 0);
          start_addr = strtoul (argv[0], NULL, 0);
          break;
          break;
        case 1:
        case 1:
          end_addr = strtoul (argv[0], NULL, 0);
          end_addr = strtoul (argv[0], NULL, 0);
          break;
          break;
        default:
        default:
          fprintf (stderr, "Invalid number of parameters.\n");
          fprintf (stderr, "Invalid number of parameters.\n");
          return -1;
          return -1;
      }
      }
      argv++; argc--; param++;
      argv++; argc--; param++;
    }
    }
  }
  }
 
 
  fprof = fopen (fmprofname, "rm");
  fprof = fopen (fmprofname, "rm");
 
 
  if (!fprof) {
  if (!fprof) {
    fprintf (stderr, "Cannot open profile file: %s\n", fmprofname);
    fprintf (stderr, "Cannot open profile file: %s\n", fmprofname);
    return 1;
    return 1;
  }
  }
 
 
  init ();
  init ();
  read_file (fprof, mode);
  read_file (fprof, mode);
  fclose (fprof);
  fclose (fprof);
  printout (mode);
  printout (mode);
  return 0;
  return 0;
}
}
 
 

powered by: WebSVN 2.1.0

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