From ace7aea375f0abea88a16c01ce86139c03dbdbef Mon Sep 17 00:00:00 2001 From: Catherine Date: Thu, 8 Feb 2024 12:57:11 +0000 Subject: [PATCH] lib.wiring: track member source locations. The source location is set to the place where `In`/`Out` was created. The source location of the instantiation is tracked but overwritten; we will need to change the internal structure storing those to be able to include both. Fixes #1085. --- amaranth/lib/wiring.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/amaranth/lib/wiring.py b/amaranth/lib/wiring.py index d9cb14d..1f6f540 100644 --- a/amaranth/lib/wiring.py +++ b/amaranth/lib/wiring.py @@ -59,7 +59,7 @@ class Flow(enum.Enum): return Out assert False # :nocov: - def __call__(self, description, *, reset=None): + def __call__(self, description, *, reset=None, src_loc_at=0): """Create a :class:`Member` with this data flow and the provided description and reset value. @@ -68,7 +68,7 @@ class Flow(enum.Enum): :class:`Member` :pc:`Member(self, description, reset=reset)` """ - return Member(self, description, reset=reset) + return Member(self, description, reset=reset, src_loc_at=src_loc_at + 1) def __repr__(self): return self.name @@ -105,11 +105,12 @@ class Member: Although instances can be created directly, most often they will be created through :data:`In` and :data:`Out`, e.g. :pc:`In(unsigned(1))` or :pc:`Out(stream.Signature(RGBPixel))`. """ - def __init__(self, flow, description, *, reset=None, _dimensions=()): + def __init__(self, flow, description, *, reset=None, _dimensions=(), src_loc_at=0): self._flow = flow self._description = description self._reset = reset self._dimensions = _dimensions + self.src_loc = tracer.get_src_loc(src_loc_at=src_loc_at) # Check that the description is valid, and populate derived properties. if self.is_port: @@ -493,8 +494,13 @@ class SignatureMembers(Mapping): for name, member in self.items(): def create_value(path, *, src_loc_at): if member.is_port: - return Signal(member.shape, reset=member.reset, src_loc_at=1 + src_loc_at, - name="__".join(str(item) for item in path)) + # Ideally we would keep both source locations here, but the .src_loc attribute + # data structure doesn't currently support that, so keep the more important one: + # the one with the name of the signal (the `In()`/`Out()` call site.) + signal = Signal(member.shape, reset=member.reset, src_loc_at=1 + src_loc_at, + name="__".join(str(item) for item in path)) + signal.src_loc = member.src_loc + return signal if member.is_signature: return member.signature.create(path=path, src_loc_at=1 + src_loc_at) assert False # :nocov: @@ -1610,7 +1616,7 @@ class Component(Elaboratable): If a name conflict is detected between two variable annotations, or between a member and an existing attribute. """ - def __init__(self, signature=None): + def __init__(self, signature=None, *, src_loc_at=0): cls = type(self) members = {} for base in reversed(cls.mro()[:cls.mro().index(Component)]): @@ -1644,7 +1650,7 @@ class Component(Elaboratable): 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(signature.members.create(path=())) + self.__dict__.update(signature.members.create(path=(), src_loc_at=src_loc_at + 1)) @property def signature(self):