misc: Standardize the way create() constructs SimObjects.
[gem5.git] / src / mem / cache / tags / compressed_tags.cc
index cc799df24fa208a88d01ac50c337146921f1c8bb..64a7102d1874c2b7284f53e58d468f4411d68059 100644 (file)
@@ -24,8 +24,6 @@
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Daniel Carvalho
  */
 
 /**
 
 #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"
 
-CompressedTags::CompressedTags(const Params *p)
+CompressedTags::CompressedTags(const Params &p)
     : SectorTags(p)
 {
 }
@@ -59,8 +61,9 @@ CompressedTags::tagsInit()
         // Locate next cache superblock
         SuperBlk* superblock = &superBlks[superblock_index];
 
-        // Link block to indexing policy
-        indexingPolicy->setEntry(superblock, superblock_index);
+        // Superblocks must be aware of the block size due to their co-
+        // allocation conditions
+        superblock->setBlkSize(blkSize);
 
         // Associate a replacement data entry to the block
         superblock->replacementData = replacementPolicy->instantiateEntry();
@@ -89,6 +92,97 @@ CompressedTags::tagsInit()
             // Update block index
             ++blk_index;
         }
+
+        // Link block to indexing policy
+        indexingPolicy->setEntry(superblock, superblock_index);
+    }
+}
+
+CacheBlk*
+CompressedTags::findVictim(Addr addr, const bool is_secure,
+                           const std::size_t compressed_size,
+                           std::vector<CacheBlk*>& evict_blks)
+{
+    // 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 (superblock->matchTag(tag, is_secure) &&
+            !superblock->blks[offset]->isValid() &&
+            superblock->isCompressed() &&
+            superblock->canCoAllocate(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){
+            if (blk->isValid()) {
+                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());
+            }
+        }
+    }
+
+    // Update number of sub-blocks evicted due to a replacement
+    sectorStats.evictionsReplacement[evict_blks.size()]++;
+
+    return victim;
+}
+
+void
+CompressedTags::insertBlock(const PacketPtr pkt, CacheBlk *blk)
+{
+    // We check if block can co-allocate before inserting, because this check
+    // assumes the block is still invalid
+    CompressionBlk* compression_blk = static_cast<CompressionBlk*>(blk);
+    const SuperBlk* superblock = static_cast<const SuperBlk*>(
+        compression_blk->getSectorBlock());
+    const bool is_co_allocatable = superblock->isCompressed() &&
+        superblock->canCoAllocate(compression_blk->getSizeBits());
+
+    // Insert block
+    SectorTags::insertBlock(pkt, blk);
+
+    // We always store compressed blocks when possible
+    if (is_co_allocatable) {
+        compression_blk->setCompressed();
+    } else {
+        compression_blk->setUncompressed();
     }
 }
 
@@ -112,7 +206,7 @@ CompressedTags::anyBlk(std::function<bool(CacheBlk &)> visitor)
 }
 
 CompressedTags *
-CompressedTagsParams::create()
+CompressedTagsParams::create() const
 {
-    return new CompressedTags(this);
+    return new CompressedTags(*this);
 }