|
|
@@ -12,6 +12,66 @@ Signal = namedtuple("Signal", ["time", "value"])
|
|
|
level = enum(WARNING=1, ERROR=2, FATAL=3)
|
|
|
epsilon = 0.001
|
|
|
|
|
|
+class Port:
|
|
|
+ IN = 0
|
|
|
+ OUT = 1
|
|
|
+
|
|
|
+ def __init__(self, name, direction, block):
|
|
|
+ self.name = name
|
|
|
+ self.direction = direction
|
|
|
+ self.block = block
|
|
|
+ self.__outgoing = []
|
|
|
+ self.__incoming = None
|
|
|
+ self.__history = []
|
|
|
+
|
|
|
+ def set(self, value):
|
|
|
+ self.__history.append(value)
|
|
|
+ for conn in self.__outgoing:
|
|
|
+ conn.transfer()
|
|
|
+
|
|
|
+ def get(self):
|
|
|
+ return self.__history[-1]
|
|
|
+
|
|
|
+ def clear(self):
|
|
|
+ self.__history.clear()
|
|
|
+
|
|
|
+ def getOutgoing(self):
|
|
|
+ return self.__outgoing
|
|
|
+
|
|
|
+ def getIncoming(self):
|
|
|
+ return self.__incoming
|
|
|
+
|
|
|
+ def getHistory(self):
|
|
|
+ return self.__history
|
|
|
+
|
|
|
+ def count(self):
|
|
|
+ return len(self.__history)
|
|
|
+
|
|
|
+ def _rewind(self):
|
|
|
+ self.__history.pop()
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def connect(source, target):
|
|
|
+ conn = Connector(source, target)
|
|
|
+ source.__outgoing.append(conn)
|
|
|
+ assert target.__incoming is None, "Fan-IN is not allowed!"
|
|
|
+ target.__incoming = conn
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def disconnect(source, target):
|
|
|
+ conn = target.__incoming
|
|
|
+ source.__outgoing.remove(conn)
|
|
|
+ target.__incoming = None
|
|
|
+
|
|
|
+
|
|
|
+class Connector:
|
|
|
+ def __init__(self, source, target):
|
|
|
+ self.source = source
|
|
|
+ self.target = target
|
|
|
+
|
|
|
+ def transfer(self):
|
|
|
+ self.target.set(self.source.get())
|
|
|
+
|
|
|
|
|
|
class BaseBlock:
|
|
|
"""
|
|
|
@@ -35,18 +95,24 @@ class BaseBlock:
|
|
|
# The output signals produced by this block are encoded in a dictionary.
|
|
|
# The key of this dictionary is the name of the output port.
|
|
|
# Each element of the dictionary contains an ordered list of values.
|
|
|
- self.__signals = dict()
|
|
|
+ # self.__signals = dict()
|
|
|
+ self.__outputs = {}
|
|
|
for output_port in output_ports:
|
|
|
- self.__signals[output_port] = []
|
|
|
+ self.addOutputPort(output_port)
|
|
|
+ # self.__signals[output_port] = []
|
|
|
+
|
|
|
|
|
|
# The input links produced by this block are encoded in a dictionary.
|
|
|
# The key of this dictionary is the name of the input port.
|
|
|
# Each element of the dictionary contains
|
|
|
# a tuple of the block and the output name of the other block.
|
|
|
- self._linksIn = dict()
|
|
|
+ # self._linksIn = dict()
|
|
|
+ self.__inputs = {}
|
|
|
+ for input_port in input_ports:
|
|
|
+ self.addInputPort(input_port)
|
|
|
|
|
|
# The list of possible input ports
|
|
|
- self.__nameLinks = input_ports
|
|
|
+ # self.__nameLinks = input_ports
|
|
|
# In which CBD the BaseBlock is situated
|
|
|
self._parent = None
|
|
|
|
|
|
@@ -57,8 +123,10 @@ class BaseBlock:
|
|
|
Args:
|
|
|
name (str): The name of the port.
|
|
|
"""
|
|
|
- if name not in self.__nameLinks:
|
|
|
- self.__nameLinks.append(name)
|
|
|
+ # if name not in self.__nameLinks:
|
|
|
+ # self.__nameLinks.append(name)
|
|
|
+ if name not in self.__inputs:
|
|
|
+ self.__inputs[name] = Port(name, Port.IN, self)
|
|
|
|
|
|
def addOutputPort(self, name):
|
|
|
"""
|
|
|
@@ -67,8 +135,41 @@ class BaseBlock:
|
|
|
Args:
|
|
|
name (str): The name of the port.
|
|
|
"""
|
|
|
- if name not in self.__signals:
|
|
|
- self.__signals[name] = []
|
|
|
+ # if name not in self.__signals:
|
|
|
+ # self.__signals[name] = []
|
|
|
+ if name not in self.__outputs:
|
|
|
+ self.__outputs[name] = Port(name, Port.OUT, self)
|
|
|
+
|
|
|
+ def getInputPorts(self):
|
|
|
+ return list(self.__inputs.values())
|
|
|
+
|
|
|
+ def getInputPortNames(self):
|
|
|
+ # return self.__nameLinks
|
|
|
+ return list(self.__inputs.keys())
|
|
|
+
|
|
|
+ def getInputPortByName(self, name):
|
|
|
+ assert self.hasInputPortWithName(name), "No such input '%s' in %s" % (name, self.getPath())
|
|
|
+ return self.__inputs[name]
|
|
|
+
|
|
|
+ def hasInputPortWithName(self, name):
|
|
|
+ return name in self.__inputs
|
|
|
+
|
|
|
+ def getOutputPorts(self):
|
|
|
+ return list(self.__outputs.values())
|
|
|
+
|
|
|
+ def getOutputPortByName(self, name):
|
|
|
+ assert self.hasOutputPortWithName(name), "No such output '%s' in %s" % (name, self.getPath())
|
|
|
+ return self.__outputs[name]
|
|
|
+
|
|
|
+ def getOutputPortNames(self):
|
|
|
+ return list(self.__outputs.keys())
|
|
|
+
|
|
|
+ def hasOutputPortWithName(self, name):
|
|
|
+ return name in self.__outputs
|
|
|
+
|
|
|
+ def reparentPorts(self):
|
|
|
+ for port in self.getInputPorts() + self.getOutputPorts():
|
|
|
+ port.block = self
|
|
|
|
|
|
def clone(self):
|
|
|
"""
|
|
|
@@ -76,7 +177,7 @@ class BaseBlock:
|
|
|
that were set on this block.
|
|
|
"""
|
|
|
other = deepcopy(self)
|
|
|
- other._linksIn.clear()
|
|
|
+ other.reparentPorts()
|
|
|
other._parent = None
|
|
|
return other
|
|
|
|
|
|
@@ -119,33 +220,6 @@ class BaseBlock:
|
|
|
"""
|
|
|
return self.__class__.__name__
|
|
|
|
|
|
- def getLinksIn(self):
|
|
|
- """
|
|
|
- Gets the inputs of this block.
|
|
|
- """
|
|
|
- return self._linksIn
|
|
|
-
|
|
|
- def getInputPortNames(self):
|
|
|
- return self.__nameLinks
|
|
|
-
|
|
|
- def getOutputNameOfInput(self, inputBlock):
|
|
|
- """
|
|
|
- Gets the name of the output port in the :code:`inputBlock` that is linked to this block.
|
|
|
-
|
|
|
- Args:
|
|
|
- inputBlock (BaseBlock): The block of which the output port must be obtained.
|
|
|
- """
|
|
|
- return [y for (x, y) in self._linksIn.items() if y.block == inputBlock][0].output_port
|
|
|
-
|
|
|
- def getInputName(self, inputBlock):
|
|
|
- """
|
|
|
- Gets the names of the inputs that are linked to the :code:`inputBlock`.
|
|
|
-
|
|
|
- Args:
|
|
|
- inputBlock (BaseBlock): The block that is linked.
|
|
|
- """
|
|
|
- return [x for (x, y) in self._linksIn.items() if y.block == inputBlock]
|
|
|
-
|
|
|
def getClock(self):
|
|
|
"""
|
|
|
Gets the simulation clock. Only works if the block is part of a :class:`CBD` model.
|
|
|
@@ -163,11 +237,11 @@ class BaseBlock:
|
|
|
the value of :code:`OUT1` will be used.
|
|
|
"""
|
|
|
name_output = "OUT1" if name_output is None else name_output
|
|
|
- assert name_output in self.__signals.keys()
|
|
|
- curIt = len(self.__signals[name_output])
|
|
|
- self.__signals[name_output].append(Signal(self.getClock().getTime(curIt), value))
|
|
|
+ port = self.getOutputPortByName(name_output)
|
|
|
+ curIt = port.count()
|
|
|
+ port.set(Signal(self.getClock().getTime(curIt), value))
|
|
|
|
|
|
- def getSignal(self, name_output=None):
|
|
|
+ def getSignalHistory(self, name_output=None):
|
|
|
"""
|
|
|
Obtains the set of signals this block has sent over an output port.
|
|
|
|
|
|
@@ -176,21 +250,11 @@ class BaseBlock:
|
|
|
the value of :code:`OUT1` will be used.
|
|
|
"""
|
|
|
name_output = "OUT1" if name_output is None else name_output
|
|
|
- assert name_output in self.__signals.keys(), "No such output '%s' in %s" % (name_output, self.getPath())
|
|
|
- return self.__signals[name_output]
|
|
|
+ return self.getOutputPortByName(name_output).getHistory()
|
|
|
|
|
|
- def getSignals(self):
|
|
|
- """
|
|
|
- Obtains all the signals of the block.
|
|
|
-
|
|
|
- Returns:
|
|
|
- Dictionary of :code:`output port name -> list of signals`.
|
|
|
- """
|
|
|
- return self.__signals
|
|
|
-
|
|
|
- def clearSignals(self):
|
|
|
- for i in self.__signals.keys():
|
|
|
- self.__signals[i].clear()
|
|
|
+ def clearPorts(self):
|
|
|
+ for port in self.getInputPorts() + self.getOutputPorts():
|
|
|
+ port.clear()
|
|
|
|
|
|
def getDependencies(self, curIteration):
|
|
|
"""
|
|
|
@@ -199,9 +263,13 @@ class BaseBlock:
|
|
|
Args:
|
|
|
curIteration (int): The current simulation's iteration, for which
|
|
|
the dependency graph must be constructed.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ A list of blocks that must be computed in order to compute this block,
|
|
|
+ at the time of the iteration.
|
|
|
"""
|
|
|
- # TO IMPLEMENT: this is a helper function you can use to create the dependency graph...
|
|
|
- return [x.block for x in self._linksIn.values()]
|
|
|
+ # TODO: what with multiple sequential connectors
|
|
|
+ return [p.getIncoming().source.block for p in self.getInputPorts() if p.getIncoming() is not None]
|
|
|
|
|
|
def getBlockConnectedToInput(self, input_port):
|
|
|
"""
|
|
|
@@ -210,7 +278,9 @@ class BaseBlock:
|
|
|
Args:
|
|
|
input_port (str): The name of the input port.
|
|
|
"""
|
|
|
- return self._linksIn[input_port]
|
|
|
+ incoming = self.getInputPortByName(input_port).getIncoming()
|
|
|
+ assert incoming is not None, "No block found that links to '%s' in '%s'." % (input_port, self.getPath())
|
|
|
+ return incoming.source
|
|
|
|
|
|
def getInputSignal(self, curIteration=-1, input_port="IN1"):
|
|
|
"""
|
|
|
@@ -223,8 +293,7 @@ class BaseBlock:
|
|
|
input_port (str): The name of the input port. If omitted, or when
|
|
|
:code:`None`, the value of :code:`IN1` will be used.
|
|
|
"""
|
|
|
- incoming_block, out_port_name = self._linksIn[input_port]
|
|
|
- return incoming_block.getSignal(out_port_name)[curIteration]
|
|
|
+ return self.getInputPortByName(input_port).getHistory()[curIteration]
|
|
|
|
|
|
def getPath(self, sep='.'):
|
|
|
"""Gets the path of the current block.
|
|
|
@@ -256,7 +325,7 @@ class BaseBlock:
|
|
|
"""
|
|
|
raise NotImplementedError("BaseBlock has nothing to compute")
|
|
|
|
|
|
- def linkInput(self, in_block, name_input=None, name_output=None):
|
|
|
+ def linkToInput(self, in_block, name_input=None, name_output=None):
|
|
|
"""
|
|
|
Links the output of the :code:`in_block` to the input of this block.
|
|
|
|
|
|
@@ -269,20 +338,20 @@ class BaseBlock:
|
|
|
"""
|
|
|
if name_output is None:
|
|
|
name_output = "OUT1"
|
|
|
- if name_input is not None:
|
|
|
- assert name_input in self.__nameLinks, "Cannot link blocks, no such input '%s' in %s" % (name_input, self.getPath())
|
|
|
- self._linksIn[name_input] = InputLink(in_block, name_output)
|
|
|
- else:
|
|
|
+ if name_input is None:
|
|
|
i = 1
|
|
|
while True:
|
|
|
nextIn = "IN" + str(i)
|
|
|
- if nextIn in self.__nameLinks:
|
|
|
- if not nextIn in self._linksIn:
|
|
|
- self._linksIn[nextIn] = InputLink(in_block, name_output)
|
|
|
- return
|
|
|
+ if self.hasInputPortWithName(nextIn):
|
|
|
+ if self.getInputPortByName(nextIn).getIncoming() is None:
|
|
|
+ name_input = nextIn
|
|
|
+ break
|
|
|
else:
|
|
|
- exit("There are no open IN inputs left in block %s" % self.getBlockName())
|
|
|
+ exit("There are no open IN inputs left in block %s" % self.getPath())
|
|
|
i += 1
|
|
|
+ source = in_block.getOutputPortByName(name_output)
|
|
|
+ target = self.getInputPortByName(name_input)
|
|
|
+ Port.connect(source, target)
|
|
|
|
|
|
def unlinkInput(self, name_input):
|
|
|
"""
|
|
|
@@ -291,8 +360,9 @@ class BaseBlock:
|
|
|
Args:
|
|
|
name_input (str): The name of the input.
|
|
|
"""
|
|
|
- assert name_input in self.__nameLinks, "Cannot link blocks, no such input '%s' in %s" % (name_input, self.getPath())
|
|
|
- del self._linksIn[name_input]
|
|
|
+ target = self.getOutputPortByName(name_input)
|
|
|
+ source = target.getIncoming()
|
|
|
+ Port.disconnect(source, target)
|
|
|
|
|
|
def __repr__(self):
|
|
|
return self.getPath() + ":" + self.getBlockType()
|
|
|
@@ -307,11 +377,12 @@ class BaseBlock:
|
|
|
"""
|
|
|
idt = "\t" * indent
|
|
|
repr = idt + self.getPath() + ":" + self.getBlockType() + "\n"
|
|
|
- if len(self._linksIn) == 0:
|
|
|
+ if len(self.__inputs) == 0:
|
|
|
repr += idt + " No incoming connections to IN ports\n"
|
|
|
else:
|
|
|
- for (key, (in_block, out_port)) in self._linksIn.items():
|
|
|
- repr += idt + " On input " + key + ": " + in_block.getPath() + ":" + in_block.getBlockType() + "\n"
|
|
|
+ for key, inport in self.__inputs:
|
|
|
+ in_block = inport.getIncoming().block
|
|
|
+ repr += "%s Input %s connected from %s (%s)\n" % (idt, key, in_block.getPath(), in_block.getBlockType())
|
|
|
return repr
|
|
|
|
|
|
def _rewind(self):
|
|
|
@@ -323,51 +394,8 @@ class BaseBlock:
|
|
|
of the CBD simulator, **not** by a user. Using this function without a
|
|
|
full understanding of the simulator may result in undefined behaviour.
|
|
|
"""
|
|
|
- for signal in self.getSignals().keys():
|
|
|
- self.__signals[signal].pop()
|
|
|
-
|
|
|
-
|
|
|
-class InputPortBlock(BaseBlock):
|
|
|
- """
|
|
|
- The input port of a CBD
|
|
|
- """
|
|
|
- def __init__(self, block_name, parent):
|
|
|
- BaseBlock.__init__(self, block_name, [], ["OUT1"])
|
|
|
- self._parent = parent
|
|
|
-
|
|
|
- def compute(self, curIteration):
|
|
|
- self.appendToSignal(self._parent.getInputSignal(curIteration, self.getBlockName()).value)
|
|
|
-
|
|
|
- @property
|
|
|
- def parent(self):
|
|
|
- return self._parent
|
|
|
-
|
|
|
-
|
|
|
-class OutputPortBlock(BaseBlock):
|
|
|
- """
|
|
|
- The output port of a CBD
|
|
|
- """
|
|
|
- def __init__(self, block_name, parent):
|
|
|
- BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
|
|
|
- self._parent = parent
|
|
|
-
|
|
|
- def compute(self, curIteration):
|
|
|
- self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
|
|
|
-
|
|
|
- @property
|
|
|
- def parent(self):
|
|
|
- return self._parent
|
|
|
-
|
|
|
-
|
|
|
-class WireBlock(BaseBlock):
|
|
|
- """
|
|
|
- When a CBD gets flattened, the port blocks will be replaced by a wire block
|
|
|
- """
|
|
|
- def __init__(self, block_name):
|
|
|
- BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
|
|
|
-
|
|
|
- def compute(self, curIteration):
|
|
|
- self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
|
|
|
+ for port in self.getInputPorts() + self.getOutputPorts():
|
|
|
+ port._rewind()
|
|
|
|
|
|
|
|
|
class CBD(BaseBlock):
|
|
|
@@ -387,22 +415,6 @@ class CBD(BaseBlock):
|
|
|
self.__blocksDict = {}
|
|
|
self.__clock = None
|
|
|
|
|
|
- for input_port in input_ports:
|
|
|
- self.addBlock(InputPortBlock(input_port, self))
|
|
|
-
|
|
|
- for output_port in output_ports:
|
|
|
- self.addBlock(OutputPortBlock(output_port, self))
|
|
|
-
|
|
|
- # TODO: automatically add Clock?
|
|
|
-
|
|
|
- def addInputPort(self, name):
|
|
|
- BaseBlock.addInputPort(self, name)
|
|
|
- self.addBlock(InputPortBlock(name, self))
|
|
|
-
|
|
|
- def addOutputPort(self, name):
|
|
|
- BaseBlock.addOutputPort(self, name)
|
|
|
- self.addBlock(OutputPortBlock(name, self))
|
|
|
-
|
|
|
def clone(self):
|
|
|
other = BaseBlock.clone(self)
|
|
|
# other.setClock(deepcopy(self.getClock()))
|
|
|
@@ -410,8 +422,8 @@ class CBD(BaseBlock):
|
|
|
for block in self.getBlocks():
|
|
|
other.addBlock(block.clone())
|
|
|
for block in self.getBlocks():
|
|
|
- for name_input, link in block.getLinksIn().items():
|
|
|
- other.addConnection(link.block.getBlockName(), block.getBlockName(), name_input, link.output_port)
|
|
|
+ for inp in block.getInputPorts():
|
|
|
+ other.addConnection(inp.block, block, inp.name, inp.getIncoming().source.name)
|
|
|
return other
|
|
|
|
|
|
def getTopCBD(self):
|
|
|
@@ -420,7 +432,7 @@ class CBD(BaseBlock):
|
|
|
"""
|
|
|
return self if self._parent is None else self._parent.getTopCBD()
|
|
|
|
|
|
- def flatten(self, parent=None, ignore=None, psep="."):
|
|
|
+ def flatten(self, ignore=None, psep="."):
|
|
|
"""
|
|
|
Flatten the CBD inline and call recursively for all sub-CBDs.
|
|
|
|
|
|
@@ -431,59 +443,22 @@ class CBD(BaseBlock):
|
|
|
no blocks are ignored. Defaults to :code:`None`.
|
|
|
psep (str): The path separator to use. Defaults to :code:`"."`.
|
|
|
"""
|
|
|
- if ignore is None:
|
|
|
- ignore = []
|
|
|
- blocksToRemove = []
|
|
|
- blocksToAdd = []
|
|
|
-
|
|
|
- # First flatten all top-layer blocks to ensure valid port connections
|
|
|
- for childBlock in self.__blocks:
|
|
|
- if isinstance(childBlock, CBD) and not childBlock.getBlockType() in ignore:
|
|
|
- childBlock.flatten(self, ignore, psep)
|
|
|
- blocksToRemove.append(childBlock)
|
|
|
-
|
|
|
- for childBlock in self.__blocks:
|
|
|
- if isinstance(childBlock, InputPortBlock) and parent is not None:
|
|
|
- # Replace InputPortBlock with WireBlock
|
|
|
- wb = WireBlock(childBlock.getBlockName())
|
|
|
-
|
|
|
- # Replace links going out of inputportblock
|
|
|
- blocksToRemove.append(childBlock)
|
|
|
- blocksToAdd.append(wb)
|
|
|
-
|
|
|
- for b in self.getBlocks():
|
|
|
- for input_name, output_port in [(x, y.output_port) for (x, y) in b._linksIn.items() if y.block == childBlock]:
|
|
|
- b._linksIn[input_name] = InputLink(wb, "OUT1")
|
|
|
-
|
|
|
- input = self._linksIn[wb.getBlockName()]
|
|
|
- parent.addConnection(input.block, wb, output_port_name=input.output_port)
|
|
|
- elif isinstance(childBlock, OutputPortBlock) and parent is not None:
|
|
|
- # Replace OutputPortBlock with WireBlock
|
|
|
- wb = WireBlock(childBlock.getBlockName())
|
|
|
- blocksToRemove.append(childBlock)
|
|
|
- blocksToAdd.append(wb)
|
|
|
-
|
|
|
- for (x, y) in childBlock._linksIn.items():
|
|
|
- wb._linksIn[x] = y
|
|
|
-
|
|
|
- # blocks connected to this output
|
|
|
- for b in parent.__blocks:
|
|
|
- for (portname, input) in b._linksIn.items():
|
|
|
- if input.block == self and input.output_port == wb.getBlockName():
|
|
|
- b._linksIn[portname] = InputLink(wb, "OUT1")
|
|
|
-
|
|
|
- # Delete blocksToRemove
|
|
|
- for block in blocksToRemove:
|
|
|
- self.removeBlock(block)
|
|
|
-
|
|
|
- for b in blocksToAdd:
|
|
|
- self.addBlock(b)
|
|
|
-
|
|
|
- if parent is not None:
|
|
|
- # Add all components to parent, do not copy blocksToRemove
|
|
|
- for block in [b for b in self.__blocks if not b in blocksToRemove]:
|
|
|
- block.setBlockName(self.getBlockName() + psep + block.getBlockName())
|
|
|
- parent.addBlock(block)
|
|
|
+ if ignore is None: ignore = []
|
|
|
+
|
|
|
+ for block in self.__blocks:
|
|
|
+ if isinstance(block, CBD) and not block.getBlockType() in ignore:
|
|
|
+ block.flatten(ignore, psep)
|
|
|
+ for child in block.getBlocks():
|
|
|
+ child.setBlockName(child.getPath(psep))
|
|
|
+ self.addBlock(child)
|
|
|
+ for port in block.getInputPorts() + block.getOutputPorts():
|
|
|
+ source = port.getIncoming().source
|
|
|
+ for conn in port.getOutgoing():
|
|
|
+ target = conn.target
|
|
|
+ self.addConnection(source.block, target.block, target.name, source.name)
|
|
|
+ Port.disconnect(port, target)
|
|
|
+ Port.disconnect(source, port)
|
|
|
+ self.removeBlock(block)
|
|
|
|
|
|
def getBlocks(self):
|
|
|
"""
|
|
|
@@ -570,14 +545,15 @@ class CBD(BaseBlock):
|
|
|
assert isinstance(block, BaseBlock), "Can only add BaseBlock (subclass) instances to a CBD"
|
|
|
block.setParent(self)
|
|
|
|
|
|
- if block.getBlockName() not in self.__blocksDict:
|
|
|
+ if block.getBlockName() not in self.__blocksDict and \
|
|
|
+ block.getBlockName() not in self.getOutputPortNames() + self.getInputPortNames():
|
|
|
self.__blocks.append(block)
|
|
|
self.__blocksDict[block.getBlockName()] = block
|
|
|
if isinstance(block, (Clock, DummyClock)):
|
|
|
self.__clock = block
|
|
|
else:
|
|
|
logger = naivelog.getLogger("CBD")
|
|
|
- logger.warning("Warning: did not add this block as it has the same name %s as an already existing block" % block.getBlockName())
|
|
|
+ logger.warning("Warning: did not add this block as it has the same name %s as an already existing block/port" % block.getBlockName())
|
|
|
|
|
|
def removeBlock(self, block):
|
|
|
"""
|
|
|
@@ -609,13 +585,21 @@ class CBD(BaseBlock):
|
|
|
:code:`OUT1` will be used.
|
|
|
|
|
|
See Also:
|
|
|
- :func:`BaseBlock.linkInput`
|
|
|
+ :func:`BaseBlock.linkToInput`
|
|
|
"""
|
|
|
if isinstance(from_block, str):
|
|
|
- from_block = self.getBlockByName(from_block)
|
|
|
+ if self.hasInputPortWithName(from_block):
|
|
|
+ from_block = self
|
|
|
+ output_port_name = from_block
|
|
|
+ else:
|
|
|
+ from_block = self.getBlockByName(from_block)
|
|
|
if isinstance(to_block, str):
|
|
|
- to_block = self.getBlockByName(to_block)
|
|
|
- to_block.linkInput(from_block, input_port_name, output_port_name)
|
|
|
+ if self.hasOutputPortWithName(to_block):
|
|
|
+ to_block = self
|
|
|
+ input_port_name = to_block
|
|
|
+ else:
|
|
|
+ to_block = self.getBlockByName(to_block)
|
|
|
+ to_block.linkToInput(from_block, input_port_name, output_port_name)
|
|
|
|
|
|
def removeConnection(self, block, input_port_name):
|
|
|
"""
|
|
|
@@ -691,19 +675,18 @@ class CBD(BaseBlock):
|
|
|
print("=========== Start of Signals Dump ===========")
|
|
|
for block in self.getBlocks():
|
|
|
print("%s:%s" % (block.getBlockName(), block.getBlockType()))
|
|
|
- print(str(block.getSignal()) + "\n")
|
|
|
+ print(str(block.getSignalHistory()) + "\n")
|
|
|
print("=========== End of Signals Dump =============\n")
|
|
|
|
|
|
- def getSignal(self, name_output=None):
|
|
|
+ def getSignalHistory(self, name_output=None):
|
|
|
name_output = "OUT1" if name_output is None else name_output
|
|
|
- portBlock = self.getBlockByName(name_output)
|
|
|
- assert portBlock is not None
|
|
|
- return portBlock.getSignal("OUT1")
|
|
|
+ port = self.getOutputPortByName(name_output)
|
|
|
+ return port.getHistory()
|
|
|
|
|
|
def getSignals(self):
|
|
|
res = {}
|
|
|
- for port in super(CBD, self).getSignals().keys():
|
|
|
- res[port] = self.getSignal(port)
|
|
|
+ for port in self.getOutputPortNames():
|
|
|
+ res[port] = self.getSignalHistory(port)
|
|
|
return res
|
|
|
|
|
|
def clearSignals(self):
|