amaranth/tests
Catherine 0cb71f8c57 sim: only preempt testbenches on explicit wait.
Before this commit, testbenches (generators added with `add_testbench`)
were not only preemptible after any `yield`, but were *guaranteed* to
be preempted by another testbench after *every* yield. This is evil:
if you have any race condition between testbenches, which is common,
this scheduling strategy will maximize the resulting nondeterminism by
interleaving your testbench with every other one as much as possible.
This behavior is an outcome of the way `add_testbench` is implemented,
which is by yielding `Settle()` after every command.

One can observe that:
- `yield value_like` should never preempt;
- `yield assignable.eq()` in `add_process()` should not preempt, since
  it only sets a `next` signal state, or appends to `write_queue` of
  a memory state, and never wakes up processes;
- `yield assignable.eq()` in `add_testbench()` should only preempt if
  changing `assignable` wakes up an RTL process. (It could potentially
  also preempt if that wakes up another testbench, but this has no
  benefit and requires `sim.set()` from RFC 36 to be awaitable, which
  is not desirable.)

After this commit, `PySimEngine._step()` is implemented with two nested
loops instead of one. The outer loop iterates through every testbench
and runs it until an explicit wait point (`Settle()`, `Delay()`, or
`Tick()`), terminating when no testbenches are runnable. The inner loop
is the usual eval/commit loop, running whenever a testbench changes
design state.

`PySimEngine._processes` is a `set`, which doesn't have a deterministic
iteration order. This does not matter for processes, where determinism
is guaranteed by the eval/commit loop, but causes racy testbenches to
pass or fail nondeterministically (in practice depending on the memory
layout of the Python process). While it is best to not have races in
the testbenches, this commit makes `PySimEngine._testbenches` a `list`,
making the outcome of a race deterministic, and enabling a hacky work-
around to make them work: reordering calls to `add_testbench()`.

A potential future improvement is a simulation mode that, instead,
randomizes the scheduling of testbenches, exposing race conditions
early.
2024-03-24 11:53:18 +00:00
..
__init__.py tests: move out of the main package. 2020-08-27 00:33:31 +00:00
test_build_dsl.py Pyupgrade to 3.8+. NFCI 2023-11-14 13:07:21 +00:00
test_build_plat.py Rename nMigen to Amaranth HDL. 2021-12-10 10:34:13 +00:00
test_build_res.py Implement RFC 53: Low-level I/O primitives. 2024-03-18 20:33:22 +00:00
test_examples.py tests: move out of the main package. 2020-08-27 00:33:31 +00:00
test_hdl_ast.py Implement RFC 51: Add ShapeCastable.from_bits and amaranth.lib.data.Const. 2024-03-19 04:01:26 +00:00
test_hdl_cd.py amaranth.hdl: start all private names with an underscore. 2024-01-30 17:20:45 +00:00
test_hdl_dsl.py Implement RFC 50: Print and string formatting. 2024-03-11 09:42:43 +00:00
test_hdl_ir.py hdl._ir: Remove support for non-Elaboratable elaboratables. 2024-03-20 08:20:23 +00:00
test_hdl_mem.py Implement RFC 45: Move hdl.Memory to lib.Memory. 2024-02-19 22:24:58 +00:00
test_hdl_rec.py hdl._ast: Make AST nodes immutable. 2024-02-29 18:56:46 +00:00
test_hdl_xfrm.py hdl._xfrm: Simplify EnableInserter logic. 2024-03-03 18:38:20 +00:00
test_lib_cdc.py Implement RFC 43: Rename reset= to init=. 2024-02-15 22:52:24 +00:00
test_lib_coding.py Implement RFC 50: Print and string formatting. 2024-03-11 09:42:43 +00:00
test_lib_crc.py Implement RFC 27 amendment: deprecate add_sync_process, not add_process. 2024-02-12 18:26:48 +00:00
test_lib_data.py Implement RFC 51: Add ShapeCastable.from_bits and amaranth.lib.data.Const. 2024-03-19 04:01:26 +00:00
test_lib_enum.py Implement RFC 51: Add ShapeCastable.from_bits and amaranth.lib.data.Const. 2024-03-19 04:01:26 +00:00
test_lib_fifo.py Implement RFC 50: Print and string formatting. 2024-03-11 09:42:43 +00:00
test_lib_io.py lib.io: Implement *Buffer from RFC 55. 2024-03-22 01:44:25 +00:00
test_lib_memory.py lib.memory: Memory.{r,w}_ports.{read,write}_ports. 2024-03-22 23:05:42 +00:00
test_lib_wiring.py lib.wiring: remove unnecessary flipping in Signature.flatten. 2024-03-15 10:35:50 +00:00
test_sim.py sim: only preempt testbenches on explicit wait. 2024-03-24 11:53:18 +00:00
test_tracer.py amaranth.hdl: start all private names with an underscore. 2024-01-30 17:20:45 +00:00
test_utils.py utils: F-strings are missing the letter "f" 2024-03-13 14:56:27 +00:00
utils.py tests: stop using implicit ports. 2024-02-12 13:24:54 +00:00