diff options
author | Joel Hestness <jthestness@gmail.com> | 2015-08-14 00:19:44 -0500 |
---|---|---|
committer | Joel Hestness <jthestness@gmail.com> | 2015-08-14 00:19:44 -0500 |
commit | 581bae9ecbafd5e94c5405ca925a55cc6e5d7488 (patch) | |
tree | c4e9136882984e561b7c1c618361e4262b482869 /src/mem/slicc | |
parent | bf06911b3f6d992dc78489d66410f4580a17db7b (diff) | |
download | gem5-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.py | 16 | ||||
-rw-r--r-- | src/mem/slicc/symbols/StateMachine.py | 103 |
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 { |