Skip to content

Commit 7870eb3

Browse files
committed
sim: document.
This commit includes additional non-documentation changes, related to issues found while documenting it: - `Simulator.run_until()` no longer accepts a `run_passive=` argument. Passive no longer exist and in any case defaulting to `False` does not make a lot of sense from an API perspective. - `add_clock()`'s `phase=` argument, when specified, no longer has `period/2` added to it. This wasn't the documented behavior in first place and it makes no sense to do that. - `add_clock()` raises a `NameError` if a clock domain does not exist, instead of `ValueError`. - `add_clock()` raises a `DriverConflict` if a clock domain is already being driven by a clock, instead of `ValueError`. - GTKWave is no longer a part of the installation instructions, and both Surfer and GTKWave are recommended (in this order).
1 parent 3c1060f commit 7870eb3

16 files changed

+1179
-222
lines changed

amaranth/sim/__init__.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
from .core import *
1+
from .core import Simulator
2+
from ._async import DomainReset, BrokenTrigger, SimulatorContext, TickTrigger, TriggerCombination
3+
from ._pycoro import Settle, Delay, Tick, Passive, Active
24

35

46
__all__ = [
5-
"DomainReset", "BrokenTrigger", "Simulator",
7+
"DomainReset", "BrokenTrigger",
8+
"SimulatorContext", "Simulator", "TickTrigger", "TriggerCombination",
69
# deprecated
710
"Settle", "Delay", "Tick", "Passive", "Active",
811
]

amaranth/sim/_async.py

+496-30
Large diffs are not rendered by default.

amaranth/sim/_pycoro.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ class Command:
1414

1515
class Settle(Command):
1616
@deprecated("The `Settle` command is deprecated per RFC 27. Use `add_testbench` to write "
17-
"testbenches; in them, an equivalent of `yield Settle()` is performed "
18-
"automatically.")
17+
"testbenches; there, an equivalent of `yield Settle()` is performed "
18+
"automatically after each `ctx.set()`.")
1919
def __init__(self):
2020
pass
2121

@@ -37,8 +37,7 @@ def __repr__(self):
3737
class Tick(Command):
3838
def __init__(self, domain="sync"):
3939
if not isinstance(domain, (str, ClockDomain)):
40-
raise TypeError("Domain must be a string or a ClockDomain instance, not {!r}"
41-
.format(domain))
40+
raise TypeError(f"Domain must be a string or a ClockDomain instance, not {domain!r}")
4241
assert domain != "comb"
4342
self.domain = domain
4443

amaranth/sim/core.py

+276-120
Large diffs are not rendered by default.

amaranth/sim/pysim.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ def add_var(path, var_type, var_size, var_init, value):
142142
suffix = f"[{var_size - 1}:0]"
143143
else:
144144
suffix = ""
145-
self.gtkw_signal_names[signal].append(".".join((*var_scope, field_name)) + suffix)
145+
self.gtkw_signal_names[signal].append(
146+
".".join((*var_scope, field_name)) + suffix)
146147
else:
147148
self.vcd_writer.register_alias(
148149
scope=var_scope, name=field_name,

docs/_code/up_counter.py

+13-13
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,29 @@ def elaborate(self, platform):
4747

4848

4949
dut = UpCounter(25)
50-
def bench():
50+
async def bench(ctx):
5151
# Disabled counter should not overflow.
52-
yield dut.en.eq(0)
52+
ctx.set(dut.en, 0)
5353
for _ in range(30):
54-
yield
55-
assert not (yield dut.ovf)
54+
await ctx.tick()
55+
assert not ctx.get(dut.ovf)
5656

5757
# Once enabled, the counter should overflow in 25 cycles.
58-
yield dut.en.eq(1)
59-
for _ in range(25):
60-
yield
61-
assert not (yield dut.ovf)
62-
yield
63-
assert (yield dut.ovf)
58+
ctx.set(dut.en, 1)
59+
for _ in range(24):
60+
await ctx.tick()
61+
assert not ctx.get(dut.ovf)
62+
await ctx.tick()
63+
assert ctx.get(dut.ovf)
6464

6565
# The overflow should clear in one cycle.
66-
yield
67-
assert not (yield dut.ovf)
66+
await ctx.tick()
67+
assert not ctx.get(dut.ovf)
6868

6969

7070
sim = Simulator(dut)
7171
sim.add_clock(1e-6) # 1 MHz
72-
sim.add_sync_process(bench)
72+
sim.add_testbench(bench)
7373
with sim.write_vcd("up_counter.vcd"):
7474
sim.run()
7575
# --- CONVERT ---

docs/_images/up_counter_gtkwave.png

-32.9 KB
Binary file not shown.

docs/changes.rst

+34-25
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,23 @@ Migrating from version 0.4
2929

3030
Apply the following changes to code written against Amaranth 0.4 to migrate it to version 0.5:
3131

32-
* Replace uses of ``m.Case()`` with no patterns with ``m.Default()``
33-
* Replace uses of ``Value.matches()`` with no patterns with ``Const(1)``
34-
* Update uses of ``amaranth.utils.log2_int(need_pow2=False)`` to :func:`amaranth.utils.ceil_log2`
35-
* Update uses of ``amaranth.utils.log2_int(need_pow2=True)`` to :func:`amaranth.utils.exact_log2`
36-
* Update uses of ``reset=`` keyword argument to ``init=``
37-
* Convert uses of ``Simulator.add_sync_process`` used as testbenches to ``Simulator.add_testbench``
38-
* Convert other uses of ``Simulator.add_sync_process`` to ``Simulator.add_process``
39-
* Replace uses of ``amaranth.hdl.Memory`` with ``amaranth.lib.memory.Memory``
40-
* Replace imports of ``amaranth.asserts.{Assert, Assume, Cover}`` with imports from ``amaranth.hdl``
41-
* Remove any usage of ``name=`` with assertions, possibly replacing them with custom messages
42-
* Ensure all elaboratables are subclasses of :class:`Elaboratable`
32+
* Replace uses of :py:`m.Case()` with no patterns with :py:`m.Default()`.
33+
* Replace uses of :py:`Value.matches()` with no patterns with :py:`Const(1)`.
34+
* Update uses of :py:`amaranth.utils.log2_int(need_pow2=False)` to :func:`amaranth.utils.ceil_log2`.
35+
* Update uses of :py:`amaranth.utils.log2_int(need_pow2=True)` to :func:`amaranth.utils.exact_log2`.
36+
* Update uses of :py:`reset=` keyword argument to :py:`init=`.
37+
* Convert uses of :py:`Simulator.add_sync_process` used as testbenches to :meth:`Simulator.add_testbench <amaranth.sim.Simulator.add_testbench>`.
38+
* Convert other uses of :py:`Simulator.add_sync_process` to :meth:`Simulator.add_process <amaranth.sim.Simulator.add_process>`.
39+
* Convert simulator processes and testbenches to use the new async API.
40+
* Replace uses of :py:`amaranth.hdl.Memory` with :class:`amaranth.lib.memory.Memory`.
41+
* Replace imports of :py:`amaranth.asserts.Assert`, :py:`Assume`, and :py:`Cover` with imports from :py:`amaranth.hdl`.
42+
* Remove uses of :py:`name=` keyword argument of :py:`Assert`, :py:`Assume`, and :py:`Cover`; a message can be used instead.
43+
* Ensure all elaboratables are subclasses of :class:`Elaboratable`.
4344
* Ensure clock domains aren't used outside the module that defines them, or its submodules; move clock domain definitions upwards in the hierarchy as necessary
44-
* Remove uses of ``amaranth.lib.coding.*`` by inlining or copying the implementation of the modules
45-
* Update uses of ``platform.request`` to pass ``dir="-"`` and use :mod:`amaranth.lib.io` buffers
45+
* Remove uses of :py:`amaranth.lib.coding.*` by inlining or copying the implementation of the modules.
46+
* Update uses of :py:`platform.request` to pass :py:`dir="-"` and use :mod:`amaranth.lib.io` buffers.
47+
* Update uses of :meth:`Simulator.add_clock <amaranth.sim.Simulator.add_clock>` with explicit :py:`phase` to take into account simulator no longer adding implicit :py:`period / 2`. (Previously, :meth:`Simulator.add_clock <amaranth.sim.Simulator.add_clock>` was documented to first toggle the clock at the time :py:`phase`, but actually first toggled the clock at :py:`period / 2 + phase`.)
48+
* Update uses of :meth:`Simulator.run_until <amaranth.sim.Simulator.run_until>` to remove the :py:`run_passive=True` argument. If the code uses :py:`run_passive=False`, ensure it still works with the new behavior.
4649

4750

4851
Implemented RFCs
@@ -51,6 +54,7 @@ Implemented RFCs
5154
.. _RFC 17: https://amaranth-lang.org/rfcs/0017-remove-log2-int.html
5255
.. _RFC 27: https://amaranth-lang.org/rfcs/0027-simulator-testbenches.html
5356
.. _RFC 30: https://amaranth-lang.org/rfcs/0030-component-metadata.html
57+
.. _RFC 36: https://amaranth-lang.org/rfcs/0036-async-testbench-functions.html
5458
.. _RFC 39: https://amaranth-lang.org/rfcs/0039-empty-case.html
5559
.. _RFC 43: https://amaranth-lang.org/rfcs/0043-rename-reset-to-init.html
5660
.. _RFC 45: https://amaranth-lang.org/rfcs/0045-lib-memory.html
@@ -68,6 +72,7 @@ Implemented RFCs
6872
* `RFC 17`_: Remove ``log2_int``
6973
* `RFC 27`_: Testbench processes for the simulator
7074
* `RFC 30`_: Component metadata
75+
* `RFC 36`_: Async testbench functions
7176
* `RFC 39`_: Change semantics of no-argument ``m.Case()``
7277
* `RFC 43`_: Rename ``reset=`` to ``init=``
7378
* `RFC 45`_: Move ``hdl.Memory`` to ``lib.Memory``
@@ -94,12 +99,12 @@ Language changes
9499
* Added: :meth:`ShapeCastable.from_bits` method. (`RFC 51`_)
95100
* Added: IO values, :class:`IOPort` objects, :class:`IOBufferInstance` objects. (`RFC 53`_)
96101
* Added: :class:`MemoryData` objects. (`RFC 62`_)
97-
* Changed: ``m.Case()`` with no patterns is never active instead of always active. (`RFC 39`_)
98-
* Changed: ``Value.matches()`` with no patterns is ``Const(0)`` instead of ``Const(1)``. (`RFC 39`_)
99-
* Changed: ``Signal(range(stop), init=stop)`` warning has been changed into a hard error and made to trigger on any out-of range value.
100-
* Changed: ``Signal(range(0))`` is now valid without a warning.
101-
* Changed: ``Shape.cast(range(1))`` is now ``unsigned(0)``. (`RFC 46`_)
102-
* Changed: the ``reset=`` argument of :class:`Signal`, :meth:`Signal.like`, :class:`amaranth.lib.wiring.Member`, :class:`amaranth.lib.cdc.FFSynchronizer`, and ``m.FSM()`` has been renamed to ``init=``. (`RFC 43`_)
102+
* Changed: :py:`m.Case()` with no patterns is never active instead of always active. (`RFC 39`_)
103+
* Changed: :py:`Value.matches()` with no patterns is :py:`Const(0)` instead of :py:`Const(1)`. (`RFC 39`_)
104+
* Changed: :py:`Signal(range(stop), init=stop)` warning has been changed into a hard error and made to trigger on any out-of range value.
105+
* Changed: :py:`Signal(range(0))` is now valid without a warning.
106+
* Changed: :py:`Shape.cast(range(1))` is now :py:`unsigned(0)`. (`RFC 46`_)
107+
* Changed: the :py:`reset=` argument of :class:`Signal`, :meth:`Signal.like`, :class:`amaranth.lib.wiring.Member`, :class:`amaranth.lib.cdc.FFSynchronizer`, and :py:`m.FSM()` has been renamed to :py:`init=`. (`RFC 43`_)
103108
* Changed: :class:`Shape` has been made immutable and hashable.
104109
* Changed: :class:`Assert`, :class:`Assume`, :class:`Cover` have been moved to :mod:`amaranth.hdl` from :mod:`amaranth.asserts`. (`RFC 50`_)
105110
* Changed: :class:`Instance` IO ports now accept only IO values, not plain values. (`RFC 53`_)
@@ -127,17 +132,21 @@ Standard library changes
127132
* Added: :mod:`amaranth.lib.meta`, :class:`amaranth.lib.wiring.ComponentMetadata`. (`RFC 30`_)
128133
* Deprecated: :mod:`amaranth.lib.coding`. (`RFC 63`_)
129134
* Removed: (deprecated in 0.4) :mod:`amaranth.lib.scheduler`. (`RFC 19`_)
130-
* Removed: (deprecated in 0.4) :class:`amaranth.lib.fifo.FIFOInterface` with ``fwft=False``. (`RFC 20`_)
131-
* Removed: (deprecated in 0.4) :class:`amaranth.lib.fifo.SyncFIFO` with ``fwft=False``. (`RFC 20`_)
135+
* Removed: (deprecated in 0.4) :class:`amaranth.lib.fifo.FIFOInterface` with :py:`fwft=False`. (`RFC 20`_)
136+
* Removed: (deprecated in 0.4) :class:`amaranth.lib.fifo.SyncFIFO` with :py:`fwft=False`. (`RFC 20`_)
132137

133138

134139
Toolchain changes
135140
-----------------
136141

137-
* Added: ``Simulator.add_testbench``. (`RFC 27`_)
142+
* Added: :meth:`Simulator.add_testbench <amaranth.sim.Simulator.add_testbench>`. (`RFC 27`_)
143+
* Added: async function support in :meth:`Simulator.add_testbench <amaranth.sim.Simulator.add_testbench>` and :meth:`Simulator.add_process <amaranth.sim.Simulator.add_process>`. (`RFC 36`_)
138144
* Added: support for :class:`amaranth.hdl.Assert` in simulation. (`RFC 50`_)
139-
* Deprecated: ``Settle`` simulation command. (`RFC 27`_)
140-
* Deprecated: ``Simulator.add_sync_process``. (`RFC 27`_)
145+
* Changed: :meth:`Simulator.add_clock <amaranth.sim.Simulator.add_clock>` no longer implicitly adds :py:`period / 2` when :py:`phase` is specified, actually matching the documentation.
146+
* Changed: :meth:`Simulator.run_until <amaranth.sim.Simulator.run_until>` always runs the simulation until the given deadline, even when no critical processes or testbenches are present.
147+
* Deprecated: :py:`Settle` simulation command. (`RFC 27`_)
148+
* Deprecated: :py:`Simulator.add_sync_process`. (`RFC 27`_)
149+
* Deprecated: the :py:`run_passive` argument to :meth:`Simulator.run_until <amaranth.sim.Simulator.run_until>` has been deprecated, and does nothing.
141150
* Removed: (deprecated in 0.4) use of mixed-case toolchain environment variable names, such as ``NMIGEN_ENV_Diamond`` or ``AMARANTH_ENV_Diamond``; use upper-case environment variable names, such as ``AMARANTH_ENV_DIAMOND``.
142151

143152

@@ -150,7 +159,7 @@ Platform integration changes
150159
* Added: :meth:`BuildPlan.extract`.
151160
* Added: ``build.sh`` begins with ``#!/bin/sh``.
152161
* Changed: ``IntelPlatform`` renamed to ``AlteraPlatform``.
153-
* Deprecated: argument ``run_script=`` in :meth:`BuildPlan.execute_local`.
162+
* Deprecated: argument :py:`run_script=` in :meth:`BuildPlan.execute_local`.
154163
* Removed: (deprecated in 0.4) :mod:`vendor.intel`, :mod:`vendor.lattice_ecp5`, :mod:`vendor.lattice_ice40`, :mod:`vendor.lattice_machxo2_3l`, :mod:`vendor.quicklogic`, :mod:`vendor.xilinx`. (`RFC 18`_)
155164

156165

docs/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
autodoc_preserve_defaults = True
4040
autodoc_inherit_docstrings = False
4141

42+
# Amaranth mostly does not include typehints, and showing them in some places but not others is
43+
# worse than not showing them at all.
44+
autodoc_typehints = "none"
45+
4246
napoleon_google_docstring = False
4347
napoleon_numpy_docstring = True
4448
napoleon_use_ivar = True

docs/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Language & toolchain
1515
guide
1616
reference
1717
stdlib
18+
simulator
1819
platform
1920
changes
2021
contrib

docs/install.rst

+9-12
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Amaranth HDL requires Python 3.8; it works on CPython_ 3.8 (or newer), and works
2727

2828
For most workflows, Amaranth requires Yosys_ |yosys-version|. A `compatible version of Yosys <amaranth-yosys_>`_ is distributed via PyPI_ for most popular platforms, so it is usually not necessary to install Yosys separately.
2929

30-
Simulating Amaranth code requires no additional software. However, a waveform viewer like GTKWave_ is invaluable for debugging. As an alternative to GTKWave, the `Amaranth Playground`_ can be used to display waveforms for simple designs.
30+
Simulating Amaranth code requires no additional software. However, a waveform viewer like Surfer_ or GTKWave_ is invaluable for debugging. As an alternative, the `Amaranth Playground`_ can be used to display waveforms for simple designs.
3131

3232
Synthesizing, placing and routing an Amaranth design for an FPGA requires the FPGA family specific toolchain. The open source iCE40, ECP5, MachXO2/3, Nexus, and Gowin toolchains are distributed via PyPI_ for most popular platforms by the YoWASP_ project.
3333

@@ -39,6 +39,7 @@ Synthesizing, placing and routing an Amaranth design for an FPGA requires the FP
3939
.. _Yosys: https://yosyshq.net/yosys/
4040
.. _amaranth-yosys: https://pypi.org/project/amaranth-yosys/
4141
.. _PyPI: https://pypi.org/
42+
.. _Surfer: https://surfer-project.org/
4243
.. _GTKWave: https://gtkwave.sourceforge.net/
4344
.. _YoWASP: https://yowasp.org/
4445

@@ -58,10 +59,6 @@ Installing prerequisites
5859

5960
:ref:`Install Python <python:using-on-windows>`, either from Windows Store or using the full installer. If using the full installer, make sure to install a 64-bit version of Python.
6061

61-
`Download GTKWave`_, either win32 or win64 binaries. GTKWave does not need to be installed; it can be unpacked to any convenient location and run from there.
62-
63-
.. _Download GTKWave: https://sourceforge.net/projects/gtkwave/files/
64-
6562
|upgrade-pip|
6663

6764
.. code-block:: doscon
@@ -71,11 +68,11 @@ Installing prerequisites
7168
.. platform-choice:: macos
7269
:title: macOS
7370

74-
Install Homebrew_. Then, install Python and GTKWave by running:
71+
Install Homebrew_. Then, install Python by running:
7572

7673
.. code-block:: console
7774
78-
$ brew install python gtkwave
75+
$ brew install python
7976
8077
.. _Homebrew: https://brew.sh
8178

@@ -89,11 +86,11 @@ Installing prerequisites
8986
:altname: linux
9087
:title: Debian
9188

92-
Install Python and GTKWave by running:
89+
Install Python by running:
9390

9491
.. code-block:: console
9592
96-
$ sudo apt-get install python3-pip gtkwave
93+
$ sudo apt-get install python3-pip
9794
9895
On architectures other than |builtin-yosys-architectures|, install Yosys by running:
9996

@@ -113,16 +110,16 @@ Installing prerequisites
113110
:altname: linux
114111
:title: Arch Linux
115112

116-
Install Python, pip, GTKWave and Yosys by running:
113+
Install Python and pip by running:
117114

118115
.. code-block:: console
119116
120-
$ sudo pacman -S python python-pip gtkwave yosys
117+
$ sudo pacman -S python python-pip
121118
122119
.. platform-choice:: linux
123120
:title: Other Linux
124121

125-
Install Python and GTKWave from the package repository of your distribution.
122+
Install Python from the package repository of your distribution.
126123

127124
On architectures other than |builtin-yosys-architectures|, install Yosys from the package repository of your distribution.
128125

0 commit comments

Comments
 (0)