back.pysim: index domains by identity, not by name.
authorwhitequark <whitequark@whitequark.org>
Mon, 19 Aug 2019 21:29:53 +0000 (21:29 +0000)
committerwhitequark <whitequark@whitequark.org>
Mon, 19 Aug 2019 21:44:33 +0000 (21:44 +0000)
Changed in preparation for introducing local clock domains.

nmigen/back/pysim.py

index 93329c4c2480d07fbc9bcc9b03f33975cbec65db..445acf0babf1d993a33977bf607a7c26d0ea22b3 100644 (file)
@@ -381,14 +381,14 @@ class Simulator:
         self._signal_slots    = SignalDict()  # Signal -> int/slot
         self._slot_signals    = list()        # int/slot -> Signal
 
-        self._domains         = dict()        # str/domain -> ClockDomain
-        self._domain_triggers = list()        # int/slot -> str/domain
+        self._domains         = list()        # [ClockDomain]
+        self._domain_triggers = list()        # int/slot -> ClockDomain
 
         self._signals         = SignalSet()   # {Signal}
         self._comb_signals    = bitarray()    # {Signal}
         self._sync_signals    = bitarray()    # {Signal}
         self._user_signals    = bitarray()    # {Signal}
-        self._domain_signals  = dict()        # str/domain -> {Signal}
+        self._domain_signals  = dict()        # ClockDomain -> {Signal}
 
         self._started         = False
         self._timestamp       = 0.
@@ -463,7 +463,9 @@ class Simulator:
         half_period = period / 2
         if phase is None:
             phase = half_period
-        clk = self._domains[domain].clk
+        for domain_obj in self._domains:
+            if not domain_obj.local and domain_obj.name == domain:
+                clk = domain_obj.clk
         def clk_process():
             yield Passive()
             yield Delay(phase)
@@ -481,17 +483,19 @@ class Simulator:
                                          comment="Generated by nMigen")
 
         root_fragment = self._fragment.prepare()
-        self._domains = root_fragment.domains
 
         hierarchy = {}
+        domains = set()
         def add_fragment(fragment, scope=()):
             hierarchy[fragment] = scope
+            domains.update(fragment.domains.values())
             for index, (subfragment, name) in enumerate(fragment.subfragments):
                 if name is None:
                     add_fragment(subfragment, (*scope, "U{}".format(index)))
                 else:
                     add_fragment(subfragment, (*scope, name))
         add_fragment(root_fragment, scope=("top",))
+        self._domains = list(domains)
 
         def add_signal(signal):
             if signal not in self._signals:
@@ -526,10 +530,10 @@ class Simulator:
             for signal in fragment.iter_signals():
                 add_signal(signal)
 
-            for domain, cd in fragment.domains.items():
-                add_domain_signal(cd.clk, domain)
-                if cd.rst is not None:
-                    add_domain_signal(cd.rst, domain)
+            for domain_name, domain in fragment.domains.items():
+                add_domain_signal(domain.clk, domain)
+                if domain.rst is not None:
+                    add_domain_signal(domain.rst, domain)
 
         for fragment, fragment_scope in hierarchy.items():
             for signal in fragment.iter_signals():
@@ -571,31 +575,31 @@ class Simulator:
                     except KeyError:
                         suffix = (suffix or 0) + 1
 
-            for domain, signals in fragment.drivers.items():
+            for domain_name, signals in fragment.drivers.items():
                 signals_bits = bitarray(len(self._signals))
                 signals_bits.setall(False)
                 for signal in signals:
                     signals_bits[self._signal_slots[signal]] = True
 
-                if domain is None:
+                if domain_name is None:
                     self._comb_signals |= signals_bits
                 else:
                     self._sync_signals |= signals_bits
-                    self._domain_signals[domain] |= signals_bits
+                    self._domain_signals[fragment.domains[domain_name]] |= signals_bits
 
             statements = []
-            for domain, signals in fragment.drivers.items():
+            for domain_name, signals in fragment.drivers.items():
                 reset_stmts = []
                 hold_stmts  = []
                 for signal in signals:
                     reset_stmts.append(signal.eq(signal.reset))
                     hold_stmts .append(signal.eq(signal))
 
-                if domain is None:
+                if domain_name is None:
                     statements += reset_stmts
                 else:
-                    if self._domains[domain].async_reset:
-                        statements.append(Switch(self._domains[domain].rst,
+                    if fragment.domains[domain_name].async_reset:
+                        statements.append(Switch(fragment.domains[domain_name].rst,
                             {0: hold_stmts, 1: reset_stmts}))
                     else:
                         statements += hold_stmts
@@ -610,10 +614,10 @@ class Simulator:
 
             for signal in compiler.sensitivity:
                 add_funclet(signal, funclet)
-            for domain, cd in fragment.domains.items():
-                add_funclet(cd.clk, funclet)
-                if cd.rst is not None:
-                    add_funclet(cd.rst, funclet)
+            for domain in fragment.domains.values():
+                add_funclet(domain.clk, funclet)
+                if domain.rst is not None:
+                    add_funclet(domain.rst, funclet)
 
         self._user_signals = bitarray(len(self._signals))
         self._user_signals.setall(True)
@@ -670,7 +674,7 @@ class Simulator:
 
     def _commit_sync_signals(self, domains):
         """Perform the sync part of IR processes (aka RTLIL posedge)."""
-        # At entry, `domains` contains a list of every simultaneously triggered sync update.
+        # At entry, `domains` contains a set of every simultaneously triggered sync update.
         while domains:
             # Advance the timeline a bit (purely for observational purposes) and commit all of them
             # at the same timestamp.
@@ -681,8 +685,8 @@ class Simulator:
                 domain = curr_domains.pop()
 
                 # Wake up any simulator processes that wait for a domain tick.
-                for process, wait_domain in list(self._wait_tick.items()):
-                    if domain == wait_domain:
+                for process, wait_domain_name in list(self._wait_tick.items()):
+                    if domain.name == wait_domain_name:
                         del self._wait_tick[process]
                         self._suspended.remove(process)
 
@@ -860,11 +864,11 @@ class Simulator:
                         suffix = ""
                     gtkw_save.trace(self._vcd_names[signal_slot] + suffix, **kwargs)
 
-            for domain, cd in self._domains.items():
-                with gtkw_save.group("d.{}".format(domain)):
-                    if cd.rst is not None:
-                        add_trace(cd.rst)
-                    add_trace(cd.clk)
+            for domain in self._domains:
+                with gtkw_save.group("d.{}".format(domain.name)):
+                    if domain.rst is not None:
+                        add_trace(domain.rst)
+                    add_trace(domain.clk)
 
             for signal in self._traces:
                 add_trace(signal)