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: ssb_cache.h,v 1.2 2006-08-24 19:05:27 afrodri Exp $ 00053 * 00054 * $Log: not supported by cvs2svn $ 00055 * Revision 1.1.1.1 2006/01/31 16:35:49 afrodri 00056 * first entry 00057 * 00058 * Revision 1.5 2004/11/16 04:17:46 arodrig6 00059 * added more documentation 00060 * 00061 * Revision 1.4 2004/10/27 21:03:39 arodrig6 00062 * added SMP support 00063 * 00064 * Revision 1.3 2004/08/20 01:17:50 arodrig6 00065 * began integrating SW2/DRAM with ssBack 00066 * 00067 * Revision 1.2 2004/08/10 22:55:35 arodrig6 00068 * works, except for the speculative stuff, caches, and multiple procs 00069 * 00070 * Revision 1.1 2004/08/05 23:51:44 arodrig6 00071 * grabed files from SS and broke up some of them 00072 * 00073 * Revision 1.1.1.1 2000/03/07 05:15:16 karu 00074 * this is the repository created for my own maintanence. 00075 * created when spec95 (lisp and compress worked). 00076 * compress still had the scanf("%i") problem 00077 * DIFF from the repository I am using alongwith ramdass on /projects 00078 * need to merge the two sometime :-) 00079 * 00080 * Revision 1.1.1.1 2000/02/25 21:02:49 karu 00081 * creating cvs repository for ss3-ppc 00082 * 00083 * Revision 1.5 1998/08/27 08:09:13 taustin 00084 * implemented host interface description in host.h 00085 * added target interface support 00086 * 00087 * Revision 1.4 1997/03/11 01:09:45 taustin 00088 * updated copyright 00089 * long/int tweaks made for ALPHA target support 00090 * 00091 * Revision 1.3 1997/01/06 15:57:55 taustin 00092 * comments updated 00093 * cache_reg_stats() now works with stats package 00094 * cp->writebacks stat added to cache 00095 * 00096 * Revision 1.1 1996/12/05 18:50:23 taustin 00097 * Initial revision 00098 * 00099 * 00100 */ 00101 00102 #ifndef CACHE_H 00103 #define CACHE_H 00104 00105 #include <stdio.h> 00106 00107 #include "ssb_host.h" 00108 #include "ssb_misc.h" 00109 #include "ssb_machine.h" 00110 #include "ssb_memory.h" 00111 #include "ssb_stats.h" 00112 00113 00114 /* highly associative caches are implemented using a hash table lookup to 00115 speed block access, this macro decides if a cache is "highly associative" */ 00116 #define CACHE_HIGHLY_ASSOC(cp) ((cp)->assoc > 4) 00117 00118 //: cache replacement policy 00119 //!SEC:ssBack 00120 enum cache_policy { 00121 LRU, /* replace least recently used block (perfect LRU) */ 00122 Random, /* replace a random block */ 00123 FIFO /* replace the oldest block in the set */ 00124 }; 00125 00126 /* block status values */ 00127 #define CACHE_BLK_VALID 0x00000001 /* block in valid, in use */ 00128 #define CACHE_BLK_DIRTY 0x00000002 /* dirty block */ 00129 00130 //: cache block (or line) definition 00131 //!SEC:ssBack 00132 struct cache_blk_t 00133 { 00134 struct cache_blk_t *way_next; /* next block in the ordered way chain, used 00135 to order blocks for replacement */ 00136 struct cache_blk_t *way_prev; /* previous block in the order way chain */ 00137 struct cache_blk_t *hash_next;/* next block in the hash bucket chain, only 00138 used in highly-associative caches */ 00139 /* since hash table lists are typically small, there is no previous 00140 pointer, deletion requires a trip through the hash table bucket list */ 00141 md_addr_t tag; /* data block tag value */ 00142 unsigned int status; /* block status, see CACHE_BLK_* defs above */ 00143 tick_t ready; /* time when block will be accessible, field 00144 is set when a miss fetch is initiated */ 00145 byte_t *user_data; /* pointer to user defined data, e.g., 00146 pre-decode data or physical page address */ 00147 /* DATA should be pointer-aligned due to preceeding field */ 00148 /* NOTE: this is a variable-size tail array, this must be the LAST field 00149 defined in this structure! */ 00150 byte_t data[1]; /* actual data block starts here, block size 00151 should probably be a multiple of 8 */ 00152 }; 00153 00154 //: cache set definition 00155 // cache set definition (one or more blocks sharing the same set index) 00156 //!SEC:ssBack 00157 struct cache_set_t 00158 { 00159 struct cache_blk_t **hash; /* hash table: for fast access w/assoc, NULL 00160 for low-assoc caches */ 00161 struct cache_blk_t *way_head; /* head of way list */ 00162 struct cache_blk_t *way_tail; /* tail pf way list */ 00163 struct cache_blk_t *blks; /* cache blocks, allocated sequentially, so 00164 this pointer can also be used for random 00165 access to cache blocks */ 00166 }; 00167 00168 class convProc; 00169 00170 //: cache definition 00171 // 00172 // This module contains code to implement various cache-like 00173 // structures. The user instantiates caches using cache_new(). When 00174 // instantiated, the user may specify the geometry of the cache (i.e., 00175 // number of set, line size, associativity), and supply a block access 00176 // function. The block access function indicates the latency to access 00177 // lines when the cache misses, accounting for any component of miss 00178 // latency, e.g., bus acquire latency, bus transfer latency, memory 00179 // access latency, etc... In addition, the user may allocate the cache 00180 // with or without lines allocated in the cache. Caches without tags 00181 // are useful when implementing structures that map data other than 00182 // the address space, e.g., TLBs which map the virtual address space 00183 // to physical page address, or BTBs which map text addresses to 00184 // branch prediction state. Tags are always allocated. User data may 00185 // also be optionally attached to cache lines, this space is useful to 00186 // storing auxilliary or additional cache line information, such as 00187 // predecode data, physical page address information, etc... 00188 // 00189 // The caches implemented by this module provide efficient storage 00190 // management and fast access for all cache geometries. When sets 00191 // become highly associative, a hash table (indexed by address) is 00192 // allocated for each set in the cache. 00193 // 00194 // This module also tracks latency of accessing the data cache, each 00195 // cache has a hit latency defined when instantiated, miss latency is 00196 // returned by the cache's block access function, the caches may 00197 // service any number of hits under any number of misses, the calling 00198 // simulator should limit the number of outstanding misses or the 00199 // number of hits under misses as per the limitations of the 00200 // particular microarchitecture being simulated. 00201 // 00202 // Due to the organization of this cache implementation, the latency 00203 // of a request cannot be affected by a later request to this 00204 // module. As a result, reordering of requests in the memory hierarchy 00205 // is not possible. 00206 // 00207 //!SEC:ssBack 00208 struct cache_t 00209 { 00210 /* parameters */ 00211 char *name; /* cache name */ 00212 convProc *proc; 00213 int nsets; /* number of sets */ 00214 int bsize; /* block size in bytes */ 00215 int balloc; /* maintain cache contents? */ 00216 int usize; /* user allocated data size */ 00217 int assoc; /* cache associativity */ 00218 enum cache_policy policy; /* cache replacement policy */ 00219 unsigned int hit_latency; /* cache hit latency */ 00220 00221 /* miss/replacement handler, read/write BSIZE bytes starting at BADDR 00222 from/into cache block BLK, returns the latency of the operation 00223 if initiated at NOW, returned latencies indicate how long it takes 00224 for the cache access to continue (e.g., fill a write buffer), the 00225 miss/repl functions are required to track how this operation will 00226 effect the latency of later operations (e.g., write buffer fills), 00227 if !BALLOC, then just return the latency; BLK_ACCESS_FN is also 00228 responsible for generating any user data and incorporating the latency 00229 of that operation */ 00230 unsigned int /* latency of block access */ 00231 (convProc::*blk_access_fn)(enum mem_cmd cmd, /* block access command */ 00232 md_addr_t baddr, /* program address to access */ 00233 int bsize, /* size of the cache block */ 00234 cache_blk_t *blk, /* ptr to cache block struct */ 00235 tick_t now, /* when fetch was initiated */ 00236 bool &needMM); 00237 00238 /* derived data, for fast decoding */ 00239 int hsize; /* cache set hash table size */ 00240 md_addr_t blk_mask; 00241 int set_shift; 00242 md_addr_t set_mask; /* use *after* shift */ 00243 int tag_shift; 00244 md_addr_t tag_mask; /* use *after* shift */ 00245 md_addr_t tagset_mask; /* used for fast hit detection */ 00246 00247 /* bus resource */ 00248 tick_t bus_free; /* time when bus to next level of cache is 00249 free, NOTE: the bus model assumes only a 00250 single, fully-pipelined port to the next 00251 level of memory that requires the bus only 00252 one cycle for cache line transfer (the 00253 latency of the access to the lower level 00254 may be more than one cycle, as specified 00255 by the miss handler */ 00256 00257 /* per-cache stats */ 00258 counter_t hits; /* total number of hits */ 00259 counter_t misses; /* total number of misses */ 00260 counter_t replacements; /* total number of replacements at misses */ 00261 counter_t writebacks; /* total number of writebacks at misses */ 00262 counter_t invalidations; /* total number of external invalidations */ 00263 void resetStats() { 00264 hits = 0; 00265 misses = 0; 00266 replacements = 0; 00267 writebacks = 0; 00268 invalidations = 0; 00269 } 00270 00271 /* last block to hit, used to optimize cache hit processing */ 00272 md_addr_t last_tagset; /* tag of last line accessed */ 00273 struct cache_blk_t *last_blk; /* cache block last accessed */ 00274 00275 /* data blocks */ 00276 byte_t *data; /* pointer to data blocks allocation */ 00277 00278 /* NOTE: this is a variable-size tail array, this must be the LAST field 00279 defined in this structure! */ 00280 struct cache_set_t sets[1]; /* each entry is a set */ 00281 }; 00282 00283 //: create and initialize a general cache structure 00284 struct cache_t * /* pointer to cache created */ 00285 cache_create(char *name, /* name of the cache */ 00286 convProc *pr, 00287 int nsets, /* total number of sets in cache */ 00288 int bsize, /* block (line) size of cache */ 00289 int balloc, /* allocate data space for blocks? */ 00290 int usize, /* size of user data to alloc w/blks */ 00291 int assoc, /* associativity of cache */ 00292 enum cache_policy policy, /* replacement policy w/in sets */ 00293 /* block access function, see description w/in struct cache def */ 00294 unsigned int (convProc::*blk_access_fn)(enum mem_cmd cmd, 00295 md_addr_t baddr, int bsize, 00296 struct cache_blk_t *blk, 00297 tick_t now, bool&), 00298 unsigned int hit_latency);/* latency in cycles for a hit */ 00299 00300 //: parse policy 00301 enum cache_policy /* replacement policy enum */ 00302 cache_char2policy(char c); /* replacement policy as a char */ 00303 00304 //: print cache configuration 00305 void 00306 cache_config(struct cache_t *cp, /* cache instance */ 00307 FILE *stream); /* output stream */ 00308 00309 //: register cache stats 00310 void 00311 cache_reg_stats(struct cache_t *cp, /* cache instance */ 00312 struct stat_sdb_t *sdb);/* stats database */ 00313 00314 //: print cache stats 00315 void 00316 cache_stats(struct cache_t *cp, /* cache instance */ 00317 FILE *stream); /* output stream */ 00318 00319 //: print cache stats 00320 void cache_stats(struct cache_t *cp, FILE *stream); 00321 00322 //: Access a cache 00323 // 00324 // access a cache, perform a CMD operation on cache CP at address 00325 // ADDR, places NBYTES of data at *P, returns latency of operation if 00326 // initiated at NOW, places pointer to block user data in *UDATA, *P 00327 // is untouched if cache blocks are not allocated (!CP->BALLOC), UDATA 00328 // should be NULL if no user data is attached to blocks 00329 unsigned int /* latency of access in cycles */ 00330 cache_access(struct cache_t *cp, /* cache to access */ 00331 enum mem_cmd cmd, /* access type, Read or Write */ 00332 md_addr_t addr, /* address of access */ 00333 void *vp, /* ptr to buffer for input/output */ 00334 int nbytes, /* number of bytes to access */ 00335 tick_t now, /* time of access */ 00336 byte_t **udata, /* for return of user data ptr */ 00337 md_addr_t *repl_addr, /* for address of replaced block */ 00338 bool &needMM, /* does this need a main me access */ 00339 md_addr_t *bumped); /* Was an address ejected from cache */ 00340 00341 /* cache access functions, these are safe, they check alignment and 00342 permissions */ 00343 /*#define cache_double(cp, cmd, addr, p, now, udata) \ 00344 cache_access(cp, cmd, addr, p, sizeof(double), now, udata) 00345 #define cache_float(cp, cmd, addr, p, now, udata) \ 00346 cache_access(cp, cmd, addr, p, sizeof(float), now, udata) 00347 #define cache_dword(cp, cmd, addr, p, now, udata) \ 00348 cache_access(cp, cmd, addr, p, sizeof(long long), now, udata) 00349 #define cache_word(cp, cmd, addr, p, now, udata) \ 00350 cache_access(cp, cmd, addr, p, sizeof(int), now, udata) 00351 #define cache_half(cp, cmd, addr, p, now, udata) \ 00352 cache_access(cp, cmd, addr, p, sizeof(short), now, udata) 00353 #define cache_byte(cp, cmd, addr, p, now, udata) \ 00354 cache_access(cp, cmd, addr, p, sizeof(char), now, udata)*/ 00355 00356 /* return non-zero if block containing address ADDR is contained in cache 00357 CP, this interface is used primarily for debugging and asserting cache 00358 invariants */ 00359 int /* non-zero if access would hit */ 00360 cache_probe(struct cache_t *cp, /* cache instance to probe */ 00361 md_addr_t addr); /* address of block to probe */ 00362 00363 /* flush the entire cache, returns latency of the operation */ 00364 unsigned int /* latency of the flush operation */ 00365 cache_flush(struct cache_t *cp, /* cache instance to flush */ 00366 tick_t now); /* time of cache flush */ 00367 00368 /* flush the block containing ADDR from the cache CP, returns the latency of 00369 the block flush operation */ 00370 unsigned int /* latency of flush operation */ 00371 cache_flush_addr(struct cache_t *cp, /* cache instance to flush */ 00372 md_addr_t addr, /* address of block to flush */ 00373 tick_t now); /* time of cache flush */ 00374 /* invalidate the block containing ADDR from the cache CP, returns the 00375 latency of the operation. does not flush to backing store */ 00376 unsigned int /* latency of flush operation */ 00377 cache_invalidate_addr(struct cache_t *cp, /* cache instance to flush */ 00378 md_addr_t addr, /* address of block to flush */ 00379 tick_t now); /* time of cache flush */ 00380 00381 md_addr_t cache_get_blkAddr(struct cache_t *cp, md_addr_t addr); 00382 #endif /* CACHE_H */