From: Lars-Peter Clausen Date: Tue, 12 Mar 2013 21:27:19 +0000 (+0100) Subject: Allow SimActors to produce/consume a constant stream of tokens X-Git-Tag: 24jan2021_ls180~2099^2~638^2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dea46749220fb78154b9cb3355b87275b4339707;p=litex.git Allow SimActors to produce/consume a constant stream of tokens Currently a SimActor requires one clock period to recover from consuming or producing a token. ack/stb are deasserted in the cycle where the token is consumed/produced and only re-asserted in the next cycle. This patch updates the code to keep the control signals asserted if the actor is able to produce or consume a token in the next cycle. The patch also sets 'initialize' attribute on the simulation method, this will make sure that the control and data signals will be ready right on the first clock cycle. Signed-off-by: Lars-Peter Clausen --- diff --git a/migen/actorlib/sim.py b/migen/actorlib/sim.py index de11f1c9..18a7bfc9 100644 --- a/migen/actorlib/sim.py +++ b/migen/actorlib/sim.py @@ -22,27 +22,31 @@ class TokenExchanger(PureSimulable): for token in self.active: ep = self.actor.endpoints[token.endpoint] if isinstance(ep, Sink): - if s.rd(ep.ack): - if s.rd(ep.stb): - token.value = s.multiread(ep.token) - completed.add(token) - s.wr(ep.ack, 0) - else: - s.wr(ep.ack, 1) + if s.rd(ep.ack) and s.rd(ep.stb): + token.value = s.multiread(ep.token) + completed.add(token) + s.wr(ep.ack, 0) elif isinstance(ep, Source): - if s.rd(ep.stb): - if s.rd(ep.ack): - completed.add(token) - s.wr(ep.stb, 0) - else: - s.wr(ep.stb, 1) - s.multiwrite(ep.token, token.value) + if s.rd(ep.ack) and s.rd(ep.stb): + completed.add(token) + s.wr(ep.stb, 0) else: raise TypeError self.active -= completed if not self.active: self.busy = True - + + def _update_control_signals(self, s): + for token in self.active: + ep = self.actor.endpoints[token.endpoint] + if isinstance(ep, Sink): + s.wr(ep.ack, 1) + elif isinstance(ep, Source): + s.multiwrite(ep.token, token.value) + s.wr(ep.stb, 1) + else: + raise TypeError + def _next_transactions(self): try: transactions = next(self.generator) @@ -62,13 +66,16 @@ class TokenExchanger(PureSimulable): raise TypeError if self.active and all(transaction.idle_wait for transaction in self.active): self.busy = False - + def do_simulation(self, s): if not self.done: - if not self.active: - self._next_transactions() if self.active: self._process_transactions(s) + if not self.active: + self._next_transactions() + self._update_control_signals(s) + + do_simulation.initialize = True class SimActor(Actor): def __init__(self, generator, *endpoint_descriptions, **misc):