Add 'passive' simulation functions that are not taken into account while determining when to stop the simulator

This commit is contained in:
Sebastien Bourdeauducq 2014-01-27 23:58:46 +01:00
parent 63c1d7e4b7
commit 90f0dfad63
5 changed files with 60 additions and 43 deletions

View File

@ -260,6 +260,7 @@ class _ReqFIFO(Module):
else: else:
selfp.bank.req_ack = 0 selfp.bank.req_ack = 0
selfp.bank.lock = bool(self.contents) selfp.bank.lock = bool(self.contents)
do_simulation.passive = True
class Target(Module): class Target(Module):
def __init__(self, model, *ifargs, **ifkwargs): def __init__(self, model, *ifargs, **ifkwargs):
@ -305,3 +306,4 @@ class Target(Module):
if done_wr_transaction is not None: if done_wr_transaction is not None:
self.model.write(done_wr_transaction[0], done_wr_transaction[1], self.model.write(done_wr_transaction[0], done_wr_transaction[1],
selfp.bus.dat_w, selfp.bus.dat_we) selfp.bus.dat_w, selfp.bus.dat_we)
do_simulation.passive = True

View File

@ -212,6 +212,7 @@ class Tap(Module):
transaction = TRead(selfp.bus.adr, transaction = TRead(selfp.bus.adr,
selfp.bus.dat_r) selfp.bus.dat_r)
self.handler(transaction) self.handler(transaction)
do_simulation.passive = True
class Initiator(Module): class Initiator(Module):
def __init__(self, generator, bus=None): def __init__(self, generator, bus=None):
@ -277,6 +278,7 @@ class Target(Module):
bus.ack = 1 bus.ack = 1
else: else:
bus.ack = 0 bus.ack = 0
do_simulation.passive = True
class SRAM(Module): class SRAM(Module):
def __init__(self, mem_or_size, read_only=None, init=None, bus=None): def __init__(self, mem_or_size, read_only=None, init=None, bus=None):

View File

@ -5,7 +5,7 @@ from migen.util.misc import flat_iteration
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.structure import _Fragment from migen.fhdl.structure import _Fragment
from migen.fhdl.tools import rename_clock_domain 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): class FinalizeError(Exception):
pass pass
@ -115,11 +115,9 @@ class Module:
except AttributeError: except AttributeError:
pass pass
else: else:
gs = GenSim(simg) simf = gen_sim(simg)
simf = gs.do_simulation
if simf is not None: if simf is not None:
ps = ProxySim(self, simf) simf = proxy_sim(self, simf)
simf = ps.do_simulation
sim = [] if simf is None else [simf] sim = [] if simf is None else [simf]
self._fragment = _Fragment(sim=sim) self._fragment = _Fragment(sim=sim)
return self._fragment return self._fragment

View File

@ -72,16 +72,6 @@ end
r += "\nendmodule" r += "\nendmodule"
return r 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: class Simulator:
def __init__(self, fragment, top_level=None, sim_runner=None, sockaddr="simsocket", **vopts): def __init__(self, fragment, top_level=None, sim_runner=None, sockaddr="simsocket", **vopts):
if not isinstance(fragment, _Fragment): if not isinstance(fragment, _Fragment):
@ -89,15 +79,15 @@ class Simulator:
if top_level is None: if top_level is None:
top_level = TopLevel() top_level = TopLevel()
if sim_runner is None: if sim_runner is None:
sim_runner = icarus.Runner() sim_runner = icarus.Runner()
self.fragment = fragment + _Fragment(clock_domains=top_level.clock_domains)
self.top_level = top_level self.top_level = top_level
self.ipc = Initiator(sockaddr) self.ipc = Initiator(sockaddr)
self.sim_runner = sim_runner self.sim_runner = sim_runner
c_top = self.top_level.get(sockaddr) 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, ios=self.top_level.ios,
name=self.top_level.dut_type, name=self.top_level.dut_type,
return_ns=True, return_ns=True,
@ -110,16 +100,31 @@ class Simulator:
self.ipc.accept() self.ipc.accept()
reply = self.ipc.recv() reply = self.ipc.recv()
assert(isinstance(reply, MessageTick)) 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): def run(self, ncycles=None):
counter = 0 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 self.cycle_counter += 1
counter += 1 counter += 1
self.ipc.send(MessageGo()) self.ipc.send(MessageGo())
reply = self.ipc.recv() reply = self.ipc.recv()
assert(isinstance(reply, MessageTick)) 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): def rd(self, item, index=0):
name = self.top_level.top_name + "." \ name = self.top_level.top_name + "." \

View File

@ -52,48 +52,58 @@ class Proxy:
assert(isinstance(item, Signal)) assert(isinstance(item, Signal))
self.simulator.wr(item, value) self.simulator.wr(item, value)
class GenSim: def gen_sim(simg):
def __init__(self, simg): gens = dict()
self.simg = simg resume_cycle = 0
self.gens = dict()
self.resume_cycle = 0 def do_simulation(s):
nonlocal resume_cycle, gens
def do_simulation(self, s):
if isinstance(s, Proxy): if isinstance(s, Proxy):
simulator = s.simulator simulator = s.simulator
else: else:
simulator = s simulator = s
if simulator.cycle_counter >= self.resume_cycle: if simulator.cycle_counter >= resume_cycle:
try: try:
gen = self.gens[simulator] gen = gens[simulator]
except KeyError: except KeyError:
gen = self.simg(s) gen = simg(s)
self.gens[simulator] = gen gens[simulator] = gen
try: try:
n = next(gen) n = next(gen)
except StopIteration: except StopIteration:
del self.gens[simulator] del gens[simulator]
raise StopSimulation raise StopSimulation
else: else:
if n is None: if n is None:
n = 1 n = 1
self.resume_cycle = simulator.cycle_counter + n resume_cycle = simulator.cycle_counter + n
class ProxySim: if hasattr(simg, "passive"):
def __init__(self, target, simf): do_simulation.passive = simg.passive
self.target = target
self.simf = simf return do_simulation
self.proxies = dict()
def proxy_sim(target, simf):
proxies = dict()
def do_simulation(simulator):
nonlocal proxies
def do_simulation(self, simulator):
try: try:
proxy = self.proxies[simulator] proxy = proxies[simulator]
except KeyError: except KeyError:
proxy = Proxy(simulator, self.target) proxy = Proxy(simulator, target)
self.proxies[simulator] = proxy proxies[simulator] = proxy
try: try:
self.simf(proxy) simf(proxy)
except StopSimulation: except StopSimulation:
del self.proxies[simulator] del proxies[simulator]
raise raise
if hasattr(simf, "passive"):
do_simulation.passive = simf.passive
return do_simulation