lib.wiring: implement Signature.flatten.

This commit is contained in:
Catherine 2023-08-31 20:26:45 +00:00
parent f135226a79
commit 87fbcedecf
2 changed files with 57 additions and 0 deletions

View file

@ -371,6 +371,33 @@ class Signature(metaclass=SignatureMeta):
self.members.freeze() self.members.freeze()
return self return self
def flatten(self, obj):
for name, member in self.members.items():
path = (name,)
value = getattr(obj, name)
def iter_member(value, *, path):
if member.is_port:
yield path, Member(member.flow, member.shape, reset=member.reset), value
elif member.is_signature:
for sub_path, sub_member, sub_value in member.signature.flatten(value):
if member.flow == In:
sub_member = sub_member.flip()
yield ((*path, *sub_path), sub_member, sub_value)
else:
assert False # :nocov:
def iter_dimensions(value, dimensions, *, path):
if not dimensions:
yield from iter_member(value, path=path)
else:
dimension, *rest_of_dimensions = dimensions
for index in range(dimension):
yield from iter_dimensions(value[index], rest_of_dimensions,
path=(path, index))
yield from iter_dimensions(value, dimensions=member.dimensions, path=path)
def is_compliant(self, obj, *, reasons=None, path=("obj",)): def is_compliant(self, obj, *, reasons=None, path=("obj",)):
def check_attr_value(member, attr_value, *, path): def check_attr_value(member, attr_value, *, path):
if member.is_port: if member.is_port:

View file

@ -372,6 +372,36 @@ class SignatureTestCase(unittest.TestCase):
r"^Cannot add members to a frozen signature$"): r"^Cannot add members to a frozen signature$"):
sig.members += {"b": Out(1)} sig.members += {"b": Out(1)}
def assertFlattenedSignature(self, actual, expected):
for (a_path, a_member, a_value), (b_path, b_member, b_value) in zip(actual, expected):
self.assertEqual(a_path, b_path)
self.assertEqual(a_member, b_member)
self.assertIs(a_value, b_value)
def test_flatten(self):
sig = Signature({"a": In(1), "b": Out(2).array(2)})
intf = sig.create()
self.assertFlattenedSignature(sig.flatten(intf), [
(("a",), In(1), intf.a),
((("b",), 0), Out(2), intf.b[0]),
((("b",), 1), Out(2), intf.b[1])
])
def test_flatten_sig(self):
sig = Signature({
"a": Out(Signature({"p": Out(1)})),
"b": Out(Signature({"q": In (1)})),
"c": In( Signature({"r": Out(1)})),
"d": In( Signature({"s": In (1)})),
})
intf = sig.create()
self.assertFlattenedSignature(sig.flatten(intf), [
(("a", "p"), Out(1), intf.a.p),
(("b", "q"), In (1), intf.b.q),
(("c", "r"), Out(1), intf.c.r),
(("d", "s"), In (1), intf.d.s),
])
def assertNotCompliant(self, reason_regex, sig, obj): def assertNotCompliant(self, reason_regex, sig, obj):
self.assertFalse(sig.is_compliant(obj)) self.assertFalse(sig.is_compliant(obj))
reasons = [] reasons = []