parent
2e20622046
commit
943ce317af
|
@ -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
|
from .hdl.ast import Past, Stable, Rose, Fell, Initial
|
||||||
|
|
|
@ -320,6 +320,9 @@ class _StatementCompiler(StatementVisitor):
|
||||||
def on_Assume(self, stmt):
|
def on_Assume(self, stmt):
|
||||||
pass # :nocov:
|
pass # :nocov:
|
||||||
|
|
||||||
|
def on_Cover(self, stmt):
|
||||||
|
raise NotImplementedError("Covers not yet implemented for Simulator backend.") # :nocov:
|
||||||
|
|
||||||
def on_Switch(self, stmt):
|
def on_Switch(self, stmt):
|
||||||
test = self.rrhs_compiler(stmt.test)
|
test = self.rrhs_compiler(stmt.test)
|
||||||
cases = []
|
cases = []
|
||||||
|
|
|
@ -654,27 +654,20 @@ class _StatementCompiler(xfrm.StatementVisitor):
|
||||||
else:
|
else:
|
||||||
self._case.assign(self.lhs_compiler(stmt.lhs), rhs_sigspec)
|
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._check.eq(stmt.test))
|
||||||
self(stmt._en.eq(1))
|
self(stmt._en.eq(1))
|
||||||
|
|
||||||
en_wire = self.rhs_compiler(stmt._en)
|
en_wire = self.rhs_compiler(stmt._en)
|
||||||
check_wire = self.rhs_compiler(stmt._check)
|
check_wire = self.rhs_compiler(stmt._check)
|
||||||
self.state.rtlil.cell("$assert", ports={
|
self.state.rtlil.cell("$" + stmt._kind, ports={
|
||||||
"\\A": check_wire,
|
"\\A": check_wire,
|
||||||
"\\EN": en_wire,
|
"\\EN": en_wire,
|
||||||
}, src=src(stmt.src_loc))
|
}, src=src(stmt.src_loc))
|
||||||
|
|
||||||
def on_Assume(self, stmt):
|
on_Assert = on_property
|
||||||
self(stmt._check.eq(stmt.test))
|
on_Assume = on_property
|
||||||
self(stmt._en.eq(1))
|
on_Cover = on_property
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
def on_Switch(self, stmt):
|
def on_Switch(self, stmt):
|
||||||
self._check_rhs(stmt.test)
|
self._check_rhs(stmt.test)
|
||||||
|
|
|
@ -15,7 +15,7 @@ __all__ = [
|
||||||
"Signal", "ClockSignal", "ResetSignal",
|
"Signal", "ClockSignal", "ResetSignal",
|
||||||
"UserValue",
|
"UserValue",
|
||||||
"Sample", "Past", "Stable", "Rose", "Fell", "Initial",
|
"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",
|
"Passive", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict",
|
||||||
"SignalSet",
|
"SignalSet",
|
||||||
]
|
]
|
||||||
|
@ -1080,6 +1080,11 @@ class Assume(Property):
|
||||||
_kind = "assume"
|
_kind = "assume"
|
||||||
|
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Cover(Property):
|
||||||
|
_kind = "cover"
|
||||||
|
|
||||||
|
|
||||||
# @final
|
# @final
|
||||||
class Switch(Statement):
|
class Switch(Statement):
|
||||||
def __init__(self, test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
|
def __init__(self, test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
|
||||||
|
|
|
@ -417,9 +417,9 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
||||||
self._pop_ctrl()
|
self._pop_ctrl()
|
||||||
|
|
||||||
for assign in Statement.wrap(assigns):
|
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(
|
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)))
|
.format(domain_name(domain)))
|
||||||
|
|
||||||
assign = SampleDomainInjector(domain)(assign)
|
assign = SampleDomainInjector(domain)(assign)
|
||||||
|
|
|
@ -196,6 +196,10 @@ class StatementVisitor(metaclass=ABCMeta):
|
||||||
def on_Assume(self, stmt):
|
def on_Assume(self, stmt):
|
||||||
pass # :nocov:
|
pass # :nocov:
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_Cover(self, stmt):
|
||||||
|
pass # :nocov:
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def on_Switch(self, stmt):
|
def on_Switch(self, stmt):
|
||||||
pass # :nocov:
|
pass # :nocov:
|
||||||
|
@ -217,6 +221,8 @@ class StatementVisitor(metaclass=ABCMeta):
|
||||||
new_stmt = self.on_Assert(stmt)
|
new_stmt = self.on_Assert(stmt)
|
||||||
elif type(stmt) is Assume:
|
elif type(stmt) is Assume:
|
||||||
new_stmt = self.on_Assume(stmt)
|
new_stmt = self.on_Assume(stmt)
|
||||||
|
elif type(stmt) is Cover:
|
||||||
|
new_stmt = self.on_Cover(stmt)
|
||||||
elif isinstance(stmt, Switch):
|
elif isinstance(stmt, Switch):
|
||||||
# Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
|
# Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
|
||||||
new_stmt = self.on_Switch(stmt)
|
new_stmt = self.on_Switch(stmt)
|
||||||
|
@ -247,6 +253,9 @@ class StatementTransformer(StatementVisitor):
|
||||||
def on_Assume(self, stmt):
|
def on_Assume(self, stmt):
|
||||||
return Assume(self.on_value(stmt.test), _check=stmt._check, _en=stmt._en)
|
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):
|
def on_Switch(self, stmt):
|
||||||
cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items())
|
cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items())
|
||||||
return Switch(self.on_value(stmt.test), cases)
|
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.lhs)
|
||||||
self.on_value(stmt.rhs)
|
self.on_value(stmt.rhs)
|
||||||
|
|
||||||
def on_Assert(self, stmt):
|
def on_property(self, stmt):
|
||||||
self.on_value(stmt.test)
|
self.on_value(stmt.test)
|
||||||
|
|
||||||
def on_Assume(self, stmt):
|
on_Assert = on_property
|
||||||
self.on_value(stmt.test)
|
on_Assume = on_property
|
||||||
|
on_Cover = on_property
|
||||||
|
|
||||||
def on_Switch(self, stmt):
|
def on_Switch(self, stmt):
|
||||||
self.on_value(stmt.test)
|
self.on_value(stmt.test)
|
||||||
|
@ -598,12 +608,13 @@ class SampleLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
||||||
|
|
||||||
|
|
||||||
class SwitchCleaner(StatementVisitor):
|
class SwitchCleaner(StatementVisitor):
|
||||||
def on_Assign(self, stmt):
|
def on_ignore(self, stmt):
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
on_Assert = on_Assign
|
on_Assign = on_ignore
|
||||||
|
on_Assert = on_ignore
|
||||||
on_Assume = on_Assign
|
on_Assume = on_ignore
|
||||||
|
on_Cover = on_ignore
|
||||||
|
|
||||||
def on_Switch(self, stmt):
|
def on_Switch(self, stmt):
|
||||||
cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items())
|
cases = OrderedDict((k, self.on_statement(s)) for k, s in stmt.cases.items())
|
||||||
|
@ -651,9 +662,14 @@ class LHSGroupAnalyzer(StatementVisitor):
|
||||||
if lhs_signals:
|
if lhs_signals:
|
||||||
self.unify(*stmt._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):
|
def on_Switch(self, stmt):
|
||||||
for case_stmts in stmt.cases.values():
|
for case_stmts in stmt.cases.values():
|
||||||
|
@ -681,12 +697,14 @@ class LHSGroupFilter(SwitchCleaner):
|
||||||
if any_lhs_signal in self.signals:
|
if any_lhs_signal in self.signals:
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
def on_Assert(self, stmt):
|
def on_property(self, stmt):
|
||||||
any_lhs_signal = next(iter(stmt._lhs_signals()))
|
any_lhs_signal = next(iter(stmt._lhs_signals()))
|
||||||
if any_lhs_signal in self.signals:
|
if any_lhs_signal in self.signals:
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
on_Assume = on_Assert
|
on_Assert = on_property
|
||||||
|
on_Assume = on_property
|
||||||
|
on_Cover = on_property
|
||||||
|
|
||||||
|
|
||||||
class _ControlInserter(FragmentTransformer):
|
class _ControlInserter(FragmentTransformer):
|
||||||
|
|
|
@ -74,7 +74,7 @@ class DSLTestCase(FHDLTestCase):
|
||||||
def test_d_asgn_wrong(self):
|
def test_d_asgn_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
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, {})
|
m.d.sync += Switch(self.s1, {})
|
||||||
|
|
||||||
def test_comb_wrong(self):
|
def test_comb_wrong(self):
|
||||||
|
|
Loading…
Reference in a new issue