mem-cache: Fix promoting of targets that need writable

There are cases where a request which does not need a writable copy
gets an response upgraded reponse and fills in a writable copy. When
this happens, we promote deferred MSHR targets that were deferred
because they needed a writable copy to service them immediately.

Previously, we would uncoditionally promote deferred targets. Since
the deferred targets might contain a cache invalidation operation, we
have to make sure that any targets following the cache invalidation is
not promoted.

Change-Id: I1f7b28f7d35f84329e065c8f63117db21852365a
Reviewed-on: https://gem5-review.googlesource.com/11016
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Nikos Nikoleris
2018-03-17 00:52:52 +00:00
parent 97075b9982
commit e656eeb288
2 changed files with 21 additions and 4 deletions

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

@@ -566,10 +566,20 @@ MSHR::promoteWritable()
// 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 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();
}
}

View File

@@ -385,6 +385,13 @@ class MSHR : public QueueEntry, public Printable
bool promoteDeferredTargets();
/**
* Promotes deferred targets that do not require writable
*
* Requests in the deferred target list are moved to the target
* list up until the first target that is a cache maintenance
* operation or needs a writable copy of the block
*/
void promoteWritable();
bool checkFunctional(PacketPtr pkt);