diff options
Diffstat (limited to 'src/mem/cache/tags/lru.cc')
-rw-r--r-- | src/mem/cache/tags/lru.cc | 258 |
1 files changed, 18 insertions, 240 deletions
diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 744d7224a..290d1bdd0 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -11,7 +11,7 @@ * unmodified and in its entirety in all distributions of the software, * modified or unmodified, in source code or in binary form. * - * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2003-2005,2014 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,292 +42,70 @@ /** * @file - * Definitions of LRU tag store. + * Definitions of a LRU tag store. */ -#include <string> - -#include "base/intmath.hh" -#include "debug/Cache.hh" #include "debug/CacheRepl.hh" #include "mem/cache/tags/lru.hh" #include "mem/cache/base.hh" -#include "sim/core.hh" - -using namespace std; LRU::LRU(const Params *p) - :BaseTags(p), assoc(p->assoc), - numSets(p->size / (p->block_size * p->assoc)), - sequentialAccess(p->sequential_access) + : BaseSetAssoc(p) { - // Check parameters - if (blkSize < 4 || !isPowerOf2(blkSize)) { - fatal("Block size must be at least 4 and a power of 2"); - } - if (numSets <= 0 || !isPowerOf2(numSets)) { - fatal("# of sets must be non-zero and a power of 2"); - } - if (assoc <= 0) { - fatal("associativity must be greater than zero"); - } - if (hitLatency <= 0) { - fatal("access latency must be greater than zero"); - } - - blkMask = blkSize - 1; - setShift = floorLog2(blkSize); - setMask = numSets - 1; - tagShift = setShift + floorLog2(numSets); - warmedUp = false; - /** @todo Make warmup percentage a parameter. */ - warmupBound = numSets * assoc; - - sets = new SetType[numSets]; - blks = new BlkType[numSets * assoc]; - // allocate data storage in one big chunk - numBlocks = numSets * assoc; - dataBlks = new uint8_t[numBlocks * blkSize]; - - unsigned blkIndex = 0; // index into blks array - for (unsigned i = 0; i < numSets; ++i) { - sets[i].assoc = assoc; - - sets[i].blks = new BlkType*[assoc]; - - // link in the data blocks - for (unsigned j = 0; j < assoc; ++j) { - // locate next cache block - BlkType *blk = &blks[blkIndex]; - blk->data = &dataBlks[blkSize*blkIndex]; - ++blkIndex; - - // invalidate new cache block - blk->invalidate(); - - //EGH Fix Me : do we need to initialize blk? - - // Setting the tag to j is just to prevent long chains in the hash - // table; won't matter because the block is invalid - blk->tag = j; - blk->whenReady = 0; - blk->isTouched = false; - blk->size = blkSize; - sets[i].blks[j]=blk; - blk->set = i; - } - } } -LRU::~LRU() -{ - delete [] dataBlks; - delete [] blks; - delete [] sets; -} - -LRU::BlkType* +BaseSetAssoc::BlkType* LRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, int master_id) { - Addr tag = extractTag(addr); - unsigned set = extractSet(addr); - BlkType *blk = sets[set].findBlk(tag, is_secure); - lat = hitLatency; - - // Access all tags in parallel, hence one in each way. The data side - // either accesses all blocks in parallel, or one block sequentially on - // a hit. Sequential access with a miss doesn't access data. - tagAccesses += assoc; - if (sequentialAccess) { - if (blk != NULL) { - dataAccesses += 1; - } - } else { - dataAccesses += assoc; - } + BlkType *blk = BaseSetAssoc::accessBlock(addr, is_secure, lat, master_id); if (blk != NULL) { // move this block to head of the MRU list - sets[set].moveToHead(blk); + sets[blk->set].moveToHead(blk); DPRINTF(CacheRepl, "set %x: moving blk %x (%s) to MRU\n", - set, regenerateBlkAddr(tag, set), is_secure ? "s" : "ns"); - if (blk->whenReady > curTick() - && cache->ticksToCycles(blk->whenReady - curTick()) > hitLatency) { - lat = cache->ticksToCycles(blk->whenReady - curTick()); - } - blk->refCount += 1; + blk->set, regenerateBlkAddr(blk->tag, blk->set), + is_secure ? "s" : "ns"); } return blk; } - -LRU::BlkType* -LRU::findBlock(Addr addr, bool is_secure) const -{ - Addr tag = extractTag(addr); - unsigned set = extractSet(addr); - BlkType *blk = sets[set].findBlk(tag, is_secure); - return blk; -} - -LRU::BlkType* -LRU::findVictim(Addr addr) +BaseSetAssoc::BlkType* +LRU::findVictim(Addr addr) const { - unsigned set = extractSet(addr); + int set = extractSet(addr); // grab a replacement candidate - BlkType *blk = sets[set].blks[assoc-1]; + BlkType *blk = sets[set].blks[assoc - 1]; if (blk->isValid()) { DPRINTF(CacheRepl, "set %x: selecting blk %x for replacement\n", set, regenerateBlkAddr(blk->tag, set)); } + return blk; } void LRU::insertBlock(PacketPtr pkt, BlkType *blk) { - Addr addr = pkt->getAddr(); - MasterID master_id = pkt->req->masterId(); - uint32_t task_id = pkt->req->taskId(); - bool is_secure = pkt->isSecure(); - if (!blk->isTouched) { - tagsInUse++; - blk->isTouched = true; - if (!warmedUp && tagsInUse.value() >= warmupBound) { - warmedUp = true; - warmupCycle = curTick(); - } - } - - // If we're replacing a block that was previously valid update - // stats for it. This can't be done in findBlock() because a - // found block might not actually be replaced there if the - // coherence protocol says it can't be. - if (blk->isValid()) { - replacements[0]++; - totalRefs += blk->refCount; - ++sampledRefs; - blk->refCount = 0; + BaseSetAssoc::insertBlock(pkt, blk); - // deal with evicted block - assert(blk->srcMasterId < cache->system->maxMasters()); - occupancies[blk->srcMasterId]--; - - blk->invalidate(); - } - - blk->isTouched = true; - // Set tag for new block. Caller is responsible for setting status. - blk->tag = extractTag(addr); - if (is_secure) - blk->status |= BlkSecure; - - // deal with what we are bringing in - assert(master_id < cache->system->maxMasters()); - occupancies[master_id]++; - blk->srcMasterId = master_id; - blk->task_id = task_id; - blk->tickInserted = curTick(); - - unsigned set = extractSet(addr); + int set = extractSet(pkt->getAddr()); sets[set].moveToHead(blk); - - // We only need to write into one tag and one data block. - tagAccesses += 1; - dataAccesses += 1; } void LRU::invalidate(BlkType *blk) { - assert(blk); - assert(blk->isValid()); - tagsInUse--; - assert(blk->srcMasterId < cache->system->maxMasters()); - occupancies[blk->srcMasterId]--; - blk->srcMasterId = Request::invldMasterId; - blk->task_id = ContextSwitchTaskId::Unknown; - blk->tickInserted = curTick(); + BaseSetAssoc::invalidate(blk); // should be evicted before valid blocks - unsigned set = blk->set; + int set = blk->set; sets[set].moveToTail(blk); } -void -LRU::clearLocks() -{ - for (int i = 0; i < numBlocks; i++){ - blks[i].clearLoadLocks(); - } -} - -LRU * +LRU* LRUParams::create() { return new LRU(this); } -std::string -LRU::print() const { - std::string cache_state; - for (unsigned i = 0; i < numSets; ++i) { - // link in the data blocks - for (unsigned j = 0; j < assoc; ++j) { - BlkType *blk = sets[i].blks[j]; - if (blk->isValid()) - cache_state += csprintf("\tset: %d block: %d %s\n", i, j, - blk->print()); - } - } - if (cache_state.empty()) - cache_state = "no valid tags\n"; - return cache_state; -} - -void -LRU::cleanupRefs() -{ - for (unsigned i = 0; i < numSets*assoc; ++i) { - if (blks[i].isValid()) { - totalRefs += blks[i].refCount; - ++sampledRefs; - } - } -} - -void -LRU::computeStats() -{ - for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) { - occupanciesTaskId[i] = 0; - for (unsigned j = 0; j < 5; ++j) { - ageTaskId[i][j] = 0; - } - } - - for (unsigned i = 0; i < numSets * assoc; ++i) { - if (blks[i].isValid()) { - assert(blks[i].task_id < ContextSwitchTaskId::NumTaskId); - occupanciesTaskId[blks[i].task_id]++; - Tick age = curTick() - blks[i].tickInserted; - assert(age >= 0); - - int age_index; - if (age / SimClock::Int::us < 10) { // <10us - age_index = 0; - } else if (age / SimClock::Int::us < 100) { // <100us - age_index = 1; - } else if (age / SimClock::Int::ms < 1) { // <1ms - age_index = 2; - } else if (age / SimClock::Int::ms < 10) { // <10ms - age_index = 3; - } else - age_index = 4; // >10ms - - ageTaskId[blks[i].task_id][age_index]++; - } - } -} - |