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);
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);
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()*/] +=
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",
- repl_addr, addr, blk->isDirty() ? "writeback" : "clean");
+ // 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");
- 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));
+ }
}
}
deferredNeedsExclusive = false;
pendingInvalidate = false;
pendingShared = false;
- replacedPendingUpgrade = false;
data = NULL;
}
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;
}
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;
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.