ruby: Implement SwapReq support
authorMarco Elver <marco.elver@ed.ac.uk>
Fri, 3 Jun 2016 20:20:08 +0000 (16:20 -0400)
committerMarco Elver <marco.elver@ed.ac.uk>
Fri, 3 Jun 2016 20:20:08 +0000 (16:20 -0400)
This implements SwapReq for Ruby memory.

A SwapReq should be treated like a write, except that the response
packet contains the overwritten data.

Note that, in particular, the conditional checking for isStore/isLoad
needs to be reversed, as a SwapReq is both.

src/mem/ruby/system/Sequencer.cc

index b7df371e1c16a31d21c733fe120c547256224808..f1f6ddadbc2a51a79319f052c3d7d4b2609080a6 100644 (file)
@@ -478,6 +478,16 @@ Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data,
                    data.getData(getOffset(request_address), pkt->getSize()),
                    pkt->getSize());
             DPRINTF(RubySequencer, "read data %s\n", data);
+        } else if (pkt->req->isSwap()) {
+            std::vector<uint8_t> overwrite_val(pkt->getSize());
+            memcpy(&overwrite_val[0], pkt->getConstPtr<uint8_t>(),
+                   pkt->getSize());
+            memcpy(pkt->getPtr<uint8_t>(),
+                   data.getData(getOffset(request_address), pkt->getSize()),
+                   pkt->getSize());
+            data.setData(&overwrite_val[0],
+                         getOffset(request_address), pkt->getSize());
+            DPRINTF(RubySequencer, "swap data %s\n", data);
         } else {
             data.setData(pkt->getConstPtr<uint8_t>(),
                          getOffset(request_address), pkt->getSize());
@@ -565,7 +575,17 @@ Sequencer::makeRequest(PacketPtr pkt)
         }
         secondary_type = RubyRequestType_ST;
     } else {
-        if (pkt->isRead()) {
+        //
+        // To support SwapReq, we need to check isWrite() first: a SwapReq
+        // should always be treated like a write, but since a SwapReq implies
+        // both isWrite() and isRead() are true, check isWrite() first here.
+        //
+        if (pkt->isWrite()) {
+            //
+            // Note: M5 packets do not differentiate ST from RMW_Write
+            //
+            primary_type = secondary_type = RubyRequestType_ST;
+        } else if (pkt->isRead()) {
             if (pkt->req->isInstFetch()) {
                 primary_type = secondary_type = RubyRequestType_IFETCH;
             } else {
@@ -583,11 +603,6 @@ Sequencer::makeRequest(PacketPtr pkt)
                     primary_type = secondary_type = RubyRequestType_LD;
                 }
             }
-        } else if (pkt->isWrite()) {
-            //
-            // Note: M5 packets do not differentiate ST from RMW_Write
-            //
-            primary_type = secondary_type = RubyRequestType_ST;
         } else if (pkt->isFlush()) {
           primary_type = secondary_type = RubyRequestType_FLUSH;
         } else {