lib.enum: add Enum wrappers that allow specifying shape.
See #756 and amaranth-lang/rfcs#3.
This commit is contained in:
parent
ef2e9fa809
commit
57612f1dce
10 changed files with 343 additions and 40 deletions
|
|
@ -22,6 +22,17 @@ Apply the following changes to code written against Amaranth 0.3 to migrate it t
|
|||
|
||||
While code that uses the features listed as deprecated below will work in Amaranth 0.4, they will be removed in the next version.
|
||||
|
||||
Implemented RFCs
|
||||
----------------
|
||||
|
||||
.. _RFC 3: https://amaranth-lang.org/rfcs/0003-enumeration-shapes.html
|
||||
.. _RFC 4: https://amaranth-lang.org/rfcs/0004-const-castable-exprs.html
|
||||
.. _RFC 5: https://amaranth-lang.org/rfcs/0005-remove-const-normalize.html
|
||||
|
||||
* `RFC 3`_: Enumeration shapes
|
||||
* `RFC 4`_: Constant-castable expressions
|
||||
* `RFC 5`_: Remove Const.normalize
|
||||
|
||||
|
||||
Language changes
|
||||
----------------
|
||||
|
|
@ -30,19 +41,24 @@ Language changes
|
|||
|
||||
* Added: :class:`ShapeCastable`, similar to :class:`ValueCastable`.
|
||||
* Added: :meth:`Value.as_signed` and :meth:`Value.as_unsigned` can be used on left-hand side of assignment (with no difference in behavior).
|
||||
* Added: :meth:`Const.cast`, evaluating constant-castable values and returning a :class:`Const`. (`RFC 4`_)
|
||||
* Added: :meth:`Const.cast`. (`RFC 4`_)
|
||||
* Added: :meth:`Value.matches` and ``with m.Case():`` accept any constant-castable objects. (`RFC 4`_)
|
||||
* Changed: :meth:`Value.cast` casts :class:`ValueCastable` objects recursively.
|
||||
* Changed: :meth:`Value.cast` treats instances of classes derived from both :class:`enum.Enum` and :class:`int` (including :class:`enum.IntEnum`) as enumerations rather than integers.
|
||||
* Changed: ``Value.matches()`` with an empty list of patterns returns ``Const(1)`` rather than ``Const(0)``, to match ``with m.Case():``.
|
||||
* Changed: :class:`Cat` accepts instances of classes derived from both :class:`enum.Enum` and :class:`int` (including :class:`enum.IntEnum`) without warning.
|
||||
* Changed: :meth:`Value.matches` with an empty list of patterns returns ``Const(1)`` rather than ``Const(0)``, to match the behavior of ``with m.Case():``.
|
||||
* Changed: :class:`Cat` warns if an enumeration without an explicitly specified shape is used.
|
||||
* Deprecated: :meth:`Const.normalize`. (`RFC 5`_)
|
||||
* Removed: (deprecated in 0.1) casting of :class:`Shape` to and from a ``(width, signed)`` tuple.
|
||||
* Removed: (deprecated in 0.3) :class:`ast.UserValue`.
|
||||
* Removed: (deprecated in 0.3) support for ``# nmigen:`` linter instructions at the beginning of file.
|
||||
|
||||
.. _RFC 4: https://amaranth-lang.org/rfcs/0004-const-castable-exprs.html
|
||||
.. _RFC 5: https://amaranth-lang.org/rfcs/0005-remove-const-normalize.html
|
||||
|
||||
Standard library changes
|
||||
------------------------
|
||||
|
||||
.. currentmodule:: amaranth.lib
|
||||
|
||||
* Added: :mod:`amaranth.lib.enum`.
|
||||
|
||||
|
||||
Toolchain changes
|
||||
|
|
|
|||
|
|
@ -27,9 +27,17 @@ intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
|
|||
|
||||
todo_include_todos = True
|
||||
|
||||
autodoc_member_order = "bysource"
|
||||
autodoc_default_options = {
|
||||
"members": True
|
||||
}
|
||||
autodoc_preserve_defaults = True
|
||||
|
||||
napoleon_google_docstring = False
|
||||
napoleon_numpy_docstring = True
|
||||
napoleon_use_ivar = True
|
||||
napoleon_include_init_with_doc = True
|
||||
napoleon_include_special_with_doc = True
|
||||
napoleon_custom_sections = ["Platform overrides"]
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
|
|
|||
|
|
@ -183,11 +183,7 @@ Specifying a shape with a range is convenient for counters, indexes, and all oth
|
|||
Shapes from enumerations
|
||||
------------------------
|
||||
|
||||
Casting a shape from an :class:`enum.Enum` subclass ``E``:
|
||||
|
||||
* fails if any of the enumeration members have non-integer values,
|
||||
* has a width large enough to represent both ``min(m.value for m in E)`` and ``max(m.value for m in E)``, and
|
||||
* is signed if either ``min(m.value for m in E)`` or ``max(m.value for m in E)`` are negative, unsigned otherwise.
|
||||
Casting a shape from an :class:`enum.Enum` subclass requires all of the enumeration members to have :ref:`constant-castable <lang-constcasting>` values. The shape has a width large enough to represent the value of every member, and is signed only if there is a member with a negative value.
|
||||
|
||||
Specifying a shape with an enumeration is convenient for finite state machines, multiplexers, complex control signals, and all other values whose width is derived from a few distinct choices they must be able to fit:
|
||||
|
||||
|
|
@ -208,9 +204,27 @@ Specifying a shape with an enumeration is convenient for finite state machines,
|
|||
>>> Shape.cast(Direction)
|
||||
unsigned(2)
|
||||
|
||||
The :mod:`amaranth.lib.enum` module extends the standard enumerations such that their shape can be specified explicitly when they are defined:
|
||||
|
||||
.. testsetup::
|
||||
|
||||
import amaranth.lib.enum
|
||||
|
||||
.. testcode::
|
||||
|
||||
class Funct4(amaranth.lib.enum.Enum, shape=unsigned(4)):
|
||||
ADD = 0
|
||||
SUB = 1
|
||||
MUL = 2
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> Shape.cast(Funct4)
|
||||
unsigned(4)
|
||||
|
||||
.. note::
|
||||
|
||||
The enumeration does not have to subclass :class:`enum.IntEnum`; it only needs to have integers as values of every member. Using enumerations based on :class:`enum.Enum` rather than :class:`enum.IntEnum` prevents unwanted implicit conversion of enum members to integers.
|
||||
The enumeration does not have to subclass :class:`enum.IntEnum` or have :class:`int` as one of its base classes; it only needs to have integers as values of every member. Using enumerations based on :class:`enum.Enum` rather than :class:`enum.IntEnum` prevents unwanted implicit conversion of enum members to integers.
|
||||
|
||||
|
||||
.. _lang-valuecasting:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Standard library
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
stdlib/enum
|
||||
stdlib/coding
|
||||
stdlib/cdc
|
||||
stdlib/fifo
|
||||
stdlib/fifo
|
||||
|
|
|
|||
43
docs/stdlib/enum.rst
Normal file
43
docs/stdlib/enum.rst
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
Enumerations
|
||||
############
|
||||
|
||||
.. py:module:: amaranth.lib.enum
|
||||
|
||||
The :mod:`amaranth.lib.enum` module is a drop-in replacement for the standard :mod:`enum` module that provides extended :class:`Enum`, :class:`IntEnum`, :class:`Flag`, and :class:`IntFlag` classes with the ability to specify a shape explicitly.
|
||||
|
||||
A shape can be specified for an enumeration with the ``shape=`` keyword argument:
|
||||
|
||||
.. testsetup::
|
||||
|
||||
from amaranth import *
|
||||
|
||||
.. testcode::
|
||||
|
||||
from amaranth.lib import enum
|
||||
|
||||
class Funct4(enum.Enum, shape=4):
|
||||
ADD = 0
|
||||
SUB = 1
|
||||
MUL = 2
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> Shape.cast(Funct4)
|
||||
unsigned(4)
|
||||
|
||||
This module is a drop-in replacement for the standard :mod:`enum` module, and re-exports all of its members (not just the ones described below). In an Amaranth project, all ``import enum`` statements may be replaced with ``from amaranth.lib import enum``.
|
||||
|
||||
|
||||
Metaclass
|
||||
=========
|
||||
|
||||
.. autoclass:: EnumMeta()
|
||||
|
||||
|
||||
Base classes
|
||||
============
|
||||
|
||||
.. autoclass:: Enum()
|
||||
.. autoclass:: IntEnum()
|
||||
.. autoclass:: Flag()
|
||||
.. autoclass:: IntFlag()
|
||||
Loading…
Add table
Add a link
Reference in a new issue