From 581bae9ecbafd5e94c5405ca925a55cc6e5d7488 Mon Sep 17 00:00:00 2001 From: Joel Hestness Date: Fri, 14 Aug 2015 00:19:44 -0500 Subject: 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. --- src/mem/slicc/ast/ObjDeclAST.py | 16 ------ src/mem/slicc/symbols/StateMachine.py | 103 ++++++++++++---------------------- 2 files changed, 35 insertions(+), 84 deletions(-) (limited to 'src/mem/slicc') 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 { -- cgit v1.2.3