diff options
author | Sebastian Koslowski <koslowski@kit.edu> | 2014-09-17 12:36:58 -0400 |
---|---|---|
committer | Sebastian Koslowski <koslowski@kit.edu> | 2014-11-07 11:31:53 +0100 |
commit | ac726bdd0aac71cbd85c7dcb11c718cd7e2732d7 (patch) | |
tree | d23f11867c205d63061a77e718abfd47be18be65 | |
parent | 4a517e173699d8338b08aacc456f4d18c2ba8adf (diff) |
grc: refactor/enhance hier block generation
-rw-r--r-- | grc/blocks/pad_sink.xml | 4 | ||||
-rw-r--r-- | grc/blocks/pad_source.xml | 4 | ||||
-rw-r--r-- | grc/python/FlowGraph.py | 80 | ||||
-rw-r--r-- | grc/python/Generator.py | 177 | ||||
-rw-r--r-- | grc/python/flow_graph.tmpl | 14 |
5 files changed, 151 insertions, 128 deletions
diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml index 37e132c34c..b022fa3d0d 100644 --- a/grc/blocks/pad_sink.xml +++ b/grc/blocks/pad_sink.xml @@ -7,9 +7,7 @@ <block> <name>Pad Sink</name> <key>pad_sink</key> - <make>#if str($type) == "message" -None;self.message_port_register_hier_in($label) -#end if</make> + <make></make> <param> <name>Label</name> <key>label</key> diff --git a/grc/blocks/pad_source.xml b/grc/blocks/pad_source.xml index 745e48c080..c0fb19eee7 100644 --- a/grc/blocks/pad_source.xml +++ b/grc/blocks/pad_source.xml @@ -7,9 +7,7 @@ <block> <name>Pad Source</name> <key>pad_source</key> - <make>#if str($type) == "message" -None;self.message_port_register_hier_out($label) -#end if</make> + <make></make> <param> <name>Label</name> <key>label</key> diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py index daec2d4310..977200da66 100644 --- a/grc/python/FlowGraph.py +++ b/grc/python/FlowGraph.py @@ -58,34 +58,62 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): #return from cache return self._eval_cache[my_hash] - def get_io_signaturev(self, direction): + def get_hier_block_stream_io(self, direction): """ - Get a list of io signatures for this flow graph. + Get a list of stream io signatures for this flow graph. Args: direction: a string of 'in' or 'out' Returns: - a list of dicts with: type, label, vlen, size + a list of dicts with: type, label, vlen, size, optional """ - sorted_pads = { - 'in': self.get_pad_sources(), - 'out': self.get_pad_sinks(), - }[direction] - # we only want stream ports - sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads); - expanded_pads = []; - for i in sorted_pads: - for j in range(i.get_param('num_streams').get_evaluated()): - expanded_pads.append(i); - #load io signature - return [{ - 'label': str(pad.get_param('label').get_evaluated()), - 'type': str(pad.get_param('type').get_evaluated()), - 'vlen': str(pad.get_param('vlen').get_value()), - 'size': pad.get_param('type').get_opt('size'), - 'optional': bool(pad.get_param('optional').get_evaluated()), - } for pad in expanded_pads] + return filter(lambda p: p['type'] != "message", + self.get_hier_block_io(direction)) + + def get_hier_block_message_io(self, direction): + """ + Get a list of message io signatures for this flow graph. + + Args: + direction: a string of 'in' or 'out' + + Returns: + a list of dicts with: type, label, vlen, size, optional + """ + return filter(lambda p: p['type'] == "message", + self.get_hier_block_io(direction)) + + def get_hier_block_io(self, direction): + """ + Get a list of io ports for this flow graph. + + Args: + direction: a string of 'in' or 'out' + + Returns: + a list of dicts with: type, label, vlen, size, optional + """ + pads = self.get_pad_sources() if direction in ('sink', 'in') else \ + self.get_pad_sinks() if direction in ('source', 'out') else [] + ports = [] + for pad in pads: + master = { + 'label': str(pad.get_param('label').get_evaluated()), + 'type': str(pad.get_param('type').get_evaluated()), + 'vlen': str(pad.get_param('vlen').get_value()), + 'size': pad.get_param('type').get_opt('size'), + 'optional': bool(pad.get_param('optional').get_evaluated()), + } + num_ports = pad.get_param('num_streams').get_evaluated() + if num_ports > 1: + for i in xrange(num_ports): + clone = master.copy() + clone['label'] += str(i) + ports.append(clone) + else: + ports.append(master) + return ports def get_pad_sources(self): """ @@ -118,20 +146,14 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): key_offset = 0 pads = self.get_pad_sources() if port.is_source() else self.get_pad_sinks() for pad in pads: + if pad.get_param('type').get_evaluated() == "message": + continue if port.get_parent() == pad: return str(key_offset + int(port.get_key())) # assuming we have either only sources or sinks key_offset += len(pad.get_ports()) return -1 - def get_msg_pad_sources(self): - ps = self.get_pad_sources(); - return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); - - def get_msg_pad_sinks(self): - ps = self.get_pad_sinks(); - return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); - def get_imports(self): """ Get a set of all import statments in this flow graph namespace. diff --git a/grc/python/Generator.py b/grc/python/Generator.py index 35cb2d99d4..24d943d28d 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -34,6 +34,8 @@ from . import expr_utils class Generator(object): + """Adaptor for various generators (uses generate_options)""" + def __init__(self, flow_graph, file_path): """ Initialize the generator object. @@ -53,6 +55,7 @@ class Generator(object): return self._generate_options def __getattr__(self, item): + """get all other attrib from actual generator object""" return getattr(self._generator, item) @@ -60,7 +63,7 @@ class TopBlockGenerator(object): def __init__(self, flow_graph, file_path): """ - Initialize the generator object. + Initialize the top block generator object. Args: flow_graph: the flow graph object @@ -77,9 +80,11 @@ class TopBlockGenerator(object): filename = self._flow_graph.get_option('id') + '.py' self._file_path = os.path.join(dirname, filename) - def get_file_path(self): return self._file_path + def get_file_path(self): + return self._file_path def write(self): + """generate output and write it to files""" #do throttle warning throttling_blocks = filter(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks()) if not throttling_blocks and self._generate_options != 'hb': @@ -165,7 +170,7 @@ class TopBlockGenerator(object): #list of variable names var_ids = [var.get_id() for var in parameters + variables] #prepend self. - replace_dict = dict([(var_id, 'self.%s'%var_id) for var_id in var_ids]) + replace_dict = dict([(var_id, 'self.%s' % var_id) for var_id in var_ids]) #list of callbacks callbacks = [ expr_utils.expr_replace(cb, replace_dict) @@ -197,119 +202,113 @@ class TopBlockGenerator(object): class HierBlockGenerator(TopBlockGenerator): + """Extends the top block generator to also generate a block XML file""" def __init__(self, flow_graph, file_path): - TopBlockGenerator.__init__(self, flow_graph, file_path) + """ + Initialize the hier block generator object. + Args: + flow_graph: the flow graph object + file_path: where to write the py file (the xml goes into HIER_BLOCK_LIB_DIR) + """ + TopBlockGenerator.__init__(self, flow_graph, file_path) self._mode = HIER_BLOCK_FILE_MODE - - dirname = HIER_BLOCKS_LIB_DIR - filename = self._flow_graph.get_option('id') - - self._file_path = os.path.join(dirname, filename + '.py') + self._file_path = os.path.join(HIER_BLOCKS_LIB_DIR, + self._flow_graph.get_option('id') + '.py') self._file_path_xml = self._file_path + '.xml' - def get_file_path(self): return self._file_path - def get_file_path_xml(self): return self._file_path_xml + def get_file_path_xml(self): + return self._file_path_xml def write(self): + """generate output and write it to files""" TopBlockGenerator.write(self) ParseXML.to_file(self._build_block_n_from_flow_graph_io(), self.get_file_path_xml()) ParseXML.validate_dtd(self.get_file_path_xml(), BLOCK_DTD) def _build_block_n_from_flow_graph_io(self): - flow_graph = self._flow_graph - python_file = self.get_file_path() + """ + Generate a block XML nested data from the flow graph IO + Returns: + a xml node tree + """ #extract info from the flow graph - input_sigs = flow_graph.get_io_signaturev('in') - output_sigs = flow_graph.get_io_signaturev('out') - input_msgp = flow_graph.get_msg_pad_sources(); - output_msgp = flow_graph.get_msg_pad_sinks(); - parameters = flow_graph.get_parameters() - bussink = flow_graph.get_bussink() - bussrc = flow_graph.get_bussrc() - bus_struct_sink = flow_graph.get_bus_structure_sink() - bus_struct_src = flow_graph.get_bus_structure_src() - block_key = flow_graph.get_option('id') - block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title() - block_category = flow_graph.get_option('category') - block_desc = flow_graph.get_option('description') - block_author = flow_graph.get_option('author') + block_key = self._flow_graph.get_option('id') + parameters = self._flow_graph.get_parameters() + + def var_or_value(name): + if name in map(lambda p: p.get_id(), parameters): + return "$"+name + return name + #build the nested data block_n = odict() - block_n['name'] = block_name + block_n['name'] = self._flow_graph.get_option('title') or \ + self._flow_graph.get_option('id').replace('_', ' ').title() block_n['key'] = block_key - block_n['category'] = block_category - block_n['import'] = 'execfile("%s")'%python_file + block_n['category'] = self._flow_graph.get_option('category') + block_n['import'] = 'execfile("{0}")'.format(self.get_file_path()) #make data - if parameters: block_n['make'] = '%s(\n %s,\n)'%( - block_key, - ',\n '.join(['%s=$%s'%(param.get_id(), param.get_id()) for param in parameters]), - ) - else: block_n['make'] = '%s()'%block_key + if parameters: + block_n['make'] = '{cls}(\n {kwargs},\n)'.format( + cls=block_key, + kwargs=',\n '.join( + '{key}=${key}'.format(key=param.get_id()) for param in parameters + ), + ) + else: + block_n['make'] = '{cls}()'.format(cls=block_key) #callback data - block_n['callback'] = ['set_%s($%s)'%(param.get_id(), param.get_id()) for param in parameters] - #param data - params_n = list() + block_n['callback'] = [ + 'set_{key}(${key})'.format(key=param.get_id()) for param in parameters + ] + + # Parameters + block_n['param'] = list() for param in parameters: param_n = odict() param_n['name'] = param.get_param('label').get_value() or param.get_id() param_n['key'] = param.get_id() param_n['value'] = param.get_param('value').get_value() param_n['type'] = 'raw' - params_n.append(param_n) - block_n['param'] = params_n - #sink data stream ports - if bussink: - block_n['bus_sink'] = '1'; - if bussrc: - block_n['bus_source'] = '1'; - block_n['sink'] = list() - for input_sig in input_sigs: - sink_n = odict() - sink_n['name'] = input_sig['label'] - sink_n['type'] = input_sig['type'] - sink_n['vlen'] = var_or_value(input_sig['vlen'], parameters) - if input_sig['optional']: sink_n['optional'] = '1' - block_n['sink'].append(sink_n) - #sink data msg ports - for input_sig in input_msgp: - sink_n = odict() - sink_n['name'] = input_sig.get_param("label").get_value(); - sink_n['type'] = "message" - sink_n['optional'] = input_sig.get_param("optional").get_value(); - block_n['sink'].append(sink_n) - #source data stream ports - block_n['source'] = list() + block_n['param'].append(param_n) + + # bus stuff + if self._flow_graph.get_bussink(): + block_n['bus_sink'] = '1' + if self._flow_graph.get_bussrc(): + block_n['bus_source'] = '1' + + # sink/source ports + for direction in ('sink', 'source'): + block_n[direction] = list() + for port in self._flow_graph.get_hier_block_io(direction): + port_n = odict() + port_n['name'] = port['label'] + port_n['type'] = port['type'] + if port['type'] != "message": + port_n['vlen'] = var_or_value(port['vlen']) + if port['optional']: + port_n['optional'] = '1' + block_n[direction].append(port_n) + + # more bus stuff + bus_struct_sink = self._flow_graph.get_bus_structure_sink() if bus_struct_sink: - block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value(); + block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value() + bus_struct_src = self._flow_graph.get_bus_structure_src() if bus_struct_src: - block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value(); - for output_sig in output_sigs: - source_n = odict() - source_n['name'] = output_sig['label'] - source_n['type'] = output_sig['type'] - source_n['vlen'] = var_or_value(output_sig['vlen'], parameters) - if output_sig['optional']: source_n['optional'] = '1' - block_n['source'].append(source_n) - #source data msg ports - for output_sig in output_msgp: - source_n = odict() - source_n['name'] = output_sig.get_param("label").get_value(); - source_n['type'] = "message" - source_n['optional'] = output_sig.get_param("optional").get_value(); - block_n['source'].append(source_n) - #doc data - block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) - block_n['grc_source'] = "%s"%(flow_graph.grc_file_path) - #write the block_n to file - n = {'block': block_n} - return n + block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value() + # documentation + block_n['doc'] = "\n".join(field for field in ( + self._flow_graph.get_option('author'), + self._flow_graph.get_option('description'), + self.get_file_path() + ) if field) + block_n['grc_source'] = str(self._flow_graph.grc_file_path) -def var_or_value(name, parameters): - if name in map(lambda p: p.get_id(), parameters): - return "$"+name - return name - + n = {'block': block_n} + return n diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index bee9c68af5..b07c296d09 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -90,8 +90,8 @@ class $(class_name)(gr.top_block): def __init__($param_str): gr.top_block.__init__(self, "$title") #elif $generate_options == 'hb' - #set $in_sigs = $flow_graph.get_io_signaturev('in') - #set $out_sigs = $flow_graph.get_io_signaturev('out') + #set $in_sigs = $flow_graph.get_hier_block_stream_io('in') + #set $out_sigs = $flow_graph.get_hier_block_stream_io('out') class $(class_name)(gr.hier_block2): #def make_io_sig($io_sigs) #set $size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in $io_sigs] @@ -110,6 +110,12 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) $make_io_sig($in_sigs), $make_io_sig($out_sigs), ) + #for $pad in $flow_graph.get_hier_block_message_io('in') + self.message_port_register_hier_out("$pad['label']") + #end for + #for $pad in $flow_graph.get_hier_block_message_io('out') + self.message_port_register_hier_in("$pad['label']") + #end for #end if ######################################################## ##Create Parameters @@ -208,11 +214,11 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) #end for ######################################################## -##Create Asynch Message Connections +##Create Message Connections ######################################################## #if $messages2 $DIVIDER - # Asynch Message Connections + # Message Connections $DIVIDER #end if #for $msg in $messages2 |