ruby: connect two controllers using only message buffers

This patch modifies ruby so that two controllers can be connected to each
other with only message buffers in between. Before this patch, all the
controllers had to be connected to the network  for them to communicate
with each other. With this patch, one can have protocols where a controller
is not connected to the network, but communicates with another controller
through a message buffer.
This commit is contained in:
Nilay Vaish 2013-03-22 15:53:23 -05:00
parent 5aa43e130a
commit eccc86e809
5 changed files with 80 additions and 17 deletions

View file

@ -79,3 +79,10 @@ AbstractController::profileMsgDelay(uint32_t virtualNetwork, Cycles delay)
m_delayHistogram.add(delay);
m_delayVCHistogram[virtualNetwork].add(delay);
}
void
AbstractController::connectWithPeer(AbstractController *c)
{
getQueuesFromPeer(c);
c->getQueuesFromPeer(this);
}

View file

@ -97,12 +97,25 @@ class AbstractController : public ClockedObject, public Consumer
Histogram& getDelayVCHist(uint32_t index)
{ return m_delayVCHistogram[index]; }
MessageBuffer *getPeerQueue(uint32_t pid)
{
std::map<uint32_t, MessageBuffer *>::iterator it =
peerQueueMap.find(pid);
assert(it != peerQueueMap.end());
return (*it).second;
}
protected:
//! Profiles original cache requests including PUTs
void profileRequest(const std::string &request);
//! Profiles the delay associated with messages.
void profileMsgDelay(uint32_t virtualNetwork, Cycles delay);
//! Function for connecting peer controllers
void connectWithPeer(AbstractController *);
virtual void getQueuesFromPeer(AbstractController *)
{ fatal("getQueuesFromPeer() should be called only if implemented!"); }
protected:
int m_transitions_per_cycle;
int m_buffer_size;
@ -120,6 +133,9 @@ class AbstractController : public ClockedObject, public Consumer
int m_cur_in_port_rank;
int m_number_of_TBEs;
//! Map from physical network number to the Message Buffer.
std::map<uint32_t, MessageBuffer*> peerQueueMap;
//! Counter for the number of cycles when the transitions carried out
//! were equal to the maximum allowed
uint64_t m_fully_busy_cycles;

View file

@ -42,4 +42,6 @@ class RubyController(ClockedObject):
buffer_size = Param.Int(0, "max buffer size 0 means infinite")
recycle_latency = Param.Cycles(10, "")
number_of_TBEs = Param.Int(256, "")
ruby_system = Param.RubySystem("");
ruby_system = Param.RubySystem("")
peer = Param.RubyController(NULL, "")

View file

@ -41,7 +41,8 @@ class ObjDeclAST(DeclAST):
def generate(self):
machineComponentSym = False
if "network" in self and "virtual_network" not in self:
if "network" in self and not ("virtual_network" in self or
"physical_network" in self) :
self.error("Network queues require a 'virtual_network' attribute")
type = self.type_ast.type

View file

@ -239,9 +239,12 @@ class $py_ident(RubyController):
''')
seen_types = set()
has_peer = False
for var in self.objects:
if var.type.ident not in seen_types and not var.type.isPrimitive:
code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
if "network" in var and "physical_network" in var:
has_peer = True
seen_types.add(var.type.ident)
# for adding information to the protocol debug trace
@ -331,6 +334,8 @@ static int m_num_controllers;
if proto:
code('$proto')
if has_peer:
code('void getQueuesFromPeer(AbstractController *);')
if self.EntryType != None:
code('''
@ -388,6 +393,7 @@ void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr);
code = self.symtab.codeFormatter()
ident = self.ident
c_ident = "%s_Controller" % self.ident
has_peer = False
code('''
/** \\file $c_ident.cc
@ -514,8 +520,21 @@ m_dma_sequencer_ptr->setController(this);
code('''
m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();
m_${{var.c_ident}}_ptr->setReceiver(this);
''')
else:
if "network" in var and "physical_network" in var and \
var["network"] == "To":
has_peer = True
code('''
m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();
peerQueueMap[${{var["physical_network"]}}] = m_${{var.c_ident}}_ptr;
m_${{var.c_ident}}_ptr->setSender(this);
''')
code('''
if (p->peer != NULL)
connectWithPeer(p->peer);
''')
code.dedent()
code('''
}
@ -549,10 +568,7 @@ $c_ident::init()
code('(*$vid) = ${{var["default"]}};')
else:
# Normal Object
# added by SS
if "factory" in var:
code('$vid = ${{var["factory"]}};')
elif var.ident.find("mandatoryQueue") < 0:
if var.ident.find("mandatoryQueue") < 0:
th = var.get("template", "")
expr = "%s = new %s%s" % (vid, vtype.c_ident, th)
args = ""
@ -593,21 +609,22 @@ $c_ident::init()
# Network port object
network = var["network"]
ordered = var["ordered"]
vnet = var["virtual_network"]
vnet_type = var["vnet_type"]
assert var.machine is not None
code('''
if "virtual_network" in var:
vnet = var["virtual_network"]
vnet_type = var["vnet_type"]
assert var.machine is not None
code('''
$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type");
assert($vid != NULL);
''')
code('assert($vid != NULL);')
# Set the end
if network == "To":
code('$vid->setSender(this);')
else:
code('$vid->setReceiver(this);')
# Set the end
if network == "To":
code('$vid->setSender(this);')
else:
code('$vid->setReceiver(this);')
# Set ordering
if "ordered" in var:
@ -1007,6 +1024,26 @@ $c_ident::functionalWriteBuffers(PacketPtr& pkt)
}
''')
# Check if this controller has a peer, if yes then write the
# function for connecting to the peer.
if has_peer:
code('''
void
$c_ident::getQueuesFromPeer(AbstractController *peer)
{
''')
for var in self.objects:
if "network" in var and "physical_network" in var and \
var["network"] == "From":
code('''
m_${{var.c_ident}}_ptr = peer->getPeerQueue(${{var["physical_network"]}});
assert(m_${{var.c_ident}}_ptr != NULL);
m_${{var.c_ident}}_ptr->setReceiver(this);
''')
code('}')
code.write(path, "%s.cc" % c_ident)
def printCWakeup(self, path, includes):