Skip to content

Commit 3d2cd15

Browse files
wanda-phiwhitequark
authored andcommitted
sim: awaken all processes waiting on changed() at time 0.
1 parent f3bcdf4 commit 3d2cd15

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

amaranth/sim/_async.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,10 +749,18 @@ def reset(self):
749749
self.critical = not self.background
750750
self.waits_on = None
751751
self.coroutine = self.constructor(self.context)
752+
self.first_await = True
752753

753754
def run(self):
754755
try:
755756
self.waits_on = self.coroutine.send(None)
757+
# Special case to make combination logic replacement work correctly: ensure that
758+
# a process looping over `changed()` always gets awakened at least once at time 0,
759+
# to see the initial values.
760+
if self.first_await and self.waits_on.initial_eligible():
761+
self.waits_on.compute_result()
762+
self.waits_on = self.coroutine.send(None)
763+
self.first_await = False
756764
except StopIteration:
757765
self.critical = False
758766
self.waits_on = None

amaranth/sim/pysim.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ def activate(self):
555555
else:
556556
self._broken = True
557557

558-
def run(self):
558+
def compute_result(self):
559559
result = []
560560
for trigger in self._combination._triggers:
561561
if isinstance(trigger, (SampleTrigger, ChangedTrigger)):
@@ -570,12 +570,20 @@ def run(self):
570570
assert False # :nocov:
571571
self._result = tuple(result)
572572

573+
def run(self):
574+
self.compute_result()
573575
self._combination._process.runnable = True
574576
self._combination._process.waits_on = None
575577
self._triggers_hit.clear()
576578
for waker, interval_fs in self._delay_wakers.items():
577579
self._engine.state.set_delay_waker(interval_fs, waker)
578580

581+
def initial_eligible(self):
582+
return not self._oneshot and any(
583+
isinstance(trigger, ChangedTrigger)
584+
for trigger in self._combination._triggers
585+
)
586+
579587
def __await__(self):
580588
self._result = None
581589
if self._broken:

tests/test_sim.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,22 @@ def test_comb_clock_conflict(self):
15061506
r"^Clock signal is already driven by combinational logic$"):
15071507
sim.add_clock(1e-6)
15081508

1509+
def test_initial(self):
1510+
a = Signal(4, init=3)
1511+
m = Module()
1512+
sim = Simulator(m)
1513+
fired = 0
1514+
1515+
async def process(ctx):
1516+
nonlocal fired
1517+
async for val_a, in ctx.changed(a):
1518+
self.assertEqual(val_a, 3)
1519+
fired += 1
1520+
1521+
sim.add_process(process)
1522+
sim.run()
1523+
self.assertEqual(fired, 1)
1524+
15091525
def test_sample(self):
15101526
m = Module()
15111527
m.domains.sync = cd_sync = ClockDomain()

0 commit comments

Comments
 (0)