First Pass At Cmp/Swap in caches
authorRon Dreslinski <rdreslin@umich.edu>
Tue, 27 Mar 2007 22:05:25 +0000 (17:05 -0500)
committerRon Dreslinski <rdreslin@umich.edu>
Tue, 27 Mar 2007 22:05:25 +0000 (17:05 -0500)
--HG--
extra : convert_revision : 211bfb7c6a59e9e120dae1600d4754baaf231332

src/mem/cache/cache.hh
src/mem/cache/cache_impl.hh
src/mem/cache/coherence/coherence_protocol.cc

index 722ce216b5768f70a2d3e6227454b60dbbbfc381..3e45c85d2fc3cd86f4109838220bb6971ca5b058 100644 (file)
@@ -227,6 +227,12 @@ class Cache : public BaseCache
     BlkType* handleAccess(PacketPtr &pkt, int & lat,
                           PacketList & writebacks, bool update = true);
 
+
+    /**
+     *Handle doing the Compare and Swap function for SPARC.
+     */
+    void cmpAndSwap(BlkType *blk, PacketPtr &pkt);
+
     /**
      * Populates a cache block and handles all outstanding requests for the
      * satisfied fill request. This version takes an MSHR pointer and uses its
index 5c6ab0950ba13593c3b69f2beabe092c36f6285e..9368e76486e2b5301b73a5229909f6760d1bddf8 100644 (file)
@@ -122,12 +122,15 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
     if (blk != NULL) {
 
         if (!update) {
+
             if (pkt->isWrite()){
                 assert(offset < blkSize);
                 assert(pkt->getSize() <= blkSize);
                 assert(offset+pkt->getSize() <= blkSize);
                 std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(),
                        pkt->getSize());
+            } else if (pkt->isReadWrite()) {
+                cmpAndSwap(blk, pkt);
             } else if (!(pkt->flags & SATISFIED)) {
                 pkt->flags |= SATISFIED;
                 pkt->result = Packet::Success;
@@ -154,7 +157,8 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
             }
         }
 
-        if ((pkt->isWrite() && blk->isWritable()) ||
+        if ((pkt->isReadWrite() && blk->isWritable()) ||
+            (pkt->isWrite() && blk->isWritable()) ||
             (pkt->isRead() && blk->isValid())) {
 
             // We are satisfying the request
@@ -180,13 +184,15 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
                     std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(),
                            pkt->getSize());
                 }
+            } else if (pkt->isReadWrite()) {
+                cmpAndSwap(blk, pkt);
             } else {
                 assert(pkt->isRead());
                 if (pkt->req->isLocked()) {
                     blk->trackLoadLocked(pkt->req);
                 }
                 std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
-                       pkt->getSize());
+                            pkt->getSize());
             }
 
             if (write_data ||
@@ -214,6 +220,44 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
     return blk;
 }
 
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::cmpAndSwap(BlkType *blk, PacketPtr &pkt){
+            uint64_t overwrite_val;
+            bool overwrite_mem;
+            uint64_t condition_val64;
+            uint32_t condition_val32;
+
+            int offset = tags->extractBlkOffset(pkt->getAddr());
+
+            assert(sizeof(uint64_t) >= pkt->getSize());
+
+            overwrite_mem = true;
+            // keep a copy of our possible write value, and copy what is at the
+            // memory address into the packet
+            std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
+            std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
+                        pkt->getSize());
+
+            if (pkt->req->isCondSwap()) {
+                if (pkt->getSize() == sizeof(uint64_t)) {
+                    condition_val64 = pkt->req->getExtraData();
+                    overwrite_mem = !std::memcmp(&condition_val64, blk->data + offset,
+                                                 sizeof(uint64_t));
+                } else if (pkt->getSize() == sizeof(uint32_t)) {
+                    condition_val32 = (uint32_t)pkt->req->getExtraData();
+                    overwrite_mem = !std::memcmp(&condition_val32, blk->data + offset,
+                                                 sizeof(uint32_t));
+                } else
+                    panic("Invalid size for conditional read/write\n");
+            }
+
+            if (overwrite_mem)
+                std::memcpy(blk->data + offset,
+                            &overwrite_val, pkt->getSize());
+
+}
+
 template<class TagStore, class Coherence>
 typename Cache<TagStore,Coherence>::BlkType*
 Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
@@ -244,8 +288,9 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
             blk = NULL;
         }
 
-        if (blk && (target->isWrite() ? blk->isWritable() : blk->isValid())) {
-            assert(target->isWrite() || target->isRead());
+        if (blk && ((target->isWrite() || target->isReadWrite()) ?
+                    blk->isWritable() : blk->isValid())) {
+            assert(target->isWrite() || target->isReadWrite() || target->isRead());
             assert(target->getOffset(blkSize) + target->getSize() <= blkSize);
             if (target->isWrite()) {
                 if (blk->checkWrite(pkt->req)) {
@@ -253,6 +298,8 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
                     std::memcpy(blk->data + target->getOffset(blkSize),
                            target->getPtr<uint8_t>(), target->getSize());
                 }
+            } else if (target->isReadWrite()) {
+                cmpAndSwap(blk, pkt);
             } else {
                 if (pkt->req->isLocked()) {
                     blk->trackLoadLocked(pkt->req);
@@ -332,8 +379,9 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr,
             continue;
         }
 
-        if (blk && (target->isWrite() ? blk->isWritable() : blk->isValid())) {
-            assert(target->isWrite() || target->isRead());
+        if (blk && ((target->isWrite() || target->isReadWrite()) ?
+            blk->isWritable() : blk->isValid())) {
+            assert(target->isWrite() || target->isRead() || target->isReadWrite() );
             assert(target->getOffset(blkSize) + target->getSize() <= blkSize);
             if (target->isWrite()) {
                 if (blk->checkWrite(pkt->req)) {
@@ -341,6 +389,8 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr,
                     std::memcpy(blk->data + target->getOffset(blkSize),
                            target->getPtr<uint8_t>(), target->getSize());
                 }
+            } else if (target->isReadWrite()) {
+                cmpAndSwap(blk, pkt);
             } else {
                 if (target->req->isLocked()) {
                     blk->trackLoadLocked(target->req);
index e8520401d36377a83710534aedcb34813ee73faa..33a8a4e631755dc1c4685c6aba8999df336824ba 100644 (file)
@@ -295,9 +295,12 @@ CoherenceProtocol::CoherenceProtocol(const string &name,
     tt[Invalid][MC::ReadReq].onRequest(MC::ReadReq);
     // we only support write allocate right now
     tt[Invalid][MC::WriteReq].onRequest(MC::ReadExReq);
+    tt[Invalid][MC::SwapReq].onRequest(MC::ReadExReq);
     tt[Shared][MC::WriteReq].onRequest(writeToSharedCmd);
+    tt[Shared][MC::SwapReq].onRequest(writeToSharedCmd);
     if (hasOwned) {
         tt[Owned][MC::WriteReq].onRequest(writeToSharedCmd);
+        tt[Owned][MC::SwapReq].onRequest(writeToSharedCmd);
     }
 
     // Prefetching causes a read