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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [profiler.c] - Diff between revs 547 and 632

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

Rev 547 Rev 632
/* profiler.c -- profiling utility
/* profiler.c -- profiling utility
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
   Copyright (C) 2001 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 --profile option at command line, when running or1ksim.  */
   by or1ksim. (use --profile option at command line, when running or1ksim.  */
 
 
#include <stdio.h>
#include <stdio.h>
 
#include "profiler.h"
#define MAX_STACK 1024
 
#define MAX_FUNCS 1024
 
 
 
struct stack_struct {
struct stack_struct {
  /* Function address */
  /* Function address */
  unsigned int addr;
  unsigned int addr;
 
 
  /* Cycles of function start; cycles of subfunctions are added later */
  /* Cycles of function start; cycles of subfunctions are added later */
  unsigned int cycles;
  unsigned int cycles;
 
 
  /* Return address */
  /* Return address */
  unsigned int raddr;
  unsigned int raddr;
 
 
  /* Name of the function */
  /* Name of the function */
  char name[33];
  char name[33];
} stack[MAX_STACK];
} stack[MAX_STACK];
 
 
struct func_struct {
struct func_struct {
  /* Start address of function */
  /* Start address of function */
  unsigned int addr;
  unsigned int addr;
 
 
  /* Name of the function */
  /* Name of the function */
  char name[33];
  char name[33];
 
 
  /* Total cycles spent in function */
  /* Total cycles spent in function */
  long cum_cycles;
  long cum_cycles;
 
 
  /* Calls to this function */
  /* Calls to this function */
  long calls;
  long calls;
} func[MAX_FUNCS];
} func[MAX_FUNCS];
 
 
/* Total number of functions */
/* Total number of functions */
int nfuncs = 0;
int nfuncs = 0;
 
 
/* Current depth */
/* Current depth */
int nstack = 0;
int nstack = 0;
 
 
/* Max depth */
/* Max depth */
int maxstack = 0;
int maxstack = 0;
 
 
/* Number of total calls */
/* Number of total calls */
int ntotcalls = 0;
int ntotcalls = 0;
 
 
/* Number of covered calls */
/* Number of covered calls */
int nfunccalls = 0;
int nfunccalls = 0;
 
 
/* Current cycles */
/* Current cycles */
static int cycles = 0;
static int cycles = 0;
 
 
/* Whether we are in cumulative mode */
/* Whether we are in cumulative mode */
static int cumulative = 0;
static int cumulative = 0;
 
 
/* Whether we should not report warnings */
/* Whether we should not report warnings */
static int quiet = 0;
static int quiet = 0;
 
 
/* File to read from */
/* File to read from */
static FILE *fprof = 0;
static FILE *fprof = 0;
 
 
int main (int argc, char *argv[]) {
int main_profile (int mode, char *fname) {
  char fprofname[50] = "sim.profile";
  char fprofname[50] = "sim.profile";
  int line = 0;
  int line = 0;
  if (argc > 4 || argc < 2) {
 
    fprintf (stderr, "USAGE: profiler [--cumulative|-c] [--quiet|-q] --generate|-g [profile_file_name]\n");
 
    exit(1);
 
  }
 
  argv++; argc--;
 
  while (argc > 0) {
 
    if (!strcmp(argv[0], "-q") || !strcmp(argv[0], "--quiet")) {
 
      quiet = 1;
 
      argv++; argc--;
 
    } else if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--cumulative")) {
 
      cumulative = 1;
 
      argv++; argc--;
 
    } else if (strcmp(argv[0], "-g") && strcmp(argv[0], "--generate")) {
 
      fprintf (stderr, "USAGE: profiler [--cumulative|-c] [--generate|-g] [profile_file_name]\n");
 
      exit(1);
 
    } else {
 
      argv++; argc--;
 
      if (argv[0] && argv[0][0] != '-') {
 
        strcpy (&fprofname[0], argv[0]);
 
        argv++; argc--;
 
      }
 
    }
 
  }
 
 
 
  fprof = fopen (&fprofname[0], "rt");
  /*
 
  if (argc > 4 || argc < 2) {
 
    fprintf (stderr, "USAGE: profiler [--cumulative|-c] [--quiet|-q] --generate|-g [profile_file_name]\n");
 
    exit(1);
 
  }
 
  */
 
 
 
  if (mode && PROF_CUMULATIVE) cumulative = 1;
 
  if (mode && PROF_QUIET)      quiet = 1;
 
  if (!fname)                  fname = fprofname;
 
 
 
  /*
 
  argv++; argc--;
 
  while (argc > 0) {
 
    if (!strcmp(argv[0], "-q") || !strcmp(argv[0], "--quiet")) {
 
      quiet = 1;
 
      argv++; argc--;
 
    } else if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--cumulative")) {
 
      cumulative = 1;
 
      argv++; argc--;
 
    } else if (strcmp(argv[0], "-g") && strcmp(argv[0], "--generate")) {
 
      fprintf (stderr, "USAGE: profiler [--cumulative|-c] [--generate|-g] [profile_file_name]\n");
 
      exit(1);
 
    } else {
 
      argv++; argc--;
 
      if (argv[0] && argv[0][0] != '-') {
 
        strcpy (&fprofname[0], argv[0]);
 
        argv++; argc--;
 
      }
 
    }
 
  }
 
  */
 
 
 
  fprof = fopen (fname, "rt");
 
 
  if (!fprof) {
  if (!fprof) {
    fprintf (stderr, "Cannot open profile file: %s\n", &fprofname[0]);
    fprintf (stderr, "Cannot open profile file: %s\n", fname);
    exit(1);
    exit(1);
  }
  }
 
 
  while (1) {
  while (1) {
    char dir = fgetc (fprof);
    char dir = fgetc (fprof);
    line++;
    line++;
    if (dir == '+') {
    if (dir == '+') {
      if (fscanf (fprof, "%08X %08X %08X %s\n", &stack[nstack].cycles, &stack[nstack].raddr,
      if (fscanf (fprof, "%08X %08X %08X %s\n", &stack[nstack].cycles, &stack[nstack].raddr,
                  &stack[nstack].addr, &stack[nstack].name[0]) != 4)
                  &stack[nstack].addr, &stack[nstack].name[0]) != 4)
        fprintf (stderr, "Error reading line #%i\n", line);
        fprintf (stderr, "Error reading line #%i\n", line);
      else {
      else {
        cycles = stack[nstack].cycles;
        cycles = stack[nstack].cycles;
        nstack++;
        nstack++;
        if (nstack > maxstack)
        if (nstack > maxstack)
          maxstack = nstack;
          maxstack = nstack;
      }
      }
      ntotcalls++;
      ntotcalls++;
    } else if (dir == '-') {
    } else if (dir == '-') {
      struct stack_struct s;
      struct stack_struct s;
      if (fscanf (fprof, "%08X %08X\n", &s.cycles, &s.raddr) != 2)
      if (fscanf (fprof, "%08X %08X\n", &s.cycles, &s.raddr) != 2)
        fprintf (stderr, "Error reading line #%i\n", line);
        fprintf (stderr, "Error reading line #%i\n", line);
      else {
      else {
        int i;
        int i;
        cycles = s.cycles;
        cycles = s.cycles;
        for (i = nstack - 1; i >= 0; i--)
        for (i = nstack - 1; i >= 0; i--)
          if (stack[i].raddr == s.raddr) break;
          if (stack[i].raddr == s.raddr) break;
        if (i >= 0) {
        if (i >= 0) {
          /* pop everything above current from stack,
          /* pop everything above current from stack,
             if more than one, something went wrong */
             if more than one, something went wrong */
          while (nstack > i) {
          while (nstack > i) {
            int j;
            int j;
            long time;
            long time;
            nstack--;
            nstack--;
            time = s.cycles - stack[nstack].cycles;
            time = s.cycles - stack[nstack].cycles;
            if (!quiet && time < 0) {
            if (!quiet && time < 0) {
              fprintf (stderr, "WARNING: Negative time at %s (return addr = %08X).\n", stack[i].name, stack[i].raddr);
              fprintf (stderr, "WARNING: Negative time at %s (return addr = %08X).\n", stack[i].name, stack[i].raddr);
              time = 0;
              time = 0;
            }
            }
 
 
            /* Whether in normal mode, we must substract called function from execution time.  */
            /* Whether in normal mode, we must substract called function from execution time.  */
            if (!cumulative)
            if (!cumulative)
              for (j = 0; j < nstack; j++)
              for (j = 0; j < nstack; j++)
                stack[j].cycles += time;
                stack[j].cycles += time;
 
 
            if (!quiet && i != nstack)
            if (!quiet && i != nstack)
              fprintf (stderr, "WARNING: Missaligned return call for %s (%08X) (found %s @ %08X), closing.\n", stack[nstack].name, stack[nstack].raddr, stack[i].name, stack[i].raddr);
              fprintf (stderr, "WARNING: Missaligned return call for %s (%08X) (found %s @ %08X), closing.\n", stack[nstack].name, stack[nstack].raddr, stack[i].name, stack[i].raddr);
 
 
            for (j = 0; j < nfuncs; j++)
            for (j = 0; j < nfuncs; j++)
              if (stack[nstack].addr == func[j].addr) { /* function exists, append. */
              if (stack[nstack].addr == func[j].addr) { /* function exists, append. */
                func[j].cum_cycles += time;
                func[j].cum_cycles += time;
                func[j].calls++;
                func[j].calls++;
                nfunccalls++;
                nfunccalls++;
                break;
                break;
              }
              }
            if (j >= nfuncs) { /* function does not yet exist, create new. */
            if (j >= nfuncs) { /* function does not yet exist, create new. */
              func[nfuncs].cum_cycles = time;
              func[nfuncs].cum_cycles = time;
              func[nfuncs].calls = 1;
              func[nfuncs].calls = 1;
              nfunccalls++;
              nfunccalls++;
              func[nfuncs].addr = stack[nstack].addr;
              func[nfuncs].addr = stack[nstack].addr;
              strcpy (func[nfuncs].name, stack[nstack].name);
              strcpy (func[nfuncs].name, stack[nstack].name);
              nfuncs++;
              nfuncs++;
            }
            }
          }
          }
        } else if (!quiet) fprintf (stderr, "WARNING: Cannot find return call for (%08X), ignoring.\n", s.raddr);
        } else if (!quiet) fprintf (stderr, "WARNING: Cannot find return call for (%08X), ignoring.\n", s.raddr);
      }
      }
    } else
    } else
      break;
      break;
  }
  }
  fclose(fprof);
  fclose(fprof);
 
 
  /* Now we have all data acquired. Print out. */
  /* Now we have all data acquired. Print out. */
  {
  {
    int i, j;
    int i, j;
    if (cumulative)
    if (cumulative)
      printf ("CUMULATIVE TIMES\n");
      printf ("CUMULATIVE TIMES\n");
    printf ("---------------------------------------------------------------------------\n");
    printf ("---------------------------------------------------------------------------\n");
    printf ("|function name            |addr    |# calls |avg cycles  |total cyles     |\n");
    printf ("|function name            |addr    |# calls |avg cycles  |total cyles     |\n");
    printf ("|-------------------------+--------+--------+------------+----------------|\n");
    printf ("|-------------------------+--------+--------+------------+----------------|\n");
    for (j = 0; j < nfuncs; j++) {
    for (j = 0; j < nfuncs; j++) {
      int bestcyc = 0, besti = 0;
      int bestcyc = 0, besti = 0;
      for (i = 0; i < nfuncs; i++)
      for (i = 0; i < nfuncs; i++)
        if (func[i].cum_cycles > bestcyc) {
        if (func[i].cum_cycles > bestcyc) {
          bestcyc = func[i].cum_cycles;
          bestcyc = func[i].cum_cycles;
          besti = i;
          besti = i;
        }
        }
      i = besti;
      i = besti;
      printf ("| %-24s|%08X|%8i|%12.1f|%11i,%3.0f%%|\n",
      printf ("| %-24s|%08X|%8i|%12.1f|%11i,%3.0f%%|\n",
              func[i].name, func[i].addr, func[i].calls, ((double)func[i].cum_cycles / func[i].calls), func[i].cum_cycles, (100. * func[i].cum_cycles / cycles));
              func[i].name, func[i].addr, func[i].calls, ((double)func[i].cum_cycles / func[i].calls), func[i].cum_cycles, (100. * func[i].cum_cycles / cycles));
      func[i].cum_cycles = -1;
      func[i].cum_cycles = -1;
    }
    }
    printf ("---------------------------------------------------------------------------\n");
    printf ("---------------------------------------------------------------------------\n");
  }
  }
  printf ("Total %i functions, %i cycles.\n", nfuncs, cycles);
  printf ("Total %i functions, %i cycles.\n", nfuncs, cycles);
  printf ("Total function calls %i/%i (max depth %i).\n", nfunccalls, ntotcalls, maxstack);
  printf ("Total function calls %i/%i (max depth %i).\n", nfunccalls, ntotcalls, maxstack);
  return 0;
  return 0;
}
}
 
 

powered by: WebSVN 2.1.0

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