hdl: remove deprecated Sample, Past, Stable, Rose, Fell.

This commit is contained in:
Catherine 2023-11-25 00:38:33 +00:00
parent 475b0f35dd
commit 750cbbc3c7
13 changed files with 23 additions and 328 deletions

View file

@ -1,2 +1,4 @@
from .hdl.ast import AnyConst, AnySeq, Assert, Assume, Cover
from .hdl.ast import Past, Stable, Rose, Fell, Initial
from .hdl.ast import AnyConst, AnySeq, Initial, Assert, Assume, Cover
__all__ = ["AnyConst", "AnySeq", "Initial", "Assert", "Assume", "Cover"]

View file

@ -398,12 +398,6 @@ class _ValueCompiler(xfrm.ValueVisitor):
def on_ResetSignal(self, value):
raise NotImplementedError # :nocov:
def on_Sample(self, value):
raise NotImplementedError # :nocov:
def on_Initial(self, value):
raise NotImplementedError # :nocov:
def on_Cat(self, value):
return "{{ {} }}".format(" ".join(reversed([self(o) for o in value.parts])))
@ -498,6 +492,13 @@ class _RHSValueCompiler(_ValueCompiler):
self.s.anys[value] = res
return res
def on_Initial(self, value):
res = self.s.rtlil.wire(width=1, src=_src(value.src_loc))
self.s.rtlil.cell("$initstate", ports={
"\\Y": res,
}, src=_src(value.src_loc))
return res
def on_Signal(self, value):
wire_curr, wire_next = self.s.resolve(value)
return wire_curr
@ -646,6 +647,9 @@ class _LHSValueCompiler(_ValueCompiler):
def on_AnySeq(self, value):
raise TypeError # :nocov:
def on_Initial(self, value):
raise TypeError # :nocov:
def on_Operator(self, value):
if value.operator in ("u", "s"):
# These operators are transparent on the LHS.

View file

@ -9,7 +9,7 @@ import jinja2
from .. import __version__
from .._toolchain import *
from ..hdl import *
from ..hdl.xfrm import SampleLowerer, DomainLowerer
from ..hdl.xfrm import DomainLowerer
from ..lib.cdc import ResetSynchronizer
from ..back import rtlil, verilog
from .res import *
@ -143,7 +143,6 @@ class Platform(ResourceManager, metaclass=ABCMeta):
self._prepared = True
fragment = Fragment.get(elaboratable, self)
fragment = SampleLowerer()(fragment)
fragment._propagate_domains(self.create_missing_domain, platform=self)
fragment = DomainLowerer()(fragment)

View file

@ -20,7 +20,7 @@ __all__ = [
"Array", "ArrayProxy",
"Signal", "ClockSignal", "ResetSignal",
"ValueCastable", "ValueLike",
"Sample", "Past", "Stable", "Rose", "Fell", "Initial",
"Initial",
"Statement", "Switch",
"Property", "Assign", "Assert", "Assume", "Cover",
"ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict", "SignalSet",
@ -1549,70 +1549,6 @@ class ValueLike(metaclass=_ValueLikeMeta):
raise TypeError("ValueLike is an abstract class and cannot be constructed")
# TODO(amaranth-0.5): remove
@final
class Sample(Value):
"""Value from the past.
A ``Sample`` of an expression is equal to the value of the expression ``clocks`` clock edges
of the ``domain`` clock back. If that moment is before the beginning of time, it is equal
to the value of the expression calculated as if each signal had its reset value.
"""
@deprecated("instead of using `Sample`, create a register explicitly")
def __init__(self, expr, clocks, domain, *, src_loc_at=0):
super().__init__(src_loc_at=1 + src_loc_at)
self.value = Value.cast(expr)
self.clocks = int(clocks)
self.domain = domain
if not isinstance(self.value, (Const, Signal, ClockSignal, ResetSignal, Initial)):
raise TypeError("Sampled value must be a signal or a constant, not {!r}"
.format(self.value))
if self.clocks < 0:
raise ValueError("Cannot sample a value {} cycles in the future"
.format(-self.clocks))
if not (self.domain is None or isinstance(self.domain, str)):
raise TypeError("Domain name must be a string or None, not {!r}"
.format(self.domain))
def shape(self):
return self.value.shape()
def _rhs_signals(self):
return SignalSet((self,))
def __repr__(self):
return "(sample {!r} @ {}[{}])".format(
self.value, "<default>" if self.domain is None else self.domain, self.clocks)
# TODO(amaranth-0.5): remove
@deprecated("instead of using `Past`, create a register explicitly")
def Past(expr, clocks=1, domain=None):
with _ignore_deprecated():
return Sample(expr, clocks, domain)
# TODO(amaranth-0.5): remove
@deprecated("instead of using `Stable`, create registers and comparisons explicitly")
def Stable(expr, clocks=0, domain=None):
with _ignore_deprecated():
return Sample(expr, clocks + 1, domain) == Sample(expr, clocks, domain)
# TODO(amaranth-0.5): remove
@deprecated("instead of using `Rose`, create registers and comparisons explicitly")
def Rose(expr, clocks=0, domain=None):
with _ignore_deprecated():
return ~Sample(expr, clocks + 1, domain) & Sample(expr, clocks, domain)
# TODO(amaranth-0.5): remove
@deprecated("instead of using `Fell`, create registers and comparisons explicitly")
def Fell(expr, clocks=0, domain=None):
with _ignore_deprecated():
return Sample(expr, clocks + 1, domain) & ~Sample(expr, clocks, domain)
@final
class Initial(Value):
"""Start indicator, for model checking.
@ -1626,7 +1562,7 @@ class Initial(Value):
return Shape(1)
def _rhs_signals(self):
return SignalSet((self,))
return SignalSet()
def __repr__(self):
return "(initial)"
@ -1895,8 +1831,6 @@ class ValueKey:
elif isinstance(self.value, ArrayProxy):
self._hash = hash((ValueKey(self.value.index),
tuple(ValueKey(e) for e in self.value._iter_as_values())))
elif isinstance(self.value, Sample):
self._hash = hash((ValueKey(self.value.value), self.value.clocks, self.value.domain))
elif isinstance(self.value, Initial):
self._hash = 0
else: # :nocov:
@ -1942,10 +1876,6 @@ class ValueKey:
all(ValueKey(a) == ValueKey(b)
for a, b in zip(self.value._iter_as_values(),
other.value._iter_as_values())))
elif isinstance(self.value, Sample):
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
self.value.clocks == other.value.clocks and
self.value.domain == self.value.domain)
elif isinstance(self.value, Initial):
return True
else: # :nocov:

View file

@ -491,7 +491,6 @@ class Module(_ModuleBuilderRoot, Elaboratable):
.format(domain_name(domain)))
stmt._MustUse__used = True
stmt = SampleDomainInjector(domain)(stmt)
for signal in stmt._lhs_signals():
if signal not in self._driving:
@ -539,8 +538,7 @@ class Module(_ModuleBuilderRoot, Elaboratable):
fragment.add_subfragment(Fragment.get(self._named_submodules[name], platform), name)
for submodule in self._anon_submodules:
fragment.add_subfragment(Fragment.get(submodule, platform), None)
statements = SampleDomainInjector("sync")(self._statements)
fragment.add_statements(statements)
fragment.add_statements(self._statements)
for signal, domain in self._driving.items():
fragment.add_driver(signal, domain)
fragment.add_domains(self._domains.values())

View file

@ -506,11 +506,10 @@ class Fragment:
self.add_ports(sig, dir="i")
def prepare(self, ports=None, missing_domain=lambda name: ClockDomain(name)):
from .xfrm import SampleLowerer, DomainLowerer
from .xfrm import DomainLowerer
fragment = SampleLowerer()(self)
new_domains = fragment._propagate_domains(missing_domain)
fragment = DomainLowerer()(fragment)
new_domains = self._propagate_domains(missing_domain)
fragment = DomainLowerer()(self)
if ports is None:
fragment._propagate_ports(ports=(), all_undef_as_ports=True)
else:

View file

@ -15,7 +15,6 @@ __all__ = ["ValueVisitor", "ValueTransformer",
"FragmentTransformer",
"TransformedElaboratable",
"DomainCollector", "DomainRenamer", "DomainLowerer",
"SampleDomainInjector", "SampleLowerer",
"SwitchCleaner", "LHSGroupAnalyzer", "LHSGroupFilter",
"ResetInserter", "EnableInserter"]
@ -65,10 +64,6 @@ class ValueVisitor(metaclass=ABCMeta):
def on_ArrayProxy(self, value):
pass # :nocov:
@abstractmethod
def on_Sample(self, value):
pass # :nocov:
@abstractmethod
def on_Initial(self, value):
pass # :nocov:
@ -103,8 +98,6 @@ class ValueVisitor(metaclass=ABCMeta):
new_value = self.on_Cat(value)
elif type(value) is ArrayProxy:
new_value = self.on_ArrayProxy(value)
elif type(value) is Sample:
new_value = self.on_Sample(value)
elif type(value) is Initial:
new_value = self.on_Initial(value)
else:
@ -153,9 +146,6 @@ class ValueTransformer(ValueVisitor):
return ArrayProxy([self.on_value(elem) for elem in value._iter_as_values()],
self.on_value(value.index))
def on_Sample(self, value):
return Sample(self.on_value(value.value), value.clocks, value.domain)
def on_Initial(self, value):
return value
@ -369,9 +359,6 @@ class DomainCollector(ValueVisitor, StatementVisitor):
self.on_value(elem)
self.on_value(value.index)
def on_Sample(self, value):
self.on_value(value.value)
def on_Initial(self, value):
pass
@ -509,81 +496,6 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
return new_fragment
class SampleDomainInjector(ValueTransformer, StatementTransformer):
def __init__(self, domain):
self.domain = domain
@_ignore_deprecated
def on_Sample(self, value):
if value.domain is not None:
return value
return Sample(value.value, value.clocks, self.domain)
def __call__(self, stmts):
return self.on_statement(stmts)
class SampleLowerer(FragmentTransformer, ValueTransformer, StatementTransformer):
def __init__(self):
self.initial = None
self.sample_cache = None
self.sample_stmts = None
def _name_reset(self, value):
if isinstance(value, Const):
return f"c${value.value}", value.value
elif isinstance(value, Signal):
return f"s${value.name}", value.reset
elif isinstance(value, ClockSignal):
return "clk", 0
elif isinstance(value, ResetSignal):
return "rst", 1
elif isinstance(value, Initial):
return "init", 0 # Past(Initial()) produces 0, 1, 0, 0, ...
else:
raise NotImplementedError # :nocov:
@_ignore_deprecated
def on_Sample(self, value):
if value in self.sample_cache:
return self.sample_cache[value]
sampled_value = self.on_value(value.value)
if value.clocks == 0:
sample = sampled_value
else:
assert value.domain is not None
sampled_name, sampled_reset = self._name_reset(value.value)
name = f"$sample${sampled_name}${value.domain}${value.clocks}"
sample = Signal.like(value.value, name=name, reset_less=True, reset=sampled_reset)
sample.attrs["amaranth.sample_reg"] = True
prev_sample = self.on_Sample(Sample(sampled_value, value.clocks - 1, value.domain))
if value.domain not in self.sample_stmts:
self.sample_stmts[value.domain] = []
self.sample_stmts[value.domain].append(sample.eq(prev_sample))
self.sample_cache[value] = sample
return sample
def on_Initial(self, value):
if self.initial is None:
self.initial = Signal(name="init")
return self.initial
def map_statements(self, fragment, new_fragment):
self.initial = None
self.sample_cache = ValueDict()
self.sample_stmts = OrderedDict()
new_fragment.add_statements(map(self.on_statement, fragment.statements))
for domain, stmts in self.sample_stmts.items():
new_fragment.add_statements(stmts)
for stmt in stmts:
new_fragment.add_driver(stmt.lhs, domain)
if self.initial is not None:
new_fragment.add_subfragment(Instance("$initstate", o_Y=self.initial))
class SwitchCleaner(StatementVisitor):
def on_ignore(self, stmt):
return stmt

View file

@ -103,9 +103,6 @@ class _ValueCompiler(ValueVisitor, _Compiler):
def on_AnySeq(self, value):
raise NotImplementedError # :nocov:
def on_Sample(self, value):
raise NotImplementedError # :nocov:
def on_Initial(self, value):
raise NotImplementedError # :nocov: