"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

cache.h

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


UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214