hdl.ast: give Assert and Assume their own src_loc.

This helps with patterns like `Assert(fsm.ongoing("IDLE"))`, which
would otherwise point into nMigen internals.
This commit is contained in:
whitequark 2019-01-19 00:08:51 +00:00
parent 66466a8a0e
commit b50b47d984
3 changed files with 23 additions and 34 deletions

View file

@ -617,7 +617,7 @@ class _StatementCompiler(xfrm.StatementVisitor):
self.state.rtlil.cell("$assert", ports={
"\\A": check_wire,
"\\EN": en_wire,
}, src=src(stmt.test.src_loc))
}, src=src(stmt.src_loc))
def on_Assume(self, stmt):
self(stmt._check.eq(stmt.test))
@ -628,7 +628,7 @@ class _StatementCompiler(xfrm.StatementVisitor):
self.state.rtlil.cell("$assume", ports={
"\\A": check_wire,
"\\EN": en_wire,
}, src=src(stmt.test.src_loc))
}, src=src(stmt.src_loc))
def on_Switch(self, stmt):
self._check_rhs(stmt.test)

View file

@ -910,19 +910,21 @@ class Assign(Statement):
return "(eq {!r} {!r})".format(self.lhs, self.rhs)
class Assert(Statement):
class Property(Statement):
def __init__(self, test, _check=None, _en=None):
self.src_loc = tracer.get_src_loc()
self.test = Value.wrap(test)
self._check = _check
if self._check is None:
self._check = Signal(reset_less=True, name="$assert$check")
self._check.src_loc = self.test.src_loc
self._check = Signal(reset_less=True, name="${}$check".format(self._kind))
self._check.src_loc = self.src_loc
self._en = _en
if _en is None:
self._en = Signal(reset_less=True, name="$assert$en")
self._en.src_loc = self.test.src_loc
self._en = Signal(reset_less=True, name="${}$en".format(self._kind))
self._en.src_loc = self.src_loc
def _lhs_signals(self):
return ValueSet((self._en, self._check))
@ -931,31 +933,15 @@ class Assert(Statement):
return self.test._rhs_signals()
def __repr__(self):
return "(assert {!r})".format(self.test)
return "({} {!r})".format(self._kind, self.test)
class Assume(Statement):
def __init__(self, test, _check=None, _en=None):
self.test = Value.wrap(test)
class Assert(Property):
_kind = "assert"
self._check = _check
if self._check is None:
self._check = Signal(reset_less=True, name="$assume$check")
self._check.src_loc = self.test.src_loc
self._en = _en
if self._en is None:
self._en = Signal(reset_less=True, name="$assume$en")
self._en.src_loc = self.test.src_loc
def _lhs_signals(self):
return ValueSet((self._en, self._check))
def _rhs_signals(self):
return self.test._rhs_signals()
def __repr__(self):
return "(assume {!r})".format(self.test)
class Assume(Property):
_kind = "assume"
class Switch(Statement):

View file

@ -190,18 +190,21 @@ class StatementVisitor(metaclass=ABCMeta):
def on_statement(self, stmt):
if type(stmt) is Assign:
return self.on_Assign(stmt)
new_stmt = self.on_Assign(stmt)
elif type(stmt) is Assert:
return self.on_Assert(stmt)
new_stmt = self.on_Assert(stmt)
elif type(stmt) is Assume:
return self.on_Assume(stmt)
new_stmt = self.on_Assume(stmt)
elif isinstance(stmt, Switch):
# Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
return self.on_Switch(stmt)
new_stmt = self.on_Switch(stmt)
elif isinstance(stmt, Iterable):
return self.on_statements(stmt)
new_stmt = self.on_statements(stmt)
else:
return self.on_unknown_statement(stmt)
new_stmt = self.on_unknown_statement(stmt)
if hasattr(stmt, "src_loc") and hasattr(new_stmt, "src_loc"):
new_stmt.src_loc = stmt.src_loc
return new_stmt
def __call__(self, value):
return self.on_statement(value)