summaryrefslogtreecommitdiff
path: root/src/mem/slicc
diff options
context:
space:
mode:
authorJoel Hestness <jthestness@gmail.com>2015-08-14 00:19:44 -0500
committerJoel Hestness <jthestness@gmail.com>2015-08-14 00:19:44 -0500
commit581bae9ecbafd5e94c5405ca925a55cc6e5d7488 (patch)
treec4e9136882984e561b7c1c618361e4262b482869 /src/mem/slicc
parentbf06911b3f6d992dc78489d66410f4580a17db7b (diff)
downloadgem5-581bae9ecbafd5e94c5405ca925a55cc6e5d7488.tar.xz
ruby: Expose MessageBuffers as SimObjects
Expose MessageBuffers from SLICC controllers as SimObjects that can be manipulated in Python. This patch has numerous benefits: 1) First and foremost, it exposes MessageBuffers as SimObjects that can be manipulated in Python code. This allows parameters to be set and checked in Python code to avoid obfuscating parameters within protocol files. Further, now as SimObjects, MessageBuffer parameters are printed to config output files as a way to track parameters across simulations (e.g. buffer sizes) 2) Cleans up special-case code for responseFromMemory buffers, and aligns their instantiation and use with mandatoryQueue buffers. These two special buffers are the only MessageBuffers that are exposed to components outside of SLICC controllers, and they're both slave ends of these buffers. They should be exposed outside of SLICC in the same way, and this patch does it. 3) Distinguishes buffer-specific parameters from buffer-to-network parameters. Specifically, buffer size, randomization, ordering, recycle latency, and ports are all specific to a MessageBuffer, while the virtual network ID and type are intrinsics of how the buffer is connected to network ports. The former are specified in the Python object, while the latter are specified in the controller *.sm files. Unlike buffer-specific parameters, which may need to change depending on the simulated system structure, buffer-to-network parameters can be specified statically for most or all different simulated systems.
Diffstat (limited to 'src/mem/slicc')
-rw-r--r--src/mem/slicc/ast/ObjDeclAST.py16
-rw-r--r--src/mem/slicc/symbols/StateMachine.py103
2 files changed, 35 insertions, 84 deletions
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
{