Source code for elasticai.creator.arithmetic.fxp_converter
from dataclasses import dataclass
from math import ceil
from typing import cast
from elasticai.creator.arithmetic.fxp_arithmetic import FxpArithmetic
from elasticai.creator.arithmetic.fxp_params import (
ConvertableToFixedPointValues,
FxpParams,
T,
)
[docs]
@dataclass
class FxpConverter:
def __init__(self, fxp_params: FxpParams):
self._config = fxp_params
@property
def total_bits(self) -> int:
return self._config.total_bits
@property
def frac_bits(self) -> int:
return self._config.frac_bits
def _round_to_integer(self, number: float | T) -> int | T:
return FxpArithmetic(self._config).round_to_integer(number)
def _integer_to_twos(self, number):
if isinstance(number, ConvertableToFixedPointValues):
return int(self._convert_integer_to_twos(cast(T, number)))
else:
return self._convert_integer_to_twos(number)
def _convert_integer_to_twos(self, number):
if self._config.integer_out_of_bounds(number):
raise ValueError(
f"Value '{number}' cannot be represented with {self._config.total_bits} bits."
)
return ((1 << self._config.total_bits) + number) if number < 0 else number
[docs]
def integer_to_binary_string_vhdl(self, number: int) -> str:
twos = self._integer_to_twos(number)
return f'"{twos:0{self._config.total_bits}b}"'
[docs]
def integer_to_hex_string_vhdl(self, number: int) -> str:
twos = self._integer_to_twos(number)
return f'X"{twos:0{ceil(self._config.total_bits / 4)}X}"'
[docs]
def integer_to_binary_string_verilog(self, number: int) -> str:
twos = self._integer_to_twos(number)
return f"{self._config.total_bits}'b{twos:0{self._config.total_bits}b}"
[docs]
def integer_to_decimal_string_verilog(self, number: int) -> str:
twos = self._integer_to_twos(number)
return f"{self._config.total_bits}'d{twos}"
[docs]
def integer_to_hex_string_verilog(self, number: int) -> str:
twos = self._integer_to_twos(number)
return (
f"{self._config.total_bits}'h{twos:0{ceil(self._config.total_bits / 4)}X}"
)
[docs]
def rational_to_binary_string_vhdl(self, number: float) -> str:
fxp = self._round_to_integer(number)
return self.integer_to_binary_string_vhdl(fxp)
[docs]
def rational_to_hex_string_vhdl(self, number: float) -> str:
fxp = self._round_to_integer(number)
return self.integer_to_hex_string_vhdl(fxp)
[docs]
def rational_to_binary_string_verilog(self, number: float) -> str:
fxp = self._round_to_integer(number)
return self.integer_to_binary_string_verilog(fxp)
[docs]
def rational_to_decimal_string_verilog(self, number: float) -> str:
fxp = self._round_to_integer(number)
return self.integer_to_decimal_string_verilog(fxp)
[docs]
def rational_to_hex_string_verilog(self, number: float) -> str:
fxp = self._round_to_integer(number)
return self.integer_to_hex_string_verilog(fxp)
[docs]
def binary_to_integer(self, binary: str) -> int:
format_binary = binary.replace('"', "").replace(" ", "").split("b")[-1]
return int(format_binary, 2) - (
(1 << self._config.total_bits)
if self._config.signed and format_binary[0] == "1"
else 0
)
[docs]
def binary_to_rational(self, binary: str) -> float:
int_val = self.binary_to_integer(binary)
return int_val * self._config.minimum_step_as_rational
[docs]
def decimal_to_integer(self, binary: str) -> int:
format_binary = binary.split("d")[-1]
return int(format_binary) - (
(1 << self._config.total_bits)
if self._config.signed and format_binary[0] == "1"
else 0
)
[docs]
def decimal_to_rational(self, binary: str) -> float:
int_val = self.decimal_to_integer(binary)
return int_val * self._config.minimum_step_as_rational
[docs]
def hex_to_integer(self, binary: str) -> int:
format_binary = binary.replace('"', "").replace(" ", "").split("X")[-1]
return int(format_binary, 16) - (
(1 << self._config.total_bits)
if self._config.signed and format_binary[0] == "1"
else 0
)
[docs]
def hex_to_rational(self, binary: str) -> float:
int_val = self.hex_to_integer(binary)
return int_val * self._config.minimum_step_as_rational