hdl.dsl: add a diagnostic for `m.d.submodules += ...`.
authorwhitequark <whitequark@whitequark.org>
Sat, 28 Sep 2019 17:50:24 +0000 (17:50 +0000)
committerwhitequark <whitequark@whitequark.org>
Sat, 28 Sep 2019 17:50:24 +0000 (17:50 +0000)
nmigen/hdl/dsl.py
nmigen/test/test_hdl_dsl.py

index 8a3b561cc0b8d4e45f0052c71575986f407f49d8..6934ed394f554cfb71990ed05e309368fe706be5 100644 (file)
@@ -28,7 +28,7 @@ class _ModuleBuilderProxy:
         object.__setattr__(self, "_depth", depth)
 
 
-class _ModuleBuilderDomainExplicit(_ModuleBuilderProxy):
+class _ModuleBuilderDomain(_ModuleBuilderProxy):
     def __init__(self, builder, depth, domain):
         super().__init__(builder, depth)
         self._domain = domain
@@ -38,13 +38,18 @@ class _ModuleBuilderDomainExplicit(_ModuleBuilderProxy):
         return self
 
 
-class _ModuleBuilderDomainImplicit(_ModuleBuilderProxy):
+class _ModuleBuilderDomains(_ModuleBuilderProxy):
     def __getattr__(self, name):
+        if name == "submodules":
+            warnings.warn("Using '<module>.d.{}' would add statements to clock domain {!r}; "
+                          "did you mean <module>.{} instead?"
+                          .format(name, name, name),
+                          SyntaxWarning, stacklevel=2)
         if name == "comb":
             domain = None
         else:
             domain = name
-        return _ModuleBuilderDomainExplicit(self._builder, self._depth, domain)
+        return _ModuleBuilderDomain(self._builder, self._depth, domain)
 
     def __getitem__(self, name):
         return self.__getattr__(name)
@@ -52,7 +57,7 @@ class _ModuleBuilderDomainImplicit(_ModuleBuilderProxy):
     def __setattr__(self, name, value):
         if name == "_depth":
             object.__setattr__(self, name, value)
-        elif not isinstance(value, _ModuleBuilderDomainExplicit):
+        elif not isinstance(value, _ModuleBuilderDomain):
             raise AttributeError("Cannot assign 'd.{}' attribute; did you mean 'd.{} +='?"
                                  .format(name, name))
 
@@ -63,7 +68,7 @@ class _ModuleBuilderDomainImplicit(_ModuleBuilderProxy):
 class _ModuleBuilderRoot:
     def __init__(self, builder, depth):
         self._builder = builder
-        self.domain = self.d = _ModuleBuilderDomainImplicit(builder, depth)
+        self.domain = self.d = _ModuleBuilderDomains(builder, depth)
 
     def __getattr__(self, name):
         if name in ("comb", "sync"):
index c3355cdd9350f0d1103e4d6f3fb194aaee4a06d3..08bcc4cd7f096214be3031861ce4dc6e72560b34 100644 (file)
@@ -96,6 +96,13 @@ class DSLTestCase(FHDLTestCase):
                 msg="'Module' object has no attribute 'nonexistentattr'"):
             m.nonexistentattr
 
+    def test_d_suspicious(self):
+        m = Module()
+        with self.assertWarns(SyntaxWarning,
+                msg="Using '<module>.d.submodules' would add statements to clock domain "
+                    "'submodules'; did you mean <module>.submodules instead?"):
+            m.d.submodules += []
+
     def test_clock_signal(self):
         m = Module()
         m.d.comb += ClockSignal("pix").eq(ClockSignal())