From 1e02fc2bcb7ea03d3acb0ced591b38204ded1f6e Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 21 Jan 2019 16:00:25 +0000 Subject: [PATCH] back.pysim: wake up processes before ever committing any values. Otherwise, the contract of the simulator to sync processes is not always fulfilled. --- nmigen/back/pysim.py | 14 +++++++------- nmigen/test/test_sim.py | 10 +++++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index bea24b4..a19905d 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -638,13 +638,6 @@ class Simulator: 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: @@ -658,6 +651,13 @@ class Simulator: # 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. diff --git a/nmigen/test/test_sim.py b/nmigen/test/test_sim.py index f063246..d1f769e 100644 --- a/nmigen/test/test_sim.py +++ b/nmigen/test/test_sim.py @@ -282,6 +282,9 @@ class SimulatorIntegrationTestCase(FHDLTestCase): 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): @@ -317,12 +320,15 @@ class SimulatorIntegrationTestCase(FHDLTestCase): 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) @@ -487,9 +493,11 @@ class SimulatorIntegrationTestCase(FHDLTestCase): 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) -- 2.30.2