00001 /* 00002 * cache.h - cache module interfaces 00003 * 00004 * This file is a part of the SimpleScalar tool suite written by 00005 * Todd M. Austin as a part of the Multiscalar Research Project. 00006 * 00007 * The tool suite is currently maintained by Doug Burger and Todd M. Austin. 00008 * 00009 * Copyright (C) 1994, 1995, 1996, 1997, 1998 by Todd M. Austin 00010 * 00011 * This source file is distributed "as is" in the hope that it will be 00012 * useful. The tool set comes with no warranty, and no author or 00013 * distributor accepts any responsibility for the consequences of its 00014 * use. 00015 * 00016 * Everyone is granted permission to copy, modify and redistribute 00017 * this tool set under the following conditions: 00018 * 00019 * This source code is distributed for non-commercial use only. 00020 * Please contact the maintainer for restrictions applying to 00021 * commercial use. 00022 * 00023 * Permission is granted to anyone to make or distribute copies 00024 * of this source code, either as received or modified, in any 00025 * medium, provided that all copyright notices, permission and 00026 * nonwarranty notices are preserved, and that the distributor 00027 * grants the recipient permission for further redistribution as 00028 * permitted by this document. 00029 * 00030 * Permission is granted to distribute this file in compiled 00031 * or executable form under the same conditions that apply for 00032 * source code, provided that either: 00033 * 00034 * A. it is accompanied by the corresponding machine-readable 00035 * source code, 00036 * B. it is accompanied by a written offer, with no time limit, 00037 * to give anyone a machine-readable copy of the corresponding 00038 * source code in return for reimbursement of the cost of 00039 * distribution. This written offer must permit verbatim 00040 * duplication by anyone, or 00041 * C. it is distributed by someone who received only the 00042 * executable form, and is accompanied by a copy of the 00043 * written offer of source code that they received concurrently. 00044 * 00045 * In other words, you are welcome to use, share and improve this 00046 * source file. You are forbidden to forbid anyone else to use, share 00047 * and improve what you give them. 00048 * 00049 * INTERNET: dburger@cs.wisc.edu 00050 * US Mail: 1210 W. Dayton Street, Madison, WI 53706 00051 * 00052 * $Id: cache.h,v 1.2 2003/12/18 20:31:59 panalyzer Exp $ 00053 * 00054 * $Log: cache.h,v $ 00055 * Revision 1.2 2003/12/18 20:31:59 panalyzer 00056 * *** empty log message *** 00057 * 00058 * Revision 1.1.1.1 2003/09/18 00:57:54 panalyzer 00059 * 00060 * 00061 * Revision 1.1.1.1 2003/09/18 00:18:43 panalyzer 00062 * 00063 * 00064 * Revision 1.1.1.1 2003/09/16 18:48:14 gdm 00065 * 00066 * 00067 * Revision 1.1.1.1 2000/11/29 14:53:54 cu-cs 00068 * Grand unification of arm sources. 00069 * 00070 * 00071 * Revision 1.1.1.1 2000/05/26 15:18:57 taustin 00072 * SimpleScalar Tool Set 00073 * 00074 * 00075 * Revision 1.5 1998/08/27 08:09:13 taustin 00076 * implemented host interface description in host.h 00077 * added target interface support 00078 * 00079 * Revision 1.4 1997/03/11 01:09:45 taustin 00080 * updated copyright 00081 * long/int tweaks made for ALPHA target support 00082 * 00083 * Revision 1.3 1997/01/06 15:57:55 taustin 00084 * comments updated 00085 * cache_reg_stats() now works with stats package 00086 * cp->writebacks stat added to cache 00087 * 00088 * Revision 1.1 1996/12/05 18:50:23 taustin 00089 * Initial revision 00090 * 00091 * 00092 */ 00093 00094 #ifndef CACHE_H 00095 #define CACHE_H 00096 00097 #include <stdio.h> 00098 00099 #include "host.h" 00100 #include "misc.h" 00101 #include "machine.h" 00102 #include "memory.h" 00103 #include "stats.h" 00104 00105 /* 00106 * This module contains code to implement various cache-like structures. The 00107 * user instantiates caches using cache_new(). When instantiated, the user 00108 * may specify the geometry of the cache (i.e., number of set, line size, 00109 * associativity), and supply a block access function. The block access 00110 * function indicates the latency to access lines when the cache misses, 00111 * accounting for any component of miss latency, e.g., bus acquire latency, 00112 * bus transfer latency, memory access latency, etc... In addition, the user 00113 * may allocate the cache with or without lines allocated in the cache. 00114 * Caches without tags are useful when implementing structures that map data 00115 * other than the address space, e.g., TLBs which map the virtual address 00116 * space to physical page address, or BTBs which map text addresses to 00117 * branch prediction state. Tags are always allocated. User data may also be 00118 * optionally attached to cache lines, this space is useful to storing 00119 * auxilliary or additional cache line information, such as predecode data, 00120 * physical page address information, etc... 00121 * 00122 * The caches implemented by this module provide efficient storage management 00123 * and fast access for all cache geometries. When sets become highly 00124 * associative, a hash table (indexed by address) is allocated for each set 00125 * in the cache. 00126 * 00127 * This module also tracks latency of accessing the data cache, each cache has 00128 * a hit latency defined when instantiated, miss latency is returned by the 00129 * cache's block access function, the caches may service any number of hits 00130 * under any number of misses, the calling simulator should limit the number 00131 * of outstanding misses or the number of hits under misses as per the 00132 * limitations of the particular microarchitecture being simulated. 00133 * 00134 * Due to the organization of this cache implementation, the latency of a 00135 * request cannot be affected by a later request to this module. As a result, 00136 * reordering of requests in the memory hierarchy is not possible. 00137 */ 00138 00139 /* highly associative caches are implemented using a hash table lookup to 00140 speed block access, this macro decides if a cache is "highly associative" */ 00141 #define CACHE_HIGHLY_ASSOC(cp) ((cp)->assoc > 4) 00142 00143 /* cache replacement policy */ 00144 enum cache_policy { 00145 LRU, /* replace least recently used block (perfect LRU) */ 00146 Random, /* replace a random block */ 00147 FIFO /* replace the oldest block in the set */ 00148 }; 00149 00150 /* block status values */ 00151 #define CACHE_BLK_VALID 0x00000001 /* block in valid, in use */ 00152 #define CACHE_BLK_DIRTY 0x00000002 /* dirty block */ 00153 00154 /* cache block (or line) definition */ 00155 struct cache_blk_t 00156 { 00157 struct cache_blk_t *way_next; /* next block in the ordered way chain, used 00158 to order blocks for replacement */ 00159 struct cache_blk_t *way_prev; /* previous block in the order way chain */ 00160 struct cache_blk_t *hash_next;/* next block in the hash bucket chain, only 00161 used in highly-associative caches */ 00162 /* since hash table lists are typically small, there is no previous 00163 pointer, deletion requires a trip through the hash table bucket list */ 00164 md_addr_t tag; /* data block tag value */ 00165 unsigned int status; /* block status, see CACHE_BLK_* defs above */ 00166 tick_t ready; /* time when block will be accessible, field 00167 is set when a miss fetch is initiated */ 00168 byte_t *user_data; /* pointer to user defined data, e.g., 00169 pre-decode data or physical page address */ 00170 /* DATA should be pointer-aligned due to preceeding field */ 00171 /* NOTE: this is a variable-size tail array, this must be the LAST field 00172 defined in this structure! */ 00173 byte_t data[1]; /* actual data block starts here, block size 00174 should probably be a multiple of 8 */ 00175 }; 00176 00177 /* cache set definition (one or more blocks sharing the same set index) */ 00178 struct cache_set_t 00179 { 00180 struct cache_blk_t **hash; /* hash table: for fast access w/assoc, NULL 00181 for low-assoc caches */ 00182 struct cache_blk_t *way_head; /* head of way list */ 00183 struct cache_blk_t *way_tail; /* tail pf way list */ 00184 struct cache_blk_t *blks; /* cache blocks, allocated sequentially, so 00185 this pointer can also be used for random 00186 access to cache blocks */ 00187 }; 00188 00189 /* cache definition */ 00190 struct cache_t 00191 { 00192 /* parameters */ 00193 char *name; /* cache name */ 00194 int nsets; /* number of sets */ 00195 int bsize; /* block size in bytes */ 00196 int balloc; /* maintain cache contents? */ 00197 int usize; /* user allocated data size */ 00198 int assoc; /* cache associativity */ 00199 enum cache_policy policy; /* cache replacement policy */ 00200 unsigned int hit_latency; /* cache hit latency */ 00201 00202 /* miss/replacement handler, read/write BSIZE bytes starting at BADDR 00203 from/into cache block BLK, returns the latency of the operation 00204 if initiated at NOW, returned latencies indicate how long it takes 00205 for the cache access to continue (e.g., fill a write buffer), the 00206 miss/repl functions are required to track how this operation will 00207 effect the latency of later operations (e.g., write buffer fills), 00208 if !BALLOC, then just return the latency; BLK_ACCESS_FN is also 00209 responsible for generating any user data and incorporating the latency 00210 of that operation */ 00211 unsigned int /* latency of block access */ 00212 (*blk_access_fn)(enum mem_cmd cmd, /* block access command */ 00213 md_addr_t baddr, /* program address to access */ 00214 int bsize, /* size of the cache block */ 00215 struct cache_blk_t *blk, /* ptr to cache block struct */ 00216 tick_t now); /* when fetch was initiated */ 00217 00218 /* derived data, for fast decoding */ 00219 int hsize; /* cache set hash table size */ 00220 md_addr_t blk_mask; 00221 int set_shift; 00222 md_addr_t set_mask; /* use *after* shift */ 00223 int tag_shift; 00224 md_addr_t tag_mask; /* use *after* shift */ 00225 md_addr_t tagset_mask; /* used for fast hit detection */ 00226 00227 /* bus resource */ 00228 tick_t bus_free; /* time when bus to next level of cache is 00229 free, NOTE: the bus model assumes only a 00230 single, fully-pipelined port to the next 00231 level of memory that requires the bus only 00232 one cycle for cache line transfer (the 00233 latency of the access to the lower level 00234 may be more than one cycle, as specified 00235 by the miss handler */ 00236 00237 /* per-cache stats */ 00238 counter_t hits; /* total number of hits */ 00239 counter_t misses; /* total number of misses */ 00240 counter_t replacements; /* total number of replacements at misses */ 00241 counter_t writebacks; /* total number of writebacks at misses */ 00242 counter_t invalidations; /* total number of external invalidations */ 00243 00244 /* last block to hit, used to optimize cache hit processing */ 00245 md_addr_t last_tagset; /* tag of last line accessed */ 00246 struct cache_blk_t *last_blk; /* cache block last accessed */ 00247 00248 /* data blocks */ 00249 byte_t *data; /* pointer to data blocks allocation */ 00250 00251 /* NOTE: this is a variable-size tail array, this must be the LAST field 00252 defined in this structure! */ 00253 struct cache_set_t sets[1]; /* each entry is a set */ 00254 }; 00255 00256 /* create and initialize a general cache structure */ 00257 struct cache_t * /* pointer to cache created */ 00258 cache_create(char *name, /* name of the cache */ 00259 int nsets, /* total number of sets in cache */ 00260 int bsize, /* block (line) size of cache */ 00261 int balloc, /* allocate data space for blocks? */ 00262 int usize, /* size of user data to alloc w/blks */ 00263 int assoc, /* associativity of cache */ 00264 enum cache_policy policy, /* replacement policy w/in sets */ 00265 /* block access function, see description w/in struct cache def */ 00266 unsigned int (*blk_access_fn)(enum mem_cmd cmd, 00267 md_addr_t baddr, int bsize, 00268 struct cache_blk_t *blk, 00269 tick_t now), 00270 unsigned int hit_latency);/* latency in cycles for a hit */ 00271 00272 /* parse policy */ 00273 enum cache_policy /* replacement policy enum */ 00274 cache_char2policy(char c); /* replacement policy as a char */ 00275 00276 /* print cache configuration */ 00277 void 00278 cache_config(struct cache_t *cp, /* cache instance */ 00279 FILE *stream); /* output stream */ 00280 00281 /* register cache stats */ 00282 void 00283 cache_reg_stats(struct cache_t *cp, /* cache instance */ 00284 struct stat_sdb_t *sdb);/* stats database */ 00285 00286 /* print cache stats */ 00287 void 00288 cache_stats(struct cache_t *cp, /* cache instance */ 00289 FILE *stream); /* output stream */ 00290 00291 /* print cache stats */ 00292 void cache_stats(struct cache_t *cp, FILE *stream); 00293 00294 /* access a cache, perform a CMD operation on cache CP at address ADDR, 00295 places NBYTES of data at *P, returns latency of operation if initiated 00296 at NOW, places pointer to block user data in *UDATA, *P is untouched if 00297 cache blocks are not allocated (!CP->BALLOC), UDATA should be NULL if no 00298 user data is attached to blocks */ 00299 unsigned int /* latency of access in cycles */ 00300 cache_access(struct cache_t *cp, /* cache to access */ 00301 enum mem_cmd cmd, /* access type, Read or Write */ 00302 md_addr_t addr, /* address of access */ 00303 void *vp, /* ptr to buffer for input/output */ 00304 int nbytes, /* number of bytes to access */ 00305 tick_t now, /* time of access */ 00306 byte_t **udata, /* for return of user data ptr */ 00307 md_addr_t *repl_addr); /* for address of replaced block */ 00308 00309 /* cache access functions, these are safe, they check alignment and 00310 permissions */ 00311 #define cache_double(cp, cmd, addr, p, now, udata) \ 00312 cache_access(cp, cmd, addr, p, sizeof(double), now, udata) 00313 #define cache_float(cp, cmd, addr, p, now, udata) \ 00314 cache_access(cp, cmd, addr, p, sizeof(float), now, udata) 00315 #define cache_dword(cp, cmd, addr, p, now, udata) \ 00316 cache_access(cp, cmd, addr, p, sizeof(long long), now, udata) 00317 #define cache_word(cp, cmd, addr, p, now, udata) \ 00318 cache_access(cp, cmd, addr, p, sizeof(int), now, udata) 00319 #define cache_half(cp, cmd, addr, p, now, udata) \ 00320 cache_access(cp, cmd, addr, p, sizeof(short), now, udata) 00321 #define cache_byte(cp, cmd, addr, p, now, udata) \ 00322 cache_access(cp, cmd, addr, p, sizeof(char), now, udata) 00323 00324 /* return non-zero if block containing address ADDR is contained in cache 00325 CP, this interface is used primarily for debugging and asserting cache 00326 invariants */ 00327 int /* non-zero if access would hit */ 00328 cache_probe(struct cache_t *cp, /* cache instance to probe */ 00329 md_addr_t addr); /* address of block to probe */ 00330 00331 /* flush the entire cache, returns latency of the operation */ 00332 unsigned int /* latency of the flush operation */ 00333 cache_flush(struct cache_t *cp, /* cache instance to flush */ 00334 tick_t now); /* time of cache flush */ 00335 00336 /* flush the block containing ADDR from the cache CP, returns the latency of 00337 the block flush operation */ 00338 unsigned int /* latency of flush operation */ 00339 cache_flush_addr(struct cache_t *cp, /* cache instance to flush */ 00340 md_addr_t addr, /* address of block to flush */ 00341 tick_t now); /* time of cache flush */ 00342 /* cache access macros */ 00343 #define CACHE_TAG(cp, addr) ((addr) >> (cp)->tag_shift) 00344 #define CACHE_SET(cp, addr) (((addr) >> (cp)->set_shift) & (cp)->set_mask) 00345 #define CACHE_BLK(cp, addr) ((addr) & (cp)->blk_mask) 00346 #define CACHE_TAGSET(cp, addr) ((addr) & (cp)->tagset_mask) 00347 00348 00349 #endif /* CACHE_H */