back.pysim: allow processes to evaluate expressions.
authorwhitequark <cz@m-labs.hk>
Fri, 14 Dec 2018 13:21:58 +0000 (13:21 +0000)
committerwhitequark <cz@m-labs.hk>
Fri, 14 Dec 2018 13:32:30 +0000 (13:32 +0000)
nmigen/back/pysim.py
nmigen/fhdl/ast.py

index 88675818e0c3bd4eafd92b7e5f3130da24d08bbc..18318b980e18bdf85f944b8d12d3a3ffb5e31310 100644 (file)
@@ -421,46 +421,58 @@ class Simulator:
 
     def _run_process(self, process):
         try:
-            stmt = process.send(None)
+            cmd = process.send(None)
+            while True:
+                if isinstance(cmd, Delay):
+                    if cmd.interval is None:
+                        interval = self._epsilon
+                    else:
+                        interval = cmd.interval
+                    self._wait_deadline[process] = self._timestamp + interval
+                    self._suspended.add(process)
+
+                elif isinstance(cmd, Tick):
+                    self._wait_tick[process] = cmd.domain
+                    self._suspended.add(process)
+
+                elif isinstance(cmd, Passive):
+                    self._passive.add(process)
+
+                elif isinstance(cmd, Value):
+                    funclet = _RHSValueCompiler(sensitivity=ValueSet())(cmd)
+                    cmd = process.send(funclet(self._state))
+                    continue
+
+                elif isinstance(cmd, Assign):
+                    lhs_signals = cmd.lhs._lhs_signals()
+                    for signal in lhs_signals:
+                        if not signal in self._signals:
+                            raise ValueError("Process {!r} sent a request to set signal '{!r}', "
+                                             "which is not a part of simulation"
+                                             .format(process, signal))
+                        if signal in self._comb_signals:
+                            raise ValueError("Process {!r} sent a request to set signal '{!r}', "
+                                             "which is a part of combinatorial assignment in "
+                                             "simulation"
+                                             .format(process, signal))
+
+                    funclet = _StatementCompiler()(cmd)
+                    funclet(self._state)
+
+                    domains = set()
+                    for signal in lhs_signals:
+                        self._commit_signal(signal, domains)
+                    self._commit_sync_signals(domains)
+
+                else:
+                    raise TypeError("Received unsupported command '{!r}' from process {!r}"
+                                    .format(cmd, process))
+
+                break
+
         except StopIteration:
             self._processes.remove(process)
             self._passive.discard(process)
-            return
-
-        if isinstance(stmt, Delay):
-            self._wait_deadline[process] = self._timestamp + stmt.interval
-            self._suspended.add(process)
-
-        elif isinstance(stmt, Tick):
-            self._wait_tick[process] = stmt.domain
-            self._suspended.add(process)
-
-        elif isinstance(stmt, Passive):
-            self._passive.add(process)
-
-        elif isinstance(stmt, Assign):
-            lhs_signals = stmt.lhs._lhs_signals()
-            for signal in lhs_signals:
-                if not signal in self._signals:
-                    raise ValueError("Process {!r} sent a request to set signal '{!r}', "
-                                     "which is not a part of simulation"
-                                     .format(process, signal))
-                if signal in self._comb_signals:
-                    raise ValueError("Process {!r} sent a request to set signal '{!r}', "
-                                     "which is a part of combinatorial assignment in simulation"
-                                     .format(process, signal))
-
-            funclet = _StatementCompiler()(stmt)
-            funclet(self._state)
-
-            domains = set()
-            for signal in lhs_signals:
-                self._commit_signal(signal, domains)
-            self._commit_sync_signals(domains)
-
-        else:
-            raise TypeError("Received unsupported statement '{!r}' from process {!r}"
-                            .format(stmt, process))
 
     def step(self, run_passive=False):
         deadline = None
index 027f70032eae9fa50f9bcd4fc543bd9d99edef7a..f97a0c913ad01d29b46bb8b21ae7da9569414d8e 100644 (file)
@@ -702,14 +702,17 @@ class Switch(Statement):
 
 
 class Delay(Statement):
-    def __init__(self, interval):
-        self.interval = float(interval)
+    def __init__(self, interval=None):
+        self.interval = None if interval is None else float(interval)
 
     def _rhs_signals(self):
         return ValueSet()
 
     def __repr__(self):
-        return "(delay {:.3}us)".format(self.interval * 10e6)
+        if self.interval is None:
+            return "(delay ε)"
+        else:
+            return "(delay {:.3}us)".format(self.interval * 10e6)
 
 
 class Tick(Statement):