diff options
author | Nicholas McCarthy <namccart@gmail.com> | 2013-07-07 18:08:20 -0400 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2013-07-08 07:19:33 -0700 |
commit | cd99526b5d1c8b1130ac1ba87e21f96c621b1bdc (patch) | |
tree | 12836648bf75868b17b04a2c3ead9c1b6fa2d4c5 /grc/python | |
parent | 2dc1b6f2ed0cabd2bccbcc58487e93be4295df84 (diff) |
grc: add bus ports
Bus ports allow ganging together of block input or output ports into
a single display item for connection to other bus ports.
Diffstat (limited to 'grc/python')
-rw-r--r-- | grc/python/Block.py | 31 | ||||
-rw-r--r-- | grc/python/Connection.py | 6 | ||||
-rw-r--r-- | grc/python/Constants.py | 1 | ||||
-rw-r--r-- | grc/python/FlowGraph.py | 80 | ||||
-rw-r--r-- | grc/python/Generator.py | 2 | ||||
-rw-r--r-- | grc/python/Port.py | 8 | ||||
-rw-r--r-- | grc/python/block.dtd | 6 | ||||
-rw-r--r-- | grc/python/convert_hier.py | 12 |
8 files changed, 137 insertions, 9 deletions
diff --git a/grc/python/Block.py b/grc/python/Block.py index 806de46724..d365c43319 100644 --- a/grc/python/Block.py +++ b/grc/python/Block.py @@ -31,6 +31,8 @@ class Block(_Block, _GUIBlock): ##for make sink to keep track of indexes _sink_count = 0 + + def __init__(self, flow_graph, n): """ Make a new block from nested data. @@ -50,6 +52,8 @@ class Block(_Block, _GUIBlock): self._checks = n.findall('check') self._callbacks = n.findall('callback') self._throttle = n.find('throttle') or '' + self._bus_structure_source = n.find('bus_structure_source') or '' + self._bus_structure_sink = n.find('bus_structure_sink') or '' #build the block _Block.__init__( self, @@ -58,6 +62,21 @@ class Block(_Block, _GUIBlock): ) _GUIBlock.__init__(self) + def get_bus_structure(self, direction): + if direction == 'source': + bus_structure = self._bus_structure_source; + else: + bus_structure = self._bus_structure_sink; + + bus_structure = self.resolve_dependencies(bus_structure); + + if not bus_structure: return '' + try: + clean_bus_structure = self.get_parent().evaluate(bus_structure) + return clean_bus_structure + + except: return '' + def throttle(self): return bool(self._throttle) def validate(self): @@ -84,10 +103,11 @@ class Block(_Block, _GUIBlock): def rectify(ports): #restore integer contiguity after insertion #rectify the port names with the index + self.back_ofthe_bus(ports); for i, port in enumerate(ports): port._key = str(i) port._name = port._n['name'] - if len(ports) > 1: port._name += str(i) + if len(ports) > 1 and not port._type == 'bus': port._name += str(i) def insert_port(get_ports, get_port, key): prev_port = get_port(str(int(key)-1)) @@ -121,14 +141,19 @@ class Block(_Block, _GUIBlock): #remove excess ports and connections if nports < num_ports: for key in reversed(map(str, range(index_first+nports, index_first+num_ports))): - remove_port(get_ports, get_port, key) + remove_port(get_ports, get_port, key); + + continue #add more ports if nports > num_ports: for key in map(str, range(index_first+num_ports, index_first+nports)): insert_port(get_ports, get_port, key) + + continue - + + def port_controller_modify(self, direction): """ Change the port controller. diff --git a/grc/python/Connection.py b/grc/python/Connection.py index 341dd2d821..97bf61d590 100644 --- a/grc/python/Connection.py +++ b/grc/python/Connection.py @@ -33,7 +33,9 @@ class Connection(_Connection, _GUIConnection): def is_message(self): return self.get_source().get_type() == self.get_sink().get_type() == 'message' - + + def is_bus(self): + return self.get_source().get_type() == self.get_sink().get_type() == 'bus' def validate(self): """ Validate the connections. @@ -44,3 +46,5 @@ class Connection(_Connection, _GUIConnection): sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen() if source_size != sink_size: self.add_error_message('Source IO size "%s" does not match sink IO size "%s".'%(source_size, sink_size)) + + diff --git a/grc/python/Constants.py b/grc/python/Constants.py index b8dc9a96a1..5666a2378b 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -59,6 +59,7 @@ CORE_TYPES = ( #name, key, sizeof, color ('Integer 8', 's8', 1, '#FF66FF'), ('Message Queue', 'msg', 0, '#777777'), ('Async Message', 'message', 0, '#C0C0C0'), + ('Bus Connection', 'bus', 0, '#FFFFFF'), ('Wildcard', '', 0, '#FFFFFF'), ) diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py index 1080006cf5..89acfd89ef 100644 --- a/grc/python/FlowGraph.py +++ b/grc/python/FlowGraph.py @@ -20,11 +20,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import expr_utils from .. base.FlowGraph import FlowGraph as _FlowGraph from .. gui.FlowGraph import FlowGraph as _GUIFlowGraph +from .. base.odict import odict import re _variable_matcher = re.compile('^(variable\w*)$') _parameter_matcher = re.compile('^(parameter)$') _monitors_searcher = re.compile('(ctrlport_monitor)') +_bussink_searcher = re.compile('^(bus_sink)$') +_bussrc_searcher = re.compile('^(bus_source)$') +_bus_struct_sink_searcher = re.compile('^(bus_structure_sink)$') +_bus_struct_src_searcher = re.compile('^(bus_structure_source)$') + class FlowGraph(_FlowGraph, _GUIFlowGraph): @@ -48,6 +54,7 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): if not code: raise Exception, 'Cannot evaluate empty statement.' my_hash = hash(code) ^ namespace_hash #cache if does not exist + if not self._eval_cache.has_key(my_hash): self._eval_cache[my_hash] = eval(code, namespace, namespace) #return from cache @@ -69,6 +76,10 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): }[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()), @@ -76,7 +87,7 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): 'vlen': str(pad.get_param('vlen').get_evaluated()), 'size': pad.get_param('type').get_opt('size'), 'optional': bool(pad.get_param('optional').get_evaluated()), - } for pad in sorted_pads] + } for pad in expanded_pads] def get_pad_sources(self): """ @@ -145,12 +156,73 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): monitors = filter(lambda b: _monitors_searcher.search(b.get_key()), self.get_enabled_blocks()) return monitors + def get_bussink(self): + bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks()) + + for i in bussink: + for j in i.get_params(): + if j.get_name() == 'On/Off' and j.get_value() == 'on': + return True; + + return False + + + + def get_bussrc(self): + bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks()) + + for i in bussrc: + for j in i.get_params(): + if j.get_name() == 'On/Off' and j.get_value() == 'on': + return True; + + return False + + def get_bus_structure_sink(self): + bussink = filter(lambda b: _bus_struct_sink_searcher.search(b.get_key()), self.get_enabled_blocks()) + + return bussink + + def get_bus_structure_src(self): + bussrc = filter(lambda b: _bus_struct_src_searcher.search(b.get_key()), self.get_enabled_blocks()) + + return bussrc + + def rewrite(self): """ Flag the namespace to be renewed. """ + + + + + def reconnect_bus_blocks(): + for block in self.get_blocks(): + + if 'bus' in map(lambda a: a.get_type(), block.get_sources_gui()): + + + for i in range(len(block.get_sources_gui())): + if len(block.get_sources_gui()[i].get_connections()) > 0: + source = block.get_sources_gui()[i] + sink = [] + + for j in range(len(source.get_connections())): + sink.append(source.get_connections()[j].get_sink()); + + + for elt in source.get_connections(): + self.remove_element(elt); + for j in sink: + self.connect(source, j); self._renew_eval_ns = True - _FlowGraph.rewrite(self) + _FlowGraph.rewrite(self); + reconnect_bus_blocks(); + + + + def evaluate(self, expr): """ @@ -163,6 +235,8 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): Returns: the evaluated data """ + + if self._renew_eval_ns: self._renew_eval_ns = False #reload namespace @@ -188,6 +262,8 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): #make namespace public self.n = n self.n_hash = hash(str(n)) + #evaluate e = self._eval(expr, self.n, self.n_hash) + return e diff --git a/grc/python/Generator.py b/grc/python/Generator.py index 77abc45281..47fe1d98fd 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -123,7 +123,7 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') #list of regular blocks (all blocks minus the special ones) blocks = filter(lambda b: b not in (imports + parameters), blocks) #list of connections where each endpoint is enabled - connections = filter(lambda c: not (c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections()) + connections = filter(lambda c: not (c.is_bus() or c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections()) messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections()) messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections()) #list of variable names diff --git a/grc/python/Port.py b/grc/python/Port.py index d4afa6cf77..8ebf5c7b05 100644 --- a/grc/python/Port.py +++ b/grc/python/Port.py @@ -110,7 +110,8 @@ class Port(_Port, _GUIPort): self._nports = n.find('nports') or '' self._vlen = n.find('vlen') or '' self._optional = bool(n.find('optional')) - + + def get_types(self): return Constants.TYPE_TO_SIZEOF.keys() def is_type_empty(self): return not self._n['type'] @@ -174,6 +175,9 @@ class Port(_Port, _GUIPort): try: return int(self.get_parent().get_parent().evaluate(vlen)) except: return 1 + + + def get_nports(self): """ Get the number of ports. @@ -191,6 +195,8 @@ class Port(_Port, _GUIPort): if 0 < nports: return nports except: return 1 + + def get_optional(self): return bool(self._optional) def get_color(self): diff --git a/grc/python/block.dtd b/grc/python/block.dtd index 292ea06cb6..99d38a0d46 100644 --- a/grc/python/block.dtd +++ b/grc/python/block.dtd @@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Top level element. A block contains a name, ...parameters list, and list of IO ports. --> -<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, make, callback*, param*, check*, sink*, source*, doc?, grc_source?)> +<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, make, callback*, param*, bus_sink?, bus_source?, check*, sink*, source*, bus_structure_sink?, bus_structure_source?, doc?, grc_source?)> <!-- Sub level elements. --> @@ -44,11 +44,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <!ELEMENT name (#PCDATA)> <!ELEMENT key (#PCDATA)> <!ELEMENT check (#PCDATA)> +<!ELEMENT bus_sink (#PCDATA)> +<!ELEMENT bus_source (#PCDATA)> <!ELEMENT opt (#PCDATA)> <!ELEMENT type (#PCDATA)> <!ELEMENT hide (#PCDATA)> <!ELEMENT vlen (#PCDATA)> <!ELEMENT nports (#PCDATA)> +<!ELEMENT bus_structure_sink (#PCDATA)> +<!ELEMENT bus_structure_source (#PCDATA)> <!ELEMENT var_make (#PCDATA)> <!ELEMENT make (#PCDATA)> <!ELEMENT value (#PCDATA)> diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py index 508ec63b2b..de76827541 100644 --- a/grc/python/convert_hier.py +++ b/grc/python/convert_hier.py @@ -28,6 +28,10 @@ def convert_hier(flow_graph, python_file): 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') @@ -58,6 +62,10 @@ def convert_hier(flow_graph, python_file): 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() @@ -75,6 +83,10 @@ def convert_hier(flow_graph, python_file): block_n['sink'].append(sink_n) #source data stream ports block_n['source'] = list() + if bus_struct_sink: + block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value(); + 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'] |