Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: amaranth-lang/amaranth
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 97cc78a3db54
Choose a base ref
...
head repository: amaranth-lang/amaranth
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a1c58633e644
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Feb 6, 2020

  1. hdl.dsl: make referencing undefined FSM states an error.

    Before this commit, doing something like:
    
        with m.FSM():
            with m.State("FOO"):
                m.next = "bAR"
            with m.State("BAR"):
                m.next = "FOO"
    
    would silently create an empty state `bAR` and get stuck in it until
    the module is reset. This was done intentionally (in Migen, this code
    would in fact miscompile), but in retrospect was clearly a bad idea;
    it turns typos into bugs, while in the rare case that branching to
    a completely empty state is desired, it is trivial to define one.
    
    Fixes #315.
    whitequark committed Feb 6, 2020
    Copy the full SHA
    a1c5863 View commit details
Showing with 13 additions and 2 deletions.
  1. +5 −1 nmigen/hdl/dsl.py
  2. +8 −1 nmigen/test/test_hdl_dsl.py
6 changes: 5 additions & 1 deletion nmigen/hdl/dsl.py
Original file line number Diff line number Diff line change
@@ -375,6 +375,10 @@ def FSM(self, reset=None, domain="sync", name="fsm"):
self._ctrl_context = "FSM"
self.domain._depth += 1
yield fsm
for state_name in fsm_data["encoding"]:
if state_name not in fsm_data["states"]:
raise NameError("FSM state '{}' is referenced but not defined"
.format(state_name))
finally:
self.domain._depth -= 1
self._ctrl_context = None
@@ -386,7 +390,7 @@ def State(self, name):
src_loc = tracer.get_src_loc(src_loc_at=1)
fsm_data = self._get_ctrl("FSM")
if name in fsm_data["states"]:
raise SyntaxError("FSM state '{}' is already defined".format(name))
raise NameError("FSM state '{}' is already defined".format(name))
if name not in fsm_data["encoding"]:
fsm_data["encoding"][name] = len(fsm_data["encoding"])
try:
9 changes: 8 additions & 1 deletion nmigen/test/test_hdl_dsl.py
Original file line number Diff line number Diff line change
@@ -582,12 +582,19 @@ def test_FSM_wrong_domain(self):
with m.FSM(domain="comb"):
pass

def test_FSM_wrong_undefined(self):
m = Module()
with self.assertRaises(NameError,
msg="FSM state 'FOO' is referenced but not defined"):
with m.FSM() as fsm:
fsm.ongoing("FOO")

def test_FSM_wrong_redefined(self):
m = Module()
with m.FSM():
with m.State("FOO"):
pass
with self.assertRaises(SyntaxError,
with self.assertRaises(NameError,
msg="FSM state 'FOO' is already defined"):
with m.State("FOO"):
pass