docs: use :py: role for inline Python code, not :pc:.

I originally picked :pc: as it is short for "python code", but it is
obscure and :py: is not taken, so a much more obvious role can be used
instead. Also, we all typo :pc: as :py: all the time anyway.
This commit is contained in:
Catherine 2024-02-13 10:31:44 +00:00
parent 3cb5f63aba
commit b9c9948038
6 changed files with 371 additions and 371 deletions

View file

@ -87,7 +87,7 @@ class Shape:
@staticmethod
def cast(obj, *, src_loc_at=0):
"""Cast :pc:`obj` to a shape.
"""Cast :py:`obj` to a shape.
Many :ref:`shape-like <lang-shapelike>` objects can be cast to a shape:
@ -104,9 +104,9 @@ class Shape:
Raises
------
TypeError
If :pc:`obj` cannot be converted to a :class:`Shape`.
If :py:`obj` cannot be converted to a :class:`Shape`.
RecursionError
If :pc:`obj` is a :class:`ShapeCastable` object that casts to itself.
If :py:`obj` is a :class:`ShapeCastable` object that casts to itself.
"""
while True:
if isinstance(obj, Shape):
@ -137,7 +137,7 @@ class Shape:
def __repr__(self):
"""Python code that creates this shape.
Returns :pc:`f"signed({self.width})"` or :pc:`f"unsigned({self.width})"`.
Returns :py:`f"signed({self.width})"` or :py:`f"unsigned({self.width})"`.
"""
if self.signed:
return f"signed({self.width})"
@ -150,12 +150,12 @@ class Shape:
def unsigned(width):
"""Returns :pc:`Shape(width, signed=False)`."""
"""Returns :py:`Shape(width, signed=False)`."""
return Shape(width, signed=False)
def signed(width):
"""Returns :pc:`Shape(width, signed=True)`."""
"""Returns :py:`Shape(width, signed=True)`."""
return Shape(width, signed=True)
@ -169,7 +169,7 @@ class ShapeCastable:
extending the Amaranth language in third-party code.
To illustrate their purpose, consider constructing a signal from a shape-castable object
:pc:`shape_castable`:
:py:`shape_castable`:
.. code::
@ -184,7 +184,7 @@ class ShapeCastable:
reset=shape_castable.const(initializer)
))
Note that the :pc:`shape_castable(x)` syntax performs :pc:`shape_castable.__call__(x)`.
Note that the :py:`shape_castable(x)` syntax performs :py:`shape_castable.__call__(x)`.
.. tip::
@ -216,9 +216,9 @@ class ShapeCastable:
def as_shape(self, *args, **kwargs):
"""as_shape()
Convert :pc:`self` to a :ref:`shape-like object <lang-shapelike>`.
Convert :py:`self` to a :ref:`shape-like object <lang-shapelike>`.
This method is called by the Amaranth language to convert :pc:`self` to a concrete
This method is called by the Amaranth language to convert :py:`self` to a concrete
:class:`Shape`. It will usually return a :class:`Shape` object, but it may also return
another shape-like object to delegate its functionality.
@ -243,15 +243,15 @@ class ShapeCastable:
def const(self, *args, **kwargs):
"""const(obj)
Convert a constant initializer :pc:`obj` to its value representation.
Convert a constant initializer :py:`obj` to its value representation.
This method is called by the Amaranth language to convert :pc:`obj`, which may be an
This method is called by the Amaranth language to convert :py:`obj`, which may be an
arbitrary Python object, to a concrete :ref:`value-like object <lang-valuelike>`.
The object :pc:`obj` will usually be a Python literal that can conveniently represent
a constant value whose shape is described by :pc:`self`. While not constrained here,
The object :py:`obj` will usually be a Python literal that can conveniently represent
a constant value whose shape is described by :py:`self`. While not constrained here,
the result will usually be an instance of the return type of :meth:`__call__`.
For any :pc:`obj`, the following condition must hold:
For any :py:`obj`, the following condition must hold:
.. code::
@ -277,18 +277,18 @@ class ShapeCastable:
Lift a :ref:`value-like object <lang-valuelike>` to a higher-level representation.
This method is called by the Amaranth language to lift :pc:`obj`, which may be any
:ref:`value-like object <lang-valuelike>` whose shape equals :pc:`Shape.cast(self)`,
This method is called by the Amaranth language to lift :py:`obj`, which may be any
:ref:`value-like object <lang-valuelike>` whose shape equals :py:`Shape.cast(self)`,
to a higher-level representation, which may be any value-like object with the same
shape. While not constrained here, usually a :class:`ShapeCastable` implementation will
be paired with a :class:`ValueCastable` implementation, and this method will return
an instance of the latter.
If :pc:`obj` is not as described above, this interface does not constrain the behavior
If :py:`obj` is not as described above, this interface does not constrain the behavior
of this method. This may be used to implement another call-based protocol at the same
time.
For any compliant :pc:`obj`, the following condition must hold:
For any compliant :py:`obj`, the following condition must hold:
.. code::
@ -328,7 +328,7 @@ class _ShapeLikeMeta(type):
class ShapeLike(metaclass=_ShapeLikeMeta):
"""Abstract class representing all objects that can be cast to a :class:`Shape`.
:pc:`issubclass(cls, ShapeLike)` returns :pc:`True` for:
:py:`issubclass(cls, ShapeLike)` returns :py:`True` for:
* :class:`Shape`;
* :class:`ShapeCastable` and its subclasses;
@ -337,7 +337,7 @@ class ShapeLike(metaclass=_ShapeLikeMeta):
* :class:`enum.EnumMeta` and its subclasses;
* :class:`ShapeLike` itself.
:pc:`isinstance(obj, ShapeLike)` returns :pc:`True` for:
:py:`isinstance(obj, ShapeLike)` returns :py:`True` for:
* :class:`Shape` instances;
* :class:`ShapeCastable` instances;
@ -381,9 +381,9 @@ class Value(metaclass=ABCMeta):
Operations on this class interpret this bit pattern either as an integer, which can be signed
or unsigned depending on the value's :meth:`shape`, or as a bit container. In either case,
the semantics of operations that implement Python's syntax, like :pc:`+` (also known as
the semantics of operations that implement Python's syntax, like :py:`+` (also known as
:meth:`__add__`), are identical to the corresponding operation on a Python :class:`int` (or on
a Python sequence container). The bitwise inversion :pc:`~` (also known as :meth:`__invert__`)
a Python sequence container). The bitwise inversion :py:`~` (also known as :meth:`__invert__`)
is the sole exception to this rule.
Data that is not conveniently representable by a single integer or a bit container can be
@ -404,24 +404,24 @@ class Value(metaclass=ABCMeta):
In each of the descriptions below, you will see a line similar to:
**Return type:** :class:`Value`, :pc:`unsigned(1)`, :ref:`assignable <lang-assignable>`
**Return type:** :class:`Value`, :py:`unsigned(1)`, :ref:`assignable <lang-assignable>`
The first part (:class:`Value`) indicates that the returned object's type is a subclass
of :class:`Value`. The second part (:pc:`unsigned(1)`) describes the shape of that value.
The third part, if present, indicates that the value is assignable if :pc:`self` is
of :class:`Value`. The second part (:py:`unsigned(1)`) describes the shape of that value.
The third part, if present, indicates that the value is assignable if :py:`self` is
assignable.
"""
@staticmethod
def cast(obj):
"""Cast :pc:`obj` to an Amaranth value.
"""Cast :py:`obj` to an Amaranth value.
Many :ref:`value-like <lang-valuelike>` objects can be cast to a value:
* a :class:`Value` instance, where the result is itself;
* a :class:`bool` or :class:`int` instance, where the result is :pc:`Const(obj)`;
* a :class:`bool` or :class:`int` instance, where the result is :py:`Const(obj)`;
* an :class:`enum.IntEnum` instance, or a :class:`enum.Enum` instance whose members are
all integers, where the result is a :class:`Const(obj, enum_shape)` where :pc:`enum_shape`
all integers, where the result is a :class:`Const(obj, enum_shape)` where :py:`enum_shape`
is a shape that can represent every member of the enumeration;
* a :class:`ValueCastable` instance, where the result is obtained by repeatedly calling
:meth:`obj.as_value() <ValueCastable.as_value>`.
@ -429,9 +429,9 @@ class Value(metaclass=ABCMeta):
Raises
------
TypeError
If :pc:`obj` cannot be converted to a :class:`Value`.
If :py:`obj` cannot be converted to a :class:`Value`.
RecursionError
If :pc:`obj` is a :class:`ValueCastable` object that casts to itself.
If :py:`obj` is a :class:`ValueCastable` object that casts to itself.
"""
while True:
if isinstance(obj, Value):
@ -454,7 +454,7 @@ class Value(metaclass=ABCMeta):
@abstractmethod
def shape(self):
"""Shape of :pc:`self`.
"""Shape of :py:`self`.
Returns
-------
@ -471,7 +471,7 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`unsigned(len(self))`, :ref:`assignable <lang-assignable>`
:class:`Value`, :py:`unsigned(len(self))`, :ref:`assignable <lang-assignable>`
"""
return Operator("u", [self])
@ -480,12 +480,12 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`signed(len(self))`, :ref:`assignable <lang-assignable>`
:class:`Value`, :py:`signed(len(self))`, :ref:`assignable <lang-assignable>`
Raises
------
ValueError
If :pc:`len(self) == 0`.
If :py:`len(self) == 0`.
"""
if len(self) == 0:
raise ValueError("Cannot create a 0-width signed value")
@ -494,7 +494,7 @@ class Value(metaclass=ABCMeta):
def __bool__(self):
"""Forbidden conversion to boolean.
Python uses this operator for its built-in semantics, e.g. :pc:`if`, and requires it to
Python uses this operator for its built-in semantics, e.g. :py:`if`, and requires it to
return a :class:`bool`. Since this is not possible for Amaranth values, this operator
always raises an exception.
@ -512,22 +512,22 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("b", [self])
def __pos__(self):
"""Unary position, :pc:`+self`.
"""Unary position, :py:`+self`.
Returns
-------
:class:`Value`, :pc:`self.shape()`
:pc:`self`
:class:`Value`, :py:`self.shape()`
:py:`self`
"""
return self
def __neg__(self):
"""Unary negation, :pc:`-self`.
"""Unary negation, :py:`-self`.
..
>>> C(-1).value, C(-1).shape()
@ -537,29 +537,29 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`signed(len(self) + 1)`
:class:`Value`, :py:`signed(len(self) + 1)`
"""
return Operator("-", [self])
@_overridable_by_reflected("__radd__")
def __add__(self, other):
"""Addition, :pc:`self + other`.
"""Addition, :py:`self + other`.
Returns
-------
:class:`Value`, :pc:`unsigned(max(self.width(), other.width()) + 1)`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(max(self.width() + 1, other.width()) + 1)`
If :pc:`self` is unsigned and :pc:`other` is signed.
:class:`Value`, :pc:`signed(max(self.width(), other.width() + 1) + 1)`
If :pc:`self` is signed and :pc:`other` is unsigned.
:class:`Value`, :pc:`signed(max(self.width(), other.width()) + 1)`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :py:`unsigned(max(self.width(), other.width()) + 1)`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(max(self.width() + 1, other.width()) + 1)`
If :py:`self` is unsigned and :py:`other` is signed.
:class:`Value`, :py:`signed(max(self.width(), other.width() + 1) + 1)`
If :py:`self` is signed and :py:`other` is unsigned.
:class:`Value`, :py:`signed(max(self.width(), other.width()) + 1)`
If both :py:`self` and :py:`other` are unsigned.
"""
return Operator("+", [self, other], src_loc_at=1)
def __radd__(self, other):
"""Addition, :pc:`other + self` (reflected).
"""Addition, :py:`other + self` (reflected).
Like :meth:`__add__`, with operands swapped.
"""
@ -567,18 +567,18 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__rsub__")
def __sub__(self, other):
"""Subtraction, :pc:`self - other`.
"""Subtraction, :py:`self - other`.
Returns
-------
:class:`Value`, :pc:`signed(max(self.width(), other.width()) + 1)`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(max(self.width() + 1, other.width()) + 1)`
If :pc:`self` is unsigned and :pc:`other` is signed.
:class:`Value`, :pc:`signed(max(self.width(), other.width() + 1) + 1)`
If :pc:`self` is signed and :pc:`other` is unsigned.
:class:`Value`, :pc:`signed(max(self.width(), other.width()) + 1)`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :py:`signed(max(self.width(), other.width()) + 1)`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(max(self.width() + 1, other.width()) + 1)`
If :py:`self` is unsigned and :py:`other` is signed.
:class:`Value`, :py:`signed(max(self.width(), other.width() + 1) + 1)`
If :py:`self` is signed and :py:`other` is unsigned.
:class:`Value`, :py:`signed(max(self.width(), other.width()) + 1)`
If both :py:`self` and :py:`other` are unsigned.
Returns
-------
@ -587,7 +587,7 @@ class Value(metaclass=ABCMeta):
return Operator("-", [self, other], src_loc_at=1)
def __rsub__(self, other):
"""Subtraction, :pc:`other - self` (reflected).
"""Subtraction, :py:`other - self` (reflected).
Like :meth:`__sub__`, with operands swapped.
"""
@ -595,19 +595,19 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__rmul__")
def __mul__(self, other):
"""Multiplication, :pc:`self * other`.
"""Multiplication, :py:`self * other`.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self) + len(other))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(len(self) + len(other))`
If either :pc:`self` or :pc:`other` are signed.
:class:`Value`, :py:`unsigned(len(self) + len(other))`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(len(self) + len(other))`
If either :py:`self` or :py:`other` are signed.
"""
return Operator("*", [self, other], src_loc_at=1)
def __rmul__(self, other):
"""Multiplication, :pc:`other * self` (reflected).
"""Multiplication, :py:`other * self` (reflected).
Like :meth:`__mul__`, with operands swapped.
"""
@ -615,27 +615,27 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__rfloordiv__")
def __floordiv__(self, other):
"""Flooring division, :pc:`self // other`.
"""Flooring division, :py:`self // other`.
If :pc:`other` is zero, the result of this operation is zero.
If :py:`other` is zero, the result of this operation is zero.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(len(self) + 1)`
If :pc:`self` is unsigned and :pc:`other` is signed.
:class:`Value`, :pc:`signed(len(self))`
If :pc:`self` is signed and :pc:`other` is unsigned.
:class:`Value`, :pc:`signed(len(self) + 1)`
If both :pc:`self` and :pc:`other` are signed.
:class:`Value`, :py:`unsigned(len(self))`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(len(self) + 1)`
If :py:`self` is unsigned and :py:`other` is signed.
:class:`Value`, :py:`signed(len(self))`
If :py:`self` is signed and :py:`other` is unsigned.
:class:`Value`, :py:`signed(len(self) + 1)`
If both :py:`self` and :py:`other` are signed.
"""
return Operator("//", [self, other], src_loc_at=1)
def __rfloordiv__(self, other):
"""Flooring division, :pc:`other // self` (reflected).
"""Flooring division, :py:`other // self` (reflected).
If :pc:`self` is zero, the result of this operation is zero.
If :py:`self` is zero, the result of this operation is zero.
Like :meth:`__floordiv__`, with operands swapped.
"""
@ -643,18 +643,18 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__rmod__")
def __mod__(self, other):
"""Flooring modulo or remainder, :pc:`self % other`.
"""Flooring modulo or remainder, :py:`self % other`.
If :pc:`other` is zero, the result of this operation is zero.
If :py:`other` is zero, the result of this operation is zero.
Returns
-------
:class:`Value`, :pc:`other.shape()`
:class:`Value`, :py:`other.shape()`
"""
return Operator("%", [self, other], src_loc_at=1)
def __rmod__(self, other):
"""Flooring modulo or remainder, :pc:`other % self` (reflected).
"""Flooring modulo or remainder, :py:`other % self` (reflected).
Like :meth:`__mod__`, with operands swapped.
"""
@ -662,66 +662,66 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__eq__")
def __eq__(self, other):
"""Equality comparison, :pc:`self == other`.
"""Equality comparison, :py:`self == other`.
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("==", [self, other], src_loc_at=1)
@_overridable_by_reflected("__ne__")
def __ne__(self, other):
"""Inequality comparison, :pc:`self != other`.
"""Inequality comparison, :py:`self != other`.
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("!=", [self, other], src_loc_at=1)
@_overridable_by_reflected("__gt__")
def __lt__(self, other):
"""Less than comparison, :pc:`self < other`.
"""Less than comparison, :py:`self < other`.
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("<", [self, other], src_loc_at=1)
@_overridable_by_reflected("__ge__")
def __le__(self, other):
"""Less than or equals comparison, :pc:`self <= other`.
"""Less than or equals comparison, :py:`self <= other`.
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("<=", [self, other], src_loc_at=1)
@_overridable_by_reflected("__lt__")
def __gt__(self, other):
"""Greater than comparison, :pc:`self > other`.
"""Greater than comparison, :py:`self > other`.
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator(">", [self, other], src_loc_at=1)
@_overridable_by_reflected("__le__")
def __ge__(self, other):
"""Greater than or equals comparison, :pc:`self >= other`.
"""Greater than or equals comparison, :py:`self >= other`.
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator(">=", [self, other], src_loc_at=1)
def __abs__(self):
"""Absolute value, :pc:`abs(self)`.
"""Absolute value, :py:`abs(self)`.
..
>>> abs(C(-1)).shape()
@ -731,7 +731,7 @@ class Value(metaclass=ABCMeta):
Return
------
:class:`Value`, :pc:`unsigned(len(self))`
:class:`Value`, :py:`unsigned(len(self))`
"""
if self.shape().signed:
return Mux(self >= 0, self, -self)[:len(self)]
@ -739,123 +739,123 @@ class Value(metaclass=ABCMeta):
return self
def __invert__(self):
"""Bitwise NOT, :pc:`~self`.
"""Bitwise NOT, :py:`~self`.
The shape of the result is the same as the shape of :pc:`self`, even for unsigned values.
The shape of the result is the same as the shape of :py:`self`, even for unsigned values.
.. important::
In Python, :pc:`~0` equals :pc:`-1`. In Amaranth, :pc:`~C(0)` equals :pc:`C(1)`.
In Python, :py:`~0` equals :py:`-1`. In Amaranth, :py:`~C(0)` equals :py:`C(1)`.
This is the only case where an Amaranth operator deviates from the Python operator
with the same name.
This deviation is necessary because Python does not allow overriding the logical
:pc:`and`, :pc:`or`, and :pc:`not` operators. Amaranth uses :pc:`&`, :pc:`|`, and
:pc:`~` instead; if it wasn't the case that :pc:`~C(0) == C(1)`, that would have
:py:`and`, :py:`or`, and :py:`not` operators. Amaranth uses :py:`&`, :py:`|`, and
:py:`~` instead; if it wasn't the case that :py:`~C(0) == C(1)`, that would have
been impossible.
Returns
-------
:class:`Value`, :pc:`self.shape()`
:class:`Value`, :py:`self.shape()`
"""
return Operator("~", [self])
@_overridable_by_reflected("__rand__")
def __and__(self, other):
"""Bitwise AND, :pc:`self & other`.
"""Bitwise AND, :py:`self & other`.
Returns
-------
:class:`Value`, :pc:`unsigned(max(self.width(), other.width()))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(max(self.width() + 1, other.width()))`
If :pc:`self` is unsigned and :pc:`other` is signed.
:class:`Value`, :pc:`signed(max(self.width(), other.width() + 1))`
If :pc:`self` is signed and :pc:`other` is unsigned.
:class:`Value`, :pc:`signed(max(self.width(), other.width()))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :py:`unsigned(max(self.width(), other.width()))`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(max(self.width() + 1, other.width()))`
If :py:`self` is unsigned and :py:`other` is signed.
:class:`Value`, :py:`signed(max(self.width(), other.width() + 1))`
If :py:`self` is signed and :py:`other` is unsigned.
:class:`Value`, :py:`signed(max(self.width(), other.width()))`
If both :py:`self` and :py:`other` are unsigned.
"""
return Operator("&", [self, other], src_loc_at=1)
def __rand__(self, other):
"""Bitwise AND, :pc:`other & self`.
"""Bitwise AND, :py:`other & self`.
Like :meth:`__and__`, with operands swapped.
"""
return Operator("&", [other, self])
def all(self):
"""Reduction AND; are all bits :pc:`1`?
"""Reduction AND; are all bits :py:`1`?
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("r&", [self])
@_overridable_by_reflected("__ror__")
def __or__(self, other):
"""Bitwise OR, :pc:`self | other`.
"""Bitwise OR, :py:`self | other`.
Returns
-------
:class:`Value`, :pc:`unsigned(max(self.width(), other.width()))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(max(self.width() + 1, other.width()))`
If :pc:`self` is unsigned and :pc:`other` is signed.
:class:`Value`, :pc:`signed(max(self.width(), other.width() + 1))`
If :pc:`self` is signed and :pc:`other` is unsigned.
:class:`Value`, :pc:`signed(max(self.width(), other.width()))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :py:`unsigned(max(self.width(), other.width()))`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(max(self.width() + 1, other.width()))`
If :py:`self` is unsigned and :py:`other` is signed.
:class:`Value`, :py:`signed(max(self.width(), other.width() + 1))`
If :py:`self` is signed and :py:`other` is unsigned.
:class:`Value`, :py:`signed(max(self.width(), other.width()))`
If both :py:`self` and :py:`other` are unsigned.
"""
return Operator("|", [self, other], src_loc_at=1)
def __ror__(self, other):
"""Bitwise OR, :pc:`other | self`.
"""Bitwise OR, :py:`other | self`.
Like :meth:`__or__`, with operands swapped.
"""
return Operator("|", [other, self])
def any(self):
"""Reduction OR; is any bit :pc:`1`?
"""Reduction OR; is any bit :py:`1`?
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("r|", [self])
@_overridable_by_reflected("__rxor__")
def __xor__(self, other):
"""Bitwise XOR, :pc:`self ^ other`.
"""Bitwise XOR, :py:`self ^ other`.
Returns
-------
:class:`Value`, :pc:`unsigned(max(self.width(), other.width()))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :pc:`signed(max(self.width() + 1, other.width()))`
If :pc:`self` is unsigned and :pc:`other` is signed.
:class:`Value`, :pc:`signed(max(self.width(), other.width() + 1))`
If :pc:`self` is signed and :pc:`other` is unsigned.
:class:`Value`, :pc:`signed(max(self.width(), other.width()))`
If both :pc:`self` and :pc:`other` are unsigned.
:class:`Value`, :py:`unsigned(max(self.width(), other.width()))`
If both :py:`self` and :py:`other` are unsigned.
:class:`Value`, :py:`signed(max(self.width() + 1, other.width()))`
If :py:`self` is unsigned and :py:`other` is signed.
:class:`Value`, :py:`signed(max(self.width(), other.width() + 1))`
If :py:`self` is signed and :py:`other` is unsigned.
:class:`Value`, :py:`signed(max(self.width(), other.width()))`
If both :py:`self` and :py:`other` are unsigned.
"""
return Operator("^", [self, other], src_loc_at=1)
def __rxor__(self, other):
"""Bitwise XOR, :pc:`other ^ self`.
"""Bitwise XOR, :py:`other ^ self`.
Like :meth:`__xor__`, with operands swapped.
"""
return Operator("^", [other, self])
def xor(self):
"""Reduction XOR; are an odd amount of bits :pc:`1`?
"""Reduction XOR; are an odd amount of bits :py:`1`?
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
return Operator("r^", [self])
@ -872,26 +872,26 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__rlshift__")
def __lshift__(self, other):
"""Left shift by variable amount, :pc:`self << other`.
"""Left shift by variable amount, :py:`self << other`.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self) + 2 ** len(other) - 1)`
If :pc:`self` is unsigned.
:class:`Value`, :pc:`signed(len(self) + 2 ** len(other) - 1)`
If :pc:`self` is signed.
:class:`Value`, :py:`unsigned(len(self) + 2 ** len(other) - 1)`
If :py:`self` is unsigned.
:class:`Value`, :py:`signed(len(self) + 2 ** len(other) - 1)`
If :py:`self` is signed.
Raises
------
:exc:`TypeError`
If :pc:`other` is signed.
If :py:`other` is signed.
"""
other = Value.cast(other)
other.__check_shamt()
return Operator("<<", [self, other], src_loc_at=1)
def __rlshift__(self, other):
"""Left shift by variable amount, :pc:`other << self`.
"""Left shift by variable amount, :py:`other << self`.
Like :meth:`__lshift__`, with operands swapped.
"""
@ -901,14 +901,14 @@ class Value(metaclass=ABCMeta):
def shift_left(self, amount):
"""Left shift by constant amount.
If :pc:`amount < 0`, performs the same operation as :pc:`self.shift_right(-amount)`.
If :py:`amount < 0`, performs the same operation as :py:`self.shift_right(-amount)`.
Returns
-------
:class:`Value`, :pc:`unsigned(max(len(self) + amount, 0))`
If :pc:`self` is unsigned.
:class:`Value`, :pc:`signed(max(len(self) + amount, 1))`
If :pc:`self` is signed.
:class:`Value`, :py:`unsigned(max(len(self) + amount, 0))`
If :py:`self` is unsigned.
:class:`Value`, :py:`signed(max(len(self) + amount, 1))`
If :py:`self` is signed.
"""
if not isinstance(amount, int):
raise TypeError(f"Shift amount must be an integer, not {amount!r}")
@ -922,11 +922,11 @@ class Value(metaclass=ABCMeta):
def rotate_left(self, amount):
"""Left rotate by constant amount.
If :pc:`amount < 0`, performs the same operation as :pc:`self.rotate_right(-amount)`.
If :py:`amount < 0`, performs the same operation as :py:`self.rotate_right(-amount)`.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self))`, :ref:`assignable <lang-assignable>`
:class:`Value`, :py:`unsigned(len(self))`, :ref:`assignable <lang-assignable>`
"""
if not isinstance(amount, int):
raise TypeError(f"Rotate amount must be an integer, not {amount!r}")
@ -936,26 +936,26 @@ class Value(metaclass=ABCMeta):
@_overridable_by_reflected("__rrshift__")
def __rshift__(self, other):
"""Right shift by variable amount, :pc:`self >> other`.
"""Right shift by variable amount, :py:`self >> other`.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self))`
If :pc:`self` is unsigned.
:class:`Value`, :pc:`signed(len(self))`
If :pc:`self` is signed.
:class:`Value`, :py:`unsigned(len(self))`
If :py:`self` is unsigned.
:class:`Value`, :py:`signed(len(self))`
If :py:`self` is signed.
Raises
------
:exc:`TypeError`
If :pc:`other` is signed.
If :py:`other` is signed.
"""
other = Value.cast(other)
other.__check_shamt()
return Operator(">>", [self, other], src_loc_at=1)
def __rrshift__(self, other):
"""Right shift by variable amount, :pc:`other >> self`.
"""Right shift by variable amount, :py:`other >> self`.
Like :meth:`__rshift__`, with operands swapped.
"""
@ -965,14 +965,14 @@ class Value(metaclass=ABCMeta):
def shift_right(self, amount):
"""Right shift by constant amount.
If :pc:`amount < 0`, performs the same operation as :pc:`self.left_right(-amount)`.
If :py:`amount < 0`, performs the same operation as :py:`self.left_right(-amount)`.
Returns
-------
:class:`Value`, :pc:`unsigned(max(len(self) - amount, 0))`
If :pc:`self` is unsigned.
:class:`Value`, :pc:`signed(max(len(self) - amount, 1))`
If :pc:`self` is signed.
:class:`Value`, :py:`unsigned(max(len(self) - amount, 0))`
If :py:`self` is unsigned.
:class:`Value`, :py:`signed(max(len(self) - amount, 1))`
If :py:`self` is signed.
"""
if not isinstance(amount, int):
raise TypeError(f"Shift amount must be an integer, not {amount!r}")
@ -988,11 +988,11 @@ class Value(metaclass=ABCMeta):
def rotate_right(self, amount):
"""Right rotate by constant amount.
If :pc:`amount < 0`, performs the same operation as :pc:`self.rotate_right(-amount)`.
If :py:`amount < 0`, performs the same operation as :py:`self.rotate_right(-amount)`.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self))`, :ref:`assignable <lang-assignable>`
:class:`Value`, :py:`unsigned(len(self))`, :ref:`assignable <lang-assignable>`
"""
if not isinstance(amount, int):
raise TypeError(f"Rotate amount must be an integer, not {amount!r}")
@ -1001,12 +1001,12 @@ class Value(metaclass=ABCMeta):
return Cat(self[amount:], self[:amount])
def __len__(self):
"""Bit width of :pc:`self`.
"""Bit width of :py:`self`.
Returns
-------
:class:`int`
:pc:`self.shape().width`
:py:`self.shape().width`
"""
return self.shape().width
@ -1055,13 +1055,13 @@ class Value(metaclass=ABCMeta):
def bit_select(self, offset, width):
"""Part-select with bit granularity.
Selects a constant width, variable offset part of :pc:`self`, where parts with successive
offsets overlap by :pc:`width - 1` bits. Bits above the most significant bit of :pc:`self`
may be selected; they are equal to zero if :pc:`self` is unsigned, to :pc:`self[-1]` if
:pc:`self` is signed, and assigning to them does nothing.
Selects a constant width, variable offset part of :py:`self`, where parts with successive
offsets overlap by :py:`width - 1` bits. Bits above the most significant bit of :py:`self`
may be selected; they are equal to zero if :py:`self` is unsigned, to :py:`self[-1]` if
:py:`self` is signed, and assigning to them does nothing.
When :pc:`offset` is a constant integer and :pc:`offset + width <= len(self)`,
this operation is equivalent to :pc:`self[offset:offset + width]`.
When :py:`offset` is a constant integer and :py:`offset + width <= len(self)`,
this operation is equivalent to :py:`self[offset:offset + width]`.
Parameters
----------
@ -1072,14 +1072,14 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`unsigned(width)`, :ref:`assignable <lang-assignable>`
:class:`Value`, :py:`unsigned(width)`, :ref:`assignable <lang-assignable>`
Raises
------
:exc:`TypeError`
If :pc:`offset` is signed.
If :py:`offset` is signed.
:exc:`TypeError`
If :pc:`width` is negative.
If :py:`width` is negative.
"""
offset = Value.cast(offset)
if type(offset) is Const and isinstance(width, int):
@ -1089,13 +1089,13 @@ class Value(metaclass=ABCMeta):
def word_select(self, offset, width):
"""Part-select with word granularity.
Selects a constant width, variable offset part of :pc:`self`, where parts with successive
offsets are adjacent but do not overlap. Bits above the most significant bit of :pc:`self`
may be selected; they are equal to zero if :pc:`self` is unsigned, to :pc:`self[-1]` if
:pc:`self` is signed, and assigning to them does nothing.
Selects a constant width, variable offset part of :py:`self`, where parts with successive
offsets are adjacent but do not overlap. Bits above the most significant bit of :py:`self`
may be selected; they are equal to zero if :py:`self` is unsigned, to :py:`self[-1]` if
:py:`self` is signed, and assigning to them does nothing.
When :pc:`offset` is a constant integer and :pc:`width:(offset + 1) * width <= len(self)`,
this operation is equivalent to :pc:`self[offset * width:(offset + 1) * width]`.
When :py:`offset` is a constant integer and :py:`width:(offset + 1) * width <= len(self)`,
this operation is equivalent to :py:`self[offset * width:(offset + 1) * width]`.
Parameters
----------
@ -1106,14 +1106,14 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`unsigned(width)`, :ref:`assignable <lang-assignable>`
:class:`Value`, :py:`unsigned(width)`, :ref:`assignable <lang-assignable>`
Raises
------
:exc:`TypeError`
If :pc:`offset` is signed.
If :py:`offset` is signed.
:exc:`TypeError`
If :pc:`width` is negative.
If :py:`width` is negative.
"""
offset = Value.cast(offset)
if type(offset) is Const and isinstance(width, int):
@ -1123,19 +1123,19 @@ class Value(metaclass=ABCMeta):
def replicate(self, count):
"""Replication.
Equivalent to :pc:`Cat(self for _ in range(count))`, but not assignable.
Equivalent to :py:`Cat(self for _ in range(count))`, but not assignable.
..
Technically assignable right now, but we don't want to commit to that.
Returns
-------
:class:`Value`, :pc:`unsigned(len(self) * count)`
:class:`Value`, :py:`unsigned(len(self) * count)`
Raises
------
:exc:`TypeError`
If :pc:`count` is negative.
If :py:`count` is negative.
"""
if not isinstance(count, int) or count < 0:
raise TypeError("Replication count must be a non-negative integer, not {!r}"
@ -1145,7 +1145,7 @@ class Value(metaclass=ABCMeta):
def matches(self, *patterns):
"""Pattern matching.
Matches against a set of patterns, recognizing the same grammar as :pc:`with m.Case()`.
Matches against a set of patterns, recognizing the same grammar as :py:`with m.Case()`.
.. todo::
@ -1153,7 +1153,7 @@ class Value(metaclass=ABCMeta):
Returns
-------
:class:`Value`, :pc:`unsigned(1)`
:class:`Value`, :py:`unsigned(1)`
"""
matches = []
# This code should accept exactly the same patterns as `with m.Case(...):`.
@ -1197,10 +1197,10 @@ class Value(metaclass=ABCMeta):
def eq(self, value, *, src_loc_at=0):
""":ref:`Assignment <lang-assigns>`.
Once it is placed in a domain, an assignment changes the bit pattern of :pc:`self` to
equal :pc:`value`. If the bit width of :pc:`value` is less than that of :pc:`self`,
it is zero-extended (for unsigned :pc:`value`\\ s) or sign-extended (for signed
:pc:`value`\\ s). If the bit width of :pc:`value` is greater than that of :pc:`self`,
Once it is placed in a domain, an assignment changes the bit pattern of :py:`self` to
equal :py:`value`. If the bit width of :py:`value` is less than that of :py:`self`,
it is zero-extended (for unsigned :py:`value`\\ s) or sign-extended (for signed
:py:`value`\\ s). If the bit width of :py:`value` is greater than that of :py:`self`,
it is truncated.
Returns
@ -1211,8 +1211,8 @@ class Value(metaclass=ABCMeta):
#: Forbidden hashing.
#:
#: Python objects are :term:`python:hashable` if they provide a :pc:`__hash__` method
#: that returns an :class:`int` and an :pc:`__eq__` method that returns a :class:`bool`.
#: Python objects are :term:`python:hashable` if they provide a :py:`__hash__` method
#: that returns an :class:`int` and an :py:`__eq__` method that returns a :class:`bool`.
#: Amaranth values define :meth:`__eq__` to return a :class:`Value`, which precludes them
#: from being hashable.
#:
@ -1251,9 +1251,9 @@ class ValueCastable:
operators, which will prefer calling a reflected arithmetic operation on
the :class:`ValueCastable` argument if it defines one.
For example, if :pc:`value_castable` implements :pc:`__radd__`, then
:pc:`C(1) + value_castable` will perform :pc:`value_castable.__radd__(C(1))`, and otherwise
it will perform :pc:`C(1).__add__(value_castable.as_value())`.
For example, if :py:`value_castable` implements :py:`__radd__`, then
:py:`C(1) + value_castable` will perform :py:`value_castable.__radd__(C(1))`, and otherwise
it will perform :py:`C(1).__add__(value_castable.as_value())`.
"""
def __init__(self, *args, **kwargs):
@ -1275,9 +1275,9 @@ class ValueCastable:
def as_value(self, *args, **kwargs):
"""as_value()
Convert :pc:`self` to a :ref:`value-like object <lang-valuelike>`.
Convert :py:`self` to a :ref:`value-like object <lang-valuelike>`.
This method is called by the Amaranth language to convert :pc:`self` to a concrete
This method is called by the Amaranth language to convert :py:`self` to a concrete
:class:`Value`. It will usually return a :class:`Value` object, but it may also return
another value-like object to delegate its functionality.
@ -1304,7 +1304,7 @@ class ValueCastable:
def shape(self, *args, **kwargs):
"""shape()
Compute the shape of :pc:`self`.
Compute the shape of :py:`self`.
This method is not called by the Amaranth language itself; whenever it needs to discover
the shape of a value-castable object, it calls :class:`self.as_value().shape()`. However,
@ -1367,7 +1367,7 @@ class _ValueLikeMeta(type):
class ValueLike(metaclass=_ValueLikeMeta):
"""Abstract class representing all objects that can be cast to a :class:`Value`.
:pc:`issubclass(cls, ValueLike)` returns :pc:`True` for:
:py:`issubclass(cls, ValueLike)` returns :py:`True` for:
* :class:`Value`;
* :class:`ValueCastable` and its subclasses;
@ -1375,8 +1375,8 @@ class ValueLike(metaclass=_ValueLikeMeta):
* :class:`enum.Enum` subclasses where all values are :ref:`value-like <lang-valuelike>`;
* :class:`ValueLike` itself.
:pc:`isinstance(obj, ValueLike)` returns the same value as
:pc:`issubclass(type(obj), ValueLike)`.
:py:`isinstance(obj, ValueLike)` returns the same value as
:py:`issubclass(type(obj), ValueLike)`.
This class cannot be instantiated or subclassed. It can only be used for checking types of
objects.
@ -1385,8 +1385,8 @@ class ValueLike(metaclass=_ValueLikeMeta):
It is possible to define an enumeration with a member that is
:ref:`value-like <lang-valuelike>` but not :ref:`constant-castable <lang-constcasting>`,
meaning that :pc:`issubclass(BadEnum, ValueLike)` returns :pc:`True`, but
:pc:`Value.cast(BadEnum.MEMBER)` raises an exception.
meaning that :py:`issubclass(BadEnum, ValueLike)` returns :py:`True`, but
:py:`Value.cast(BadEnum.MEMBER)` raises an exception.
The :mod:`amaranth.lib.enum` module prevents such enumerations from being defined when
the shape is specified explicitly. Using :mod:`amaranth.lib.enum` and specifying the shape

View file

@ -51,7 +51,7 @@ class Flow(enum.Enum):
Returns
-------
:class:`Flow`
:attr:`In` if called as :pc:`Out.flip()`; :attr:`Out` if called as :pc:`In.flip()`.
:attr:`In` if called as :py:`Out.flip()`; :attr:`Out` if called as :py:`In.flip()`.
"""
if self == Out:
return In
@ -66,7 +66,7 @@ class Flow(enum.Enum):
Returns
-------
:class:`Member`
:pc:`Member(self, description, reset=reset)`
:py:`Member(self, description, reset=reset)`
"""
return Member(self, description, reset=reset, src_loc_at=src_loc_at + 1)
@ -103,7 +103,7 @@ class Member:
will equal ``reset``.
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))`.
:data:`In` and :data:`Out`, e.g. :py:`In(unsigned(1))` or :py:`Out(stream.Signature(RGBPixel))`.
"""
def __init__(self, flow, description, *, reset=None, _dimensions=(), src_loc_at=0):
self._flow = flow
@ -145,8 +145,8 @@ class Member:
Returns
-------
:class:`Member`
A new :pc:`member` with :pc:`member.flow` equal to :pc:`self.flow.flip()`, and identical
to :pc:`self` other than that.
A new :py:`member` with :py:`member.flow` equal to :py:`self.flow.flip()`, and identical
to :py:`self` other than that.
"""
return Member(self._flow.flip(), self._description, reset=self._reset,
_dimensions=self._dimensions)
@ -155,21 +155,21 @@ class Member:
"""Add array dimensions to this member.
The dimensions passed to this method are `prepended` to the existing dimensions.
For example, :pc:`Out(1).array(2)` describes an array of 2 elements, whereas both
:pc:`Out(1).array(2, 3)` and :pc:`Out(1).array(3).array(2)` both describe a two dimensional
For example, :py:`Out(1).array(2)` describes an array of 2 elements, whereas both
:py:`Out(1).array(2, 3)` and :py:`Out(1).array(3).array(2)` both describe a two dimensional
array of 2 by 3 elements.
Dimensions are passed to :meth:`array` in the order in which they would be indexed.
That is, :pc:`.array(x, y)` creates a member that can be indexed up to :pc:`[x-1][y-1]`.
That is, :py:`.array(x, y)` creates a member that can be indexed up to :py:`[x-1][y-1]`.
The :meth:`array` method is composable: calling :pc:`member.array(x)` describes an array of
:pc:`x` members even if :pc:`member` was already an array.
The :meth:`array` method is composable: calling :py:`member.array(x)` describes an array of
:py:`x` members even if :py:`member` was already an array.
Returns
-------
:class:`Member`
A new :pc:`member` with :pc:`member.dimensions` extended by :pc:`dimensions`, and
identical to :pc:`self` other than that.
A new :py:`member` with :py:`member.dimensions` extended by :py:`dimensions`, and
identical to :py:`self` other than that.
"""
for dimension in dimensions:
if not (isinstance(dimension, int) and dimension >= 0):
@ -195,8 +195,8 @@ class Member:
Returns
-------
:class:`bool`
:pc:`True` if this is a description of a port member,
:pc:`False` if this is a description of a signature member.
:py:`True` if this is a description of a port member,
:py:`False` if this is a description of a signature member.
"""
return not isinstance(self._description, Signature)
@ -207,8 +207,8 @@ class Member:
Returns
-------
:class:`bool`
:pc:`True` if this is a description of a signature member,
:pc:`False` if this is a description of a port member.
:py:`True` if this is a description of a signature member,
:py:`False` if this is a description of a port member.
"""
return isinstance(self._description, Signature)
@ -224,7 +224,7 @@ class Member:
Raises
------
:exc:`AttributeError`
If :pc:`self` describes a signature member.
If :py:`self` describes a signature member.
"""
if self.is_signature:
raise AttributeError(f"A signature member does not have a shape")
@ -242,7 +242,7 @@ class Member:
Raises
------
:exc:`AttributeError`
If :pc:`self` describes a signature member.
If :py:`self` describes a signature member.
"""
if self.is_signature:
raise AttributeError(f"A signature member does not have a reset value")
@ -260,7 +260,7 @@ class Member:
Raises
------
:exc:`AttributeError`
If :pc:`self` describes a port member.
If :py:`self` describes a port member.
"""
if self.is_port:
raise AttributeError(f"A port member does not have a signature")
@ -316,7 +316,7 @@ class SignatureError(Exception):
class SignatureMembers(Mapping):
"""Mapping of signature member names to their descriptions.
This container, a :class:`collections.abc.Mapping`, is used to implement the :pc:`members`
This container, a :class:`collections.abc.Mapping`, is used to implement the :py:`members`
attribute of signature objects.
The keys in this container must be valid Python attribute names that are public (do not begin
@ -326,7 +326,7 @@ class SignatureMembers(Mapping):
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 :pc:`+=` opreator.
the :py:`+=` opreator.
The :meth:`create` method converts this mapping into a mapping of names to signature members
(signals and interface objects) by creating them from their descriptions. The created mapping
@ -348,7 +348,7 @@ class SignatureMembers(Mapping):
Returns
-------
:class:`FlippedSignatureMembers`
Proxy collection :pc:`FlippedSignatureMembers(self)` that flips the data flow of
Proxy collection :py:`FlippedSignatureMembers(self)` that flips the data flow of
the members that are accessed using it.
"""
return FlippedSignatureMembers(self)
@ -359,7 +359,7 @@ class SignatureMembers(Mapping):
Returns
-------
:class:`bool`
:pc:`True` if the mappings contain the same key-value pairs, :pc:`False` otherwise.
:py:`True` if the mappings contain the same key-value pairs, :py:`False` otherwise.
"""
return (isinstance(other, (SignatureMembers, FlippedSignatureMembers)) and
list(sorted(self.flatten())) == list(sorted(other.flatten())))
@ -391,11 +391,11 @@ class SignatureMembers(Mapping):
Raises
------
:exc:`TypeError`
If :pc:`name` is not a string.
If :py:`name` is not a string.
:exc:`NameError`
If :pc:`name` is not a valid, public Python attribute name.
If :py:`name` is not a valid, public Python attribute name.
:exc:`SignatureError`
If a member called :pc:`name` does not exist in the collection.
If a member called :py:`name` does not exist in the collection.
"""
self._check_name(name)
if name not in self._dict:
@ -551,7 +551,7 @@ class FlippedSignatureMembers(Mapping):
Returns
-------
:class:`SignatureMembers`
:pc:`unflipped`
:py:`unflipped`
"""
return self.__unflipped
@ -637,7 +637,7 @@ class SignatureMeta(type):
def __subclasscheck__(cls, subclass):
"""
Override of :pc:`issubclass(cls, Signature)`.
Override of :py:`issubclass(cls, Signature)`.
In addition to the standard behavior of :func:`issubclass`, this override makes
:class:`FlippedSignature` a subclass of :class:`Signature` or any of its subclasses.
@ -651,11 +651,11 @@ class SignatureMeta(type):
def __instancecheck__(cls, instance):
"""
Override of :pc:`isinstance(obj, Signature)`.
Override of :py:`isinstance(obj, Signature)`.
In addition to the standard behavior of :func:`isinstance`, this override makes
:pc:`isinstance(obj, cls)` act as :pc:`isinstance(obj.flip(), cls)` where
:pc:`obj` is an instance of :class:`FlippedSignature`.
:py:`isinstance(obj, cls)` act as :py:`isinstance(obj.flip(), cls)` where
:py:`obj` is an instance of :class:`FlippedSignature`.
"""
# `FlippedSignature` is an instance of a `Signature` or its subclass if the unflipped
@ -668,7 +668,7 @@ class SignatureMeta(type):
class Signature(metaclass=SignatureMeta):
"""Description of an interface object.
An interface object is a Python object that has a :pc:`signature` attribute containing
An interface object is a Python object that has a :py:`signature` attribute containing
a :class:`Signature` object, as well as an attribute for every member of its signature.
Signatures and interface objects are tightly linked: an interface object can be created out
of a signature, and the signature is used when :func:`connect` ing two interface objects
@ -693,7 +693,7 @@ class Signature(metaclass=SignatureMeta):
Returns
-------
:class:`FlippedSignature`
Proxy object :pc:`FlippedSignature(self)` that flips the data flow of the attributes
Proxy object :py:`FlippedSignature(self)` that flips the data flow of the attributes
corresponding to the members that are accessed using it.
See the documentation for the :class:`FlippedSignature` class for a detailed discussion
@ -714,10 +714,10 @@ class Signature(metaclass=SignatureMeta):
def __eq__(self, other):
"""Compare this signature with another.
The behavior of this operator depends on the types of the arguments. If both :pc:`self`
and :pc:`other` are instances of the base :class:`Signature` class, they are compared
structurally (the result is :pc:`self.members == other.members`); otherwise they are
compared by identity (the result is :pc:`self is other`).
The behavior of this operator depends on the types of the arguments. If both :py:`self`
and :py:`other` are instances of the base :class:`Signature` class, they are compared
structurally (the result is :py:`self.members == other.members`); otherwise they are
compared by identity (the result is :py:`self is other`).
Subclasses of :class:`Signature` are expected to override this method to take into account
the specifics of the domain. If the subclass has additional properties that do not influence
@ -806,9 +806,9 @@ class Signature(metaclass=SignatureMeta):
It verifies that:
* :pc:`obj` has a :pc:`signature` attribute whose value a :class:`Signature` instance
* :py:`obj` has a :py:`signature` attribute whose value a :class:`Signature` instance
such that ``self == obj.signature``;
* for each member, :pc:`obj` has an attribute with the same name, whose value:
* for each member, :py:`obj` has an attribute with the same name, whose value:
* for members with :meth:`dimensions <Member.dimensions>` specified, contains a list or
a tuple (or several levels of nested lists or tuples, for multiple dimensions)
@ -820,24 +820,24 @@ class Signature(metaclass=SignatureMeta):
* for signature members, matches the description in the signature as verified by
:meth:`Signature.is_compliant`.
If the verification fails, this method reports the reason(s) by filling the :pc:`reasons`
If the verification fails, this method reports the reason(s) by filling the :py:`reasons`
container. These reasons are intended to be human-readable: more than one reason may be
reported but only in cases where this is helpful (e.g. the same error message will not
repeat 10 times for each of the 10 ports in a list).
Arguments
---------
reasons : :class:`list` or :pc:`None`
reasons : :class:`list` or :py:`None`
If provided, a container that receives diagnostic messages.
path : :class:`tuple` of :class:`str`
The :ref:`path <wiring-path>` to :pc:`obj`. Could be set to improve diagnostic
messages if :pc:`obj` is nested within another object, or for clarity.
The :ref:`path <wiring-path>` to :py:`obj`. Could be set to improve diagnostic
messages if :py:`obj` is nested within another object, or for clarity.
Returns
-------
:class:`bool`
:pc:`True` if :pc:`obj` matches the description in this signature, :pc:`False`
otherwise. If :pc:`False` and :pc:`reasons` was not :pc:`None`, it will contain
:py:`True` if :py:`obj` matches the description in this signature, :py:`False`
otherwise. If :py:`False` and :py:`reasons` was not :py:`None`, it will contain
a detailed explanation why.
"""
@ -952,7 +952,7 @@ class Signature(metaclass=SignatureMeta):
This implementation creates an interface object from this signature that serves purely
as a container for the attributes corresponding to the signature members, and implements
no behavior. Such an implementation is sufficient for signatures created ad-hoc using
the :pc:`Signature({ ... })` constructor as well as simple signature subclasses.
the :py:`Signature({ ... })` constructor as well as simple signature subclasses.
When defining a :class:`Signature` subclass that needs to customize the behavior of
the created interface objects, override this method with a similar implementation
@ -969,7 +969,7 @@ class Signature(metaclass=SignatureMeta):
def my_property(self):
...
The :pc:`path` and :pc:`src_loc_at` arguments are necessary to ensure the generated signals
The :py:`path` and :py:`src_loc_at` arguments are necessary to ensure the generated signals
have informative names and accurate source location information.
The custom :meth:`create` method may take positional or keyword arguments in addition to
@ -1033,9 +1033,9 @@ class FlippedSignature:
It is not possible to inherit from :class:`FlippedSignature` and :meth:`Signature.flip` must not
be overridden. If a :class:`Signature` subclass defines a method and this method is called on
a flipped instance of the subclass, it receives the flipped instance as its :pc:`self` argument.
a flipped instance of the subclass, it receives the flipped instance as its :py:`self` argument.
To distinguish being called on the flipped instance from being called on the unflipped one, use
:pc:`isinstance(self, FlippedSignature)`:
:py:`isinstance(self, FlippedSignature)`:
.. testcode::
@ -1058,7 +1058,7 @@ class FlippedSignature:
Returns
-------
:class:`Signature`
:pc:`unflipped`
:py:`unflipped`
"""
return self.__unflipped
@ -1089,11 +1089,11 @@ class FlippedSignature:
# are two possible exits via `except AttributeError`: from `getattr` and from `.__get__()`.
def __getattr__(self, name):
"""Retrieves attribute or method :pc:`name` of the unflipped signature.
"""Retrieves attribute or method :py:`name` of the unflipped signature.
Performs :pc:`getattr(unflipped, name)`, ensuring that, if :pc:`name` refers to a property
getter or a method, its :pc:`self` argument receives the *flipped* signature. A class
method's :pc:`cls` argument receives the class of the *unflipped* signature, as usual.
Performs :py:`getattr(unflipped, name)`, ensuring that, if :py:`name` refers to a property
getter or a method, its :py:`self` argument receives the *flipped* signature. A class
method's :py:`cls` argument receives the class of the *unflipped* signature, as usual.
"""
try: # descriptor first
return _gettypeattr(self.__unflipped, name).__get__(self, type(self.__unflipped))
@ -1101,10 +1101,10 @@ class FlippedSignature:
return getattr(self.__unflipped, name)
def __setattr__(self, name, value):
"""Assigns attribute :pc:`name` of the unflipped signature to ``value``.
"""Assigns attribute :py:`name` of the unflipped signature to ``value``.
Performs :pc:`setattr(unflipped, name, value)`, ensuring that, if :pc:`name` refers to
a property setter, its :pc:`self` argument receives the flipped signature.
Performs :py:`setattr(unflipped, name, value)`, ensuring that, if :py:`name` refers to
a property setter, its :py:`self` argument receives the flipped signature.
"""
try: # descriptor first
_gettypeattr(self.__unflipped, name).__set__(self, value)
@ -1112,10 +1112,10 @@ class FlippedSignature:
setattr(self.__unflipped, name, value)
def __delattr__(self, name):
"""Removes attribute :pc:`name` of the unflipped signature.
"""Removes attribute :py:`name` of the unflipped signature.
Performs :pc:`delattr(unflipped, name)`, ensuring that, if :pc:`name` refers to a property
deleter, its :pc:`self` argument receives the flipped signature.
Performs :py:`delattr(unflipped, name)`, ensuring that, if :py:`name` refers to a property
deleter, its :py:`self` argument receives the flipped signature.
"""
try: # descriptor first
_gettypeattr(self.__unflipped, name).__delete__(self)
@ -1140,7 +1140,7 @@ class PureInterface:
.. important::
Any object can be an interface object; it only needs a :pc:`signature` property containing
Any object can be an interface object; it only needs a :py:`signature` property containing
a compliant signature. It is **not** necessary to use :class:`PureInterface` in order to
create an interface object, but it may be used either directly or as a base class whenever
it is convenient to do so.
@ -1150,7 +1150,7 @@ class PureInterface:
"""Create attributes from a signature.
The sole method defined by this helper is its constructor, which only defines
the :pc:`self.signature` attribute as well as the attributes created from the signature
the :py:`self.signature` attribute as well as the attributes created from the signature
members:
.. code::
@ -1187,7 +1187,7 @@ class FlippedInterface:
"""An interface object, with its members' directions flipped.
An instance of :class:`FlippedInterface` should only be created by calling :func:`flipped`,
which ensures that a :pc:`FlippedInterface(FlippedInterface(...))` object is never created.
which ensures that a :py:`FlippedInterface(FlippedInterface(...))` object is never created.
This proxy wraps any interface object and forwards attribute and method access to the wrapped
interface object while flipping its signature and the values of any attributes corresponding to
@ -1211,9 +1211,9 @@ class FlippedInterface:
It is not possible to inherit from :class:`FlippedInterface`. If an interface object class
defines a method or a property and it is called on the flipped interface object, the method
receives the flipped interface object as its :pc:`self` argument. To distinguish being called
receives the flipped interface object as its :py:`self` argument. To distinguish being called
on the flipped interface object from being called on the unflipped one, use
:pc:`isinstance(self, FlippedInterface)`:
:py:`isinstance(self, FlippedInterface)`:
.. testcode::
@ -1240,7 +1240,7 @@ class FlippedInterface:
Returns
-------
Signature
:pc:`unflipped.signature.flip()`
:py:`unflipped.signature.flip()`
"""
return self.__unflipped.signature.flip()
@ -1250,8 +1250,8 @@ class FlippedInterface:
Returns
-------
bool
:pc:`True` if :pc:`other` is an instance :pc:`FlippedInterface(other_unflipped)` where
:pc:`unflipped == other_unflipped`, :pc:`False` otherwise.
:py:`True` if :py:`other` is an instance :py:`FlippedInterface(other_unflipped)` where
:py:`unflipped == other_unflipped`, :py:`False` otherwise.
"""
return type(self) is type(other) and self.__unflipped == other.__unflipped
@ -1259,13 +1259,13 @@ class FlippedInterface:
# an interface member.
def __getattr__(self, name):
"""Retrieves attribute or method :pc:`name` of the unflipped interface.
"""Retrieves attribute or method :py:`name` of the unflipped interface.
Performs :pc:`getattr(unflipped, name)`, with the following caveats:
Performs :py:`getattr(unflipped, name)`, with the following caveats:
1. If :pc:`name` refers to a signature member, the returned interface object is flipped.
2. If :pc:`name` refers to a property getter or a method, its :pc:`self` argument receives
the *flipped* interface. A class method's :pc:`cls` argument receives the class of
1. If :py:`name` refers to a signature member, the returned interface object is flipped.
2. If :py:`name` refers to a property getter or a method, its :py:`self` argument receives
the *flipped* interface. A class method's :py:`cls` argument receives the class of
the *unflipped* interface, as usual.
"""
if (name in self.__unflipped.signature.members and
@ -1278,12 +1278,12 @@ class FlippedInterface:
return getattr(self.__unflipped, name)
def __setattr__(self, name, value):
"""Assigns attribute :pc:`name` of the unflipped interface to ``value``.
"""Assigns attribute :py:`name` of the unflipped interface to ``value``.
Performs :pc:`setattr(unflipped, name, value)`, with the following caveats:
Performs :py:`setattr(unflipped, name, value)`, with the following caveats:
1. If :pc:`name` refers to a signature member, the assigned interface object is flipped.
2. If :pc:`name` refers to a property setter, its :pc:`self` argument receives the flipped
1. If :py:`name` refers to a signature member, the assigned interface object is flipped.
2. If :py:`name` refers to a property setter, its :py:`self` argument receives the flipped
interface.
"""
if (name in self.__unflipped.signature.members and
@ -1296,10 +1296,10 @@ class FlippedInterface:
setattr(self.__unflipped, name, value)
def __delattr__(self, name):
"""Removes attribute :pc:`name` of the unflipped interface.
"""Removes attribute :py:`name` of the unflipped interface.
Performs :pc:`delattr(unflipped, name)`, ensuring that, if :pc:`name` refers to a property
deleter, its :pc:`self` argument receives the flipped interface.
Performs :py:`delattr(unflipped, name)`, ensuring that, if :py:`name` refers to a property
deleter, its :py:`self` argument receives the flipped interface.
"""
try: # descriptor first
_gettypeattr(self.__unflipped, name).__delete__(self)
@ -1312,10 +1312,10 @@ class FlippedInterface:
def flipped(interface):
"""
Flip the data flow of the members of the interface object :pc:`interface`.
Flip the data flow of the members of the interface object :py:`interface`.
If an interface object is flipped twice, returns the original object:
:pc:`flipped(flipped(interface)) is interface`. Otherwise, wraps :pc:`interface` in
:py:`flipped(flipped(interface)) is interface`. Otherwise, wraps :py:`interface` in
a :class:`FlippedInterface` proxy object that flips the directions of its members.
See the documentation for the :class:`FlippedInterface` class for a detailed discussion of how
@ -1352,11 +1352,11 @@ def connect(m, *args, **kwargs):
to a constant value, then the rest of the interface objects must have output port members
corresponding to the same constant value.
For example, if :pc:`obj1` is being connected to :pc:`obj2` and :pc:`obj3`, and :pc:`obj1.a.b`
is an output, then :pc:`obj2.a.b` and :pc:`obj2.a.b` must exist and be inputs. If :pc:`obj2.c`
is an input and its value is :pc:`Const(1)`, then :pc:`obj1.c` and :pc:`obj3.c` must be outputs
whose value is also :pc:`Const(1)`. If no ports besides :pc:`obj1.a.b` and :pc:`obj1.c` exist,
then no ports except for those two must exist on :pc:`obj2` and :pc:`obj3` either.
For example, if :py:`obj1` is being connected to :py:`obj2` and :py:`obj3`, and :py:`obj1.a.b`
is an output, then :py:`obj2.a.b` and :py:`obj2.a.b` must exist and be inputs. If :py:`obj2.c`
is an input and its value is :py:`Const(1)`, then :py:`obj1.c` and :py:`obj3.c` must be outputs
whose value is also :py:`Const(1)`. If no ports besides :py:`obj1.a.b` and :py:`obj1.c` exist,
then no ports except for those two must exist on :py:`obj2` and :py:`obj3` either.
Once it is determined that the interface objects can be connected, this function performs
an equivalent of:
@ -1369,12 +1369,12 @@ def connect(m, *args, **kwargs):
...
]
Where :pc:`out1` is an output and :pc:`in1`, :pc:`in2`, ... are the inputs that have the same
Where :py:`out1` is an output and :py:`in1`, :py:`in2`, ... are the inputs that have the same
path. (If no interface object has an output for a given path, **no connection at all** is made.)
The positions (within :pc:`args`) or names (within :pc:`kwargs`) of the arguments do not affect
the connections that are made. There is no difference in behavior between :pc:`connect(m, a, b)`
and :pc:`connect(m, b, a)` or :pc:`connect(m, arbiter=a, decoder=b)`. The names of the keyword
The positions (within :py:`args`) or names (within :py:`kwargs`) of the arguments do not affect
the connections that are made. There is no difference in behavior between :py:`connect(m, a, b)`
and :py:`connect(m, b, a)` or :py:`connect(m, arbiter=a, decoder=b)`. The names of the keyword
arguments serve only a documentation purpose: they clarify the diagnostic messages when
a connection cannot be made.
"""
@ -1609,8 +1609,8 @@ class Component(Elaboratable):
Raises
------
:exc:`TypeError`
If the :pc:`signature` object is neither a :class:`Signature` nor a :class:`dict`.
If neither variable annotations nor the :pc:`signature` argument are present, or if
If the :py:`signature` object is neither a :class:`Signature` nor a :class:`dict`.
If neither variable annotations nor the :py:`signature` argument are present, or if
both are present.
:exc:`NameError`
If a name conflict is detected between two variable annotations, or between a member