summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/o3/fetch_impl.hh2
-rw-r--r--src/cpu/o3/lsq_impl.hh5
-rw-r--r--src/cpu/o3/lsq_unit.hh2
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh2
-rw-r--r--src/mem/cache/base_cache.cc56
-rw-r--r--src/mem/cache/base_cache.hh24
-rw-r--r--src/mem/packet.hh2
7 files changed, 81 insertions, 12 deletions
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<Impl>::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 <class Impl>
void
LSQ<Impl>::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<Impl>::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<Impl>::writebackStores()
++lsqCacheBlocked;
assert(retryPkt == NULL);
retryPkt = data_pkt;
+ lsq->setRetryTid(lsqID);
} else {
storePostSend(data_pkt);
}
@@ -869,6 +870,7 @@ LSQUnit<Impl>::recvRetry()
storePostSend(retryPkt);
retryPkt = NULL;
isStoreBlocked = false;
+ lsq->setRetryTid(-1);
} else {
// Still blocked!
++lsqCacheBlocked;
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;
}
@@ -92,20 +93,62 @@ BaseCache::CachePort::recvFunctional(Packet *pkt)
}
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 9e961b0dc..c8b0cdaed 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -217,7 +217,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; }