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
}
/**
- * 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;
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);
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);
* @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;
}
}
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
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.