From 2b7afb4cf1fe7d817962a5f43e0609528d9f28be Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 4 Feb 2020 07:54:54 +0000 Subject: [PATCH] hdl.{ast,dsl}: allow whitespace in bit patterns. Fixes #316. --- nmigen/hdl/ast.py | 10 ++++++---- nmigen/hdl/dsl.py | 8 +++++--- nmigen/test/test_hdl_ast.py | 6 +++++- nmigen/test/test_hdl_dsl.py | 6 +++++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 2c039d1..96f1e30 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -357,11 +357,12 @@ class Value(metaclass=ABCMeta): raise SyntaxError("Match pattern must be an integer, a string, or an enumeration, " "not {!r}" .format(pattern)) - if isinstance(pattern, str) and any(bit not in "01-" for bit in pattern): + if isinstance(pattern, str) and any(bit not in "01- \t" for bit in pattern): raise SyntaxError("Match pattern '{}' must consist of 0, 1, and - (don't care) " - "bits" + "bits, and may include whitespace" .format(pattern)) - if isinstance(pattern, str) and len(pattern) != len(self): + if (isinstance(pattern, str) and + len("".join(pattern.split())) != len(self)): raise SyntaxError("Match pattern '{}' must have the same width as match value " "(which is {})" .format(pattern, len(self))) @@ -372,6 +373,7 @@ class Value(metaclass=ABCMeta): SyntaxWarning, stacklevel=3) continue if isinstance(pattern, str): + pattern = "".join(pattern.split()) # remove whitespace mask = int(pattern.replace("0", "1").replace("-", "0"), 2) pattern = int(pattern.replace("-", "0"), 2) matches.append((self & mask) == pattern) @@ -1300,7 +1302,7 @@ class Switch(Statement): new_keys = () for key in keys: if isinstance(key, str): - pass + key = "".join(key.split()) # remove whitespace elif isinstance(key, int): key = format(key, "b").rjust(len(self.test), "0") elif isinstance(key, Enum): diff --git a/nmigen/hdl/dsl.py b/nmigen/hdl/dsl.py index 247e07e..8363737 100644 --- a/nmigen/hdl/dsl.py +++ b/nmigen/hdl/dsl.py @@ -301,10 +301,12 @@ class Module(_ModuleBuilderRoot, Elaboratable): raise SyntaxError("Case pattern must be an integer, a string, or an enumeration, " "not {!r}" .format(pattern)) - if isinstance(pattern, str) and any(bit not in "01-" for bit in pattern): - raise SyntaxError("Case pattern '{}' must consist of 0, 1, and - (don't care) bits" + if isinstance(pattern, str) and any(bit not in "01- \t" for bit in pattern): + raise SyntaxError("Case pattern '{}' must consist of 0, 1, and - (don't care) " + "bits, and may include whitespace" .format(pattern)) - if isinstance(pattern, str) and len(pattern) != len(switch_data["test"]): + if (isinstance(pattern, str) and + len("".join(pattern.split())) != len(switch_data["test"])): raise SyntaxError("Case pattern '{}' must have the same width as switch value " "(which is {})" .format(pattern, len(switch_data["test"]))) diff --git a/nmigen/test/test_hdl_ast.py b/nmigen/test/test_hdl_ast.py index 76665cc..2a40e8b 100644 --- a/nmigen/test/test_hdl_ast.py +++ b/nmigen/test/test_hdl_ast.py @@ -464,6 +464,9 @@ class OperatorTestCase(FHDLTestCase): self.assertRepr(s.matches("10--"), """ (== (& (sig s) (const 4'd12)) (const 4'd8)) """) + self.assertRepr(s.matches("1 0--"), """ + (== (& (sig s) (const 4'd12)) (const 4'd8)) + """) def test_matches_enum(self): s = Signal(SignedEnum) @@ -484,7 +487,8 @@ class OperatorTestCase(FHDLTestCase): def test_matches_bits_wrong(self): s = Signal(4) with self.assertRaises(SyntaxError, - msg="Match pattern 'abc' must consist of 0, 1, and - (don't care) bits"): + msg="Match pattern 'abc' must consist of 0, 1, and - (don't care) bits, " + "and may include whitespace"): s.matches("abc") def test_matches_pattern_wrong(self): diff --git a/nmigen/test/test_hdl_dsl.py b/nmigen/test/test_hdl_dsl.py index 7573941..cc8467c 100644 --- a/nmigen/test/test_hdl_dsl.py +++ b/nmigen/test/test_hdl_dsl.py @@ -331,12 +331,15 @@ class DSLTestCase(FHDLTestCase): m.d.comb += self.c1.eq(1) with m.Case("11--"): m.d.comb += self.c2.eq(1) + with m.Case("1 0--"): + m.d.comb += self.c2.eq(1) m._flush() self.assertRepr(m._statements, """ ( (switch (sig w1) (case 0011 (eq (sig c1) (const 1'd1))) (case 11-- (eq (sig c2) (const 1'd1))) + (case 10-- (eq (sig c2) (const 1'd1))) ) ) """) @@ -435,7 +438,8 @@ class DSLTestCase(FHDLTestCase): m = Module() with m.Switch(self.w1): with self.assertRaises(SyntaxError, - msg="Case pattern 'abc' must consist of 0, 1, and - (don't care) bits"): + msg="Case pattern 'abc' must consist of 0, 1, and - (don't care) bits, " + "and may include whitespace"): with m.Case("abc"): pass -- 2.30.2