From 6dc599ea9bae9cb56ca81094b37009f5a14ebdff Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 9 Sep 2010 14:40:19 -0400 Subject: mem: fix functional accesses to deal with coherence change We can't just obliviously return the first valid cache block we find any more... see comments for details. --- src/mem/cache/cache_impl.hh | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src/mem/cache') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 8d2806b8d..3f3dc6877 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -759,21 +759,44 @@ Cache::functionalAccess(PacketPtr pkt, { Addr blk_addr = blockAlign(pkt->getAddr()); BlkType *blk = tags->findBlock(pkt->getAddr()); + MSHR *mshr = mshrQueue.findMatch(blk_addr); pkt->pushLabel(name()); CacheBlkPrintWrapper cbpw(blk); - bool done = - (blk && pkt->checkFunctional(&cbpw, blk_addr, blkSize, blk->data)) + + // Note that just because an L2/L3 has valid data doesn't mean an + // L1 doesn't have a more up-to-date modified copy that still + // needs to be found. As a result we always update the request if + // we have it, but only declare it satisfied if we are the owner. + + // see if we have data at all (owned or otherwise) + bool have_data = blk && blk->isValid() + && pkt->checkFunctional(&cbpw, blk_addr, blkSize, blk->data); + + // data we have is dirty if marked as such or if valid & ownership + // pending due to outstanding UpgradeReq + bool have_dirty = + have_data && (blk->isDirty() || + (mshr && mshr->inService && mshr->isPendingDirty())); + + bool done = have_dirty || incomingPort->checkFunctional(pkt) || mshrQueue.checkFunctional(pkt, blk_addr) || writeBuffer.checkFunctional(pkt, blk_addr) || otherSidePort->checkFunctional(pkt); + DPRINTF(Cache, "functional %s %x %s%s%s\n", + pkt->cmdString(), pkt->getAddr(), + (blk && blk->isValid()) ? "valid " : "", + have_data ? "data " : "", done ? "done " : ""); + // We're leaving the cache, so pop cache->name() label pkt->popLabel(); - if (!done) { + if (done) { + pkt->makeResponse(); + } else { otherSidePort->sendFunctional(pkt); } } -- cgit v1.2.3