Add 'passive' simulation functions that are not taken into account while determining when to stop the simulator
This commit is contained in:
parent
63c1d7e4b7
commit
90f0dfad63
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 + "." \
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue