X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmem%2Fcache%2Fmshr.cc;h=5b9302925831ae67751ff64fbbe28d497b9d5f14;hb=338a173e822298bd22741342a7b24352450afdd1;hp=d6208dde97621166195726b55fd32ab5f9b3c19c;hpb=97075b9982537b8d7cf7f921b8e0e667ffa7691c;p=gem5.git diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc index d6208dde9..5b9302925 100644 --- a/src/mem/cache/mshr.cc +++ b/src/mem/cache/mshr.cc @@ -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); } } } @@ -207,10 +210,10 @@ MSHR::TargetList::clearDownstreamPending() 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; } } @@ -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 @@ -548,6 +559,49 @@ MSHR::promoteDeferredTargets() return true; } +void +MSHR::promoteIf(const std::function& 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,29 +617,29 @@ 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)); } }