Implement RFC 27: Testbench processes for the simulator.

Co-authored-by: Wanda <wanda@phinode.net>
This commit is contained in:
Catherine 2020-10-20 01:54:24 +00:00
parent f48b8650c4
commit 9e75962c35
7 changed files with 279 additions and 143 deletions

View file

@ -15,6 +15,12 @@ class Command:
class Settle(Command):
@deprecated("The `Settle` command is deprecated per RFC 27. Use `add_testbench` to write "
"testbenches; in them, an equivalent of `yield Settle()` is performed "
"automatically.")
def __init__(self):
pass
def __repr__(self):
return "(settle)"
@ -74,11 +80,12 @@ class Simulator:
.format(process))
return process
@deprecated("The `add_process` method is deprecated per RFC 27. Use `add_testbench` instead.")
def add_process(self, process):
process = self._check_process(process)
def wrapper():
# Only start a bench process after comb settling, so that the reset values are correct.
yield Settle()
yield object.__new__(Settle)
yield from process()
self._engine.add_coroutine_process(wrapper, default_cmd=None)
@ -87,10 +94,74 @@ class Simulator:
def wrapper():
# Only start a sync process after the first clock edge (or reset edge, if the domain
# uses an asynchronous reset). This matches the behavior of synchronous FFs.
generator = process()
result = None
exception = None
yield Tick(domain)
yield from process()
while True:
try:
if exception is None:
command = generator.send(result)
else:
command = generator.throw(exception)
except StopIteration:
break
try:
if isinstance(command, (Settle, Delay, Tick)):
frame = generator.gi_frame
module_globals = frame.f_globals
if '__name__' in module_globals:
module = module_globals['__name__']
else:
module = "<string>"
# If the warning action is "error", this call will throw the warning, and
# the try block will redirect it into the generator.
warnings.warn_explicit(
f"Using `{command.__class__.__name__}` is deprecated within "
f"`add_sync_process` per RFC 27; use `add_testbench` instead.",
DeprecationWarning,
filename=frame.f_code.co_filename,
lineno=frame.f_lineno,
module=module,
registry=module_globals.setdefault("__warningregistry__", {}),
module_globals=module_globals,
)
result = yield command
exception = None
except Exception as e:
result = None
exception = e
self._engine.add_coroutine_process(wrapper, default_cmd=Tick(domain))
def add_testbench(self, process):
process = self._check_process(process)
def wrapper():
generator = process()
# Only start a bench process after power-on reset finishes. Use object.__new__ to
# avoid deprecation warning.
yield object.__new__(Settle)
result = None
exception = None
while True:
try:
if exception is None:
command = generator.send(result)
else:
command = generator.throw(exception)
except StopIteration:
break
if command is None or isinstance(command, Settle):
exception = TypeError(f"Command {command!r} is not allowed in testbenches")
else:
try:
result = yield command
exception = None
yield object.__new__(Settle)
except Exception as e:
result = None
exception = e
self._engine.add_coroutine_process(wrapper, default_cmd=None)
def add_clock(self, period, *, phase=None, domain="sync", if_exists=False):
"""Add a clock process.

View file

@ -29,16 +29,21 @@ Apply the following changes to code written against Amaranth 0.4 to migrate it t
* Replace uses of ``Value.matches()`` with no patterns with ``Const(1)``
* Update uses of ``amaranth.utils.log2_int(need_pow2=False)`` to :func:`amaranth.utils.ceil_log2`
* Update uses of ``amaranth.utils.log2_int(need_pow2=True)`` to :func:`amaranth.utils.exact_log2`
* Update uses of ``Simulator.add_process`` to ``Simulator.add_testbench``
* Convert uses of ``Simulator.add_sync_process`` used as testbenches to ``Simulator.add_testbench``
* Convert uses of ``yield Tick()`` within remaining ``Simulator.add_sync_process`` to plain ``yield``
Implemented RFCs
----------------
.. _RFC 17: https://amaranth-lang.org/rfcs/0017-remove-log2-int.html
.. _RFC 27: https://amaranth-lang.org/rfcs/0027-simulator-testbenches.html
.. _RFC 39: https://amaranth-lang.org/rfcs/0039-empty-case.html
.. _RFC 46: https://amaranth-lang.org/rfcs/0046-shape-range-1.html
* `RFC 17`_: Remove ``log2_int``
* `RFC 27`_: Testbench processes for the simulator
* `RFC 39`_: Change semantics of no-argument ``m.Case()``
* `RFC 46`_: Change ``Shape.cast(range(1))`` to ``unsigned(0)``
@ -71,6 +76,14 @@ Standard library changes
* Removed: (deprecated in 0.4) :class:`amaranth.lib.fifo.SyncFIFO` with ``fwft=False``. (`RFC 20`_)
Toolchain changes
-----------------
* Added: ``Simulator.add_testbench``. (`RFC 27`_)
* Deprecated: ``Settle`` simulation command. (`RFC 27`_)
* Deprecated: ``Simulator.add_process``. (`RFC 27`_)
Platform integration changes
----------------------------

View file

@ -26,13 +26,13 @@ class FFSynchronizerTestCase(FHDLTestCase):
def process():
self.assertEqual((yield o), 0)
yield i.eq(1)
yield Tick()
yield
self.assertEqual((yield o), 0)
yield Tick()
yield
self.assertEqual((yield o), 0)
yield Tick()
yield
self.assertEqual((yield o), 1)
sim.add_process(process)
sim.add_sync_process(process)
sim.run()
def test_reset_value(self):
@ -45,13 +45,13 @@ class FFSynchronizerTestCase(FHDLTestCase):
def process():
self.assertEqual((yield o), 1)
yield i.eq(0)
yield Tick()
yield
self.assertEqual((yield o), 1)
yield Tick()
yield
self.assertEqual((yield o), 1)
yield Tick()
yield
self.assertEqual((yield o), 0)
sim.add_process(process)
sim.add_sync_process(process)
sim.run()
@ -90,28 +90,27 @@ class AsyncFFSynchronizerTestCase(FHDLTestCase):
# initial reset
self.assertEqual((yield i), 0)
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
yield i.eq(1)
yield Delay(1e-8)
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 1)
yield i.eq(0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
sim.add_process(process)
yield Tick()
sim.add_testbench(process)
with sim.write_vcd("test.vcd"):
sim.run()
@ -128,28 +127,27 @@ class AsyncFFSynchronizerTestCase(FHDLTestCase):
# initial reset
self.assertEqual((yield i), 1)
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
yield i.eq(0)
yield Delay(1e-8)
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 1)
yield i.eq(1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield o), 0)
yield Tick(); yield Delay(1e-8)
sim.add_process(process)
yield Tick()
sim.add_testbench(process)
with sim.write_vcd("test.vcd"):
sim.run()
@ -176,28 +174,28 @@ class ResetSynchronizerTestCase(FHDLTestCase):
def process():
# initial reset
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
yield arst.eq(1)
yield Delay(1e-8)
self.assertEqual((yield s), 0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 1)
yield arst.eq(0)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
yield Tick()
self.assertEqual((yield s), 0)
yield Tick(); yield Delay(1e-8)
sim.add_process(process)
yield Tick()
sim.add_testbench(process)
with sim.write_vcd("test.vcd"):
sim.run()
@ -223,17 +221,17 @@ class PulseSynchronizerTestCase(FHDLTestCase):
yield ps.i.eq(0)
# TODO: think about reset
for n in range(5):
yield Tick()
yield
# Make sure no pulses are generated in quiescent state
for n in range(3):
yield Tick()
yield
self.assertEqual((yield ps.o), 0)
# Check conservation of pulses
accum = 0
for n in range(10):
yield ps.i.eq(1 if n < 4 else 0)
yield Tick()
yield
accum += yield ps.o
self.assertEqual(accum, 4)
sim.add_process(process)
sim.add_sync_process(process)
sim.run()

View file

@ -14,22 +14,19 @@ class EncoderTestCase(FHDLTestCase):
self.assertEqual((yield enc.o), 0)
yield enc.i.eq(0b0001)
yield Settle()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 0)
yield enc.i.eq(0b0100)
yield Settle()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 2)
yield enc.i.eq(0b0110)
yield Settle()
self.assertEqual((yield enc.n), 1)
self.assertEqual((yield enc.o), 0)
sim = Simulator(enc)
sim.add_process(process)
sim.add_testbench(process)
sim.run()
@ -41,22 +38,19 @@ class PriorityEncoderTestCase(FHDLTestCase):
self.assertEqual((yield enc.o), 0)
yield enc.i.eq(0b0001)
yield Settle()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 0)
yield enc.i.eq(0b0100)
yield Settle()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 2)
yield enc.i.eq(0b0110)
yield Settle()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 1)
sim = Simulator(enc)
sim.add_process(process)
sim.add_testbench(process)
sim.run()
@ -67,19 +61,16 @@ class DecoderTestCase(FHDLTestCase):
self.assertEqual((yield dec.o), 0b0001)
yield dec.i.eq(1)
yield Settle()
self.assertEqual((yield dec.o), 0b0010)
yield dec.i.eq(3)
yield Settle()
self.assertEqual((yield dec.o), 0b1000)
yield dec.n.eq(1)
yield Settle()
self.assertEqual((yield dec.o), 0b0000)
sim = Simulator(dec)
sim.add_process(process)
sim.add_testbench(process)
sim.run()

View file

@ -870,7 +870,7 @@ class RFCExamplesTestCase(TestCase):
def simulate(m):
def wrapper(fn):
sim = Simulator(m)
sim.add_process(fn)
sim.add_testbench(fn)
sim.run()
return wrapper

View file

@ -315,10 +315,10 @@ class AsyncFIFOSimCase(FHDLTestCase):
for i in range(fill_in):
yield fifo.w_data.eq(i)
yield fifo.w_en.eq(1)
yield Tick("write")
yield
yield fifo.w_en.eq(0)
yield Tick("write")
yield Tick("write")
yield
yield
self.assertEqual((yield fifo.w_level), expected_level)
yield write_done.eq(1)
@ -326,7 +326,7 @@ class AsyncFIFOSimCase(FHDLTestCase):
if read:
yield fifo.r_en.eq(1)
while not (yield write_done):
yield Tick("read")
yield
self.assertEqual((yield fifo.r_level), expected_level)
simulator = Simulator(fifo)

View file

@ -35,9 +35,8 @@ class SimulatorUnitTestCase(FHDLTestCase):
def process():
for isig, input in zip(isigs, inputs):
yield isig.eq(input)
yield Settle()
self.assertEqual((yield osig), output.value)
sim.add_process(process)
sim.add_testbench(process)
with sim.write_vcd("test.vcd", "test.gtkw", traces=[*isigs, osig]):
sim.run()
@ -436,28 +435,29 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
def test_counter_process(self):
self.setUp_counter()
with self.assertSimulation(self.m) as sim:
def process():
self.assertEqual((yield self.count), 4)
yield Delay(1e-6)
self.assertEqual((yield self.count), 4)
yield self.sync.clk.eq(1)
self.assertEqual((yield self.count), 4)
yield Settle()
self.assertEqual((yield self.count), 5)
yield Delay(1e-6)
self.assertEqual((yield self.count), 5)
yield self.sync.clk.eq(0)
self.assertEqual((yield self.count), 5)
yield Settle()
self.assertEqual((yield self.count), 5)
for _ in range(3):
with _ignore_deprecated():
with self.assertSimulation(self.m) as sim:
def process():
self.assertEqual((yield self.count), 4)
yield Delay(1e-6)
self.assertEqual((yield self.count), 4)
yield self.sync.clk.eq(1)
self.assertEqual((yield self.count), 4)
yield Settle()
self.assertEqual((yield self.count), 5)
yield Delay(1e-6)
self.assertEqual((yield self.count), 5)
yield self.sync.clk.eq(0)
self.assertEqual((yield self.count), 0)
sim.add_process(process)
self.assertEqual((yield self.count), 5)
yield Settle()
self.assertEqual((yield self.count), 5)
for _ in range(3):
yield Delay(1e-6)
yield self.sync.clk.eq(1)
yield Delay(1e-6)
yield self.sync.clk.eq(0)
self.assertEqual((yield self.count), 0)
sim.add_process(process)
def test_counter_clock_and_sync_process(self):
self.setUp_counter()
@ -611,10 +611,9 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
def process():
yield self.i.eq(0b10101010)
yield self.i[:4].eq(-1)
yield Settle()
self.assertEqual((yield self.i[:4]), 0b1111)
self.assertEqual((yield self.i), 0b10101111)
sim.add_process(process)
sim.add_testbench(process)
def test_run_until(self):
m = Module()
@ -626,7 +625,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
for _ in range(101):
yield Delay(1e-6)
self.fail()
sim.add_process(process)
sim.add_testbench(process)
def test_run_until_fail(self):
m = Module()
@ -639,13 +638,13 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
for _ in range(99):
yield Delay(1e-6)
self.fail()
sim.add_process(process)
sim.add_testbench(process)
def test_add_process_wrong(self):
with self.assertSimulation(Module()) as sim:
with self.assertRaisesRegex(TypeError,
r"^Cannot add a process 1 because it is not a generator function$"):
sim.add_process(1)
sim.add_sync_process(1)
def test_add_process_wrong_generator(self):
with self.assertSimulation(Module()) as sim:
@ -653,7 +652,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
r"^Cannot add a process <.+?> because it is not a generator function$"):
def process():
yield Delay()
sim.add_process(process())
sim.add_sync_process(process())
def test_add_clock_wrong_twice(self):
m = Module()
@ -679,14 +678,47 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
def test_command_wrong(self):
survived = False
with self.assertSimulation(Module()) as sim:
with _ignore_deprecated():
with self.assertSimulation(Module()) as sim:
def process():
nonlocal survived
with self.assertRaisesRegex(TypeError,
r"Received unsupported command 1 from process .+?"):
yield 1
survived = True
sim.add_process(process)
self.assertTrue(survived)
def test_sync_command_deprecated(self):
survived = False
m = Module()
dummy = Signal()
m.d.sync += dummy.eq(1)
with self.assertSimulation(m) as sim:
def process():
nonlocal survived
with self.assertWarnsRegex(DeprecationWarning,
r"Using `Delay` is deprecated within `add_sync_process`"):
yield Delay(1e-8)
survived = True
sim.add_sync_process(process)
sim.add_clock(1e-6)
self.assertTrue(survived)
def test_sync_command_wrong(self):
survived = False
m = Module()
dummy = Signal()
m.d.sync += dummy.eq(1)
with self.assertSimulation(m) as sim:
def process():
nonlocal survived
with self.assertRaisesRegex(TypeError,
r"Received unsupported command 1 from process .+?"):
yield 1
survived = True
sim.add_process(process)
sim.add_sync_process(process)
sim.add_clock(1e-6)
self.assertTrue(survived)
def test_value_castable(self):
@ -701,13 +733,19 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
a = Array([1,2,3])
a[MyValue()]
def test_bench_command_wrong(self):
survived = False
with self.assertSimulation(Module()) as sim:
def process():
nonlocal survived
yield MyValue()
with self.assertWarnsRegex(DeprecationWarning,
r"The `Settle` command is deprecated"):
settle = Settle()
with self.assertRaisesRegex(TypeError,
r"Command \(settle\) is not allowed in testbenches"):
yield settle
survived = True
sim.add_process(process)
sim.add_testbench(process)
self.assertTrue(survived)
def setUp_memory(self, rd_synchronous=True, rd_transparent=True, wr_granularity=None):
@ -755,23 +793,23 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
def process():
yield self.wrport.data.eq(0x50)
yield self.wrport.en.eq(0b00)
yield
yield Tick()
yield self.wrport.en.eq(0)
yield
yield Tick()
self.assertEqual((yield self.rdport.data), 0xaa)
yield self.wrport.en.eq(0b10)
yield
yield Tick()
yield self.wrport.en.eq(0)
yield
yield Tick()
self.assertEqual((yield self.rdport.data), 0x5a)
yield self.wrport.data.eq(0x33)
yield self.wrport.en.eq(0b01)
yield
yield Tick()
yield self.wrport.en.eq(0)
yield
yield Tick()
self.assertEqual((yield self.rdport.data), 0x53)
sim.add_clock(1e-6)
sim.add_sync_process(process)
sim.add_testbench(process)
def test_memory_read_before_write(self):
self.setUp_memory(rd_transparent=False)
@ -779,52 +817,46 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
def process():
yield self.wrport.data.eq(0x33)
yield self.wrport.en.eq(1)
yield
yield Tick()
self.assertEqual((yield self.rdport.data), 0xaa)
yield
self.assertEqual((yield self.rdport.data), 0xaa)
yield Settle()
yield Tick()
self.assertEqual((yield self.rdport.data), 0x33)
sim.add_clock(1e-6)
sim.add_sync_process(process)
sim.add_testbench(process)
def test_memory_write_through(self):
self.setUp_memory(rd_transparent=True)
with self.assertSimulation(self.m) as sim:
def process():
yield Tick()
yield self.wrport.data.eq(0x33)
yield self.wrport.en.eq(1)
yield
self.assertEqual((yield self.rdport.data), 0xaa)
yield Settle()
yield Tick()
self.assertEqual((yield self.rdport.data), 0x33)
yield
yield Tick()
yield self.rdport.addr.eq(1)
yield Settle()
self.assertEqual((yield self.rdport.data), 0x33)
sim.add_clock(1e-6)
sim.add_sync_process(process)
sim.add_testbench(process)
def test_memory_async_read_write(self):
self.setUp_memory(rd_synchronous=False)
with self.assertSimulation(self.m) as sim:
def process():
yield self.rdport.addr.eq(0)
yield Settle()
self.assertEqual((yield self.rdport.data), 0xaa)
yield self.rdport.addr.eq(1)
yield Settle()
self.assertEqual((yield self.rdport.data), 0x55)
yield self.rdport.addr.eq(0)
yield self.wrport.addr.eq(0)
yield self.wrport.data.eq(0x33)
yield self.wrport.en.eq(1)
yield Tick("sync")
self.assertEqual((yield self.rdport.data), 0xaa)
yield Settle()
yield Tick("sync")
self.assertEqual((yield self.rdport.data), 0x33)
sim.add_clock(1e-6)
sim.add_process(process)
sim.add_testbench(process)
def test_memory_read_only(self):
self.m = Module()
@ -841,6 +873,49 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
sim.add_clock(1e-6)
sim.add_sync_process(process)
def test_comb_bench_process(self):
m = Module()
a = Signal(reset=1)
b = Signal()
m.d.comb += b.eq(a)
with self.assertSimulation(m) as sim:
def process():
self.assertEqual((yield a), 1)
self.assertEqual((yield b), 1)
yield a.eq(0)
self.assertEqual((yield a), 0)
self.assertEqual((yield b), 0)
sim.add_testbench(process)
def test_sync_bench_process(self):
m = Module()
a = Signal(reset=1)
b = Signal()
m.d.sync += b.eq(a)
t = Signal()
m.d.sync += t.eq(~t)
with self.assertSimulation(m) as sim:
def process():
self.assertEqual((yield a), 1)
self.assertEqual((yield b), 0)
self.assertEqual((yield t), 0)
yield Tick()
self.assertEqual((yield a), 1)
self.assertEqual((yield b), 1)
self.assertEqual((yield t), 1)
yield Tick()
self.assertEqual((yield a), 1)
self.assertEqual((yield b), 1)
self.assertEqual((yield t), 0)
yield a.eq(0)
self.assertEqual((yield a), 0)
self.assertEqual((yield b), 1)
yield Tick()
self.assertEqual((yield a), 0)
self.assertEqual((yield b), 0)
sim.add_clock(1e-6)
sim.add_testbench(process)
def test_memory_transparency_simple(self):
m = Module()
init = [0x11, 0x22, 0x33, 0x44]
@ -850,41 +925,35 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
with self.assertSimulation(m) as sim:
def process():
yield rdport.addr.eq(0)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x11)
yield rdport.addr.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22)
yield wrport.addr.eq(0)
yield wrport.data.eq(0x44444444)
yield wrport.en.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22)
yield wrport.addr.eq(1)
yield wrport.data.eq(0x55)
yield wrport.en.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x55)
yield wrport.addr.eq(1)
yield wrport.data.eq(0x66)
yield wrport.en.eq(1)
yield rdport.en.eq(0)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x55)
yield wrport.addr.eq(2)
yield wrport.data.eq(0x77)
yield wrport.en.eq(1)
yield rdport.en.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x66)
sim.add_clock(1e-6)
sim.add_sync_process(process)
sim.add_testbench(process)
def test_memory_transparency_multibit(self):
m = Module()
@ -895,41 +964,35 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
with self.assertSimulation(m) as sim:
def process():
yield rdport.addr.eq(0)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x11111111)
yield rdport.addr.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22222222)
yield wrport.addr.eq(0)
yield wrport.data.eq(0x44444444)
yield wrport.en.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22222222)
yield wrport.addr.eq(1)
yield wrport.data.eq(0x55555555)
yield wrport.en.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22222255)
yield wrport.addr.eq(1)
yield wrport.data.eq(0x66666666)
yield wrport.en.eq(2)
yield rdport.en.eq(0)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22222255)
yield wrport.addr.eq(1)
yield wrport.data.eq(0x77777777)
yield wrport.en.eq(4)
yield rdport.en.eq(1)
yield
yield Settle()
yield Tick()
self.assertEqual((yield rdport.data), 0x22776655)
sim.add_clock(1e-6)
sim.add_sync_process(process)
sim.add_testbench(process)
def test_vcd_wrong_nonzero_time(self):
s = Signal()
@ -977,7 +1040,7 @@ class SimulatorRegressionTestCase(FHDLTestCase):
sim = Simulator(Module())
def process():
self.assertEqual((yield -(Const(0b11, 2).as_signed())), 1)
sim.add_process(process)
sim.add_testbench(process)
sim.run()
def test_bug_595(self):
@ -1018,5 +1081,5 @@ class SimulatorRegressionTestCase(FHDLTestCase):
self.assertEqual((yield C(0b0000, 4) | ~C(1, 1)), 0b0000)
self.assertEqual((yield C(0b1111, 4) & ~C(1, 1)), 0b0000)
self.assertEqual((yield C(0b1111, 4) ^ ~C(1, 1)), 0b1111)
sim.add_process(process)
sim.add_testbench(process)
sim.run()