lib.wiring: use tracer to obtain default Signature path and src_loc.

Fixes #987.
This commit is contained in:
Wanda 2023-12-07 10:13:10 +01:00 committed by Catherine
parent 7db049f37f
commit 422ba9ea51
2 changed files with 26 additions and 20 deletions

View file

@ -5,6 +5,7 @@ import inspect
import re import re
import warnings import warnings
from .. import tracer
from ..hdl.ast import Shape, ShapeCastable, Const, Signal, Value, ValueCastable from ..hdl.ast import Shape, ShapeCastable, Const, Signal, Value, ValueCastable
from ..hdl.ir import Elaboratable from ..hdl.ir import Elaboratable
from .._utils import final from .._utils import final
@ -219,23 +220,27 @@ class SignatureMembers(Mapping):
if member.is_signature: if member.is_signature:
yield from member.signature.members.flatten(path=(*path, name)) 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 = {} attrs = {}
for name, member in self.items(): for name, member in self.items():
def create_value(path): def create_value(path, *, src_loc_at):
if member.is_port: 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)) name="__".join(str(item) for item in path))
if member.is_signature: 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: assert False # :nocov:
def create_dimensions(dimensions, *, path): def create_dimensions(dimensions, *, path, src_loc_at):
if not dimensions: if not dimensions:
return create_value(path) return create_value(path, src_loc_at=1 + src_loc_at)
dimension, *rest_of_dimensions = dimensions 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)] 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 return attrs
def __repr__(self): def __repr__(self):
@ -503,8 +508,8 @@ class Signature(metaclass=SignatureMeta):
continue continue
return result return result
def create(self, *, path=()): def create(self, *, path=None, src_loc_at=0):
return PureInterface(self, path=path) return PureInterface(self, path=path, src_loc_at=1 + src_loc_at)
def __repr__(self): def __repr__(self):
if type(self) is Signature: if type(self) is Signature:
@ -593,18 +598,19 @@ class FlippedSignature:
except AttributeError: except AttributeError:
delattr(self.__unflipped, name) delattr(self.__unflipped, name)
def create(self, *, path=()): def create(self, *args, path=None, src_loc_at=0, **kwargs):
return flipped(self.__unflipped.create(path=path)) return flipped(self.__unflipped.create(*args, path=path, src_loc_at=1 + src_loc_at,
**kwargs))
def __repr__(self): def __repr__(self):
return f"{self.__unflipped!r}.flip()" return f"{self.__unflipped!r}.flip()"
class PureInterface: class PureInterface:
def __init__(self, signature, *, path): def __init__(self, signature, *, path=None, src_loc_at=0):
self.__dict__.update({ self.__dict__.update({
"signature": signature, "signature": signature,
**signature.members.create(path=path) **signature.members.create(path=path, src_loc_at=1 + src_loc_at)
}) })
def __repr__(self): def __repr__(self):
@ -864,7 +870,7 @@ class Component(Elaboratable):
if hasattr(self, name): if hasattr(self, name):
raise NameError(f"Cannot initialize attribute for signature member {name!r} " raise NameError(f"Cannot initialize attribute for signature member {name!r} "
f"because an attribute with the same name already exists") 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 @property
def signature(self): def signature(self):

View file

@ -279,9 +279,9 @@ class SignatureMembersTestCase(unittest.TestCase):
self.assertEqual(list(attrs.keys()), ["a", "s"]) self.assertEqual(list(attrs.keys()), ["a", "s"])
self.assertIsInstance(attrs["a"], Signal) self.assertIsInstance(attrs["a"], Signal)
self.assertEqual(attrs["a"].shape(), unsigned(1)) 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.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): def test_create_reset(self):
members = SignatureMembers({ members = SignatureMembers({
@ -301,7 +301,7 @@ class SignatureMembersTestCase(unittest.TestCase):
for x in members["a"]: for x in members["a"]:
for y in x: for y in x:
self.assertIsInstance(y, Signal) 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): def test_repr(self):
self.assertEqual(repr(SignatureMembers({})), self.assertEqual(repr(SignatureMembers({})),
@ -773,8 +773,8 @@ class FlippedInterfaceTestCase(unittest.TestCase):
return 69 return 69
class CustomSignature(Signature): class CustomSignature(Signature):
def create(self, *, path=()): def create(self, *, path=None, src_loc_at=0):
return CustomInterface(self, path=path) return CustomInterface(self, path=path, src_loc_at=1 + src_loc_at)
flipped_interface = CustomSignature({}).flip().create() flipped_interface = CustomSignature({}).flip().create()
self.assertTrue(hasattr(flipped_interface, "custom_method")) self.assertTrue(hasattr(flipped_interface, "custom_method"))