Cache: Refactor packet forwarding a bit.
authorSteve Reinhardt <Steve.Reinhardt@amd.com>
Mon, 10 Nov 2008 22:10:28 +0000 (14:10 -0800)
committerSteve Reinhardt <Steve.Reinhardt@amd.com>
Mon, 10 Nov 2008 22:10:28 +0000 (14:10 -0800)
Makes adding write-through operations easier.

src/mem/cache/cache_impl.hh
src/mem/cache/mshr.cc
src/mem/cache/mshr.hh

index 40d1c9c2f974565776468c7c00f53fce83ee3f78..c4a19ad5cd4dbcad673fcbafa7df7cba42a1f76e 100644 (file)
@@ -613,38 +613,53 @@ Cache<TagStore>::atomicAccess(PacketPtr pkt)
 
     if (!access(pkt, blk, lat, writebacks)) {
         // MISS
-        PacketPtr busPkt = getBusPacket(pkt, blk, pkt->needsExclusive());
+        PacketPtr bus_pkt = getBusPacket(pkt, blk, pkt->needsExclusive());
 
-        bool isCacheFill = (busPkt != NULL);
+        bool is_forward = (bus_pkt == NULL);
 
-        if (busPkt == NULL) {
+        if (is_forward) {
             // just forwarding the same request to the next level
             // no local cache operation involved
-            busPkt = pkt;
+            bus_pkt = pkt;
         }
 
         DPRINTF(Cache, "Sending an atomic %s for %x\n",
-                busPkt->cmdString(), busPkt->getAddr());
+                bus_pkt->cmdString(), bus_pkt->getAddr());
 
 #if TRACING_ON
         CacheBlk::State old_state = blk ? blk->status : 0;
 #endif
 
-        lat += memSidePort->sendAtomic(busPkt);
+        lat += memSidePort->sendAtomic(bus_pkt);
 
         DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
-                busPkt->cmdString(), busPkt->getAddr(), old_state);
-
-        bool is_error = busPkt->isError();
-        assert(!busPkt->wasNacked());
-
-        if (is_error && pkt->needsResponse()) {
-            pkt->makeAtomicResponse();
-            pkt->copyError(busPkt);
-        } else if (isCacheFill && !is_error) {
-            blk = handleFill(busPkt, blk, writebacks);
-            satisfyCpuSideRequest(pkt, blk);
-            delete busPkt;
+                bus_pkt->cmdString(), bus_pkt->getAddr(), old_state);
+
+        assert(!bus_pkt->wasNacked());
+
+        // If packet was a forward, the response (if any) is already
+        // in place in the bus_pkt == pkt structure, so we don't need
+        // to do anything.  Otherwise, use the separate bus_pkt to
+        // generate response to pkt and then delete it.
+        if (!is_forward) {
+            if (pkt->needsResponse()) {
+                assert(bus_pkt->isResponse());
+                if (bus_pkt->isError()) {
+                    pkt->makeAtomicResponse();
+                    pkt->copyError(bus_pkt);
+                } else if (bus_pkt->isRead() ||
+                           bus_pkt->cmd == MemCmd::UpgradeResp) {
+                    // we're updating cache state to allow us to
+                    // satisfy the upstream request from the cache
+                    blk = handleFill(bus_pkt, blk, writebacks);
+                    satisfyCpuSideRequest(pkt, blk);
+                } else {
+                    // we're satisfying the upstream request without
+                    // modifying cache state, e.g., a write-through
+                    pkt->makeAtomicResponse();
+                }
+            }
+            delete bus_pkt;
         }
     }
 
@@ -748,7 +763,10 @@ Cache<TagStore>::handleResponse(PacketPtr pkt)
             miss_latency;
     }
 
-    if (mshr->isCacheFill && !is_error) {
+    bool is_fill = !mshr->isForward &&
+        (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp);
+
+    if (is_fill && !is_error) {
         DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
                 pkt->getAddr());
 
@@ -771,7 +789,7 @@ Cache<TagStore>::handleResponse(PacketPtr pkt)
 
         if (target->isCpuSide()) {
             Tick completion_time;
-            if (blk != NULL) {
+            if (is_fill) {
                 satisfyCpuSideRequest(target->pkt, blk);
                 // How many bytes past the first request is this one
                 int transfer_offset =
@@ -1287,7 +1305,7 @@ Cache<TagStore>::getTimingPacket()
     PacketPtr tgt_pkt = mshr->getTarget()->pkt;
     PacketPtr pkt = NULL;
 
-    if (mshr->isSimpleForward()) {
+    if (mshr->isForwardNoResponse()) {
         // no response expected, just forward packet as it is
         assert(tags->findBlock(mshr->addr) == NULL);
         pkt = tgt_pkt;
@@ -1295,11 +1313,10 @@ Cache<TagStore>::getTimingPacket()
         BlkType *blk = tags->findBlock(mshr->addr);
         pkt = getBusPacket(tgt_pkt, blk, mshr->needsExclusive());
 
-        mshr->isCacheFill = (pkt != NULL);
+        mshr->isForward = (pkt == NULL);
 
-        if (pkt == NULL) {
+        if (mshr->isForward) {
             // not a cache block request, but a response is expected
-            assert(!mshr->isSimpleForward());
             // make copy of current packet to forward, keep current
             // copy for response handling
             pkt = new Packet(tgt_pkt);
@@ -1473,7 +1490,7 @@ Cache<TagStore>::MemSidePort::sendPacket()
             waitingOnRetry = !success;
             if (waitingOnRetry) {
                 DPRINTF(CachePort, "now waiting on a retry\n");
-                if (!mshr->isSimpleForward()) {
+                if (!mshr->isForwardNoResponse()) {
                     delete pkt;
                 }
             } else {
index 6537f63439f5bc1cbd86577534e44591463f5fea..04b2b8d770cf6fb3a8b586daef3fe8e986ad20ea 100644 (file)
@@ -156,7 +156,7 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target,
     readyTime = whenReady;
     order = _order;
     assert(target);
-    isCacheFill = false;
+    isForward = false;
     _isUncacheable = target->req->isUncacheable();
     inService = false;
     downstreamPending = false;
@@ -187,7 +187,7 @@ bool
 MSHR::markInService()
 {
     assert(!inService);
-    if (isSimpleForward()) {
+    if (isForwardNoResponse()) {
         // we just forwarded the request packet & don't expect a
         // response, so get rid of it
         assert(getNumTargets() == 1);
@@ -403,7 +403,8 @@ MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
 {
     ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
              prefix, addr, addr+size-1,
-             isCacheFill ? "Fill" : "",
+             isForward ? "Forward" : "",
+             isForwardNoResponse() ? "ForwNoResp" : "",
              needsExclusive() ? "Excl" : "",
              _isUncacheable ? "Unc" : "",
              inService ? "InSvc" : "",
index fdb0485cb5d61f9e772ee1e6a7076e973c8ddbbb..2ff1c2489890bb2a3721f1eabfe9c3c542e75b20 100644 (file)
@@ -118,8 +118,8 @@ class MSHR : public Packet::SenderState, public Printable
     /** True if the request has been sent to the bus. */
     bool inService;
 
-    /** True if we will be putting the returned block in the cache */
-    bool isCacheFill;
+    /** True if the request is just a simple forward from an upper level */
+    bool isForward;
 
     /** True if we need to get an exclusive copy of the block. */
     bool needsExclusive() const { return targets->needsExclusive; }
@@ -200,7 +200,7 @@ public:
      * Returns the current number of allocated targets.
      * @return The current number of allocated targets.
      */
-    int getNumTargets() { return ntargets; }
+    int getNumTargets() const { return ntargets; }
 
     /**
      * Returns a pointer to the target list.
@@ -212,13 +212,17 @@ public:
      * Returns true if there are targets left.
      * @return true if there are targets
      */
-    bool hasTargets() { return !targets->empty(); }
+    bool hasTargets() const { return !targets->empty(); }
 
     /**
      * Returns a reference to the first target.
      * @return A pointer to the first target.
      */
-    Target *getTarget() { assert(hasTargets());  return &targets->front(); }
+    Target *getTarget() const
+    {
+        assert(hasTargets());
+        return &targets->front();
+    }
 
     /**
      * Pop first target.
@@ -229,7 +233,7 @@ public:
         targets->pop_front();
     }
 
-    bool isSimpleForward()
+    bool isForwardNoResponse() const
     {
         if (getNumTargets() != 1)
             return false;