diff options
Diffstat (limited to 'src/mem/cache/miss')
-rw-r--r-- | src/mem/cache/miss/mshr.cc | 53 | ||||
-rw-r--r-- | src/mem/cache/miss/mshr.hh | 11 |
2 files changed, 64 insertions, 0 deletions
diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index fc8d2175e..ca5e38601 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -75,6 +75,8 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target, assert(deferredTargets.empty()); deferredNeedsExclusive = false; pendingInvalidate = false; + replacedPendingUpgrade = false; + data = NULL; } void @@ -171,6 +173,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 MSHR::dump() { ccprintf(cerr, diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index 92288cf52..a9380d99a 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -105,12 +105,20 @@ class MSHR : public Packet::SenderState bool deferredNeedsExclusive; bool pendingInvalidate; + /** Is there a pending upgrade that got replaced? */ + bool replacedPendingUpgrade; + bool replacedPendingUpgradeDirty; /** Thread number of the miss. */ short threadNum; /** The number of currently allocated targets. */ short ntargets; + + /** Data buffer (if needed). Currently used only for pending + * upgrade handling. */ + uint8_t *data; + /** * Pointer to this MSHR on the ready list. * @sa MissQueue, MSHRQueue::readyList @@ -204,6 +212,9 @@ public: bool promoteDeferredTargets(); + void handleReplacement(CacheBlk *blk, int blkSize); + bool handleReplacedPendingUpgrade(Packet *pkt); + /** * Prints the contents of this MSHR to stderr. */ |