summaryrefslogtreecommitdiff
path: root/src/mem/ruby/system
diff options
context:
space:
mode:
authorBrad Beckmann ext:(%2C%20Nilay%20Vaish%20%3Cnilay%40cs.wisc.edu%3E) <Brad.Beckmann@amd.com>2011-06-30 19:49:26 -0500
committerBrad Beckmann ext:(%2C%20Nilay%20Vaish%20%3Cnilay%40cs.wisc.edu%3E) <Brad.Beckmann@amd.com>2011-06-30 19:49:26 -0500
commitc86f849d5a1da1fc77f2fca43b82cb6760f68bc9 (patch)
treef192cbc73d86ee4e15e752f6ed174e4ce3425c9e /src/mem/ruby/system
parentf4cfd65d2982f0f97304ef05083b40f3346a496f (diff)
downloadgem5-c86f849d5a1da1fc77f2fca43b82cb6760f68bc9.tar.xz
Ruby: Add support for functional accesses
This patch rpovides functional access support in Ruby. Currently only the M5Port of RubyPort supports functional accesses. The support for functional through the PioPort will be added as a separate patch.
Diffstat (limited to 'src/mem/ruby/system')
-rw-r--r--src/mem/ruby/system/Cache.py41
-rw-r--r--src/mem/ruby/system/DirectoryMemory.cc4
-rw-r--r--src/mem/ruby/system/DirectoryMemory.py43
-rw-r--r--src/mem/ruby/system/RubyPort.cc175
-rw-r--r--src/mem/ruby/system/RubyPort.hh7
-rw-r--r--src/mem/ruby/system/RubySystem.py3
-rw-r--r--src/mem/ruby/system/SConscript3
-rw-r--r--src/mem/ruby/system/Sequencer.py1
-rw-r--r--src/mem/ruby/system/System.cc28
-rw-r--r--src/mem/ruby/system/System.hh13
10 files changed, 215 insertions, 103 deletions
diff --git a/src/mem/ruby/system/Cache.py b/src/mem/ruby/system/Cache.py
deleted file mode 100644
index ab3ec4b29..000000000
--- a/src/mem/ruby/system/Cache.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Steve Reinhardt
-# Brad Beckmann
-
-from m5.params import *
-from m5.SimObject import SimObject
-from Controller import RubyController
-
-class RubyCache(SimObject):
- type = 'RubyCache'
- cxx_class = 'CacheMemory'
- size = Param.MemorySize("capacity in bytes");
- latency = Param.Int("");
- assoc = Param.Int("");
- replacement_policy = Param.String("PSEUDO_LRU", "");
- start_index_bit = Param.Int(6, "index start, default 6 for 64-byte line");
diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc
index fe54c8d79..c461ce09b 100644
--- a/src/mem/ruby/system/DirectoryMemory.cc
+++ b/src/mem/ruby/system/DirectoryMemory.cc
@@ -156,7 +156,7 @@ DirectoryMemory::lookup(PhysAddress address)
assert(isPresent(address));
Directory_Entry* entry;
uint64 idx;
- DPRINTF(RubyCache, "address: %s\n", address);
+ DPRINTF(RubyCache, "Looking up address: %s\n", address);
if (m_use_map) {
if (m_sparseMemory->exist(address)) {
@@ -166,6 +166,7 @@ DirectoryMemory::lookup(PhysAddress address)
// Note: SparseMemory internally creates a new Directory Entry
m_sparseMemory->add(address);
entry = m_sparseMemory->lookup(address);
+ entry->changePermission(AccessPermission_Read_Write);
}
} else {
idx = mapAddressToLocalIdx(address);
@@ -175,6 +176,7 @@ DirectoryMemory::lookup(PhysAddress address)
if (entry == NULL) {
entry = new Directory_Entry();
entry->getDataBlk().assign(m_ram->getBlockPtr(address));
+ entry->changePermission(AccessPermission_Read_Only);
m_entries[idx] = entry;
}
}
diff --git a/src/mem/ruby/system/DirectoryMemory.py b/src/mem/ruby/system/DirectoryMemory.py
deleted file mode 100644
index d3b6bc591..000000000
--- a/src/mem/ruby/system/DirectoryMemory.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Steve Reinhardt
-# Brad Beckmann
-
-from m5.params import *
-from m5.proxy import *
-from m5.SimObject import SimObject
-
-class RubyDirectoryMemory(SimObject):
- type = 'RubyDirectoryMemory'
- cxx_class = 'DirectoryMemory'
- version = Param.Int(0, "")
- size = Param.MemorySize("1GB", "capacity in bytes")
- use_map = Param.Bool(False, "enable sparse memory")
- map_levels = Param.Int(4, "sparse memory map levels")
- # the default value of the numa high bit is specified in the command line
- # option and must be passed into the directory memory sim object
- numa_high_bit = Param.Int("numa high bit")
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index 40f893257..662f971f2 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -31,8 +31,8 @@
#include "arch/x86/insts/microldstop.hh"
#endif // X86_ISA
#include "cpu/testers/rubytest/RubyTester.hh"
-#include "debug/MemoryAccess.hh"
#include "debug/Ruby.hh"
+#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/RubyPort.hh"
#include "mem/physical.hh"
@@ -54,6 +54,8 @@ RubyPort::RubyPort(const Params *p)
m_usingRubyTester = p->using_ruby_tester;
access_phys_mem = p->access_phys_mem;
+
+ ruby_system = p->ruby_system;
}
void
@@ -68,7 +70,7 @@ RubyPort::getPort(const std::string &if_name, int idx)
{
if (if_name == "port") {
return new M5Port(csprintf("%s-port%d", name(), idx), this,
- access_phys_mem);
+ ruby_system, access_phys_mem);
}
if (if_name == "pio_port") {
@@ -85,7 +87,7 @@ RubyPort::getPort(const std::string &if_name, int idx)
assert (physMemPort == NULL);
physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this,
- access_phys_mem);
+ ruby_system, access_phys_mem);
return physMemPort;
}
@@ -109,12 +111,13 @@ RubyPort::PioPort::PioPort(const std::string &_name,
ruby_port = _port;
}
-RubyPort::M5Port::M5Port(const std::string &_name,
- RubyPort *_port, bool _access_phys_mem)
+RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port,
+ RubySystem *_system, bool _access_phys_mem)
: SimpleTimingPort(_name, _port)
{
DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name);
ruby_port = _port;
+ ruby_system = _system;
_onRetryList = false;
access_phys_mem = _access_phys_mem;
}
@@ -289,6 +292,168 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
return false;
}
+bool
+RubyPort::M5Port::doFunctionalRead(PacketPtr pkt)
+{
+ Address address(pkt->getAddr());
+ Address line_address(address);
+ line_address.makeLineAddress();
+
+ AccessPermission accessPerm = AccessPermission_NotPresent;
+ int num_controllers = ruby_system->m_abs_cntrl_vec.size();
+
+ // In this loop, we try to figure which controller has a read only or
+ // a read write copy of the given address. Any valid copy would suffice
+ // for a functional read.
+
+ DPRINTF(RubyPort, "Functional Read request for %s\n",address);
+ for(int i = 0;i < num_controllers;++i)
+ {
+ accessPerm = ruby_system->m_abs_cntrl_vec[i]
+ ->getAccessPermission(line_address);
+ if(accessPerm == AccessPermission_Read_Only ||
+ accessPerm == AccessPermission_Read_Write)
+ {
+ unsigned startByte = address.getAddress() - line_address.getAddress();
+
+ uint8* data = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ DataBlock& block = ruby_system->m_abs_cntrl_vec[i]
+ ->getDataBlock(line_address);
+
+ DPRINTF(RubyPort, "reading from %s block %s\n",
+ ruby_system->m_abs_cntrl_vec[i]->name(), block);
+ for (unsigned i = 0; i < size_in_bytes; ++i)
+ {
+ data[i] = block.getByte(i + startByte);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt)
+{
+ Address addr(pkt->getAddr());
+ Address line_addr = line_address(addr);
+ AccessPermission accessPerm = AccessPermission_NotPresent;
+ int num_controllers = ruby_system->m_abs_cntrl_vec.size();
+
+ DPRINTF(RubyPort, "Functional Write request for %s\n",addr);
+
+ unsigned int num_ro = 0;
+ unsigned int num_rw = 0;
+ unsigned int num_busy = 0;
+
+ // In this loop we count the number of controllers that have the given
+ // address in read only, read write and busy states.
+ for(int i = 0;i < num_controllers;++i)
+ {
+ accessPerm = ruby_system->m_abs_cntrl_vec[i]->
+ getAccessPermission(line_addr);
+ if(accessPerm == AccessPermission_Read_Only) num_ro++;
+ else if(accessPerm == AccessPermission_Read_Write) num_rw++;
+ else if(accessPerm == AccessPermission_Busy) num_busy++;
+ }
+
+ // If the number of read write copies is more than 1, then there is bug in
+ // coherence protocol. Otherwise, if all copies are in stable states, i.e.
+ // num_busy == 0, we update all the copies. If there is at least one copy
+ // in busy state, then we check if there is read write copy. If yes, then
+ // also we let the access go through.
+
+ DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n",
+ num_busy, num_ro, num_rw);
+ assert(num_rw <= 1);
+ if((num_busy == 0 && num_ro > 0) || num_rw == 1)
+ {
+ uint8* data = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ unsigned startByte = addr.getAddress() - line_addr.getAddress();
+
+ for(int i = 0; i < num_controllers;++i)
+ {
+ accessPerm = ruby_system->m_abs_cntrl_vec[i]->
+ getAccessPermission(line_addr);
+ if(accessPerm == AccessPermission_Read_Only ||
+ accessPerm == AccessPermission_Read_Write||
+ accessPerm == AccessPermission_Maybe_Stale)
+ {
+ DataBlock& block = ruby_system->m_abs_cntrl_vec[i]
+ ->getDataBlock(line_addr);
+
+ DPRINTF(RubyPort, "%s\n",block);
+ for (unsigned i = 0; i < size_in_bytes; ++i)
+ {
+ block.setByte(i + startByte, data[i]);
+ }
+ DPRINTF(RubyPort, "%s\n",block);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void
+RubyPort::M5Port::recvFunctional(PacketPtr pkt)
+{
+ DPRINTF(RubyPort, "Functional access caught for address %#x\n",
+ pkt->getAddr());
+
+ // Check for pio requests and directly send them to the dedicated
+ // pio port.
+ if (!isPhysMemAddress(pkt->getAddr())) {
+ assert(ruby_port->pio_port != NULL);
+ DPRINTF(RubyPort, "Request for address 0x%#x is a pio request\n",
+ pkt->getAddr());
+ panic("RubyPort::PioPort::recvFunctional() not implemented!\n");
+ }
+
+ assert(pkt->getAddr() + pkt->getSize() <=
+ line_address(Address(pkt->getAddr())).getAddress() +
+ RubySystem::getBlockSizeBytes());
+
+ bool accessSucceeded = false;
+ bool needsResponse = pkt->needsResponse();
+
+ // Do the functional access on ruby memory
+ if (pkt->isRead()) {
+ accessSucceeded = doFunctionalRead(pkt);
+ } else if (pkt->isWrite()) {
+ accessSucceeded = doFunctionalWrite(pkt);
+ } else {
+ panic("RubyPort: unsupported functional command %s\n",
+ pkt->cmdString());
+ }
+
+ // Unless the requester explicitly said otherwise, generate an error if
+ // the functional request failed
+ if (!accessSucceeded && !pkt->suppressFuncError()) {
+ fatal("Ruby functional %s failed for address %#x\n",
+ pkt->isWrite() ? "write" : "read", pkt->getAddr());
+ }
+
+ if (access_phys_mem) {
+ // The attached physmem contains the official version of data.
+ // The following command performs the real functional access.
+ // This line should be removed once Ruby supplies the official version
+ // of data.
+ ruby_port->physMemPort->sendFunctional(pkt);
+ }
+
+ // turn packet around to go back to requester if response expected
+ if (needsResponse) {
+ pkt->setFunctionalResponseStatus(accessSucceeded);
+ DPRINTF(RubyPort, "Sending packet back over port\n");
+ sendFunctional(pkt);
+ }
+ DPRINTF(RubyPort, "Functional access %s!\n",
+ accessSucceeded ? "successful":"failed");
+}
+
void
RubyPort::ruby_hit_callback(PacketPtr pkt)
{
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
index dc7a141c3..e1ba2f7d1 100644
--- a/src/mem/ruby/system/RubyPort.hh
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -50,12 +50,13 @@ class RubyPort : public MemObject
{
private:
RubyPort *ruby_port;
+ RubySystem* ruby_system;
bool _onRetryList;
bool access_phys_mem;
public:
M5Port(const std::string &_name, RubyPort *_port,
- bool _access_phys_mem);
+ RubySystem*_system, bool _access_phys_mem);
bool sendTiming(PacketPtr pkt);
void hitCallback(PacketPtr pkt);
unsigned deviceBlockSize() const;
@@ -69,9 +70,12 @@ class RubyPort : public MemObject
protected:
virtual bool recvTiming(PacketPtr pkt);
virtual Tick recvAtomic(PacketPtr pkt);
+ virtual void recvFunctional(PacketPtr pkt);
private:
bool isPhysMemAddress(Addr addr);
+ bool doFunctionalRead(PacketPtr pkt);
+ bool doFunctionalWrite(PacketPtr pkt);
};
friend class M5Port;
@@ -145,6 +149,7 @@ class RubyPort : public MemObject
M5Port* physMemPort;
PhysicalMemory* physmem;
+ RubySystem* ruby_system;
//
// Based on similar code in the M5 bus. Stores pointers to those ports
diff --git a/src/mem/ruby/system/RubySystem.py b/src/mem/ruby/system/RubySystem.py
index 7878cec63..d66ada4b9 100644
--- a/src/mem/ruby/system/RubySystem.py
+++ b/src/mem/ruby/system/RubySystem.py
@@ -39,9 +39,6 @@ class RubySystem(SimObject):
block_size_bytes = Param.Int(64,
"default cache block size; must be a power of two");
mem_size = Param.MemorySize("total memory size of the system");
- network = Param.RubyNetwork("")
- profiler = Param.RubyProfiler("");
- tracer = Param.RubyTracer("");
stats_filename = Param.String("ruby.stats",
"file to which ruby dumps its stats")
no_mem_vec = Param.Bool(False, "do not allocate Ruby's mem vector");
diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript
index f1e7c425c..0820ef2c8 100644
--- a/src/mem/ruby/system/SConscript
+++ b/src/mem/ruby/system/SConscript
@@ -33,9 +33,8 @@ Import('*')
if not env['RUBY']:
Return()
-SimObject('Cache.py')
+SimObject('AbstractMemory.py')
SimObject('Sequencer.py')
-SimObject('DirectoryMemory.py')
SimObject('MemoryControl.py')
SimObject('WireBuffer.py')
SimObject('RubySystem.py')
diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py
index 16fb795f8..5d56dc000 100644
--- a/src/mem/ruby/system/Sequencer.py
+++ b/src/mem/ruby/system/Sequencer.py
@@ -43,6 +43,7 @@ class RubyPort(MemObject):
using_network_tester = Param.Bool(False, "")
access_phys_mem = Param.Bool(True,
"should the rubyport atomically update phys_mem")
+ ruby_system = Param.RubySystem("")
class RubySequencer(RubyPort):
type = 'RubySequencer'
diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc
index d9c4fa821..81824b9b7 100644
--- a/src/mem/ruby/system/System.cc
+++ b/src/mem/ruby/system/System.cc
@@ -74,10 +74,6 @@ RubySystem::RubySystem(const Params *p)
m_memory_size_bits = floorLog2(m_memory_size_bytes);
}
- m_network_ptr = p->network;
- m_profiler_ptr = p->profiler;
- m_tracer_ptr = p->tracer;
-
g_eventQueue_ptr = new RubyEventQueue(p->eventq, m_clock);
g_system_ptr = this;
if (p->no_mem_vec) {
@@ -100,6 +96,30 @@ RubySystem::init()
m_profiler_ptr->clearStats();
}
+void
+RubySystem::registerNetwork(Network* network_ptr)
+{
+ m_network_ptr = network_ptr;
+}
+
+void
+RubySystem::registerProfiler(Profiler* profiler_ptr)
+{
+ m_profiler_ptr = profiler_ptr;
+}
+
+void
+RubySystem::registerTracer(Tracer* tracer_ptr)
+{
+ m_tracer_ptr = tracer_ptr;
+}
+
+void
+RubySystem::registerAbstractController(AbstractController* cntrl)
+{
+ m_abs_cntrl_vec.push_back(cntrl);
+}
+
RubySystem::~RubySystem()
{
delete m_network_ptr;
diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh
index 608aca1d8..88a0186c5 100644
--- a/src/mem/ruby/system/System.hh
+++ b/src/mem/ruby/system/System.hh
@@ -39,9 +39,12 @@
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/system/RubyPort.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "params/RubySystem.hh"
#include "sim/sim_object.hh"
+class AbstractController;
+class AbstractMemory;
class CacheRecorder;
class MemoryVector;
class Network;
@@ -128,6 +131,12 @@ class RubySystem : public SimObject
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ void registerNetwork(Network*);
+ void registerProfiler(Profiler*);
+ void registerTracer(Tracer*);
+ void registerAbstractMemory(AbstractMemory*);
+ void registerAbstractController(AbstractController*);
+
private:
// Private copy constructor and assignment operator
RubySystem(const RubySystem& obj);
@@ -153,6 +162,7 @@ class RubySystem : public SimObject
static Profiler* m_profiler_ptr;
static Tracer* m_tracer_ptr;
static MemoryVector* m_mem_vec_ptr;
+ std::vector<AbstractController*> m_abs_cntrl_vec;
};
inline std::ostream&
@@ -180,6 +190,3 @@ class RubyExitCallback : public Callback
};
#endif // __MEM_RUBY_SYSTEM_SYSTEM_HH__
-
-
-