|
|
@@ -15,7 +15,7 @@ __all__ = ['ConstantBlock', 'NegatorBlock', 'InverterBlock',
|
|
|
'MultiplexerBlock', 'SplitBlock',
|
|
|
'DelayBlock', 'DeltaTBlock', 'TimeBlock', 'LoggingBlock',
|
|
|
'AddOneBlock', 'DerivatorBlock', 'IntegratorBlock',
|
|
|
- 'Clock', 'DummyClock', 'SequenceBlock']
|
|
|
+ 'Clock', 'SequenceBlock']
|
|
|
|
|
|
class ConstantBlock(BaseBlock):
|
|
|
"""
|
|
|
@@ -876,8 +876,8 @@ class TimeBlock(BaseBlock):
|
|
|
BaseBlock.__init__(self, block_name, [], ["OUT1", "relative"])
|
|
|
|
|
|
def compute(self, curIteration):
|
|
|
- time = self.getClock().getTime(curIteration)
|
|
|
- rel_time = self.getClock().getRelativeTime(curIteration)
|
|
|
+ time = self.getClock().getTime()
|
|
|
+ rel_time = self.getClock().getRelativeTime()
|
|
|
self.appendToSignal(time)
|
|
|
self.appendToSignal(rel_time, "relative")
|
|
|
|
|
|
@@ -907,7 +907,7 @@ class LoggingBlock(BaseBlock):
|
|
|
|
|
|
def compute(self, curIteration):
|
|
|
if self.getInputSignal(curIteration, "IN1").value:
|
|
|
- simtime = str(self.getClock().getTime(-1))
|
|
|
+ simtime = str(self.getClock().getTime())
|
|
|
if self.__lev == logging.WARNING:
|
|
|
self.__logger.warning("[" + simtime + "] " + self.__string, extra={"block": self})
|
|
|
elif self.__lev == logging.ERROR:
|
|
|
@@ -1025,21 +1025,23 @@ class IntegratorBlock(CBD):
|
|
|
self.addConnection("sumState", "OUT1")
|
|
|
|
|
|
|
|
|
-class Clock(CBD):
|
|
|
+class Clock(BaseBlock):
|
|
|
"""
|
|
|
System clock. **Must be present in a simulation model.**
|
|
|
|
|
|
Args:
|
|
|
- block_name (str): The name of the block.
|
|
|
- start_time (float): Time at which the simulation starts. Defaults to 0.
|
|
|
+ block_name (str): The name of the block.
|
|
|
+ start_delta (float): Time delta at the start of the simulation. Defaults to 0.1.
|
|
|
+ start_time (float): Time at which the simulation starts. Defaults to 0.
|
|
|
|
|
|
:Input Ports:
|
|
|
- **h** -- The delta in-between timesteps. For fixed-rate simulations,
|
|
|
- this must be linked up to a constant value (e.g. a :class:`ConstantBlock`).
|
|
|
+ **h** -- The delta for the next iteration. I.e., the time to wait until the next
|
|
|
+ iteration can be computed.
|
|
|
|
|
|
:Output Ports:
|
|
|
- **time** -- The current simulation time.
|
|
|
- **rel_time** -- The relative simulation time, ignoring the start time.
|
|
|
+ - **delta_t** -- The current delta.
|
|
|
|
|
|
Warning:
|
|
|
**Clock Usage Assumption:** When adding a (custom) clock to your model(s),
|
|
|
@@ -1047,8 +1049,8 @@ class Clock(CBD):
|
|
|
independent of the simulation algorithm used. I.e., changing the delay of a
|
|
|
fixed-rate clock should only influence the accuracy of the signals, **not**
|
|
|
the correctness of the signals. It is forbidden to misuse these outputs for
|
|
|
- specific simulations (e.g., using the :code:`time` as a counter, using
|
|
|
- :code:`delta` as a constant value...).
|
|
|
+ specific simulations (e.g., using the :code:`time` as a counter, assuming
|
|
|
+ :code:`delta_t` is a constant value...).
|
|
|
|
|
|
In other words, the clock is guaranteed to output a correct value and should
|
|
|
only be used in the context of "time". When exporting the CBD model to other
|
|
|
@@ -1058,147 +1060,56 @@ class Clock(CBD):
|
|
|
See Also:
|
|
|
- :class:`TimeBlock`
|
|
|
- :class:`DeltaTBlock`
|
|
|
- - :class:`DummyClock`
|
|
|
"""
|
|
|
- def __init__(self, block_name, start_time=0.0):
|
|
|
- # TODO: simplify if start_time is 0
|
|
|
- CBD.__init__(self, block_name, ["h"], ["time", "rel_time", "delta"])
|
|
|
+ def __init__(self, block_name, start_delta=0.1, start_time=0.0):
|
|
|
+ BaseBlock.__init__(self, block_name, ["h"], ["time", "rel_time", "delta_t"])
|
|
|
+ self.__start_delta = start_delta
|
|
|
self.__start_time = start_time
|
|
|
+ self.__delta = self.__start_delta
|
|
|
+ self.__time = self.__start_time
|
|
|
|
|
|
- self.addBlock(ConstantBlock("IC", start_time))
|
|
|
- self.addBlock(DelayBlock("delay"))
|
|
|
- self.addBlock(AdderBlock("TSum"))
|
|
|
- self.addBlock(AdderBlock("STSum"))
|
|
|
- self.addBlock(NegatorBlock("STNeg"))
|
|
|
- self.addBlock(ConstantBlock("Past", 0.0))
|
|
|
- self.addBlock(AdderBlock("PastSum"))
|
|
|
-
|
|
|
- self.addConnection("h", "TSum")
|
|
|
- self.addConnection("delay", "TSum")
|
|
|
- self.addConnection("TSum", "delay", input_port_name='IN1')
|
|
|
- self.addConnection("delay", "PastSum")
|
|
|
- self.addConnection("Past", "PastSum")
|
|
|
- self.addConnection("PastSum", "time")
|
|
|
-
|
|
|
- self.addConnection("IC", "delay", input_port_name='IC')
|
|
|
+ def getDependencies(self, curIteration):
|
|
|
+ return []
|
|
|
|
|
|
- self.addConnection("IC", "STNeg")
|
|
|
- self.addConnection("PastSum", "STSum")
|
|
|
- self.addConnection("STNeg", "STSum")
|
|
|
- self.addConnection("STSum", "rel_time")
|
|
|
+ def compute(self, curIteration):
|
|
|
+ if curIteration > 0:
|
|
|
+ self.__delta = self.getInputSignal(curIteration - 1, "h").value
|
|
|
+ self.__time += self.__delta
|
|
|
|
|
|
- self.addConnection("h", "delta")
|
|
|
+ self.appendToSignal(self.__time, "time")
|
|
|
+ self.appendToSignal(self.getRelativeTime(), "rel_time")
|
|
|
+ self.appendToSignal(self.__delta, "delta_t")
|
|
|
|
|
|
- def getTime(self, curIt):
|
|
|
+ def getTime(self):
|
|
|
"""
|
|
|
Gets the current time of the clock.
|
|
|
"""
|
|
|
- # FIXME: this will produce wrong signals for all clock inputs and
|
|
|
- # all blocks in the clock itself
|
|
|
- sig = self.getBlockByName("TSum").getSignalHistory("OUT1")
|
|
|
- if curIt == 0 or len(sig) == 0:
|
|
|
- return self.__start_time
|
|
|
- return sig[curIt - 1].value
|
|
|
-
|
|
|
- def getRelativeTime(self, curIt):
|
|
|
+ return self.__time
|
|
|
+
|
|
|
+ def getRelativeTime(self):
|
|
|
"""
|
|
|
Gets the relative simulation time (ignoring the start time).
|
|
|
"""
|
|
|
- return self.getTime(curIt) - self.__start_time
|
|
|
+ return self.getTime() - self.__start_time
|
|
|
|
|
|
def setStartTime(self, start_time=0.0):
|
|
|
self.__start_time = start_time
|
|
|
- self.getBlockByName("IC").setValue(start_time)
|
|
|
|
|
|
def getDeltaT(self):
|
|
|
- dSig = self.getSignalHistory("delta")
|
|
|
- if len(dSig) == 0:
|
|
|
- return 0.0
|
|
|
- return dSig[-1].value
|
|
|
+ return self.__delta
|
|
|
|
|
|
def reset(self):
|
|
|
"""
|
|
|
Resets the clock. Required for restarting a simulation.
|
|
|
"""
|
|
|
- self.clearSignals()
|
|
|
-
|
|
|
- def _rewind(self):
|
|
|
- CBD._rewind(self)
|
|
|
- time = self.getInputSignal(-1, "h").value
|
|
|
- c = self.getBlockByName("Past")
|
|
|
- c.setValue(c.getValue() - time)
|
|
|
-
|
|
|
-
|
|
|
-class DummyClock(BaseBlock):
|
|
|
- """
|
|
|
- Dummy clock to be used in the tests. It contains the exact same functionality
|
|
|
- as the actual fixed rate :class:`Clock`, but allows for testing without the
|
|
|
- need for other correctly implemented blocks.
|
|
|
-
|
|
|
- Args:
|
|
|
- block_name (str): The name of the block.
|
|
|
- start_time (float): The tima at which the simulation starts. Defaults to 0.
|
|
|
- delta (float): The (fixed) time-delta between two iterations.
|
|
|
-
|
|
|
- :Output Ports:
|
|
|
- - **time** -- The current simulation time.
|
|
|
- - **rel_time** -- The relative simulation time, ignoring the start time.
|
|
|
- - **delta** -- The delay between two clock "ticks".
|
|
|
-
|
|
|
- Warning:
|
|
|
- Only use this block in the tests!
|
|
|
-
|
|
|
- See Also:
|
|
|
- - :class:`TimeBlock`
|
|
|
- - :class:`DeltaTBlock`
|
|
|
- - :class:`Clock`
|
|
|
- """
|
|
|
- def __init__(self, block_name, start_time=0.0, delta=0.1):
|
|
|
- BaseBlock.__init__(self, block_name, [], ["time", "rel_time", "delta"])
|
|
|
- self.__start_time = start_time
|
|
|
+ self.clearPorts()
|
|
|
self.__time = self.__start_time
|
|
|
- self.__delta_t = delta
|
|
|
-
|
|
|
- def compute(self, curIteration):
|
|
|
- self.appendToSignal(self.__time, "time")
|
|
|
- self.appendToSignal(self.__time - self.__start_time, "rel_time")
|
|
|
- self.appendToSignal(self.__delta_t, "delta")
|
|
|
- self.__time += self.__delta_t
|
|
|
-
|
|
|
- def getTime(self, curIt):
|
|
|
- """
|
|
|
- Obtains the current time of the clock.
|
|
|
- """
|
|
|
- sig = self.getSignalHistory("time")
|
|
|
- if curIt == 0 or len(sig) == 0:
|
|
|
- return self.__start_time
|
|
|
- return sig[curIt - 1].value + self.__delta_t
|
|
|
-
|
|
|
- def getRelativeTime(self, curIt):
|
|
|
- """
|
|
|
- Obtains the relative simulation time (ignoring the start time).
|
|
|
- """
|
|
|
- return self.getTime(curIt) - self.__start_time
|
|
|
-
|
|
|
- def getDeltaT(self):
|
|
|
- """
|
|
|
- Obtains the time-delta.
|
|
|
- """
|
|
|
- return self.__delta_t
|
|
|
-
|
|
|
- def setDeltaT(self, dt):
|
|
|
- """
|
|
|
- Sets the time-delta.
|
|
|
- Args:
|
|
|
- dt (float): New time delta.
|
|
|
- """
|
|
|
- self.__delta_t = dt
|
|
|
-
|
|
|
- def setStartTime(self, st):
|
|
|
- self.__start_time = st
|
|
|
+ self.__delta = self.__start_delta
|
|
|
|
|
|
def _rewind(self):
|
|
|
- self.__start_time -= self.__delta_t
|
|
|
+ self.__time -= self.__delta
|
|
|
+ BaseBlock._rewind(self)
|
|
|
+ self.__delta = self.getInputSignal(-1, "h").value
|
|
|
|
|
|
|
|
|
class SequenceBlock(BaseBlock):
|