mem: Remove redundant is_top_level cache parameter
authorAndreas Hansson <andreas.hansson@arm.com>
Fri, 3 Jul 2015 14:14:43 +0000 (10:14 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Fri, 3 Jul 2015 14:14:43 +0000 (10:14 -0400)
This patch takes the final step in removing the is_top_level parameter
from the cache. With the recent changes to read requests and write
invalidations, the parameter is no longer needed, and consequently
removed.

This also means that asymmetric cache hierarchies are now fully
supported (and we are actually using them already with L1 caches, but
no table-walker caches, connected to a shared L2).

configs/common/Caches.py
configs/common/O3_ARM_v7a.py
configs/example/memcheck.py
configs/example/memtest.py
src/mem/cache/BaseCache.py
src/mem/cache/base.cc
src/mem/cache/base.hh
src/mem/cache/cache_impl.hh

index 2bdffc6c773aaa668fdf7c1d0b25f08566bc192b..cfb873b5edb564278cf40ec5591019df881c5463 100644 (file)
@@ -52,7 +52,6 @@ class L1Cache(BaseCache):
     response_latency = 2
     mshrs = 4
     tgts_per_mshr = 20
-    is_top_level = True
 
 class L1_ICache(L1Cache):
     is_read_only = True
@@ -76,7 +75,6 @@ class IOCache(BaseCache):
     size = '1kB'
     tgts_per_mshr = 12
     forward_snoops = False
-    is_top_level = True
 
 class PageTableWalkerCache(BaseCache):
     assoc = 2
@@ -86,7 +84,6 @@ class PageTableWalkerCache(BaseCache):
     size = '1kB'
     tgts_per_mshr = 12
     forward_snoops = False
-    is_top_level = True
     # the x86 table walker actually writes to the table-walker cache
     if buildEnv['TARGET_ISA'] == 'x86':
         is_read_only = False
index b4b66df9c84ec4df32e9dfb00741a785edb9b796..dbfdf6c4112d0fcaf28ff79ce96c6b3ca72a00a2 100644 (file)
@@ -149,7 +149,6 @@ class O3_ARM_v7a_ICache(BaseCache):
     tgts_per_mshr = 8
     size = '32kB'
     assoc = 2
-    is_top_level = True
     forward_snoops = False
     is_read_only = True
 
@@ -162,7 +161,6 @@ class O3_ARM_v7a_DCache(BaseCache):
     size = '32kB'
     assoc = 2
     write_buffers = 16
-    is_top_level = True
 
 # TLB Cache
 # Use a cache as a L2 TLB
@@ -174,7 +172,6 @@ class O3_ARM_v7aWalkCache(BaseCache):
     size = '1kB'
     assoc = 8
     write_buffers = 16
-    is_top_level = True
     forward_snoops = False
     is_read_only = True
 
index f0bc26e32044243ca4255cb450e988a983506726..ca2659ed0960218ccd2f5fc123765dd28011a58f 100644 (file)
@@ -154,7 +154,7 @@ for t, m in zip(testerspec, multiplier):
 # Define a prototype L1 cache that we scale for all successive levels
 proto_l1 = BaseCache(size = '32kB', assoc = 4,
                      hit_latency = 1, response_latency = 1,
-                     tgts_per_mshr = 8, is_top_level = True)
+                     tgts_per_mshr = 8)
 
 if options.blocking:
      proto_l1.mshrs = 1
@@ -179,7 +179,6 @@ for scale in cachespec[:-1]:
      next.response_latency = prev.response_latency * 10
      next.assoc = prev.assoc * scale
      next.mshrs = prev.mshrs * scale
-     next.is_top_level = False
      cache_proto.insert(0, next)
 
 # Create a config to be used by all the traffic generators
index 0df9f766f3fb176643385bb33c0d4e1432ee0c3f..a51bd27964cbc13827ece921a86c7033d9bf138a 100644 (file)
@@ -177,7 +177,7 @@ else:
 # Define a prototype L1 cache that we scale for all successive levels
 proto_l1 = BaseCache(size = '32kB', assoc = 4,
                      hit_latency = 1, response_latency = 1,
-                     tgts_per_mshr = 8, is_top_level = True)
+                     tgts_per_mshr = 8)
 
 if options.blocking:
      proto_l1.mshrs = 1
@@ -197,7 +197,6 @@ for scale in cachespec[:-1]:
      next.response_latency = prev.response_latency * 10
      next.assoc = prev.assoc * scale
      next.mshrs = prev.mshrs * scale
-     next.is_top_level = False
      cache_proto.insert(0, next)
 
 # Make a prototype for the tester to be used throughout
index 4d67664561e6c3247c48cb51d93d42e5dda95511..d908430e5189a7ad9be0187503e4d25a21c38a9a 100644 (file)
@@ -64,7 +64,6 @@ class BaseCache(MemObject):
 
     forward_snoops = Param.Bool(True,
         "Forward snoops from mem side to cpu side")
-    is_top_level = Param.Bool(False, "Is this cache at the top level (e.g. L1)")
     is_read_only = Param.Bool(False, "Is this cache read only (e.g. inst)")
 
     prefetcher = Param.BasePrefetcher(NULL,"Prefetcher attached to cache")
index b1c51207979efdcacf5e7e7204e6b1a167130c7f..1d0b9a3dd86bc30aed6a83d7742e8f3bc644c333 100644 (file)
@@ -78,7 +78,6 @@ BaseCache::BaseCache(const Params *p)
       responseLatency(p->response_latency),
       numTarget(p->tgts_per_mshr),
       forwardSnoops(p->forward_snoops),
-      isTopLevel(p->is_top_level),
       isReadOnly(p->is_read_only),
       blocked(0),
       order(0),
index d2cb11f339326a63e968e5bde39f4c29d45e4b74..6c87fad128f2b3aceafb97043ebcbfca590f1274 100644 (file)
@@ -304,11 +304,6 @@ class BaseCache : public MemObject
     /** Do we forward snoops from mem side port through to cpu side port? */
     const bool forwardSnoops;
 
-    /** Is this cache a toplevel cache (e.g. L1, I/O cache). If so we should
-     * never try to forward ownership and similar optimizations to the cpu
-     * side */
-    const bool isTopLevel;
-
     /**
      * Is this cache read only, for example the instruction cache, or
      * table-walker cache. A cache that is read only should never see
index 39206ca8443420b0d17e028d184adc317235e98b..9dec54f45a9e656c24267e20ae70c34e83ad9e7d 100644 (file)
@@ -179,7 +179,15 @@ Cache::satisfyCpuSideRequest(PacketPtr pkt, CacheBlk *blk,
             blk->trackLoadLocked(pkt);
         }
         pkt->setDataFromBlock(blk->data, blkSize);
-        if (pkt->getSize() == blkSize) {
+        // determine if this read is from a (coherent) cache, or not
+        // by looking at the command type; we could potentially add a
+        // packet attribute such as 'FromCache' to make this check a
+        // bit cleaner
+        if (pkt->cmd == MemCmd::ReadExReq ||
+            pkt->cmd == MemCmd::ReadSharedReq ||
+            pkt->cmd == MemCmd::ReadCleanReq ||
+            pkt->cmd == MemCmd::SCUpgradeFailReq) {
+            assert(pkt->getSize() == blkSize);
             // special handling for coherent block requests from
             // upper-level caches
             if (pkt->needsExclusive()) {
@@ -211,7 +219,7 @@ Cache::satisfyCpuSideRequest(PacketPtr pkt, CacheBlk *blk,
 
                 if (blk->isDirty()) {
                     // special considerations if we're owner:
-                    if (!deferred_response && !isTopLevel) {
+                    if (!deferred_response) {
                         // if we are responding immediately and can
                         // signal that we're transferring ownership
                         // along with exclusivity, do so
@@ -526,7 +534,6 @@ Cache::promoteWholeLineWrites(PacketPtr pkt)
         (pkt->getSize() == blkSize) && (pkt->getOffset(blkSize) == 0)) {
         pkt->cmd = MemCmd::WriteLineReq;
         DPRINTF(Cache, "packet promoted from Write to WriteLineReq\n");
-        assert(isTopLevel); // should only happen at L1 or I/O cache
     }
 }
 
@@ -696,7 +703,7 @@ Cache::recvTimingReq(PacketPtr pkt)
         // processing happens before any MSHR munging on the behalf of
         // this request because this new Request will be the one stored
         // into the MSHRs, not the original.
-        if (pkt->cmd.isSWPrefetch() && isTopLevel) {
+        if (pkt->cmd.isSWPrefetch()) {
             assert(needsResponse);
             assert(pkt->req->hasPaddr());
             assert(!pkt->req->isUncacheable());
@@ -905,7 +912,6 @@ Cache::getBusPacket(PacketPtr cpu_pkt, CacheBlk *blk,
         // the line in exclusive state, and invalidates all other
         // copies
         cmd = MemCmd::InvalidateReq;
-        assert(isTopLevel);
     } else {
         // block is invalid
         cmd = needsExclusive ? MemCmd::ReadExReq :
@@ -1034,17 +1040,12 @@ Cache::recvAtomic(PacketPtr pkt)
                     pkt->makeAtomicResponse();
                     pkt->copyError(bus_pkt);
                 } else if (pkt->cmd == MemCmd::InvalidateReq) {
-                    assert(!isTopLevel);
                     if (blk) {
                         // invalidate response to a cache that received
                         // an invalidate request
                         satisfyCpuSideRequest(pkt, blk);
                     }
                 } else if (pkt->cmd == MemCmd::WriteLineReq) {
-                    // invalidate response to the cache that
-                    // received the original write-line request
-                    assert(isTopLevel);
-
                     // note the use of pkt, not bus_pkt here.
 
                     // write-line request to the cache that promoted
@@ -1256,7 +1257,7 @@ Cache::recvTimingResp(PacketPtr pkt)
             completion_time = pkt->headerDelay;
 
             // Software prefetch handling for cache closest to core
-            if (tgt_pkt->cmd.isSWPrefetch() && isTopLevel) {
+            if (tgt_pkt->cmd.isSWPrefetch()) {
                 // a software prefetch would have already been ack'd immediately
                 // with dummy data so the core would be able to retire it.
                 // this request completes right here, so we deallocate it.
@@ -2148,7 +2149,7 @@ Cache::getNextMSHR()
 bool
 Cache::isCachedAbove(const PacketPtr pkt) const
 {
-    if (isTopLevel)
+    if (!forwardSnoops)
         return false;
     // Mirroring the flow of HardPFReqs, the cache sends CleanEvict and
     // Writeback snoops into upper level caches to check for copies of the