diff -r 66fdc1c6f94f -r 9be908d7c501 configs/common/Caches.py --- a/configs/common/Caches.py Mon Jun 29 10:37:50 2015 +0100 +++ b/configs/common/Caches.py Mon Jun 29 10:43:33 2015 +0100 @@ -52,7 +52,6 @@ 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 @@ size = '1kB' tgts_per_mshr = 12 forward_snoops = False - is_top_level = True class PageTableWalkerCache(BaseCache): assoc = 2 @@ -86,7 +84,6 @@ 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 diff -r 66fdc1c6f94f -r 9be908d7c501 configs/common/O3_ARM_v7a.py --- a/configs/common/O3_ARM_v7a.py Mon Jun 29 10:37:50 2015 +0100 +++ b/configs/common/O3_ARM_v7a.py Mon Jun 29 10:43:33 2015 +0100 @@ -149,7 +149,6 @@ tgts_per_mshr = 8 size = '32kB' assoc = 2 - is_top_level = True forward_snoops = False is_read_only = True @@ -162,7 +161,6 @@ size = '32kB' assoc = 2 write_buffers = 16 - is_top_level = True # TLB Cache # Use a cache as a L2 TLB @@ -174,7 +172,6 @@ size = '1kB' assoc = 8 write_buffers = 16 - is_top_level = True forward_snoops = False is_read_only = True diff -r 66fdc1c6f94f -r 9be908d7c501 configs/example/memcheck.py --- a/configs/example/memcheck.py Mon Jun 29 10:37:50 2015 +0100 +++ b/configs/example/memcheck.py Mon Jun 29 10:43:33 2015 +0100 @@ -154,7 +154,7 @@ # 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 @@ 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 diff -r 66fdc1c6f94f -r 9be908d7c501 configs/example/memtest.py --- a/configs/example/memtest.py Mon Jun 29 10:37:50 2015 +0100 +++ b/configs/example/memtest.py Mon Jun 29 10:43:33 2015 +0100 @@ -177,7 +177,7 @@ # 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 @@ 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 diff -r 66fdc1c6f94f -r 9be908d7c501 src/mem/cache/BaseCache.py --- a/src/mem/cache/BaseCache.py Mon Jun 29 10:37:50 2015 +0100 +++ b/src/mem/cache/BaseCache.py Mon Jun 29 10:43:33 2015 +0100 @@ -64,7 +64,6 @@ 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") diff -r 66fdc1c6f94f -r 9be908d7c501 src/mem/cache/base.hh --- a/src/mem/cache/base.hh Mon Jun 29 10:37:50 2015 +0100 +++ b/src/mem/cache/base.hh Mon Jun 29 10:43:33 2015 +0100 @@ -304,11 +304,6 @@ /** 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 diff -r 66fdc1c6f94f -r 9be908d7c501 src/mem/cache/base.cc --- a/src/mem/cache/base.cc Mon Jun 29 10:37:50 2015 +0100 +++ b/src/mem/cache/base.cc Mon Jun 29 10:43:33 2015 +0100 @@ -78,7 +78,6 @@ 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), diff -r 66fdc1c6f94f -r 9be908d7c501 src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Mon Jun 29 10:37:50 2015 +0100 +++ b/src/mem/cache/cache_impl.hh Mon Jun 29 10:43:33 2015 +0100 @@ -179,7 +179,15 @@ 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 @@ 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 @@ (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 @@ // 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 @@ // 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 @@ pkt->makeAtomicResponse(); pkt->copyError(bus_pkt); } else if (pkt->cmd == MemCmd::InvalidateReq) { - assert(!isTopLevel); if (blk) { // write invalidate response to a cache that received // an write invalidate request satisfyCpuSideRequest(pkt, blk); } } else if (pkt->cmd == MemCmd::WriteLineReq) { - // write invalidate response to the cache that - // received the original write - assert(isTopLevel); - // note the use of pkt, not bus_pkt here. // write invalidate to the cache that promoted @@ -1256,7 +1257,7 @@ 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 @@ 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