Newer
Older
Angus Lothian
committed
"""B-ASIC Core Operations Module.
Contains some of the most commonly used mathematical operations.
Angus Lothian
committed
from typing import Optional, Dict
from numpy import conjugate, sqrt, abs as np_abs
Angus Lothian
committed
from b_asic.port import SignalSourceProvider, InputPort, OutputPort
from b_asic.operation import AbstractOperation
from b_asic.graph_component import Name, TypeName
class Constant(AbstractOperation):
"""Constant value operation.
Angus Lothian
committed
Gives a specified value that remains constant for every iteration.
output(0): self.param("value")
"""
def __init__(self, value: Number = 0, name: Name = ""):
Angus Lothian
committed
"""Construct a Constant operation with the given value."""
super().__init__(input_count=0, output_count=1, name=name, latency_offsets={'out0' : 0})
Angus Lothian
committed
self.set_param("value", value)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "c"
def evaluate(self):
return self.param("value")
@property
Angus Lothian
committed
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."""
return self.set_param("value", value)
class Addition(AbstractOperation):
"""Binary addition operation.
Angus Lothian
committed
Gives the result of adding two inputs.
output(0): input(0) + input(1)
"""
Angus Lothian
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 an Addition operation."""
super().__init__(input_count=2, output_count=1, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "add"
def evaluate(self, a, b):
return a + b
class Subtraction(AbstractOperation):
"""Binary subtraction operation.
Angus Lothian
committed
Gives the result of subtracting the second input from the first one.
output(0): input(0) - input(1)
Angus Lothian
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 Subtraction operation."""
super().__init__(input_count=2, output_count=1, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "sub"
def evaluate(self, a, b):
return a - b
class Multiplication(AbstractOperation):
"""Binary multiplication operation.
Angus Lothian
committed
Gives the result of multiplying two inputs.
output(0): input(0) * input(1)
Angus Lothian
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."""
super().__init__(input_count=2, output_count=1, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "mul"
def evaluate(self, a, b):
return a * b
class Division(AbstractOperation):
"""Binary division operation.
Angus Lothian
committed
Gives the result of dividing the first input by the second one.
Angus Lothian
committed
output(0): input(0) / input(1)
"""
Angus Lothian
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 Division operation."""
super().__init__(input_count=2, output_count=1, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
Angus Lothian
committed
def evaluate(self, a, b):
return a / b
Angus Lothian
committed
class Min(AbstractOperation):
"""Binary min operation.
Angus Lothian
committed
Gives the minimum value of two inputs.
NOTE: Non-real numbers are not supported.
Angus Lothian
committed
output(0): min(input(0), input(1))
Angus Lothian
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 Min operation."""
super().__init__(input_count=2, output_count=1, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "min"
Angus Lothian
committed
def evaluate(self, a, b):
assert not isinstance(a, complex) and not isinstance(b, complex), \
("core_operations.Min does not support complex numbers.")
return a if a < b else b
class Max(AbstractOperation):
"""Binary max operation.
Angus Lothian
committed
Gives the maximum value of two inputs.
NOTE: Non-real numbers are not supported.
output(0): max(input(0), input(1))
Angus Lothian
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 Max operation."""
super().__init__(input_count=2, output_count=1, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "max"
def evaluate(self, a, b):
assert not isinstance(a, complex) and not isinstance(b, complex), \
("core_operations.Max does not support complex numbers.")
return a if a > b else b
Angus Lothian
committed
class SquareRoot(AbstractOperation):
"""Square root operation.
Angus Lothian
committed
Gives the square root of its input.
output(0): sqrt(input(0))
Angus Lothian
committed
def __init__(self, src0: Optional[SignalSourceProvider] = None, name: Name = "", latency: Optional[int] = None, latency_offsets: Optional[Dict[str, int]] = None):
"""Construct a SquareRoot operation."""
super().__init__(input_count=1, output_count=1, name=name, input_sources=[src0],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "sqrt"
Angus Lothian
committed
def evaluate(self, a):
return sqrt(complex(a))
Angus Lothian
committed
class ComplexConjugate(AbstractOperation):
"""Complex conjugate operation.
Angus Lothian
committed
Gives the complex conjugate of its input.
output(0): conj(input(0))
Angus Lothian
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."""
super().__init__(input_count=1, output_count=1, name=name, input_sources=[src0],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "conj"
Angus Lothian
committed
return conjugate(a)
Angus Lothian
committed
class Absolute(AbstractOperation):
"""Absolute value operation.
Angus Lothian
committed
Gives the absolute value of its input.
output(0): abs(input(0))
Angus Lothian
committed
def __init__(self, src0: Optional[SignalSourceProvider] = None, name: Name = "", latency: Optional[int] = None, latency_offsets: Optional[Dict[str, int]] = None):
"""Construct an Absolute operation."""
super().__init__(input_count=1, output_count=1, name=name, input_sources=[src0],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "abs"
Angus Lothian
committed
return np_abs(a)
Angus Lothian
committed
class ConstantMultiplication(AbstractOperation):
"""Constant multiplication operation.
Gives the result of multiplying its input by a specified value.
Angus Lothian
committed
output(0): self.param("value") * input(0)
Angus Lothian
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."""
super().__init__(input_count=1, output_count=1, name=name, input_sources=[src0],
latency=latency, latency_offsets=latency_offsets)
self.set_param("value", value)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "cmul"
Angus Lothian
committed
return a * self.param("value")
Angus Lothian
committed
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."""
return self.set_param("value", value)
Angus Lothian
committed
class Butterfly(AbstractOperation):
"""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)
Angus Lothian
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 Butterfly operation."""
super().__init__(input_count=2, output_count=2, name=name, input_sources=[src0, src1],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "bfly"
Angus Lothian
committed
def evaluate(self, a, b):
return a + b, a - b
Angus Lothian
committed
class MAD(AbstractOperation):
"""Multiply-add operation.
Angus Lothian
committed
Gives the result of multiplying the first input by the second input and
then adding the third input.
Angus Lothian
committed
output(0): (input(0) * input(1)) + input(2)
"""
Angus Lothian
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):
"""Construct a MAD operation."""
super().__init__(input_count=3, output_count=1, name=name, input_sources=[src0, src1, src2],
latency=latency, latency_offsets=latency_offsets)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "mad"
Angus Lothian
committed
def evaluate(self, a, b, c):
return a * b + c