#include <string>
-#include "mem/cache/base_cache.hh"
#include "base/intmath.hh"
+#include "debug/CacheRepl.hh"
+#include "mem/cache/tags/cacheset.hh"
#include "mem/cache/tags/lru.hh"
-#include "sim/root.hh"
+#include "mem/cache/base.hh"
+#include "sim/core.hh"
using namespace std;
-LRUBlk*
-CacheSet::findBlk(Addr tag) const
-{
- for (int i = 0; i < assoc; ++i) {
- if (blks[i]->tag == tag && blks[i]->isValid()) {
- return blks[i];
- }
- }
- return 0;
-}
-
-
-void
-CacheSet::moveToHead(LRUBlk *blk)
-{
- // nothing to do if blk is already head
- if (blks[0] == blk)
- return;
-
- // write 'next' block into blks[i], moving up from MRU toward LRU
- // until we overwrite the block we moved to head.
-
- // start by setting up to write 'blk' into blks[0]
- int i = 0;
- LRUBlk *next = blk;
-
- do {
- assert(i < assoc);
- // swap blks[i] and next
- LRUBlk *tmp = blks[i];
- blks[i] = next;
- next = tmp;
- ++i;
- } while (next != blk);
-}
-
-
// create and initialize a LRU/MRU cache structure
-LRU::LRU(int _numSets, int _blkSize, int _assoc, int _hit_latency) :
- numSets(_numSets), blkSize(_blkSize), assoc(_assoc), hitLatency(_hit_latency)
+LRU::LRU(unsigned _numSets, unsigned _blkSize, unsigned _assoc,
+ unsigned _hit_latency)
+ : numSets(_numSets), blkSize(_blkSize), assoc(_assoc),
+ hitLatency(_hit_latency)
{
// Check parameters
if (blkSize < 4 || !isPowerOf2(blkSize)) {
fatal("access latency must be greater than zero");
}
- LRUBlk *blk;
- int i, j, blkIndex;
-
blkMask = blkSize - 1;
setShift = floorLog2(blkSize);
setMask = numSets - 1;
warmupBound = numSets * assoc;
sets = new CacheSet[numSets];
- blks = new LRUBlk[numSets * assoc];
+ blks = new BlkType[numSets * assoc];
// allocate data storage in one big chunk
- dataBlks = new uint8_t[numSets*assoc*blkSize];
+ numBlocks = numSets * assoc;
+ dataBlks = new uint8_t[numBlocks * blkSize];
- blkIndex = 0; // index into blks array
- for (i = 0; i < numSets; ++i) {
+ unsigned blkIndex = 0; // index into blks array
+ for (unsigned i = 0; i < numSets; ++i) {
sets[i].assoc = assoc;
- sets[i].blks = new LRUBlk*[assoc];
+ sets[i].blks = new BlkType*[assoc];
// link in the data blocks
- for (j = 0; j < assoc; ++j) {
+ for (unsigned j = 0; j < assoc; ++j) {
// locate next cache block
- blk = &blks[blkIndex];
+ BlkType *blk = &blks[blkIndex];
blk->data = &dataBlks[blkSize*blkIndex];
++blkIndex;
delete [] sets;
}
-// probe cache for presence of given block.
-bool
-LRU::probe(Addr addr) const
-{
- // return(findBlock(Read, addr, asid) != 0);
- Addr tag = extractTag(addr);
- unsigned myset = extractSet(addr);
-
- LRUBlk *blk = sets[myset].findBlk(tag);
-
- return (blk != NULL); // true if in cache
-}
-
-LRUBlk*
-LRU::findBlock(Addr addr, int &lat)
+LRU::BlkType*
+LRU::accessBlock(Addr addr, int &lat, int master_id)
{
Addr tag = extractTag(addr);
unsigned set = extractSet(addr);
- LRUBlk *blk = sets[set].findBlk(tag);
+ BlkType *blk = sets[set].findBlk(tag);
lat = hitLatency;
if (blk != NULL) {
// move this block to head of the MRU list
sets[set].moveToHead(blk);
- if (blk->whenReady > curTick
- && blk->whenReady - curTick > hitLatency) {
- lat = blk->whenReady - curTick;
+ DPRINTF(CacheRepl, "set %x: moving blk %x to MRU\n",
+ set, regenerateBlkAddr(tag, set));
+ if (blk->whenReady > curTick()
+ && blk->whenReady - curTick() > hitLatency) {
+ lat = blk->whenReady - curTick();
}
blk->refCount += 1;
}
return blk;
}
-LRUBlk*
-LRU::findBlock(Packet * &pkt, int &lat)
-{
- Addr addr = pkt->getAddr();
+LRU::BlkType*
+LRU::findBlock(Addr addr) const
+{
Addr tag = extractTag(addr);
unsigned set = extractSet(addr);
- LRUBlk *blk = sets[set].findBlk(tag);
- lat = hitLatency;
- if (blk != NULL) {
- // move this block to head of the MRU list
- sets[set].moveToHead(blk);
- if (blk->whenReady > curTick
- && blk->whenReady - curTick > hitLatency) {
- lat = blk->whenReady - curTick;
- }
- blk->refCount += 1;
- }
-
+ BlkType *blk = sets[set].findBlk(tag);
return blk;
}
-LRUBlk*
-LRU::findBlock(Addr addr) const
+LRU::BlkType*
+LRU::findVictim(Addr addr, PacketList &writebacks)
{
- Addr tag = extractTag(addr);
unsigned set = extractSet(addr);
- LRUBlk *blk = sets[set].findBlk(tag);
+ // grab a replacement candidate
+ 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;
}
-LRUBlk*
-LRU::findReplacement(Packet * &pkt, PacketList &writebacks,
- BlkList &compress_blocks)
+void
+LRU::insertBlock(Addr addr, BlkType *blk, int master_id)
{
- unsigned set = extractSet(pkt->getAddr());
- // grab a replacement candidate
- LRUBlk *blk = sets[set].blks[assoc-1];
- sets[set].moveToHead(blk);
- if (blk->isValid()) {
- replacements[0]++;
- totalRefs += blk->refCount;
- ++sampledRefs;
- blk->refCount = 0;
- } else if (!blk->isTouched) {
+ if (!blk->isTouched) {
tagsInUse++;
blk->isTouched = true;
if (!warmedUp && tagsInUse.value() >= warmupBound) {
warmedUp = true;
- warmupCycle = curTick;
+ warmupCycle = curTick();
}
}
- return blk;
+ // 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;
+
+ // deal with evicted block
+ assert(blk->srcMasterId < cache->system->maxMasters());
+ occupancies[blk->srcMasterId]--;
+ }
+
+ // Set tag for new block. Caller is responsible for setting status.
+ blk->tag = extractTag(addr);
+
+ // deal with what we are bringing in
+ assert(master_id < cache->system->maxMasters());
+ occupancies[master_id]++;
+ blk->srcMasterId = master_id;
+
+ unsigned set = extractSet(addr);
+ sets[set].moveToHead(blk);
}
void
-LRU::invalidateBlk(Addr addr)
+LRU::invalidateBlk(BlkType *blk)
{
- LRUBlk *blk = findBlock(addr);
if (blk) {
+ if (blk->isValid()) {
+ tagsInUse--;
+ assert(blk->srcMasterId < cache->system->maxMasters());
+ occupancies[blk->srcMasterId]--;
+ blk->srcMasterId = Request::invldMasterId;
+ }
blk->status = 0;
blk->isTouched = false;
- tagsInUse--;
+ blk->clearLoadLocks();
+
+ // should be evicted before valid blocks
+ unsigned set = blk->set;
+ sets[set].moveToTail(blk);
}
}
void
-LRU::doCopy(Addr source, Addr dest, PacketList &writebacks)
+LRU::clearLocks()
{
- assert(source == blkAlign(source));
- assert(dest == blkAlign(dest));
- LRUBlk *source_blk = findBlock(source);
- assert(source_blk);
- LRUBlk *dest_blk = findBlock(dest);
- if (dest_blk == NULL) {
- // Need to do a replacement
- Request *search = new Request(dest,1,0);
- Packet * pkt = new Packet(search, Packet::ReadReq, -1);
- BlkList dummy_list;
- dest_blk = findReplacement(pkt, writebacks, dummy_list);
- if (dest_blk->isValid() && dest_blk->isModified()) {
- // Need to writeback data.
-/* pkt = buildWritebackReq(regenerateBlkAddr(dest_blk->tag,
- dest_blk->set),
- dest_blk->req->asid,
- dest_blk->xc,
- blkSize,
- dest_blk->data,
- dest_blk->size);
-*/
- Request *writebackReq = new Request(regenerateBlkAddr(dest_blk->tag,
- dest_blk->set),
- blkSize, 0);
- Packet *writeback = new Packet(writebackReq, Packet::Writeback, -1);
- writeback->allocate();
- memcpy(writeback->getPtr<uint8_t>(),dest_blk->data, blkSize);
- writebacks.push_back(writeback);
- }
- dest_blk->tag = extractTag(dest);
- delete search;
- delete pkt;
+ for (int i = 0; i < numBlocks; i++){
+ blks[i].clearLoadLocks();
}
- /**
- * @todo Can't assume the status once we have coherence on copies.
- */
-
- // Set this block as readable, writeable, and dirty.
- dest_blk->status = 7;
- memcpy(dest_blk->data, source_blk->data, blkSize);
}
void
LRU::cleanupRefs()
{
- for (int i = 0; i < numSets*assoc; ++i) {
+ for (unsigned i = 0; i < numSets*assoc; ++i) {
if (blks[i].isValid()) {
totalRefs += blks[i].refCount;
++sampledRefs;