diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/protocol/RubySlicc_Defines.sm --- a/src/mem/protocol/RubySlicc_Defines.sm Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/protocol/RubySlicc_Defines.sm Wed May 27 13:06:59 2015 -0500 @@ -31,7 +31,6 @@ NodeID version; MachineID machineID; NodeID clusterID; -MessageBuffer responseFromMemory, ordered="false"; // Functions implemented in the AbstractController class for // making timing access to the memory maintained by the diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/network/MessageBuffer.hh --- a/src/mem/ruby/network/MessageBuffer.hh Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/network/MessageBuffer.hh Wed May 27 13:06:59 2015 -0500 @@ -46,13 +46,15 @@ #include "mem/ruby/network/MessageBufferNode.hh" #include "mem/ruby/slicc_interface/Message.hh" #include "mem/packet.hh" +#include "params/MessageBuffer.hh" +#include "sim/sim_object.hh" -class MessageBuffer +class MessageBuffer : public SimObject { public: - MessageBuffer(const std::string &name = ""); + MessageBuffer(const Params *p); - std::string name() const { return m_name; } + const std::string name() const { return m_name; } void setRecycleLatency(Cycles recycle_latency) { m_recycle_latency = recycle_latency; } diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/network/MessageBuffer.cc --- a/src/mem/ruby/network/MessageBuffer.cc Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/network/MessageBuffer.cc Wed May 27 13:06:59 2015 -0500 @@ -39,9 +39,9 @@ using namespace std; using m5::stl_helpers::operator<<; -MessageBuffer::MessageBuffer(const string &name) - : m_time_last_time_size_checked(0), m_time_last_time_enqueue(0), - m_time_last_time_pop(0), m_last_arrival_time(0) +MessageBuffer::MessageBuffer(const Params *p) + : SimObject(p), m_time_last_time_size_checked(0), + m_time_last_time_enqueue(0), m_time_last_time_pop(0), m_last_arrival_time(0) { m_msg_counter = 0; m_consumer = NULL; @@ -57,7 +57,7 @@ m_msgs_this_cycle = 0; m_not_avail_count = 0; m_priority_rank = 0; - m_name = name; + m_name = p->name; m_stall_msg_map.clear(); m_input_link_id = 0; @@ -421,3 +421,9 @@ return num_functional_writes; } + +MessageBuffer * +MessageBufferParams::create() +{ + return new MessageBuffer(this); +} diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/network/MessageBuffer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/MessageBuffer.py Wed May 27 13:06:59 2015 -0500 @@ -0,0 +1,39 @@ +# 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: Joel Hestness + +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject + +class MessageBuffer(SimObject): + type = 'MessageBuffer' + cxx_class = 'MessageBuffer' + cxx_header = "mem/ruby/network/MessageBuffer.hh" + ordered = Param.Bool(False, "Whether the buffer is ordered") + buffer_size = Param.Unsigned(0, "") + recycle_latency = Param.Unsigned(Parent.any, "") diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/network/SConscript --- a/src/mem/ruby/network/SConscript Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/network/SConscript Wed May 27 13:06:59 2015 -0500 @@ -35,6 +35,7 @@ SimObject('BasicLink.py') SimObject('BasicRouter.py') +SimObject('MessageBuffer.py') SimObject('Network.py') Source('BasicLink.cc') diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/network/simple/SimpleNetwork.cc --- a/src/mem/ruby/network/simple/SimpleNetwork.cc Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc Wed May 27 13:06:59 2015 -0500 @@ -121,7 +121,7 @@ for (int i = 0; i < m_virtual_networks; i++) { // allocate a buffer - MessageBuffer* buffer_ptr = new MessageBuffer; + MessageBuffer* buffer_ptr = new MessageBuffer(params()); buffer_ptr->setOrdering(true); if (m_buffer_size > 0) { diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/network/simple/Switch.cc --- a/src/mem/ruby/network/simple/Switch.cc Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/network/simple/Switch.cc Wed May 27 13:06:59 2015 -0500 @@ -96,7 +96,7 @@ out[i]->setSender(this); } - MessageBuffer* buffer_ptr = new MessageBuffer; + MessageBuffer* buffer_ptr = new MessageBuffer(params()); // Make these queues ordered buffer_ptr->setOrdering(true); if (m_network_ptr->getBufferSize() > 0) { diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/slicc_interface/AbstractController.hh --- a/src/mem/ruby/slicc_interface/AbstractController.hh Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/slicc_interface/AbstractController.hh Wed May 27 13:06:59 2015 -0500 @@ -67,6 +67,7 @@ void unblock(Address); virtual MessageBuffer* getMandatoryQueue() const = 0; + virtual MessageBuffer* getMemoryQueue() const = 0; virtual AccessPermission getAccessPermission(const Address& addr) = 0; virtual void print(std::ostream & out) const = 0; @@ -97,8 +98,8 @@ virtual void collateStats() {fatal("collateStats() should be overridden!");} - //! Set the message buffer with given name. - virtual void setNetQueue(const std::string& name, MessageBuffer *b) = 0; + //! Initialize the message buffers. + virtual void initNetQueues() = 0; /** A function used to return the port associated with this bus object. */ BaseMasterPort& getMasterPort(const std::string& if_name, @@ -201,10 +202,6 @@ /* 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 { diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/ruby/slicc_interface/AbstractController.cc --- a/src/mem/ruby/slicc_interface/AbstractController.cc Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/ruby/slicc_interface/AbstractController.cc Wed May 27 13:06:59 2015 -0500 @@ -39,16 +39,8 @@ 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()) + memoryPort(csprintf("%s.memory", name()), this, "") { - // 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 // of this particular type. @@ -66,6 +58,9 @@ m_delayVCHistogram.push_back(new Stats::Histogram()); m_delayVCHistogram[i]->init(10); } + if (getMemoryQueue()) { + getMemoryQueue()->setSender(this); + } } void @@ -287,9 +282,6 @@ { 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++; @@ -303,6 +295,7 @@ void AbstractController::recvTimingResp(PacketPtr pkt) { + assert(getMemoryQueue()); assert(pkt->isResponse()); std::shared_ptr msg = std::make_shared(clockEdge()); @@ -327,7 +320,7 @@ panic("Incorrect packet type received from memory controller!"); } - m_responseFromMemory_ptr->enqueue(msg); + getMemoryQueue()->enqueue(msg); delete pkt; } diff -r 056e0d156fdb -r 0c31c4ef98c0 src/mem/slicc/symbols/StateMachine.py --- a/src/mem/slicc/symbols/StateMachine.py Wed May 27 13:06:58 2015 -0500 +++ b/src/mem/slicc/symbols/StateMachine.py Wed May 27 13:06:59 2015 -0500 @@ -210,10 +210,8 @@ dflt_str = str(param.rvalue.inline()) + ', ' if param.type_ast.type.c_ident == "MessageBuffer": - if param["network"] == "To": - code('${{param.ident}} = MasterPort(${dflt_str}"")') - else: - code('${{param.ident}} = SlavePort(${dflt_str}"")') + # The MessageBuffer MUST be instantiated in the protocol config + code('${{param.ident}} = Param.MessageBuffer("")') elif python_class_map.has_key(param.type_ast.type.c_ident): python_type = python_class_map[param.type_ast.type.c_ident] @@ -223,6 +221,15 @@ self.error("Unknown c++ to python class conversion for c++ " \ "type: '%s'. Please update the python_class_map " \ "in StateMachine.py", param.type_ast.type.c_ident) + + # Also add any mandatory or memory queue, even though they must + # be declared as internal MessageBuffers! + for var in self.objects: + if var.ident.find("mandatoryQueue") >= 0: + code('mandatoryQueue = Param.MessageBuffer("")') + elif var.ident.find("responseFromMemory") >= 0: + code('responseFromMemory = Param.MessageBuffer("")') + code.dedent() code.write(path, '%s.py' % py_ident) @@ -274,7 +281,8 @@ void init(); MessageBuffer* getMandatoryQueue() const; - void setNetQueue(const std::string& name, MessageBuffer *b); + MessageBuffer* getMemoryQueue() const; + void initNetQueues(); void print(std::ostream& out) const; void wakeup(); @@ -496,12 +504,6 @@ # include a sequencer, connect the it to the controller. # for param in self.config_parameters: - - # Do not initialize messgage buffers since they are initialized - # when the port based connections are made. - if param.type_ast.type.c_ident == "MessageBuffer": - continue - if param.pointer: code('m_${{param.ident}}_ptr = p->${{param.ident}};') else: @@ -511,9 +513,13 @@ code('m_${{param.ident}}_ptr->setController(this);') for var in self.objects: - if var.ident.find("mandatoryQueue") >= 0: + # Mandatory and memory queues are instantiated internally to + # StateMachines but exposed to components outside SLICC, so make + # sure to set up this controller as their receivers + if var.ident.find("mandatoryQueue") >= 0 or \ + var.ident.find("responseFromMemory") >= 0: code(''' -m_${{var.ident}}_ptr = new ${{var.type.c_ident}}(); +m_${{var.ident}}_ptr = p->${{var.ident}}; m_${{var.ident}}_ptr->setReceiver(this); ''') @@ -534,7 +540,7 @@ } void -$c_ident::setNetQueue(const std::string& name, MessageBuffer *b) +$c_ident::initNetQueues() { MachineType machine_type = string_to_MachineType("${{self.ident}}"); int base M5_VAR_USED = MachineType_base_number(machine_type); @@ -552,12 +558,8 @@ vtype = var.type_ast.type vid = "m_%s_ptr" % var.ident - code(''' -if ("${{var.ident}}" == name) { - $vid = b; - assert($vid != NULL); -''') - code.indent() + code('assert($vid != NULL);') + # Network port object network = var["network"] ordered = var["ordered"] @@ -571,7 +573,7 @@ code(''' m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet, - "$vnet_type", b); + "$vnet_type", $vid); ''') # Set the end if network == "To": @@ -604,8 +606,6 @@ code(''' $vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]"); ''') - code.dedent() - code('}\n') code.dedent() code(''' @@ -615,7 +615,7 @@ $c_ident::init() { // initialize objects - + initNetQueues(); ''') code.indent() @@ -631,12 +631,15 @@ code('(*$vid) = ${{var["default"]}};') else: # Normal Object - if var.ident.find("mandatoryQueue") < 0: + if var.ident.find("mandatoryQueue") < 0 and \ + var.ident.find("responseFromMemory") < 0: th = var.get("template", "") expr = "%s = new %s%s" % (vid, vtype.c_ident, th) args = "" if "non_obj" not in vtype and not vtype.isEnumeration: args = var.get("constructor", "") + if vtype.c_ident == 'MessageBuffer': + args = 'params()' code('$expr($args);') code('assert($vid != NULL);') @@ -717,6 +720,11 @@ if port.code.find("mandatoryQueue_ptr") >= 0: mq_ident = "m_mandatoryQueue_ptr" + memq_ident = "NULL" + for port in self.in_ports: + if port.code.find("responseFromMemory_ptr") >= 0: + memq_ident = "m_responseFromMemory_ptr" + seq_ident = "NULL" for param in self.config_parameters: if param.ident == "sequencer": @@ -841,6 +849,12 @@ return $mq_ident; } +MessageBuffer* +$c_ident::getMemoryQueue() const +{ + return $memq_ident; +} + Sequencer* $c_ident::getSequencer() const { diff -r 056e0d156fdb -r 0c31c4ef98c0 src/python/swig/pyobject.cc --- a/src/python/swig/pyobject.cc Wed May 27 13:06:58 2015 -0500 +++ b/src/python/swig/pyobject.cc Wed May 27 13:06:59 2015 -0500 @@ -100,26 +100,6 @@ } #endif - // These could be objects from the ruby memory system. If yes, then at - // least one of them should be an abstract controller. Do a type check. - AbstractController *ac1, *ac2; - ac1 = dynamic_cast(o1); - ac2 = dynamic_cast(o2); - - if ((ac1 || ac2) && name1 != "memory" && name2 != "memory") { - MessageBuffer *b = new MessageBuffer(); - - // set the message buffer associated with the provided names - if (ac1) { - ac1->setNetQueue(name1, b); - } - if (ac2) { - ac2->setNetQueue(name2, b); - } - - return 1; - } - MemObject *mo1, *mo2; mo1 = dynamic_cast(o1); mo2 = dynamic_cast(o2);