Skip to content

Commit 8035d66

Browse files
committed
hdl: remove deprecated Sample, Past, Stable, Rose, Fell. (WIP)
1 parent 28e1d28 commit 8035d66

File tree

12 files changed

+26
-332
lines changed

12 files changed

+26
-332
lines changed

amaranth/asserts.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
from .hdl.ast import AnyConst, AnySeq, Assert, Assume, Cover
2-
from .hdl.ast import Past, Stable, Rose, Fell, Initial
1+
from .hdl.ast import AnyConst, AnySeq, Initial, Assert, Assume, Cover
2+
3+
4+
__all__ = ["AnyConst", "AnySeq", "Initial", "Assert", "Assume", "Cover"]

amaranth/back/rtlil.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def resolve(self, signal, prefix=None):
337337
wire_name = signal.name
338338

339339
is_sync_driven = signal in self.driven and self.driven[signal]
340-
340+
341341
attrs = dict(signal.attrs)
342342
if signal._enum_class is not None:
343343
attrs["enum_base_type"] = signal._enum_class.__name__
@@ -396,12 +396,6 @@ def on_ClockSignal(self, value):
396396
def on_ResetSignal(self, value):
397397
raise NotImplementedError # :nocov:
398398

399-
def on_Sample(self, value):
400-
raise NotImplementedError # :nocov:
401-
402-
def on_Initial(self, value):
403-
raise NotImplementedError # :nocov:
404-
405399
def on_Cat(self, value):
406400
return "{{ {} }}".format(" ".join(reversed([self(o) for o in value.parts])))
407401

@@ -496,6 +490,13 @@ def on_AnySeq(self, value):
496490
self.s.anys[value] = res
497491
return res
498492

493+
def on_Initial(self, value):
494+
res = self.s.rtlil.wire(width=1, src=_src(value.src_loc))
495+
self.s.rtlil.cell("$initstate", ports={
496+
"\\Y": res,
497+
}, src=_src(value.src_loc))
498+
return res
499+
499500
def on_Signal(self, value):
500501
wire_curr, wire_next = self.s.resolve(value)
501502
return wire_curr
@@ -644,6 +645,9 @@ def on_AnyConst(self, value):
644645
def on_AnySeq(self, value):
645646
raise TypeError # :nocov:
646647

648+
def on_Initial(self, value):
649+
raise TypeError # :nocov:
650+
647651
def on_Operator(self, value):
648652
if value.operator in ("u", "s"):
649653
# These operators are transparent on the LHS.
@@ -872,7 +876,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
872876

873877
if sub_type == "$mem_v2" and "MEMID" not in sub_params:
874878
sub_params["MEMID"] = builder._make_name(sub_name, local=False)
875-
879+
876880
sub_ports = OrderedDict()
877881
for port, value in sub_port_map.items():
878882
if not isinstance(subfragment, ir.Instance):
@@ -917,7 +921,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
917921
stmt_compiler._has_rhs = False
918922
stmt_compiler._wrap_assign = False
919923
stmt_compiler(group_stmts)
920-
924+
921925
# For every driven signal in the sync domain, create a flop of appropriate type. Which type
922926
# is appropriate depends on the domain: for domains with sync reset, it is a $dff, for
923927
# domains with async reset it is an $adff. The latter is directly provided with the reset
@@ -930,7 +934,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
930934
wire_curr, wire_next = compiler_state.resolve(signal)
931935

932936
if not cd.async_reset:
933-
# For sync reset flops, the reset value comes from logic inserted by
937+
# For sync reset flops, the reset value comes from logic inserted by
934938
# `hdl.xfrm.DomainLowerer`.
935939
module.cell("$dff", ports={
936940
"\\CLK": wire_clk,

amaranth/build/plat.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .. import __version__
1010
from .._toolchain import *
1111
from ..hdl import *
12-
from ..hdl.xfrm import SampleLowerer, DomainLowerer
12+
from ..hdl.xfrm import DomainLowerer
1313
from ..lib.cdc import ResetSynchronizer
1414
from ..back import rtlil, verilog
1515
from .res import *
@@ -143,7 +143,6 @@ def prepare(self, elaboratable, name="top", **kwargs):
143143
self._prepared = True
144144

145145
fragment = Fragment.get(elaboratable, self)
146-
fragment = SampleLowerer()(fragment)
147146
fragment._propagate_domains(self.create_missing_domain, platform=self)
148147
fragment = DomainLowerer()(fragment)
149148

amaranth/hdl/ast.py

Lines changed: 2 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"Array", "ArrayProxy",
2020
"Signal", "ClockSignal", "ResetSignal",
2121
"ValueCastable",
22-
"Sample", "Past", "Stable", "Rose", "Fell", "Initial",
22+
"Initial",
2323
"Statement", "Switch",
2424
"Property", "Assign", "Assert", "Assume", "Cover",
2525
"ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict", "SignalSet",
@@ -1443,70 +1443,6 @@ def wrapper_memoized(self, *args, **kwargs):
14431443
return wrapper_memoized
14441444

14451445

1446-
# TODO(amaranth-0.5): remove
1447-
@final
1448-
class Sample(Value):
1449-
"""Value from the past.
1450-
1451-
A ``Sample`` of an expression is equal to the value of the expression ``clocks`` clock edges
1452-
of the ``domain`` clock back. If that moment is before the beginning of time, it is equal
1453-
to the value of the expression calculated as if each signal had its reset value.
1454-
"""
1455-
@deprecated("instead of using `Sample`, create a register explicitly")
1456-
def __init__(self, expr, clocks, domain, *, src_loc_at=0):
1457-
super().__init__(src_loc_at=1 + src_loc_at)
1458-
self.value = Value.cast(expr)
1459-
self.clocks = int(clocks)
1460-
self.domain = domain
1461-
if not isinstance(self.value, (Const, Signal, ClockSignal, ResetSignal, Initial)):
1462-
raise TypeError("Sampled value must be a signal or a constant, not {!r}"
1463-
.format(self.value))
1464-
if self.clocks < 0:
1465-
raise ValueError("Cannot sample a value {} cycles in the future"
1466-
.format(-self.clocks))
1467-
if not (self.domain is None or isinstance(self.domain, str)):
1468-
raise TypeError("Domain name must be a string or None, not {!r}"
1469-
.format(self.domain))
1470-
1471-
def shape(self):
1472-
return self.value.shape()
1473-
1474-
def _rhs_signals(self):
1475-
return SignalSet((self,))
1476-
1477-
def __repr__(self):
1478-
return "(sample {!r} @ {}[{}])".format(
1479-
self.value, "<default>" if self.domain is None else self.domain, self.clocks)
1480-
1481-
1482-
# TODO(amaranth-0.5): remove
1483-
@deprecated("instead of using `Past`, create a register explicitly")
1484-
def Past(expr, clocks=1, domain=None):
1485-
with _ignore_deprecated():
1486-
return Sample(expr, clocks, domain)
1487-
1488-
1489-
# TODO(amaranth-0.5): remove
1490-
@deprecated("instead of using `Stable`, create registers and comparisons explicitly")
1491-
def Stable(expr, clocks=0, domain=None):
1492-
with _ignore_deprecated():
1493-
return Sample(expr, clocks + 1, domain) == Sample(expr, clocks, domain)
1494-
1495-
1496-
# TODO(amaranth-0.5): remove
1497-
@deprecated("instead of using `Rose`, create registers and comparisons explicitly")
1498-
def Rose(expr, clocks=0, domain=None):
1499-
with _ignore_deprecated():
1500-
return ~Sample(expr, clocks + 1, domain) & Sample(expr, clocks, domain)
1501-
1502-
1503-
# TODO(amaranth-0.5): remove
1504-
@deprecated("instead of using `Fell`, create registers and comparisons explicitly")
1505-
def Fell(expr, clocks=0, domain=None):
1506-
with _ignore_deprecated():
1507-
return Sample(expr, clocks + 1, domain) & ~Sample(expr, clocks, domain)
1508-
1509-
15101446
@final
15111447
class Initial(Value):
15121448
"""Start indicator, for model checking.
@@ -1520,7 +1456,7 @@ def shape(self):
15201456
return Shape(1)
15211457

15221458
def _rhs_signals(self):
1523-
return SignalSet((self,))
1459+
return SignalSet()
15241460

15251461
def __repr__(self):
15261462
return "(initial)"
@@ -1789,8 +1725,6 @@ def __init__(self, value):
17891725
elif isinstance(self.value, ArrayProxy):
17901726
self._hash = hash((ValueKey(self.value.index),
17911727
tuple(ValueKey(e) for e in self.value._iter_as_values())))
1792-
elif isinstance(self.value, Sample):
1793-
self._hash = hash((ValueKey(self.value.value), self.value.clocks, self.value.domain))
17941728
elif isinstance(self.value, Initial):
17951729
self._hash = 0
17961730
else: # :nocov:
@@ -1836,10 +1770,6 @@ def __eq__(self, other):
18361770
all(ValueKey(a) == ValueKey(b)
18371771
for a, b in zip(self.value._iter_as_values(),
18381772
other.value._iter_as_values())))
1839-
elif isinstance(self.value, Sample):
1840-
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1841-
self.value.clocks == other.value.clocks and
1842-
self.value.domain == self.value.domain)
18431773
elif isinstance(self.value, Initial):
18441774
return True
18451775
else: # :nocov:

amaranth/hdl/dsl.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,6 @@ def domain_name(domain):
491491
.format(domain_name(domain)))
492492

493493
stmt._MustUse__used = True
494-
stmt = SampleDomainInjector(domain)(stmt)
495494

496495
for signal in stmt._lhs_signals():
497496
if signal not in self._driving:
@@ -539,8 +538,7 @@ def elaborate(self, platform):
539538
fragment.add_subfragment(Fragment.get(self._named_submodules[name], platform), name)
540539
for submodule in self._anon_submodules:
541540
fragment.add_subfragment(Fragment.get(submodule, platform), None)
542-
statements = SampleDomainInjector("sync")(self._statements)
543-
fragment.add_statements(statements)
541+
fragment.add_statements(self._statements)
544542
for signal, domain in self._driving.items():
545543
fragment.add_driver(signal, domain)
546544
fragment.add_domains(self._domains.values())

amaranth/hdl/ir.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -506,11 +506,10 @@ def lca_of(fragu, fragv):
506506
self.add_ports(sig, dir="i")
507507

508508
def prepare(self, ports=None, missing_domain=lambda name: ClockDomain(name)):
509-
from .xfrm import SampleLowerer, DomainLowerer
509+
from .xfrm import DomainLowerer
510510

511-
fragment = SampleLowerer()(self)
512-
new_domains = fragment._propagate_domains(missing_domain)
513-
fragment = DomainLowerer()(fragment)
511+
new_domains = self._propagate_domains(missing_domain)
512+
fragment = DomainLowerer()(self)
514513
if ports is None:
515514
fragment._propagate_ports(ports=(), all_undef_as_ports=True)
516515
else:

amaranth/hdl/xfrm.py

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"FragmentTransformer",
1616
"TransformedElaboratable",
1717
"DomainCollector", "DomainRenamer", "DomainLowerer",
18-
"SampleDomainInjector", "SampleLowerer",
1918
"SwitchCleaner", "LHSGroupAnalyzer", "LHSGroupFilter",
2019
"ResetInserter", "EnableInserter"]
2120

@@ -65,10 +64,6 @@ def on_Cat(self, value):
6564
def on_ArrayProxy(self, value):
6665
pass # :nocov:
6766

68-
@abstractmethod
69-
def on_Sample(self, value):
70-
pass # :nocov:
71-
7267
@abstractmethod
7368
def on_Initial(self, value):
7469
pass # :nocov:
@@ -103,8 +98,6 @@ def on_value(self, value):
10398
new_value = self.on_Cat(value)
10499
elif type(value) is ArrayProxy:
105100
new_value = self.on_ArrayProxy(value)
106-
elif type(value) is Sample:
107-
new_value = self.on_Sample(value)
108101
elif type(value) is Initial:
109102
new_value = self.on_Initial(value)
110103
else:
@@ -153,9 +146,6 @@ def on_ArrayProxy(self, value):
153146
return ArrayProxy([self.on_value(elem) for elem in value._iter_as_values()],
154147
self.on_value(value.index))
155148

156-
def on_Sample(self, value):
157-
return Sample(self.on_value(value.value), value.clocks, value.domain)
158-
159149
def on_Initial(self, value):
160150
return value
161151

@@ -369,9 +359,6 @@ def on_ArrayProxy(self, value):
369359
self.on_value(elem)
370360
self.on_value(value.index)
371361

372-
def on_Sample(self, value):
373-
self.on_value(value.value)
374-
375362
def on_Initial(self, value):
376363
pass
377364

@@ -509,81 +496,6 @@ def on_fragment(self, fragment):
509496
return new_fragment
510497

511498

512-
class SampleDomainInjector(ValueTransformer, StatementTransformer):
513-
def __init__(self, domain):
514-
self.domain = domain
515-
516-
@_ignore_deprecated
517-
def on_Sample(self, value):
518-
if value.domain is not None:
519-
return value
520-
return Sample(value.value, value.clocks, self.domain)
521-
522-
def __call__(self, stmts):
523-
return self.on_statement(stmts)
524-
525-
526-
class SampleLowerer(FragmentTransformer, ValueTransformer, StatementTransformer):
527-
def __init__(self):
528-
self.initial = None
529-
self.sample_cache = None
530-
self.sample_stmts = None
531-
532-
def _name_reset(self, value):
533-
if isinstance(value, Const):
534-
return f"c${value.value}", value.value
535-
elif isinstance(value, Signal):
536-
return f"s${value.name}", value.reset
537-
elif isinstance(value, ClockSignal):
538-
return "clk", 0
539-
elif isinstance(value, ResetSignal):
540-
return "rst", 1
541-
elif isinstance(value, Initial):
542-
return "init", 0 # Past(Initial()) produces 0, 1, 0, 0, ...
543-
else:
544-
raise NotImplementedError # :nocov:
545-
546-
@_ignore_deprecated
547-
def on_Sample(self, value):
548-
if value in self.sample_cache:
549-
return self.sample_cache[value]
550-
551-
sampled_value = self.on_value(value.value)
552-
if value.clocks == 0:
553-
sample = sampled_value
554-
else:
555-
assert value.domain is not None
556-
sampled_name, sampled_reset = self._name_reset(value.value)
557-
name = f"$sample${sampled_name}${value.domain}${value.clocks}"
558-
sample = Signal.like(value.value, name=name, reset_less=True, reset=sampled_reset)
559-
sample.attrs["amaranth.sample_reg"] = True
560-
561-
prev_sample = self.on_Sample(Sample(sampled_value, value.clocks - 1, value.domain))
562-
if value.domain not in self.sample_stmts:
563-
self.sample_stmts[value.domain] = []
564-
self.sample_stmts[value.domain].append(sample.eq(prev_sample))
565-
566-
self.sample_cache[value] = sample
567-
return sample
568-
569-
def on_Initial(self, value):
570-
if self.initial is None:
571-
self.initial = Signal(name="init")
572-
return self.initial
573-
574-
def map_statements(self, fragment, new_fragment):
575-
self.initial = None
576-
self.sample_cache = ValueDict()
577-
self.sample_stmts = OrderedDict()
578-
new_fragment.add_statements(map(self.on_statement, fragment.statements))
579-
for domain, stmts in self.sample_stmts.items():
580-
new_fragment.add_statements(stmts)
581-
for stmt in stmts:
582-
new_fragment.add_driver(stmt.lhs, domain)
583-
if self.initial is not None:
584-
new_fragment.add_subfragment(Instance("$initstate", o_Y=self.initial))
585-
586-
587499
class SwitchCleaner(StatementVisitor):
588500
def on_ignore(self, stmt):
589501
return stmt

amaranth/sim/_pyrtl.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ def on_AnyConst(self, value):
101101
def on_AnySeq(self, value):
102102
raise NotImplementedError # :nocov:
103103

104-
def on_Sample(self, value):
105-
raise NotImplementedError # :nocov:
106-
107104
def on_Initial(self, value):
108105
raise NotImplementedError # :nocov:
109106

0 commit comments

Comments
 (0)