summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel R. Carvalho <odanrc@yahoo.com.br>2019-06-12 17:26:11 +0200
committerDaniel Carvalho <odanrc@yahoo.com.br>2020-01-17 16:31:03 +0000
commit7dce9e3782523e1b1989c50be194385b93603aea (patch)
tree47e9084bf1a6c5b229836a659d4e4a9e9b79956f
parentc5d87b0693f1f3cab8bf05ba5327986940cedf5b (diff)
downloadgem5-7dce9e3782523e1b1989c50be194385b93603aea.tar.xz
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 <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22607 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com> Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
-rw-r--r--src/mem/cache/base.cc112
-rw-r--r--src/mem/cache/base.hh12
2 files changed, 58 insertions, 66 deletions
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
@@ -795,6 +795,43 @@ BaseCache::getNextQueueEntry()
}
bool
+BaseCache::handleEvictions(std::vector<CacheBlk*> &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<CacheBlk*> evict_blks;
const bool was_compressed = compression_blk->isCompressed();
if (was_compressed && !is_co_allocatable) {
- // Get all co-allocated blocks
+ std::vector<CacheBlk*> 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
@@ -710,6 +710,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<CacheBlk*> &evict_blks,
+ PacketList &writebacks);
+
+ /**
* Handle a fill operation caused by a received packet.
*
* Populates a cache block and handles all outstanding requests for the