From: whitequark Date: Tue, 3 Sep 2019 01:32:24 +0000 (+0000) Subject: hdl.ast,back.rtlil: implement Cover. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d035cdb5f4ef0d8c4b7a56139277f2bba3261425;p=nmigen.git hdl.ast,back.rtlil: implement Cover. Fixes #194. --- diff --git a/nmigen/asserts.py b/nmigen/asserts.py index f374cf0..b0e97b9 100644 --- a/nmigen/asserts.py +++ b/nmigen/asserts.py @@ -1,2 +1,2 @@ -from .hdl.ast import AnyConst, AnySeq, Assert, Assume +from .hdl.ast import AnyConst, AnySeq, Assert, Assume, Cover from .hdl.ast import Past, Stable, Rose, Fell, Initial diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index 25b65a7..82df605 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -320,6 +320,9 @@ class _StatementCompiler(StatementVisitor): def on_Assume(self, stmt): pass # :nocov: + def on_Cover(self, stmt): + raise NotImplementedError("Covers not yet implemented for Simulator backend.") # :nocov: + def on_Switch(self, stmt): test = self.rrhs_compiler(stmt.test) cases = [] diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index f0c1563..09788aa 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -654,27 +654,20 @@ class _StatementCompiler(xfrm.StatementVisitor): else: self._case.assign(self.lhs_compiler(stmt.lhs), rhs_sigspec) - def on_Assert(self, stmt): + def on_property(self, stmt): self(stmt._check.eq(stmt.test)) self(stmt._en.eq(1)) en_wire = self.rhs_compiler(stmt._en) check_wire = self.rhs_compiler(stmt._check) - self.state.rtlil.cell("$assert", ports={ + self.state.rtlil.cell("$" + stmt._kind, ports={ "\\A": check_wire, "\\EN": en_wire, }, src=src(stmt.src_loc)) - def on_Assume(self, stmt): - self(stmt._check.eq(stmt.test)) - self(stmt._en.eq(1)) - - en_wire = self.rhs_compiler(stmt._en) - check_wire = self.rhs_compiler(stmt._check) - self.state.rtlil.cell("$assume", ports={ - "\\A": check_wire, - "\\EN": en_wire, - }, src=src(stmt.src_loc)) + on_Assert = on_property + on_Assume = on_property + on_Cover = on_property def on_Switch(self, stmt): self._check_rhs(stmt.test) diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index c5376d0..a6839e2 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -15,7 +15,7 @@ __all__ = [ "Signal", "ClockSignal", "ResetSignal", "UserValue", "Sample", "Past", "Stable", "Rose", "Fell", "Initial", - "Statement", "Assign", "Assert", "Assume", "Switch", "Delay", "Tick", + "Statement", "Assign", "Assert", "Assume", "Cover", "Switch", "Delay", "Tick", "Passive", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict", "SignalSet", ] @@ -1080,6 +1080,11 @@ class Assume(Property): _kind = "assume" +@final +class Cover(Property): + _kind = "cover" + + # @final class Switch(Statement): def __init__(self, test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}): diff --git a/nmigen/hdl/dsl.py b/nmigen/hdl/dsl.py index 9a7d598..7f85f2d 100644 --- a/nmigen/hdl/dsl.py +++ b/nmigen/hdl/dsl.py @@ -417,9 +417,9 @@ class Module(_ModuleBuilderRoot, Elaboratable): self._pop_ctrl() for assign in Statement.wrap(assigns): - if not compat_mode and not isinstance(assign, (Assign, Assert, Assume)): + if not compat_mode and not isinstance(assign, (Assign, Assert, Assume, Cover)): raise SyntaxError( - "Only assignments, asserts, and assumes may be appended to d.{}" + "Only assignments and property checks may be appended to d.{}" .format(domain_name(domain))) assign = SampleDomainInjector(domain)(assign) diff --git a/nmigen/hdl/xfrm.py b/nmigen/hdl/xfrm.py index 8793c59..ab12ffd 100644 --- a/nmigen/hdl/xfrm.py +++ b/nmigen/hdl/xfrm.py @@ -196,6 +196,10 @@ class StatementVisitor(metaclass=ABCMeta): def on_Assume(self, stmt): pass # :nocov: + @abstractmethod + def on_Cover(self, stmt): + pass # :nocov: + @abstractmethod def on_Switch(self, stmt): pass # :nocov: @@ -217,6 +221,8 @@ class StatementVisitor(metaclass=ABCMeta): new_stmt = self.on_Assert(stmt) elif type(stmt) is Assume: new_stmt = self.on_Assume(stmt) + elif type(stmt) is Cover: + new_stmt = self.on_Cover(stmt) elif isinstance(stmt, Switch): # Uses `isinstance()` and not `type() is` because nmigen.compat requires it. new_stmt = self.on_Switch(stmt) @@ -247,6 +253,9 @@ class StatementTransformer(StatementVisitor): def on_Assume(self, stmt): return Assume(self.on_value(stmt.test), _check=stmt._check, _en=stmt._en) + def on_Cover(self, stmt): + return Cover(self.on_value(stmt.test), _check=stmt._check, _en=stmt._en) + def on_Switch(self, stmt): cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items()) return Switch(self.on_value(stmt.test), cases) @@ -396,11 +405,12 @@ class DomainCollector(ValueVisitor, StatementVisitor): self.on_value(stmt.lhs) self.on_value(stmt.rhs) - def on_Assert(self, stmt): + def on_property(self, stmt): self.on_value(stmt.test) - def on_Assume(self, stmt): - self.on_value(stmt.test) + on_Assert = on_property + on_Assume = on_property + on_Cover = on_property def on_Switch(self, stmt): self.on_value(stmt.test) @@ -598,12 +608,13 @@ class SampleLowerer(FragmentTransformer, ValueTransformer, StatementTransformer) class SwitchCleaner(StatementVisitor): - def on_Assign(self, stmt): + def on_ignore(self, stmt): return stmt - on_Assert = on_Assign - - on_Assume = on_Assign + on_Assign = on_ignore + on_Assert = on_ignore + on_Assume = on_ignore + on_Cover = on_ignore def on_Switch(self, stmt): cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items()) @@ -651,9 +662,14 @@ class LHSGroupAnalyzer(StatementVisitor): if lhs_signals: self.unify(*stmt._lhs_signals()) - on_Assert = on_Assign + def on_property(self, stmt): + lhs_signals = stmt._lhs_signals() + if lhs_signals: + self.unify(*stmt._lhs_signals()) - on_Assume = on_Assign + on_Assert = on_property + on_Assume = on_property + on_Cover = on_property def on_Switch(self, stmt): for case_stmts in stmt.cases.values(): @@ -681,12 +697,14 @@ class LHSGroupFilter(SwitchCleaner): if any_lhs_signal in self.signals: return stmt - def on_Assert(self, stmt): + def on_property(self, stmt): any_lhs_signal = next(iter(stmt._lhs_signals())) if any_lhs_signal in self.signals: return stmt - on_Assume = on_Assert + on_Assert = on_property + on_Assume = on_property + on_Cover = on_property class _ControlInserter(FragmentTransformer): diff --git a/nmigen/test/test_hdl_dsl.py b/nmigen/test/test_hdl_dsl.py index 1da5a6a..02433d8 100644 --- a/nmigen/test/test_hdl_dsl.py +++ b/nmigen/test/test_hdl_dsl.py @@ -74,7 +74,7 @@ class DSLTestCase(FHDLTestCase): def test_d_asgn_wrong(self): m = Module() with self.assertRaises(SyntaxError, - msg="Only assignments, asserts, and assumes may be appended to d.sync"): + msg="Only assignments and property checks may be appended to d.sync"): m.d.sync += Switch(self.s1, {}) def test_comb_wrong(self):