summaryrefslogtreecommitdiff
path: root/grc/python
diff options
context:
space:
mode:
authorNicholas McCarthy <namccart@gmail.com>2013-07-07 18:08:20 -0400
committerJohnathan Corgan <johnathan@corganlabs.com>2013-07-08 07:19:33 -0700
commitcd99526b5d1c8b1130ac1ba87e21f96c621b1bdc (patch)
tree12836648bf75868b17b04a2c3ead9c1b6fa2d4c5 /grc/python
parent2dc1b6f2ed0cabd2bccbcc58487e93be4295df84 (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.py31
-rw-r--r--grc/python/Connection.py6
-rw-r--r--grc/python/Constants.py1
-rw-r--r--grc/python/FlowGraph.py80
-rw-r--r--grc/python/Generator.py2
-rw-r--r--grc/python/Port.py8
-rw-r--r--grc/python/block.dtd6
-rw-r--r--grc/python/convert_hier.py12
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']