diff --git a/amaranth/hdl/ast.py b/amaranth/hdl/ast.py index 75ebbc676..47347ec46 100644 --- a/amaranth/hdl/ast.py +++ b/amaranth/hdl/ast.py @@ -541,6 +541,8 @@ def matches(self, *patterns): continue matches.append(self == pattern) if not matches: + warnings.warn("The value of Value.matches() with no patterns will change to Const(0) " + "in Amaranth 0.5", SyntaxWarning, stacklevel=2) return Const(1) elif len(matches) == 1: return matches[0] diff --git a/amaranth/hdl/dsl.py b/amaranth/hdl/dsl.py index 467fd1e8e..92dd6796b 100644 --- a/amaranth/hdl/dsl.py +++ b/amaranth/hdl/dsl.py @@ -307,6 +307,9 @@ def Case(self, *patterns): src_loc = tracer.get_src_loc(src_loc_at=1) switch_data = self._get_ctrl("Switch") new_patterns = () + if not patterns: + warnings.warn("The behavior of Case() with no patterns will change to never-active " + "in Amaranth 0.5; use Default() instead", SyntaxWarning, stacklevel=3) # This code should accept exactly the same patterns as `v.matches(...)`. for pattern in patterns: if isinstance(pattern, str) and any(bit not in "01- \t" for bit in pattern): @@ -353,8 +356,22 @@ def Case(self, *patterns): self._ctrl_context = "Switch" self._statements = _outer_case + @contextmanager def Default(self): - return self.Case() + self._check_context("Default", context="Switch") + src_loc = tracer.get_src_loc(src_loc_at=1) + switch_data = self._get_ctrl("Switch") + try: + _outer_case, self._statements = self._statements, [] + self._ctrl_context = None + yield + self._flush_ctrl() + if () not in switch_data["cases"]: + switch_data["cases"][()] = self._statements + switch_data["case_src_locs"][()] = src_loc + finally: + self._ctrl_context = "Switch" + self._statements = _outer_case @contextmanager def FSM(self, reset=None, domain="sync", name="fsm"): diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py index 1e4d8a480..65e3ce18f 100644 --- a/tests/test_hdl_ast.py +++ b/tests/test_hdl_ast.py @@ -682,7 +682,9 @@ def test_xor_value(self): def test_matches(self): s = Signal(4) - self.assertRepr(s.matches(), "(const 1'd1)") + with self.assertWarnsRegex(SyntaxWarning, + r"^The value of Value.matches\(\) with no patterns will change to Const\(0\)"): + self.assertRepr(s.matches(), "(const 1'd1)") self.assertRepr(s.matches(1), """ (== (sig s) (const 1'd1)) """) diff --git a/tests/test_hdl_dsl.py b/tests/test_hdl_dsl.py index 9fc210ff5..44001d0ff 100644 --- a/tests/test_hdl_dsl.py +++ b/tests/test_hdl_dsl.py @@ -387,11 +387,13 @@ def test_Switch(self): def test_Switch_default_Case(self): m = Module() - with m.Switch(self.w1): - with m.Case(3): - m.d.comb += self.c1.eq(1) - with m.Case(): - m.d.comb += self.c2.eq(1) + with self.assertWarnsRegex(SyntaxWarning, + r"^The behavior of Case\(\) with no patterns will change to never-active"): + with m.Switch(self.w1): + with m.Case(3): + m.d.comb += self.c1.eq(1) + with m.Case(): + m.d.comb += self.c2.eq(1) m._flush() self.assertRepr(m._statements, """ (