diff options
Diffstat (limited to 'src/mem/ruby/slicc_interface')
-rw-r--r-- | src/mem/ruby/slicc_interface/AbstractController.cc | 164 | ||||
-rw-r--r-- | src/mem/ruby/slicc_interface/AbstractController.hh | 65 | ||||
-rw-r--r-- | src/mem/ruby/slicc_interface/Controller.py | 8 |
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") |