Source code for elasticai.creator.vhdl.shared_designs.precomputed_scalar_function.design

from collections.abc import Callable

from elasticai.creator.file_generation.savable import Path
from elasticai.creator.file_generation.template import (
    InProjectTemplate,
    module_to_package,
)
from elasticai.creator.vhdl.auto_wire_protocols.port_definitions import create_port
from elasticai.creator.vhdl.design.design import Design
from elasticai.creator.vhdl.design.ports import Port


[docs] class PrecomputedScalarFunction(Design): _template_package = module_to_package(__name__) def __init__( self, name: str, input_width: int, output_width: int, function: Callable[[int], int], inputs: list[int], ) -> None: super().__init__(name) self._input_width = input_width self._output_width = output_width self._function = function self._inputs = inputs self._template = InProjectTemplate( file_name="precomputed_scalar_function.tpl.vhd", package=self._template_package, parameters=dict( name=self.name, input_data_width=str(self._input_width), output_data_width=str(self._output_width), ), ) def _compute_io_pairs(self) -> list[tuple[int, int]]: ascending_unique_inputs = sorted(set(self._inputs)) io_pairs = [] for input_value in ascending_unique_inputs: _assert_value_is_representable_with_n_bits(input_value, self._input_width) output_value = self._function(input_value) _assert_value_is_representable_with_n_bits(output_value, self._output_width) io_pairs.append((input_value, output_value)) return io_pairs @property def port(self) -> Port: return create_port(x_width=self._input_width, y_width=self._output_width)
[docs] def save_to(self, destination: Path) -> None: process_content = [] pairs = self._compute_io_pairs() input_value, output_value = pairs[0] process_content.append( f"if signed_x <= to_signed({input_value}, BITWIDTH_OUTPUT) then " f"signed_y <= to_signed({output_value}, BITWIDTH_OUTPUT);" ) for input_value, output_value in pairs[1:-1]: process_content.append( f"elsif signed_x <= to_signed({input_value}, BITWIDTH_OUTPUT) then " f"signed_y <= to_signed({output_value}, BITWIDTH_OUTPUT);" ) _, output = pairs[-1] process_content.append( f"else signed_y <= to_signed({output}, BITWIDTH_OUTPUT);" ) process_content.append("end if;") self._template.parameters.update(process_content=process_content) destination.create_subpath(self.name).as_file(".vhd").write(self._template)
def _assert_value_is_representable_with_n_bits(value: int, n_bits: int) -> None: min_value = 2 ** (n_bits - 1) * (-1) max_value = 2 ** (n_bits - 1) - 1 if value < min_value or value > max_value: raise ValueError( f"The value '{value}' cannot be represented " f"with {n_bits} in two's complement representation." )