Skip to content

Commit

Permalink
Merge pull request #349 from es-ude/merging-main-to-develop
Browse files Browse the repository at this point in the history
Merging main to develop
  • Loading branch information
SuperChange001 authored May 28, 2024
2 parents ce92f2b + 29a1894 commit 72aff07
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 374 deletions.
2 changes: 1 addition & 1 deletion .github/actions/setup_test_environment/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ runs:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.11.x
python-version: 3.10.x
- name: Install Poetry
run: python3 -m pip install poetry==1.4.0 --upgrade pip
shell: bash
Expand Down
11 changes: 9 additions & 2 deletions elasticai/creator/file_generation/template.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
from collections.abc import Iterable, Iterator, Mapping
from dataclasses import dataclass
from itertools import repeat
Expand Down Expand Up @@ -89,7 +90,7 @@ def _expand_multiline_template(
for line in lines:
contains_no_key = True
for key in kwargs:
if f"${key}" in line:
if f"${key}" in line or f"${{{key}}}" in line:
contains_no_key = False
for placeholder_line, value in zip(repeat(line), kwargs[key]):
t = StringTemplate(placeholder_line)
Expand All @@ -113,4 +114,10 @@ def _expand_template(template: str | Iterable[str], **kwargs: str) -> Iterator[s


def _extract_template_variables(template: list[str]) -> set[str]:
return set(StringTemplate("\n".join(template)).get_identifiers())
template_text = "\n".join(template)
id_pattern = r"\$([_a-z][_a-z0-9]*)"
bid_pattern = r"\${([_a-z][_a-z0-9]*)}"
identifiers = set(
re.findall(id_pattern, template_text) + re.findall(bid_pattern, template_text)
)
return identifiers
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def create_design(self, name: str) -> PrecomputedScalarFunction:
quantized_inputs = list(map(self._config.as_integer, self._step_lut.tolist()))
return PrecomputedScalarFunction(
name=name,
width=self._config.total_bits,
input_width=self._config.total_bits,
output_width=self._config.total_bits,
inputs=quantized_inputs,
function=self._quantized_inference,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ def test_vhdl_code_matches_expected_for_tanh_as_base_module() -> None:
end tanh;
architecture rtl of tanh is
signal signed_x, signed_y : signed(8-1 downto 0) := (others=>'0');
signal signed_x : signed(8-1 downto 0) := (others=>'0');
signal signed_y : signed(8-1 downto 0) := (others=>'0');
begin
signed_x <= signed(x);
y <= std_logic_vector(signed_y);
tanh_process : process(x)
begin
if signed_x <= 20 then signed_y <= to_signed(3, 8);
elsif signed_x <= 10 then signed_y <= to_signed(3, 8);
elsif signed_x <= 0 then signed_y <= to_signed(0, 8);
if signed_x <= -20 then signed_y <= to_signed(-3, 8);
elsif signed_x <= -10 then signed_y <= to_signed(-3, 8);
else signed_y <= to_signed(-3, 8);
elsif signed_x <= 0 then signed_y <= to_signed(0, 8);
elsif signed_x <= 10 then signed_y <= to_signed(3, 8);
else signed_y <= to_signed(3, 8);
end if;
end process;
end rtl;
Expand Down Expand Up @@ -66,17 +67,18 @@ def test_vhdl_code_matches_expected_for_sigmoid_as_base_module() -> None:
end sigmoid;
architecture rtl of sigmoid is
signal signed_x, signed_y : signed(8-1 downto 0) := (others=>'0');
signal signed_x : signed(8-1 downto 0) := (others=>'0');
signal signed_y : signed(8-1 downto 0) := (others=>'0');
begin
signed_x <= signed(x);
y <= std_logic_vector(signed_y);
sigmoid_process : process(x)
begin
if signed_x <= 20 then signed_y <= to_signed(3, 8);
elsif signed_x <= 10 then signed_y <= to_signed(3, 8);
elsif signed_x <= 0 then signed_y <= to_signed(2, 8);
if signed_x <= -20 then signed_y <= to_signed(0, 8);
elsif signed_x <= -10 then signed_y <= to_signed(0, 8);
else signed_y <= to_signed(0, 8);
elsif signed_x <= 0 then signed_y <= to_signed(2, 8);
elsif signed_x <= 10 then signed_y <= to_signed(3, 8);
else signed_y <= to_signed(3, 8);
end if;
end process;
end rtl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,70 @@ class PrecomputedScalarFunction(Design):
def __init__(
self,
name: str,
width: int,
input_width: int,
output_width: int,
function: Callable[[int], int],
inputs: list[int],
) -> None:
super().__init__(name)
self._width = width
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, data_width=str(width)),
parameters=dict(
name=self.name,
input_data_width=str(self._input_width),
output_data_width=str(self._output_width),
),
)

def _compute_io_pairs(self) -> dict[int, int]:
inputs_in_descending_order = sorted(self._inputs, reverse=True)
pairs = dict()
for number in inputs_in_descending_order:
pairs[number] = self._function(number)
return pairs
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._width, y_width=self._width)
return create_port(x_width=self._input_width, y_width=self._output_width)

def save_to(self, destination: Path) -> None:
process_content = []

pairs = list(self._compute_io_pairs().items())
pairs = self._compute_io_pairs()
input_value, output_value = pairs[0]
process_content.append(
f"if signed_x <= {input_value} then "
f"signed_y <= to_signed({output_value}, {self._width});"
f"signed_y <= to_signed({output_value}, {self._output_width});"
)
for input_value, output_value in pairs[1:-1]:
process_content.append(
f"elsif signed_x <= {input_value} then "
f"signed_y <= to_signed({output_value}, {self._width});"
f"signed_y <= to_signed({output_value}, {self._output_width});"
)
_, output = pairs[-1]
process_content.append(f"else signed_y <= to_signed({output}, {self._width});")
process_content.append(
f"else signed_y <= to_signed({output}, {self._output_width});"
)
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."
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all; -- for type conversions

entity $name is
entity ${name} is
port (
enable : in std_logic;
clock : in std_logic;
x : in std_logic_vector($data_width-1 downto 0);
y : out std_logic_vector($data_width-1 downto 0)
x : in std_logic_vector(${input_data_width}-1 downto 0);
y : out std_logic_vector(${output_data_width}-1 downto 0)
);
end $name;
end ${name};

architecture rtl of $name is
signal signed_x, signed_y : signed($data_width-1 downto 0) := (others=>'0');
architecture rtl of ${name} is
signal signed_x : signed(${input_data_width}-1 downto 0) := (others=>'0');
signal signed_y : signed(${output_data_width}-1 downto 0) := (others=>'0');
begin
signed_x <= signed(x);
y <= std_logic_vector(signed_y);
${name}_process : process(x)
begin
$process_content
${process_content}
end process;
end rtl;
Loading

0 comments on commit 72aff07

Please sign in to comment.