The Cache represents memory local to the processor and the interactions that take place between it and the processor and main memory.
Three replacement policies are modeled as indicated by the enumerated type cache_policy. The caches do not represent shared memory. Each thread's accesses are isolated from each other through the use of a thread id.
- Highly Associative Cache: When associativity is greater than 4. Defined by the macro: #define CACHE_HIGHLY_ASSOC(cp) ((cp)->assoc > 4)
- CACHE_BLK_VALID: Determines if a cache block is valid. Not exclusive with CACHE_BLK_DIRTY.
- CACHE_BLK_DIRTY: Determines if a cache block is dirty (has been altered). Not exclusive with CACHE_BLK_VALID.
- Cache Policy: enum cache_policy enumerates the three cache replacement policies: LRU, Random, FIFO.
- cache_blk_t: Represents a block (or line) stored within the cache.
- cache_set_t: Represents a set stored within the cache. A set contains N blocks, where N is the associativity of the cache.
- cache_t: Represents the entire cache.
Each core has access to their own caches via the pointers: cache_dl1, cache_il1, cache_dl2, cache_il2.
Each core has access to the shared L3 cache via the pointers: cache_dl3, cache_il3.
cache_blk_t is designed as follows
- cache_blk_t * way_next: Points to the next cache block in whatever sequence is being maintained.
- cache_blk_t * way_prev: Points to the previous cache block in whatever sequence is being maintained.
- cache_blk_t * hash_next: Points to the next cache block in whatever sequence is being maintained - used in highly associative caches only.
- md_addr_t tag: The address tag for the current block.
- unsigned int status: The status of the block (CACHE_BLK_VALID, CACHE_BLK_DIRTY).
- tick_t ready: The time at which the results of this block are valid/ready.
- byte_t * user_data: User defined data, if used.
- std::vector<byte_t> data: The data stored within this cache block.
- int context_id: The id of the thread that requested this data.
cache_set_t is designed as follows
- cache_blk_t * blks: Is a pointer to all the blocks within the set (N blocks, where N is the associativity of the cache). This points to the first block in the set and the other blocks can be accessed by offsetting this pointer. Do not deallocate this pointer. The data is not owned by the set, rather, it is owned by the cache who will handle deallocations appropriately.
- cache_blk_t * way_head: When ordering the blocks (for example to determine FIFO or pseudo-LRU), this is the block at the front of the list.
- cache_blk_t * way_tail: When ordering the blocks (for example to determine FIFO or pseudo-LRU), this is the block at the back of the list.
- std::vector<cache_blk_t *> hash: Used for fast accesses to the blocks when associativity is high (associativity determines the length of the linked-list bounded by way_head and way_tail).
cache_t is designed as follows
- cache_t(): Default constructor
- ~cache_t(): Destructor
- cache_t(const cache_t & target): Copy constructor
- cache_t(std::string name, unsigned int nsets, unsigned int bsize, bool balloc, int usize, unsigned int assoc, cache_policy policy, unsigned long long (*blk_access_fn), unsigned int hit_latency):
- std::string name -> Name of the cache
- unsigned int nsets -> Number of sets in the cache
- unsigned int bsize -> Size of the blocks (or lines) within the cache, in bytes.
- bool balloc -> Do we actually use the blocks?
- int usize -> Size of the user specific data
- unsigned int assoc -> Cache associativity
- cache_policy policy -> Replacement policy - see enum cache_policy
- unsigned long long (*blk_access_fn) -> Block Replacement Function pointer
- unsigned int hit_latency -> Latency on a cache hit
- void reset_cache_stats(): Resets the cache statistics (use after fast forwarding to clear statistics).
- void cache_config(FILE * stream): Outputs some cache configuration details to the file handle specified by stream
- void cache_reg_stats(stat_sdb_t * sdb): Registers this cache with the statistics handler.
- void cache_stats(FILE * stream): Outputs the cache statistics to the file handle specified by stream
- unsigned long long cache_access(mem_cmd cmd, md_addr_t addr, int context_id, void *vp, unsigned int nbytes, tick_t now, byte_t ** data, md_addr_t * repl_addr): Makes a memory request to this cache
- mem_cmd cmd -> Read or Write (see enum mem_cmd)
- md_addr_t addr -> Address of the request
- int context_id -> Which thread made the request
- void *vp -> if cache blocks are in use (balloc == True)
- if cmd==Read, vp points to a buffer that will store the data read from the cache
- if cmd==Write, vp points to a buffer that stores the data to be written to the cache
- unsigned int nbytes -> How many bytes do we read/write?
- tick_t now -> At what time is this access being made?
- byte_t ** data -> if user specific data exists (usize!=0), this points to the user data.
- md_addr_t *repl_addr -> Points to the address of the data from the replaced block in the cache, NULL if no block replaced.
- bool cache_probe(md_addr_t addr): Returns True if the address would hit into the cache, False otherwise.
- unsigned long long cache_flush(tick_t now): Clears the cache (empties it) at time now, returns latency of this process.
- unsigned long long cache_flush_addr(md_addr_t addr, tick_t now): Clears the cache entry corresponding to addr if it exists, returns the latency of this process.
- private: void link_htab_ent(cache_set_t * set, cache_blk_t * blk): From a cache entry (set), link blk into the hash bucket.
- private: void unlink_htab_ent(cache_set_t * set, cache_blk_t * blk): From a cache entry(set), remove blk from the hash bucket.
- std::string name -> Identifies the name of the cache
- unsigned int nsets -> Number of sets (cache entries)
- unsigned int bsize -> Size of the cache blocks
- bool balloc -> Flag: Do we actually retain data in the cache?
- int usize -> Size of the user specific data for each cache block
- unsigned int assoc -> Number of blocks per set.
- cache_policy policy -> The cache replacement policy. ('l'->LRU, 'f'->FIFO, 'r'->Random)
- unsigned int hit_latency -> Latency of a cache hit.
- unsigned int (*blk_access_fn) -> Function pointer, handles accessing the next level in the memory hierarchy.
- int hsize -> Size of the hash table (for highly associative caches)
- md_addr_t blk_mask -> Mask for extracting a block number
- int set_shift -> Number of bits to shift to get a set value (cache index)
- md_addr_t set_mask -> Mask used after shifting an address to get a set value.
- int tag_shift -> Number of bits used to shift to get a tag value.
- md_addr_t tag_mask -> Mask used after shifting an address to get a tag value.
- md_addr_t tagset_mask -> Mask used to remove the bit offset from an address.
- tick_t bus_free -> Used to model bus contention to the next level in the memory hierarchy.
- counter_t hits -> Statistics: Number of hits.
- counter_t misses -> Statistics: Number of misses.
- counter_t replacements -> Statistics: Number of blocks replaced.
- counter_t writebacks -> Statistics: Number of writebacks (assuming a write-back cache).
- counter_t invalidations -> Statistics: Number of cache blocks that were flushed by cache_flush, cache_flush_addr
- md_addr_t last_tagset -> Represents the last tag that generated a hit. Used to detect cache_fast_hit (avoids way_list adjustments - repeat hit)
- cache_blk_t * last_blk -> Represents the last block that generated a hit. Used to detect cache_fast_hit (avoids way_list adjustments - repeat hit)
- std::vector<byte_t> data -> The actual data storage. Is sized to number of blocks * sizeof(blocks). Where, number of blocks is nsets * assoc. sizeof(blocks) is size of cache_blk_t + storage for the actual data (bsize bytes) if balloc is set.
- std::vector<cache_set_t> sets -> Represents the cache entries. There are nsets of these. These are just the pointers to the actual data!
- cache_policy cache_char2policy(char c): Converts a replacement policy from a character to enum cache_policy.
Adding New Models