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
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
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;
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
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);
}
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
return num_functional_writes;
}
+
+MessageBuffer *
+MessageBufferParams::create()
+{
+ return new MessageBuffer(this);
+}
#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();
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",
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;
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;
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;
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;
// 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;
--- /dev/null
+# 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")
SimObject('BasicLink.py')
SimObject('BasicRouter.py')
+SimObject('MessageBuffer.py')
SimObject('Network.py')
Source('BasicLink.cc')
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);
}
m_switches.push_back(s);
s->init_net_ptr(this);
}
+
+ m_int_link_buffers = p->int_link_buffers;
+ m_num_connected_buffers = 0;
}
void
SimpleNetwork::~SimpleNetwork()
{
deletePointers(m_switches);
- deletePointers(m_buffers_to_free);
+ deletePointers(m_int_link_buffers);
}
// From a switch to an endpoint node
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
}
}
- 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;
}
}
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;
}
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;
from m5.proxy import *
from Network import RubyNetwork
from BasicRouter import BasicRouter
+from MessageBuffer import MessageBuffer
class SimpleNetwork(RubyNetwork):
type = 'SimpleNetwork'
"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, "")
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()
deletePointers(m_throttles);
// Delete MessageBuffers
- deletePointers(m_buffers_to_free);
+ deletePointers(m_port_buffers);
}
void
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);
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;
}
}
{
// 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;
}
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;
in_ptr->setConsumer(this);
string desc = "[Queue to Throttle " + to_string(m_sID) + " " +
to_string(m_node) + "]";
- in_ptr->setDescription(desc);
}
}
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.
m_delayVCHistogram.push_back(new Stats::Histogram());
m_delayVCHistogram[i]->init(10);
}
+ if (getMemoryQueue()) {
+ getMemoryQueue()->setSender(this);
+ }
}
void
{
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++;
void
AbstractController::recvTimingResp(PacketPtr pkt)
{
+ assert(getMemoryQueue());
assert(pkt->isResponse());
std::shared_ptr<MemoryMsg> msg = std::make_shared<MemoryMsg>(clockEdge());
panic("Incorrect packet type received from memory controller!");
}
- m_responseFromMemory_ptr->enqueue(msg);
+ getMemoryQueue()->enqueue(msg);
delete pkt;
}
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;
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,
/* 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
{
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":
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]
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)
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();
# 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:
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);
''')
}
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);
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"]
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":
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('''
}
$c_ident::init()
{
// initialize objects
-
+ initNetQueues();
''')
code.indent()
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 = ""
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"]}});')
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:
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()
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":
return $mq_ident;
}
+MessageBuffer*
+$c_ident::getMemoryQueue() const
+{
+ return $memq_ident;
+}
+
Sequencer*
$c_ident::getSequencer() const
{
}
#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;
}