summaryrefslogtreecommitdiff
path: root/src/mem/slicc/symbols/StateMachine.py
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2014-09-01 16:55:47 -0500
committerNilay Vaish <nilay@cs.wisc.edu>2014-09-01 16:55:47 -0500
commit7a0d5aafe4b845a2d1cff6210d7c6ee66e8aba61 (patch)
tree6ef6157a33d226688f2909998b71936976ee755b /src/mem/slicc/symbols/StateMachine.py
parent00286fc5cbb7b8635d56eb335fed11d1499e2552 (diff)
downloadgem5-7a0d5aafe4b845a2d1cff6210d7c6ee66e8aba61.tar.xz
ruby: message buffers: significant changes
This patch is the final patch in a series of patches. The aim of the series is to make ruby more configurable than it was. More specifically, the connections between controllers are not at all possible (unless one is ready to make significant changes to the coherence protocol). Moreover the buffers themselves are magically connected to the network inside the slicc code. These connections are not part of the configuration file. This patch makes changes so that these connections will now be made in the python configuration files associated with the protocols. This requires each state machine to expose the message buffers it uses for input and output. So, the patch makes these buffers configurable members of the machines. The patch drops the slicc code that usd to connect these buffers to the network. Now these buffers are exposed to the python configuration system as Master and Slave ports. In the configuration files, any master port can be connected any slave port. The file pyobject.cc has been modified to take care of allocating the actual message buffer. This is inline with how other port connections work.
Diffstat (limited to 'src/mem/slicc/symbols/StateMachine.py')
-rw-r--r--src/mem/slicc/symbols/StateMachine.py208
1 files changed, 118 insertions, 90 deletions
diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py
index 71fcc053f..736013612 100644
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -51,7 +51,12 @@ class StateMachine(Symbol):
def __init__(self, symtab, ident, location, pairs, config_parameters):
super(StateMachine, self).__init__(symtab, ident, location, pairs)
self.table = None
+
+ # Data members in the State Machine that have been declared before
+ # the opening brace '{' of the machine. Note that these along with
+ # the members in self.objects form the entire set of data members.
self.config_parameters = config_parameters
+
self.prefetchers = []
for param in config_parameters:
@@ -74,6 +79,10 @@ class StateMachine(Symbol):
self.transitions = []
self.in_ports = []
self.functions = []
+
+ # Data members in the State Machine that have been declared inside
+ # the {} machine. Note that these along with the config params
+ # form the entire set of data members of the machine.
self.objects = []
self.TBEType = None
self.EntryType = None
@@ -200,7 +209,13 @@ class $py_ident(RubyController):
if param.rvalue is not None:
dflt_str = str(param.rvalue.inline()) + ', '
- if python_class_map.has_key(param.type_ast.type.c_ident):
+ 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}"")')
+
+ elif python_class_map.has_key(param.type_ast.type.c_ident):
python_type = python_class_map[param.type_ast.type.c_ident]
code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")')
@@ -241,13 +256,10 @@ 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)
+ seen_types.add(var.type.ident)
# for adding information to the protocol debug trace
code('''
@@ -260,7 +272,9 @@ class $c_ident : public AbstractController
$c_ident(const Params *p);
static int getNumControllers();
void init();
+
MessageBuffer* getMandatoryQueue() const;
+ void setNetQueue(const std::string& name, MessageBuffer *b);
void print(std::ostream& out) const;
void wakeup();
@@ -340,8 +354,6 @@ static int m_num_controllers;
if proto:
code('$proto')
- if has_peer:
- code('void getQueuesFromPeer(AbstractController *);')
if self.EntryType != None:
code('''
@@ -404,7 +416,6 @@ 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
@@ -486,10 +497,17 @@ $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:
code('m_${{param.ident}} = p->${{param.ident}};')
+
if re.compile("sequencer").search(param.ident):
code('m_${{param.ident}}_ptr->setController(this);')
@@ -499,19 +517,8 @@ $c_ident::$c_ident(const Params *p)
m_${{var.ident}}_ptr = new ${{var.type.c_ident}}();
m_${{var.ident}}_ptr->setReceiver(this);
''')
- else:
- if "network" in var and "physical_network" in var and \
- var["network"] == "To":
- has_peer = True
- code('''
-m_${{var.ident}}_ptr = new ${{var.type.c_ident}}();
-peerQueueMap[${{var["physical_network"]}}] = m_${{var.ident}}_ptr;
-m_${{var.ident}}_ptr->setSender(this);
-''')
code('''
-if (p->peer != NULL)
- connectWithPeer(p->peer);
for (int state = 0; state < ${ident}_State_NUM; state++) {
for (int event = 0; event < ${ident}_Event_NUM; event++) {
@@ -528,16 +535,92 @@ for (int event = 0; event < ${ident}_Event_NUM; event++) {
}
void
-$c_ident::init()
+$c_ident::setNetQueue(const std::string& name, MessageBuffer *b)
{
- MachineType machine_type = string_to_MachineType("${{var.machine.ident}}");
+ MachineType machine_type = string_to_MachineType("${{self.ident}}");
int base M5_VAR_USED = MachineType_base_number(machine_type);
+''')
+ code.indent()
+
+ # set for maintaining the vnet, direction pairs already seen for this
+ # machine. This map helps in implementing the check for avoiding
+ # multiple message buffers being mapped to the same vnet.
+ vnet_dir_set = set()
+
+ for var in self.config_parameters:
+ if "network" in var:
+ vtype = var.type_ast.type
+ vid = "m_%s_ptr" % var.ident
+
+ code('''
+if ("${{var.ident}}" == name) {
+ $vid = b;
+ assert($vid != NULL);
+''')
+ code.indent()
+ # Network port object
+ network = var["network"]
+ ordered = var["ordered"]
+
+ if "virtual_network" in var:
+ vnet = var["virtual_network"]
+ vnet_type = var["vnet_type"]
+
+ assert (vnet, network) not in vnet_dir_set
+ vnet_dir_set.add((vnet,network))
+
+ code('''
+m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet,
+ "$vnet_type", b);
+''')
+ # Set the end
+ if network == "To":
+ code('$vid->setSender(this);')
+ 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('''
+}
+
+void
+$c_ident::init()
+{
// initialize objects
''')
code.indent()
+
for var in self.objects:
vtype = var.type
vid = "m_%s_ptr" % var.ident
@@ -589,55 +672,6 @@ $c_ident::init()
code('$vid->setSender(this);')
code('$vid->setReceiver(this);')
- else:
- # Network port object
- network = var["network"]
- ordered = var["ordered"]
-
- 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);
-''')
-
- # Set the end
- if network == "To":
- code('$vid->setSender(this);')
- else:
- code('$vid->setReceiver(this);')
-
- # 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 "rank" in var:
- code('$vid->setPriority(${{var["rank"]}})')
-
- # Set buffer size
- if vtype.isBuffer:
- code('''
-if (m_buffer_size > 0) {
- $vid->resize(m_buffer_size);
-}
-''')
-
- # set description (may be overriden later by port def)
- code('''
-$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]");
-
-''')
-
if vtype.isBuffer:
if "recycle_latency" in var:
code('$vid->setRecycleLatency( ' \
@@ -965,6 +999,13 @@ $c_ident::functionalReadBuffers(PacketPtr& pkt)
if vtype.isBuffer:
vid = "m_%s_ptr" % var.ident
code('if ($vid->functionalRead(pkt)) { return true; }')
+
+ for var in self.config_parameters:
+ vtype = var.type_ast.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.ident
+ code('if ($vid->functionalRead(pkt)) { return true; }')
+
code('''
return false;
}
@@ -982,31 +1023,18 @@ $c_ident::functionalWriteBuffers(PacketPtr& pkt)
if vtype.isBuffer:
vid = "m_%s_ptr" % var.ident
code('num_functional_writes += $vid->functionalWrite(pkt);')
+
+ for var in self.config_parameters:
+ vtype = var.type_ast.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.ident
+ code('num_functional_writes += $vid->functionalWrite(pkt);')
+
code('''
return num_functional_writes;
}
''')
- # 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.ident}}_ptr = peer->getPeerQueue(${{var["physical_network"]}});
-assert(m_${{var.ident}}_ptr != NULL);
-m_${{var.ident}}_ptr->setReceiver(this);
-
-''')
- code('}')
-
code.write(path, "%s.cc" % c_ident)
def printCWakeup(self, path, includes):