⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profiler.c

📁 realview22.rar
💻 C
字号:
/* profiler.c - module to do ARMsd profiling
 * Copyright (c) 1996-1998  Advanced RISC Machines Limited. 
 * Copyright (C) 1998-2001  ARM Limited.
 * All Rights Reserved.
 *
 * RCS $Revision: 1.6.4.6 $
 * Checkin $Date: 2001/08/28 13:01:28 $
 * Revising $Author: dsinclai $
 */

#define MODEL_NAME Profiler

#include <stdlib.h>
#include <string.h>


#include "minperip.h"

#include "armul_callbackid.h"
#include "rdi_prop.h"  /* for RDIProperty_SetAsNumeric */


#if 0 /* ndef NDEBUG */
# if 1
#  define VERBOSE
# else
#  define VERBOSE_EVENT
# endif
#endif


#define ARMulCnf_EventMask (tag_t)"EVENTMASK"
#define ARMulCnf_Event (tag_t)"EVENT"
#define ARMulCnf_Verbose (tag_t)"VERBOSE"
#define ARMulCnf_Type (tag_t)"TYPE"
#define ARMulCnf_EventWord (tag_t)"EVENTWORD"

BEGIN_STATE_DECL(Profiler)
  ARMword mapsize;
  ARMword *map;
  ARMword *counts;
  enum {
    PROFILE_usec, PROFILE_cycle,
    PROFILE_event1, PROFILE_event2, PROFILE_eventpc
    } prof_type;
  void *handle;
  union {
    struct {
      unsigned long rate;
      unsigned int ignore;
    } usec;
    struct {
      ARMTime last;
      unsigned long interval, countdown;
    } cycle;
    struct {
      unsigned long mask, value;
    } event;
  } x;
  bool verbose;
END_STATE_DECL(Profiler)

static void count(ProfilerState *p,ARMword pc,unsigned cnt)
{
  ARMword *map = p->map;
  ARMword size = p->mapsize;
  ARMword low = 0, high = size-1;

  /* binary search */
  if (map[low] <= pc && pc < map[high]) {
    ARMword i;
    for (;;) {
      i = (high + low) / 2;
      if (pc >= map[i]) {
        if (pc < map[i+1]) {
          i++; break;
        } else
          low = i;
      } else if (pc >= map[i-1])
        break;
      else
        high = i;
    }
    p->counts[i-1]+=cnt;
  }
}

/*
 * Microsecond-based scheduler
 * This is an ARMul_EventProc
 */
static void ProfileMicrosecond(void *handle)
{
  ProfilerState *p = (ProfilerState *)handle;

  if (p->verbose)
      Hostif_DebugPrint(p->hostif,"ProfileMicrosecond\n");


  if (!p->x.usec.ignore) {
    (void)ARMulif_ScheduleNewTimedCallback(
        &p->coredesc, ProfileMicrosecond, handle, 
        p->x.usec.rate + ARMulif_Time(&p->coredesc), 0);
    count(p, ARMulif_GetPC(&p->coredesc), 1);
  } else {
    p->handle = handle;
    p->x.usec.ignore = FALSE;
  }

  return ;
}

/*
 * Cycles-based profiler
 * This is an hourglass function
 */
static void ProfileCycles(void *handle, ARMword pc, ARMword instr)
{
  ProfilerState *p = (ProfilerState *)handle;
#ifdef VERBOSE_EVENT
  if (p->verbose)
      Hostif_ConsolePrint(p->hostif, "ProfileCycles pc:%08lx\n",
                          (unsigned long)pc);
#endif
  
#ifndef COMPLEX_HOURGLASS
  if (--p->x.cycle.countdown == 0)
  {
#endif
      ARMTime t = ARMulif_Time(&p->coredesc);
      unsigned long delta = (unsigned long)(t - p->x.cycle.last);
      p->x.cycle.last = t;

      count(p, pc, delta);

#ifndef COMPLEX_HOURGLASS
      p->x.cycle.countdown = p->x.cycle.interval;
  }
#endif

  UNUSEDARG(instr);
}

/*
 * Events based profiler
 * This is an EventProc function
 */
static unsigned ProfileEvents(
    void *handle, void *data)
{
    ARMul_Event *evt = (ARMul_Event *)data;
  ProfilerState *p=(ProfilerState *)handle;
  ARMword addr;
  unsigned int event = evt->event;
  ARMword addr1 = evt->data1; ARMword addr2 = evt->data2;

  /*
   * profiling function that lets you profile by event, e.g. cache misses
   */
  
  if ((event & p->x.event.mask)==p->x.event.value)
  {
  
      switch (p->prof_type) {
      case PROFILE_event1: addr=addr1; break;
      case PROFILE_event2: addr=addr2; break;
      default:
      case PROFILE_eventpc: addr=ARMulif_GetPC(&p->coredesc); break;
      }

      count(p,addr,1);
  }

  return 0; /* Carry on */
}

static int RDI_info(void *handle, unsigned type, ARMword *arg1, ARMword *arg2)
{
    ProfilerState *p=(ProfilerState *)handle;

#ifdef VERBOSE
    if (p->verbose)
        Hostif_DebugPrint(p->hostif,"RDI_info %08lx\n", (unsigned long)type);
#endif

  switch (type) {
  case RDIInfo_Target:
#ifdef VERBOSE
      if (p->verbose)
          Hostif_DebugPrint(p->hostif, "Info_Target\n");
#endif
    /* Add the "we can do profiling" capability */
    *arg1 = (*arg1) | RDITarget_CanProfile;
    /* return Unimplemented because this should be passed on */
    return RDIError_UnimplementedMessage;

  case RDIProfile_Stop:
#ifdef VERBOSE
      if (p->verbose)
          Hostif_DebugPrint(p->hostif, "Profile_Stop\n");
#endif
    if (p->handle != NULL) switch (p->prof_type) {
    case PROFILE_usec:
      p->x.usec.ignore = TRUE;
      break;

    case PROFILE_cycle:
      ARMulif_RemoveHourglass(&p->coredesc, p->handle);
      p->handle = NULL;
      break;

    case PROFILE_event1:
    case PROFILE_event2:
    case PROFILE_eventpc:
        ARMulif_RemoveEventHandler(&p->coredesc, p->handle);
      p->handle = NULL;
      break;
    }
    return RDIError_NoError;
      
  case RDIProfile_Start:
    if (p->handle == NULL) switch (p->prof_type) {
    case PROFILE_usec: {
      /* ARG1 is in microseconds. Convert this to bus-cycles. */
      double rate = (double)*arg1 * 10000.0;
      double cycle_length = (double)ARMulif_GetCycleLength(&p->coredesc);


      p->x.usec.ignore = FALSE;
      if (cycle_length != 0.0) {
        p->x.usec.rate = (unsigned long)(rate / cycle_length);
      } else {
        p->x.usec.rate = *arg1;
      }
      (void) ARMulif_ScheduleNewTimedCallback(
          &p->coredesc, ProfileMicrosecond, (void *)p,
          p->x.usec.rate + ARMulif_Time(&p->coredesc),0
          );

#ifdef VERBOSE
      if (p->verbose)
          Hostif_DebugPrint(p->hostif, "Profile_Start, microsecond "
                            "rate:%08lx\n", (unsigned long)p->x.usec.rate);
#endif
    }
      break;

    case PROFILE_cycle:
      p->handle = ARMulif_InstallHourglass(&p->coredesc, 
                                                           (armul_Hourglass*)ProfileCycles, p); /* !TIP!*/
      p->x.cycle.interval = *arg1;
      p->x.cycle.last = ARMulif_Time(&p->coredesc);

      /* We're called every cycle, so count-down ourselves. */
      p->x.cycle.countdown = p->x.cycle.interval;
#ifdef VERBOSE
      if (p->verbose)
          Hostif_DebugPrint(p->hostif, "Profile_Start, cycle, interval:%lu\n",
                            (unsigned long)p->x.cycle.interval);
#endif
      break;

    case PROFILE_event1:
    case PROFILE_event2:
    case PROFILE_eventpc:
#ifdef VERBOSE
      if (p->verbose)
          Hostif_DebugPrint(p->hostif, "Profile_Start, event\n");
#endif
        p->handle = ARMulif_InstallEventHandler(&p->coredesc, 
                                                ~(uint32)0, 
                                                ProfileEvents, p);
      break;
    }
    return RDIError_NoError;

  case RDIProfile_WriteMap:
    { RDI_ProfileMap *map = (RDI_ProfileMap *)arg1;
      size_t bytes = (size_t)map->len * sizeof(ARMword);

#ifdef VERBOSE
      if (p->verbose)
      {
          unsigned i;
          Hostif_DebugPrint(p->hostif,"RDIProfile_WriteMap len=%u [words]\n",
                            (unsigned)map->len);
          for (i=0; i < map->len; i++)
          {
              Hostif_DebugPrint(p->hostif,"%08lx ",
                                (unsigned long)map->map[i]);
          }
          Hostif_DebugPrint(p->hostif,"\n");
      }
#endif


      if (p->mapsize != map->len) {
        if (p->mapsize != 0) {
          free(p->map);
          free(p->counts);
        }
        p->map = NULL;
      }
      if (p->map == NULL) {
        p->map = (ARMword *)malloc(bytes);
        p->counts = (ARMword *)malloc(bytes);
        if (p->map == NULL || p->counts == NULL)
          return RDIError_OutOfStore;
      }
      p->mapsize = map->len;
      memcpy(p->map, map->map, bytes);
      /* and fall through to clear counts */
    }

  case RDIProfile_ClearCounts:
#ifdef VERBOSE
      if (p->verbose)
          Hostif_DebugPrint(p->hostif,"RDIProfile_ClearMap\n");
#endif
    memset(p->counts, 0, (size_t)p->mapsize * sizeof(ARMword));
    return RDIError_NoError;

  case RDIProfile_ReadMap:
#ifdef VERBOSE
      if (p->verbose)
      {
          unsigned i, n = (unsigned)*arg1;
          Hostif_DebugPrint(p->hostif,"RDIProfile_ReadMap length %lu\n",
                            (unsigned long)n);
          for (i=0; i < n; i++)
          {
              Hostif_DebugPrint(p->hostif,"%08lx ",
                            (unsigned long)p->counts[i]);
          }
          Hostif_DebugPrint(p->hostif,"\n");
      }
#endif
    { ARMword len = *(ARMword *)arg1;
      memcpy(arg2, p->counts, (size_t)len * sizeof(ARMword));
      return RDIError_NoError;
    }



    case RDIProperty_SetAsNumeric:
    {
        unsigned PrID = (unsigned)arg1;
        if (arg2 == NULL)
            return RDIError_UnimplementedMessage;
        switch (PrID)
        {
        case RDIPropID_ARMulProp_Hostif:
            p->hostif = *(struct RDI_HostosInterface const **)arg2;
            return RDIError_UnimplementedMessage;
        default:
            return RDIError_UnimplementedMessage;
        }   
    }


  default:
    if (type & RDIInfo_CapabilityRequest) {
      switch (type & ~RDIInfo_CapabilityRequest) {
      case RDIProfile_Stop:           case RDIProfile_Start:
      case RDIProfile_WriteMap:       case RDIProfile_ClearCounts:
      case RDIProfile_ReadMap:
        return RDIError_NoError;
      }
    }
    break;
  }

  return RDIError_UnimplementedMessage;
}

/*
 * Reset handler -- to deal with ScheduleEvents being removed on
 * reset.
 */
static unsigned Profile_ConfigEvents(void *handle, void *data)
{
    ProfilerState *p = (ProfilerState *)handle;
    ARMul_Event *evt = data;

    if (evt->event == ConfigEvent_Reset)
    {
        if (p->handle != NULL) {
            switch (p->prof_type) {
            case PROFILE_usec:
                p->x.usec.ignore = FALSE;
                break;
                
            case PROFILE_cycle:
                ARMulif_RemoveHourglass(&p->coredesc, p->handle);
                break;

            case PROFILE_event1:
            case PROFILE_event2:
            case PROFILE_eventpc:
                ARMulif_RemoveEventHandler(&p->coredesc, p->handle);
                break;
            }
            p->handle = NULL;
        }
    }
    return 0; /* Continue */
}

BEGIN_INIT(Profiler)
{
  ProfilerState *p = state;
  const char *option;
  int verbose = ToolConf_DLookupBool(config, ARMulCnf_Verbose, FALSE);
  p->verbose = verbose;

  if (verbose)
      Hostif_PrettyPrint(hostif, config, ",\nProfiler ");
  else
      Hostif_PrettyPrint(hostif, config, ", Profiler");

  
  p->prof_type=PROFILE_usec;

  option=ToolConf_Lookup(config,ARMulCnf_Type);
  if (option) {
    if (ToolConf_Cmp(option,"MICROSECOND"))
      p->prof_type=PROFILE_usec;
    else if (ToolConf_Cmp(option,"CYCLE"))
      p->prof_type=PROFILE_cycle;
    else if (ToolConf_Cmp(option,"EVENT"))
      p->prof_type=PROFILE_eventpc;
    else
      Hostif_ConsolePrint(state->hostif,"\n\
Profiling type '%s' not understood (defaulting to \"MICROSECOND\").\n",option);
  }


  switch (p->prof_type) {
  case PROFILE_usec:
    if (verbose) Hostif_PrettyPrint(state->hostif,state->config,"(Microsecond based)");
    p->x.usec.rate = 1;
    break;

  case PROFILE_cycle:
    if (verbose) Hostif_PrettyPrint(state->hostif, state->config,"(Cycle based)");
    break;

  case PROFILE_eventpc:
    if (verbose) Hostif_PrettyPrint(state->hostif,state->config,"(Event");
    option=ToolConf_Lookup(config, ARMulCnf_EventWord);
    if (option) {
      if (ToolConf_Cmp(option,"WORD1") || ToolConf_Cmp(option,"1"))
        p->prof_type=PROFILE_event1;
      else if (ToolConf_Cmp(option,"WORD2") || ToolConf_Cmp(option,"2"))
        p->prof_type=PROFILE_event2;
      else if (ToolConf_Cmp(option,"PC"))
        p->prof_type=PROFILE_eventpc;
      else
        Hostif_ConsolePrint(state->hostif,"\n\
Event profiling type '%s' not understood (defaulting to \"WORD1\").\n",option);
    }
    option=ToolConf_Lookup(config, ARMulCnf_EventMask);

  
    if (option && option[0]) {
      char *q;
      p->x.event.mask = strtoul(option, &q, 0);
      p->x.event.value = q ? strtoul(q+1, NULL, 0) : p->x.event.mask;
      if (verbose) Hostif_PrettyPrint(state->hostif,state->config,
                                      " Mask 0x%08x-0x%08x",
                                      p->x.event.mask,p->x.event.value);
    } else {
      option=ToolConf_Lookup(config, ARMulCnf_Event);
      if (option && option[0]) {
        p->x.event.mask=(unsigned int)~0;
        p->x.event.value=strtoul(option,NULL,0);
        if (verbose) Hostif_PrettyPrint(state->hostif,state->config,
                                        " 0x%08x",p->x.event.value);
      } else {
        p->x.event.mask=p->x.event.value=0;
        if (verbose) Hostif_ConsolePrint(state->hostif,"s");
      }
    }
    break;
  }

  if (verbose) Hostif_ConsolePrint(state->hostif, "\n");

  p->handle=NULL;
  p->mapsize=0;
  p->map=NULL;
  p->counts=NULL;

  ARMulif_InstallUnkRDIInfoHandler(&state->coredesc,RDI_info,p);
  ARMulif_InstallEventHandler(&state->coredesc,
                              ConfigEventSel,
                              Profile_ConfigEvents, p);
}
END_INIT(Profiler)


BEGIN_EXIT(Profiler)
END_EXIT(Profiler)


/*--- <SORDI STUFF> ---*/


#define SORDI_DLL_DESCRIPTION_STRING "Profiler (a Utility)"
#define SORDI_RDI_PROCVEC Profiler_AgentRDI
#include "perip_sordi.h"

#include "perip_rdi_agent.h"
    IMPLEMENT_AGENT_PROCS_NOEXE_NOMODULE(Profiler)
    IMPLEMENT_AGENT_PROCVEC_NOEXE(Profiler)

/*--- </> ---*/



/* EOF profiler.c */






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -