diff -r e88f53ab940e -r 258a32a088d2 src/mem/cache/base.cc --- a/src/mem/cache/base.cc Thu Jul 02 15:49:11 2015 +0100 +++ b/src/mem/cache/base.cc Thu Jul 02 15:51:36 2015 +0100 @@ -190,7 +190,8 @@ // to change the subset of commands that are considered "demand" vs // "non-demand" #define SUM_DEMAND(s) \ - (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq]) + (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + \ + s[MemCmd::ReadExReq] + s[MemCmd::ReadCleanReq] + s[MemCmd::ReadSharedReq]) // should writebacks be included here? prior code was inconsistent... #define SUM_NON_DEMAND(s) \ diff -r e88f53ab940e -r 258a32a088d2 src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Thu Jul 02 15:49:11 2015 +0100 +++ b/src/mem/cache/cache_impl.hh Thu Jul 02 15:51:36 2015 +0100 @@ -184,6 +184,10 @@ // special handling for coherent block requests from // upper-level caches if (pkt->needsExclusive()) { + // sanity check + assert(pkt->cmd == MemCmd::ReadExReq || + pkt->cmd == MemCmd::SCUpgradeFailReq); + // if we have a dirty copy, make sure the recipient // keeps it marked dirty if (blk->isDirty()) { @@ -193,8 +197,9 @@ if (blk != tempBlock) tags->invalidate(blk); blk->invalidate(); - } else if (blk->isWritable() && !pending_downgrade - && !pkt->sharedAsserted() && !pkt->req->isInstFetch()) { + } else if (blk->isWritable() && !pending_downgrade && + !pkt->sharedAsserted() && + pkt->cmd != MemCmd::ReadCleanReq) { // we can give the requester an exclusive copy (by not // asserting shared line) on a read request if: // - we have an exclusive copy at this level (& below) @@ -901,7 +906,8 @@ cmd = cpu_pkt->cmd; } else { // block is invalid - cmd = needsExclusive ? MemCmd::ReadExReq : MemCmd::ReadReq; + cmd = needsExclusive ? MemCmd::ReadExReq : + (isReadOnly ? MemCmd::ReadCleanReq : MemCmd::ReadSharedReq); } PacketPtr pkt = new Packet(cpu_pkt->req, cmd, blkSize); diff -r e88f53ab940e -r 258a32a088d2 src/mem/packet.hh --- a/src/mem/packet.hh Thu Jul 02 15:49:11 2015 +0100 +++ b/src/mem/packet.hh Thu Jul 02 15:51:36 2015 +0100 @@ -101,6 +101,8 @@ UpgradeFailResp, // Valid for SCUpgradeReq only ReadExReq, ReadExResp, + ReadCleanReq, + ReadSharedReq, LoadLockedReq, StoreCondReq, StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent) diff -r e88f53ab940e -r 258a32a088d2 src/mem/packet.cc --- a/src/mem/packet.cc Thu Jul 02 15:49:11 2015 +0100 +++ b/src/mem/packet.cc Thu Jul 02 15:51:36 2015 +0100 @@ -71,7 +71,8 @@ { /* InvalidCmd */ { 0, InvalidCmd, "InvalidCmd" }, - /* ReadReq */ + /* ReadReq - Read issued by a non-caching agent such as a CPU or + * device, with no restrictions on alignment. */ { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, /* ReadResp */ { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, @@ -125,12 +126,23 @@ * that it has failed, acquires line as Dirty*/ { SET4(IsRead, NeedsExclusive, IsResponse, HasData), InvalidCmd, "UpgradeFailResp" }, - /* ReadExReq */ + /* ReadExReq - Read issues by a cache, always cache-line aligned, + * and the response is guaranteed to be writeable (exclusive or + * even modified) */ { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse), ReadExResp, "ReadExReq" }, - /* ReadExResp */ + /* ReadExResp - Response matching a read exclusive, as we check + * the need for exclusive also on responses */ { SET4(IsRead, NeedsExclusive, IsResponse, HasData), InvalidCmd, "ReadExResp" }, + /* ReadCleanReq - Read issued by a cache, always cache-line + * aligned, and the response is guaranteed to not contain dirty data + * (exclusive or shared).*/ + { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadCleanReq" }, + /* ReadSharedReq - Read issued by a cache, always cache-line + * aligned, response is shared, possibly exclusive, owned or even + * modified. */ + { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadSharedReq" }, /* LoadLockedReq: note that we use plain ReadResp as response, so that * we can also use ReadRespWithInvalidate when needed */ { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse),