From 35a44f017f6660c3c429b63791298fd1c6f9ec95 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 26 Dec 2018 12:42:43 +0000 Subject: [PATCH] hdl.dsl: forbid m.next= inside of FSM but outside of FSM state, too. --- nmigen/hdl/dsl.py | 23 ++++++++++++----------- nmigen/test/test_hdl_dsl.py | 6 +++++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/nmigen/hdl/dsl.py b/nmigen/hdl/dsl.py index 6ed5c02..9144ad1 100644 --- a/nmigen/hdl/dsl.py +++ b/nmigen/hdl/dsl.py @@ -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() diff --git a/nmigen/test/test_hdl_dsl.py b/nmigen/test/test_hdl_dsl.py index 7087bc5..8b72410 100644 --- a/nmigen/test/test_hdl_dsl.py +++ b/nmigen/test/test_hdl_dsl.py @@ -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() -- 2.30.2