From 422ba9ea51855472e1ed50c3c6eb297a4bff446d Mon Sep 17 00:00:00 2001 From: Wanda Date: Thu, 7 Dec 2023 10:13:10 +0100 Subject: [PATCH] lib.wiring: use tracer to obtain default Signature path and src_loc. Fixes #987. --- amaranth/lib/wiring.py | 36 +++++++++++++++++++++--------------- tests/test_lib_wiring.py | 10 +++++----- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/amaranth/lib/wiring.py b/amaranth/lib/wiring.py index 0d9420189..18ceb586e 100644 --- a/amaranth/lib/wiring.py +++ b/amaranth/lib/wiring.py @@ -5,6 +5,7 @@ import re import warnings +from .. import tracer from ..hdl.ast import Shape, ShapeCastable, Const, Signal, Value, ValueCastable from ..hdl.ir import Elaboratable from .._utils import final @@ -219,23 +220,27 @@ def flatten(self, *, path=()): if member.is_signature: yield from member.signature.members.flatten(path=(*path, name)) - def create(self, *, path=()): + def create(self, *, path=None, src_loc_at=0): + if path is None: + path = (tracer.get_var_name(depth=2 + src_loc_at, default="$signature"),) attrs = {} for name, member in self.items(): - def create_value(path): + def create_value(path, *, src_loc_at): if member.is_port: - return Signal(member.shape, reset=member.reset, + return Signal(member.shape, reset=member.reset, src_loc_at=1 + src_loc_at, name="__".join(str(item) for item in path)) if member.is_signature: - return member.signature.create(path=path) + return member.signature.create(path=path, src_loc_at=1 + src_loc_at) assert False # :nocov: - def create_dimensions(dimensions, *, path): + def create_dimensions(dimensions, *, path, src_loc_at): if not dimensions: - return create_value(path) + return create_value(path, src_loc_at=1 + src_loc_at) dimension, *rest_of_dimensions = dimensions - return [create_dimensions(rest_of_dimensions, path=(*path, index)) + return [create_dimensions(rest_of_dimensions, path=(*path, index), + src_loc_at=1 + src_loc_at) for index in range(dimension)] - attrs[name] = create_dimensions(member.dimensions, path=(*path, name)) + attrs[name] = create_dimensions(member.dimensions, path=(*path, name), + src_loc_at=1 + src_loc_at) return attrs def __repr__(self): @@ -503,8 +508,8 @@ def check_dimensions(member, attr_value, dimensions, *, path): continue return result - def create(self, *, path=()): - return PureInterface(self, path=path) + def create(self, *, path=None, src_loc_at=0): + return PureInterface(self, path=path, src_loc_at=1 + src_loc_at) def __repr__(self): if type(self) is Signature: @@ -593,18 +598,19 @@ def __delattr__(self, name): except AttributeError: delattr(self.__unflipped, name) - def create(self, *, path=()): - return flipped(self.__unflipped.create(path=path)) + def create(self, *args, path=None, src_loc_at=0, **kwargs): + return flipped(self.__unflipped.create(*args, path=path, src_loc_at=1 + src_loc_at, + **kwargs)) def __repr__(self): return f"{self.__unflipped!r}.flip()" class PureInterface: - def __init__(self, signature, *, path): + def __init__(self, signature, *, path=None, src_loc_at=0): self.__dict__.update({ "signature": signature, - **signature.members.create(path=path) + **signature.members.create(path=path, src_loc_at=1 + src_loc_at) }) def __repr__(self): @@ -864,7 +870,7 @@ def __init__(self): if hasattr(self, name): raise NameError(f"Cannot initialize attribute for signature member {name!r} " f"because an attribute with the same name already exists") - self.__dict__.update(self.signature.members.create()) + self.__dict__.update(self.signature.members.create(path=())) @property def signature(self): diff --git a/tests/test_lib_wiring.py b/tests/test_lib_wiring.py index ac6e2f0ec..9bdef91bd 100644 --- a/tests/test_lib_wiring.py +++ b/tests/test_lib_wiring.py @@ -279,9 +279,9 @@ def test_create(self): self.assertEqual(list(attrs.keys()), ["a", "s"]) self.assertIsInstance(attrs["a"], Signal) self.assertEqual(attrs["a"].shape(), unsigned(1)) - self.assertEqual(attrs["a"].name, "a") + self.assertEqual(attrs["a"].name, "attrs__a") self.assertEqual(attrs["s"].b.shape(), unsigned(2)) - self.assertEqual(attrs["s"].b.name, "s__b") + self.assertEqual(attrs["s"].b.name, "attrs__s__b") def test_create_reset(self): members = SignatureMembers({ @@ -301,7 +301,7 @@ def test_create_tuple(self): for x in members["a"]: for y in x: self.assertIsInstance(y, Signal) - self.assertEqual(members["a"][1][2].name, "a__1__2") + self.assertEqual(members["a"][1][2].name, "members__a__1__2") def test_repr(self): self.assertEqual(repr(SignatureMembers({})), @@ -773,8 +773,8 @@ def custom_method(self): return 69 class CustomSignature(Signature): - def create(self, *, path=()): - return CustomInterface(self, path=path) + def create(self, *, path=None, src_loc_at=0): + return CustomInterface(self, path=path, src_loc_at=1 + src_loc_at) flipped_interface = CustomSignature({}).flip().create() self.assertTrue(hasattr(flipped_interface, "custom_method"))