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
Reviewed-on: https://gem5-review.googlesource.com/c/12904
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
This commit is contained in:
Nikos Nikoleris
2016-10-10 14:25:42 +01:00
parent 6adc2afaa0
commit 0ac40753c3
2 changed files with 114 additions and 6 deletions

17
src/mem/cache/mshr.cc vendored
View File

@@ -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 @@ MSHR::TargetList::updateFlags(PacketPtr pkt, Target::Source source,
if (source != Target::FromPrefetcher) {
hasFromCache = hasFromCache || pkt->fromCache();
updateWriteFlags(pkt);
}
}
}
@@ -257,16 +260,19 @@ MSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
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 @@ MSHR::markInService(bool pending_modified_resp)
// 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::TargetList
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

103
src/mem/cache/mshr.hh vendored
View File

@@ -38,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Erik Hallnor
* Nikos Nikoleris
*/
/**
@@ -52,11 +53,13 @@
#include <iosfwd>
#include <list>
#include <string>
#include <vector>
#include "base/printable.hh"
#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 +118,9 @@ class MSHR : public QueueEntry, public Printable
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 +193,24 @@ class MSHR : public QueueEntry, public Printable
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;
writesBitmap.resize(blk_size);
resetFlags();
}
void resetFlags() {
onlyWrites = true;
std::fill(writesBitmap.begin(), writesBitmap.end(), false);
needsWritable = false;
hasUpgrade = false;
allocOnFill = false;
@@ -202,13 +225,45 @@ class MSHR : public QueueEntry, public Printable
*/
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;
// 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 (!isWholeLineWrite()) {
bool can_merge_write = pkt->isWrite() &&
((pkt->req->getFlags() & noMergeFlags) == 0);
onlyWrites &= can_merge_write;
if (onlyWrites) {
auto offset = pkt->getOffset(blkSize);
auto begin = writesBitmap.begin() + offset;
std::fill(begin, begin + pkt->getSize(), true);
}
}
}
/**
* Tests if the flags of this TargetList have their default
* values.
*
* @return True if the TargetList are reset, false otherwise.
*/
bool isReset() const {
return !needsWritable && !hasUpgrade && !allocOnFill &&
!hasFromCache;
!hasFromCache && onlyWrites;
}
/**
@@ -224,8 +279,7 @@ class MSHR : public QueueEntry, public Printable
* @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 +292,39 @@ class MSHR : public QueueEntry, public Printable
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 &&
std::all_of(writesBitmap.begin(),
writesBitmap.end(), [](bool i) { return i; });
}
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;
// NOTE: std::vector<bool> might not meet satisfy the
// ForwardIterator requirement and therefore cannot be used
// for writesBitmap.
/**
* Track which bytes are written by requests in this target
* list.
*/
std::vector<char> writesBitmap;
};
/** A list of MSHRs. */
@@ -315,6 +402,16 @@ class MSHR : public QueueEntry, public Printable
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.