summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Reinhardt <stever@eecs.umich.edu>2007-07-17 06:33:28 -0700
committerSteve Reinhardt <stever@eecs.umich.edu>2007-07-17 06:33:28 -0700
commita25f3ac67f9c467cf945b45fbc0f4e587e640cab (patch)
tree9fabcc4277726eee2c93dfa755d83c7246fb383a
parentff13827ccb559890f05b2e1d97bc6ecf86f9dd16 (diff)
downloadgem5-a25f3ac67f9c467cf945b45fbc0f4e587e640cab.tar.xz
Forward cache-to-cache responses through other caches.
--HG-- extra : convert_revision : 5b6a02255bccd98b00949703cf4ba4b221553cea
-rw-r--r--src/mem/cache/cache_impl.hh56
1 files changed, 49 insertions, 7 deletions
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 59571dd6f..c069d8ba9 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -315,6 +315,29 @@ Cache<TagStore>::access(PacketPtr pkt, BlkType *&blk, int &lat)
}
+class ForwardResponseRecord : public Packet::SenderState
+{
+ Packet::SenderState *prevSenderState;
+ int prevSrc;
+#ifndef NDEBUG
+ BaseCache *cache;
+#endif
+ public:
+ ForwardResponseRecord(Packet *pkt, BaseCache *_cache)
+ : prevSenderState(pkt->senderState), prevSrc(pkt->getSrc())
+#ifndef NDEBUG
+ , cache(_cache)
+#endif
+ {}
+ void restore(Packet *pkt, BaseCache *_cache)
+ {
+ assert(_cache == cache);
+ pkt->senderState = prevSenderState;
+ pkt->setDest(prevSrc);
+ }
+};
+
+
template<class TagStore>
bool
Cache<TagStore>::timingAccess(PacketPtr pkt)
@@ -325,6 +348,19 @@ Cache<TagStore>::timingAccess(PacketPtr pkt)
// we charge hitLatency for doing just about anything here
Tick time = curTick + hitLatency;
+ if (pkt->isResponse()) {
+ // must be cache-to-cache response from upper to lower level
+ ForwardResponseRecord *rec =
+ dynamic_cast<ForwardResponseRecord *>(pkt->senderState);
+ assert(rec != NULL);
+ rec->restore(pkt, this);
+ delete rec;
+ memSidePort->respond(pkt, time);
+ return true;
+ }
+
+ assert(pkt->isRequest());
+
if (pkt->memInhibitAsserted()) {
DPRINTF(Cache, "mem inhibited on 0x%x: not responding\n",
pkt->getAddr());
@@ -392,6 +428,8 @@ Cache<TagStore>::timingAccess(PacketPtr pkt)
if (needsResponse) {
pkt->makeTimingResponse();
cpuSidePort->respond(pkt, curTick+lat);
+ } else {
+ delete pkt;
}
} else {
// miss
@@ -424,12 +462,6 @@ Cache<TagStore>::timingAccess(PacketPtr pkt)
}
}
- if (!needsResponse) {
- // Need to clean up the packet on a writeback miss, but leave
- // the request for the next level.
- delete pkt;
- }
-
return true;
}
@@ -872,7 +904,14 @@ Cache<TagStore>::doTimingSupplyResponse(PacketPtr req_pkt,
{
// timing-mode snoop responses require a new packet, unless we
// already made a copy...
- PacketPtr pkt = already_copied ? req_pkt : new Packet(req_pkt);
+ PacketPtr pkt = already_copied ? req_pkt : new Packet(req_pkt, true);
+ if (!req_pkt->isInvalidate()) {
+ // note that we're ignoring the shared flag on req_pkt... it's
+ // basically irrelveant, as we'll always assert shared unless
+ // it's an exclusive request, in which case the shared line
+ // should never be asserted1
+ pkt->assertShared();
+ }
pkt->allocate();
pkt->makeTimingResponse();
pkt->setDataFromBlock(blk_data, blkSize);
@@ -894,11 +933,14 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk,
if (is_timing) {
Packet *snoopPkt = new Packet(pkt, true); // clear flags
snoopPkt->setExpressSnoop();
+ snoopPkt->senderState = new ForwardResponseRecord(pkt, this);
cpuSidePort->sendTiming(snoopPkt);
if (snoopPkt->memInhibitAsserted()) {
// cache-to-cache response from some upper cache
assert(!alreadySupplied);
pkt->assertMemInhibit();
+ } else {
+ delete snoopPkt->senderState;
}
if (snoopPkt->sharedAsserted()) {
pkt->assertShared();