Merge zizzer:/bk/newmem
[gem5.git] / src / mem / cache / cache_impl.hh
index 18f56b1ba98eaac37ab784101d52c414f19536fe..df59b0a4ff95352b71660b807bfe3933f7ac074b 100644 (file)
 
 #include "sim/sim_exit.hh" // for SimExitEvent
 
+bool SIGNAL_NACK_HACK;
+
 template<class TagStore, class Buffering, class Coherence>
 bool
 Cache<TagStore,Buffering,Coherence>::
-doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide)
+doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide)
 {
     if (isCpuSide)
     {
@@ -82,7 +84,7 @@ doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide)
 template<class TagStore, class Buffering, class Coherence>
 Tick
 Cache<TagStore,Buffering,Coherence>::
-doAtomicAccess(Packet *pkt, bool isCpuSide)
+doAtomicAccess(PacketPtr pkt, bool isCpuSide)
 {
     if (isCpuSide)
     {
@@ -104,7 +106,7 @@ doAtomicAccess(Packet *pkt, bool isCpuSide)
 template<class TagStore, class Buffering, class Coherence>
 void
 Cache<TagStore,Buffering,Coherence>::
-doFunctionalAccess(Packet *pkt, bool isCpuSide)
+doFunctionalAccess(PacketPtr pkt, bool isCpuSide)
 {
     if (isCpuSide)
     {
@@ -205,9 +207,10 @@ Cache<TagStore,Buffering,Coherence>::access(PacketPtr &pkt)
         missQueue->doWriteback(writebacks.front());
         writebacks.pop_front();
     }
-    DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(),
-            pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",
-            pkt->getAddr() & ~((Addr)blkSize - 1));
+
+    DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(),
+            (blk) ? "hit" : "miss");
+
     if (blk) {
         // Hit
         hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
@@ -231,18 +234,31 @@ Cache<TagStore,Buffering,Coherence>::access(PacketPtr &pkt)
                 exitSimLoop("A cache reached the maximum miss count");
         }
     }
-    missQueue->handleMiss(pkt, size, curTick + hitLatency);
-//    return MA_CACHE_MISS;
+
+    if (pkt->flags & SATISFIED) {
+        // happens when a store conditional fails because it missed
+        // the cache completely
+        if (pkt->needsResponse())
+            respond(pkt, curTick+lat);
+    } else {
+        missQueue->handleMiss(pkt, size, curTick + hitLatency);
+    }
+
+    if (pkt->cmd == Packet::Writeback) {
+        //Need to clean up the packet on a writeback miss, but leave the request
+        delete pkt;
+    }
+
     return true;
 }
 
 
 template<class TagStore, class Buffering, class Coherence>
-Packet *
+PacketPtr
 Cache<TagStore,Buffering,Coherence>::getPacket()
 {
     assert(missQueue->havePending());
-    Packet * pkt = missQueue->getPacket();
+    PacketPtr pkt = missQueue->getPacket();
     if (pkt) {
         if (!pkt->req->isUncacheable()) {
             if (pkt->cmd == Packet::HardPFReq)
@@ -256,6 +272,7 @@ Cache<TagStore,Buffering,Coherence>::getPacket()
 
     assert(!doMasterRequest() || missQueue->havePending());
     assert(!pkt || pkt->time <= curTick);
+    SIGNAL_NACK_HACK = false;
     return pkt;
 }
 
@@ -264,26 +281,23 @@ void
 Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
                                                 bool success)
 {
-    if (success && !(pkt && (pkt->flags & NACKED_LINE))) {
-        if (!mshr->pkt->needsResponse()
-            && !(mshr->pkt->cmd == Packet::UpgradeReq)
-            && (pkt && (pkt->flags & SATISFIED))) {
-            //Writeback, clean up the non copy version of the packet
-            delete pkt;
-        }
+    if (success && !(SIGNAL_NACK_HACK)) {
+        //Remember if it was an upgrade because writeback MSHR's are removed
+        //in Mark in Service
+        bool upgrade = (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq);
+
         missQueue->markInService(mshr->pkt, mshr);
+
         //Temp Hack for UPGRADES
-        if (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq) {
+        if (upgrade) {
             assert(pkt);  //Upgrades need to be fixed
             pkt->flags &= ~CACHE_LINE_FILL;
             BlkType *blk = tags->findBlock(pkt);
             CacheBlk::State old_state = (blk) ? blk->status : 0;
             CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
             if (old_state != new_state)
-                DPRINTF(Cache, "Block for blk addr %x moving from "
-                        "state %i to %i\n",
-                        pkt->getAddr() & (((ULL(1))<<48)-1),
-                        old_state, new_state);
+                DPRINTF(Cache, "Block for blk addr %x moving from state "
+                        "%i to %i\n", pkt->getAddr(), old_state, new_state);
             //Set the state on the upgrade
             memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
             PacketList writebacks;
@@ -293,6 +307,7 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
         }
     } else if (pkt && !pkt->req->isUncacheable()) {
         pkt->flags &= ~NACKED_LINE;
+        SIGNAL_NACK_HACK = false;
         pkt->flags &= ~SATISFIED;
         pkt->flags &= ~SNOOP_COMMIT;
 
@@ -306,7 +321,7 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
 
 template<class TagStore, class Buffering, class Coherence>
 void
-Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt)
+Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt)
 {
     BlkType *blk = NULL;
     if (pkt->senderState) {
@@ -323,10 +338,11 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt)
             //Make the response a Bad address and send it
         }
 //     MemDebug::cacheResponse(pkt);
-        DPRINTF(Cache, "Handling reponse to %x, blk addr: %x\n",pkt->getAddr(),
-                pkt->getAddr() & (((ULL(1))<<48)-1));
+        DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr());
 
         if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
+            DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
+                    pkt->getAddr());
             blk = tags->findBlock(pkt);
             CacheBlk::State old_state = (blk) ? blk->status : 0;
             PacketList writebacks;
@@ -334,7 +350,7 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt)
             if (old_state != new_state)
                 DPRINTF(Cache, "Block for blk addr %x moving from "
                         "state %i to %i\n",
-                        pkt->getAddr() & (((ULL(1))<<48)-1),
+                        pkt->getAddr(),
                         old_state, new_state);
             blk = tags->handleFill(blk, (MSHR*)pkt->senderState,
                                    new_state, writebacks, pkt);
@@ -348,7 +364,7 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt)
 }
 
 template<class TagStore, class Buffering, class Coherence>
-Packet *
+PacketPtr
 Cache<TagStore,Buffering,Coherence>::getCoherencePacket()
 {
     return coherence->getPacket();
@@ -356,7 +372,7 @@ Cache<TagStore,Buffering,Coherence>::getCoherencePacket()
 
 template<class TagStore, class Buffering, class Coherence>
 void
-Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(Packet* &pkt,
+Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(PacketPtr &pkt,
                                                          MSHR *cshr,
                                                          bool success)
 {
@@ -366,7 +382,7 @@ Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(Packet* &pkt,
 
 template<class TagStore, class Buffering, class Coherence>
 void
-Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
+Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
 {
     if (pkt->req->isUncacheable()) {
         //Can't get a hit on an uncacheable address
@@ -396,6 +412,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
                     assert(!(pkt->flags & SATISFIED));
                     pkt->flags |= SATISFIED;
                     pkt->flags |= NACKED_LINE;
+                    SIGNAL_NACK_HACK = true;
                     ///@todo NACK's from other levels
                     //warn("NACKs from devices not connected to the same bus "
                     //"not implemented\n");
@@ -419,8 +436,8 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
 
                     //Append the invalidate on
                     missQueue->addTarget(mshr,invalidatePkt);
-                    DPRINTF(Cache, "Appending Invalidate to blk_addr: %x\n",
-                            pkt->getAddr() & (((ULL(1))<<48)-1));
+                    DPRINTF(Cache, "Appending Invalidate to addr: %x\n",
+                            pkt->getAddr());
                     return;
                 }
             }
@@ -428,8 +445,8 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
         //We also need to check the writeback buffers and handle those
         std::vector<MSHR *> writebacks;
         if (missQueue->findWrites(blk_addr, writebacks)) {
-            DPRINTF(Cache, "Snoop hit in writeback to blk_addr: %x\n",
-                    pkt->getAddr() & (((ULL(1))<<48)-1));
+            DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n",
+                    pkt->getAddr());
 
             //Look through writebacks for any non-uncachable writes, use that
             for (int i=0; i<writebacks.size(); i++) {
@@ -468,6 +485,13 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
     }
     CacheBlk::State new_state;
     bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state);
+
+    if (blk && mshr && !mshr->inService && new_state == 0) {
+            //There was a outstanding write to a shared block, not need ReadEx
+            //not update, so change No Allocate param in MSHR
+            mshr->pkt->flags &= ~NO_ALLOCATE;
+    }
+
     if (satisfy) {
         DPRINTF(Cache, "Cache snooped a %s request for addr %x and "
                 "now supplying data, new state is %i\n",
@@ -480,12 +504,13 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
     if (blk)
         DPRINTF(Cache, "Cache snooped a %s request for addr %x, "
                 "new state is %i\n", pkt->cmdString(), blk_addr, new_state);
+
     tags->handleSnoop(blk, new_state);
 }
 
 template<class TagStore, class Buffering, class Coherence>
 void
-Cache<TagStore,Buffering,Coherence>::snoopResponse(Packet * &pkt)
+Cache<TagStore,Buffering,Coherence>::snoopResponse(PacketPtr &pkt)
 {
     //Need to handle the response, if NACKED
     if (pkt->flags & NACKED_LINE) {
@@ -515,25 +540,22 @@ Cache<TagStore,Buffering,Coherence>::invalidateBlk(Addr addr)
  */
 template<class TagStore, class Buffering, class Coherence>
 Tick
-Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update,
+Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update,
                                            CachePort* otherSidePort)
 {
 //    MemDebug::cacheProbe(pkt);
     if (!pkt->req->isUncacheable()) {
-        if (pkt->isInvalidate() && !pkt->isRead()
-            && !pkt->isWrite()) {
+        if (pkt->isInvalidate() && !pkt->isRead() && !pkt->isWrite()) {
             //Upgrade or Invalidate, satisfy it, don't forward
-            DPRINTF(Cache, "%s %x ? blk_addr: %x\n", pkt->cmdString(),
-                    pkt->getAddr() & (((ULL(1))<<48)-1),
-                    pkt->getAddr() & ~((Addr)blkSize - 1));
+            DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr());
             pkt->flags |= SATISFIED;
             return 0;
         }
     }
 
-    if (!update && (pkt->isWrite() || (otherSidePort == cpuSidePort))) {
+    if (!update && (otherSidePort == cpuSidePort)) {
         // Still need to change data in all locations.
-        otherSidePort->sendFunctional(pkt);
+        otherSidePort->checkAndSendFunctional(pkt);
         if (pkt->isRead() && pkt->result == Packet::Success)
             return 0;
     }
@@ -542,9 +564,8 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update,
     int lat;
     BlkType *blk = tags->handleAccess(pkt, lat, writebacks, update);
 
-    DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(),
-            pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",
-            pkt->getAddr() & ~((Addr)blkSize - 1));
+    DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(),
+            pkt->getAddr(), (blk) ? "hit" : "miss");
 
 
     // Need to check for outstanding misses and writes
@@ -558,84 +579,40 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update,
     missQueue->findWrites(blk_addr, writes);
 
     if (!update) {
+        bool notDone = !(pkt->flags & SATISFIED); //Hit in cache (was a block)
         // Check for data in MSHR and writebuffer.
         if (mshr) {
-            warn("Found outstanding miss on an non-update probe");
             MSHR::TargetList *targets = mshr->getTargetList();
             MSHR::TargetList::iterator i = targets->begin();
             MSHR::TargetList::iterator end = targets->end();
-            for (; i != end; ++i) {
-                Packet * target = *i;
+            for (; i != end && notDone; ++i) {
+                PacketPtr target = *i;
                 // If the target contains data, and it overlaps the
                 // probed request, need to update data
-                if (target->isWrite() && target->intersect(pkt)) {
-                    uint8_t* pkt_data;
-                    uint8_t* write_data;
-                    int data_size;
-                    if (target->getAddr() < pkt->getAddr()) {
-                        int offset = pkt->getAddr() - target->getAddr();
-                        pkt_data = pkt->getPtr<uint8_t>();
-                        write_data = target->getPtr<uint8_t>() + offset;
-                        data_size = target->getSize() - offset;
-                        assert(data_size > 0);
-                        if (data_size > pkt->getSize())
-                            data_size = pkt->getSize();
-                    } else {
-                        int offset = target->getAddr() - pkt->getAddr();
-                        pkt_data = pkt->getPtr<uint8_t>() + offset;
-                        write_data = target->getPtr<uint8_t>();
-                        data_size = pkt->getSize() - offset;
-                        assert(data_size > pkt->getSize());
-                        if (data_size > target->getSize())
-                            data_size = target->getSize();
-                    }
-
-                    if (pkt->isWrite()) {
-                        memcpy(pkt_data, write_data, data_size);
-                    } else {
-                        memcpy(write_data, pkt_data, data_size);
-                    }
+                if (target->intersect(pkt)) {
+                    DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a MSHR\n",
+                            pkt->cmdString(), blk_addr);
+                    notDone = fixPacket(pkt, target);
                 }
             }
         }
-        for (int i = 0; i < writes.size(); ++i) {
-            Packet * write = writes[i]->pkt;
+        for (int i = 0; i < writes.size() && notDone; ++i) {
+            PacketPtr write = writes[i]->pkt;
             if (write->intersect(pkt)) {
-                warn("Found outstanding write on an non-update probe");
-                uint8_t* pkt_data;
-                uint8_t* write_data;
-                int data_size;
-                if (write->getAddr() < pkt->getAddr()) {
-                    int offset = pkt->getAddr() - write->getAddr();
-                    pkt_data = pkt->getPtr<uint8_t>();
-                    write_data = write->getPtr<uint8_t>() + offset;
-                    data_size = write->getSize() - offset;
-                    assert(data_size > 0);
-                    if (data_size > pkt->getSize())
-                        data_size = pkt->getSize();
-                } else {
-                    int offset = write->getAddr() - pkt->getAddr();
-                    pkt_data = pkt->getPtr<uint8_t>() + offset;
-                    write_data = write->getPtr<uint8_t>();
-                    data_size = pkt->getSize() - offset;
-                    assert(data_size > pkt->getSize());
-                    if (data_size > write->getSize())
-                        data_size = write->getSize();
-                }
-
-                if (pkt->isWrite()) {
-                    memcpy(pkt_data, write_data, data_size);
-                } else {
-                    memcpy(write_data, pkt_data, data_size);
-                }
-
+                DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a writeback\n",
+                        pkt->cmdString(), blk_addr);
+                notDone = fixPacket(pkt, write);
             }
         }
+        if (notDone && otherSidePort == memSidePort) {
+            otherSidePort->checkAndSendFunctional(pkt);
+            assert(pkt->result == Packet::Success);
+        }
         return 0;
-    } else if (!blk) {
+    } else if (!blk && !(pkt->flags & SATISFIED)) {
         // update the cache state and statistics
         if (mshr || !writes.empty()){
-            // Can't handle it, return pktuest unsatisfied.
+            // Can't handle it, return request unsatisfied.
             panic("Atomic access ran into outstanding MSHR's or WB's!");
         }
         if (!pkt->req->isUncacheable()) {
@@ -644,16 +621,14 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update,
             Packet::Command temp_cmd = coherence->getBusCmd(pkt->cmd,
                                                             (blk)? blk->status : 0);
 
-            Packet * busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize);
+            PacketPtr busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize);
 
             busPkt->allocate();
 
             busPkt->time = curTick;
 
-            DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n",
-                    busPkt->cmdString(),
-                    busPkt->getAddr() & (((ULL(1))<<48)-1),
-                    busPkt->getAddr() & ~((Addr)blkSize - 1));
+            DPRINTF(Cache, "Sending a atomic %s for %x\n",
+                    busPkt->cmdString(), busPkt->getAddr());
 
             lat = memSidePort->sendAtomic(busPkt);
 
@@ -672,25 +647,19 @@ return 0;
             CacheBlk::State old_state = (blk) ? blk->status : 0;
             CacheBlk::State new_state =
                 coherence->getNewState(busPkt, old_state);
-            DPRINTF(Cache,
-                        "Receive response:%s for blk addr %x in state %i\n",
-                    busPkt->cmdString(),
-                    busPkt->getAddr() & (((ULL(1))<<48)-1), old_state);
+            DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
+                    busPkt->cmdString(), busPkt->getAddr(), old_state);
             if (old_state != new_state)
-                    DPRINTF(Cache, "Block for blk addr %x moving from "
-                            "state %i to %i\n",
-                            busPkt->getAddr() & (((ULL(1))<<48)-1),
-                            old_state, new_state);
-
-            tags->handleFill(blk, busPkt,
-                             new_state,
-                             writebacks, pkt);
+                DPRINTF(Cache, "Block for blk addr %x moving from state "
+                        "%i to %i\n", busPkt->getAddr(), old_state, new_state);
+
+            tags->handleFill(blk, busPkt, new_state, writebacks, pkt);
             //Free the packet
             delete busPkt;
 
             // Handle writebacks if needed
             while (!writebacks.empty()){
-                Packet *wbPkt = writebacks.front();
+                PacketPtr wbPkt = writebacks.front();
                 memSidePort->sendAtomic(wbPkt);
                 writebacks.pop_front();
                 delete wbPkt;
@@ -700,18 +669,20 @@ return 0;
             return memSidePort->sendAtomic(pkt);
         }
     } else {
-        // There was a cache hit.
-        // Handle writebacks if needed
-        while (!writebacks.empty()){
-            memSidePort->sendAtomic(writebacks.front());
-            writebacks.pop_front();
-        }
+        if (blk) {
+            // There was a cache hit.
+            // Handle writebacks if needed
+            while (!writebacks.empty()){
+                memSidePort->sendAtomic(writebacks.front());
+                writebacks.pop_front();
+            }
 
-        hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+            hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+        }
 
         return hitLatency;
     }
-    fatal("Probe not handled.\n");
+
     return 0;
 }
 
@@ -720,7 +691,7 @@ Tick
 Cache<TagStore,Buffering,Coherence>::snoopProbe(PacketPtr &pkt)
 {
     //Send a atomic (false) invalidate up if the protocol calls for it
-    coherence->propogateInvalidate(pkt, true);
+    coherence->propogateInvalidate(pkt, false);
 
     Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
     BlkType *blk = tags->findBlock(pkt);