docs/reference: document compat guarantee, importing, shapes.

This commit also contains a related semantic change: it adds `Shape`
and `ShapeCastable` to the `__all__` list in `amaranth.hdl`. This is
consistent with the policy that is laid out in the new documentation,
which permits such additions without notice.

Co-authored-by: mcclure <mcclure@users.noreply.github.com>
This commit is contained in:
Catherine 2024-01-30 01:44:07 +00:00
parent c9b87a4fc5
commit ea3d6c9557
6 changed files with 325 additions and 79 deletions

View file

@ -6,6 +6,8 @@
Language guide
##############
.. py:currentmodule:: amaranth.hdl
.. warning::
This guide is a work in progress and is seriously incomplete!
@ -44,7 +46,7 @@ All of the examples below assume that a glob import is used.
Shapes
======
A ``Shape`` is an object with two attributes, ``.width`` and ``.signed``. It can be constructed directly:
A :class:`Shape` describes the bit width and signedness of an Amaranth value. It can be constructed directly:
.. doctest::
@ -53,7 +55,7 @@ A ``Shape`` is an object with two attributes, ``.width`` and ``.signed``. It can
>>> Shape(width=12, signed=True)
signed(12)
However, in most cases, the shape is always constructed with the same signedness, and the aliases ``signed`` and ``unsigned`` are more convenient:
However, in most cases, the signedness of a shape is known upfront, and the convenient aliases :func:`signed` and :func:`unsigned` can be used:
.. doctest::
@ -126,9 +128,9 @@ The shape of the constant can be specified explicitly, in which case the number'
Shape casting
=============
Shapes can be *cast* from other objects, which are called *shape-like*. Casting is a convenient way to specify a shape indirectly, for example, by a range of numbers representable by values with that shape.
Shapes can be *cast* from other objects, which are called *shape-like*. Casting is a convenient way to specify a shape indirectly, for example, by a range of numbers representable by values with that shape. Shapes are shape-like objects as well.
Casting to a shape can be done explicitly with ``Shape.cast``, but is usually implicit, since shape-like objects are accepted anywhere shapes are.
Casting to a shape can be done explicitly with :meth:`Shape.cast`, but is usually implicit, since shape-like objects are accepted anywhere shapes are.
.. _lang-shapeint:
@ -136,7 +138,7 @@ Casting to a shape can be done explicitly with ``Shape.cast``, but is usually im
Shapes from integers
--------------------
Casting a shape from an integer ``i`` is a shorthand for constructing a shape with ``unsigned(i)``:
Casting a shape from an integer ``i`` is a shorthand for constructing a shape with :func:`unsigned(i) <unsigned>`:
.. doctest::
@ -186,7 +188,7 @@ Specifying a shape with a range is convenient for counters, indexes, and all oth
.. note::
An empty range always casts to an ``unsigned(0)``, even if both of its bounds are negative.
An empty range always casts to an :py:`unsigned(0)`, even if both of its bounds are negative.
This happens because, being empty, it does not contain any negative values.
.. doctest::
@ -244,22 +246,30 @@ The :mod:`amaranth.lib.enum` module extends the standard enumerations such that
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-shapecustom:
Custom shapes
-------------
Any Python value that implements the :class:`ShapeCastable` interface can extend the language with a custom shape-like object. For example, the standard library module :mod:`amaranth.lib.data` uses this facility to add support for aggregate data types to the language.
.. _lang-valuelike:
Value casting
=============
Like shapes, values may be *cast* from other objects, which are called *value-like*. Casting to values allows objects that are not provided by Amaranth, such as integers or enumeration members, to be used in Amaranth expressions directly.
Like shapes, values may be *cast* from other objects, which are called *value-like*. Casting to values allows objects that are not provided by Amaranth, such as integers or enumeration members, to be used in Amaranth expressions directly. Values are value-like objects as well.
.. TODO: link to ValueCastable
Casting to a value can be done explicitly with ``Value.cast``, but is usually implicit, since value-like objects are accepted anywhere values are.
Casting to a value can be done explicitly with :meth:`Value.cast`, but is usually implicit, since value-like objects are accepted anywhere values are.
Values from integers
--------------------
Casting a value from an integer ``i`` is equivalent to ``Const(i)``:
Casting a value from an integer ``i`` is equivalent to :class:`Const(i) <Const>`:
.. doctest::
@ -344,7 +354,7 @@ A *signal* is a value representing a (potentially) varying number. Signals can b
Signal shapes
-------------
A signal can be created with an explicitly specified shape (any :ref:`shape-like <lang-shapelike>` object); if omitted, the shape defaults to ``unsigned(1)``. Although rarely useful, 0-bit signals are permitted.
A signal can be created with an explicitly specified shape (any :ref:`shape-like <lang-shapelike>` object); if omitted, the shape defaults to :func:`unsigned(1) <unsigned>`. Although rarely useful, 0-bit signals are permitted.
.. doctest::

View file

@ -1,8 +1,106 @@
Language reference
##################
.. py:module:: amaranth.hdl
.. warning::
This guide is a work in progress and is seriously incomplete!
This reference is a work in progress and is seriously incomplete!
While the wording below states that anything not described in this document isn't covered by the backwards compatibility guarantee, this should be ignored until the document is complete and this warning is removed.
This reference describes the Python classes that underlie the Amaranth language's syntax. It assumes familiarity with the :doc:`language guide <guide>`.
.. _lang-stability:
Backwards compatibility
=======================
As part of the Amaranth backwards compatibility guarantee, any behaviors described in this document will not change from a version to another without at least one version including a warning about the impending change. Any nontrivial change to these behaviors must also go through the public review as a part of the `Amaranth Request for Comments process <https://amaranth-lang.org/rfcs/>`_.
Conversely, any behavior not documented here is subject to change at any time with or without notice, and any names under the :mod:`amaranth.hdl` module that are not explicitly included in this document, even if they do not begin with an underscore, are internal to the implementation of the language.
.. _lang-importing:
Importing syntax
================
There are two ways to import the Amaranth syntax into a Python file: by importing the :ref:`prelude <lang-prelude>` or by importing individual names from the :mod:`amaranth.hdl` module. Since the prelude is kept small and rarely extended to avoid breaking downstream code that uses a glob import, there are some names that are only exported from the :mod:`amaranth.hdl` module. The following three snippets are equivalent:
.. testcode::
from amaranth import *
m = Module()
.. testcode::
import amaranth as am
m = am.Module()
.. testcode::
from amaranth.hdl import Module
m = Module()
The prelude exports exactly the following names:
.. must be kept in sync with amaranth/__init__.py!
* :class:`Shape`
* :func:`unsigned`
* :func:`signed`
* :class:`Value`
* :class:`Const`
* :func:`C`
* :func:`Mux`
* :class:`Cat`
* :class:`Repl` (deprecated)
* :class:`Array`
* :class:`Signal`
* :class:`ClockSignal`
* :class:`ResetSignal`
* :class:`Module`
* :class:`ClockDomain`
* :class:`Elaboratable`
* :class:`Fragment`
* :class:`Instance`
* :class:`Memory`
* :class:`Record` (deprecated)
* :class:`DomainRenamer`
* :class:`ResetInserter`
* :class:`EnableInserter`
.. _lang-srcloc:
Source locations
================
Many functions and methods in Amaranth take the :pc:`src_loc_at=0` keyword argument. These language constructs may inspect the call stack to determine the file and line of its call site, which will be used to annotate generated code when a netlist is generated or to improve diagnostic messages.
Some call sites are not relevant for an Amaranth designer; e.g. when an Amaranth language construct is called from a user-defined utility function, the source location of the call site within this utility function is usually not interesting to the designer. In these cases, one or more levels of function calls can be removed from consideration using the :pc:`src_loc_at` argument as follows (using :meth:`Shape.cast` to demonstrate the concept):
.. testcode::
def my_shape_cast(obj, *, src_loc_at=0):
... # additionally process `obj`...
return Shape.cast(obj, src_loc_at=1 + src_loc_at)
The number :pc:`1` corresponds to the number of call stack frames that should be skipped.
Shapes
======
See also the introduction to :ref:`shapes <lang-shapes>` and :ref:`casting from shape-like objects <lang-shapelike>` in the language guide.
.. autoclass:: Shape
.. autofunction:: unsigned
.. autofunction:: signed
.. autoclass:: ShapeCastable
.. autoclass:: ShapeLike

View file

@ -7,6 +7,8 @@ The :mod:`amaranth.lib` module, also known as the standard library, provides mod
2. Modules that abstract common functionality whose implementation differs between hardware platforms. This includes :mod:`amaranth.lib.cdc`.
3. Modules that have essentially one correct implementation and are of broad utility in digital designs. This includes :mod:`amaranth.lib.coding`, :mod:`amaranth.lib.fifo`, and :mod:`amaranth.lib.crc`.
As part of the Amaranth backwards compatibility guarantee, any behaviors described in these documents will not change from a version to another without at least one version including a warning about the impending change. Any nontrivial change to these behaviors must also go through the public review as a part of the `Amaranth Request for Comments process <https://amaranth-lang.org/rfcs/>`_.
The Amaranth standard library is separate from the Amaranth language: everything provided in it could have been implemented in a third-party library.
.. toctree::