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.
This commit is contained in:
Steve Reinhardt
2010-09-09 14:40:19 -04:00
parent 71aca6d29e
commit 6dc599ea9b
3 changed files with 29 additions and 5 deletions

View File

@@ -325,8 +325,10 @@ Bridge::BridgePort::recvFunctional(PacketPtr pkt)
pkt->pushLabel(name());
for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
if (pkt->checkFunctional((*i)->pkt))
if (pkt->checkFunctional((*i)->pkt)) {
pkt->makeResponse();
return;
}
}
pkt->popLabel();

View File

@@ -759,21 +759,44 @@ Cache<TagStore>::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);
}
}

View File

@@ -179,7 +179,6 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data)
if (func_start >= val_start && func_end <= val_end) {
allocate();
memcpy(getPtr<uint8_t>(), data + offset, getSize());
makeResponse();
return true;
} else {
// In this case the timing packet only partially satisfies