summaryrefslogtreecommitdiff
path: root/src/mem/ruby/slicc_interface
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2014-11-06 05:42:21 -0600
committerNilay Vaish <nilay@cs.wisc.edu>2014-11-06 05:42:21 -0600
commit3022d463fbe1f969aadf7284ade996539c9454f9 (patch)
tree7cd252e05ba750a4abe282db2d53957189e19173 /src/mem/ruby/slicc_interface
parent68ddfab8a4fa6f56c5f8bff6d91facd39abe353b (diff)
downloadgem5-3022d463fbe1f969aadf7284ade996539c9454f9.tar.xz
ruby: interface with classic memory controller
This patch is the final in the series. The whole series and this patch in particular were written with the aim of interfacing ruby's directory controller with the memory controller in the classic memory system. This is being done since ruby's memory controller has not being kept up to date with the changes going on in DRAMs. Classic's memory controller is more up to date and supports multiple different types of DRAM. This also brings classic and ruby ever more close. The patch also changes ruby's memory controller to expose the same interface.
Diffstat (limited to 'src/mem/ruby/slicc_interface')
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.cc164
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh65
-rw-r--r--src/mem/ruby/slicc_interface/Controller.py8
3 files changed, 220 insertions, 17 deletions
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 366ea04ce..6bcbfbcbf 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Mark D. Hill and David A. Wood
+ * Copyright (c) 2011-2014 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,21 +26,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "mem/protocol/MemoryMsg.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/Sequencer.hh"
#include "mem/ruby/system/System.hh"
+#include "sim/system.hh"
AbstractController::AbstractController(const Params *p)
- : ClockedObject(p), Consumer(this)
+ : MemObject(p), Consumer(this), m_version(p->version),
+ m_clusterID(p->cluster_id),
+ m_masterId(p->system->getMasterId(name())), m_is_blocking(false),
+ m_number_of_TBEs(p->number_of_TBEs),
+ m_transitions_per_cycle(p->transitions_per_cycle),
+ m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency),
+ memoryPort(csprintf("%s.memory", name()), this, ""),
+ m_responseFromMemory_ptr(new MessageBuffer())
{
- m_version = p->version;
- m_clusterID = p->cluster_id;
-
- m_transitions_per_cycle = p->transitions_per_cycle;
- m_buffer_size = p->buffer_size;
- m_recycle_latency = p->recycle_latency;
- m_number_of_TBEs = p->number_of_TBEs;
- m_is_blocking = false;
+ // Set the sender pointer of the response message buffer from the
+ // memory controller.
+ // This pointer is used for querying for the current time.
+ m_responseFromMemory_ptr->setSender(this);
+ m_responseFromMemory_ptr->setReceiver(this);
+ m_responseFromMemory_ptr->setOrdering(false);
if (m_version == 0) {
// Combine the statistics from all controllers
@@ -187,3 +194,140 @@ AbstractController::unblock(Address addr)
m_is_blocking = false;
}
}
+
+BaseMasterPort &
+AbstractController::getMasterPort(const std::string &if_name,
+ PortID idx)
+{
+ return memoryPort;
+}
+
+void
+AbstractController::queueMemoryRead(const MachineID &id, Address addr,
+ Cycles latency)
+{
+ RequestPtr req = new Request(addr.getAddress(),
+ RubySystem::getBlockSizeBytes(), 0,
+ m_masterId);
+
+ PacketPtr pkt = Packet::createRead(req);
+ uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()];
+ pkt->dataDynamic(newData);
+
+ SenderState *s = new SenderState(id);
+ pkt->pushSenderState(s);
+
+ memoryPort.schedTimingReq(pkt, clockEdge(latency));
+}
+
+void
+AbstractController::queueMemoryWrite(const MachineID &id, Address addr,
+ Cycles latency, const DataBlock &block)
+{
+ RequestPtr req = new Request(addr.getAddress(),
+ RubySystem::getBlockSizeBytes(), 0,
+ m_masterId);
+
+ PacketPtr pkt = Packet::createWrite(req);
+ uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()];
+ pkt->dataDynamic(newData);
+ memcpy(newData, block.getData(0, RubySystem::getBlockSizeBytes()),
+ RubySystem::getBlockSizeBytes());
+
+ SenderState *s = new SenderState(id);
+ pkt->pushSenderState(s);
+
+ // Create a block and copy data from the block.
+ memoryPort.schedTimingReq(pkt, clockEdge(latency));
+}
+
+void
+AbstractController::queueMemoryWritePartial(const MachineID &id, Address addr,
+ Cycles latency,
+ const DataBlock &block, int size)
+{
+ RequestPtr req = new Request(addr.getAddress(),
+ RubySystem::getBlockSizeBytes(), 0,
+ m_masterId);
+
+ PacketPtr pkt = Packet::createWrite(req);
+ uint8_t *newData = new uint8_t[size];
+ pkt->dataDynamic(newData);
+ memcpy(newData, block.getData(addr.getOffset(), size), size);
+
+ SenderState *s = new SenderState(id);
+ pkt->pushSenderState(s);
+
+ // Create a block and copy data from the block.
+ memoryPort.schedTimingReq(pkt, clockEdge(latency));
+}
+
+void
+AbstractController::functionalMemoryRead(PacketPtr pkt)
+{
+ memoryPort.sendFunctional(pkt);
+}
+
+int
+AbstractController::functionalMemoryWrite(PacketPtr pkt)
+{
+ int num_functional_writes = 0;
+
+ // Check the message buffer that runs from the memory to the controller.
+ num_functional_writes += m_responseFromMemory_ptr->functionalWrite(pkt);
+
+ // Check the buffer from the controller to the memory.
+ if (memoryPort.checkFunctional(pkt)) {
+ num_functional_writes++;
+ }
+
+ // Update memory itself.
+ memoryPort.sendFunctional(pkt);
+ return num_functional_writes + 1;
+}
+
+void
+AbstractController::recvTimingResp(PacketPtr pkt)
+{
+ assert(pkt->isResponse());
+
+ std::shared_ptr<MemoryMsg> msg = std::make_shared<MemoryMsg>(clockEdge());
+ (*msg).m_Addr.setAddress(pkt->getAddr());
+ (*msg).m_Sender = m_machineID;
+
+ SenderState *s = dynamic_cast<SenderState *>(pkt->senderState);
+ (*msg).m_OriginalRequestorMachId = s->id;
+ delete s;
+
+ if (pkt->isRead()) {
+ (*msg).m_Type = MemoryRequestType_MEMORY_READ;
+ (*msg).m_MessageSize = MessageSizeType_Response_Data;
+
+ // Copy data from the packet
+ (*msg).m_DataBlk.setData(pkt->getPtr<uint8_t>(), 0,
+ RubySystem::getBlockSizeBytes());
+ } else if (pkt->isWrite()) {
+ (*msg).m_Type = MemoryRequestType_MEMORY_WB;
+ (*msg).m_MessageSize = MessageSizeType_Writeback_Control;
+ } else {
+ panic("Incorrect packet type received from memory controller!");
+ }
+
+ m_responseFromMemory_ptr->enqueue(msg);
+ delete pkt;
+}
+
+bool
+AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt)
+{
+ controller->recvTimingResp(pkt);
+ return true;
+}
+
+AbstractController::MemoryPort::MemoryPort(const std::string &_name,
+ AbstractController *_controller,
+ const std::string &_label)
+ : QueuedMasterPort(_name, _controller, _queue),
+ _queue(*_controller, *this, _label), controller(_controller)
+{
+}
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index 98fce574f..45d355b3e 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009-2014 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,12 +43,13 @@
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/system/CacheRecorder.hh"
#include "mem/packet.hh"
+#include "mem/qport.hh"
#include "params/RubyController.hh"
-#include "sim/clocked_object.hh"
+#include "mem/mem_object.hh"
class Network;
-class AbstractController : public ClockedObject, public Consumer
+class AbstractController : public MemObject, public Consumer
{
public:
typedef RubyControllerParams Params;
@@ -79,10 +80,12 @@ class AbstractController : public ClockedObject, public Consumer
//! These functions are used by ruby system to read/write the data blocks
//! that exist with in the controller.
virtual void functionalRead(const Address &addr, PacketPtr) = 0;
+ void functionalMemoryRead(PacketPtr);
//! The return value indicates the number of messages written with the
//! data from the packet.
- virtual uint32_t functionalWriteBuffers(PacketPtr&) = 0;
+ virtual int functionalWriteBuffers(PacketPtr&) = 0;
virtual int functionalWrite(const Address &addr, PacketPtr) = 0;
+ int functionalMemoryWrite(PacketPtr);
//! Function for enqueuing a prefetch request
virtual void enqueuePrefetch(const Address&, const RubyRequestType&)
@@ -97,6 +100,17 @@ class AbstractController : public ClockedObject, public Consumer
//! Set the message buffer with given name.
virtual void setNetQueue(const std::string& name, MessageBuffer *b) = 0;
+ /** A function used to return the port associated with this bus object. */
+ BaseMasterPort& getMasterPort(const std::string& if_name,
+ PortID idx = InvalidPortID);
+
+ void queueMemoryRead(const MachineID &id, Address addr, Cycles latency);
+ void queueMemoryWrite(const MachineID &id, Address addr, Cycles latency,
+ const DataBlock &block);
+ void queueMemoryWritePartial(const MachineID &id, Address addr, Cycles latency,
+ const DataBlock &block, int size);
+ void recvTimingResp(PacketPtr pkt);
+
public:
MachineID getMachineID() const { return m_machineID; }
@@ -120,6 +134,9 @@ class AbstractController : public ClockedObject, public Consumer
MachineID m_machineID;
NodeID m_clusterID;
+ // MasterID used by some components of gem5.
+ MasterID m_masterId;
+
Network* m_net_ptr;
bool m_is_blocking;
std::map<Address, MessageBuffer*> m_block_map;
@@ -156,6 +173,46 @@ class AbstractController : public ClockedObject, public Consumer
StatsCallback(AbstractController *_ctr) : ctr(_ctr) {}
void process() {ctr->collateStats();}
};
+
+ /**
+ * Port that forwards requests and receives responses from the
+ * memory controller. It has a queue of packets not yet sent.
+ */
+ class MemoryPort : public QueuedMasterPort
+ {
+ private:
+ // Packet queue used to store outgoing requests and responses.
+ MasterPacketQueue _queue;
+
+ // Controller that operates this port.
+ AbstractController *controller;
+
+ public:
+ MemoryPort(const std::string &_name, AbstractController *_controller,
+ const std::string &_label);
+
+ // Function for receiving a timing response from the peer port.
+ // Currently the pkt is handed to the coherence controller
+ // associated with this port.
+ bool recvTimingResp(PacketPtr pkt);
+ };
+
+ /* Master port to the memory controller. */
+ MemoryPort memoryPort;
+
+ // Message Buffer for storing the response received from the
+ // memory controller.
+ MessageBuffer *m_responseFromMemory_ptr;
+
+ // State that is stored in packets sent to the memory controller.
+ struct SenderState : public Packet::SenderState
+ {
+ // Id of the machine from which the request originated.
+ MachineID id;
+
+ SenderState(MachineID _id) : id(_id)
+ {}
+ };
};
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
diff --git a/src/mem/ruby/slicc_interface/Controller.py b/src/mem/ruby/slicc_interface/Controller.py
index f82e0a70d..ba7d17c7c 100644
--- a/src/mem/ruby/slicc_interface/Controller.py
+++ b/src/mem/ruby/slicc_interface/Controller.py
@@ -28,9 +28,10 @@
# Brad Beckmann
from m5.params import *
-from ClockedObject import ClockedObject
+from m5.proxy import *
+from MemObject import MemObject
-class RubyController(ClockedObject):
+class RubyController(MemObject):
type = 'RubyController'
cxx_class = 'AbstractController'
cxx_header = "mem/ruby/slicc_interface/AbstractController.hh"
@@ -46,4 +47,5 @@ class RubyController(ClockedObject):
number_of_TBEs = Param.Int(256, "")
ruby_system = Param.RubySystem("")
- peer = Param.RubyController(NULL, "")
+ memory = MasterPort("Port for attaching a memory controller")
+ system = Param.System(Parent.any, "system object parameter")