diff --git a/requirements-dev.txt b/requirements-dev.txt index 1d9530305..addb96214 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -20,3 +20,4 @@ pytest-xdist==3.5.0 pyelftools==0.29 tabulate==0.9.0 filelock==3.13.1 +hypothesis==6.99.6 diff --git a/transactron/lib/storage.py b/transactron/lib/storage.py index 4cdb080eb..5f9da1692 100644 --- a/transactron/lib/storage.py +++ b/transactron/lib/storage.py @@ -163,7 +163,7 @@ class ContentAddressableMemory(Elaboratable): Inserts new data. """ - def __init__(self, address_layout: LayoutList, data_layout: LayoutList, entries_number: int): + def __init__(self, address_layout: MethodLayout, data_layout: LayoutList, entries_number: int): """ Parameters ---------- @@ -174,8 +174,8 @@ def __init__(self, address_layout: LayoutList, data_layout: LayoutList, entries_ entries_number : int The number of slots to create in memory. """ - self.address_layout = address_layout - self.data_layout = data_layout + self.address_layout = from_method_layout(address_layout) + self.data_layout = from_method_layout(data_layout) self.entries_number = entries_number self.pop = Method(i=[("addr", self.address_layout)], o=[("data", self.data_layout), ("not_found", 1)]) diff --git a/transactron/testing/input_generation.py b/transactron/testing/input_generation.py index 6885235e2..ae3f9fc35 100644 --- a/transactron/testing/input_generation.py +++ b/transactron/testing/input_generation.py @@ -1,17 +1,29 @@ +from amaranth import * import random from typing import Optional -from transactron.utils import SimpleLayout +from hypothesis.strategies import composite, DrawFn, integers +from transactron.utils import LayoutList - -def generate_based_on_layout(layout: SimpleLayout, *, max_bits: Optional[int] = None): +@composite +def generate_based_on_layout(draw : DrawFn, layout: LayoutList): d = {} - for elem in layout: - if isinstance(elem[1], int): - if max_bits is None: - max_val = 2 ** elem[1] + for name, sublayout in layout: + if isinstance(sublayout, list): + elem = draw(generate_based_on_layout(sublayout)) + elif isinstance(sublayout, int): + elem = draw(integers(min_value=0, max_value=sublayout)) + elif isinstance(sublayout, range): + elem = draw(integers(min_value=sublayout.start, max_value=sublayout.stop-1)) + elif isinstance(sublayout, Shape): + if sublayout.signed: + min_value = -2**(sublayout.width-1) + max_value = 2**(sublayout.width-1)-1 else: - max_val = 2 ** min(max_bits, elem[1]) - d[elem[0]] = random.randrange(max_val) + min_value = 0 + max_value = 2**sublayout.width + elem = draw(integers(min_value = min_value, max_value = max_value)) else: - d[elem[0]] = generate_based_on_layout(elem[1]) + # Currently type[Enum] and ShapeCastable + raise NotImplementedError("Passed LayoutList with syntax yet unsuported in automatic value generation.") + d[name] = elem return d diff --git a/transactron/utils/_typing.py b/transactron/utils/_typing.py index 555c41736..b03859db8 100644 --- a/transactron/utils/_typing.py +++ b/transactron/utils/_typing.py @@ -33,7 +33,6 @@ "ValueLike", "ShapeLike", "StatementLike", - "SimpleLayout", "SwitchKey", "SrcLoc", "MethodLayout", @@ -67,7 +66,6 @@ SignalBundle: TypeAlias = Signal | Record | View | Iterable["SignalBundle"] | Mapping[str, "SignalBundle"] LayoutListField: TypeAlias = tuple[str, "ShapeLike | LayoutList"] LayoutList: TypeAlias = list[LayoutListField] -SimpleLayout = list[Tuple[str, Union[int, "SimpleLayout"]]] LayoutIterable: TypeAlias = Iterable[LayoutListField] MethodLayout: TypeAlias = StructLayout | LayoutIterable MethodStruct: TypeAlias = "View[StructLayout]" diff --git a/transactron/utils/data_repr.py b/transactron/utils/data_repr.py index 0974ba4f0..95e6d4d4e 100644 --- a/transactron/utils/data_repr.py +++ b/transactron/utils/data_repr.py @@ -1,5 +1,5 @@ from collections.abc import Iterable, Mapping -from ._typing import LayoutList, SimpleLayout, ShapeLike +from ._typing import LayoutList, ShapeLike from typing import Any, Sized from statistics import fmean from amaranth.lib.data import StructLayout