From 7f58cecba72c300da77f423f87b6c2be6baf95bd Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 31 Dec 2021 21:03:57 +0000 Subject: [PATCH] add on_Display, by jeanthom https://gist.github.com/jeanthom/f97f5b928720d4adda9d295e8a5bc078 --- nmigen/back/rtlil.py | 3 +++ nmigen/hdl/ast.py | 26 ++++++++++++++++++++++++-- nmigen/hdl/dsl.py | 2 +- nmigen/hdl/xfrm.py | 16 ++++++++++++++++ nmigen/sim/_pyrtl.py | 7 +++++++ 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 0990e42..bf77d14 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -751,6 +751,9 @@ class _StatementCompiler(xfrm.StatementVisitor): on_Assume = on_property on_Cover = on_property + def on_Display(self, stmt): + pass + def on_Switch(self, stmt): self._check_rhs(stmt.test) diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 1bbe9f6..6fe8fee 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -19,7 +19,7 @@ __all__ = [ "UserValue", "ValueCastable", "Sample", "Past", "Stable", "Rose", "Fell", "Initial", "Statement", "Switch", - "Property", "Assign", "Assert", "Assume", "Cover", + "Property", "Assign", "Assert", "Assume", "Cover", "Display", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict", "SignalSet", ] @@ -1457,7 +1457,6 @@ class Property(Statement, MustUse): def __repr__(self): return "({} {!r})".format(self._kind, self.test) - @final class Assert(Property): _kind = "assert" @@ -1472,6 +1471,29 @@ class Assume(Property): class Cover(Property): _kind = "cover" +@final +class Display(Statement): + _MustUse__warning = UnusedProperty + + def __init__(self, text, *args): + super().__init__(src_loc_at=0) + self.text = text + self.args = args + self.test = Signal() + self._check = Signal(reset_less=True) + self._check.src_loc = self.src_loc + self._en = Signal(reset_less=True) + self._en.src_loc = self.src_loc + + def _lhs_signals(self): + return SignalSet((self._en, self._check)) + + def _rhs_signals(self): + return self.test._rhs_signals() + + def __repr__(self): + return "(display {!r})".format(self.text) + # @final class Switch(Statement): diff --git a/nmigen/hdl/dsl.py b/nmigen/hdl/dsl.py index 564d8b8..cf40c66 100644 --- a/nmigen/hdl/dsl.py +++ b/nmigen/hdl/dsl.py @@ -484,7 +484,7 @@ class Module(_ModuleBuilderRoot, Elaboratable): self._pop_ctrl() for stmt in Statement.cast(assigns): - if not compat_mode and not isinstance(stmt, (Assign, Assert, Assume, Cover)): + if not compat_mode and not isinstance(stmt, (Assign, Assert, Assume, Cover, Display)): raise SyntaxError( "Only assignments and property checks may be appended to d.{}" .format(domain_name(domain))) diff --git a/nmigen/hdl/xfrm.py b/nmigen/hdl/xfrm.py index 97f8c53..4e043f7 100644 --- a/nmigen/hdl/xfrm.py +++ b/nmigen/hdl/xfrm.py @@ -190,6 +190,10 @@ class StatementVisitor(metaclass=ABCMeta): def on_Cover(self, stmt): pass # :nocov: + @abstractmethod + def on_Display(self, stmt): + pass # :nocov: + @abstractmethod def on_Switch(self, stmt): pass # :nocov: @@ -213,6 +217,8 @@ class StatementVisitor(metaclass=ABCMeta): new_stmt = self.on_Assume(stmt) elif type(stmt) is Cover: new_stmt = self.on_Cover(stmt) + elif type(stmt) is Display: + new_stmt = self.on_Display(stmt) elif isinstance(stmt, Switch): # Uses `isinstance()` and not `type() is` because nmigen.compat requires it. new_stmt = self.on_Switch(stmt) @@ -248,6 +254,12 @@ class StatementTransformer(StatementVisitor): def on_Cover(self, stmt): return Cover(self.on_value(stmt.test), _check=stmt._check, _en=stmt._en) + def on_Display(self, stmt): + # args = [self.on_value(arg) for arg in stmt.args] + # return Display(stmt.text, *args) + stmt.args = [self.on_value(arg) for arg in stmt.args] + return stmt + 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) @@ -401,6 +413,7 @@ class DomainCollector(ValueVisitor, StatementVisitor): on_Assert = on_property on_Assume = on_property on_Cover = on_property + on_Display = on_property def on_Switch(self, stmt): self.on_value(stmt.test) @@ -606,6 +619,7 @@ class SwitchCleaner(StatementVisitor): on_Assert = on_ignore on_Assume = on_ignore on_Cover = on_ignore + on_Display = on_ignore def on_Switch(self, stmt): cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items()) @@ -661,6 +675,7 @@ class LHSGroupAnalyzer(StatementVisitor): on_Assert = on_property on_Assume = on_property on_Cover = on_property + on_Display = on_property def on_Switch(self, stmt): for case_stmts in stmt.cases.values(): @@ -696,6 +711,7 @@ class LHSGroupFilter(SwitchCleaner): on_Assert = on_property on_Assume = on_property on_Cover = on_property + on_Display = on_property class _ControlInserter(FragmentTransformer): diff --git a/nmigen/sim/_pyrtl.py b/nmigen/sim/_pyrtl.py index 126ae51..ee3c847 100644 --- a/nmigen/sim/_pyrtl.py +++ b/nmigen/sim/_pyrtl.py @@ -383,6 +383,13 @@ class _StatementCompiler(StatementVisitor, _Compiler): def on_Cover(self, stmt): raise NotImplementedError # :nocov: + def on_Display(self, stmt): + args = [] + for i in range(len(stmt.args)): + arg = self.emitter.def_var(f"args{i}", f"{self.rhs(stmt.args[i])} & {(1 << len(stmt.args[i])) - 1}") + args.append(arg) + self.emitter.append(f"print(\"{stmt.text}\" % tuple([{','.join(args)}]))") + @classmethod def compile(cls, state, stmt): output_indexes = [state.get_signal(signal) for signal in stmt._lhs_signals()] -- 2.30.2