hw_events.h
8.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
* 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 */