Handle replacement of block with pending upgrade.
src/mem/cache/tags/lru.cc: Add some replacement DPRINTFs --HG-- extra : convert_revision : 7993ec24d6af7e7774d04ce36f20e3f43f887fd9
This commit is contained in:
parent
f697e959a1
commit
7dacbcf492
4 changed files with 89 additions and 6 deletions
27
src/mem/cache/cache_impl.hh
vendored
27
src/mem/cache/cache_impl.hh
vendored
|
@ -300,7 +300,6 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketList writebacks;
|
|
||||||
int lat = hitLatency;
|
int lat = hitLatency;
|
||||||
bool satisfied = false;
|
bool satisfied = false;
|
||||||
|
|
||||||
|
@ -319,6 +318,8 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
PacketList writebacks;
|
||||||
|
|
||||||
// If this is a block size write/hint (WH64) allocate the block here
|
// If this is a block size write/hint (WH64) allocate the block here
|
||||||
// if the coherence protocol allows it.
|
// if the coherence protocol allows it.
|
||||||
/** @todo make the fast write alloc (wh64) work with coherence. */
|
/** @todo make the fast write alloc (wh64) work with coherence. */
|
||||||
|
@ -338,7 +339,6 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
|
||||||
++fastWrites;
|
++fastWrites;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// copy writebacks to write buffer
|
// copy writebacks to write buffer
|
||||||
while (!writebacks.empty()) {
|
while (!writebacks.empty()) {
|
||||||
|
@ -346,6 +346,7 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
|
||||||
allocateBuffer(wbPkt, time, true);
|
allocateBuffer(wbPkt, time, true);
|
||||||
writebacks.pop_front();
|
writebacks.pop_front();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool needsResponse = pkt->needsResponse();
|
bool needsResponse = pkt->needsResponse();
|
||||||
|
|
||||||
|
@ -676,6 +677,15 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt)
|
||||||
DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
|
DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
|
||||||
pkt->getAddr());
|
pkt->getAddr());
|
||||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||||
|
|
||||||
|
if (blk == NULL && pkt->cmd == MemCmd::UpgradeResp) {
|
||||||
|
if (!mshr->handleReplacedPendingUpgrade(pkt)) {
|
||||||
|
mq->markPending(mshr);
|
||||||
|
requestMemSideBus((RequestCause)mq->index, pkt->finishTime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PacketList writebacks;
|
PacketList writebacks;
|
||||||
blk = handleFill(pkt, blk, writebacks);
|
blk = handleFill(pkt, blk, writebacks);
|
||||||
deallocate = satisfyMSHR(mshr, pkt, blk);
|
deallocate = satisfyMSHR(mshr, pkt, blk);
|
||||||
|
@ -747,15 +757,20 @@ Cache<TagStore,Coherence>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||||
Addr addr = pkt->getAddr();
|
Addr addr = pkt->getAddr();
|
||||||
|
|
||||||
if (blk == NULL) {
|
if (blk == NULL) {
|
||||||
// better have read new data
|
// better have read new data...
|
||||||
assert(pkt->isRead());
|
assert(pkt->isRead());
|
||||||
|
|
||||||
// need to do a replacement
|
// need to do a replacement
|
||||||
blk = tags->findReplacement(addr, writebacks);
|
blk = tags->findReplacement(addr, writebacks);
|
||||||
if (blk->isValid()) {
|
if (blk->isValid()) {
|
||||||
|
Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
|
||||||
|
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr);
|
||||||
|
if (repl_mshr) {
|
||||||
|
repl_mshr->handleReplacement(blk, blkSize);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
|
DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
|
||||||
tags->regenerateBlkAddr(blk->tag, blk->set), addr,
|
repl_addr, addr, blk->isDirty() ? "writeback" : "clean");
|
||||||
blk->isDirty() ? "writeback" : "clean");
|
|
||||||
|
|
||||||
if (blk->isDirty()) {
|
if (blk->isDirty()) {
|
||||||
// Save writeback packet for handling by caller
|
// Save writeback packet for handling by caller
|
||||||
|
@ -992,7 +1007,7 @@ Cache<TagStore,Coherence>::getNextMSHR()
|
||||||
return conflict_mshr;
|
return conflict_mshr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No conclifts; issue read
|
// No conflicts; issue read
|
||||||
return miss_mshr;
|
return miss_mshr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
53
src/mem/cache/miss/mshr.cc
vendored
53
src/mem/cache/miss/mshr.cc
vendored
|
@ -75,6 +75,8 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target,
|
||||||
assert(deferredTargets.empty());
|
assert(deferredTargets.empty());
|
||||||
deferredNeedsExclusive = false;
|
deferredNeedsExclusive = false;
|
||||||
pendingInvalidate = false;
|
pendingInvalidate = false;
|
||||||
|
replacedPendingUpgrade = false;
|
||||||
|
data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -170,6 +172,57 @@ MSHR::promoteDeferredTargets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MSHR::handleReplacement(CacheBlk *blk, int blkSize)
|
||||||
|
{
|
||||||
|
// must be an outstanding upgrade request on block we're about to
|
||||||
|
// replace...
|
||||||
|
assert(!blk->isWritable());
|
||||||
|
assert(needsExclusive);
|
||||||
|
replacedPendingUpgrade = true;
|
||||||
|
|
||||||
|
// if it's dirty, just remember what happened and allow the
|
||||||
|
// writeback to continue. we'll reissue a ReadEx later whether
|
||||||
|
// the upgrade succeeds or not
|
||||||
|
if (blk->isDirty()) {
|
||||||
|
replacedPendingUpgradeDirty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not dirty, we need to save it off as it will be only valid
|
||||||
|
// copy in system if upgrade is successful (and may need to be
|
||||||
|
// written back then, as the current owner if any will be
|
||||||
|
// invalidating its block)
|
||||||
|
replacedPendingUpgradeDirty = false;
|
||||||
|
data = new uint8_t[blkSize];
|
||||||
|
std::memcpy(data, blk->data, blkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MSHR::handleReplacedPendingUpgrade(Packet *pkt)
|
||||||
|
{
|
||||||
|
// @TODO: if upgrade is nacked and replacedPendingUpgradeDirty is true, then we need to writeback the data (or rel
|
||||||
|
assert(pkt->cmd == MemCmd::UpgradeResp);
|
||||||
|
assert(replacedPendingUpgrade);
|
||||||
|
replacedPendingUpgrade = false; // reset
|
||||||
|
if (replacedPendingUpgradeDirty) {
|
||||||
|
// we wrote back the previous copy; just reissue as a ReadEx
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// previous copy was not dirty, but we are now owner... fake out
|
||||||
|
// cache by taking saved data and converting UpgradeResp to
|
||||||
|
// ReadExResp
|
||||||
|
assert(data);
|
||||||
|
pkt->cmd = MemCmd::ReadExResp;
|
||||||
|
pkt->setData(data);
|
||||||
|
delete [] data;
|
||||||
|
data = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MSHR::dump()
|
MSHR::dump()
|
||||||
{
|
{
|
||||||
|
|
11
src/mem/cache/miss/mshr.hh
vendored
11
src/mem/cache/miss/mshr.hh
vendored
|
@ -105,12 +105,20 @@ class MSHR : public Packet::SenderState
|
||||||
|
|
||||||
bool deferredNeedsExclusive;
|
bool deferredNeedsExclusive;
|
||||||
bool pendingInvalidate;
|
bool pendingInvalidate;
|
||||||
|
/** Is there a pending upgrade that got replaced? */
|
||||||
|
bool replacedPendingUpgrade;
|
||||||
|
bool replacedPendingUpgradeDirty;
|
||||||
|
|
||||||
/** Thread number of the miss. */
|
/** Thread number of the miss. */
|
||||||
short threadNum;
|
short threadNum;
|
||||||
/** The number of currently allocated targets. */
|
/** The number of currently allocated targets. */
|
||||||
short ntargets;
|
short ntargets;
|
||||||
|
|
||||||
|
|
||||||
|
/** Data buffer (if needed). Currently used only for pending
|
||||||
|
* upgrade handling. */
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to this MSHR on the ready list.
|
* Pointer to this MSHR on the ready list.
|
||||||
* @sa MissQueue, MSHRQueue::readyList
|
* @sa MissQueue, MSHRQueue::readyList
|
||||||
|
@ -204,6 +212,9 @@ public:
|
||||||
|
|
||||||
bool promoteDeferredTargets();
|
bool promoteDeferredTargets();
|
||||||
|
|
||||||
|
void handleReplacement(CacheBlk *blk, int blkSize);
|
||||||
|
bool handleReplacedPendingUpgrade(Packet *pkt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the contents of this MSHR to stderr.
|
* Prints the contents of this MSHR to stderr.
|
||||||
*/
|
*/
|
||||||
|
|
4
src/mem/cache/tags/lru.cc
vendored
4
src/mem/cache/tags/lru.cc
vendored
|
@ -173,6 +173,8 @@ LRU::findBlock(Addr addr, int &lat)
|
||||||
if (blk != NULL) {
|
if (blk != NULL) {
|
||||||
// move this block to head of the MRU list
|
// move this block to head of the MRU list
|
||||||
sets[set].moveToHead(blk);
|
sets[set].moveToHead(blk);
|
||||||
|
DPRINTF(Cache, "set %x: moving blk %x to MRU\n",
|
||||||
|
set, regenerateBlkAddr(tag, set));
|
||||||
if (blk->whenReady > curTick
|
if (blk->whenReady > curTick
|
||||||
&& blk->whenReady - curTick > hitLatency) {
|
&& blk->whenReady - curTick > hitLatency) {
|
||||||
lat = blk->whenReady - curTick;
|
lat = blk->whenReady - curTick;
|
||||||
|
@ -214,6 +216,8 @@ LRU::findReplacement(Addr addr, PacketList &writebacks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(Cache, "set %x: selecting blk %x for replacement\n",
|
||||||
|
set, regenerateBlkAddr(blk->tag, set));
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue