|
|
@@ -8,8 +8,6 @@ from collections import namedtuple
|
|
|
InputLink = namedtuple("InputLink", ["block", "output_port"])
|
|
|
Signal = namedtuple("Signal", ["time", "value"])
|
|
|
|
|
|
-epsilon = 0.001
|
|
|
-
|
|
|
class Port:
|
|
|
"""
|
|
|
Defines a port of a block.
|
|
|
@@ -211,7 +209,7 @@ class BaseBlock:
|
|
|
logger = logging.getLogger("CBD")
|
|
|
logger.warning("No block name given, using hashed object id. This is a bad practice and should be avoided.",
|
|
|
extra={"block": self})
|
|
|
- if re.match(r"[^a-zA-Z0-9_]", self.__block_name):
|
|
|
+ if re.search(r"[^a-zA-Z0-9_.]", self.__block_name):
|
|
|
logger = logging.getLogger("CBD")
|
|
|
logger.warning("Block names should only contain alphanumeric characters or underscores.", extra={"block": self})
|
|
|
|
|
|
@@ -405,7 +403,6 @@ class BaseBlock:
|
|
|
A list of ports that must be computed in order to compute this block,
|
|
|
at the time of the iteration.
|
|
|
"""
|
|
|
- # TODO: what with multiple sequential connectors
|
|
|
return [p.getIncoming().source for p in self.getInputPorts() if p.getIncoming() is not None]
|
|
|
|
|
|
def getPortConnectedToInput(self, input_port):
|
|
|
@@ -585,6 +582,9 @@ class CBD(BaseBlock):
|
|
|
self.__blocksDict = {}
|
|
|
self.__clock = None
|
|
|
|
|
|
+ # When flattened, we still want to access the old ports!
|
|
|
+ self.__aliases = {}
|
|
|
+
|
|
|
def clone(self):
|
|
|
# Clone all fields
|
|
|
other: CBD = BaseBlock.clone(self)
|
|
|
@@ -640,6 +640,8 @@ class CBD(BaseBlock):
|
|
|
for block in blocks:
|
|
|
if isinstance(block, CBD) and not block.getBlockType() in ignore:
|
|
|
block.flatten(ignore, psep)
|
|
|
+ for k, v in block.__aliases.items():
|
|
|
+ self.__aliases[block.getBlockName() + psep + k] = block.getBlockName() + psep + v
|
|
|
for child in block.getBlocks():
|
|
|
child.setBlockName(block.getBlockName() + psep + child.getBlockName())
|
|
|
self.addBlock(child)
|
|
|
@@ -653,6 +655,7 @@ class CBD(BaseBlock):
|
|
|
Port.disconnect(port, target)
|
|
|
self.addConnection(source.block, target.block, input_port_name=target.name,
|
|
|
output_port_name=source.name)
|
|
|
+ self.__aliases[block.getBlockName() + psep + port.name] = source.block.getBlockName() + psep + source.name
|
|
|
self.removeBlock(block)
|
|
|
|
|
|
def flattened(self, ignore=None, psep="."):
|
|
|
@@ -742,9 +745,9 @@ class CBD(BaseBlock):
|
|
|
formalisms/simulators, the Clock's outputs should be replaced with the
|
|
|
corresponding simulator's clock without loss of generality.
|
|
|
"""
|
|
|
- self.addBlock(Clock("%s-clock" % prefix, delta_t, start_time))
|
|
|
- self.addBlock(ConstantBlock("%s-delta" % prefix, delta_t))
|
|
|
- self.addConnection("%s-delta" % prefix, "%s-clock" % prefix, input_port_name='h')
|
|
|
+ self.addBlock(Clock("%s_clock" % prefix, delta_t, start_time))
|
|
|
+ self.addBlock(ConstantBlock("%s_delta" % prefix, delta_t))
|
|
|
+ self.addConnection("%s_delta" % prefix, "%s_clock" % prefix, input_port_name='h')
|
|
|
|
|
|
def addBlock(self, block):
|
|
|
"""
|
|
|
@@ -822,12 +825,6 @@ class CBD(BaseBlock):
|
|
|
to_block = self.getBlockByName(to_block)
|
|
|
to_block.linkToInput(from_block, name_input=input_port_name, name_output=output_port_name)
|
|
|
|
|
|
- def getDependencies(self, curIteration):
|
|
|
- deps = []
|
|
|
- for block in self.getBlocks():
|
|
|
- deps += [x for x in block.getDependencies(curIteration) if x.block == self]
|
|
|
- return deps
|
|
|
-
|
|
|
def removeConnection(self, block, input_port_name):
|
|
|
"""
|
|
|
Removes an input connection of block :code:`block` and port :code:`input_port_name`.
|
|
|
@@ -863,18 +860,33 @@ class CBD(BaseBlock):
|
|
|
"""
|
|
|
if path == '':
|
|
|
return self, self.getPath()
|
|
|
- cur = self
|
|
|
- for p in path.split(sep):
|
|
|
- if p in cur.__blocksDict:
|
|
|
- cur = cur.getBlockByName(p)
|
|
|
- elif p in cur.getInputPortNames():
|
|
|
- cur = cur.getInputPortByName(p)
|
|
|
- path = cur.block.getPath()
|
|
|
- elif p in cur.getOutputPortNames():
|
|
|
- cur = cur.getOutputPortByName(p)
|
|
|
- path = cur.block.getPath()
|
|
|
+ if path in self.__aliases:
|
|
|
+ return self.find(self.__aliases[path], sep)
|
|
|
+
|
|
|
+ ps = path.split(sep)
|
|
|
+ cur = None
|
|
|
+ px = 0
|
|
|
+ p = ps[px]
|
|
|
+ while px < len(ps):
|
|
|
+ if p in self.__blocksDict:
|
|
|
+ cur = self.getBlockByName(p)
|
|
|
+ if isinstance(cur, CBD):
|
|
|
+ cur, path = cur.find(sep.join(ps[1:]), sep)
|
|
|
+ else:
|
|
|
+ if p in self.getInputPortNames():
|
|
|
+ cur = self.getInputPortByName(p)
|
|
|
+ path = cur.block.getPath()
|
|
|
+ elif p in self.getOutputPortNames():
|
|
|
+ cur = self.getOutputPortByName(p)
|
|
|
+ path = cur.block.getPath()
|
|
|
+
|
|
|
+ if cur is None:
|
|
|
+ px += 1
|
|
|
+ p += sep + ps[px]
|
|
|
else:
|
|
|
- raise ValueError("Cannot find block '{}' in '{}'.".format(p, cur.getPath()))
|
|
|
+ break
|
|
|
+ if cur is None:
|
|
|
+ raise ValueError("Cannot find block '{}' in '{}'.".format(path, self.getPath()))
|
|
|
return cur, path
|
|
|
|
|
|
def __repr__(self):
|