summaryrefslogtreecommitdiff
path: root/src/mem/cache/mshr.cc
diff options
context:
space:
mode:
authorNikos Nikoleris <nikos.nikoleris@arm.com>2018-03-17 01:50:57 +0000
committerNikos Nikoleris <nikos.nikoleris@arm.com>2018-06-22 17:39:16 +0000
commitf4015a2c62e7cd8c169dae801e6d6901f40e1e40 (patch)
tree99f6ff952cdd82565d19a84c400c47dbcfa9161e /src/mem/cache/mshr.cc
parente656eeb288f8de94cc293012ba74c9c05fd75da3 (diff)
downloadgem5-f4015a2c62e7cd8c169dae801e6d6901f40e1e40.tar.xz
mem-cache: Promote targets that don't require writable
Until now, all deferred targets of an MSHR would be promoted together as soon as the targets were serviced. Due to the way we handle cache clean operations we might need to promote only deferred targets that don't require writable, leaving some targets as deferred. This change adds support for this selective promotion. Change-Id: I502e523dc9adbaf394955cbacea8286ab6a9b6bc Reviewed-on: https://gem5-review.googlesource.com/11017 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Jason Lowe-Power <jason@lowepower.com>
Diffstat (limited to 'src/mem/cache/mshr.cc')
-rw-r--r--src/mem/cache/mshr.cc67
1 files changed, 50 insertions, 17 deletions
diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc
index 8ef8a2ca2..8629b3377 100644
--- a/src/mem/cache/mshr.cc
+++ b/src/mem/cache/mshr.cc
@@ -548,6 +548,49 @@ MSHR::promoteDeferredTargets()
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()
@@ -563,23 +606,13 @@ 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
-
- auto last_it = std::find_if(
- deferredTargets.begin(), deferredTargets.end(),
- [](MSHR::Target &t) {
- assert(t.source == Target::FromCPU);
- return t.pkt->req->isCacheInvalidate();
- });
- 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();
+
+ auto pred = [](Target &t) {
+ assert(t.source == Target::FromCPU);
+ return !t.pkt->req->isCacheInvalidate();
+ };
+
+ promoteIf(pred);
}
}