summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSteve Reinhardt <stever@eecs.umich.edu>2007-06-26 23:30:30 -0700
committerSteve Reinhardt <stever@eecs.umich.edu>2007-06-26 23:30:30 -0700
commitc4903e088247ad187356864459d2e4be77d97154 (patch)
tree195ce9d5e233e3bb437d6a1222fb4c464226ca41 /src
parent1b20df5607e86d3b384716792274fe01fa4f3f80 (diff)
downloadgem5-c4903e088247ad187356864459d2e4be77d97154.tar.xz
Revamp replacement-of-upgrade handling.
--HG-- extra : convert_revision : 9bc09d8ae6d50e6dfbb4ab21514612f9aa102a2e
Diffstat (limited to 'src')
-rw-r--r--src/mem/cache/cache.hh3
-rw-r--r--src/mem/cache/cache_impl.hh44
-rw-r--r--src/mem/cache/miss/mshr.cc51
-rw-r--r--src/mem/cache/miss/mshr.hh6
4 files changed, 36 insertions, 68 deletions
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 161fb801d..9e8c35066 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -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.
*/
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 599eecc82..3685bc8cb 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -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);
- }
-
- 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));
+ }
}
}
diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc
index 23645cb27..63b3cacc2 100644
--- a/src/mem/cache/miss/mshr.cc
+++ b/src/mem/cache/miss/mshr.cc
@@ -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;
}
diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh
index 07fe5c96c..4db7b1cfe 100644
--- a/src/mem/cache/miss/mshr.hh
+++ b/src/mem/cache/miss/mshr.hh
@@ -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.