From e5e23644a43581b912e8b6ce46f22a4934781c94 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 25 Jun 2019 17:53:09 +0000 Subject: [PATCH] hdl.{ast,dst}: directly represent RTLIL default case. This makes RTLIL mildly nicer: casez ({ \$5 , \$3 , \$1 }) 3'bzz1: \$next\o = \$7 ; 3'bz1z: \$next\o = \$9 ; 3'b1zz: \$next\o = \$11 ; - 3'bz: + default: { \$next\co , \$next\o } = \$13 ; endcase --- nmigen/back/pysim.py | 20 +++++++++++--------- nmigen/hdl/ast.py | 8 ++++++-- nmigen/hdl/dsl.py | 2 +- nmigen/test/test_hdl_dsl.py | 4 ++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index fee545a..c07677f 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -319,16 +319,18 @@ class _StatementCompiler(StatementVisitor): test = self.rrhs_compiler(stmt.test) cases = [] for value, stmts in stmt.cases.items(): - if "-" in value: - mask = "".join("0" if b == "-" else "1" for b in value) - value = "".join("0" if b == "-" else b for b in value) + if value is None: + check = lambda test: True else: - mask = "1" * len(value) - mask = int(mask, 2) - value = int(value, 2) - def make_test(mask, value): - return lambda test: test & mask == value - cases.append((make_test(mask, value), self.on_statements(stmts))) + if "-" in value: + mask = "".join("0" if b == "-" else "1" for b in value) + value = "".join("0" if b == "-" else b for b in value) + else: + mask = "1" * len(value) + mask = int(mask, 2) + value = int(value, 2) + check = lambda test: test & mask == value + cases.append((check, self.on_statements(stmts))) def run(state): test_value = test(state) for check, body in cases: diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 8be490d..1bcbc5e 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -1024,10 +1024,12 @@ class Switch(Statement): key = "{:0{}b}".format(key, len(self.test)) elif isinstance(key, str): pass + elif key is None: + pass else: raise TypeError("Object '{!r}' cannot be used as a switch key" .format(key)) - assert len(key) == len(self.test) + assert key is None or len(key) == len(self.test) if not isinstance(stmts, Iterable): stmts = [stmts] self.cases[key] = Statement.wrap(stmts) @@ -1043,7 +1045,9 @@ class Switch(Statement): return self.test._rhs_signals() | signals def __repr__(self): - cases = ["(case {} {})".format(key, " ".join(map(repr, stmts))) + cases = ["(default {})".format(" ".join(map(repr, stmts))) + if key is None else + "(case {} {})".format(key, " ".join(map(repr, stmts))) for key, stmts in self.cases.items()] return "(switch {!r} {})".format(self.test, " ".join(cases)) diff --git a/nmigen/hdl/dsl.py b/nmigen/hdl/dsl.py index 30629c4..851d721 100644 --- a/nmigen/hdl/dsl.py +++ b/nmigen/hdl/dsl.py @@ -316,7 +316,7 @@ class Module(_ModuleBuilderRoot, Elaboratable): if if_test is not None: match = ("1" + "-" * (len(tests) - 1)).rjust(len(if_tests), "-") else: - match = "-" * len(tests) + match = None cases[match] = if_case self._statements.append(Switch(Cat(tests), cases)) diff --git a/nmigen/test/test_hdl_dsl.py b/nmigen/test/test_hdl_dsl.py index 0e703e0..e15b1aa 100644 --- a/nmigen/test/test_hdl_dsl.py +++ b/nmigen/test/test_hdl_dsl.py @@ -174,7 +174,7 @@ class DSLTestCase(FHDLTestCase): (switch (cat (sig s1) (sig s2)) (case -1 (eq (sig c1) (const 1'd1))) (case 1- (eq (sig c2) (const 1'd0))) - (case -- (eq (sig c3) (const 1'd1))) + (default (eq (sig c3) (const 1'd1))) ) ) """) @@ -234,7 +234,7 @@ class DSLTestCase(FHDLTestCase): (case 1 (eq (sig c2) (const 1'd1))) ) ) - (case - + (default (eq (sig c3) (const 1'd1)) ) ) -- 2.30.2