hdl.xfrm: lower resets in DomainLowerer as well.
authorwhitequark <whitequark@whitequark.org>
Mon, 19 Aug 2019 21:32:48 +0000 (21:32 +0000)
committerwhitequark <whitequark@whitequark.org>
Mon, 19 Aug 2019 21:44:30 +0000 (21:44 +0000)
Changed in preparation for introducing local clock domains.

Also makes elaboration about 15% faster.

nmigen/hdl/ir.py
nmigen/hdl/xfrm.py
nmigen/test/test_hdl_xfrm.py

index 79e308affd52c7c2c17974253e1d873ee9320d03..c21bc82647f40488bc28018864f8fcb05ddc16b2 100644 (file)
@@ -386,12 +386,6 @@ class Fragment:
         self._propagate_domains_down()
         return new_domains
 
-    def _insert_domain_resets(self):
-        from .xfrm import ResetInserter
-
-        resets = {cd.name: cd.rst for cd in self.domains.values() if cd.rst is not None}
-        return ResetInserter(resets)(self)
-
     def _lower_domain_signals(self):
         from .xfrm import DomainLowerer
 
@@ -543,7 +537,6 @@ class Fragment:
         fragment = SampleLowerer()(self)
         new_domains = fragment._propagate_domains(missing_domain)
         fragment._resolve_hierarchy_conflicts()
-        fragment = fragment._insert_domain_resets()
         fragment = fragment._lower_domain_signals()
         if ports is None:
             fragment._propagate_ports(ports=(), all_undef_as_ports=True)
index 2fdf707e2dc9ea50c932396c1e326d45e6722929..d143b41cc1ad0eff136b8e4e5ab1ee8488fb40d1 100644 (file)
@@ -488,22 +488,34 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
         return not isinstance(value, (ClockSignal, ResetSignal))
 
     def on_ClockSignal(self, value):
-        cd = self._resolve(value.domain, value)
-        return cd.clk
+        domain = self._resolve(value.domain, value)
+        return domain.clk
 
     def on_ResetSignal(self, value):
-        cd = self._resolve(value.domain, value)
-        if cd.rst is None:
+        domain = self._resolve(value.domain, value)
+        if domain.rst is None:
             if value.allow_reset_less:
                 return Const(0)
             else:
                 raise DomainError("Signal {!r} refers to reset of reset-less domain '{}'"
                                   .format(value, value.domain))
-        return cd.rst
+        return domain.rst
+
+    def _insert_resets(self, fragment):
+        for domain_name, signals in fragment.drivers.items():
+            if domain_name is None:
+                continue
+            domain = fragment.domains[domain_name]
+            if domain.rst is None:
+                continue
+            stmts = [signal.eq(Const(signal.reset, signal.nbits))
+                     for signal in signals if not signal.reset_less]
+            fragment.add_statements(Switch(domain.rst, {1: stmts}))
 
     def on_fragment(self, fragment):
         self.domains = fragment.domains
         new_fragment = super().on_fragment(fragment)
+        self._insert_resets(new_fragment)
         return new_fragment
 
 
index 1a2a6c83b7f8de409d5b2413d5717a27c9c8b1bc..d67dc6fe8f206ec05e31f427149584f420fd9bbb 100644 (file)
@@ -150,9 +150,10 @@ class DomainLowererTestCase(FHDLTestCase):
         """)
 
     def test_lower_drivers(self):
+        sync = ClockDomain()
         pix = ClockDomain()
         f = Fragment()
-        f.add_domains(pix)
+        f.add_domains(sync, pix)
         f.add_driver(ClockSignal("pix"), None)
         f.add_driver(ResetSignal("pix"), "sync")
 
@@ -597,6 +598,7 @@ class UserValueTestCase(FHDLTestCase):
     def test_lower(self):
         sync = ClockDomain()
         f = Fragment()
+        f.add_domains(sync)
         f.add_statements(
             self.uv.eq(1)
         )
@@ -611,5 +613,8 @@ class UserValueTestCase(FHDLTestCase):
             (switch (sig c)
                 (case 1 (eq (sig s) (const 1'd0)))
             )
+            (switch (sig rst)
+                (case 1 (eq (sig s) (const 1'd0)))
+            )
         )
         """)