Skip to content

Instantly share code, notes, and snippets.

@jeanthom
Created August 5, 2020 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeanthom/f97f5b928720d4adda9d295e8a5bc078 to your computer and use it in GitHub Desktop.
Save jeanthom/f97f5b928720d4adda9d295e8a5bc078 to your computer and use it in GitHub Desktop.
diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py
index 100df5a..7581163 100644
--- a/nmigen/back/rtlil.py
+++ b/nmigen/back/rtlil.py
@@ -749,6 +749,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 55b825b..1686569 100644
--- a/nmigen/hdl/ast.py
+++ b/nmigen/hdl/ast.py
@@ -19,7 +19,7 @@ __all__ = [
"UserValue",
"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",
]
@@ -1398,7 +1398,6 @@ class Property(Statement, MustUse):
def __repr__(self):
return "({} {!r})".format(self._kind, self.test)
-
@final
class Assert(Property):
_kind = "assert"
@@ -1413,6 +1412,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 12081ac..18dac05 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 6e0c209..7c23569 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 14279ac..e70f990 100644
--- a/nmigen/sim/_pyrtl.py
+++ b/nmigen/sim/_pyrtl.py
@@ -370,6 +370,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()]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment