fa_lru.cc
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· CC 代码 · 共 336 行
CC
336 行
/* * Copyright (c) 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi, * and Andrew Schultz. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. *//** * @file * Definitions a fully associative LRU tagstore. */#include <sstream>#include <assert.h>#include "mem/cache/tags/fa_lru.hh"#include "base/intmath.hh"using namespace std;FALRU::FALRU(int _blkSize, int _size, int hit_latency) : blkSize(_blkSize), size(_size), numBlks(size/blkSize), hitLatency(hit_latency){ if ((blkSize & (blkSize - 1)) != 0) fatal("cache block size (in bytes) `%d' must be a power of two", blkSize); if (!(hitLatency > 0)) fatal("Access latency in cycles must be at least one cycle"); if ((size & (size - 1)) !=0) fatal("Cache Size must be power of 2 for now"); // Track all cache sizes from 128K up by powers of 2 numCaches = FloorLog2(size) - 17; if (numCaches >0){ cacheBoundaries = new FALRUBlk *[numCaches]; cacheMask = (1 << numCaches) - 1; } else { cacheMask = 0; } warmedUp = false; warmupBound = size/blkSize; blks = new FALRUBlk[numBlks]; head = &(blks[0]); tail = &(blks[numBlks-1]); head->prev = NULL; head->next = &(blks[1]); head->inCache = cacheMask; tail->prev = &(blks[numBlks-2]); tail->next = NULL; tail->inCache = 0; int index = (1 << 17) / blkSize; int j = 0; int flags = cacheMask; for (int i = 1; i < numBlks-1; i++) { blks[i].inCache = flags; if (i == index - 1){ cacheBoundaries[j] = &(blks[i]); flags &= ~ (1<<j); ++j; index = index << 1; } blks[i].prev = &(blks[i-1]); blks[i].next = &(blks[i+1]); blks[i].isTouched = false; } assert(j == numCaches); assert(index == numBlks); //assert(check());}voidFALRU::regStats(const string &name){ using namespace Stats; BaseTags::regStats(name); hits .init(numCaches+1) .name(name + ".falru_hits") .desc("The number of hits in each cache size.") ; misses .init(numCaches+1) .name(name + ".falru_misses") .desc("The number of misses in each cache size.") ; accesses .name(name + ".falru_accesses") .desc("The number of accesses to the FA LRU cache.") ; for (int i = 0; i < numCaches+1; ++i) { stringstream size_str; if (i < 3){ size_str << (1<<(i+7)) <<"K"; } else { size_str << (1<<(i-3)) <<"M"; } hits.subname(i, size_str.str()); hits.subdesc(i, "Hits in a " + size_str.str() +" cache"); misses.subname(i, size_str.str()); misses.subdesc(i, "Misses in a " + size_str.str() +" cache"); }}FALRUBlk *FALRU::hashLookup(Addr addr) const{ tagIterator iter = tagHash.find(addr); if (iter != tagHash.end()) { return (*iter).second; } return NULL;}boolFALRU::probe(int asid, Addr addr) const{ Addr blkAddr = blkAlign(addr); FALRUBlk* blk = hashLookup(blkAddr); return blk && blk->tag == blkAddr && blk->isValid();}voidFALRU::invalidateBlk(int asid, Addr addr){ Addr blkAddr = blkAlign(addr); FALRUBlk* blk = (*tagHash.find(blkAddr)).second; if (blk) { assert(blk->tag == blkAddr); blk->status = 0; blk->isTouched = false; tagsInUse--; }}FALRUBlk*FALRU::findBlock(Addr addr, int asid, int &lat, int *inCache){ accesses++; int tmp_in_cache = 0; Addr blkAddr = blkAlign(addr); FALRUBlk* blk = hashLookup(blkAddr); if (blk && blk->isValid()) { assert(blk->tag == blkAddr); tmp_in_cache = blk->inCache; for (int i = 0; i < numCaches; i++) { if (1<<i & blk->inCache) { hits[i]++; } else { misses[i]++; } } hits[numCaches]++; if (blk != head){ moveToHead(blk); } } else { blk = NULL; for (int i = 0; i < numCaches+1; ++i) { misses[i]++; } } if (inCache) { *inCache = tmp_in_cache; } lat = hitLatency; //assert(check()); return blk;}FALRUBlk*FALRU::findBlock(MemReqPtr &req, int &lat, int *inCache){ Addr addr = req->paddr; accesses++; int tmp_in_cache = 0; Addr blkAddr = blkAlign(addr); FALRUBlk* blk = hashLookup(blkAddr); if (blk && blk->isValid()) { assert(blk->tag == blkAddr); tmp_in_cache = blk->inCache; for (int i = 0; i < numCaches; i++) { if (1<<i & blk->inCache) { hits[i]++; } else { misses[i]++; } } hits[numCaches]++; if (blk != head){ moveToHead(blk); } } else { blk = NULL; for (int i = 0; i < numCaches+1; ++i) { misses[i]++; } } if (inCache) { *inCache = tmp_in_cache; } lat = hitLatency; //assert(check()); return blk;}FALRUBlk*FALRU::findBlock(Addr addr, int asid) const{ Addr blkAddr = blkAlign(addr); FALRUBlk* blk = hashLookup(blkAddr); if (blk && blk->isValid()) { assert(blk->tag == blkAddr); } else { blk = NULL; } return blk;}FALRUBlk*FALRU::findReplacement(MemReqPtr &req, MemReqList &writebacks, BlkList &compress_blocks){ FALRUBlk * blk = tail; assert(blk->inCache == 0); moveToHead(blk); tagHash.erase(blk->tag); tagHash[blkAlign(req->paddr)] = blk; if (blk->isValid()) { int thread_num = (blk->xc) ? blk->xc->thread_num : 0; replacements[thread_num]++; } else { tagsInUse++; blk->isTouched = true; if (!warmedUp && tagsInUse.value() >= warmupBound) { warmedUp = true; warmupCycle = curTick; } } //assert(check()); return blk;}voidFALRU::moveToHead(FALRUBlk *blk){ int updateMask = blk->inCache ^ cacheMask; for (int i = 0; i < numCaches; i++){ if ((1<<i) & updateMask) { cacheBoundaries[i]->inCache &= ~(1<<i); cacheBoundaries[i] = cacheBoundaries[i]->prev; } else if (cacheBoundaries[i] == blk) { cacheBoundaries[i] = blk->prev; } } blk->inCache = cacheMask; if (blk != head) { if (blk == tail){ assert(blk->next == NULL); tail = blk->prev; tail->next = NULL; } else { blk->prev->next = blk->next; blk->next->prev = blk->prev; } blk->next = head; blk->prev = NULL; head->prev = blk; head = blk; }}boolFALRU::check(){ FALRUBlk* blk = head; int size = 0; int boundary = 1<<17; int j = 0; int flags = cacheMask; while (blk) { size += blkSize; if (blk->inCache != flags) { return false; } if (size == boundary && blk != tail) { if (cacheBoundaries[j] != blk) { return false; } flags &=~(1 << j); boundary = boundary<<1; ++j; } blk = blk->next; } return true;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?