4 from ..hdl
.ast
import Statement
, SignalSet
5 from .core
import Tick
, Settle
, Delay
, Passive
, Active
6 from ._base
import BaseProcess
7 from ._pyrtl
import _ValueCompiler
, _RHSValueCompiler
, _StatementCompiler
10 __all__
= ["PyCoroProcess"]
13 class PyCoroProcess(BaseProcess
):
14 def __init__(self
, state
, domains
, constructor
, *, default_cmd
=None):
16 self
.domains
= domains
17 self
.constructor
= constructor
18 self
.default_cmd
= default_cmd
26 self
.coroutine
= self
.constructor()
28 "slots": self
.state
.slots
,
30 **_ValueCompiler
.helpers
32 self
.waits_on
= SignalSet()
35 coroutine
= self
.coroutine
38 while coroutine
.gi_yieldfrom
is not None and inspect
.isgenerator(coroutine
.gi_yieldfrom
):
39 coroutine
= coroutine
.gi_yieldfrom
40 if inspect
.isgenerator(coroutine
):
41 frame
= coroutine
.gi_frame
42 if inspect
.iscoroutine(coroutine
):
43 frame
= coroutine
.cr_frame
44 return "{}:{}".format(inspect
.getfile(frame
), inspect
.getlineno(frame
))
46 def add_trigger(self
, signal
, trigger
=None):
47 self
.state
.add_trigger(self
, signal
, trigger
=trigger
)
48 self
.waits_on
.add(signal
)
50 def clear_triggers(self
):
51 for signal
in self
.waits_on
:
52 self
.state
.remove_trigger(self
, signal
)
56 if self
.coroutine
is None:
64 command
= self
.coroutine
.send(response
)
66 command
= self
.default_cmd
69 if isinstance(command
, Value
):
70 exec(_RHSValueCompiler
.compile(self
.state
, command
, mode
="curr"),
72 response
= Const
.normalize(self
.exec_locals
["result"], command
.shape())
74 elif isinstance(command
, Statement
):
75 exec(_StatementCompiler
.compile(self
.state
, command
),
78 elif type(command
) is Tick
:
79 domain
= command
.domain
80 if isinstance(domain
, ClockDomain
):
82 elif domain
in self
.domains
:
83 domain
= self
.domains
[domain
]
85 raise NameError("Received command {!r} that refers to a nonexistent "
86 "domain {!r} from process {!r}"
87 .format(command
, command
.domain
, self
.src_loc()))
88 self
.add_trigger(domain
.clk
, trigger
=1 if domain
.clk_edge
== "pos" else 0)
89 if domain
.rst
is not None and domain
.async_reset
:
90 self
.add_trigger(domain
.rst
, trigger
=1)
93 elif type(command
) is Settle
:
94 self
.state
.wait_interval(self
, None)
97 elif type(command
) is Delay
:
98 self
.state
.wait_interval(self
, command
.interval
)
101 elif type(command
) is Passive
:
104 elif type(command
) is Active
:
107 elif command
is None: # only possible if self.default_cmd is None
108 raise TypeError("Received default command from process {!r} that was added "
109 "with add_process(); did you mean to add this process with "
110 "add_sync_process() instead?"
111 .format(self
.src_loc()))
114 raise TypeError("Received unsupported command {!r} from process {!r}"
115 .format(command
, self
.src_loc()))
117 except StopIteration:
119 self
.coroutine
= None
122 except Exception as exn
:
123 self
.coroutine
.throw(exn
)