From 7dce9e3782523e1b1989c50be194385b93603aea Mon Sep 17 00:00:00 2001 From: "Daniel R. Carvalho" Date: Wed, 12 Jun 2019 17:26:11 +0200 Subject: mem-cache: Factor out multiple block eviction Create a function to try to evict multiple blocks while checking for transient state. Change-Id: I6a879fa5e793cd92c4bdf4a258a133de4c865012 Signed-off-by: Daniel R. Carvalho Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22607 Tested-by: kokoro Reviewed-by: Nikos Nikoleris Maintainer: Nikos Nikoleris --- src/mem/cache/base.cc | 112 +++++++++++++++++++++----------------------------- src/mem/cache/base.hh | 12 ++++++ 2 files changed, 58 insertions(+), 66 deletions(-) (limited to 'src/mem/cache') diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index d56fcbeee..87f2af161 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -794,6 +794,43 @@ BaseCache::getNextQueueEntry() return nullptr; } +bool +BaseCache::handleEvictions(std::vector &evict_blks, + PacketList &writebacks) +{ + bool replacement = false; + for (const auto& blk : evict_blks) { + if (blk->isValid()) { + replacement = true; + + const MSHR* mshr = + mshrQueue.findMatch(regenerateBlkAddr(blk), blk->isSecure()); + if (mshr) { + // Must be an outstanding upgrade or clean request on a block + // we're about to replace + assert((!blk->isWritable() && mshr->needsWritable()) || + mshr->isCleaning()); + return false; + } + } + } + + // The victim will be replaced by a new entry, so increase the replacement + // counter if a valid block is being replaced + if (replacement) { + stats.replacements++; + + // Evict valid blocks associated to this victim block + for (auto& blk : evict_blks) { + if (blk->isValid()) { + evictBlock(blk, writebacks); + } + } + } + + return true; +} + bool BaseCache::updateCompressionData(CacheBlk *blk, const uint64_t* data, PacketList &writebacks) @@ -833,37 +870,20 @@ BaseCache::updateCompressionData(CacheBlk *blk, const uint64_t* data, // allocated blocks to make room for the expansion, but other approaches // that take the replacement data of the superblock into account may // generate better results - std::vector evict_blks; const bool was_compressed = compression_blk->isCompressed(); if (was_compressed && !is_co_allocatable) { - // Get all co-allocated blocks + std::vector evict_blks; for (const auto& sub_blk : superblock->blks) { if (sub_blk->isValid() && (compression_blk != sub_blk)) { - // Check for transient state allocations. If any of the - // entries listed for eviction has a transient state, the - // allocation fails - const Addr repl_addr = regenerateBlkAddr(sub_blk); - const MSHR *repl_mshr = - mshrQueue.findMatch(repl_addr, sub_blk->isSecure()); - if (repl_mshr) { - DPRINTF(CacheRepl, "Aborting data expansion of %s due " \ - "to replacement of block in transient state: %s\n", - compression_blk->print(), sub_blk->print()); - // Too hard to replace block with transient state, so it - // cannot be evicted. Mark the update as failed and expect - // the caller to evict this block. Since this is called - // only when writebacks arrive, and packets do not contain - // compressed data, there is no need to decompress - compression_blk->setSizeBits(blkSize * 8); - compression_blk->setDecompressionLatency(Cycles(0)); - compression_blk->setUncompressed(); - return false; - } - evict_blks.push_back(sub_blk); } } + // Try to evict blocks; if it fails, give up on update + if (!handleEvictions(evict_blks, writebacks)) { + return false; + } + // Update the number of data expansions stats.dataExpansions++; @@ -880,13 +900,6 @@ BaseCache::updateCompressionData(CacheBlk *blk, const uint64_t* data, compression_blk->setSizeBits(compression_size); compression_blk->setDecompressionLatency(decompression_lat); - // Evict valid blocks - for (const auto& evict_blk : evict_blks) { - if (evict_blk->isValid()) { - evictBlock(evict_blk, writebacks); - } - } - return true; } @@ -1427,42 +1440,9 @@ BaseCache::allocateBlock(const PacketPtr pkt, PacketList &writebacks) // Print victim block's information DPRINTF(CacheRepl, "Replacement victim: %s\n", victim->print()); - // Check for transient state allocations. If any of the entries listed - // for eviction has a transient state, the allocation fails - bool replacement = false; - for (const auto& blk : evict_blks) { - if (blk->isValid()) { - replacement = true; - - Addr repl_addr = regenerateBlkAddr(blk); - MSHR *repl_mshr = mshrQueue.findMatch(repl_addr, blk->isSecure()); - if (repl_mshr) { - // must be an outstanding upgrade or clean request - // on a block we're about to replace... - assert((!blk->isWritable() && repl_mshr->needsWritable()) || - repl_mshr->isCleaning()); - - // too hard to replace block with transient state - // allocation failed, block not inserted - return nullptr; - } - } - } - - // The victim will be replaced by a new entry, so increase the replacement - // counter if a valid block is being replaced - if (replacement) { - // Evict valid blocks associated to this victim block - for (const auto& blk : evict_blks) { - if (blk->isValid()) { - DPRINTF(CacheRepl, "Evicting %s (%#llx) to make room for " \ - "%#llx (%s)\n", blk->print(), regenerateBlkAddr(blk), - addr, is_secure); - evictBlock(blk, writebacks); - } - } - - stats.replacements++; + // Try to evict blocks; if it fails, give up on allocation + if (!handleEvictions(evict_blks, writebacks)) { + return nullptr; } // If using a compressor, set compression data. This must be done before diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index cd467c8ad..8e5c18c11 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -709,6 +709,18 @@ class BaseCache : public ClockedObject */ void maintainClusivity(bool from_cache, CacheBlk *blk); + /** + * Try to evict the given blocks. If any of them is a transient eviction, + * that is, the block is present in the MSHR queue all evictions are + * cancelled since handling such cases has not been implemented. + * + * @param evict_blks Blocks marked for eviction. + * @param writebacks List for any writebacks that need to be performed. + * @return False if any of the evicted blocks is in transient state. + */ + bool handleEvictions(std::vector &evict_blks, + PacketList &writebacks); + /** * Handle a fill operation caused by a received packet. * -- cgit v1.2.3