From 19e91faad053f9fa24090ca9fde3923553d1c0fb Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 21 Aug 2019 03:28:48 +0000 Subject: [PATCH] back.pysim: allow coroutines as processes. This is a somewhat obscure use case, but it is possible to use async functions with pysim by carefully using @asyncio.coroutine. That is, async functions can call back into pysim if they are declared in a specific way: @asyncio.coroutine def do_something(self, value): yield self.reg.eq(value) which may then be called from elsewhere with: async def test_case(self): await do_something(0x1234) This approach is unfortunately limited in that async functions cannot yield directly. It should likely be improved by using async generators, but supporting coroutines in pysim is unobtrustive and allows existing code that made use of this feature in oMigen to work. --- nmigen/back/pysim.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index a89556f..25189d7 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -402,7 +402,7 @@ class Simulator: def _check_process(process): if inspect.isgeneratorfunction(process): process = process() - if not inspect.isgenerator(process): + if not (inspect.isgenerator(process) or inspect.iscoroutine(process)): raise TypeError("Cannot add a process '{!r}' because it is not a generator or " "a generator function" .format(process)) @@ -412,7 +412,10 @@ class Simulator: if process in self._process_loc: return self._process_loc[process] else: - frame = process.gi_frame + if inspect.isgenerator(process): + frame = process.gi_frame + if inspect.iscoroutine(process): + frame = process.cr_frame return "{}:{}".format(inspect.getfile(frame), inspect.getlineno(frame)) def add_process(self, process): -- 2.30.2