back.pysim: wake up processes before ever committing any values.
authorwhitequark <whitequark@whitequark.org>
Mon, 21 Jan 2019 16:00:25 +0000 (16:00 +0000)
committerwhitequark <whitequark@whitequark.org>
Mon, 21 Jan 2019 16:00:25 +0000 (16:00 +0000)
Otherwise, the contract of the simulator to sync processes is not
always fulfilled.

nmigen/back/pysim.py
nmigen/test/test_sim.py

index bea24b4418f139e717cc8f79c57104f43f5fbcdc..a19905d757ccbbe28f9864437d81eedfbccf82d1 100644 (file)
@@ -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.
index f063246dcf6667d867c6292daa557b699372fe05..d1f769e58784e4d1a04848a196c416416e192005 100644 (file)
@@ -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)