summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/ruby/Ruby.py5
-rw-r--r--src/mem/protocol/RubySlicc_Defines.sm1
-rw-r--r--src/mem/ruby/network/MessageBuffer.cc26
-rw-r--r--src/mem/ruby/network/MessageBuffer.hh44
-rw-r--r--src/mem/ruby/network/MessageBuffer.py44
-rw-r--r--src/mem/ruby/network/SConscript1
-rw-r--r--src/mem/ruby/network/simple/PerfectSwitch.cc7
-rw-r--r--src/mem/ruby/network/simple/SimpleNetwork.cc25
-rw-r--r--src/mem/ruby/network/simple/SimpleNetwork.hh3
-rw-r--r--src/mem/ruby/network/simple/SimpleNetwork.py40
-rw-r--r--src/mem/ruby/network/simple/Switch.cc23
-rw-r--r--src/mem/ruby/network/simple/Switch.hh3
-rw-r--r--src/mem/ruby/network/simple/Throttle.cc1
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.cc19
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh9
-rw-r--r--src/mem/slicc/ast/ObjDeclAST.py16
-rw-r--r--src/mem/slicc/symbols/StateMachine.py103
-rw-r--r--src/python/swig/pyobject.cc29
18 files changed, 202 insertions, 197 deletions
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<MsgPtr> copy(m_prio_heap);
sort_heap(copy.begin(), copy.end(), greater<MsgPtr>());
- 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 <string>
#include <vector>
+#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<MsgPtr> &, 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<MsgPtr> > 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<MessageBuffer*>& 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<Switch*> m_switches;
- std::vector<MessageBuffer*> m_buffers_to_free;
+ std::vector<MessageBuffer*> m_int_link_buffers;
+ int m_num_connected_buffers;
std::vector<Switch*> 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<MessageBuffer*>& 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<Throttle*> m_throttles;
- std::vector<MessageBuffer*> m_buffers_to_free;
+ std::vector<MessageBuffer*> 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<MessageBuffer*>& 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<MemoryMsg> msg = std::make_shared<MemoryMsg>(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<AbstractController*>(o1);
- ac2 = dynamic_cast<AbstractController*>(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<MessageBuffer*>(o1);
+ mb2 = dynamic_cast<MessageBuffer*>(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;
}