Nikos Nikoleris has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/12904
Change subject: mem: Determine if an MSHR does a whole-line write
......................................................................
mem: Determine if an MSHR does a whole-line write
This patch adds support for determining whether the targets in an MSHR
are 1) only writes and 2) whether these writes are effectively a
whole-line write. This patch adds the necessary functions in the MSHR
to allow for write coalescing in the cache.
Change-Id: I2c9a9a83d2d9b506a491ba5b0b9ac1054bdb31b4
---
M src/mem/cache/mshr.cc
M src/mem/cache/mshr.hh
2 files changed, 103 insertions(+), 6 deletions(-)
diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc
index ccaec7b..5b93029 100644
--- a/src/mem/cache/mshr.cc
+++ b/src/mem/cache/mshr.cc
@@ -40,6 +40,7 @@
*
* Authors: Erik Hallnor
* Dave Greene
+ * Nikos Nikoleris
*/
/**
@@ -63,7 +64,7 @@
MSHR::MSHR() : downstreamPending(false),
pendingModified(false),
postInvalidate(false), postDowngrade(false),
- isForward(false)
+ wasWholeLineWrite(false), isForward(false)
{
}
@@ -95,6 +96,8 @@
if (source != Target::FromPrefetcher) {
hasFromCache = hasFromCache || pkt->fromCache();
+
+ updateWriteFlags(pkt);
}
}
}
@@ -257,16 +260,19 @@
order = _order;
assert(target);
isForward = false;
+ wasWholeLineWrite = false;
_isUncacheable = target->req->isUncacheable();
inService = false;
downstreamPending = false;
- assert(targets.isReset());
+
+ targets.init(blkAddr, blkSize);
+ deferredTargets.init(blkAddr, blkSize);
+
// Don't know of a case where we would allocate a new MSHR for a
// snoop (mem-side request), so set source according to request here
Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
Target::FromPrefetcher : Target::FromCPU;
targets.add(target, when_ready, _order, source, true, alloc_on_fill);
- assert(deferredTargets.isReset());
}
@@ -294,6 +300,10 @@
// level where it's going to get a response
targets.clearDownstreamPending();
}
+ // if the line is not considered a whole-line write when sent
+ // downstream, make sure it is also not considered a whole-line
+ // write when receiving the response, and vice versa
+ wasWholeLineWrite = isWholeLineWrite();
}
@@ -480,6 +490,7 @@
MSHR::extractServiceableTargets(PacketPtr pkt)
{
TargetList ready_targets;
+ ready_targets.init(blkAddr, blkSize);
// If the downstream MSHR got an invalidation request then we only
// service the first of the FromCPU targets and any other
// non-FromCPU target. This way the remaining FromCPU targets
diff --git a/src/mem/cache/mshr.hh b/src/mem/cache/mshr.hh
index 218de924..5c19290 100644
--- a/src/mem/cache/mshr.hh
+++ b/src/mem/cache/mshr.hh
@@ -38,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Erik Hallnor
+ * Nikos Nikoleris
*/
/**
@@ -57,6 +58,7 @@
#include "base/types.hh"
#include "mem/cache/queue_entry.hh"
#include "mem/packet.hh"
+#include "mem/request.hh"
#include "sim/core.hh"
class BaseCache;
@@ -115,6 +117,9 @@
public:
+ /** Track if we sent this as a whole line write or not */
+ bool wasWholeLineWrite;
+
/** True if the entry is just a simple forward from an upper level */
bool isForward;
@@ -187,7 +192,23 @@
void updateFlags(PacketPtr pkt, Target::Source source,
bool alloc_on_fill);
+ /**
+ * Reset state
+ *
+ * @param blk_addr Address of the cache block
+ * @param blk_size Size of the cache block
+ */
+ void init(Addr blk_addr, Addr blk_size) {
+ blkAddr = blk_addr;
+ blkSize = blk_size;
+
+ resetFlags();
+ }
+
void resetFlags() {
+ onlyWrites = true;
+ endOfWrites = blkAddr;
+
needsWritable = false;
hasUpgrade = false;
allocOnFill = false;
@@ -203,12 +224,43 @@
void populateFlags();
/**
+ * Add the specified packet in the TargetList. This function
+ * stores information related to the added packet and updates
+ * accordingly the flags.
+ *
+ * @param pkt Packet considered for adding
+ */
+ void updateWriteFlags(PacketPtr pkt) {
+ const Request::FlagsType noMergeFlags =
+ Request::UNCACHEABLE |
+ Request::STRICT_ORDER | Request::MMAPPED_IPR |
+ Request::PRIVILEGED | Request::LLSC |
+ Request::MEM_SWAP | Request::MEM_SWAP_COND |
+ Request::SECURE;
+
+ bool can_merge_write = pkt->isWrite() &&
+ ((pkt->req->getFlags() & noMergeFlags) == 0);
+
+ // if we have already seen writes for the full block stop
+ // here, this might be a full line write followed by
+ // other compatible requests (e.g., reads)
+ if (endOfWrites != (blkAddr + blkSize)) {
+ onlyWrites &= can_merge_write;
+ if (onlyWrites && (endOfWrites == pkt->getAddr())) {
+ endOfWrites += pkt->getSize();
+ }
+ }
+ }
+
+ /**
* Tests if the flags of this TargetList have their default
* values.
+ *
+ * @param blk_addr Address of the cache block
*/
bool isReset() const {
return !needsWritable && !hasUpgrade && !allocOnFill &&
- !hasFromCache;
+ !hasFromCache && onlyWrites && endOfWrites == blkAddr;
}
/**
@@ -224,8 +276,7 @@
* @param alloc_on_fill Whether it should allocate on a fill
*/
void add(PacketPtr pkt, Tick readyTime, Counter order,
- Target::Source source, bool markPending,
- bool alloc_on_fill);
+ Target::Source source, bool markPending, bool
alloc_on_fill);
/**
* Convert upgrades to the equivalent request if the cache line
they
@@ -238,6 +289,31 @@
bool trySatisfyFunctional(PacketPtr pkt);
void print(std::ostream &os, int verbosity,
const std::string &prefix) const;
+
+ /**
+ * Check if this list contains only compatible writes, and if they
+ * span the entire cache line. This is used as part of the
+ * miss-packet creation. Note that new requests may arrive after a
+ * miss-packet has been created, and for the fill we therefore use
+ * the wasWholeLineWrite field.
+ */
+ bool isWholeLineWrite() const
+ {
+ return onlyWrites && (endOfWrites == (blkAddr + blkSize));
+ }
+
+ private:
+ /** Address of the cache block for this list of targets. */
+ Addr blkAddr;
+
+ /** Size of the cache block. */
+ Addr blkSize;
+
+ /** Are we only dealing with writes. */
+ bool onlyWrites;
+
+ /** Track what bytes are written for possible write merging. */
+ Addr endOfWrites;
};
/** A list of MSHRs. */
@@ -315,6 +391,16 @@
TargetList deferredTargets;
public:
+ /**
+ * Check if this MSHR contains only compatible writes, and if they
+ * span the entire cache line. This is used as part of the
+ * miss-packet creation. Note that new requests may arrive after a
+ * miss-packet has been created, and for the fill we therefore use
+ * the wasWholeLineWrite field.
+ */
+ bool isWholeLineWrite() const {
+ return targets.isWholeLineWrite();
+ }
/**
* Allocate a miss to this MSHR.
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/12904
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: I2c9a9a83d2d9b506a491ba5b0b9ac1054bdb31b4
Gerrit-Change-Number: 12904
Gerrit-PatchSet: 1
Gerrit-Owner: Nikos Nikoleris <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev