summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--grc/core/Block.py54
-rw-r--r--grc/core/Platform.py9
-rw-r--r--grc/core/Port.py79
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()
+