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 00264 /* last block to hit, used to optimize cache hit processing */ 00265 md_addr_t last_tagset; /* tag of last line accessed */ 00266 struct cache_blk_t *last_blk; /* cache block last accessed */ 00267 00268 /* data blocks */ 00269 byte_t *data; /* pointer to data blocks allocation */ 00270 00271 /* NOTE: this is a variable-size tail array, this must be the LAST field 00272 defined in this structure! */ 00273 struct cache_set_t sets[1]; /* each entry is a set */ 00274 }; 00275 00276 //: create and initialize a general cache structure 00277 struct cache_t * /* pointer to cache created */ 00278 cache_create(char *name, /* name of the cache */ 00279 convProc *pr, 00280 int nsets, /* total number of sets in cache */ 00281 int bsize, /* block (line) size of cache */ 00282 int balloc, /* allocate data space for blocks? */ 00283 int usize, /* size of user data to alloc w/blks */ 00284 int assoc, /* associativity of cache */ 00285 enum cache_policy policy, /* replacement policy w/in sets */ 00286 /* block access function, see description w/in struct cache def */ 00287 unsigned int (convProc::*blk_access_fn)(enum mem_cmd cmd, 00288 md_addr_t baddr, int bsize, 00289 struct cache_blk_t *blk, 00290 tick_t now, bool&), 00291 unsigned int hit_latency);/* latency in cycles for a hit */ 00292 00293 //: parse policy 00294 enum cache_policy /* replacement policy enum */ 00295 cache_char2policy(char c); /* replacement policy as a char */ 00296 00297 //: print cache configuration 00298 void 00299 cache_config(struct cache_t *cp, /* cache instance */ 00300 FILE *stream); /* output stream */ 00301 00302 //: register cache stats 00303 void 00304 cache_reg_stats(struct cache_t *cp, /* cache instance */ 00305 struct stat_sdb_t *sdb);/* stats database */ 00306 00307 //: print cache stats 00308 void 00309 cache_stats(struct cache_t *cp, /* cache instance */ 00310 FILE *stream); /* output stream */ 00311 00312 //: print cache stats 00313 void cache_stats(struct cache_t *cp, FILE *stream); 00314 00315 //: Access a cache 00316 // 00317 // access a cache, perform a CMD operation on cache CP at address 00318 // ADDR, places NBYTES of data at *P, returns latency of operation if 00319 // initiated at NOW, places pointer to block user data in *UDATA, *P 00320 // is untouched if cache blocks are not allocated (!CP->BALLOC), UDATA 00321 // should be NULL if no user data is attached to blocks 00322 unsigned int /* latency of access in cycles */ 00323 cache_access(struct cache_t *cp, /* cache to access */ 00324 enum mem_cmd cmd, /* access type, Read or Write */ 00325 md_addr_t addr, /* address of access */ 00326 void *vp, /* ptr to buffer for input/output */ 00327 int nbytes, /* number of bytes to access */ 00328 tick_t now, /* time of access */ 00329 byte_t **udata, /* for return of user data ptr */ 00330 md_addr_t *repl_addr, /* for address of replaced block */ 00331 bool &needMM, /* does this need a main me access */ 00332 md_addr_t *bumped); /* Was an address ejected from cache */ 00333 00334 /* cache access functions, these are safe, they check alignment and 00335 permissions */ 00336 /*#define cache_double(cp, cmd, addr, p, now, udata) \ 00337 cache_access(cp, cmd, addr, p, sizeof(double), now, udata) 00338 #define cache_float(cp, cmd, addr, p, now, udata) \ 00339 cache_access(cp, cmd, addr, p, sizeof(float), now, udata) 00340 #define cache_dword(cp, cmd, addr, p, now, udata) \ 00341 cache_access(cp, cmd, addr, p, sizeof(long long), now, udata) 00342 #define cache_word(cp, cmd, addr, p, now, udata) \ 00343 cache_access(cp, cmd, addr, p, sizeof(int), now, udata) 00344 #define cache_half(cp, cmd, addr, p, now, udata) \ 00345 cache_access(cp, cmd, addr, p, sizeof(short), now, udata) 00346 #define cache_byte(cp, cmd, addr, p, now, udata) \ 00347 cache_access(cp, cmd, addr, p, sizeof(char), now, udata)*/ 00348 00349 /* return non-zero if block containing address ADDR is contained in cache 00350 CP, this interface is used primarily for debugging and asserting cache 00351 invariants */ 00352 int /* non-zero if access would hit */ 00353 cache_probe(struct cache_t *cp, /* cache instance to probe */ 00354 md_addr_t addr); /* address of block to probe */ 00355 00356 /* flush the entire cache, returns latency of the operation */ 00357 unsigned int /* latency of the flush operation */ 00358 cache_flush(struct cache_t *cp, /* cache instance to flush */ 00359 tick_t now); /* time of cache flush */ 00360 00361 /* flush the block containing ADDR from the cache CP, returns the latency of 00362 the block flush operation */ 00363 unsigned int /* latency of flush operation */ 00364 cache_flush_addr(struct cache_t *cp, /* cache instance to flush */ 00365 md_addr_t addr, /* address of block to flush */ 00366 tick_t now); /* time of cache flush */ 00367 /* invalidate the block containing ADDR from the cache CP, returns the 00368 latency of the operation. does not flush to backing store */ 00369 unsigned int /* latency of flush operation */ 00370 cache_invalidate_addr(struct cache_t *cp, /* cache instance to flush */ 00371 md_addr_t addr, /* address of block to flush */ 00372 tick_t now); /* time of cache flush */ 00373 00374 md_addr_t cache_get_blkAddr(struct cache_t *cp, md_addr_t addr); 00375 #endif /* CACHE_H */