stats.c 5.38 KB
/*
 * Copyright (C) 1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * Copyright (C) 1998 Digital Equipment Corporation
 *
 * This file is part of the SimOS distribution.
 * See LICENSE file for terms of the license.
 *
 */



/* ******************************************************
 * gamma.c
 *
 * main fetch/decode/execute loop for the gamma instruction
 * set interpreter. To be integrated into SimOS. 
 * ******************************************************/

#include <setjmp.h>
#include <alpha/inst.h>

#include "simtypes.h"
#include "sim_error.h"

#include "cpu_stats.h"
#include "gamma.h"
#include "ev5.h"
#include "disassembler.h"
#include "alpha_regs.h"
#include "ipr_decode.h"
#include "tcl_init.h"
#include "print_insts.h"
#include "cpu_interface.h"
#include "registry.h"
#include "machine_params.h"
#include "memref.h"
#include "memstat.h"
#include "hw_events.h"




#define CACHE_LINE_SIZE 64 /* elsewhere XXX */
static void EnablePeriodicStats(int cpuNum, SimTime statInterval);
static void PeriodicStats(SimTime cycleCount);

/*****************************************************************
 * GammaInitStats
 * 
 *****************************************************************/
void
GammaInitStats(void)
{
   MemRefInit();
   InitCPUStats();
   EnablePeriodicStats(0, SAMPLE_PC_INTERVAL);
}



/*****************************************************************
 * GammaResetStats
 *
 *****************************************************************/ 
void
GammaResetStats(void)
{
   unsigned i;

   ResetCPUStats();

   for (i=0; i < TOTAL_CPUS; i++) {
      MemRefResetStats(i);
   }

#ifdef SOLO
   Tcl_Eval(TCLInterp, "annotation exec solo resetStats");
#endif
}

/*****************************************************************
 * GammaStatsCallback:
 *
 * This is a heavily used callback. Right now I check almost every 
 * periodic event here and process it if needed. It also prints out 
 * a whole mess of statistics at regular intervals and then reinstalls 
 * itelf everytime. This event is called every SAMPLE_PC_INTERVAL. 
 *
 * We do all kinds of things here that aren't directly related to
 * stats, including checking for interrupts and for exit conditions.
 * Additionally, every STAT_INTERVAL cycles we call out to print the
 * periodic statistics.
 *****************************************************************/

static struct StatsHdr {
    EventCallbackHdr hdr;
    SimTime statsInterval;
    int periodicStats;
    int intervalsLeft;

} statsEvent[SIM_MAXCPUS];


static void 
GammaStatsCallback(int cpuNum, EventCallbackHdr *hdr, void *arg)
{
   int cpu;

   ASSERT(simosCPUType == GAMMA || 
          simosCPUType==KAPPA || 
          simosCPUType==EPSILON);


   for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {
      AlphaState *P = PE[cpu];
      if (P->cpuState == cpu_halted) {
         continue;
      }
      CYCLE_SAMPLE_EVENT(CPUVec.CycleCount(cpu), cpu, P->PC);

   }
   
   --statsEvent[cpuNum].intervalsLeft;
   if (statsEvent[cpuNum].intervalsLeft <= 0) { 
      statsEvent[cpuNum].intervalsLeft = statsEvent[cpuNum].periodicStats;
      PERIODIC_EVENT;
      PeriodicStats((SimTime)CPUVec.CycleCount(cpuNum));
   } /* Things to do each STAT_INTERVAL */
   
   EventDoCallback(cpuNum, GammaStatsCallback,
                   (EventCallbackHdr *)&statsEvent[cpuNum],
                   0, statsEvent[cpuNum].statsInterval);
}

/*****************************************************************
 * EnablePeriodicStats
 * 
 * Installs the first statistics callback. When the callback runs, it
 * will reinsert itself into the callback queue.
 *****************************************************************/
static void 
EnablePeriodicStats(int cpuNum, SimTime statInterval)
{
   statsEvent[cpuNum].statsInterval = statInterval;
   statsEvent[cpuNum].periodicStats = STAT_INTERVAL / statInterval;
   statsEvent[cpuNum].intervalsLeft = statsEvent[cpuNum].periodicStats;

   EventDoCallback(0, GammaStatsCallback, 
                   (EventCallbackHdr *)&statsEvent[cpuNum],
                   0, statInterval);
}

/*****************************************************************
 * PeriodicStats
 * 
 * Current means of printing out periodic statistics. This is
 * called at the end of each "STAT_INTERVAL" and when it is time to
 * exit gamma. Every "DETAILED_STAT_INTERVAL" some extra stuff will be
 * printed out.
 *****************************************************************/

static void
PeriodicStats(SimTime cycleCount)
{
   int cpuNum;

   PrintPeriodicCPUStats();
   for (cpuNum = 0; cpuNum < TOTAL_CPUS; cpuNum++) {
      /* The memory subsystem should do any sampling and printing in
         this procedure. */
     MemRefPeriodicStats(cpuNum);
   }
   memsysVec.MemsysDumpStats();

}


/*****************************************************************
 * GammaDumpAllStats
 * 
 * Complete dumping of stats. 
 * This is typically called at the end of execution.
 *****************************************************************/
void
GammaDumpAllStats(void) 
{
   int cpuNum;

   CPUPrint("*******************DUMPING GAMMA STATS******************* \n");
   PrintAllCPUStats();
   CPUPrint("************\n");
   CPUPrint("Cache Stats\n");
   CPUPrint("************\n");
   for (cpuNum=0; cpuNum<TOTAL_CPUS; cpuNum++) {
      CPUPrint("C%d Stall Time: %d\n", cpuNum, STATS_VALUE(cpuNum, stallTime));
#ifdef GAMMA_MXS
      dump_stats(PE[cpuNum].st);
#endif
#if 0
      MemRefDumpStats(cpuNum);
#endif
   }
}