mem-cache: Add co-allocation function to compressed tags
authorDaniel R. Carvalho <odanrc@yahoo.com.br>
Tue, 19 Jun 2018 15:31:26 +0000 (17:31 +0200)
committerDaniel Carvalho <odanrc@yahoo.com.br>
Wed, 8 May 2019 17:41:09 +0000 (17:41 +0000)
Implement a co-allocation function in compressed tags, so
that compressed blocks can be co-allocated in a superblock.
Co-allocation is possible when compression ratio (CR) blocks
that share a superblock tag can be compressed to up to (100/CR)%
of their size.

Change-Id: I937cc1fcbb488e70309cb5478c12db65f1b4b23f
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/11411
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>

src/mem/cache/tags/compressed_tags.cc
src/mem/cache/tags/compressed_tags.hh

index 46043be6860aa871dffc49f84a9a8e02e8c2a5d1..94b9293237cd5bd76618933e6cf3f6a2a366e0e7 100644 (file)
 
 #include "mem/cache/tags/compressed_tags.hh"
 
+#include "base/trace.hh"
+#include "debug/CacheComp.hh"
 #include "mem/cache/replacement_policies/base.hh"
+#include "mem/cache/replacement_policies/replaceable_entry.hh"
 #include "mem/cache/tags/indexing_policies/base.hh"
 #include "mem/packet.hh"
 #include "params/CompressedTags.hh"
@@ -93,6 +96,78 @@ CompressedTags::tagsInit()
     }
 }
 
+bool
+CompressedTags::canCoAllocate(const SuperBlk* superblock,
+                              const std::size_t compressed_size) const
+{
+    // Simple co-allocation function: at most numBlocksPerSector blocks that
+    // compress at least to (100/numBlocksPerSector)% of their original size
+    // can share a superblock
+    return superblock->isCompressed() &&
+           (compressed_size <= (blkSize * 8) / numBlocksPerSector);
+}
+
+CacheBlk*
+CompressedTags::findVictim(Addr addr, const bool is_secure,
+                           const std::size_t compressed_size,
+                           std::vector<CacheBlk*>& evict_blks) const
+{
+    // Get all possible locations of this superblock
+    const std::vector<ReplaceableEntry*> superblock_entries =
+        indexingPolicy->getPossibleEntries(addr);
+
+    // Check if the superblock this address belongs to has been allocated. If
+    // so, try co-allocating
+    Addr tag = extractTag(addr);
+    SuperBlk* victim_superblock = nullptr;
+    bool is_co_allocation = false;
+    const uint64_t offset = extractSectorOffset(addr);
+    for (const auto& entry : superblock_entries){
+        SuperBlk* superblock = static_cast<SuperBlk*>(entry);
+        if ((tag == superblock->getTag()) && superblock->isValid() &&
+            (is_secure == superblock->isSecure()) &&
+            !superblock->blks[offset]->isValid() &&
+            canCoAllocate(superblock, compressed_size))
+        {
+            victim_superblock = superblock;
+            is_co_allocation = true;
+            break;
+        }
+    }
+
+    // If the superblock is not present or cannot be co-allocated a
+    // superblock must be replaced
+    if (victim_superblock == nullptr){
+        // Choose replacement victim from replacement candidates
+        victim_superblock = static_cast<SuperBlk*>(
+            replacementPolicy->getVictim(superblock_entries));
+
+        // The whole superblock must be evicted to make room for the new one
+        for (const auto& blk : victim_superblock->blks){
+            evict_blks.push_back(blk);
+        }
+    }
+
+    // Get the location of the victim block within the superblock
+    SectorSubBlk* victim = victim_superblock->blks[offset];
+
+    // It would be a hit if victim was valid in a co-allocation, and upgrades
+    // do not call findVictim, so it cannot happen
+    if (is_co_allocation){
+        assert(!victim->isValid());
+
+        // Print all co-allocated blocks
+        DPRINTF(CacheComp, "Co-Allocation: offset %d with blocks\n", offset);
+        for (const auto& blk : victim_superblock->blks){
+            if (blk->isValid()) {
+                DPRINTFR(CacheComp, "\t[%s]\n", blk->print());
+            }
+        }
+    }
+
+    return victim;
+}
+
 void
 CompressedTags::insertBlock(const PacketPtr pkt, CacheBlk *blk)
 {
index 303bc79d8783cafea4ab2d0b4e83fe161f033376..f9321b946a0c4891c4ea2a71f4a9ef48f3c7c909 100644 (file)
@@ -42,6 +42,7 @@
 #include "mem/cache/tags/super_blk.hh"
 
 class BaseCache;
+class CacheBlk;
 struct CompressedTagsParams;
 
 /**
@@ -96,6 +97,30 @@ class CompressedTags : public SectorTags
      */
     void tagsInit() override;
 
+    /**
+     * Checks whether a superblock can co-allocate given compressed data block.
+     *
+     * @param superblock Superblock to check.
+     * @param compressed_size Size, in bits, of new block to allocate.
+     * @return True if block can be co-allocated in superblock.
+     */
+    bool canCoAllocate(const SuperBlk* superblock,
+                       const std::size_t compressed_size) const;
+
+    /**
+     * Find replacement victim based on address. Checks if data can be co-
+     * allocated before choosing blocks to be evicted.
+     *
+     * @param addr Address to find a victim for.
+     * @param is_secure True if the target memory space is secure.
+     * @param compressed_size Size, in bits, of new block to allocate.
+     * @param evict_blks Cache blocks to be evicted.
+     * @return Cache block to be replaced.
+     */
+    CacheBlk* findVictim(Addr addr, const bool is_secure,
+                         const std::size_t compressed_size,
+                         std::vector<CacheBlk*>& evict_blks) const override;
+
     /**
      * Insert the new block into the cache and update replacement data.
      *