summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2013-03-22 15:53:23 -0500
committerNilay Vaish <nilay@cs.wisc.edu>2013-03-22 15:53:23 -0500
commiteccc86e8095995d49326a9fffc3a1088b97b03fc (patch)
tree1621ce6ec3a78f90a653628ba3d8b9108fc3d814
parent5aa43e130acec02bc616008a8758cf5096025c19 (diff)
downloadgem5-eccc86e8095995d49326a9fffc3a1088b97b03fc.tar.xz
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.
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.cc7
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh16
-rw-r--r--src/mem/ruby/slicc_interface/Controller.py4
-rw-r--r--src/mem/slicc/ast/ObjDeclAST.py3
-rw-r--r--src/mem/slicc/symbols/StateMachine.py67
5 files changed, 80 insertions, 17 deletions
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 9a0ee2b2b..1615f8c1d 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -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);
+}
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index ba0c4b683..81ef3c52b 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -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;
diff --git a/src/mem/ruby/slicc_interface/Controller.py b/src/mem/ruby/slicc_interface/Controller.py
index 5c2fd9b71..f8242322e 100644
--- a/src/mem/ruby/slicc_interface/Controller.py
+++ b/src/mem/ruby/slicc_interface/Controller.py
@@ -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, "")
diff --git a/src/mem/slicc/ast/ObjDeclAST.py b/src/mem/slicc/ast/ObjDeclAST.py
index 4509b4527..6469bc25a 100644
--- a/src/mem/slicc/ast/ObjDeclAST.py
+++ b/src/mem/slicc/ast/ObjDeclAST.py
@@ -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
diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py
index d5965d46d..3f54a1cdb 100644
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -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
@@ -515,7 +521,20 @@ m_dma_sequencer_ptr->setController(this);
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):