Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Co-authored-by: Charlotte <[email protected]>
  • Loading branch information
whitequark and charlottia committed Sep 26, 2023
1 parent 41dc22e commit 1684c58
Showing 1 changed file with 82 additions and 6 deletions.
88 changes: 82 additions & 6 deletions amaranth/lib/wiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,18 +312,55 @@ class SignatureError(Exception):
# and most of the methods (except for `update`) added by MutableMapping are useless.
@final
class SignatureMembers(Mapping):
"""
.. todo:: Write this
"""Mapping of signature member names to their descriptions.
This container is used to implement the :pycode:`members` attribute of signature objects.
The keys in this container must be valid Python attribute names that are public (do not begin
with an underscore. The values must be instances of :class:`Member`. The container is mutable
in a restricted manner: new keys may be added, but existing keys may not be modified or removed.
In addition, the container can be _frozen_, which disallows addition of new keys. Freezing
a container recursively freezes the members of any signatures inside.
In addition to the use of the superscript operator, multiple members can be added at once with
the :pycode:`+=` opreator:
.. testcode::
sig = Signature()
sig.members += {
"clk": In(1),
"rst": In(1)
}
The :meth:`create` converts this mapping into a mapping of names to signature members (signals
and interface objects) by creating them from their descriptions. The created mapping can be
used to populate an interface object.
"""
def __init__(self, members=()):
self._dict = dict()
self._frozen = False
self += members

def flip(self):
"""Flip the data flow of the members in this mapping.
Returns
-------
:class:`FlippedSignatureMembers`
:pycode:`FlippedSignatureMembers(self)`
"""
return FlippedSignatureMembers(self)

def __eq__(self, other):
"""Compare the members in this and another mapping.
Returns
-------
:class:`bool`
:pycode:`True` if the mappings contain the set of keys with the same values,
:pycode:`False` otherwise.
"""
return (isinstance(other, (SignatureMembers, FlippedSignatureMembers)) and
list(self.flatten()) == list(other.flatten()))

Expand Down Expand Up @@ -366,27 +403,65 @@ def __len__(self):
return len(self._dict)

def __iadd__(self, members):
"""Add multiple members to this mapping.
:pycode:`members` must be another mapping: a :class:`dict` or anything that can be
converted to one.
"""
for name, member in dict(members).items():
self[name] = member
return self

@property
def frozen(self):
"""Whether this collection has been frozen yet.
Returns
-------
:class:`bool`
"""
return self._frozen

def freeze(self):
"""Freezes this collection.
Freezing prevents further modification to it or any nested signatures.
"""
self._frozen = True
for member in self.values():
if member.is_signature:
member.signature.freeze()

def flatten(self, *, path=()):
"""Recursively iterates through this collection.
Returns
-------
iterator of (:class:`tuple` of :class:`str`, :class:`Member`)
Pairs of paths and the corresponding members. A path is a tuple of strings where each
item is a key through which the item may be reached.
"""
for name, member in self.items():
yield ((*path, name), member)
if member.is_signature:
yield from member.signature.members.flatten(path=(*path, name))

def create(self, *, path=()):
"""Creates members from their descriptions.
For each port member, this function creates a :class:`Signal` with the shape and reset
value taken from the member description, and the name constructed from the path to
the member (by concatenating path items with a double underscore, ``__``).
For each signature member, this function calls :meth:`Signature.create` for that signature.
The resulting object can have any type if a :class:`Signature` subclass overrides
the :class:`create` method.
Returns
-------
dict of :class:`str` to :class:`Signal` or interface object
Mapping of names to actual signature members.
"""
attrs = {}
for name, member in self.items():
def create_value(path):
Expand All @@ -412,7 +487,7 @@ def __repr__(self):

@final
class FlippedSignatureMembers(Mapping):
"""A mapping of signature member names to their descriptions, with the directions flipped.
"""Mapping of signature member names to their descriptions, with the directions flipped.
Although an instance of :class:`FlippedSignatureMembers` could be created directly, it will
be usually created by a call to :meth:`SignatureMembers.flip`.
Expand Down Expand Up @@ -530,7 +605,7 @@ def _format_shape(shape):


class SignatureMeta(type):
"""A metaclass for :class:`Signature` that makes :class:`FlippedSignature` its
"""Metaclass for :class:`Signature` that makes :class:`FlippedSignature` its
'virtual subclass'.
The object returned by :meth:`Signature.flip` is an instance of :class:`FlippedSignature`.
Expand Down Expand Up @@ -576,8 +651,9 @@ def __instancecheck__(cls, instance):


class Signature(metaclass=SignatureMeta):
"""
.. todo:: Write this
"""Description of an interface object.
An interface object is a Python object used at the boundary between two interacting
"""
def __init__(self, members):
self.__members = SignatureMembers(members)
Expand Down

0 comments on commit 1684c58

Please sign in to comment.