diff --git a/migen/bus/lasmibus.py b/migen/bus/lasmibus.py index d907581b6..481d2a8bf 100644 --- a/migen/bus/lasmibus.py +++ b/migen/bus/lasmibus.py @@ -260,6 +260,7 @@ class _ReqFIFO(Module): else: selfp.bank.req_ack = 0 selfp.bank.lock = bool(self.contents) + do_simulation.passive = True class Target(Module): def __init__(self, model, *ifargs, **ifkwargs): @@ -305,3 +306,4 @@ class Target(Module): if done_wr_transaction is not None: self.model.write(done_wr_transaction[0], done_wr_transaction[1], selfp.bus.dat_w, selfp.bus.dat_we) + do_simulation.passive = True diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py index e2f95c40b..b09137efb 100644 --- a/migen/bus/wishbone.py +++ b/migen/bus/wishbone.py @@ -212,6 +212,7 @@ class Tap(Module): transaction = TRead(selfp.bus.adr, selfp.bus.dat_r) self.handler(transaction) + do_simulation.passive = True class Initiator(Module): def __init__(self, generator, bus=None): @@ -277,6 +278,7 @@ class Target(Module): bus.ack = 1 else: bus.ack = 0 + do_simulation.passive = True class SRAM(Module): def __init__(self, mem_or_size, read_only=None, init=None, bus=None): diff --git a/migen/fhdl/module.py b/migen/fhdl/module.py index eb236a943..1d97dd41b 100644 --- a/migen/fhdl/module.py +++ b/migen/fhdl/module.py @@ -5,7 +5,7 @@ from migen.util.misc import flat_iteration from migen.fhdl.structure import * from migen.fhdl.structure import _Fragment from migen.fhdl.tools import rename_clock_domain -from migen.sim.upper import GenSim, ProxySim +from migen.sim.upper import gen_sim, proxy_sim class FinalizeError(Exception): pass @@ -115,11 +115,9 @@ class Module: except AttributeError: pass else: - gs = GenSim(simg) - simf = gs.do_simulation + simf = gen_sim(simg) if simf is not None: - ps = ProxySim(self, simf) - simf = ps.do_simulation + simf = proxy_sim(self, simf) sim = [] if simf is None else [simf] self._fragment = _Fragment(sim=sim) return self._fragment diff --git a/migen/sim/generic.py b/migen/sim/generic.py index 02017e380..c06d12653 100644 --- a/migen/sim/generic.py +++ b/migen/sim/generic.py @@ -72,16 +72,6 @@ end r += "\nendmodule" return r -def _call_sim(fragment, simulator): - del_list = [] - for s in fragment.sim: - try: - s(simulator) - except StopSimulation: - del_list.append(s) - for s in del_list: - fragment.sim.remove(s) - class Simulator: def __init__(self, fragment, top_level=None, sim_runner=None, sockaddr="simsocket", **vopts): if not isinstance(fragment, _Fragment): @@ -89,15 +79,15 @@ class Simulator: if top_level is None: top_level = TopLevel() if sim_runner is None: - sim_runner = icarus.Runner() - self.fragment = fragment + _Fragment(clock_domains=top_level.clock_domains) + sim_runner = icarus.Runner() self.top_level = top_level self.ipc = Initiator(sockaddr) self.sim_runner = sim_runner c_top = self.top_level.get(sockaddr) - c_fragment, self.namespace = verilog.convert(self.fragment, + fragment = fragment + _Fragment(clock_domains=top_level.clock_domains) + c_fragment, self.namespace = verilog.convert(fragment, ios=self.top_level.ios, name=self.top_level.dut_type, return_ns=True, @@ -110,16 +100,31 @@ class Simulator: self.ipc.accept() reply = self.ipc.recv() assert(isinstance(reply, MessageTick)) + + self.sim_functions = fragment.sim + self.active_sim_functions = set(f for f in fragment.sim if not hasattr(f, "passive") or not f.passive) def run(self, ncycles=None): counter = 0 - while self.fragment.sim and (ncycles is None or counter < ncycles): + while self.active_sim_functions and (ncycles is None or counter < ncycles): self.cycle_counter += 1 counter += 1 self.ipc.send(MessageGo()) reply = self.ipc.recv() assert(isinstance(reply, MessageTick)) - _call_sim(self.fragment, self) + + del_list = [] + for s in self.sim_functions: + try: + s(self) + except StopSimulation: + del_list.append(s) + for s in del_list: + self.sim_functions.remove(s) + try: + self.active_sim_functions.remove(s) + except KeyError: + pass def rd(self, item, index=0): name = self.top_level.top_name + "." \ diff --git a/migen/sim/upper.py b/migen/sim/upper.py index 34b3e1415..b681a4a46 100644 --- a/migen/sim/upper.py +++ b/migen/sim/upper.py @@ -52,48 +52,58 @@ class Proxy: assert(isinstance(item, Signal)) self.simulator.wr(item, value) -class GenSim: - def __init__(self, simg): - self.simg = simg - self.gens = dict() - self.resume_cycle = 0 +def gen_sim(simg): + gens = dict() + resume_cycle = 0 + + def do_simulation(s): + nonlocal resume_cycle, gens - def do_simulation(self, s): if isinstance(s, Proxy): simulator = s.simulator else: simulator = s - if simulator.cycle_counter >= self.resume_cycle: + if simulator.cycle_counter >= resume_cycle: try: - gen = self.gens[simulator] + gen = gens[simulator] except KeyError: - gen = self.simg(s) - self.gens[simulator] = gen + gen = simg(s) + gens[simulator] = gen try: n = next(gen) except StopIteration: - del self.gens[simulator] + del gens[simulator] raise StopSimulation else: if n is None: n = 1 - self.resume_cycle = simulator.cycle_counter + n + resume_cycle = simulator.cycle_counter + n -class ProxySim: - def __init__(self, target, simf): - self.target = target - self.simf = simf - self.proxies = dict() + if hasattr(simg, "passive"): + do_simulation.passive = simg.passive + + return do_simulation + + +def proxy_sim(target, simf): + proxies = dict() + + def do_simulation(simulator): + nonlocal proxies - def do_simulation(self, simulator): try: - proxy = self.proxies[simulator] + proxy = proxies[simulator] except KeyError: - proxy = Proxy(simulator, self.target) - self.proxies[simulator] = proxy + proxy = Proxy(simulator, target) + proxies[simulator] = proxy try: - self.simf(proxy) + simf(proxy) except StopSimulation: - del self.proxies[simulator] + del proxies[simulator] raise + + if hasattr(simf, "passive"): + do_simulation.passive = simf.passive + + return do_simulation