summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Elver <marco.elver@ed.ac.uk>2016-06-03 16:20:08 -0400
committerMarco Elver <marco.elver@ed.ac.uk>2016-06-03 16:20:08 -0400
commit289a8ebdb1348994164c292f24970e56817cd1d6 (patch)
tree530d2e3042b7fa9c1d005930b40c3cccf24812b4
parent8a52029adc5c30915b33fa9a7238ef3d4d14f0fd (diff)
downloadgem5-289a8ebdb1348994164c292f24970e56817cd1d6.tar.xz
ruby: Implement SwapReq support
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.
-rw-r--r--src/mem/ruby/system/Sequencer.cc27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index b7df371e1..f1f6ddadb 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -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 {