mem-cache: Add function to move blocks in the tags
authorDaniel R. Carvalho <odanrc@yahoo.com.br>
Fri, 7 Jun 2019 15:16:39 +0000 (17:16 +0200)
committerDaniel Carvalho <odanrc@yahoo.com.br>
Thu, 12 Nov 2020 21:46:43 +0000 (21:46 +0000)
Add a function to allow moving a block's metadata from a source
entry to an invalid destination entry.

Change-Id: I7c8adbcd1133c907f1eea7f69dca983215bc3960
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/36576
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/mem/cache/tags/base.cc
src/mem/cache/tags/base.hh
src/mem/cache/tags/base_set_assoc.cc
src/mem/cache/tags/base_set_assoc.hh
src/mem/cache/tags/fa_lru.cc
src/mem/cache/tags/fa_lru.hh
src/mem/cache/tags/sector_tags.cc
src/mem/cache/tags/sector_tags.hh

index b00ad49211ebf416ba72f5ba0ac5f267bc6213bf..edd85a47a0b27e2d2a867ba5372a052e54b2b92d 100644 (file)
@@ -123,6 +123,19 @@ BaseTags::insertBlock(const PacketPtr pkt, CacheBlk *blk)
     stats.dataAccesses += 1;
 }
 
+void
+BaseTags::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
+{
+    assert(!dest_blk->isValid());
+    assert(src_blk->isValid());
+
+    // Move src's contents to dest's
+    *dest_blk = std::move(*src_blk);
+
+    assert(dest_blk->isValid());
+    assert(!src_blk->isValid());
+}
+
 Addr
 BaseTags::extractTag(const Addr addr) const
 {
index deda63ec251805c3923fa47e7ff6a9878603d3d7..5a407a6b16d5d64f35be39cf58ffcdca77d592dd 100644 (file)
@@ -308,6 +308,16 @@ class BaseTags : public ClockedObject
      */
     virtual void insertBlock(const PacketPtr pkt, CacheBlk *blk);
 
+    /**
+     * Move a block's metadata to another location decided by the replacement
+     * policy. It behaves as a swap, however, since the destination block
+     * should be invalid, the result is a move.
+     *
+     * @param src_blk The source block.
+     * @param dest_blk The destination block. Must be invalid.
+     */
+    virtual void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk);
+
     /**
      * Regenerate the block address.
      *
index 6507007a7f0a3cc02afaafffb0e06269d6978855..66635335d66c70fc21a2b9920a7933f56580ed21 100644 (file)
@@ -93,3 +93,15 @@ BaseSetAssoc::invalidate(CacheBlk *blk)
     // Invalidate replacement data
     replacementPolicy->invalidate(blk->replacementData);
 }
+
+void
+BaseSetAssoc::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
+{
+    BaseTags::moveBlock(src_blk, dest_blk);
+
+    // Since the blocks were using different replacement data pointers,
+    // we must touch the replacement data of the new entry, and invalidate
+    // the one that is being moved.
+    replacementPolicy->invalidate(src_blk->replacementData);
+    replacementPolicy->reset(dest_blk->replacementData);
+}
index 787cc6bd0132870c81d2cb6f68626d1264933789..b13b0078a2934a523f13f9797c4c29e133743a10 100644 (file)
@@ -199,6 +199,8 @@ class BaseSetAssoc : public BaseTags
         replacementPolicy->reset(blk->replacementData);
     }
 
+    void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override;
+
     /**
      * Limit the allocation for the cache ways.
      * @param ways The maximum number of ways available for replacement.
index 78d601d7782db7f84bb21421c903e19a3c3070e9..79019fc7644b77fc8c2d37aab5fc46acd105000b 100644 (file)
@@ -225,6 +225,12 @@ FALRU::insertBlock(const PacketPtr pkt, CacheBlk *blk)
     tagHash[std::make_pair(blk->getTag(), blk->isSecure())] = falruBlk;
 }
 
+void
+FALRU::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
+{
+    panic("Moving blocks in FALRU has not been implemented");
+}
+
 void
 FALRU::moveToHead(FALRUBlk *blk)
 {
index f03ecee582cecf510b0e241014340b30099a65e3..f24ac0e8c2ad8c5f5fb74e249e7f71f2f2a2573d 100644 (file)
@@ -232,6 +232,8 @@ class FALRU : public BaseTags
      */
     void insertBlock(const PacketPtr pkt, CacheBlk *blk) override;
 
+    void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override;
+
     /**
      * Generate the tag from the addres. For fully associative this is just the
      * block address.
index 8a4b86f90e92d35e8f058e6a5c02d98158d93d75..ff2f4a415f47cf15e05ca000edd3e5d647be0667 100644 (file)
@@ -128,6 +128,7 @@ SectorTags::invalidate(CacheBlk *blk)
     if (!sector_blk->isValid()) {
         // Decrease the number of tags in use
         stats.tagsInUse--;
+        assert(stats.tagsInUse.value() >= 0);
 
         // Invalidate replacement data, as we're invalidating the sector
         replacementPolicy->invalidate(sector_blk->replacementData);
@@ -186,6 +187,7 @@ SectorTags::insertBlock(const PacketPtr pkt, CacheBlk *blk)
     } else {
         // Increment tag counter
         stats.tagsInUse++;
+        assert(stats.tagsInUse.value() <= numSectors);
 
         // A new entry resets the replacement data
         replacementPolicy->reset(sector_blk->replacementData);
@@ -195,6 +197,52 @@ SectorTags::insertBlock(const PacketPtr pkt, CacheBlk *blk)
     BaseTags::insertBlock(pkt, blk);
 }
 
+void
+SectorTags::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
+{
+    const bool dest_was_valid =
+        static_cast<SectorSubBlk*>(dest_blk)->getSectorBlock()->isValid();
+
+    BaseTags::moveBlock(src_blk, dest_blk);
+
+    // Get blocks' sectors. The blocks have effectively been swapped by now,
+    // so src points to an invalid block, and dest to the moved valid one.
+    SectorSubBlk* src_sub_blk = static_cast<SectorSubBlk*>(src_blk);
+    const SectorBlk* src_sector_blk = src_sub_blk->getSectorBlock();
+    SectorSubBlk* dest_sub_blk = static_cast<SectorSubBlk*>(dest_blk);
+    const SectorBlk* dest_sector_blk = dest_sub_blk->getSectorBlock();
+
+    // Since the blocks were using different replacement data pointers,
+    // we must touch the replacement data of the new entry, and invalidate
+    // the one that is being moved.
+    // When a block in a sector is invalidated, it does not make the tag
+    // invalid automatically, as there might be other blocks in the sector
+    // using it. The tag is invalidated only when there is a single block
+    // in the sector.
+    if (!src_sector_blk->isValid()) {
+        // Invalidate replacement data, as we're invalidating the sector
+        replacementPolicy->invalidate(src_sector_blk->replacementData);
+
+        if (dest_was_valid) {
+            // If destination sector was valid, and the source sector became
+            // invalid, there is one less tag being used
+            stats.tagsInUse--;
+            assert(stats.tagsInUse.value() >= 0);
+        }
+    } else if (!dest_was_valid) {
+        // If destination sector was invalid and became valid, and the source
+        // sector is still valid, there is one extra tag being used
+        stats.tagsInUse++;
+        assert(stats.tagsInUse.value() <= numSectors);
+    }
+
+    if (dest_was_valid) {
+        replacementPolicy->touch(dest_sector_blk->replacementData);
+    } else {
+        replacementPolicy->reset(dest_sector_blk->replacementData);
+    }
+}
+
 CacheBlk*
 SectorTags::findBlock(Addr addr, bool is_secure) const
 {
index c56ef2409e38ce34a1085b0cceb3978e225a52e1..5c228eeea3477128f67fd35225aa0e6449aeb030 100644 (file)
@@ -149,6 +149,8 @@ class SectorTags : public BaseTags
      */
     void insertBlock(const PacketPtr pkt, CacheBlk *blk) override;
 
+    void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override;
+
     /**
      * Finds the given address in the cache, do not update replacement data.
      * i.e. This is a no-side-effect find of a block.