From 3c8a02c700c73800a91af0b8bef2f9ea9955b3c3 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 14 Dec 2018 13:21:58 +0000 Subject: [PATCH] back.pysim: allow processes to evaluate expressions. --- nmigen/back/pysim.py | 86 +++++++++++++++++++++++++------------------- nmigen/fhdl/ast.py | 9 +++-- 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index 8867581..18318b9 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -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 diff --git a/nmigen/fhdl/ast.py b/nmigen/fhdl/ast.py index 027f700..f97a0c9 100644 --- a/nmigen/fhdl/ast.py +++ b/nmigen/fhdl/ast.py @@ -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): -- 2.30.2