summaryrefslogtreecommitdiff
path: root/src/mem/cache/cache.hh
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-11-06 03:26:41 -0500
committerAndreas Hansson <andreas.hansson@arm.com>2015-11-06 03:26:41 -0500
commit654266f39cd67055d6176d22a46c7d678f6340c4 (patch)
tree250cf876eca7a4370ecc3a3e3fa6d9ba695f2830 /src/mem/cache/cache.hh
parentf02a9338c1efaf7680f598a57ff6607e9b11120e (diff)
downloadgem5-654266f39cd67055d6176d22a46c7d678f6340c4.tar.xz
mem: Add cache clusivity
This patch adds a parameter to control the cache clusivity, that is if the cache is mostly inclusive or exclusive. At the moment there is no intention to support strict policies, and thus the options are: 1) mostly inclusive, or 2) mostly exclusive. The choice of policy guides the behaviuor on a cache fill, and a new helper function, allocOnFill, is created to encapsulate the decision making process. For the timing mode, the decision is annotated on the MSHR on sending out the downstream packet, and in atomic we directly pass the decision to handleFill. We (ab)use the tempBlock in cases where we are not allocating on fill, leaving the rest of the cache unaffected. Simple and effective. This patch also makes it more explicit that multiple caches are allowed to consider a block writable (this is the case also before this patch). That is, for a mostly inclusive cache, multiple caches upstream may also consider the block exclusive. The caches considering the block writable/exclusive all appear along the same path to memory, and from a coherency protocol point of view it works due to the fact that we always snoop upwards in zero time before querying any downstream cache. Note that this patch does not introduce clean writebacks. Thus, for clean lines we are essentially removing a cache level if it is made mostly exclusive. For example, lines from the read-only L1 instruction cache or table-walker cache are always clean, and simply get dropped rather than being passed to the L2. If the L2 is mostly exclusive and does not allocate on fill it will thus never hold the line. A follow on patch adds the clean writebacks. The patch changes the L2 of the O3_ARM_v7a CPU configuration to be mostly exclusive (and stats are affected accordingly).
Diffstat (limited to 'src/mem/cache/cache.hh')
-rw-r--r--src/mem/cache/cache.hh71
1 files changed, 69 insertions, 2 deletions
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index ae9e7e694..6da837003 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 ARM Limited
+ * Copyright (c) 2012-2015 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -53,6 +53,7 @@
#define __MEM_CACHE_CACHE_HH__
#include "base/misc.hh" // fatal, panic, and warn
+#include "enums/Clusivity.hh"
#include "mem/cache/base.hh"
#include "mem/cache/blk.hh"
#include "mem/cache/mshr.hh"
@@ -194,6 +195,13 @@ class Cache : public BaseCache
*/
const bool prefetchOnAccess;
+ /**
+ * Clusivity with respect to the upstream cache, determining if we
+ * fill into both this cache and the cache above on a miss. Note
+ * that we currently do not support strict clusivity policies.
+ */
+ const Enums::Clusivity clusivity;
+
/**
* Upstream caches need this packet until true is returned, so
* hold it for deletion until a subsequent call
@@ -201,6 +209,35 @@ class Cache : public BaseCache
std::unique_ptr<Packet> pendingDelete;
/**
+ * Writebacks from the tempBlock, resulting on the response path
+ * in atomic mode, must happen after the call to recvAtomic has
+ * finished (for the right ordering of the packets). We therefore
+ * need to hold on to the packets, and have a method and an event
+ * to send them.
+ */
+ PacketPtr tempBlockWriteback;
+
+ /**
+ * Send the outstanding tempBlock writeback. To be called after
+ * recvAtomic finishes in cases where the block we filled is in
+ * fact the tempBlock, and now needs to be written back.
+ */
+ void writebackTempBlockAtomic() {
+ assert(tempBlockWriteback != nullptr);
+ PacketList writebacks{tempBlockWriteback};
+ doWritebacksAtomic(writebacks);
+ tempBlockWriteback = nullptr;
+ }
+
+ /**
+ * An event to writeback the tempBlock after recvAtomic
+ * finishes. To avoid other calls to recvAtomic getting in
+ * between, we create this event with a higher priority.
+ */
+ EventWrapper<Cache, &Cache::writebackTempBlockAtomic> \
+ writebackTempBlockAtomicEvent;
+
+ /**
* Does all the processing necessary to perform the provided request.
* @param pkt The memory request to perform.
* @param blk The cache block to be updated.
@@ -226,17 +263,47 @@ class Cache : public BaseCache
CacheBlk *allocateBlock(Addr addr, bool is_secure, PacketList &writebacks);
/**
+ * Invalidate a cache block.
+ *
+ * @param blk Block to invalidate
+ */
+ void invalidateBlock(CacheBlk *blk);
+
+ /**
* Populates a cache block and handles all outstanding requests for the
* satisfied fill request. This version takes two memory requests. One
* contains the fill data, the other is an optional target to satisfy.
* @param pkt The memory request with the fill data.
* @param blk The cache block if it already exists.
* @param writebacks List for any writebacks that need to be performed.
+ * @param allocate Whether to allocate a block or use the temp block
* @return Pointer to the new cache block.
*/
CacheBlk *handleFill(PacketPtr pkt, CacheBlk *blk,
- PacketList &writebacks);
+ PacketList &writebacks, bool allocate);
+ /**
+ * Determine whether we should allocate on a fill or not. If this
+ * cache is mostly inclusive with regards to the upstream cache(s)
+ * we always allocate (for any non-forwarded and cacheable
+ * requests). In the case of a mostly exclusive cache, we allocate
+ * on fill if the packet did not come from a cache, thus if we:
+ * are dealing with a whole-line write (the latter behaves much
+ * like a writeback), the original target packet came from a
+ * non-caching source, or if we are performing a prefetch or LLSC.
+ *
+ * @param cmd Command of the incoming requesting packet
+ * @return Whether we should allocate on the fill
+ */
+ inline bool allocOnFill(MemCmd cmd) const
+ {
+ return clusivity == Enums::mostly_incl ||
+ cmd == MemCmd::WriteLineReq ||
+ cmd == MemCmd::ReadReq ||
+ cmd == MemCmd::WriteReq ||
+ cmd.isPrefetch() ||
+ cmd.isLLSC();
+ }
/**
* Performs the access specified by the request.