diff options
-rw-r--r-- | grc/core/Block.py | 54 | ||||
-rw-r--r-- | grc/core/Platform.py | 9 | ||||
-rw-r--r-- | grc/core/Port.py | 79 |
3 files changed, 85 insertions, 57 deletions
diff --git a/grc/core/Block.py b/grc/core/Block.py index d37909b4b8..d3fe4d85f2 100644 --- a/grc/core/Block.py +++ b/grc/core/Block.py @@ -170,39 +170,45 @@ class Block(Element): """ Element.rewrite(self) - # Adjust nports, disconnect hidden ports - for ports in (self.sources, self.sinks): - for i, master_port in enumerate(ports): - nports = master_port.get_nports() or 1 - num_ports = 1 + len(master_port.get_clones()) - if master_port.get_hide(): - for connection in master_port.get_connections(): - self.parent.remove_element(connection) - if not nports and num_ports == 1: # Not a master port and no left-over clones - continue - # Remove excess cloned ports - for port in master_port.get_clones()[nports-1:]: - # Remove excess connections - for connection in port.get_connections(): - self.parent.remove_element(connection) - master_port.remove_clone(port) - ports.remove(port) - # Add more cloned ports - for j in range(num_ports, nports): - port = master_port.add_clone() - ports.insert(ports.index(master_port) + j, port) - - self.back_ofthe_bus(ports) - # Renumber non-message/message ports + def rekey(ports): + """Renumber non-message/message ports""" domain_specific_port_index = collections.defaultdict(int) for port in [p for p in ports if p.key.isdigit()]: domain = port.domain port.key = str(domain_specific_port_index[domain]) domain_specific_port_index[domain] += 1 + # Adjust nports, disconnect hidden ports + for ports in (self.sources, self.sinks): + self._rewrite_nports(ports) + self.back_ofthe_bus(ports) + rekey(ports) + + # disconnect hidden ports + for port in itertools.chain(self.sources, self.sinks): + if port.get_hide(): + for connection in port.get_connections(): + self.parent.remove_element(connection) + self.active_sources = [p for p in self.get_sources_gui() if not p.get_hide()] self.active_sinks = [p for p in self.get_sinks_gui() if not p.get_hide()] + def _rewrite_nports(self, ports): + for port in ports: + if port.is_clone: # Not a master port and no left-over clones + continue + nports = port.get_nports() or 1 + for clone in port.clones[nports-1:]: + # Remove excess connections + for connection in clone.get_connections(): + self.parent.remove_element(connection) + port.remove_clone(clone) + ports.remove(clone) + # Add more cloned ports + for j in range(1 + len(port.clones), nports): + clone = port.add_clone() + ports.insert(ports.index(port) + j, clone) + def validate(self): """ Validate this block. diff --git a/grc/core/Platform.py b/grc/core/Platform.py index 696281380e..997631d2c1 100644 --- a/grc/core/Platform.py +++ b/grc/core/Platform.py @@ -33,7 +33,7 @@ from .generator import Generator from .FlowGraph import FlowGraph from .Connection import Connection from .Block import Block, EPyBlock -from .Port import Port +from .Port import Port, PortClone from .Param import Param from .utils import extract_docs @@ -318,6 +318,7 @@ class Platform(Element): } port_classes = { None: Port, # default + 'clone': PortClone, # default } param_classes = { None: Param, # default @@ -333,9 +334,9 @@ class Platform(Element): return cls(parent, key=key, **kwargs) def get_new_param(self, parent, **kwargs): - cls = self.param_classes[None] + cls = self.param_classes[kwargs.pop('cls_key', None)] return cls(parent, **kwargs) def get_new_port(self, parent, **kwargs): - cls = self.port_classes[None] - return cls(parent, **kwargs)
\ No newline at end of file + cls = self.port_classes[kwargs.pop('cls_key', None)] + return cls(parent, **kwargs) diff --git a/grc/core/Port.py b/grc/core/Port.py index 9030bef375..f12eb075e7 100644 --- a/grc/core/Port.py +++ b/grc/core/Port.py @@ -104,8 +104,9 @@ def _get_sink_from_virtual_sink_port(vsp, traversed=[]): class Port(Element): is_port = True + is_clone = False - def __init__(self, block, direction, **n): + def __init__(self, parent, direction, **n): """ Make a new port from nested data. @@ -127,12 +128,12 @@ class Port(Element): n['key'] = 'msg' # Build the port - Element.__init__(self, parent=block) + Element.__init__(self, parent) # Grab the data self._name = n['name'] self.key = n['key'] - self._type = n.get('type', '') self.domain = n.get('domain') + self._type = n.get('type', '') self._hide = n.get('hide', '') self._dir = direction self._hide_evaluated = False # Updated on rewrite() @@ -140,7 +141,7 @@ class Port(Element): self._nports = n.get('nports', '') self._vlen = n.get('vlen', '') self._optional = bool(n.get('optional')) - self._clones = [] # References to cloned ports (for nports > 1) + self.clones = [] # References to cloned ports (for nports > 1) def __str__(self): if self.is_source: @@ -155,7 +156,7 @@ class Port(Element): Element.validate(self) if self.get_type() not in Constants.TYPE_TO_SIZEOF.keys(): self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type())) - platform = self.parent.parent.parent + platform = self.parent_platform if self.domain not in platform.domains: self.add_error_message('Domain key "{}" is not registered.'.format(self.domain)) if not self.get_enabled_connections() and not self.get_optional(): @@ -233,7 +234,7 @@ class Port(Element): """ vlen = self.parent.resolve_dependencies(self._vlen) try: - return int(self.parent.parent.evaluate(vlen)) + return max(1, int(self.parent_flowgraph.evaluate(vlen))) except: return 1 @@ -247,26 +248,17 @@ class Port(Element): the number of ports or 1 """ if self._nports == '': - return '' + return 1 nports = self.parent.resolve_dependencies(self._nports) try: - return max(1, int(self.parent.parent.evaluate(nports))) + return max(1, int(self.parent_flowgraph.evaluate(nports))) except: return 1 def get_optional(self): return bool(self._optional) - def get_clones(self): - """ - Get the clones of this master port (nports > 1) - - Returns: - a list of ports - """ - return self._clones - def add_clone(self): """ Create a clone of this (master) port and store a reference in self._clones. @@ -278,24 +270,23 @@ class Port(Element): the cloned port """ # Add index to master port name if there are no clones yet - if not self._clones: + if not self.clones: self._name = self._n['name'] + '0' # Also update key for none stream ports if not self.key.isdigit(): self.key = self._name - # Prepare a copy of the odict for the clone - n = self._n.copy() - # Remove nports from the key so the copy cannot be a duplicator - if 'nports' in n: - n.pop('nports') - n['name'] = self._n['name'] + str(len(self._clones) + 1) + name = self._n['name'] + str(len(self.clones) + 1) # Dummy value 99999 will be fixed later - n['key'] = '99999' if self.key.isdigit() else n['name'] + key = '99999' if self.key.isdigit() else name # Clone - port = self.__class__(self.parent, n, self._dir) - self._clones.append(port) + port_factory = self.parent_platform.get_new_port + port = port_factory(self.parent, direction=self._dir, + name=name, key=key, + master=self, cls_key='clone') + + self.clones.append(port) return port def remove_clone(self, port): @@ -303,9 +294,9 @@ class Port(Element): Remove a cloned port (from the list of clones only) Remove the index 0 of the master port name (and key9 if there are no more clones left """ - self._clones.remove(port) + self.clones.remove(port) # Remove index from master port name if there are no more clones - if not self._clones: + if not self.clones: self._name = self._n['name'] # Also update key for none stream ports if not self.key.isdigit(): @@ -369,3 +360,33 @@ class Port(Element): bus_index = [i for i in block_ports if i.get_type() == 'bus'].index(self) ports = [p for i, p in enumerate(ports) if i in bus_structure[bus_index]] return ports + + +class PortClone(Port): + + is_clone = True + + def __init__(self, parent, direction, master, name, key): + """ + Make a new port from nested data. + + Args: + block: the parent element + n: the nested odict + dir: the direction + """ + Element.__init__(self, parent) + self.master = master + self._name = name + self._key = key + self._nports = '1' + + def __getattr__(self, item): + return getattr(self.master, item) + + def add_clone(self): + raise NotImplementedError() + + def remove_clone(self, port): + raise NotImplementedError() + |