Revamp replacement-of-upgrade handling.
--HG-- extra : convert_revision : 9bc09d8ae6d50e6dfbb4ab21514612f9aa102a2e
This commit is contained in:
parent
1b20df5607
commit
c4903e0882
4 changed files with 36 additions and 68 deletions
3
src/mem/cache/cache.hh
vendored
3
src/mem/cache/cache.hh
vendored
|
@ -136,6 +136,9 @@ class Cache : public BaseCache
|
||||||
/** Prefetcher */
|
/** Prefetcher */
|
||||||
BasePrefetcher *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.
|
* Can this cache should allocate a block on a line-sized write miss.
|
||||||
*/
|
*/
|
||||||
|
|
36
src/mem/cache/cache_impl.hh
vendored
36
src/mem/cache/cache_impl.hh
vendored
|
@ -58,6 +58,9 @@ Cache<TagStore,Coherence>::Cache(const std::string &_name,
|
||||||
doFastWrites(params.doFastWrites),
|
doFastWrites(params.doFastWrites),
|
||||||
prefetchMiss(params.prefetchMiss)
|
prefetchMiss(params.prefetchMiss)
|
||||||
{
|
{
|
||||||
|
tempBlock = new BlkType();
|
||||||
|
tempBlock->data = new uint8_t[blkSize];
|
||||||
|
|
||||||
cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
|
cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
|
||||||
memSidePort = new MemSidePort(_name + "-mem_side_port", this);
|
memSidePort = new MemSidePort(_name + "-mem_side_port", this);
|
||||||
cpuSidePort->setOtherPort(memSidePort);
|
cpuSidePort->setOtherPort(memSidePort);
|
||||||
|
@ -678,11 +681,8 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt)
|
||||||
pkt->getAddr());
|
pkt->getAddr());
|
||||||
BlkType *blk = tags->findBlock(pkt->getAddr());
|
BlkType *blk = tags->findBlock(pkt->getAddr());
|
||||||
|
|
||||||
if (!mshr->handleFill(pkt, blk)) {
|
// give mshr a chance to do some dirty work
|
||||||
mq->markPending(mshr);
|
mshr->handleFill(pkt, blk);
|
||||||
requestMemSideBus((RequestCause)mq->index, pkt->finishTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketList writebacks;
|
PacketList writebacks;
|
||||||
blk = handleFill(pkt, blk, writebacks);
|
blk = handleFill(pkt, blk, writebacks);
|
||||||
|
@ -693,6 +693,13 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt)
|
||||||
allocateBuffer(wbPkt, time, true);
|
allocateBuffer(wbPkt, time, true);
|
||||||
writebacks.pop_front();
|
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 {
|
} else {
|
||||||
if (pkt->req->isUncacheable()) {
|
if (pkt->req->isUncacheable()) {
|
||||||
mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
|
mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
|
||||||
|
@ -764,17 +771,28 @@ Cache<TagStore,Coherence>::handleFill(PacketPtr pkt, BlkType *blk,
|
||||||
Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
|
Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
|
||||||
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr);
|
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr);
|
||||||
if (repl_mshr) {
|
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",
|
DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
|
||||||
repl_addr, addr, blk->isDirty() ? "writeback" : "clean");
|
repl_addr, addr,
|
||||||
|
blk->isDirty() ? "writeback" : "clean");
|
||||||
|
|
||||||
if (blk->isDirty()) {
|
if (blk->isDirty()) {
|
||||||
// Save writeback packet for handling by caller
|
// Save writeback packet for handling by caller
|
||||||
writebacks.push_back(writebackBlk(blk));
|
writebacks.push_back(writebackBlk(blk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
blk->tag = tags->extractTag(addr);
|
blk->tag = tags->extractTag(addr);
|
||||||
blk->status = coherence->getNewState(pkt);
|
blk->status = coherence->getNewState(pkt);
|
||||||
|
|
51
src/mem/cache/miss/mshr.cc
vendored
51
src/mem/cache/miss/mshr.cc
vendored
|
@ -76,7 +76,6 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target,
|
||||||
deferredNeedsExclusive = false;
|
deferredNeedsExclusive = false;
|
||||||
pendingInvalidate = false;
|
pendingInvalidate = false;
|
||||||
pendingShared = false;
|
pendingShared = false;
|
||||||
replacedPendingUpgrade = false;
|
|
||||||
data = NULL;
|
data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,61 +184,13 @@ MSHR::promoteDeferredTargets()
|
||||||
|
|
||||||
|
|
||||||
void
|
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)
|
MSHR::handleFill(Packet *pkt, CacheBlk *blk)
|
||||||
{
|
{
|
||||||
if (replacedPendingUpgrade) {
|
if (pendingShared) {
|
||||||
// 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) {
|
|
||||||
// we snooped another read while this read was in
|
// we snooped another read while this read was in
|
||||||
// service... assert shared line on its behalf
|
// service... assert shared line on its behalf
|
||||||
pkt->assertShared();
|
pkt->assertShared();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
6
src/mem/cache/miss/mshr.hh
vendored
6
src/mem/cache/miss/mshr.hh
vendored
|
@ -106,9 +106,6 @@ class MSHR : public Packet::SenderState
|
||||||
bool deferredNeedsExclusive;
|
bool deferredNeedsExclusive;
|
||||||
bool pendingInvalidate;
|
bool pendingInvalidate;
|
||||||
bool pendingShared;
|
bool pendingShared;
|
||||||
/** 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;
|
||||||
|
@ -213,8 +210,7 @@ public:
|
||||||
|
|
||||||
bool promoteDeferredTargets();
|
bool promoteDeferredTargets();
|
||||||
|
|
||||||
void handleReplacement(CacheBlk *blk, int blkSize);
|
void handleFill(Packet *pkt, CacheBlk *blk);
|
||||||
bool handleFill(Packet *pkt, CacheBlk *blk);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the contents of this MSHR to stderr.
|
* Prints the contents of this MSHR to stderr.
|
||||||
|
|
Loading…
Reference in a new issue