mem-cache: ReplacementPolicy specific replacement data
[gem5.git] / src / mem / cache / tags / base_set_assoc.hh
index 1fd739110fc1ed7c19e83c4b43fcc7a644d0201f..5a3e832c15e356bb02631f22ecac79fa3216e35a 100644 (file)
 
 #include <cassert>
 #include <cstring>
-#include <memory>
 #include <vector>
 
+#include "debug/CacheRepl.hh"
 #include "mem/cache/base.hh"
 #include "mem/cache/blk.hh"
+#include "mem/cache/replacement_policies/base.hh"
 #include "mem/cache/tags/base.hh"
 #include "mem/cache/tags/cacheset.hh"
 #include "mem/packet.hh"
  * A BaseSetAssoc cache tag store.
  * @sa  \ref gem5MemorySystem "gem5 Memory System"
  *
- * The BaseSetAssoc tags provide a base, as well as the functionality
- * common to any set associative tags. Any derived class must implement
- * the methods related to the specifics of the actual replacment policy.
- * These are:
- *
- * BlkType* accessBlock();
- * BlkType* findVictim();
- * void insertBlock();
+ * The BaseSetAssoc placement policy divides the cache into s sets of w
+ * cache lines (ways). A cache line is mapped onto a set, and can be placed
+ * into any of the ways of this set.
  */
 class BaseSetAssoc : public BaseTags
 {
@@ -81,7 +77,6 @@ class BaseSetAssoc : public BaseTags
     /** Typedef the set type used in this tag store. */
     typedef CacheSet<CacheBlk> SetType;
 
-
   protected:
     /** The associativity of the cache. */
     const unsigned assoc;
@@ -90,8 +85,6 @@ class BaseSetAssoc : public BaseTags
 
     /** The cache blocks. */
     std::vector<BlkType> blks;
-    /** The data blocks, 1 per cache block. */
-    std::unique_ptr<uint8_t[]> dataBlks;
 
     /** The number of sets in the cache. */
     const unsigned numSets;
@@ -109,8 +102,10 @@ class BaseSetAssoc : public BaseTags
     /** Mask out all bits that aren't part of the set index. */
     unsigned setMask;
 
-public:
+    /** Replacement policy */
+    BaseReplacementPolicy *replacementPolicy;
 
+  public:
     /** Convenience typedef. */
      typedef BaseSetAssocParams Params;
 
@@ -124,6 +119,14 @@ public:
      */
     virtual ~BaseSetAssoc() {};
 
+    /**
+     * This function updates the tags when a block is invalidated but does
+     * not invalidate the block itself. It also updates the replacement data.
+     *
+     * @param blk The block to invalidate.
+     */
+    void invalidate(CacheBlk *blk) override;
+
     /**
      * Find the cache block given set and way
      * @param set The set of the block.
@@ -169,7 +172,12 @@ public:
                 lat = cache->ticksToCycles(blk->whenReady - curTick()) +
                 accessLatency;
             }
-            blk->refCount += 1;
+
+            // Update number of references to accessed block
+            blk->refCount++;
+
+            // Update replacement data of accessed block
+            replacementPolicy->touch(blk->replacementData);
         } else {
             // If a cache miss
             lat = lookupLatency;
@@ -189,77 +197,55 @@ public:
     CacheBlk* findBlock(Addr addr, bool is_secure) const override;
 
     /**
-     * Find an invalid block to evict for the address provided.
-     * If there are no invalid blocks, this will return the block
-     * in the least-recently-used position.
-     * @param addr The addr to a find a replacement candidate for.
-     * @return The candidate block.
+     * Find replacement victim based on address.
+     *
+     * @param addr Address to find a victim for.
+     * @return Cache block to be replaced.
      */
     CacheBlk* findVictim(Addr addr) override
     {
-        BlkType *blk = nullptr;
-        int set = extractSet(addr);
-
-        // prefer to evict an invalid block
-        for (int i = 0; i < allocAssoc; ++i) {
-            blk = sets[set].blks[i];
-            if (!blk->isValid())
-                break;
-        }
+        // Get possible locations for the victim block
+        std::vector<CacheBlk*> locations = getPossibleLocations(addr);
 
-        return blk;
+        // Choose replacement victim from replacement candidates
+        CacheBlk* victim = static_cast<CacheBlk*>(replacementPolicy->getVictim(
+                               std::vector<ReplaceableEntry*>(
+                                   locations.begin(), locations.end())));
+
+        DPRINTF(CacheRepl, "set %x, way %x: selecting blk for replacement\n",
+            victim->set, victim->way);
+
+        return victim;
+    }
+
+    /**
+     * Find all possible block locations for insertion and replacement of
+     * an address. Should be called immediately before ReplacementPolicy's
+     * findVictim() not to break cache resizing.
+     * Returns blocks in all ways belonging to the set of the address.
+     *
+     * @param addr The addr to a find possible locations for.
+     * @return The possible locations.
+     */
+    const std::vector<CacheBlk*> getPossibleLocations(Addr addr)
+    {
+        return sets[extractSet(addr)].blks;
     }
 
     /**
-     * Insert the new block into the cache.
+     * Insert the new block into the cache and update replacement data.
+     *
      * @param pkt Packet holding the address to update
      * @param blk The block to update.
      */
-     void insertBlock(PacketPtr pkt, CacheBlk *blk) override
-     {
-         Addr addr = pkt->getAddr();
-         MasterID master_id = pkt->req->masterId();
-         uint32_t task_id = pkt->req->taskId();
-
-         if (!blk->isTouched) {
-             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;
-
-             invalidate(blk);
-             blk->invalidate();
-         }
-
-         // Previous block, if existed, has been removed, and now we have
-         // to insert the new one and mark it as touched
-         tagsInUse++;
-         blk->isTouched = true;
-
-         // 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;
-         blk->task_id = task_id;
-         blk->tickInserted = curTick();
-
-         // We only need to write into one tag and one data block.
-         tagAccesses += 1;
-         dataAccesses += 1;
-     }
+    void insertBlock(PacketPtr pkt, CacheBlk *blk) override
+    {
+        // Insert block
+        BaseTags::insertBlock(pkt, blk);
+
+        // Update replacement policy
+        replacementPolicy->reset(blk->replacementData);
+    }
 
     /**
      * Limit the allocation for the cache ways.
@@ -339,8 +325,8 @@ public:
      * \param visitor Visitor to call on each block.
      */
     void forEachBlk(CacheBlkVisitor &visitor) override {
-        for (unsigned i = 0; i < numSets * assoc; ++i) {
-            if (!visitor(blks[i]))
+        for (CacheBlk& blk : blks) {
+            if (!visitor(blk))
                 return;
         }
     }