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>
This commit is contained in:
@@ -83,6 +83,11 @@ def setCPUClass(options):
|
||||
TmpClass = AtomicSimpleCPU
|
||||
test_mem_mode = 'atomic'
|
||||
|
||||
# Ruby only supports atomic accesses in noncaching mode
|
||||
if test_mem_mode == 'atomic' and options.ruby:
|
||||
warn("Memory mode will be changed to atomic_noncaching")
|
||||
test_mem_mode = 'atomic_noncaching'
|
||||
|
||||
return (TmpClass, test_mem_mode, CPUClass)
|
||||
|
||||
def setMemClass(options):
|
||||
|
||||
@@ -47,7 +47,7 @@ import sys
|
||||
import m5
|
||||
from m5.defines import buildEnv
|
||||
from m5.objects import *
|
||||
from m5.util import addToPath, fatal
|
||||
from m5.util import addToPath, fatal, warn
|
||||
|
||||
addToPath('../')
|
||||
|
||||
@@ -147,12 +147,6 @@ def build_test_system(np):
|
||||
test_sys.kvm_vm = KvmVM()
|
||||
|
||||
if options.ruby:
|
||||
# Check for timing mode because ruby does not support atomic accesses
|
||||
if not (options.cpu_type == "DerivO3CPU" or
|
||||
options.cpu_type == "TimingSimpleCPU"):
|
||||
print >> sys.stderr, "Ruby requires TimingSimpleCPU or O3CPU!!"
|
||||
sys.exit(1)
|
||||
|
||||
Ruby.create_system(options, True, test_sys, test_sys.iobus,
|
||||
test_sys._dma_ports)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ import os
|
||||
import m5
|
||||
from m5.defines import buildEnv
|
||||
from m5.objects import *
|
||||
from m5.util import addToPath, fatal
|
||||
from m5.util import addToPath, fatal, warn
|
||||
|
||||
addToPath('../')
|
||||
|
||||
@@ -250,10 +250,6 @@ for i in xrange(np):
|
||||
system.cpu[i].createThreads()
|
||||
|
||||
if options.ruby:
|
||||
if options.cpu_type == "AtomicSimpleCPU":
|
||||
print >> sys.stderr, "Ruby does not work with atomic cpu!!"
|
||||
sys.exit(1)
|
||||
|
||||
Ruby.create_system(options, False, system)
|
||||
assert(options.num_cpus == len(system.ruby._cpu_ports))
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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!"); }
|
||||
|
||||
Reference in New Issue
Block a user