Daniel Carvalho has uploaded this change for review. ( https://gem5-review.googlesource.com/10142

Change subject: mem-cache: Return evictions along with victims
......................................................................

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
---
M src/mem/cache/cache.cc
M src/mem/cache/tags/base.hh
M src/mem/cache/tags/base_set_assoc.hh
M src/mem/cache/tags/fa_lru.cc
M src/mem/cache/tags/fa_lru.hh
5 files changed, 57 insertions(+), 23 deletions(-)



diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc
index d54dd5c..1b60113 100644
--- a/src/mem/cache/cache.cc
+++ b/src/mem/cache/cache.cc
@@ -1810,32 +1810,44 @@
 Cache::allocateBlock(Addr addr, bool is_secure, PacketList &writebacks)
 {
     // Find replacement victim
-    CacheBlk *blk = tags->findVictim(addr);
+    std::vector<CacheBlk*> evictBlks;
+    CacheBlk *victim = tags->findVictim(addr, evictBlks);

     // It is valid to return nullptr if there is no victim
-    if (!blk)
+    if (!victim)
         return nullptr;

-    if (blk->isValid()) {
-        Addr repl_addr = tags->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 {
+    // Check for transient state allocations
+    for (const auto& blk : evictBlks) {
+        if (blk->isValid()) {
+            Addr repl_addr = tags->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;
+            }
+        }
+    }
+
+    // Evict valid blocks associated to this victim block
+    for (const auto& blk : evictBlks) {
+        if (blk->isValid()) {
             DPRINTF(Cache, "replacement: replacing %#llx (%s) with %#llx "
-                    "(%s): %s\n", repl_addr, blk->isSecure() ? "s" : "ns",
+                    "(%s): %s\n", tags->regenerateBlkAddr(blk),
+                    blk->isSecure() ? "s" : "ns",
                     addr, is_secure ? "s" : "ns",
                     blk->isDirty() ? "writeback" : "clean");

             if (blk->wasPrefetched()) {
                 unusedPrefetches++;
             }
+
             // Will send up Writeback/CleanEvict snoops via isCachedAbove
             // when pushing this writeback list into the write buffer.
             if (blk->isDirty() || writebackClean) {
@@ -1844,10 +1856,19 @@
             } else {
                 writebacks.push_back(cleanEvictBlk(blk));
             }
+
+ // A successful block allocation is followed by an insertion to the + // victim block. If multiple blocks are evicted, that means that
+            // we are evicting all blocks co-associated to this victim, and
+            // they should be invalidated after writeback/evict
+            if (blk != victim) {
+                tags->invalidate(blk);
+                blk->invalidate();
+            }
         }
     }

-    return blk;
+    return victim;
 }

 void
diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh
index 29b9606..b733bda 100644
--- a/src/mem/cache/tags/base.hh
+++ b/src/mem/cache/tags/base.hh
@@ -249,9 +249,11 @@
      * Find replacement victim based on address.
      *
      * @param addr Address to find a victim for.
+     * @param evictBlks 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*>& evictBlks) + const = 0;

virtual CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) = 0;

diff --git a/src/mem/cache/tags/base_set_assoc.hh b/src/mem/cache/tags/base_set_assoc.hh
index ad04f0b..bf1dff8 100644
--- a/src/mem/cache/tags/base_set_assoc.hh
+++ b/src/mem/cache/tags/base_set_assoc.hh
@@ -183,14 +183,18 @@
      * Find replacement victim based on address.
      *
      * @param addr Address to find a victim for.
+     * @param evictBlks Cache blocks to be evicted.
      * @return Cache block to be replaced.
      */
-    CacheBlk* findVictim(Addr addr) override
+ CacheBlk* findVictim(Addr addr, std::vector<CacheBlk*>& evictBlks) const
     {
         // Choose replacement victim from replacement candidates
         CacheBlk* victim = replacementPolicy->getVictim(
                                getPossibleLocations(addr));

+        // There is only one eviction for this replacement
+        evictBlks.push_back(victim);
+
DPRINTF(CacheRepl, "set %x, way %x: selecting blk for replacement\n",
             victim->set, victim->way);

@@ -206,7 +210,7 @@
      * @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;
     }
diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc
index 2a1c9b9..055c2aa 100644
--- a/src/mem/cache/tags/fa_lru.cc
+++ b/src/mem/cache/tags/fa_lru.cc
@@ -190,9 +190,15 @@
 }

 CacheBlk*
-FALRU::findVictim(Addr addr)
+FALRU::findVictim(Addr addr, std::vector<CacheBlk*>& evictBlks) 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
+    evictBlks.push_back(victim);
+
+    return victim;
 }

 void
diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh
index 98369df..cf6863f 100644
--- a/src/mem/cache/tags/fa_lru.hh
+++ b/src/mem/cache/tags/fa_lru.hh
@@ -184,10 +184,11 @@
      * Find replacement victim based on address.
      *
      * @param addr Address to find a victim for.
+     * @param evictBlks Cache blocks to be evicted.
      * @return Cache block to be replaced.
      */
-    CacheBlk* findVictim(Addr addr) override;
-
+ CacheBlk* findVictim(Addr addr, std::vector<CacheBlk*>& evictBlks) const + override;
     /**
      * Insert the new block into the cache and update replacement data.
      *

--
To view, visit https://gem5-review.googlesource.com/10142
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I77bedf69637cf899fef4d9432eb6da8529ea398b
Gerrit-Change-Number: 10142
Gerrit-PatchSet: 1
Gerrit-Owner: Daniel Carvalho <oda...@yahoo.com.br>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to