mem: Keep track of allocOnFill in the TargetList
Previously the information of whether a response was allocating or not was a property of the MSHR. This change makes this flag a property of the TargetList. Differernt TargetLists, e.g. the targets and the deferred targets lists might have different values. Additionally, the information about whether each of the target expects an allocating response is stored inside the TargetList container. This allows for repopulating the flag in case some of the targets are removed. Change-Id: If3ec2516992f42a6d9da907009ffe3ab8d0d2021 Reviewed-by: Andreas Hansson <andreas.hansson@arm.com> Reviewed-by: Stephan Diestelhorst <stephan.diestelhorst@arm.com>
This commit is contained in:
parent
f7a5de3bec
commit
d28c2906f4
3 changed files with 59 additions and 28 deletions
5
src/mem/cache/cache.cc
vendored
5
src/mem/cache/cache.cc
vendored
|
@ -1318,7 +1318,7 @@ Cache::recvTimingResp(PacketPtr pkt)
|
||||||
DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
|
DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
|
||||||
pkt->getAddr());
|
pkt->getAddr());
|
||||||
|
|
||||||
blk = handleFill(pkt, blk, writebacks, mshr->allocOnFill);
|
blk = handleFill(pkt, blk, writebacks, mshr->allocOnFill());
|
||||||
assert(blk != nullptr);
|
assert(blk != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1369,7 +1369,8 @@ Cache::recvTimingResp(PacketPtr pkt)
|
||||||
// any deferred targets if possible
|
// any deferred targets if possible
|
||||||
mshr->promoteWritable();
|
mshr->promoteWritable();
|
||||||
// NB: we use the original packet here and not the response!
|
// NB: we use the original packet here and not the response!
|
||||||
blk = handleFill(tgt_pkt, blk, writebacks, mshr->allocOnFill);
|
blk = handleFill(tgt_pkt, blk, writebacks,
|
||||||
|
mshr->allocOnFill());
|
||||||
assert(blk != nullptr);
|
assert(blk != nullptr);
|
||||||
|
|
||||||
// treat as a fill, and discard the invalidation
|
// treat as a fill, and discard the invalidation
|
||||||
|
|
37
src/mem/cache/mshr.cc
vendored
37
src/mem/cache/mshr.cc
vendored
|
@ -65,17 +65,18 @@ using namespace std;
|
||||||
MSHR::MSHR() : downstreamPending(false),
|
MSHR::MSHR() : downstreamPending(false),
|
||||||
pendingModified(false),
|
pendingModified(false),
|
||||||
postInvalidate(false), postDowngrade(false),
|
postInvalidate(false), postDowngrade(false),
|
||||||
isForward(false), allocOnFill(false)
|
isForward(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MSHR::TargetList::TargetList()
|
MSHR::TargetList::TargetList()
|
||||||
: needsWritable(false), hasUpgrade(false)
|
: needsWritable(false), hasUpgrade(false), allocOnFill(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MSHR::TargetList::updateFlags(PacketPtr pkt, Target::Source source)
|
MSHR::TargetList::updateFlags(PacketPtr pkt, Target::Source source,
|
||||||
|
bool alloc_on_fill)
|
||||||
{
|
{
|
||||||
if (source != Target::FromSnoop) {
|
if (source != Target::FromSnoop) {
|
||||||
if (pkt->needsWritable()) {
|
if (pkt->needsWritable()) {
|
||||||
|
@ -88,6 +89,10 @@ MSHR::TargetList::updateFlags(PacketPtr pkt, Target::Source source)
|
||||||
if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
|
if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
|
||||||
hasUpgrade = true;
|
hasUpgrade = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// potentially re-evaluate whether we should allocate on a fill or
|
||||||
|
// not
|
||||||
|
allocOnFill = allocOnFill || alloc_on_fill;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,15 +101,16 @@ MSHR::TargetList::populateFlags()
|
||||||
{
|
{
|
||||||
resetFlags();
|
resetFlags();
|
||||||
for (auto& t: *this) {
|
for (auto& t: *this) {
|
||||||
updateFlags(t.pkt, t.source);
|
updateFlags(t.pkt, t.source, t.allocOnFill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
MSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
|
MSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
|
||||||
Counter order, Target::Source source, bool markPending)
|
Counter order, Target::Source source, bool markPending,
|
||||||
|
bool alloc_on_fill)
|
||||||
{
|
{
|
||||||
updateFlags(pkt, source);
|
updateFlags(pkt, source, alloc_on_fill);
|
||||||
if (markPending) {
|
if (markPending) {
|
||||||
// Iterate over the SenderState stack and see if we find
|
// Iterate over the SenderState stack and see if we find
|
||||||
// an MSHR entry. If we do, set the downstreamPending
|
// an MSHR entry. If we do, set the downstreamPending
|
||||||
|
@ -119,7 +125,7 @@ MSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emplace_back(pkt, readyTime, order, source, markPending);
|
emplace_back(pkt, readyTime, order, source, markPending, alloc_on_fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,7 +245,6 @@ MSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
|
||||||
order = _order;
|
order = _order;
|
||||||
assert(target);
|
assert(target);
|
||||||
isForward = false;
|
isForward = false;
|
||||||
allocOnFill = alloc_on_fill;
|
|
||||||
_isUncacheable = target->req->isUncacheable();
|
_isUncacheable = target->req->isUncacheable();
|
||||||
inService = false;
|
inService = false;
|
||||||
downstreamPending = false;
|
downstreamPending = false;
|
||||||
|
@ -248,7 +253,7 @@ MSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
|
||||||
// snoop (mem-side request), so set source according to request here
|
// snoop (mem-side request), so set source according to request here
|
||||||
Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
|
Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
|
||||||
Target::FromPrefetcher : Target::FromCPU;
|
Target::FromPrefetcher : Target::FromCPU;
|
||||||
targets.add(target, when_ready, _order, source, true);
|
targets.add(target, when_ready, _order, source, true, alloc_on_fill);
|
||||||
assert(deferredTargets.isReset());
|
assert(deferredTargets.isReset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,10 +310,6 @@ MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order,
|
||||||
// have targets addded if originally allocated uncacheable
|
// have targets addded if originally allocated uncacheable
|
||||||
assert(!_isUncacheable);
|
assert(!_isUncacheable);
|
||||||
|
|
||||||
// potentially re-evaluate whether we should allocate on a fill or
|
|
||||||
// not
|
|
||||||
allocOnFill = allocOnFill || alloc_on_fill;
|
|
||||||
|
|
||||||
// if there's a request already in service for this MSHR, we will
|
// if there's a request already in service for this MSHR, we will
|
||||||
// have to defer the new target until after the response if any of
|
// have to defer the new target until after the response if any of
|
||||||
// the following are true:
|
// the following are true:
|
||||||
|
@ -326,13 +327,15 @@ MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order,
|
||||||
// need to put on deferred list
|
// need to put on deferred list
|
||||||
if (hasPostInvalidate())
|
if (hasPostInvalidate())
|
||||||
replaceUpgrade(pkt);
|
replaceUpgrade(pkt);
|
||||||
deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true);
|
deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true,
|
||||||
|
alloc_on_fill);
|
||||||
} else {
|
} else {
|
||||||
// No request outstanding, or still OK to append to
|
// No request outstanding, or still OK to append to
|
||||||
// outstanding request: append to regular target list. Only
|
// outstanding request: append to regular target list. Only
|
||||||
// mark pending if current request hasn't been issued yet
|
// mark pending if current request hasn't been issued yet
|
||||||
// (isn't in service).
|
// (isn't in service).
|
||||||
targets.add(pkt, whenReady, _order, Target::FromCPU, !inService);
|
targets.add(pkt, whenReady, _order, Target::FromCPU, !inService,
|
||||||
|
alloc_on_fill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +434,7 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order)
|
||||||
// recipient does not care there is no harm in doing so
|
// recipient does not care there is no harm in doing so
|
||||||
}
|
}
|
||||||
targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
|
targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
|
||||||
downstreamPending && targets.needsWritable);
|
downstreamPending && targets.needsWritable, false);
|
||||||
|
|
||||||
if (pkt->needsWritable()) {
|
if (pkt->needsWritable()) {
|
||||||
// This transaction will take away our pending copy
|
// This transaction will take away our pending copy
|
||||||
|
@ -527,7 +530,7 @@ MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
|
||||||
prefix, blkAddr, blkAddr + blkSize - 1,
|
prefix, blkAddr, blkAddr + blkSize - 1,
|
||||||
isSecure ? "s" : "ns",
|
isSecure ? "s" : "ns",
|
||||||
isForward ? "Forward" : "",
|
isForward ? "Forward" : "",
|
||||||
allocOnFill ? "AllocOnFill" : "",
|
allocOnFill() ? "AllocOnFill" : "",
|
||||||
needsWritable() ? "Wrtbl" : "",
|
needsWritable() ? "Wrtbl" : "",
|
||||||
_isUncacheable ? "Unc" : "",
|
_isUncacheable ? "Unc" : "",
|
||||||
inService ? "InSvc" : "",
|
inService ? "InSvc" : "",
|
||||||
|
|
45
src/mem/cache/mshr.hh
vendored
45
src/mem/cache/mshr.hh
vendored
|
@ -128,11 +128,14 @@ class MSHR : public QueueEntry, public Printable
|
||||||
const Source source; //!< Request from cpu, memory, or prefetcher?
|
const Source source; //!< Request from cpu, memory, or prefetcher?
|
||||||
const bool markedPending; //!< Did we mark upstream MSHR
|
const bool markedPending; //!< Did we mark upstream MSHR
|
||||||
//!< as downstreamPending?
|
//!< as downstreamPending?
|
||||||
|
const bool allocOnFill; //!< Should the response servicing this
|
||||||
|
//!< target list allocate in the cache?
|
||||||
|
|
||||||
Target(PacketPtr _pkt, Tick _readyTime, Counter _order,
|
Target(PacketPtr _pkt, Tick _readyTime, Counter _order,
|
||||||
Source _source, bool _markedPending)
|
Source _source, bool _markedPending, bool alloc_on_fill)
|
||||||
: recvTime(curTick()), readyTime(_readyTime), order(_order),
|
: recvTime(curTick()), readyTime(_readyTime), order(_order),
|
||||||
pkt(_pkt), source(_source), markedPending(_markedPending)
|
pkt(_pkt), source(_source), markedPending(_markedPending),
|
||||||
|
allocOnFill(alloc_on_fill)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,6 +144,8 @@ class MSHR : public QueueEntry, public Printable
|
||||||
public:
|
public:
|
||||||
bool needsWritable;
|
bool needsWritable;
|
||||||
bool hasUpgrade;
|
bool hasUpgrade;
|
||||||
|
/** Set when the response should allocate on fill */
|
||||||
|
bool allocOnFill;
|
||||||
|
|
||||||
TargetList();
|
TargetList();
|
||||||
|
|
||||||
|
@ -150,10 +155,12 @@ class MSHR : public QueueEntry, public Printable
|
||||||
*
|
*
|
||||||
* @param pkt Packet considered for the flag update
|
* @param pkt Packet considered for the flag update
|
||||||
* @param source Indicates the source of the packet
|
* @param source Indicates the source of the packet
|
||||||
|
* @param alloc_on_fill Whether the pkt would allocate on a fill
|
||||||
*/
|
*/
|
||||||
void updateFlags(PacketPtr pkt, Target::Source source);
|
void updateFlags(PacketPtr pkt, Target::Source source,
|
||||||
|
bool alloc_on_fill);
|
||||||
|
|
||||||
void resetFlags() { needsWritable = hasUpgrade = false; }
|
void resetFlags() { needsWritable = hasUpgrade = allocOnFill = false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Goes through the list of targets and uses them to populate
|
* Goes through the list of targets and uses them to populate
|
||||||
|
@ -163,9 +170,29 @@ class MSHR : public QueueEntry, public Printable
|
||||||
*/
|
*/
|
||||||
void populateFlags();
|
void populateFlags();
|
||||||
|
|
||||||
bool isReset() const { return !needsWritable && !hasUpgrade; }
|
/**
|
||||||
|
* Tests if the flags of this TargetList have their default
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
bool isReset() const {
|
||||||
|
return !needsWritable && !hasUpgrade && !allocOnFill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @param readTime Tick at which the packet is processed by this cache
|
||||||
|
* @param order A counter giving a unique id to each target
|
||||||
|
* @param source Indicates the source agent of the packet
|
||||||
|
* @param markPending Set for deferred targets or pending MSHRs
|
||||||
|
* @param alloc_on_fill Whether it should allocate on a fill
|
||||||
|
*/
|
||||||
void add(PacketPtr pkt, Tick readyTime, Counter order,
|
void add(PacketPtr pkt, Tick readyTime, Counter order,
|
||||||
Target::Source source, bool markPending);
|
Target::Source source, bool markPending,
|
||||||
|
bool alloc_on_fill);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert upgrades to the equivalent request if the cache line they
|
* Convert upgrades to the equivalent request if the cache line they
|
||||||
|
@ -184,9 +211,6 @@ class MSHR : public QueueEntry, public Printable
|
||||||
/** MSHR list iterator. */
|
/** MSHR list iterator. */
|
||||||
typedef List::iterator Iterator;
|
typedef List::iterator Iterator;
|
||||||
|
|
||||||
/** Keep track of whether we should allocate on fill or not */
|
|
||||||
bool allocOnFill;
|
|
||||||
|
|
||||||
/** The pending* and post* flags are only valid if inService is
|
/** The pending* and post* flags are only valid if inService is
|
||||||
* true. Using the accessor functions lets us detect if these
|
* true. Using the accessor functions lets us detect if these
|
||||||
* flags are accessed improperly.
|
* flags are accessed improperly.
|
||||||
|
@ -209,6 +233,9 @@ class MSHR : public QueueEntry, public Printable
|
||||||
|
|
||||||
bool sendPacket(Cache &cache);
|
bool sendPacket(Cache &cache);
|
||||||
|
|
||||||
|
bool allocOnFill() const {
|
||||||
|
return targets.allocOnFill;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue