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>
This commit is contained in:
committed by
Daniel Carvalho
parent
815b12fb4a
commit
62db2c46f4
64
src/mem/cache/base.cc
vendored
64
src/mem/cache/base.cc
vendored
@@ -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());
|
||||
|
||||
if (blk->wasPrefetched()) {
|
||||
unusedPrefetches++;
|
||||
// too hard to replace block with transient state
|
||||
// allocation failed, block not inserted
|
||||
return nullptr;
|
||||
}
|
||||
evictBlock(blk, writebacks);
|
||||
replacements++;
|
||||
}
|
||||
}
|
||||
|
||||
return blk;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
return victim;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
12
src/mem/cache/tags/base.hh
vendored
12
src/mem/cache/tags/base.hh
vendored
@@ -262,12 +262,20 @@ class BaseTags : public ClockedObject
|
||||
}
|
||||
|
||||
/**
|
||||
* Find replacement victim based on address.
|
||||
* Find replacement victim based on address. If the address requires
|
||||
* blocks to be evicted, their locations are listed for eviction. If a
|
||||
* conventional cache is being used, the list only contains the victim.
|
||||
* However, if using sector or compressed caches, the victim is one of
|
||||
* the blocks to be evicted, but its location is the only one that will
|
||||
* be assigned to the newly allocated block associated to this address.
|
||||
* @sa insertBlock
|
||||
*
|
||||
* @param addr Address to find a victim for.
|
||||
* @param evict_blks Cache blocks to be evicted.
|
||||
* @return Cache block to be replaced.
|
||||
*/
|
||||
virtual CacheBlk* findVictim(Addr addr) = 0;
|
||||
virtual CacheBlk* findVictim(Addr addr, std::vector<CacheBlk*>& evict_blks)
|
||||
const = 0;
|
||||
|
||||
virtual CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) = 0;
|
||||
|
||||
|
||||
12
src/mem/cache/tags/base_set_assoc.hh
vendored
12
src/mem/cache/tags/base_set_assoc.hh
vendored
@@ -200,12 +200,15 @@ class BaseSetAssoc : public BaseTags
|
||||
ReplaceableEntry* findBlockBySetAndWay(int set, int way) const override;
|
||||
|
||||
/**
|
||||
* Find replacement victim based on address.
|
||||
* Find replacement victim based on address. The list of evicted blocks
|
||||
* only contains the victim.
|
||||
*
|
||||
* @param addr Address to find a victim for.
|
||||
* @param evict_blks Cache blocks to be evicted.
|
||||
* @return Cache block to be replaced.
|
||||
*/
|
||||
CacheBlk* findVictim(Addr addr) override
|
||||
CacheBlk* findVictim(Addr addr, std::vector<CacheBlk*>& evict_blks) const
|
||||
override
|
||||
{
|
||||
// Get possible locations for the victim block
|
||||
std::vector<CacheBlk*> locations = getPossibleLocations(addr);
|
||||
@@ -215,6 +218,9 @@ class BaseSetAssoc : public BaseTags
|
||||
std::vector<ReplaceableEntry*>(
|
||||
locations.begin(), locations.end())));
|
||||
|
||||
// There is only one eviction for this replacement
|
||||
evict_blks.push_back(victim);
|
||||
|
||||
DPRINTF(CacheRepl, "set %x, way %x: selecting blk for replacement\n",
|
||||
victim->set, victim->way);
|
||||
|
||||
@@ -230,7 +236,7 @@ class BaseSetAssoc : public BaseTags
|
||||
* @param addr The addr to a find possible locations for.
|
||||
* @return The possible locations.
|
||||
*/
|
||||
const std::vector<CacheBlk*> getPossibleLocations(Addr addr)
|
||||
const std::vector<CacheBlk*> getPossibleLocations(Addr addr) const
|
||||
{
|
||||
return sets[extractSet(addr)].blks;
|
||||
}
|
||||
|
||||
10
src/mem/cache/tags/fa_lru.cc
vendored
10
src/mem/cache/tags/fa_lru.cc
vendored
@@ -193,9 +193,15 @@ FALRU::findBlockBySetAndWay(int set, int way) const
|
||||
}
|
||||
|
||||
CacheBlk*
|
||||
FALRU::findVictim(Addr addr)
|
||||
FALRU::findVictim(Addr addr, std::vector<CacheBlk*>& evict_blks) const
|
||||
{
|
||||
return tail;
|
||||
// The victim is always stored on the tail for the FALRU
|
||||
FALRUBlk* victim = tail;
|
||||
|
||||
// There is only one eviction for this replacement
|
||||
evict_blks.push_back(victim);
|
||||
|
||||
return victim;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
7
src/mem/cache/tags/fa_lru.hh
vendored
7
src/mem/cache/tags/fa_lru.hh
vendored
@@ -195,12 +195,15 @@ class FALRU : public BaseTags
|
||||
ReplaceableEntry* findBlockBySetAndWay(int set, int way) const override;
|
||||
|
||||
/**
|
||||
* Find replacement victim based on address.
|
||||
* Find replacement victim based on address. The list of evicted blocks
|
||||
* only contains the victim.
|
||||
*
|
||||
* @param addr Address to find a victim for.
|
||||
* @param evict_blks Cache blocks to be evicted.
|
||||
* @return Cache block to be replaced.
|
||||
*/
|
||||
CacheBlk* findVictim(Addr addr) override;
|
||||
CacheBlk* findVictim(Addr addr, std::vector<CacheBlk*>& evict_blks) const
|
||||
override;
|
||||
|
||||
/**
|
||||
* Insert the new block into the cache and update replacement data.
|
||||
|
||||
Reference in New Issue
Block a user