hw_events.h 8.78 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. 
 *
 */

/*****************************************************************
 * hw_events.h
 *
 * Definitions of events. These various flags are or'ed together
 * to come up with a particular cache line miss, transition, or 
 * other hardware event that might want to be accounted for. The 
 * statistics gatherers can then bit swizzle out whatever they need.
 *
 * Hardware events can either be processed locally or passed to
 * another module (Memstat, False_sharing) for processing. 
 *****************************************************************/

#ifndef _HW_EVENTS_H
#define _HW_EVENTS_H

#include "memstat.h"
#include "false_sharing.h"
#include "instr_util.h"
#include "annotations.h"
#include "tcl_init.h"

extern void HWEventsEarlyInit(Tcl_Interp *);
extern void HWEventsLateInit(void);

/************************
 * CACHE RELATED EVENTS *
 ************************/

/* 
 * Any change in these next 8 defines need to be reflected in the scache
 * annotation code in annotations.c
 */

/* Cache type */
#define E_L1        (1<<0)
#define E_L2        (1<<1)
#define E_I         (1<<2)
#define E_D         (1<<3)

/* Miss type */
#define E_READ       (1<<4) 
#define E_WRITE      (1<<5)
#define E_UPGRADE    (1<<6)
#define E_SC_UPGRADE (1<<7)

/* Miss traits */
#define E_CAUSED_INVAL   (1<<8)   /* wmiss caused invalidation */
#define E_FOUND_IN_CACHE (1<<9)   /* data fetched from another cache */
#define E_SC_NAK         (1<<10)  /* attribute stall when sc is nak-ed */

/* Local or Remote home */
#define E_REMOTE         (1<<11)  /* Home of miss was a remote memory */


/* Transition traits */
#define E_EXTERNAL      (1<<21)   /* External request changed line */
#define E_WRITEBACK     (1<<22)   /* line flushed, was written back */
#define E_FLUSH_CLEAN   (1<<23)   /* line flushed, was clean */
#define E_DOWNGRADE     (1<<24)   /* line now clean, was dirty (was WRITEBACK) */
#define E_USER_REPLACED (1<<25)   /* line was replaced by a user process */
#define E_KERN_REPLACED (1<<26)   /* line was replaced by the kernel */
#define E_FAKE_EXTERNAL (1<<27)   /* the cache transition calls for an 
                                   * invalidate, even though it knows
                                   * that the line was not in the cache */
/****************
 * OTHER EVENTS *
 ****************/
#define E_PIPELINE (1<<30)


/*****************************************************************
 * Calls that are handled in-line 
 *****************************************************************/
#include "statrecord.h"
#include "memstat.h"
#include "false_sharing.h"

typedef struct HWEventBucket {
   StatRecordFieldDesc dTlb;
   StatRecordFieldDesc iTlb;
   StatRecordFieldDesc cycleSample;
   StatRecordFieldDesc instrSample;
   StatRecordFieldDesc readSample;
   StatRecordFieldDesc writeSample;
   StatRecordFieldDesc excStall;
   StatRecordFieldDesc scNak;
   StatRecordFieldDesc scNakStall;
   StatRecordFieldDesc prefetch;
   StatRecordFieldDesc prefetchIssued;
   StatRecordFieldDesc prefetchNoMiss;
   StatRecordFieldDesc prefetchNoUpg;
   StatRecordFieldDesc prefetchTransFailed;
   StatRecordFieldDesc dStallPrefetch;
   /* Embra counters -- Mipsy uses them also for exact counts */
   StatRecordFieldDesc instrCount;
   StatRecordFieldDesc refCount;
} HWEventBucket;

extern HWEventBucket hwEventBucket;

/*****************************************************************
 * MACROS TO PERFORM A CERTAIN ACTION ON HARDWARE EVENTS 
 *****************************************************************/

/*****************************************************************
 * EXCEPTION EVENTS 
 *****************************************************************/
#define ITLB_MISS_EVENT(_time, _cpu, _addr) {\
   StatRecordEntry(_cpu, _addr, 0, hwEventBucket.iTlb, 1); \
}

#define DTLB_MISS_EVENT(_time, _cpu, _pc, _addr) {\
   StatRecordEntry(_cpu, _pc, _addr, hwEventBucket.dTlb, 1); \
}

#define EXC_STALL_EVENT(_cpu, _pc, _stall) {\
   StatRecordEntry(_cpu, _pc, 0, hwEventBucket.excStall, _stall); \
}

/*****************************************************************
 * Events handled in-line
 *****************************************************************/
#define MEM_SAMPLE_EVENT(_time, _cpu, _pc, _va, _pa, _isRead) {\
   if (_isRead) { \
      StatRecordEntry(_cpu, 0, _va, hwEventBucket.readSample, 1); \
   } else { \
      StatRecordEntry(_cpu, 0, _va, hwEventBucket.writeSample, 1); \
   } \
}

#define INST_SAMPLE_EVENT(_time, _cpu, _pc) {\
   StatRecordEntry(_cpu, _pc, 0, hwEventBucket.instrSample, 1); \
}

#define CYCLE_SAMPLE_EVENT(_time, _cpu, _pc) {\
   StatRecordEntry(_cpu, _pc, 0, hwEventBucket.cycleSample, 1); \
}


#define UTLB_EVENT() { \
   AnnExec(annUTLB); \
}

#define EXC_EVENT(_prettyCode) { \
   AnnExec(annExcTable[(_prettyCode)]);\
}

#define RFE_EVENT() { \
   AnnExec(annRFE); \
}

/*****************************************************************
 * CACHE MISS EVENTS
 *****************************************************************/
#define L1_IMISS_EVENT(_time, _cpu, _vAddr, _pAddr, _stallTime, _type, _lru) {\
   MemStatImiss(_time, _cpu, _vAddr, _pAddr, _stallTime, _type);\
   InstrUtilNewLine(_cpu, _vAddr, _pAddr, _lru);\
}

#define L1_DMISS_EVENT(_time, _cpu, _pc, _vAddr, _pAddr, _stallTime, _type) {\
   MemStatDmiss(_time, _cpu, _pc, _vAddr, _pAddr, _stallTime, _type, -1);\
}

#define L2_IMISS_EVENT(_time, _cpu, _vAddr, _pAddr, _stallTime, _type) {\
   if( interest(_pAddr)) { LogEntry("l2-i",_cpu,"pAddr=0x%x type=%x \n",_pAddr,_type);} \
   MemStatImiss(_time, _cpu, _vAddr, _pAddr, _stallTime, _type);\
   if (scacheAnnotation) {ScacheAnnotation(_vAddr, _pAddr, _type, _cpu);} \
}

#define L2_DMISS_EVENT(_time, _cpu, _pc, _vAddr, _pAddr, _stallTime, _type, _lru) {\
   if( interest(_pAddr)) { LogEntry("l2-d",_cpu,"pAddr=0x%x type=%x \n",_pAddr,_type);} \
   if( !((_type)&E_UPGRADE) && !((_type)&E_SC_UPGRADE)) { \
      FalseSharingDefine(_cpu, _pAddr, _lru, _pc, _vAddr,_stallTime);\
   } \
   MemStatDmiss(_time, _cpu, _pc, _vAddr, _pAddr, _stallTime, _type, _lru);\
   if (scacheAnnotation) {ScacheAnnotation(_vAddr, _pAddr, _type, _cpu);} \
}

#define SC_NAK_EVENT(_time, _cpu, _pc, _vAddr, _pAddr, _stallTime, _type) {\
   StatRecordEntry(_cpu, _pc, _vAddr, hwEventBucket.scNak, 1); \
   StatRecordEntry(_cpu, _pc, _vAddr, hwEventBucket.scNakStall, _stallTime); \
}


/*****************************************************************
 * CACHE LINE TRANSITIONS
 ****************************************************************/
#define L1_LINE_TRANS_EVENT(_cpu, _pAddr, _type, _lru,_isUser) {\
   MemStatCacheTrans(_cpu, _pAddr, _type, 0,_isUser);\
   if ((_type) & E_I) \
      InstrUtilReplaceLine(_cpu, _pAddr, _lru);\
}

#define L2_LINE_TRANS_EVENT(_cpu, _pAddr, _type, _evictor, _lru,_isUser) {\
   if( interest(_pAddr)) { LogEntry("trans",_cpu,"pAddr=0x%x type=%x evictor=%x \n",_pAddr,_type,_evictor);} \
   MemStatCacheTrans(_cpu, _pAddr, _type, _evictor,_isUser);\
   if (!((_type) & (E_FAKE_EXTERNAL|E_DOWNGRADE))) {\
      if( interest(_pAddr)) { LogEntry("trans2",_cpu,"pAddr=0x%x type=%x \n",_pAddr,_type);} \
      FalseSharingEvict(_cpu, _pAddr, _lru,_type);\
   }\
}

#define PREFETCH_EVENT(_time, _cpu, _pc, _vAddr) {\
   StatRecordEntry(_cpu, _pc, _vAddr, hwEventBucket.prefetch, 1); \
}

#define PREFETCH_NOMISS_EVENT(_cpu,_pc,_vAddr,_pAddr,_lru,_stall) { \
   FalseSharingDefine(_cpu, _pAddr, _lru, _pc, _vAddr,0);     \
   MemStatPrefetchNoMiss(_cpu,_pAddr,_lru);  \
   StatRecordEntry(_cpu,_pc, _vAddr, hwEventBucket.prefetchNoMiss,1); \
   StatRecordEntry(_cpu,_pc, _vAddr, hwEventBucket.dStallPrefetch,_stall); \
}

#define PREFETCH_NOUPGRADE_EVENT(_cpu,_pc,_vAddr,_pAddr,_lru,_stall) { \
   StatRecordEntry(_cpu,_pc, _vAddr, hwEventBucket.prefetchNoUpg,1); \
   StatRecordEntry(_cpu,_pc, _vAddr, hwEventBucket.dStallPrefetch,_stall); \
}

#define PREFETCH_FAILED_TRANS(_cpu,_pc,_vAddr) { \
   StatRecordEntry(_cpu,_pc, _vAddr, hwEventBucket.prefetchTransFailed,1); \
}

#define PREFETCH_ISSUE_EVENT(_cpu,_pc,_vAddr) { \
   StatRecordEntry(_cpu,_pc, _vAddr, hwEventBucket.prefetchIssued,1); \
}

/*****************************************************************
 * PERIODIC EVENTS
 ****************************************************************/
#define PERIODIC_EVENT { \
   AnnExec(AnnFind("simos", "periodic")); \
}

/*****************************************************************
 * EMBRA COUNTS (no sampling --> no byData/byPC)
 ****************************************************************/

#define EMBRA_INSTR_COUNT_EVENT(_cpu,_count) {\
   StatRecordEntry(_cpu,0,0,hwEventBucket.instrCount,_count); \
} 

#define EMBRA_REF_COUNT_EVENT(_cpu,_count) {\
      StatRecordEntry(_cpu,0,0,hwEventBucket.refCount,_count); \
}


#endif /* _HW_EVENTS_H */