diff options
author | Daniel R. Carvalho <odanrc@yahoo.com.br> | 2018-04-24 11:20:38 +0200 |
---|---|---|
committer | Daniel Carvalho <odanrc@yahoo.com.br> | 2018-06-08 09:33:39 +0000 |
commit | 62db2c46f460deb41d43930e4b6460e53f70376a (patch) | |
tree | b00cde3c6f1c2f7f12d8c86b5db8aa68ea69259a /src/mem/cache/base.cc | |
parent | 815b12fb4aa45bfe8b38f96f923c150880bf9200 (diff) | |
download | gem5-62db2c46f460deb41d43930e4b6460e53f70376a.tar.xz |
mem-cache: Return evictions along with victims
For both sector and compressed caches multiple blocks may need
to be evicted in order to make room for a new block.
For example, when replacing a sector, all the blocks in this
sector must be evicted. A replacement, however, does not always
need to evict multiple blocks, as it is in the case of an
insertion of a block whose sector is already present in the cache
(i.e., its corresponding entry in the sector had not been brought
in yet, so it was invalid).
This patch creates the cache framework for that to happen.
Change-Id: I77bedf69637cf899fef4d9432eb6da8529ea398b
Reviewed-on: https://gem5-review.googlesource.com/10142
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Diffstat (limited to 'src/mem/cache/base.cc')
-rw-r--r-- | src/mem/cache/base.cc | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index efdb3be2c..75b17699a 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -1209,38 +1209,56 @@ CacheBlk* BaseCache::allocateBlock(Addr addr, bool is_secure, PacketList &writebacks) { // Find replacement victim - CacheBlk *blk = tags->findVictim(addr); + std::vector<CacheBlk*> evict_blks; + CacheBlk *victim = tags->findVictim(addr, evict_blks); // It is valid to return nullptr if there is no victim - if (!blk) + if (!victim) return nullptr; - if (blk->isValid()) { - 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; - } else { - DPRINTF(Cache, "replacement: replacing %#llx (%s) with %#llx " - "(%s): %s\n", repl_addr, blk->isSecure() ? "s" : "ns", - addr, is_secure ? "s" : "ns", - blk->isDirty() ? "writeback" : "clean"); + // Check for transient state allocations. If any of the entries listed + // for eviction has a transient state, the allocation fails + for (const auto& blk : evict_blks) { + if (blk->isValid()) { + 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 (victim->isValid()) { + DPRINTF(Cache, "replacement: replacing %#llx (%s) with %#llx " + "(%s): %s\n", regenerateBlkAddr(victim), + victim->isSecure() ? "s" : "ns", + addr, is_secure ? "s" : "ns", + victim->isDirty() ? "writeback" : "clean"); + replacements++; + } + + // Evict valid blocks associated to this victim block + for (const auto& blk : evict_blks) { + if (blk->isValid()) { if (blk->wasPrefetched()) { unusedPrefetches++; } + evictBlock(blk, writebacks); - replacements++; } } - return blk; + return victim; } void |