SCons: Support building without an ISA
[gem5.git] / src / mem / cache / tags / lru.cc
index 8e87797744c5582294a29260f68650a2ab8bbb35..8a8b0d0d650c714a23eadb7d62cddb8578ec568b 100644 (file)
 
 #include <string>
 
-#include "mem/cache/base_cache.hh"
 #include "base/intmath.hh"
+#include "mem/cache/base.hh"
+#include "mem/cache/tags/cacheset.hh"
 #include "mem/cache/tags/lru.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)) {
@@ -97,9 +63,6 @@ LRU::LRU(int _numSets, int _blkSize, int _assoc, int _hit_latency) :
         fatal("access latency must be greater than zero");
     }
 
-    LRUBlk  *blk;
-    int i, j, blkIndex;
-
     blkMask = blkSize - 1;
     setShift = floorLog2(blkSize);
     setMask = numSets - 1;
@@ -109,20 +72,21 @@ LRU::LRU(int _numSets, int _blkSize, int _assoc, int _hit_latency) :
     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;
 
@@ -150,29 +114,18 @@ LRU::~LRU()
     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 context_src)
 {
     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);
+        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;
@@ -184,29 +137,45 @@ LRU::findBlock(Addr addr, int &lat)
 }
 
 
-LRUBlk*
+LRU::BlkType*
 LRU::findBlock(Addr addr) const
 {
     Addr tag = extractTag(addr);
     unsigned set = extractSet(addr);
-    LRUBlk *blk = sets[set].findBlk(tag);
+    BlkType *blk = sets[set].findBlk(tag);
     return blk;
 }
 
-LRUBlk*
-LRU::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                     BlkList &compress_blocks)
+LRU::BlkType*
+LRU::findVictim(Addr addr, PacketList &writebacks)
 {
-    unsigned set = extractSet(pkt->getAddr());
+    unsigned set = extractSet(addr);
     // grab a replacement candidate
-    LRUBlk *blk = sets[set].blks[assoc-1];
-    sets[set].moveToHead(blk);
+    BlkType *blk = sets[set].blks[assoc-1];
     if (blk->isValid()) {
         replacements[0]++;
         totalRefs += blk->refCount;
         ++sampledRefs;
         blk->refCount = 0;
-    } else if (!blk->isTouched) {
+
+        // deal with evicted block
+        if (blk->contextSrc != -1) {
+            occupancies[blk->contextSrc % cache->numCpus()]--;
+            blk->contextSrc = -1;
+        } else {
+            occupancies[cache->numCpus()]--;
+        }
+
+        DPRINTF(CacheRepl, "set %x: selecting blk %x for replacement\n",
+                set, regenerateBlkAddr(blk->tag, set));
+    }
+    return blk;
+}
+
+void
+LRU::insertBlock(Addr addr, BlkType *blk, int context_src)
+{
+    if (!blk->isTouched) {
         tagsInUse++;
         blk->isTouched = true;
         if (!warmedUp && tagsInUse.value() >= warmupBound) {
@@ -215,24 +184,50 @@ LRU::findReplacement(PacketPtr &pkt, PacketList &writebacks,
         }
     }
 
-    return blk;
+    // Set tag for new block.  Caller is responsible for setting status.
+    blk->tag = extractTag(addr);
+
+    // deal with what we are bringing in
+    if (context_src != -1) {
+        occupancies[context_src % cache->numCpus()]++;
+    } else {
+        occupancies[cache->numCpus()]++;
+    }
+    blk->contextSrc = context_src;
+
+    unsigned set = extractSet(addr);
+    sets[set].moveToHead(blk);
 }
 
 void
-LRU::invalidateBlk(LRU::BlkType *blk)
+LRU::invalidateBlk(BlkType *blk)
 {
     if (blk) {
         blk->status = 0;
         blk->isTouched = false;
         blk->clearLoadLocks();
         tagsInUse--;
+        if (blk->contextSrc != -1) {
+            occupancies[blk->contextSrc % cache->numCpus()]--;
+            blk->contextSrc = -1;
+        } else {
+            occupancies[cache->numCpus()]--;
+        }
+    }
+}
+
+void
+LRU::clearLocks()
+{
+    for (int i = 0; i < numBlocks; i++){
+        blks[i].clearLoadLocks();
     }
 }
 
 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;