*
* Authors: Erik Hallnor
* Dave Greene
+ * Nikos Nikoleris
*/
/**
MSHR::MSHR() : downstreamPending(false),
pendingModified(false),
postInvalidate(false), postDowngrade(false),
- isForward(false)
+ wasWholeLineWrite(false), isForward(false)
{
}
if (source != Target::FromPrefetcher) {
hasFromCache = hasFromCache || pkt->fromCache();
+
+ updateWriteFlags(pkt);
}
}
}
bool
-MSHR::TargetList::checkFunctional(PacketPtr pkt)
+MSHR::TargetList::trySatisfyFunctional(PacketPtr pkt)
{
for (auto& t : *this) {
- if (pkt->checkFunctional(t.pkt)) {
+ if (pkt->trySatisfyFunctional(t.pkt)) {
return true;
}
}
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());
}
// 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();
}
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
return true;
}
+void
+MSHR::promoteIf(const std::function<bool (Target &)>& pred)
+{
+ // if any of the deferred targets were upper-level cache
+ // requests marked downstreamPending, need to clear that
+ assert(!downstreamPending); // not pending here anymore
+
+ // find the first target does not satisfy the condition
+ auto last_it = std::find_if_not(deferredTargets.begin(),
+ deferredTargets.end(),
+ pred);
+
+ // for the prefix of the deferredTargets [begin(), last_it) clear
+ // the downstreamPending flag and move them to the target list
+ deferredTargets.clearDownstreamPending(deferredTargets.begin(),
+ last_it);
+ targets.splice(targets.end(), deferredTargets,
+ deferredTargets.begin(), last_it);
+ // We need to update the flags for the target lists after the
+ // modifications
+ deferredTargets.populateFlags();
+}
+
+void
+MSHR::promoteReadable()
+{
+ if (!deferredTargets.empty() && !hasPostInvalidate()) {
+ // We got a non invalidating response, and we have the block
+ // but we have deferred targets which are waiting and they do
+ // not need writable. This can happen if the original request
+ // was for a cache clean operation and we had a copy of the
+ // block. Since we serviced the cache clean operation and we
+ // have the block, there's no need to defer the targets, so
+ // move them up to the regular target list.
+
+ auto pred = [](Target &t) {
+ assert(t.source == Target::FromCPU);
+ return !t.pkt->req->isCacheInvalidate() &&
+ !t.pkt->needsWritable();
+ };
+ promoteIf(pred);
+ }
+}
void
MSHR::promoteWritable()
// target list.
assert(!targets.needsWritable);
targets.needsWritable = true;
- // if any of the deferred targets were upper-level cache
- // requests marked downstreamPending, need to clear that
- assert(!downstreamPending); // not pending here anymore
- deferredTargets.clearDownstreamPending();
- // this clears out deferredTargets too
- targets.splice(targets.end(), deferredTargets);
- deferredTargets.resetFlags();
+
+ auto pred = [](Target &t) {
+ assert(t.source == Target::FromCPU);
+ return !t.pkt->req->isCacheInvalidate();
+ };
+
+ promoteIf(pred);
}
}
bool
-MSHR::checkFunctional(PacketPtr pkt)
+MSHR::trySatisfyFunctional(PacketPtr pkt)
{
// For printing, we treat the MSHR as a whole as single entity.
// For other requests, we iterate over the individual targets
// since that's where the actual data lies.
if (pkt->isPrint()) {
- pkt->checkFunctional(this, blkAddr, isSecure, blkSize, nullptr);
+ pkt->trySatisfyFunctional(this, blkAddr, isSecure, blkSize, nullptr);
return false;
} else {
- return (targets.checkFunctional(pkt) ||
- deferredTargets.checkFunctional(pkt));
+ return (targets.trySatisfyFunctional(pkt) ||
+ deferredTargets.trySatisfyFunctional(pkt));
}
}