Newer
Older
Angus Lothian
committed
Contains operations with special purposes that may be treated differently from
normal operations in an SFG.
"""
from typing import Optional, Sequence, Tuple
Angus Lothian
committed
from b_asic.operation import (
AbstractOperation,
DelayMap,
MutableDelayMap,
MutableResultMap,
)
Angus Lothian
committed
from b_asic.port import SignalSourceProvider
Angus Lothian
committed
class Input(AbstractOperation):
Angus Lothian
committed
Marks an input port to an SFG.
Its value will be updated on each iteration when simulating the SFG.
"""
Angus Lothian
committed
"""Construct an Input operation."""
super().__init__(
input_count=0,
output_count=1,
Angus Lothian
committed
self.set_param("value", 0)
@classmethod
def type_name(cls) -> TypeName:
Angus Lothian
committed
def evaluate(self):
return self.param("value")
@property
def latency(self) -> int:
return self.latency_offsets["out0"]
Angus Lothian
committed
@property
Angus Lothian
committed
"""Get the current value of this input."""
return self.param("value")
@value.setter
Angus Lothian
committed
"""Set the current value of this input."""
self.set_param("value", value)
) -> Tuple[Tuple[Tuple[float, float], ...], Tuple[Tuple[float, float], ...]]:
(
(-0.5, 0),
(-0.5, 1),
(-0.25, 1),
(0, 0.5),
(-0.25, 0),
(-0.5, 0),
),
(
(-0.5, 0),
(-0.5, 1),
(-0.25, 1),
(0, 0.5),
(-0.25, 0),
(-0.5, 0),
),
def get_input_coordinates(self) -> Tuple[Tuple[float, float], ...]:
# doc-string inherited
return tuple()
def get_output_coordinates(self) -> Tuple[Tuple[float, float], ...]:
# doc-string inherited
return ((0, 0.5),)
@property
def is_constant(self) -> bool:
return False
@property
def is_linear(self) -> bool:
return True
Angus Lothian
committed
class Output(AbstractOperation):
Angus Lothian
committed
Marks an output port to an SFG.
The SFG will forward its input to the corresponding output signal
destinations.
"""
self,
src0: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
Angus Lothian
committed
"""Construct an Output operation."""
super().__init__(
input_count=1,
output_count=0,
input_sources=[src0],
latency_offsets={"in0": 0},
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
Angus Lothian
committed
def evaluate(self, _):
return None
) -> Tuple[Tuple[Tuple[float, float], ...], Tuple[Tuple[float, float], ...]]:
((0, 0), (0, 1), (0.25, 1), (0.5, 0.5), (0.25, 0), (0, 0)),
((0, 0), (0, 1), (0.25, 1), (0.5, 0.5), (0.25, 0), (0, 0)),
def get_input_coordinates(self) -> Tuple[Tuple[float, float], ...]:
# doc-string inherited
return ((0, 0.5),)
def get_output_coordinates(self) -> Tuple[Tuple[float, float], ...]:
# doc-string inherited
return tuple()
@property
def latency(self) -> int:
return self.latency_offsets["in0"]
@property
def is_linear(self) -> bool:
return True
Angus Lothian
committed
class Delay(AbstractOperation):
Angus Lothian
committed
Represents one unit of delay in a circuit, typically a clock cycle.
Can be thought of as a register or a D flip-flop.
"""
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
Angus Lothian
committed
"""Construct a Delay operation."""
input_count=1,
output_count=1,
name=Name(name),
input_sources=[src0],
Angus Lothian
committed
self.set_param("initial_value", initial_value)
@classmethod
def type_name(cls) -> TypeName:
Angus Lothian
committed
def evaluate(self, a):
return self.param("initial_value")
def current_output(
self, index: int, delays: Optional[DelayMap] = None, prefix: str = ""
Angus Lothian
committed
if delays is not None:
return delays.get(self.key(index, prefix), self.param("initial_value"))
Angus Lothian
committed
return self.param("initial_value")
results: Optional[MutableResultMap] = None,
delays: Optional[MutableDelayMap] = None,
prefix: str = "",
bits_override: Optional[int] = None,
Angus Lothian
committed
if index != 0:
raise IndexError(f"Output index out of range (expected 0-0, got {index})")
Angus Lothian
committed
if len(input_values) != 1:
raise ValueError(
"Wrong number of inputs supplied to SFG for evaluation"
f" (expected 1, got {len(input_values)})"
)
Angus Lothian
committed
key = self.key(index, prefix)
value = self.param("initial_value")
if delays is not None:
value = delays.get(key, value)
self.quantize_inputs(input_values, bits_override)[0]
if quantize
Angus Lothian
committed
if results is not None:
results[key] = value
return value
@property
Angus Lothian
committed
"""Get the initial value of this delay."""
return self.param("initial_value")
@initial_value.setter
Angus Lothian
committed
"""Set the initial value of this delay."""
self.set_param("initial_value", value)
@property
def is_linear(self) -> bool:
return True