Revamp replacement-of-upgrade handling.

--HG--
extra : convert_revision : 9bc09d8ae6d50e6dfbb4ab21514612f9aa102a2e
This commit is contained in:
Steve Reinhardt 2007-06-26 23:30:30 -07:00
parent 1b20df5607
commit c4903e0882
4 changed files with 36 additions and 68 deletions

View file

@ -136,6 +136,9 @@ class Cache : public BaseCache
/** Prefetcher */
BasePrefetcher *prefetcher;
/** Temporary cache block for occasional transitory use */
BlkType *tempBlock;
/**
* Can this cache should allocate a block on a line-sized write miss.
*/

View file

@ -58,6 +58,9 @@ Cache<TagStore,Coherence>::Cache(const std::string &_name,
doFastWrites(params.doFastWrites),
prefetchMiss(params.prefetchMiss)
{
tempBlock = new BlkType();
tempBlock->data = new uint8_t[blkSize];
cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
memSidePort = new MemSidePort(_name + "-mem_side_port", this);
cpuSidePort->setOtherPort(memSidePort);
@ -678,11 +681,8 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt)
pkt->getAddr());
BlkType *blk = tags->findBlock(pkt->getAddr());
if (!mshr->handleFill(pkt, blk)) {
mq->markPending(mshr);
requestMemSideBus((RequestCause)mq->index, pkt->finishTime);
return;
}
// give mshr a chance to do some dirty work
mshr->handleFill(pkt, blk);
PacketList writebacks;
blk = handleFill(pkt, blk, writebacks);
@ -693,6 +693,13 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt)
allocateBuffer(wbPkt, time, true);
writebacks.pop_front();
}
// if we used temp block, clear it out
if (blk == tempBlock) {
if (blk->isDirty()) {
allocateBuffer(writebackBlk(blk), time, true);
}
tags->invalidateBlk(blk);
}
} else {
if (pkt->req->isUncacheable()) {
mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
@ -764,15 +771,26 @@ Cache<TagStore,Coherence>::handleFill(PacketPtr pkt, BlkType *blk,
Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr);
if (repl_mshr) {
repl_mshr->handleReplacement(blk, blkSize);
}
// must be an outstanding upgrade request on block
// we're about to replace...
assert(!blk->isWritable());
assert(repl_mshr->needsExclusive);
// too hard to replace block with transient state;
// just use temporary storage to complete the current
// request and then get rid of it
assert(!tempBlock->isValid());
blk = tempBlock;
tempBlock->set = tags->extractSet(addr);
DPRINTF(Cache, "using temp block for %x\n", addr);
} else {
DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
repl_addr, addr,
blk->isDirty() ? "writeback" : "clean");
DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
repl_addr, addr, blk->isDirty() ? "writeback" : "clean");
if (blk->isDirty()) {
// Save writeback packet for handling by caller
writebacks.push_back(writebackBlk(blk));
if (blk->isDirty()) {
// Save writeback packet for handling by caller
writebacks.push_back(writebackBlk(blk));
}
}
}

View file

@ -76,7 +76,6 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target,
deferredNeedsExclusive = false;
pendingInvalidate = false;
pendingShared = false;
replacedPendingUpgrade = false;
data = NULL;
}
@ -185,61 +184,13 @@ 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::handleFill(Packet *pkt, CacheBlk *blk)
{
if (replacedPendingUpgrade) {
// block was replaced while upgrade request was in service
assert(pkt->cmd == MemCmd::UpgradeResp);
assert(blk == NULL);
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;
} else if (pendingShared) {
if (pendingShared) {
// we snooped another read while this read was in
// service... assert shared line on its behalf
pkt->assertShared();
}
return true;
}

View file

@ -106,9 +106,6 @@ class MSHR : public Packet::SenderState
bool deferredNeedsExclusive;
bool pendingInvalidate;
bool pendingShared;
/** Is there a pending upgrade that got replaced? */
bool replacedPendingUpgrade;
bool replacedPendingUpgradeDirty;
/** Thread number of the miss. */
short threadNum;
@ -213,8 +210,7 @@ public:
bool promoteDeferredTargets();
void handleReplacement(CacheBlk *blk, int blkSize);
bool handleFill(Packet *pkt, CacheBlk *blk);
void handleFill(Packet *pkt, CacheBlk *blk);
/**
* Prints the contents of this MSHR to stderr.