From 8a82553aec48029a7752f7192ca1c65236192cce Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Wed, 16 Aug 2006 15:54:02 -0400 Subject: [PATCH 1/2] Fixes for blocking in the caches that needed to be pulled src/mem/cache/base_cache.cc: Add in retry path for blocking with multi-level caches src/mem/cache/base_cache.hh: Pull more of the blocking fixes into head src/mem/packet.hh: Fix typo --HG-- extra : convert_revision : d4d149adfa414136ebd2c4789b739bb065710f7a --- src/mem/cache/base_cache.cc | 56 +++++++++++++++++++++++++++++++++++-- src/mem/cache/base_cache.hh | 24 ++++++++++------ src/mem/packet.hh | 2 +- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 9b1034577..8978fef02 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -73,6 +73,7 @@ BaseCache::CachePort::recvTiming(Packet *pkt) { if (blocked) { + DPRINTF(Cache,"Scheduling a retry while blocked\n"); mustSendRetry = true; return false; } @@ -91,21 +92,63 @@ BaseCache::CachePort::recvFunctional(Packet *pkt) cache->doFunctionalAccess(pkt, isCpuSide); } +void +BaseCache::CachePort::recvRetry() +{ + Packet *pkt; + + if (!isCpuSide) + { + pkt = cache->getPacket(); + bool success = sendTiming(pkt); + DPRINTF(Cache, "Address %x was %s in sending the timing request\n", + pkt->getAddr(), success ? "succesful" : "unsuccesful"); + cache->sendResult(pkt, success); + if (success && cache->doMasterRequest()) + { + //Still more to issue, rerequest in 1 cycle + pkt = NULL; + BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); + reqCpu->schedule(curTick + 1); + } + } + else + { + pkt = cache->getCoherencePacket(); + bool success = sendTiming(pkt); + if (success && cache->doSlaveRequest()) + { + //Still more to issue, rerequest in 1 cycle + pkt = NULL; + BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); + reqCpu->schedule(curTick + 1); + } + + } + return; +} void BaseCache::CachePort::setBlocked() { + assert(!blocked); + DPRINTF(Cache, "Cache Blocking\n"); blocked = true; + //Clear the retry flag + mustSendRetry = false; } void BaseCache::CachePort::clearBlocked() { + assert(blocked); + DPRINTF(Cache, "Cache Unblocking\n"); + blocked = false; if (mustSendRetry) { + DPRINTF(Cache, "Cache Sending Retry\n"); mustSendRetry = false; sendRetry(); } - blocked = false; } BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) @@ -128,6 +171,7 @@ BaseCache::CacheEvent::process() { if (!cachePort->isCpuSide) { + //MSHR pkt = cachePort->cache->getPacket(); bool success = cachePort->sendTiming(pkt); DPRINTF(Cache, "Address %x was %s in sending the timing request\n", @@ -142,11 +186,19 @@ BaseCache::CacheEvent::process() } else { + //CSHR pkt = cachePort->cache->getCoherencePacket(); - cachePort->sendTiming(pkt); + bool success = cachePort->sendTiming(pkt); + if (success && cachePort->cache->doSlaveRequest()) + { + //Still more to issue, rerequest in 1 cycle + pkt = NULL; + this->schedule(curTick+1); + } } return; } + //Response //Know the packet to send, no need to mark in service (must succed) bool success = cachePort->sendTiming(pkt); assert(success); diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 9fb790cee..069dbab58 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -98,6 +98,8 @@ class BaseCache : public MemObject virtual int deviceBlockSize(); + virtual void recvRetry(); + public: void setBlocked(); @@ -407,17 +409,23 @@ class BaseCache : public MemObject void clearBlocked(BlockedCause cause) { uint8_t flag = 1 << cause; - blocked &= ~flag; - blockedSnoop &= ~flag; DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", cause, blocked); - if (!isBlocked()) { - blocked_cycles[cause] += curTick - blockedCycle; - DPRINTF(Cache,"Unblocking from all causes\n"); - cpuSidePort->clearBlocked(); + if (blocked & flag) + { + blocked &= ~flag; + if (!isBlocked()) { + blocked_cycles[cause] += curTick - blockedCycle; + DPRINTF(Cache,"Unblocking from all causes\n"); + cpuSidePort->clearBlocked(); + } } - if (!isBlockedForSnoop()) { - memSidePort->clearBlocked(); + if (blockedSnoop & flag) + { + blockedSnoop &= ~flag; + if (!isBlockedForSnoop()) { + memSidePort->clearBlocked(); + } } } diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 83b4006e2..9511d43b5 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -216,7 +216,7 @@ class Packet bool isRequest() { return (cmd & IsRequest) != 0; } bool isResponse() { return (cmd & IsResponse) != 0; } bool needsResponse() { return (cmd & NeedsResponse) != 0; } - bool isInvalidate() { return (cmd * IsInvalidate) != 0; } + bool isInvalidate() { return (cmd & IsInvalidate) != 0; } bool isCacheFill() { return (flags & CACHE_LINE_FILL) != 0; } bool isNoAllocate() { return (flags & NO_ALLOCATE) != 0; } From ec0a18ffb956bbcf54b8d4d94dac7255f8868a9e Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Wed, 16 Aug 2006 15:56:22 -0400 Subject: [PATCH 2/2] Fixes for Kevins O3 model to work with the blocking caches. src/cpu/o3/fetch_impl.hh: Fix ordering so dereference works src/cpu/o3/lsq_impl.hh: Check to make sure we didn't squash already src/cpu/o3/lsq_unit.hh: Fix for counting squashed retrys in the WB count src/cpu/o3/lsq_unit_impl.hh: Make sure to set retryID for stores, and clear it appropriately --HG-- extra : convert_revision : 689765a1baea7b36f13eb177d65e97b52b6da09f --- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/o3/lsq_impl.hh | 5 +++++ src/cpu/o3/lsq_unit.hh | 2 ++ src/cpu/o3/lsq_unit_impl.hh | 2 ++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 990db88ac..25be9d455 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -672,9 +672,9 @@ DefaultFetch::doSquash(const Addr &new_PC, unsigned tid) assert(cacheBlocked); cacheBlocked = false; retryTid = -1; - retryPkt = NULL; delete retryPkt->req; delete retryPkt; + retryPkt = NULL; } fetchStatus[tid] = Squashing; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index db2c253e1..2bbab71f0 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -71,6 +71,11 @@ template void LSQ::DcachePort::recvRetry() { + if (lsq->retryTid == -1) + { + //Squashed, so drop it + return; + } lsq->thread[lsq->retryTid].recvRetry(); // Speculatively clear the retry Tid. This will get set again if // the LSQUnit was unable to complete its access. diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 512b5a63c..1358a3699 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -646,6 +646,8 @@ LSQUnit::read(Request *req, T &data, int load_idx) // handle it. if (lsq->cacheBlocked()) { ++lsqCacheBlocked; + + iewStage->decrWb(load_inst->seqNum); // There's an older load that's already going to squash. if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) return NoFault; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 4f5dbbf1c..fa716c712 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -626,6 +626,7 @@ LSQUnit::writebackStores() ++lsqCacheBlocked; assert(retryPkt == NULL); retryPkt = data_pkt; + lsq->setRetryTid(lsqID); } else { storePostSend(data_pkt); } @@ -869,6 +870,7 @@ LSQUnit::recvRetry() storePostSend(retryPkt); retryPkt = NULL; isStoreBlocked = false; + lsq->setRetryTid(-1); } else { // Still blocked! ++lsqCacheBlocked;