Skip to content
Snippets Groups Projects
core_operations.py 14.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • """
    B-ASIC Core Operations Module.
    
    
    Contains some of the most commonly used mathematical operations.
    
    """
    
    from numbers import Number
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
    from typing import Dict, Optional
    
    from numpy import abs as np_abs
    from numpy import conjugate, sqrt
    
    from b_asic.graph_component import Name, TypeName
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
    from b_asic.operation import AbstractOperation
    from b_asic.port import SignalSourceProvider
    
    
    
    class Constant(AbstractOperation):
    
        """
        Constant value operation.
    
    
        Gives a specified value that remains constant for every iteration.
    
        output(0): self.param("value")
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        _execution_time = 0
    
    
        def __init__(self, value: Number = 0, name: Name = ""):
    
            """Construct a Constant operation with the given value."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=0,
                output_count=1,
                name=name,
                latency_offsets={"out0": 0},
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "c"
    
    
        def evaluate(self):
            return self.param("value")
    
        @property
    
        def value(self) -> Number:
            """Get the constant value of this operation."""
            return self.param("value")
    
        @value.setter
        def value(self, value: Number) -> None:
            """Set the constant value of this operation."""
    
            self.set_param("value", value)
    
    
    
    class Addition(AbstractOperation):
    
        """
        Binary addition operation.
    
        Gives the result of adding two inputs.
    
        output(0): input(0) + input(1)
        """
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "add"
    
    
        def evaluate(self, a, b):
            return a + b
    
    
    class Subtraction(AbstractOperation):
    
        """
        Binary subtraction operation.
    
    
        Gives the result of subtracting the second input from the first one.
    
        output(0): input(0) - input(1)
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "sub"
    
    
        def evaluate(self, a, b):
            return a - b
    
    
    
    class AddSub(AbstractOperation):
    
        """
        Two-input addition or subtraction operation.
    
    
        Gives the result of adding or subtracting two inputs.
    
        output(0): input(0) + input(1) if is_add = True
        output(0): input(0) - input(1) if is_add = False
        """
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            is_add: bool = True,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
            """Construct an Addition operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
            self.set_param("is_add", is_add)
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "addsub"
    
        def evaluate(self, a, b):
            return a + b if self.is_add else a - b
    
        @property
        def is_add(self) -> Number:
            """Get if operation is add."""
            return self.param("is_add")
    
        @is_add.setter
        def is_add(self, is_add: bool) -> None:
            """Set if operation is add."""
    
            self.set_param("is_add", is_add)
    
    class Multiplication(AbstractOperation):
    
        """
        Binary multiplication operation.
    
    
        Gives the result of multiplying two inputs.
    
        output(0): input(0) * input(1)
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
            """Construct a Multiplication operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "mul"
    
    
        def evaluate(self, a, b):
            return a * b
    
    
    class Division(AbstractOperation):
    
        """
        Binary division operation.
    
        Gives the result of dividing the first input by the second one.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
            return "div"
    
    
        """
        Binary min operation.
    
        Gives the minimum value of two inputs.
        NOTE: Non-real numbers are not supported.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "min"
    
            if isinstance(a, complex) or isinstance(b, complex):
                raise ValueError(
                    "core_operations.Min does not support complex numbers.")
    
    
    
    class Max(AbstractOperation):
    
        """
        Binary max operation.
    
    
        Gives the maximum value of two inputs.
        NOTE: Non-real numbers are not supported.
    
        output(0): max(input(0), input(1))
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "max"
    
    
        def evaluate(self, a, b):
    
            if isinstance(a, complex) or isinstance(b, complex):
                raise ValueError(
                    "core_operations.Max does not support complex numbers.")
    
            return a if a > b else b
    
    
    
        """
        Square root operation.
    
        Gives the square root of its input.
    
        output(0): sqrt(input(0))
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
                name=name,
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "sqrt"
    
        def evaluate(self, a):
            return sqrt(complex(a))
    
    class ComplexConjugate(AbstractOperation):
    
        """
        Complex conjugate operation.
    
        Gives the complex conjugate of its input.
    
        output(0): conj(input(0))
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
            """Construct a ComplexConjugate operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
                name=name,
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "conj"
    
    
        def evaluate(self, a):
    
        """
        Absolute value operation.
    
        Gives the absolute value of its input.
    
        output(0): abs(input(0))
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
                name=name,
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "abs"
    
    
        def evaluate(self, a):
    
    class ConstantMultiplication(AbstractOperation):
    
        """
        Constant multiplication operation.
    
    
        Gives the result of multiplying its input by a specified value.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            value: Number = 0,
            src0: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
            """Construct a ConstantMultiplication operation with the given value.
            """
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
                name=name,
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "cmul"
    
    
        def evaluate(self, a):
    
    
        @property
    
        def value(self) -> Number:
            """Get the constant value of this operation."""
            return self.param("value")
    
        @value.setter
        def value(self, value: Number) -> None:
            """Set the constant value of this operation."""
    
            self.set_param("value", value)
    
        """
        Butterfly operation.
    
    
        Gives the result of adding its two inputs, as well as the result of
        subtracting the second input from the first one.
    
        output(0): input(0) + input(1)
        output(1): input(0) - input(1)
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=2,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "bfly"
    
        """
        Multiply-add operation.
    
        Gives the result of multiplying the first input by the second input and
        then adding the third input.
    
        output(0): (input(0) * input(1)) + input(2)
        """
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            src2: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=3,
                output_count=1,
                name=name,
                input_sources=[src0, src1, src2],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "mad"
    
    
    
    class SymmetricTwoportAdaptor(AbstractOperation):
    
        """
        Symmetric twoport-adaptor operation.
    
    
        output(0): input(1) + value*(input(1) - input(0)
        output(1): input(0) + value*(input(1) - input(0)
        """
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            value: Number = 0,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            name: Name = "",
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
        ):
    
            """Construct a Butterfly operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=2,
                name=name,
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
            )
    
            self.set_param("value", value)
    
        @classmethod
        def type_name(cls) -> TypeName:
            return "sym2p"
    
        def evaluate(self, a, b):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            tmp = self.value * (b - a)
    
            return b + tmp, a + tmp
    
        @property
        def value(self) -> Number:
            """Get the constant value of this operation."""
            return self.param("value")
    
        @value.setter
        def value(self, value: Number) -> None:
            """Set the constant value of this operation."""
    
            self.set_param("value", value)