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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [profiler.c] - Diff between revs 19 and 100

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

Rev 19 Rev 100
/* profiler.c -- profiling utility
/* profiler.c -- profiling utility
 
 
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
   Copyright (C) 2001 Marko Mlinar, markom@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. */
 
 
/* Command line utility, that displays profiling information, generated
/* Command line utility, that displays profiling information, generated
   by or1ksim. (use profile command interactively, when running or1ksim, or
   by or1ksim. (use profile command interactively, when running or1ksim, or
   separate psim command).  */
   separate psim command).  */
 
 
 
#define PROF_DEBUG 0
 
 
/* Autoconf and/or portability configuration */
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
#include "port.h"
#include "port.h"
 
 
/* Package includes */
/* Package includes */
#include "profiler.h"
#include "profiler.h"
#include "sim-config.h"
#include "sim-config.h"
#include "argtable2.h"
#include "argtable2.h"
 
 
/*! Maximum stack frames that can be profiled */
/*! Maximum stack frames that can be profiled */
#define MAX_STACK  1024
#define MAX_STACK  262144
 
 
/*! Data structure representing information about a stack frame */
/*! Data structure representing information about a stack frame */
struct stack_struct
struct stack_struct
{
{
  unsigned int  addr;      /*!< Function address */
  unsigned int  addr;      /*!< Function address */
  unsigned int  cycles;    /*!< Cycles of func start; subfuncs added later */
  unsigned int  cycles;    /*!< Cycles of func start; subfuncs added later */
  unsigned int  raddr;     /*!< Return address */
  unsigned int  raddr;     /*!< Return address */
  char          name[33];  /*!< Name of the function */
  char          name[33];  /*!< Name of the function */
};
};
 
 
/*! Global: data about functions */
/*! Global: data about functions */
struct func_struct  prof_func[MAX_FUNCS];
struct func_struct  prof_func[MAX_FUNCS];
 
 
/*! Global: total number of functions */
/*! Global: total number of functions */
int  prof_nfuncs = 0;
int  prof_nfuncs = 0;
 
 
/*! Global: current cycles */
/*! Global: current cycles */
int  prof_cycles = 0;
int  prof_cycles = 0;
 
 
/*! Representation of the stack */
/*! Representation of the stack */
static struct stack_struct  stack[MAX_STACK];
static struct stack_struct  stack[MAX_STACK];
 
 
/*! Current depth */
/*! Current depth */
static int  nstack = 0;
static int  nstack = 0;
 
 
/*! Max depth */
/*! Max depth */
static int  maxstack = 0;
static int  maxstack = 0;
 
 
/*! Number of total calls */
/*! Number of total calls */
static int  ntotcalls = 0;
static int  ntotcalls = 0;
 
 
/*! Number of covered calls */
/*! Number of covered calls */
static int  nfunccalls = 0;
static int  nfunccalls = 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;
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*! Acquire data from profiler file
/*! Acquire data from profiler file
 
 
  @param[in] fprofname   Data file to analyse
  @param[in] fprofname   Data file to analyse
 
 
  @return  0 on success, return code otherwise                               */
  @return  0 on success, return code otherwise                               */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
int
prof_acquire (const char *fprofname)
prof_acquire (const char *fprofname)
{
{
  int line = 0;
  int line = 0;
  int reopened = 0;
  int reopened = 0;
 
 
  if (runtime.sim.fprof)
  if (runtime.sim.fprof)
    {
    {
      fprof = runtime.sim.fprof;
      fprof = runtime.sim.fprof;
      reopened = 1;
      reopened = 1;
 
      if (PROF_DEBUG) printf("reopened=1\n");
      rewind (fprof);
      rewind (fprof);
    }
    }
  else
  else
    fprof = fopen (fprofname, "rt");
    fprof = fopen (fprofname, "rt");
 
 
  if (!fprof)
  if (!fprof)
    {
    {
      fprintf (stderr, "Cannot open profile file: %s\n", fprofname);
      fprintf (stderr, "Cannot open profile file: %s\n", fprofname);
      return 1;
      return 1;
    }
    }
 
  int ctr =0;
  while (1)
  while (1)
    {
    {
 
      if (PROF_DEBUG) printf("%d ",ctr++);
      char dir = fgetc (fprof);
      char dir = fgetc (fprof);
      line++;
      line++;
      if (dir == '+')
      if (dir == '+')
        {
        {
          if (fscanf
          if (fscanf
              (fprof, "%08X %08X %08X %s\n", &stack[nstack].cycles,
              (fprof, "%08X %08X %08X %s\n", &stack[nstack].cycles,
               &stack[nstack].raddr, &stack[nstack].addr,
               &stack[nstack].raddr, &stack[nstack].addr,
               &stack[nstack].name[0]) != 4)
               &stack[nstack].name[0]) != 4)
            fprintf (stderr, "Error reading line #%i\n", line);
            fprintf (stderr, "Error reading line #%i\n", line);
          else
          else
            {
            {
              prof_cycles = stack[nstack].cycles;
              prof_cycles = stack[nstack].cycles;
              nstack++;
              nstack++;
 
              if (PROF_DEBUG) printf("+ 0x%.8x nstack %d\n",stack[nstack-1].raddr, 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;
              prof_cycles = s.cycles;
              prof_cycles = s.cycles;
 
              if (PROF_DEBUG) printf("- 0x%.8x nstack %d\n",s.raddr ,nstack);
              for (i = nstack - 1; i >= 0; i--)
              for (i = nstack - 1; i >= 0; i--)
                if (stack[i].raddr == s.raddr)
                if (stack[i].raddr == s.raddr)
                  break;
                  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,
                          fprintf (stderr,
                                   "WARNING: Negative time at %s (return addr = %08X).\n",
                                   "WARNING: Negative time at %s (return addr = %08X).\n",
                                   stack[i].name, stack[i].raddr);
                                   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,
                        fprintf (stderr,
                                 "WARNING: Missaligned return call for %s (%08X) (found %s @ %08X), closing.\n",
                                 "WARNING: Missaligned return call for %s (%08X) (found %s @ %08X), closing.\n",
                                 stack[nstack].name, stack[nstack].raddr,
                                 stack[nstack].name, stack[nstack].raddr,
                                 stack[i].name, stack[i].raddr);
                                 stack[i].name, stack[i].raddr);
 
 
                      for (j = 0; j < prof_nfuncs; j++)
                      for (j = 0; j < prof_nfuncs; j++)
                        if (stack[nstack].addr == prof_func[j].addr)
                        if (stack[nstack].addr == prof_func[j].addr)
                          {     /* function exists, append. */
                          {     /* function exists, append. */
                            prof_func[j].cum_cycles += time;
                            prof_func[j].cum_cycles += time;
                            prof_func[j].calls++;
                            prof_func[j].calls++;
                            nfunccalls++;
                            nfunccalls++;
                            break;
                            break;
                          }
                          }
                      if (j >= prof_nfuncs)
                      if (j >= prof_nfuncs)
                        {       /* function does not yet exist, create new. */
                        {       /* function does not yet exist, create new. */
                          prof_func[prof_nfuncs].cum_cycles = time;
                          prof_func[prof_nfuncs].cum_cycles = time;
                          prof_func[prof_nfuncs].calls = 1;
                          prof_func[prof_nfuncs].calls = 1;
                          nfunccalls++;
                          nfunccalls++;
                          prof_func[prof_nfuncs].addr = stack[nstack].addr;
                          prof_func[prof_nfuncs].addr = stack[nstack].addr;
                          strcpy (prof_func[prof_nfuncs].name,
                          strcpy (prof_func[prof_nfuncs].name,
                                  stack[nstack].name);
                                  stack[nstack].name);
                          prof_nfuncs++;
                          prof_nfuncs++;
                        }
                        }
                    }
                    }
                }
                }
              else if (!quiet)
              else if (!quiet)
                fprintf (stderr,
                fprintf (stderr,
                         "WARNING: Cannot find return call for (%08X), ignoring.\n",
                         "WARNING: Cannot find return call for (%08X), ignoring.\n",
                         s.raddr);
                         s.raddr);
            }
            }
        }
        }
      else
      else
        break;
        break;
    }
    }
 
 
  /* If we have reopened the file, we need to add end of "[outside functions]" */
  /* If we have reopened the file, we need to add end of "[outside functions]" */
  if (reopened)
  if (reopened)
    {
    {
      prof_cycles = runtime.sim.cycles;
      prof_cycles = runtime.sim.cycles;
      /* 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 > 0)
      while (nstack > 0)
        {
        {
          int j;
          int j;
          long time;
          long time;
          nstack--;
          nstack--;
          time = runtime.sim.cycles - stack[nstack].cycles;
          time = runtime.sim.cycles - stack[nstack].cycles;
          /* 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;
 
 
          for (j = 0; j < prof_nfuncs; j++)
          for (j = 0; j < prof_nfuncs; j++)
            if (stack[nstack].addr == prof_func[j].addr)
            if (stack[nstack].addr == prof_func[j].addr)
              {                 /* function exists, append. */
              {                 /* function exists, append. */
                prof_func[j].cum_cycles += time;
                prof_func[j].cum_cycles += time;
                prof_func[j].calls++;
                prof_func[j].calls++;
                nfunccalls++;
                nfunccalls++;
                break;
                break;
              }
              }
          if (j >= prof_nfuncs)
          if (j >= prof_nfuncs)
            {                   /* function does not yet exist, create new. */
            {                   /* function does not yet exist, create new. */
              prof_func[prof_nfuncs].cum_cycles = time;
              prof_func[prof_nfuncs].cum_cycles = time;
              prof_func[prof_nfuncs].calls = 1;
              prof_func[prof_nfuncs].calls = 1;
              nfunccalls++;
              nfunccalls++;
              prof_func[prof_nfuncs].addr = stack[nstack].addr;
              prof_func[prof_nfuncs].addr = stack[nstack].addr;
              strcpy (prof_func[prof_nfuncs].name, stack[nstack].name);
              strcpy (prof_func[prof_nfuncs].name, stack[nstack].name);
              prof_nfuncs++;
              prof_nfuncs++;
            }
            }
        }
        }
    }
    }
  else
  else
    fclose (fprof);
    fclose (fprof);
  return 0;
  return 0;
}
}
 
 
/* Print out profiling data */
/* Print out profiling data */
static void
static void
prof_print ()
prof_print ()
{
{
  int i, j;
  int i, j;
  if (cumulative)
  if (cumulative)
    PRINTF ("CUMULATIVE TIMES\n");
    PRINTF ("CUMULATIVE TIMES\n");
  PRINTF
  PRINTF
    ("---------------------------------------------------------------------------\n");
    ("---------------------------------------------------------------------------\n");
  PRINTF
  PRINTF
    ("|function name            |addr    |# calls |avg cycles  |total cyles     |\n");
    ("|function name            |addr    |# calls |avg cycles  |total cyles     |\n");
  PRINTF
  PRINTF
    ("|-------------------------+--------+--------+------------+----------------|\n");
    ("|-------------------------+--------+--------+------------+----------------|\n");
  for (j = 0; j < prof_nfuncs; j++)
  for (j = 0; j < prof_nfuncs; j++)
    {
    {
      int bestcyc = 0, besti = 0;
      int bestcyc = 0, besti = 0;
      for (i = 0; i < prof_nfuncs; i++)
      for (i = 0; i < prof_nfuncs; i++)
        if (prof_func[i].cum_cycles > bestcyc)
        if (prof_func[i].cum_cycles > bestcyc)
          {
          {
            bestcyc = prof_func[i].cum_cycles;
            bestcyc = prof_func[i].cum_cycles;
            besti = i;
            besti = i;
          }
          }
      i = besti;
      i = besti;
      PRINTF ("| %-24s|%08X|%8li|%12.1f|%11li,%3.0f%%|\n",
      PRINTF ("| %-24s|%08X|%8li|%12.1f|%11li,%3.0f%%|\n",
              prof_func[i].name, prof_func[i].addr, prof_func[i].calls,
              prof_func[i].name, prof_func[i].addr, prof_func[i].calls,
              ((double) prof_func[i].cum_cycles / prof_func[i].calls),
              ((double) prof_func[i].cum_cycles / prof_func[i].calls),
              prof_func[i].cum_cycles,
              prof_func[i].cum_cycles,
              (100. * prof_func[i].cum_cycles / prof_cycles));
              (100. * prof_func[i].cum_cycles / prof_cycles));
      prof_func[i].cum_cycles = -1;
      prof_func[i].cum_cycles = -1;
    }
    }
  PRINTF
  PRINTF
    ("---------------------------------------------------------------------------\n");
    ("---------------------------------------------------------------------------\n");
  PRINTF ("Total %i functions, %i cycles.\n", prof_nfuncs, prof_cycles);
  PRINTF ("Total %i functions, %i cycles.\n", prof_nfuncs, prof_cycles);
  PRINTF ("Total function calls %i/%i (max depth %i).\n", nfunccalls,
  PRINTF ("Total function calls %i/%i (max depth %i).\n", nfunccalls,
          ntotcalls, maxstack);
          ntotcalls, maxstack);
}
}
 
 
/* Set options */
/* Set options */
void
void
prof_set (int _quiet, int _cumulative)
prof_set (int _quiet, int _cumulative)
{
{
  quiet = _quiet;
  quiet = _quiet;
  cumulative = _cumulative;
  cumulative = _cumulative;
}
}
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*! 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_profiler (int argc, char *argv[], int just_help)
main_profiler (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_lit *cum_arg;
  struct arg_lit *cum_arg;
  struct arg_lit *quiet_arg;
  struct arg_lit *quiet_arg;
  struct arg_file *gen_file;
  struct arg_file *gen_file;
  struct arg_end *end;
  struct arg_end *end;
 
 
  void *argtab[6];
  void *argtab[6];
  int nerrors;
  int nerrors;
 
 
  /* Specify each argument, with fallback values */
  /* Specify each argument, with fallback values */
  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");
  cum_arg = arg_lit0 ("c", "cumulative",
  cum_arg = arg_lit0 ("c", "cumulative",
                      "cumulative sum of cycles in functions");
                      "cumulative sum of cycles in functions");
  quiet_arg = arg_lit0 ("q", "quiet", "suppress messages");
  quiet_arg = arg_lit0 ("q", "quiet", "suppress messages");
  gen_file = arg_file0 ("g", "generate", "<file>",
  gen_file = arg_file0 ("g", "generate", "<file>",
                        "data file to analyse (default " "sim.profile)");
                        "data file to analyse (default " "sim.profile)");
  gen_file->filename[0] = "sim.profile";
  gen_file->filename[0] = "sim.profile";
  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] = cum_arg;
  argtab[2] = cum_arg;
  argtab[3] = quiet_arg;
  argtab[3] = quiet_arg;
  argtab[4] = gen_file;
  argtab[4] = gen_file;
  argtab[5] = end;
  argtab[5] = 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 ("profile");
      printf ("profile");
      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 Profiling Utility, version %s\n",
      PRINTF ("OpenRISC 1000 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, "profile");
      arg_print_errors (stderr, end, "profile");
      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;
    }
    }
 
 
  /* Cumulative result wanted? */
  /* Cumulative result wanted? */
  cumulative = cum_arg->count;
  cumulative = cum_arg->count;
 
 
  /* Suppress messages? */
  /* Suppress messages? */
  quiet = quiet_arg->count;
  quiet = quiet_arg->count;
 
 
  /* Get the profile from the file */
  /* Get the profile from the file */
  prof_acquire (gen_file->filename[0]);
  prof_acquire (gen_file->filename[0]);
 
 
  /* Now we have all data acquired. Print out. */
  /* Now we have all data acquired. Print out. */
  prof_print ();
  prof_print ();
 
 
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
  return 0;
  return 0;
 
 
}                               /* main_profiler() */
}                               /* main_profiler() */
 
 

powered by: WebSVN 2.1.0

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