Skip to content

Commit

Permalink
lib.wiring: use tracer to obtain default Signature path and src_loc.
Browse files Browse the repository at this point in the history
Fixes #987.
  • Loading branch information
wanda-phi authored and whitequark committed Dec 7, 2023
1 parent 7db049f commit 422ba9e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
36 changes: 21 additions & 15 deletions amaranth/lib/wiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down
10 changes: 5 additions & 5 deletions tests/test_lib_wiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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({})),
Expand Down Expand Up @@ -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"))
Expand Down

0 comments on commit 422ba9e

Please sign in to comment.