stats.h 5.68 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

#ifndef STATS_H
#define STATS_H
#ifndef _LANGUAGE_ASSEMBLY
#include <stdio.h>
#include "syslimits.h"
#endif


#ifdef GONE_CLEANUP
#define GET_CACHE
/* This gets information on the QC performance (if in page mode) */
/* #define GET_QC*/
/* This flag controls whether we monitor register usage */
/*#define GET_REG_USAGE*/
/* This flag controls whether we tabulate basic block info */
/* #define BB_HISTOGRAM */


#endif

#define STAT_TIMER_START(x) (hw_counter_start(&(em_stats.x)))
#define STAT_TIMER_STOP(x) (hw_counter_stop(&(em_stats.x)))
#define STAT_TIMER_RESET(x) (hw_counter_reset(&(em_stats.x)))
#define STAT_INC(x) ((em_stats.x)++)
#define STAT_DEC(x) ((em_stats.x)--)
#define STAT_INC_BY(x,_step) ((em_stats.x)+=_step)
#define STAT_EXC(_name,_code,_utlb) ((em_stats._name[_utlb][_code]++))



#ifdef GET_QC
#define STAT_VQC(_sel) (VQC_INST(_sel)?(em_stats.vqc_i_misses)++:((VQC_EXCL(_sel)?(em_stats.vqc_d_excl_misses)++:(em_stats.vqc_d_shared_misses)++)))
#define STAT_PQC(_sel) (VQC_INST(_sel)?(em_stats.pqc_i_misses)++:((VQC_EXCL(_sel)?(em_stats.pqc_d_excl_misses)++:(em_stats.pqc_d_shared_misses)++)))
#else
#define STAT_VQC(_sel)
#define STAT_PQC(_sel) 
#endif

#ifdef GET_CACHE
/* Simple increment */
#define CACHE_SINC(_cpuNum, _mode, _label) (em_cache_info[_mode][_cpuNum]._label)++
#define CACHE_INC(_cpuNum, _mode, _I, _D, _state) {if(VQC_INST(_state)) { (em_cache_info[_mode][_cpuNum]._I)++;} else {(em_cache_info[_mode][_cpuNum]._D)++;}}
#define CACHE_INC_BY(_cpuNum, _mode, _I, _D, _state,_step) {if(VQC_INST(_state)) { (em_cache_info[_mode][_cpuNum]._I)+=_step;} else {(em_cache_info[_mode][_cpuNum]._D)+=_step;}}
#else
#define CACHE_SINC(_cpuNum, _mode, _label)
#define CACHE_INC(_cpuNum, _mode, _I, _D, _state)
#define CACHE_INC_BY(_cpuNum, _mode, _I, _D, _state,_step) 
#endif



#ifdef GET_REG_USAGE
#define STAT_INC_REG_USE(x) (em_stats.reg_usage[x]++)
#else
#define STAT_INC_REG_USE(x)
#endif




#ifdef BB_HISTOGRAM
#define STAT_BB_SIZE(_sz) (((_sz)<640)?em_stats.bb_sizes[(unsigned)(_sz)>>6]++:\
em_stats.bb_sizes[9]++)
#define STAT_DEC_BB_SIZE(_sz) (((_sz)<40)?\
em_stats.dec_bb_sizes[(uint)(_sz)>>2]++:em_stats.dec_bb_sizes[9]++)
#else
#define STAT_BB_SIZE(x)
#define STAT_DEC_BB_SIZE(_sz)
#endif

#ifndef _LANGUAGE_ASSEMBLY

/* This provides an interface to the SGI memory mapped counter.  */
/* 32 bit wrapping is detected and corrected */
typedef struct {
  uint64 current;
  uint64 ticks;  
  int on;
} HW_counter;

/* These return int so they can be used as part of a conditional */
/* expression.  As seen in stats.h the conditional expression checks */
/* to see if we are on an R_4000 where this service is available */
int hw_counter_start( HW_counter* count );
int hw_counter_stop( HW_counter* count );
int hw_counter_reset( HW_counter* count );

typedef struct {
/* TC stuff */
  int tc_flushes;
  /*int kern_tc_flushes;*/
  int tc_filled;
  int kern_cacheflush_tc_flush;
  int kern_ID_cacheflush;
  int kern_I_cacheflush;
  int kern_D_cacheflush;

/* Translator Stuff */
  int translations;
  int trans_instrs;

/* PC_TC stuff */
  int pc_tc_insert;
  int pc_tc_conflicts;
  int pc_tc_lookup;
  int ne_pc_tc_lookup;
  int pc_tc_lookup_misses;
  int ne_pc_tc_lookup_misses;
  int pc_tc_bdoor_misses;

  int kern_pc_tc_insert;
  int kern_pc_tc_conflicts;
  int kern_pc_tc_lookup;
  int kern_pc_tc_lookup_misses;

/* QC stats */
   int64 vqc_i_misses;
   int64 vqc_d_excl_misses;
   int64 vqc_d_shared_misses;

   int64 pqc_i_misses;
   int64 pqc_d_excl_misses;
   int64 pqc_d_shared_misses;

/* Backdoor */
   int backdoor_calls;
   int64 backdoor_ref;
   int64 backdoor_unaltered_ref;

/* Exceptions */
  int exceptions;
  int exception_type[2][41];
  int raised_clock_bit; /*Could see if any are being dropped by
                          checking against an annotation set at clock */

/* icache coherence */
  int icache_coherence;

   /* Chaining Stats */
   uint chain_invocations;
   uint chain_bounced;
   uint chain_known_chains;
   uint chain_spec_chains;
   uint chain_samepg_chains;
   uint chain_user_chains;
   uint chain_sameln_chains;

  /* Timers */
  HW_counter trans_timer;

  /* Translated Basic Block Sizes */
  int bb_sizes[10];

  /* Decoded Basic Block Sizes */
  int dec_bb_sizes[10];

  /* Register usage (number of regs used in a BB)*/
  /* 33 because 0 to 32 (inclusive) registers can be used */
  int reg_usage[33];
}stats_t;

/* Cache Info Unit */
typedef uint64 ci_u;
typedef struct {
   ci_u pc_sample;              /* PC sampling for time */
   /* Cache */
   ci_u i_stall_cyc;            /* I Stall */
   ci_u d_stall_cyc;            /* D Stall */
   /* This information only used to Sanity Check */
   ci_u i_miss;                 /* number of times miss in cache simulator */
   ci_u d_miss;                 /* number of times miss in cache simulator */
   ci_u instr_count;            /* Number of executed instructions */
   ci_u data_refs;              /* Total number of memory references */
   ci_u upgrades;               /* Total number of upgrades */
   ci_u upgd_inval;             /* Total number of upgrades w/ invalidation*/
  /*int cache_conflict;*/
}cache_info_t;

extern stats_t em_stats;
extern SimTime EmbraCpuInstrCount(int cpuNum);

extern void Stat_Init( void );
extern void Print_Recent_Stats( int cpuNum );
extern void Print_Total_Stats( void );
#ifdef gone
extern void Embra_Change_Mode_Actions( int cpuNum, CPUMode prev_mode );
#endif
extern void Dump_QC_Counters (int cpuNum);
extern SimTime EmbraInstrCount(void);
extern double EmbraTimeDiff(void);

#endif /* _LANGUAGE_ASSEMBLY */

#endif /* STATS_H */