-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcache.h
377 lines (334 loc) · 15.1 KB
/
cache.h
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/*
* cache.h - cache module interfaces
*
* This file is a part of the SimpleScalar tool suite written by
* Todd M. Austin as a part of the Multiscalar Research Project.
*
* The tool suite is currently maintained by Doug Burger and Todd M. Austin.
*
* Copyright (C) 1994, 1995, 1996, 1997, 1998 by Todd M. Austin
*
* This source file is distributed "as is" in the hope that it will be
* useful. The tool set comes with no warranty, and no author or
* distributor accepts any responsibility for the consequences of its
* use.
*
* Everyone is granted permission to copy, modify and redistribute
* this tool set under the following conditions:
*
* This source code is distributed for non-commercial use only.
* Please contact the maintainer for restrictions applying to
* commercial use.
*
* Permission is granted to anyone to make or distribute copies
* of this source code, either as received or modified, in any
* medium, provided that all copyright notices, permission and
* nonwarranty notices are preserved, and that the distributor
* grants the recipient permission for further redistribution as
* permitted by this document.
*
* Permission is granted to distribute this file in compiled
* or executable form under the same conditions that apply for
* source code, provided that either:
*
* A. it is accompanied by the corresponding machine-readable
* source code,
* B. it is accompanied by a written offer, with no time limit,
* to give anyone a machine-readable copy of the corresponding
* source code in return for reimbursement of the cost of
* distribution. This written offer must permit verbatim
* duplication by anyone, or
* C. it is distributed by someone who received only the
* executable form, and is accompanied by a copy of the
* written offer of source code that they received concurrently.
*
* In other words, you are welcome to use, share and improve this
* source file. You are forbidden to forbid anyone else to use, share
* and improve what you give them.
*
* INTERNET: dburger@cs.wisc.edu
* US Mail: 1210 W. Dayton Street, Madison, WI 53706
*
*
* Revision 1.5 1998/08/27 08:09:13 taustin
* implemented host interface description in host.h
* added target interface support
*
* Revision 1.4 1997/03/11 01:09:45 taustin
* updated copyright
* long/int tweaks made for ALPHA target support
*
* Revision 1.3 1997/01/06 15:57:55 taustin
* comments updated
* cache_reg_stats() now works with stats package
* cp->writebacks stat added to cache
*
* Revision 1.1 1996/12/05 18:50:23 taustin
* Initial revision
*
*
*/
#ifndef CACHE_H
#define CACHE_H
#include <stdio.h>
#include "host.h"
#include "misc.h"
#include "machine.h"
#include "memory.h"
#include "stats.h"
/*
* This module contains code to implement various cache-like structures. The
* user instantiates caches using cache_new(). When instantiated, the user
* may specify the geometry of the cache (i.e., number of set, line size,
* associativity), and supply a block access function. The block access
* function indicates the latency to access lines when the cache misses,
* accounting for any component of miss latency, e.g., bus acquire latency,
* bus transfer latency, memory access latency, etc... In addition, the user
* may allocate the cache with or without lines allocated in the cache.
* Caches without tags are useful when implementing structures that map data
* other than the address space, e.g., TLBs which map the virtual address
* space to physical page address, or BTBs which map text addresses to
* branch prediction state. Tags are always allocated. User data may also be
* optionally attached to cache lines, this space is useful to storing
* auxilliary or additional cache line information, such as predecode data,
* physical page address information, etc...
*
* The caches implemented by this module provide efficient storage management
* and fast access for all cache geometries. When sets become highly
* associative, a hash table (indexed by address) is allocated for each set
* in the cache.
*
* This module also tracks latency of accessing the data cache, each cache has
* a hit latency defined when instantiated, miss latency is returned by the
* cache's block access function, the caches may service any number of hits
* under any number of misses, the calling simulator should limit the number
* of outstanding misses or the number of hits under misses as per the
* limitations of the particular microarchitecture being simulated.
*
* Due to the organization of this cache implementation, the latency of a
* request cannot be affected by a later request to this module. As a result,
* reordering of requests in the memory hierarchy is not possible.
*/
/* highly associative caches are implemented using a hash table lookup to
speed block access, this macro decides if a cache is "highly associative" */
#define CACHE_HIGHLY_ASSOC(cp) ((cp)->assoc > 4)
/* cache replacement policy */
enum cache_policy {
LRU, /* replace least recently used block (perfect LRU) */
Random, /* replace a random block */
FIFO /* replace the oldest block in the set */
};
/* block status values */
#define CACHE_BLK_VALID 0x00000001 /* block in valid, in use */
#define CACHE_BLK_DIRTY 0x00000002 /* dirty block */
#define CACHE_BLK_DECAYED 0x00000004 /* decayed block */
#define CACHE_BLK_NFLAGS 3 /* number of flag bits*/
/* cache block (or line) definition */
struct cache_blk_t
{
struct cache_blk_t *way_next; /* next block in the ordered way chain, used
to order blocks for replacement */
struct cache_blk_t *way_prev; /* previous block in the order way chain */
struct cache_blk_t *hash_next;/* next block in the hash bucket chain, only
used in highly-associative caches */
/* since hash table lists are typically small, there is no previous
pointer, deletion requires a trip through the hash table bucket list */
md_addr_t tag; /* data block tag value */
unsigned int status; /* block status, see CACHE_BLK_* defs above */
tick_t ready; /* time when block will be accessible, field
is set when a miss fetch is initiated */
byte_t *user_data; /* pointer to user defined data, e.g.,
pre-decode data or physical page address */
tick_t time_first_access;
enum mem_cmd first_cmd;
tick_t time_last_access; /* when this result is produced ? */
enum mem_cmd last_cmd;
tick_t time_dirty;
tick_t time_decayed;
int n_access;
int n_total_access;
int n_total_miss;
int n_read;
int n_write;
int local_counter;
int local_counter_max;
int tag_counter;
int frequency;
int slow_decay; /* TRUE -- using a slow counter, FALSE -- using a fast counter */
int tag_valid; /* TRUE -- tag is valid, FALSE -- tag is invalid */
md_addr_t pc_last_access; /* pc of the last inst access this block */
struct stat_stat_t *n_use_prof; /* profile the # of usage of value */
struct stat_stat_t *n_read_prof; /* profile the # of usage of value */
struct stat_stat_t *live_period_prof; /* profile the # of usage of value */
struct stat_stat_t *dead_period_prof; /* profile the # of usage of value */
struct stat_stat_t *access_interval_prof; /* profile the # of usage of value */
/* DATA should be pointer-aligned due to preceeding field */
/* NOTE: this is a variable-size tail array, this must be the LAST field
defined in this structure! */
byte_t data[1]; /* actual data block starts here, block size
should probably be a multiple of 8 */
};
/* cache set definition (one or more blocks sharing the same set index) */
struct cache_set_t
{
struct cache_blk_t **hash; /* hash table: for fast access w/assoc, NULL
for low-assoc caches */
struct cache_blk_t *way_head; /* head of way list */
struct cache_blk_t *way_tail; /* tail pf way list */
struct cache_blk_t *blks; /* cache blocks, allocated sequentially, so
this pointer can also be used for random
access to cache blocks */
};
/* cache definition */
struct cache_t
{
/* parameters */
char *name; /* cache name */
int nsets; /* number of sets */
int bsize; /* block size in bytes */
int balloc; /* maintain cache contents? */
int usize; /* user allocated data size */
int assoc; /* cache associativity */
enum cache_policy policy; /* cache replacement policy */
unsigned int hit_latency; /* cache hit latency */
/* miss/replacement handler, read/write BSIZE bytes starting at BADDR
from/into cache block BLK, returns the latency of the operation
if initiated at NOW, returned latencies indicate how long it takes
for the cache access to continue (e.g., fill a write buffer), the
miss/repl functions are required to track how this operation will
effect the latency of later operations (e.g., write buffer fills),
if !BALLOC, then just return the latency; BLK_ACCESS_FN is also
responsible for generating any user data and incorporating the latency
of that operation */
unsigned int /* latency of block access */
(*blk_access_fn)(enum mem_cmd cmd, /* block access command */
md_addr_t baddr, /* program address to access */
int bsize, /* size of the cache block */
struct cache_blk_t *blk, /* ptr to cache block struct */
tick_t now); /* when fetch was initiated */
/* derived data, for fast decoding */
int hsize; /* cache set hash table size */
md_addr_t blk_mask;
int set_shift;
md_addr_t set_mask; /* use *after* shift */
int tag_shift;
md_addr_t tag_mask; /* use *after* shift */
md_addr_t tagset_mask; /* used for fast hit detection */
/* bus resource */
tick_t bus_free; /* time when bus to next level of cache is
free, NOTE: the bus model assumes only a
single, fully-pipelined port to the next
level of memory that requires the bus only
one cycle for cache line transfer (the
latency of the access to the lower level
may be more than one cycle, as specified
by the miss handler */
/* per-cache stats */
counter_t hits; /* total number of hits */
counter_t misses; /* total number of misses */
counter_t replacements; /* total number of replacements at misses */
counter_t writebacks; /* total number of writebacks at misses */
counter_t invalidations; /* total number of external invalidations */
counter_t read_misses;
counter_t write_misses;
/* last block to hit, used to optimize cache hit processing */
md_addr_t last_tagset; /* tag of last line accessed */
struct cache_blk_t *last_blk; /* cache block last accessed */
/* data blocks */
byte_t *data; /* pointer to data blocks allocation */
/* NOTE: this is a variable-size tail array, this must be the LAST field
defined in this structure! */
struct cache_set_t sets[1]; /* each entry is a set */
};
/* create and initialize a general cache structure */
struct cache_t * /* pointer to cache created */
cache_create(char *name, /* name of the cache */
int nsets, /* total number of sets in cache */
int bsize, /* block (line) size of cache */
int balloc, /* allocate data space for blocks? */
int usize, /* size of user data to alloc w/blks */
int assoc, /* associativity of cache */
enum cache_policy policy, /* replacement policy w/in sets */
/* block access function, see description w/in struct cache def */
unsigned int (*blk_access_fn)(enum mem_cmd cmd,
md_addr_t baddr, int bsize,
struct cache_blk_t *blk,
tick_t now),
unsigned int hit_latency);/* latency in cycles for a hit */
/* parse policy */
enum cache_policy /* replacement policy enum */
cache_char2policy(char c); /* replacement policy as a char */
/* print cache configuration */
void
cache_config(struct cache_t *cp, /* cache instance */
FILE *stream); /* output stream */
/* register cache stats */
void
cache_reg_stats(struct cache_t *cp, /* cache instance */
struct stat_sdb_t *sdb);/* stats database */
/* print cache stats */
void
cache_stats(struct cache_t *cp, /* cache instance */
FILE *stream); /* output stream */
/* print cache stats */
void cache_stats(struct cache_t *cp, FILE *stream);
/* access a cache, perform a CMD operation on cache CP at address ADDR,
places NBYTES of data at *P, returns latency of operation if initiated
at NOW, places pointer to block user data in *UDATA, *P is untouched if
cache blocks are not allocated (!CP->BALLOC), UDATA should be NULL if no
user data is attached to blocks */
unsigned int /* latency of access in cycles */
cache_access(struct cache_t *cp, /* cache to access */
enum mem_cmd cmd, /* access type, Read or Write */
md_addr_t addr, /* address of access */
void *vp, /* ptr to buffer for input/output */
int nbytes, /* number of bytes to access */
tick_t now, /* time of access */
byte_t **udata, /* for return of user data ptr */
md_addr_t *repl_addr); /* for address of replaced block */
/* cache access functions, these are safe, they check alignment and
permissions */
#define cache_double(cp, cmd, addr, p, now, udata) \
cache_access(cp, cmd, addr, p, sizeof(double), now, udata)
#define cache_float(cp, cmd, addr, p, now, udata) \
cache_access(cp, cmd, addr, p, sizeof(float), now, udata)
#define cache_dword(cp, cmd, addr, p, now, udata) \
cache_access(cp, cmd, addr, p, sizeof(long long), now, udata)
#define cache_word(cp, cmd, addr, p, now, udata) \
cache_access(cp, cmd, addr, p, sizeof(int), now, udata)
#define cache_half(cp, cmd, addr, p, now, udata) \
cache_access(cp, cmd, addr, p, sizeof(short), now, udata)
#define cache_byte(cp, cmd, addr, p, now, udata) \
cache_access(cp, cmd, addr, p, sizeof(char), now, udata)
/* return non-zero if block containing address ADDR is contained in cache
CP, this interface is used primarily for debugging and asserting cache
invariants */
int /* non-zero if access would hit */
cache_probe(struct cache_t *cp, /* cache instance to probe */
md_addr_t addr); /* address of block to probe */
/* flush the entire cache, returns latency of the operation */
unsigned int /* latency of the flush operation */
cache_flush(struct cache_t *cp, /* cache instance to flush */
tick_t now); /* time of cache flush */
/* flush the block containing ADDR from the cache CP, returns the latency of
the block flush operation */
unsigned int /* latency of flush operation */
cache_flush_addr(struct cache_t *cp, /* cache instance to flush */
md_addr_t addr, /* address of block to flush */
tick_t now); /* time of cache flush */
void clear_cache_stats(struct cache_t *cp);
/* Leakage: modifications start here */
#include "cache_leak_ctrl.h"
/* some of the cache.c macros shifted here */
#define cache_decay /* decay turned on */
/* Note: L2 HAS TO BE unified, IL1 and DL1 HAVE TO BE separate */
#ifndef decayed_cache
#define decayed_cache cache_dl1 /* DL1 is decayed by default */
#endif
/* initialization */
void cache_leak_init (void);
/* get the ratio between overhead leakage baseline leakage */
double cache_get_ctrl_ovhd_ratio (enum leak_ctrl_type_t type);
/* get an estimate of dynamic power for the overhead logic */
double cache_get_xtra_power (enum leak_ctrl_type_t type);
#endif /* CACHE_H */