summaryrefslogtreecommitdiff
path: root/src/mem/packet.hh
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-12-31 09:32:58 -0500
committerAndreas Hansson <andreas.hansson@arm.com>2015-12-31 09:32:58 -0500
commit0fcb376e5fc6bc0a7b16dc4595d4a7e3f910cbc8 (patch)
tree4be665e3596d9d4e193e6354c5577ee0077732da /src/mem/packet.hh
parenta3177645773b8eb4b835050c395554d3e2b4664a (diff)
downloadgem5-0fcb376e5fc6bc0a7b16dc4595d4a7e3f910cbc8.tar.xz
mem: Make cache terminology easier to understand
This patch changes the name of a bunch of packet flags and MSHR member functions and variables to make the coherency protocol easier to understand. In addition the patch adds and updates lots of descriptions, explicitly spelling out assumptions. The following name changes are made: * the packet memInhibit flag is renamed to cacheResponding * the packet sharedAsserted flag is renamed to hasSharers * the packet NeedsExclusive attribute is renamed to NeedsWritable * the packet isSupplyExclusive is renamed responderHadWritable * the MSHR pendingDirty is renamed to pendingModified The cache states, Modified, Owned, Exclusive, Shared are also called out in the cache and MSHR code to make it easier to understand.
Diffstat (limited to 'src/mem/packet.hh')
-rw-r--r--src/mem/packet.hh123
1 files changed, 101 insertions, 22 deletions
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index 12295555d..4614799bf 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -139,7 +139,7 @@ class MemCmd
IsWrite, //!< Data flows from requester to responder
IsUpgrade,
IsInvalidate,
- NeedsExclusive, //!< Requires exclusive copy to complete in-cache
+ NeedsWritable, //!< Requires writable copy to complete in-cache
IsRequest, //!< Issued by requester
IsResponse, //!< Issue by responder
NeedsResponse, //!< Requester needs response from target
@@ -189,7 +189,7 @@ class MemCmd
bool isUpgrade() const { return testCmdAttrib(IsUpgrade); }
bool isRequest() const { return testCmdAttrib(IsRequest); }
bool isResponse() const { return testCmdAttrib(IsResponse); }
- bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
+ bool needsWritable() const { return testCmdAttrib(NeedsWritable); }
bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
bool isEviction() const { return testCmdAttrib(IsEviction); }
@@ -252,15 +252,22 @@ class Packet : public Printable
// Flags to transfer across when copying a packet
COPY_FLAGS = 0x0000000F,
- SHARED = 0x00000001,
+ // Does this packet have sharers (which means it should not be
+ // considered writable) or not. See setHasSharers below.
+ HAS_SHARERS = 0x00000001,
+
// Special control flags
/// Special timing-mode atomic snoop for multi-level coherence.
EXPRESS_SNOOP = 0x00000002,
- /// Does supplier have exclusive copy?
- /// Useful for multi-level coherence.
- SUPPLY_EXCLUSIVE = 0x00000004,
- // Snoop response flags
- MEM_INHIBIT = 0x00000008,
+
+ /// Allow a responding cache to inform the cache hierarchy
+ /// that it had a writable copy before responding. See
+ /// setResponderHadWritable below.
+ RESPONDER_HAD_WRITABLE = 0x00000004,
+
+ // Snoop co-ordination flag to indicate that a cache is
+ // responding to a snoop. See setCacheResponding below.
+ CACHE_RESPONDING = 0x00000008,
/// Are the 'addr' and 'size' fields valid?
VALID_ADDR = 0x00000100,
@@ -495,7 +502,7 @@ class Packet : public Printable
bool isUpgrade() const { return cmd.isUpgrade(); }
bool isRequest() const { return cmd.isRequest(); }
bool isResponse() const { return cmd.isResponse(); }
- bool needsExclusive() const { return cmd.needsExclusive(); }
+ bool needsWritable() const { return cmd.needsWritable(); }
bool needsResponse() const { return cmd.needsResponse(); }
bool isInvalidate() const { return cmd.isInvalidate(); }
bool isEviction() const { return cmd.isEviction(); }
@@ -506,22 +513,94 @@ class Packet : public Printable
bool isPrint() const { return cmd.isPrint(); }
bool isFlush() const { return cmd.isFlush(); }
- // Snoop flags
- void assertMemInhibit()
+ //@{
+ /// Snoop flags
+ /**
+ * Set the cacheResponding flag. This is used by the caches to
+ * signal another cache that they are responding to a request. A
+ * cache will only respond to snoops if it has the line in either
+ * Modified or Owned state. Note that on snoop hits we always pass
+ * the line as Modified and never Owned. In the case of an Owned
+ * line we proceed to invalidate all other copies.
+ *
+ * On a cache fill (see Cache::handleFill), we check hasSharers
+ * first, ignoring the cacheResponding flag if hasSharers is set.
+ * A line is consequently allocated as:
+ *
+ * hasSharers cacheResponding state
+ * true false Shared
+ * true true Shared
+ * false false Exclusive
+ * false true Modified
+ */
+ void setCacheResponding()
{
assert(isRequest());
- assert(!flags.isSet(MEM_INHIBIT));
- flags.set(MEM_INHIBIT);
+ assert(!flags.isSet(CACHE_RESPONDING));
+ flags.set(CACHE_RESPONDING);
}
- bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
- void assertShared() { flags.set(SHARED); }
- bool sharedAsserted() const { return flags.isSet(SHARED); }
-
- // Special control flags
- void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
- bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
- void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
- bool isSupplyExclusive() const { return flags.isSet(SUPPLY_EXCLUSIVE); }
+ bool cacheResponding() const { return flags.isSet(CACHE_RESPONDING); }
+ /**
+ * On fills, the hasSharers flag is used by the caches in
+ * combination with the cacheResponding flag, as clarified
+ * above. If the hasSharers flag is not set, the packet is passing
+ * writable. Thus, a response from a memory passes the line as
+ * writable by default.
+ *
+ * The hasSharers flag is also used by upstream caches to inform a
+ * downstream cache that they have the block (by calling
+ * setHasSharers on snoop request packets that hit in upstream
+ * cachs tags or MSHRs). If the snoop packet has sharers, a
+ * downstream cache is prevented from passing a dirty line upwards
+ * if it was not explicitly asked for a writable copy. See
+ * Cache::satisfyCpuSideRequest.
+ *
+ * The hasSharers flag is also used on writebacks, in
+ * combination with the WritbackClean or WritebackDirty commands,
+ * to allocate the block downstream either as:
+ *
+ * command hasSharers state
+ * WritebackDirty false Modified
+ * WritebackDirty true Owned
+ * WritebackClean false Exclusive
+ * WritebackClean true Shared
+ */
+ void setHasSharers() { flags.set(HAS_SHARERS); }
+ bool hasSharers() const { return flags.isSet(HAS_SHARERS); }
+ //@}
+
+ /**
+ * The express snoop flag is used for two purposes. Firstly, it is
+ * used to bypass flow control for normal (non-snoop) requests
+ * going downstream in the memory system. In cases where a cache
+ * is responding to a snoop from another cache (it had a dirty
+ * line), but the line is not writable (and there are possibly
+ * other copies), the express snoop flag is set by the downstream
+ * cache to invalidate all other copies in zero time. Secondly,
+ * the express snoop flag is also set to be able to distinguish
+ * snoop packets that came from a downstream cache, rather than
+ * snoop packets from neighbouring caches.
+ */
+ void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
+ bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
+
+ /**
+ * On responding to a snoop request (which only happens for
+ * Modified or Owned lines), make sure that we can transform an
+ * Owned response to a Modified one. If this flag is not set, the
+ * responding cache had the line in the Owned state, and there are
+ * possibly other Shared copies in the memory system. A downstream
+ * cache helps in orchestrating the invalidation of these copies
+ * by sending out the appropriate express snoops.
+ */
+ void setResponderHadWritable()
+ {
+ assert(cacheResponding());
+ flags.set(RESPONDER_HAD_WRITABLE);
+ }
+ bool responderHadWritable() const
+ { return flags.isSet(RESPONDER_HAD_WRITABLE); }
+
void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); }
void setBlockCached() { flags.set(BLOCK_CACHED); }