summaryrefslogtreecommitdiff
path: root/src/mem/ruby
diff options
context:
space:
mode:
authorSwapnil Haria <swapnilster@gmail.com>2017-11-09 13:04:39 -0600
committerSwapnil Haria <swapnilster@gmail.com>2017-12-15 00:50:32 +0000
commit6ab6c52b0bf9c91ef9249613cb4c9d8ab579b4f3 (patch)
tree8da65d170bf38e885eec878d7cb4fa934a81e3c7 /src/mem/ruby
parentc5095c75f7a721551816efd16196d88eb997ec5a (diff)
downloadgem5-6ab6c52b0bf9c91ef9249613cb4c9d8ab579b4f3.tar.xz
mem-ruby: Support atomic_noncaching acceses in ruby
Ruby has no support for atomic_noncaching accesses, which prevents using it with kvm-cpu. This patch fixes this by directly forwarding atomic requests from the ruby port/sequencer to the corresponding directory based on the destination address of the packet. Change-Id: I0b4928bfda44fd9e5e48583c51d1ea422800da2d Reviewed-on: https://gem5-review.googlesource.com/5601 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-by: Bradford Beckmann <brad.beckmann@amd.com> Maintainer: Jason Lowe-Power <jason@lowepower.com> Maintainer: Bradford Beckmann <brad.beckmann@amd.com>
Diffstat (limited to 'src/mem/ruby')
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.cc6
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh1
-rw-r--r--src/mem/ruby/system/RubyPort.cc62
-rw-r--r--src/mem/ruby/system/RubyPort.hh7
4 files changed, 72 insertions, 4 deletions
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 0bc88eefa..b920ff7b0 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -360,6 +360,12 @@ AbstractController::recvTimingResp(PacketPtr pkt)
delete pkt;
}
+Tick
+AbstractController::recvAtomic(PacketPtr pkt)
+{
+ return ticksToCycles(memoryPort.sendAtomic(pkt));
+}
+
MachineID
AbstractController::mapAddressToMachine(Addr addr, MachineType mtype) const
{
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index 354dc80aa..35cd3d2a5 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -135,6 +135,7 @@ class AbstractController : public MemObject, public Consumer
void queueMemoryWritePartial(const MachineID &id, Addr addr, Cycles latency,
const DataBlock &block, int size);
void recvTimingResp(PacketPtr pkt);
+ Tick recvAtomic(PacketPtr pkt);
const AddrRangeList &getAddrRanges() const { return addrRanges; }
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index fd535cca2..5977ce9ef 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -226,6 +226,26 @@ RubyPort::PioSlavePort::recvTimingReq(PacketPtr pkt)
panic("Should never reach here!\n");
}
+Tick
+RubyPort::PioSlavePort::recvAtomic(PacketPtr pkt)
+{
+ RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
+ // Only atomic_noncaching mode supported!
+ if (!ruby_port->system->bypassCaches()) {
+ panic("Ruby supports atomic accesses only in noncaching mode\n");
+ }
+
+ for (size_t i = 0; i < ruby_port->master_ports.size(); ++i) {
+ AddrRangeList l = ruby_port->master_ports[i]->getAddrRanges();
+ for (auto it = l.begin(); it != l.end(); ++it) {
+ if (it->contains(pkt->getAddr())) {
+ return ruby_port->master_ports[i]->sendAtomic(pkt);
+ }
+ }
+ }
+ panic("Could not find address in Ruby PIO address ranges!\n");
+}
+
bool
RubyPort::MemSlavePort::recvTimingReq(PacketPtr pkt)
{
@@ -295,6 +315,48 @@ RubyPort::MemSlavePort::recvTimingReq(PacketPtr pkt)
return false;
}
+Tick
+RubyPort::MemSlavePort::recvAtomic(PacketPtr pkt)
+{
+ RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
+ // Only atomic_noncaching mode supported!
+ if (!ruby_port->system->bypassCaches()) {
+ panic("Ruby supports atomic accesses only in noncaching mode\n");
+ }
+
+ // Check for pio requests and directly send them to the dedicated
+ // pio port.
+ if (pkt->cmd != MemCmd::MemFenceReq) {
+ if (!isPhysMemAddress(pkt->getAddr())) {
+ assert(ruby_port->memMasterPort.isConnected());
+ DPRINTF(RubyPort, "Request address %#x assumed to be a "
+ "pio address\n", pkt->getAddr());
+
+ // Save the port in the sender state object to be used later to
+ // route the response
+ pkt->pushSenderState(new SenderState(this));
+
+ // send next cycle
+ Tick req_ticks = ruby_port->memMasterPort.sendAtomic(pkt);
+ return ruby_port->ticksToCycles(req_ticks);
+ }
+
+ assert(getOffset(pkt->getAddr()) + pkt->getSize() <=
+ RubySystem::getBlockSizeBytes());
+ }
+
+ // Find appropriate directory for address
+ // This assumes that protocols have a Directory machine,
+ // which has its memPort hooked up to memory. This can
+ // fail for some custom protocols.
+ MachineID id = ruby_port->m_controller->mapAddressToMachine(
+ pkt->getAddr(), MachineType_Directory);
+ RubySystem *rs = ruby_port->m_ruby_system;
+ AbstractController *directory =
+ rs->m_abstract_controls[id.getType()][id.getNum()];
+ return directory->recvAtomic(pkt);
+}
+
void
RubyPort::MemSlavePort::addToRetryList()
{
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
index 6c991c162..146443282 100644
--- a/src/mem/ruby/system/RubyPort.hh
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -46,6 +46,7 @@
#include <string>
#include "mem/protocol/RequestStatus.hh"
+#include "mem/ruby/common/MachineID.hh"
#include "mem/ruby/network/MessageBuffer.hh"
#include "mem/ruby/system/RubySystem.hh"
#include "mem/mem_object.hh"
@@ -88,8 +89,7 @@ class RubyPort : public MemObject
protected:
bool recvTimingReq(PacketPtr pkt);
- Tick recvAtomic(PacketPtr pkt)
- { panic("RubyPort::MemSlavePort::recvAtomic() not implemented!\n"); }
+ Tick recvAtomic(PacketPtr pkt);
void recvFunctional(PacketPtr pkt);
@@ -127,8 +127,7 @@ class RubyPort : public MemObject
protected:
bool recvTimingReq(PacketPtr pkt);
- Tick recvAtomic(PacketPtr pkt)
- { panic("recvAtomic not supported with ruby!"); }
+ Tick recvAtomic(PacketPtr pkt);
void recvFunctional(PacketPtr pkt)
{ panic("recvFunctional should never be called on pio slave port!"); }