Skip to content

Commit

Permalink
back.pysim: wake up processes before ever committing any values.
Browse files Browse the repository at this point in the history
Otherwise, the contract of the simulator to sync processes is not
always fulfilled.
  • Loading branch information
whitequark committed Jan 21, 2019
1 parent 52a9f81 commit 12e04e4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 8 deletions.
14 changes: 7 additions & 7 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,13 +638,6 @@ def _commit_sync_signals(self, domains):
while curr_domains:
domain = curr_domains.pop()

# Take the computed value (at the start of this delta cycle) of every sync signal
# in this domain and update the value for this delta cycle. This can trigger more
# synchronous logic, so record that.
for signal_slot in self._state.iter_next_dirty():
if self._domain_signals[domain][signal_slot]:
self._commit_signal(signal_slot, domains)

# Wake up any simulator processes that wait for a domain tick.
for process, wait_domain in list(self._wait_tick.items()):
if domain == wait_domain:
Expand All @@ -658,6 +651,13 @@ def _commit_sync_signals(self, domains):
# values from the previous clock cycle on a tick, too.
self._run_process(process)

# Take the computed value (at the start of this delta cycle) of every sync signal
# in this domain and update the value for this delta cycle. This can trigger more
# synchronous logic, so record that.
for signal_slot in self._state.iter_next_dirty():
if self._domain_signals[domain][signal_slot]:
self._commit_signal(signal_slot, domains)

# Unless handling synchronous logic above has triggered more synchronous logic (which
# can happen e.g. if a domain is clocked off a clock divisor in fabric), we're done.
# Otherwise, do one more round of updates.
Expand Down
10 changes: 9 additions & 1 deletion nmigen/test/test_sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ def process():
self.assertEqual((yield self.count), 4)
self.assertEqual((yield self.sync.clk), 0)
yield
self.assertEqual((yield self.count), 4)
self.assertEqual((yield self.sync.clk), 1)
yield
self.assertEqual((yield self.count), 5)
self.assertEqual((yield self.sync.clk), 1)
for _ in range(3):
Expand Down Expand Up @@ -317,12 +320,15 @@ def process():
yield self.b.eq(1)
yield
self.assertEqual((yield self.x), 4)
yield
self.assertEqual((yield self.o), 6)
yield self.s.eq(1)
yield
yield
self.assertEqual((yield self.o), 4)
yield self.s.eq(2)
yield
yield
self.assertEqual((yield self.o), 0)
sim.add_sync_process(process)

Expand Down Expand Up @@ -487,9 +493,11 @@ def process():
yield self.wrport.en.eq(1)
yield self.rdport.en.eq(1)
yield
self.assertEqual((yield self.rdport.data), 0x00)
yield
self.assertEqual((yield self.rdport.data), 0xaa)
yield Delay(1e-6) # let comb propagate
self.assertEqual((yield self.rdport.data), 0xaa)
self.assertEqual((yield self.rdport.data), 0x33)
sim.add_clock(1e-6)
sim.add_sync_process(process)

Expand Down

0 comments on commit 12e04e4

Please sign in to comment.