From: whitequark Date: Fri, 14 Dec 2018 12:42:39 +0000 (+0000) Subject: back.pysim: more general clean-up. X-Git-Tag: working~270 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dd00b5e2d6774adb23d41e5b95a9f87ec8b42bd3;p=nmigen.git back.pysim: more general clean-up. --- diff --git a/examples/clkdiv.py b/examples/clkdiv.py index 1eae421..ce49eae 100644 --- a/examples/clkdiv.py +++ b/examples/clkdiv.py @@ -20,6 +20,7 @@ frag = ctr.get_fragment(platform=None) # print(rtlil.convert(frag, ports=[ctr.o])) print(verilog.convert(frag, ports=[ctr.o])) -sim = pysim.Simulator(frag, vcd_file=open("clkdiv.vcd", "w")) -sim.add_clock("sync", 1e-6) -with sim: sim.run_until(100e-6, run_passive=True) +with pysim.Simulator(frag, + vcd_file=open("clkdiv.vcd", "w")) as sim: + sim.add_clock(1e-6) + sim.run_until(100e-6, run_passive=True) diff --git a/examples/ctrl.py b/examples/ctrl.py index f88e917..b2d352d 100644 --- a/examples/ctrl.py +++ b/examples/ctrl.py @@ -21,17 +21,17 @@ frag = ctr.get_fragment(platform=None) # print(rtlil.convert(frag, ports=[ctr.o, ctr.ce])) print(verilog.convert(frag, ports=[ctr.o, ctr.ce])) -sim = pysim.Simulator(frag, - vcd_file=open("ctrl.vcd", "w"), - gtkw_file=open("ctrl.gtkw", "w"), - gtkw_signals=[ctr.ce, ctr.v, ctr.o]) -sim.add_clock("sync", 1e-6) -def ce_proc(): - yield; yield; yield - yield ctr.ce.eq(1) - yield; yield; yield - yield ctr.ce.eq(0) - yield; yield; yield - yield ctr.ce.eq(1) -sim.add_sync_process(ce_proc()) -with sim: sim.run_until(100e-6, run_passive=True) +with pysim.Simulator(frag, + vcd_file=open("ctrl.vcd", "w"), + gtkw_file=open("ctrl.gtkw", "w"), + gtkw_signals=[ctr.ce, ctr.v, ctr.o]) as sim: + sim.add_clock(1e-6) + def ce_proc(): + yield; yield; yield + yield ctr.ce.eq(1) + yield; yield; yield + yield ctr.ce.eq(0) + yield; yield; yield + yield ctr.ce.eq(1) + sim.add_sync_process(ce_proc()) + sim.run_until(100e-6, run_passive=True) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index b2b42fc..8867581 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -190,7 +190,7 @@ class _StatementCompiler(StatementTransformer): class Simulator: def __init__(self, fragment, vcd_file=None, gtkw_file=None, gtkw_signals=()): - self._fragments = {} # fragment -> hierarchy + self._fragment = fragment self._domains = {} # str/domain -> ClockDomain self._domain_triggers = ValueDict() # Signal -> str/domain @@ -223,25 +223,10 @@ class Simulator: self._gtkw_file = gtkw_file self._gtkw_signals = gtkw_signals - fragment = fragment.prepare() - - def add_fragment(fragment, hierarchy=("top",)): - self._fragments[fragment] = hierarchy - for subfragment, name in fragment.subfragments: - add_fragment(subfragment, (*hierarchy, name)) - add_fragment(fragment) - - self._domains = fragment.domains - for domain, cd in self._domains.items(): - self._domain_triggers[cd.clk] = domain - if cd.rst is not None: - self._domain_triggers[cd.rst] = domain - self._domain_signals[domain] = ValueSet() - def add_process(self, process): self._processes.add(process) - def add_clock(self, domain, period): + def add_clock(self, period, domain="sync"): if self._fastest_clock == self._epsilon or period < self._fastest_clock: self._fastest_clock = period @@ -272,7 +257,23 @@ class Simulator: self._vcd_writer = VCDWriter(self._vcd_file, timescale="100 ps", comment="Generated by nMigen") - for fragment in self._fragments: + root_fragment = self._fragment.prepare() + + self._domains = root_fragment.domains + for domain, cd in self._domains.items(): + self._domain_triggers[cd.clk] = domain + if cd.rst is not None: + self._domain_triggers[cd.rst] = domain + self._domain_signals[domain] = ValueSet() + + fragment_names = {} + def add_fragment(fragment, hierarchy=("top",)): + fragment_names[fragment] = hierarchy + for subfragment, name in fragment.subfragments: + add_fragment(subfragment, (*hierarchy, name)) + add_fragment(root_fragment) + + for fragment, fragment_name in fragment_names.items(): for signal in fragment.iter_signals(): self._signals.add(signal) @@ -307,11 +308,10 @@ class Simulator: else: var_name_suffix = "{}${}".format(var_name, suffix) self._vcd_signals[signal].add(self._vcd_writer.register_var( - scope=".".join(self._fragments[fragment]), name=var_name_suffix, + scope=".".join(fragment_name), name=var_name_suffix, var_type=var_type, size=var_size, init=var_init)) if signal not in self._vcd_names: - self._vcd_names[signal] = \ - ".".join(self._fragments[fragment] + (var_name_suffix,)) + self._vcd_names[signal] = ".".join(fragment_name + (var_name_suffix,)) break except KeyError: suffix = (suffix or 0) + 1 @@ -344,6 +344,8 @@ class Simulator: self._user_signals = self._signals - self._comb_signals - self._sync_signals + return self + def _update_dirty_signals(self): """Perform the statement part of IR processes (aka RTLIL case).""" # First, for all dirty signals, use sensitivity lists to determine the set of fragments @@ -502,6 +504,10 @@ class Simulator: # No processes, or all processes are passive. Nothing to do! return False + def run(self): + while self.step(): + pass + def run_until(self, deadline, run_passive=False): while self._timestamp < deadline: if not self.step(run_passive):