diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index c9ef71593..44dbb925f 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -209,6 +209,11 @@ def create_system(options, full_system, system, piobus = None, dma_ports = []): topology.makeTopology(options, network, IntLinkClass, ExtLinkClass, RouterClass) + if options.garnet_network is None: + assert(NetworkClass == SimpleNetwork) + assert(RouterClass == Switch) + network.setup_buffers() + if InterfaceClass != None: netifs = [InterfaceClass(id=i) for (i,n) in enumerate(network.ext_links)] network.netifs = netifs diff --git a/src/mem/protocol/RubySlicc_Defines.sm b/src/mem/protocol/RubySlicc_Defines.sm index 514a307df..d25250864 100644 --- a/src/mem/protocol/RubySlicc_Defines.sm +++ b/src/mem/protocol/RubySlicc_Defines.sm @@ -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 --git a/src/mem/ruby/network/MessageBuffer.cc b/src/mem/ruby/network/MessageBuffer.cc index 484d2876b..e9bbd0059 100644 --- a/src/mem/ruby/network/MessageBuffer.cc +++ b/src/mem/ruby/network/MessageBuffer.cc @@ -39,25 +39,23 @@ 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_recycle_latency(p->recycle_latency), + m_max_size(p->buffer_size), 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_strict_fifo(p->ordered), + m_randomization(p->randomization) { m_msg_counter = 0; m_consumer = NULL; m_sender = NULL; m_receiver = NULL; - m_ordering_set = false; - m_strict_fifo = true; - m_max_size = 0; - m_randomization = true; m_size_last_time_size_checked = 0; m_size_at_cycle_start = 0; m_msgs_this_cycle = 0; m_not_avail_count = 0; m_priority_rank = 0; - m_name = name; m_stall_msg_map.clear(); m_input_link_id = 0; @@ -144,8 +142,6 @@ random_time() void MessageBuffer::enqueue(MsgPtr message, Cycles delta) { - assert(m_ordering_set); - // record current time incase we have a pop that also adjusts my size if (m_time_last_time_enqueue < m_sender->curCycle()) { m_msgs_this_cycle = 0; // first msg this cycle @@ -184,7 +180,7 @@ MessageBuffer::enqueue(MsgPtr message, Cycles delta) if (arrival_time < m_last_arrival_time) { panic("FIFO ordering violated: %s name: %s current time: %d " "delta: %d arrival_time: %d last arrival_time: %d\n", - *this, m_name, current_time, + *this, name(), current_time, delta * m_sender->clockPeriod(), arrival_time, m_last_arrival_time); } @@ -356,7 +352,7 @@ MessageBuffer::print(ostream& out) const vector copy(m_prio_heap); sort_heap(copy.begin(), copy.end(), greater()); - ccprintf(out, "%s] %s", copy, m_name); + ccprintf(out, "%s] %s", copy, name()); } bool @@ -424,3 +420,9 @@ MessageBuffer::functionalWrite(Packet *pkt) return num_functional_writes; } + +MessageBuffer * +MessageBufferParams::create() +{ + return new MessageBuffer(this); +} diff --git a/src/mem/ruby/network/MessageBuffer.hh b/src/mem/ruby/network/MessageBuffer.hh index 3ced44250..d47284eb1 100644 --- a/src/mem/ruby/network/MessageBuffer.hh +++ b/src/mem/ruby/network/MessageBuffer.hh @@ -41,20 +41,19 @@ #include #include +#include "debug/RubyQueue.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Consumer.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 = ""); - - std::string name() const { return m_name; } - - void setRecycleLatency(Cycles recycle_latency) - { m_recycle_latency = recycle_latency; } + typedef MessageBufferParams Params; + MessageBuffer(const Params *p); void reanalyzeMessages(const Address& addr); void reanalyzeAllMessages(); @@ -78,6 +77,7 @@ class MessageBuffer void setPriority(int rank) { m_priority_rank = rank; } void setConsumer(Consumer* consumer) { + DPRINTF(RubyQueue, "Setting consumer: %s\n", *consumer); if (m_consumer != NULL) { fatal("Trying to connect %s to MessageBuffer %s. \ \n%s already connected. Check the cntrl_id's.\n", @@ -88,21 +88,22 @@ class MessageBuffer void setSender(ClockedObject* obj) { + DPRINTF(RubyQueue, "Setting sender: %s\n", obj->name()); assert(m_sender == NULL || m_sender == obj); m_sender = obj; } void setReceiver(ClockedObject* obj) { + DPRINTF(RubyQueue, "Setting receiver: %s\n", obj->name()); assert(m_receiver == NULL || m_receiver == obj); m_receiver = obj; } - void setDescription(const std::string& name) { m_name = name; } - std::string getDescription() { return m_name;} - Consumer* getConsumer() { return m_consumer; } + bool getOrdered() { return m_strict_fifo; } + //! Function for extracting the message at the head of the //! message queue. The function assumes that the queue is nonempty. const Message* peek() const; @@ -126,16 +127,7 @@ class MessageBuffer bool isStallMapEmpty() { return m_stall_msg_map.size() == 0; } unsigned int getStallMapSize() { return m_stall_msg_map.size(); } - void - setOrdering(bool order) - { - m_strict_fifo = order; - m_ordering_set = true; - } - - void resize(unsigned int size) { m_max_size = size; } unsigned int getSize(); - void setRandomization(bool random_flag) { m_randomization = random_flag; } void clear(); void print(std::ostream& out) const; @@ -156,12 +148,12 @@ class MessageBuffer uint32_t functionalWrite(Packet *pkt); private: + //added by SS + const Cycles m_recycle_latency; + void reanalyzeList(std::list &, Tick); private: - //added by SS - Cycles m_recycle_latency; - // Data Members (m_ prefix) //! The two ends of the buffer. ClockedObject* m_sender; @@ -176,9 +168,8 @@ class MessageBuffer typedef std::map< Address, std::list > StallMsgMapType; StallMsgMapType m_stall_msg_map; - std::string m_name; - unsigned int m_max_size; + const unsigned int m_max_size; Cycles m_time_last_time_size_checked; unsigned int m_size_last_time_size_checked; @@ -195,9 +186,8 @@ class MessageBuffer // slots available uint64 m_msg_counter; int m_priority_rank; - bool m_strict_fifo; - bool m_ordering_set; - bool m_randomization; + const bool m_strict_fifo; + const bool m_randomization; int m_input_link_id; int m_vnet_id; diff --git a/src/mem/ruby/network/MessageBuffer.py b/src/mem/ruby/network/MessageBuffer.py new file mode 100644 index 000000000..88c528e30 --- /dev/null +++ b/src/mem/ruby/network/MessageBuffer.py @@ -0,0 +1,44 @@ +# Copyright (c) 2015 Mark D. Hill and David A. Wood. +# 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, "Maximum number of entries to buffer \ + (0 allows infinite entries)") + recycle_latency = Param.Cycles(Parent.recycle_latency, "") + randomization = Param.Bool(False, "") + + master = MasterPort("Master port to MessageBuffer receiver") + slave = SlavePort("Slave port from MessageBuffer sender") diff --git a/src/mem/ruby/network/SConscript b/src/mem/ruby/network/SConscript index 282d47647..36b02432f 100644 --- a/src/mem/ruby/network/SConscript +++ b/src/mem/ruby/network/SConscript @@ -35,6 +35,7 @@ if env['PROTOCOL'] == 'None': SimObject('BasicLink.py') SimObject('BasicRouter.py') +SimObject('MessageBuffer.py') SimObject('Network.py') Source('BasicLink.cc') diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc b/src/mem/ruby/network/simple/PerfectSwitch.cc index 06072724e..de038d211 100644 --- a/src/mem/ruby/network/simple/PerfectSwitch.cc +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc @@ -76,13 +76,6 @@ PerfectSwitch::addInPort(const vector& in) for (int i = 0; i < in.size(); ++i) { if (in[i] != nullptr) { in[i]->setConsumer(this); - - string desc = - csprintf("[Queue from port %s %s %s to PerfectSwitch]", - to_string(m_switch_id), to_string(port), - to_string(i)); - - in[i]->setDescription(desc); in[i]->setIncomingLink(port); in[i]->setVnet(i); } diff --git a/src/mem/ruby/network/simple/SimpleNetwork.cc b/src/mem/ruby/network/simple/SimpleNetwork.cc index 7426e9691..5b7d7ebad 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.cc +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc @@ -62,6 +62,9 @@ SimpleNetwork::SimpleNetwork(const Params *p) m_switches.push_back(s); s->init_net_ptr(this); } + + m_int_link_buffers = p->int_link_buffers; + m_num_connected_buffers = 0; } void @@ -78,7 +81,7 @@ SimpleNetwork::init() SimpleNetwork::~SimpleNetwork() { deletePointers(m_switches); - deletePointers(m_buffers_to_free); + deletePointers(m_int_link_buffers); } // From a switch to an endpoint node @@ -121,16 +124,10 @@ SimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link, for (int i = 0; i < m_virtual_networks; i++) { // allocate a buffer - MessageBuffer* buffer_ptr = new MessageBuffer; - buffer_ptr->setOrdering(true); - - if (m_buffer_size > 0) { - buffer_ptr->resize(m_buffer_size); - } - + assert(m_num_connected_buffers < m_int_link_buffers.size()); + MessageBuffer* buffer_ptr = m_int_link_buffers[m_num_connected_buffers]; + m_num_connected_buffers++; queues[i] = buffer_ptr; - // remember to deallocate it - m_buffers_to_free.push_back(buffer_ptr); } // Connect it to the two switches @@ -236,8 +233,8 @@ SimpleNetwork::functionalRead(Packet *pkt) } } - for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) { - if (m_buffers_to_free[i]->functionalRead(pkt)) { + for (unsigned int i = 0; i < m_int_link_buffers.size(); ++i) { + if (m_int_link_buffers[i]->functionalRead(pkt)) { return true; } } @@ -254,8 +251,8 @@ SimpleNetwork::functionalWrite(Packet *pkt) num_functional_writes += m_switches[i]->functionalWrite(pkt); } - for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) { - num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt); + for (unsigned int i = 0; i < m_int_link_buffers.size(); ++i) { + num_functional_writes += m_int_link_buffers[i]->functionalWrite(pkt); } return num_functional_writes; } diff --git a/src/mem/ruby/network/simple/SimpleNetwork.hh b/src/mem/ruby/network/simple/SimpleNetwork.hh index a2723c715..fe0c1838b 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.hh +++ b/src/mem/ruby/network/simple/SimpleNetwork.hh @@ -93,7 +93,8 @@ class SimpleNetwork : public Network SimpleNetwork& operator=(const SimpleNetwork& obj); std::vector m_switches; - std::vector m_buffers_to_free; + std::vector m_int_link_buffers; + int m_num_connected_buffers; std::vector m_endpoint_switches; int m_buffer_size; diff --git a/src/mem/ruby/network/simple/SimpleNetwork.py b/src/mem/ruby/network/simple/SimpleNetwork.py index 8d0442b7d..f4ec440a3 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.py +++ b/src/mem/ruby/network/simple/SimpleNetwork.py @@ -31,6 +31,7 @@ from m5.params import * from m5.proxy import * from Network import RubyNetwork from BasicRouter import BasicRouter +from MessageBuffer import MessageBuffer class SimpleNetwork(RubyNetwork): type = 'SimpleNetwork' @@ -39,9 +40,48 @@ class SimpleNetwork(RubyNetwork): "default buffer size; 0 indicates infinite buffering"); endpoint_bandwidth = Param.Int(1000, "bandwidth adjustment factor"); adaptive_routing = Param.Bool(False, "enable adaptive routing"); + int_link_buffers = VectorParam.MessageBuffer("Buffers for int_links") + # int_links do not recycle buffers, so this parameter is not used. + # TODO: Move recycle_latency out of MessageBuffers and into controllers + recycle_latency = Param.Cycles(0, "") + + def setup_buffers(self): + # Note that all SimpleNetwork MessageBuffers are currently ordered + network_buffers = [] + for link in self.int_links: + # The network needs number_of_virtual_networks buffers per + # int_link port + for i in xrange(self.number_of_virtual_networks): + network_buffers.append(MessageBuffer(ordered = True)) + network_buffers.append(MessageBuffer(ordered = True)) + self.int_link_buffers = network_buffers + + # Also add buffers for all router-link connections + for router in self.routers: + router_buffers = [] + # Add message buffers to routers for each internal link connection + for link in self.int_links: + if link.node_a == router: + for i in xrange(self.number_of_virtual_networks): + router_buffers.append(MessageBuffer(ordered = True)) + if link.node_b == router: + for i in xrange(self.number_of_virtual_networks): + router_buffers.append(MessageBuffer(ordered = True)) + + # Add message buffers to routers for each external link connection + for link in self.ext_links: + # Routers can only be int_nodes on ext_links + if link.int_node in self.routers: + for i in xrange(self.number_of_virtual_networks): + router_buffers.append(MessageBuffer(ordered = True)) + router.port_buffers = router_buffers class Switch(BasicRouter): type = 'Switch' cxx_header = 'mem/ruby/network/simple/Switch.hh' virt_nets = Param.Int(Parent.number_of_virtual_networks, "number of virtual networks") + port_buffers = VectorParam.MessageBuffer("Port buffers") + # Ports do not recycle buffers, so this parameter is not used. + # TODO: Move recycle_latency out of MessageBuffers and into controllers + recycle_latency = Param.Cycles(0, "") diff --git a/src/mem/ruby/network/simple/Switch.cc b/src/mem/ruby/network/simple/Switch.cc index 431a7b28f..b9d0b8010 100644 --- a/src/mem/ruby/network/simple/Switch.cc +++ b/src/mem/ruby/network/simple/Switch.cc @@ -43,6 +43,8 @@ using m5::stl_helpers::operator<<; Switch::Switch(const Params *p) : BasicRouter(p) { m_perfect_switch = new PerfectSwitch(m_id, this, p->virt_nets); + m_port_buffers = p->port_buffers; + m_num_connected_buffers = 0; } Switch::~Switch() @@ -53,7 +55,7 @@ Switch::~Switch() deletePointers(m_throttles); // Delete MessageBuffers - deletePointers(m_buffers_to_free); + deletePointers(m_port_buffers); } void @@ -97,15 +99,10 @@ Switch::addOutPort(const vector& out, out[i]->setSender(this); } - MessageBuffer* buffer_ptr = new MessageBuffer; - // Make these queues ordered - buffer_ptr->setOrdering(true); - if (m_network_ptr->getBufferSize() > 0) { - buffer_ptr->resize(m_network_ptr->getBufferSize()); - } - + assert(m_num_connected_buffers < m_port_buffers.size()); + MessageBuffer* buffer_ptr = m_port_buffers[m_num_connected_buffers]; + m_num_connected_buffers++; intermediateBuffers.push_back(buffer_ptr); - m_buffers_to_free.push_back(buffer_ptr); buffer_ptr->setSender(this); buffer_ptr->setReceiver(this); @@ -188,8 +185,8 @@ bool Switch::functionalRead(Packet *pkt) { // Access the buffers in the switch for performing a functional read - for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) { - if (m_buffers_to_free[i]->functionalRead(pkt)) { + for (unsigned int i = 0; i < m_port_buffers.size(); ++i) { + if (m_port_buffers[i]->functionalRead(pkt)) { return true; } } @@ -201,8 +198,8 @@ Switch::functionalWrite(Packet *pkt) { // Access the buffers in the switch for performing a functional write uint32_t num_functional_writes = 0; - for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) { - num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt); + for (unsigned int i = 0; i < m_port_buffers.size(); ++i) { + num_functional_writes += m_port_buffers[i]->functionalWrite(pkt); } return num_functional_writes; } diff --git a/src/mem/ruby/network/simple/Switch.hh b/src/mem/ruby/network/simple/Switch.hh index 3c11a5fa0..dbb1bbd05 100644 --- a/src/mem/ruby/network/simple/Switch.hh +++ b/src/mem/ruby/network/simple/Switch.hh @@ -89,7 +89,8 @@ class Switch : public BasicRouter PerfectSwitch* m_perfect_switch; SimpleNetwork* m_network_ptr; std::vector m_throttles; - std::vector m_buffers_to_free; + std::vector m_port_buffers; + unsigned m_num_connected_buffers; // Statistical variables Stats::Formula m_avg_utilization; diff --git a/src/mem/ruby/network/simple/Throttle.cc b/src/mem/ruby/network/simple/Throttle.cc index 2164d76de..785e09aa2 100644 --- a/src/mem/ruby/network/simple/Throttle.cc +++ b/src/mem/ruby/network/simple/Throttle.cc @@ -100,7 +100,6 @@ Throttle::addLinks(const vector& in_vec, in_ptr->setConsumer(this); string desc = "[Queue to Throttle " + to_string(m_sID) + " " + to_string(m_node) + "]"; - in_ptr->setDescription(desc); } } diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc index dfcd61ab2..6bc5a9b96 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.cc +++ b/src/mem/ruby/slicc_interface/AbstractController.cc @@ -41,16 +41,8 @@ AbstractController::AbstractController(const Params *p) 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. @@ -68,6 +60,9 @@ AbstractController::init() m_delayVCHistogram.push_back(new Stats::Histogram()); m_delayVCHistogram[i]->init(10); } + if (getMemoryQueue()) { + getMemoryQueue()->setSender(this); + } } void @@ -298,9 +293,6 @@ 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++; @@ -314,6 +306,7 @@ AbstractController::functionalMemoryWrite(PacketPtr pkt) void AbstractController::recvTimingResp(PacketPtr pkt) { + assert(getMemoryQueue()); assert(pkt->isResponse()); std::shared_ptr msg = std::make_shared(clockEdge()); @@ -338,7 +331,7 @@ AbstractController::recvTimingResp(PacketPtr pkt) panic("Incorrect packet type received from memory controller!"); } - m_responseFromMemory_ptr->enqueue(msg); + getMemoryQueue()->enqueue(msg); delete pkt; } diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index aadf03bd8..afde97b1f 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -75,6 +75,7 @@ class AbstractController : public MemObject, public Consumer 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; @@ -105,8 +106,8 @@ class AbstractController : public MemObject, public Consumer 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, @@ -210,10 +211,6 @@ class AbstractController : public MemObject, public Consumer /* 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 --git a/src/mem/slicc/ast/ObjDeclAST.py b/src/mem/slicc/ast/ObjDeclAST.py index 92ff15d52..7cea70b32 100644 --- a/src/mem/slicc/ast/ObjDeclAST.py +++ b/src/mem/slicc/ast/ObjDeclAST.py @@ -47,22 +47,6 @@ class ObjDeclAST(DeclAST): type = self.type_ast.type - if type.isBuffer and "ordered" not in self: - self.error("Buffer object decls require an 'ordered' attribute") - - if "ordered" in self: - value = self["ordered"] - - if value not in ("true", "false"): - self.error("The 'ordered' attribute is '%s' " + \ - "must be 'true' or 'false'.", value) - - if "random" in self: - value = self["random"] - if value not in ("true", "false"): - self.error("The 'random' attribute is '%s' " + \ - "must be 'true' or 'false'.", value) - # FIXME : should all use accessors here to avoid public member # variables if self.ident == "version": diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 425bd522d..7a6d78458 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -235,10 +235,8 @@ class $py_ident(RubyController): 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] @@ -248,6 +246,13 @@ class $py_ident(RubyController): 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 MessageBuffers declared internally to the controller + # Note: This includes mandatory and memory queues + for var in self.objects: + if var.type.c_ident == "MessageBuffer": + code('${{var.ident}} = Param.MessageBuffer("")') + code.dedent() code.write(path, '%s.py' % py_ident) @@ -299,7 +304,8 @@ class $c_ident : public AbstractController 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(); @@ -525,12 +531,6 @@ $c_ident::$c_ident(const Params *p) # 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: @@ -540,9 +540,13 @@ $c_ident::$c_ident(const Params *p) code('m_${{param.ident}}_ptr->setController(this);') for var in self.objects: - if var.ident.find("mandatoryQueue") >= 0: + # Some MessageBuffers (e.g. 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.type.c_ident == "MessageBuffer": code(''' -m_${{var.ident}}_ptr = new ${{var.type.c_ident}}(); +m_${{var.ident}}_ptr = p->${{var.ident}}; m_${{var.ident}}_ptr->setReceiver(this); ''') @@ -563,7 +567,7 @@ for (int event = 0; event < ${ident}_Event_NUM; event++) { } 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); @@ -581,15 +585,10 @@ $c_ident::setNetQueue(const std::string& name, MessageBuffer *b) 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"] if "virtual_network" in var: vnet = var["virtual_network"] @@ -599,8 +598,8 @@ if ("${{var.ident}}" == name) { vnet_dir_set.add((vnet,network)) code(''' -m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet, - "$vnet_type", b); +m_net_ptr->set${network}NetQueue(m_version + base, $vid->getOrdered(), $vnet, + "$vnet_type", $vid); ''') # Set the end if network == "To": @@ -608,34 +607,10 @@ m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet, else: code('$vid->setReceiver(this);') - # Set ordering - code('$vid->setOrdering(${{var["ordered"]}});') - - # Set randomization - if "random" in var: - # A buffer - code('$vid->setRandomization(${{var["random"]}});') - # Set Priority if "rank" in var: code('$vid->setPriority(${{var["rank"]}})') - # Set buffer size - code('$vid->resize(m_buffer_size);') - - if "recycle_latency" in var: - code('$vid->setRecycleLatency( ' \ - 'Cycles(${{var["recycle_latency"]}}));') - else: - code('$vid->setRecycleLatency(m_recycle_latency);') - - # set description (may be overriden later by port def) - code(''' -$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]"); -''') - code.dedent() - code('}\n') - code.dedent() code(''' } @@ -644,7 +619,7 @@ void $c_ident::init() { // initialize objects - + initNetQueues(); ''') code.indent() @@ -660,7 +635,7 @@ $c_ident::init() code('(*$vid) = ${{var["default"]}};') else: # Normal Object - if var.ident.find("mandatoryQueue") < 0: + if var.type.c_ident != "MessageBuffer": th = var.get("template", "") expr = "%s = new %s%s" % (vid, vtype.c_ident, th) args = "" @@ -676,16 +651,6 @@ $c_ident::init() comment = "Type %s default" % vtype.ident code('*$vid = ${{vtype["default"]}}; // $comment') - # Set ordering - if "ordered" in var: - # A buffer - code('$vid->setOrdering(${{var["ordered"]}});') - - # Set randomization - if "random" in var: - # A buffer - code('$vid->setRandomization(${{var["random"]}});') - # Set Priority if vtype.isBuffer and "rank" in var: code('$vid->setPriority(${{var["rank"]}});') @@ -700,13 +665,6 @@ $c_ident::init() code('$vid->setSender(this);') code('$vid->setReceiver(this);') - if vtype.isBuffer: - if "recycle_latency" in var: - code('$vid->setRecycleLatency( ' \ - 'Cycles(${{var["recycle_latency"]}}));') - else: - code('$vid->setRecycleLatency(m_recycle_latency);') - # Set the prefetchers code() for prefetcher in self.prefetchers: @@ -716,8 +674,6 @@ $c_ident::init() for port in self.in_ports: # Set the queue consumers code('${{port.code}}.setConsumer(this);') - # Set the queue descriptions - code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') # Initialize the transition profiling code() @@ -746,6 +702,11 @@ $c_ident::init() 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": @@ -872,6 +833,12 @@ $c_ident::getMandatoryQueue() const return $mq_ident; } +MessageBuffer* +$c_ident::getMemoryQueue() const +{ + return $memq_ident; +} + Sequencer* $c_ident::getSequencer() const { diff --git a/src/python/swig/pyobject.cc b/src/python/swig/pyobject.cc index f90e456e2..85a303b43 100644 --- a/src/python/swig/pyobject.cc +++ b/src/python/swig/pyobject.cc @@ -100,23 +100,18 @@ connectPorts(SimObject *o1, const std::string &name1, int i1, } #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); - } + // These could be MessageBuffers from the ruby memory system. If so, they + // need not be connected to anything currently. + MessageBuffer *mb1, *mb2; + mb1 = dynamic_cast(o1); + mb2 = dynamic_cast(o2); + if (mb1 || mb2) { + // No need to connect anything here currently. MessageBuffer + // connections in Python only serve to print the connections in + // the config output. + // TODO: Add real ports to MessageBuffers and use MemObject connect + // code below to bind MessageBuffer senders and receivers return 1; }