hdl.dsl: forbid m.next= inside of FSM but outside of FSM state, too.
authorwhitequark <whitequark@whitequark.org>
Wed, 26 Dec 2018 12:42:43 +0000 (12:42 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 26 Dec 2018 12:42:43 +0000 (12:42 +0000)
nmigen/hdl/dsl.py
nmigen/test/test_hdl_dsl.py

index 6ed5c02f5f09c42ab3fc9db40928b070b2e5a870..9144ad1e14109943c6835539fb06bdde236497c7 100644 (file)
@@ -260,17 +260,18 @@ class Module(_ModuleBuilderRoot):
 
     @next.setter
     def next(self, name):
-        for ctrl_name, ctrl_data in reversed(self._ctrl_stack):
-            if ctrl_name == "FSM":
-                if name not in ctrl_data["encoding"]:
-                    ctrl_data["encoding"][name] = len(ctrl_data["encoding"])
-                self._add_statement(
-                    assigns=[ctrl_data["signal"].eq(ctrl_data["encoding"][name])],
-                    domain=ctrl_data["domain"],
-                    depth=len(self._ctrl_stack))
-                break
-        else:
-            raise SyntaxError("`m.next = <...>` is only permitted inside an FSM")
+        if self._ctrl_context != "FSM":
+            for level, (ctrl_name, ctrl_data) in enumerate(reversed(self._ctrl_stack)):
+                if ctrl_name == "FSM":
+                    if name not in ctrl_data["encoding"]:
+                        ctrl_data["encoding"][name] = len(ctrl_data["encoding"])
+                    self._add_statement(
+                        assigns=[ctrl_data["signal"].eq(ctrl_data["encoding"][name])],
+                        domain=ctrl_data["domain"],
+                        depth=len(self._ctrl_stack))
+                    return
+
+        raise SyntaxError("`m.next = <...>` is only permitted inside an FSM state")
 
     def _pop_ctrl(self):
         name, data = self._ctrl_stack.pop()
index 7087bc57ac4c1a8b8e0f417b07792b1c27ebb384..8b7241084348911a99da7ba0fd43054f84c63286 100644 (file)
@@ -392,8 +392,12 @@ class DSLTestCase(FHDLTestCase):
                 msg="Only assignment to `m.next` is permitted"):
             m.next
         with self.assertRaises(SyntaxError,
-                msg="`m.next = <...>` is only permitted inside an FSM"):
+                msg="`m.next = <...>` is only permitted inside an FSM state"):
             m.next = "FOO"
+        with self.assertRaises(SyntaxError,
+                msg="`m.next = <...>` is only permitted inside an FSM state"):
+            with m.FSM():
+                m.next = "FOO"
 
     def test_auto_pop_ctrl(self):
         m = Module()