back.pysim: more general clean-up.
authorwhitequark <cz@m-labs.hk>
Fri, 14 Dec 2018 12:42:39 +0000 (12:42 +0000)
committerwhitequark <cz@m-labs.hk>
Fri, 14 Dec 2018 12:46:04 +0000 (12:46 +0000)
examples/clkdiv.py
examples/ctrl.py
nmigen/back/pysim.py

index 1eae4215a2f81ee6319827b037e0eb72b79d22dc..ce49eae4dd31e27c3a52c66431b2b1ebf521bae8 100644 (file)
@@ -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)
index f88e917c46b84b4d2407b0b6512fdfe79fc0d0f4..b2d352d07493c404b068bc98c0334bd0c064ed11 100644 (file)
@@ -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)
index b2b42fc7f12a25977c4d73147fbf7f1213fee884..88675818e0c3bd4eafd92b7e5f3130da24d08bbc 100644 (file)
@@ -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):