From 24a392887af19a9d013252759ec209d5a91a378a Mon Sep 17 00:00:00 2001 From: Wanda Date: Wed, 14 Feb 2024 07:13:12 +0100 Subject: [PATCH] Implement RFC 43: Rename `reset=` to `init=`. --- amaranth/hdl/_ast.py | 95 +++++++++++++++++++----------- amaranth/hdl/_dsl.py | 23 +++++--- amaranth/hdl/_ir.py | 10 ++-- amaranth/hdl/_mem.py | 2 +- amaranth/hdl/_xfrm.py | 4 +- amaranth/lib/cdc.py | 24 ++++++-- amaranth/lib/crc/__init__.py | 2 +- amaranth/lib/data.py | 22 +++---- amaranth/lib/enum.py | 4 +- amaranth/lib/wiring.py | 104 +++++++++++++++++++-------------- amaranth/sim/_pyrtl.py | 2 +- amaranth/sim/core.py | 6 +- amaranth/sim/pysim.py | 6 +- amaranth/vendor/_xilinx.py | 2 +- docs/changes.rst | 6 +- docs/guide.rst | 20 +++---- docs/stdlib/wiring.rst | 2 +- examples/basic/ctr.py | 2 +- examples/basic/ctr_en.py | 2 +- examples/basic/por.py | 2 +- examples/basic/uart.py | 4 +- tests/test_hdl_ast.py | 108 ++++++++++++++++++++++------------- tests/test_hdl_dsl.py | 57 ++++++++++++++++-- tests/test_hdl_mem.py | 4 +- tests/test_hdl_rec.py | 8 +-- tests/test_hdl_xfrm.py | 4 +- tests/test_lib_cdc.py | 38 ++++++++++-- tests/test_lib_data.py | 54 +++++++++--------- tests/test_lib_wiring.py | 103 ++++++++++++++++++++------------- tests/test_sim.py | 32 +++++------ 30 files changed, 476 insertions(+), 276 deletions(-) diff --git a/amaranth/hdl/_ast.py b/amaranth/hdl/_ast.py index 5eaf56f..dfa802f 100644 --- a/amaranth/hdl/_ast.py +++ b/amaranth/hdl/_ast.py @@ -173,7 +173,7 @@ class ShapeCastable: .. code:: - value_like = Signal(shape_castable, reset=initializer) + value_like = Signal(shape_castable, init=initializer) The code above is equivalent to: @@ -181,7 +181,7 @@ class ShapeCastable: value_like = shape_castable(Signal( shape_castable.as_shape(), - reset=shape_castable.const(initializer) + init=shape_castable.const(initializer) )) Note that the :py:`shape_castable(x)` syntax performs :py:`shape_castable.__call__(x)`. @@ -1731,15 +1731,15 @@ class Signal(Value, DUID, metaclass=_SignalMeta): name : str Name hint for this signal. If ``None`` (default) the name is inferred from the variable name this ``Signal`` is assigned to. - reset : int or integral Enum + init : int or integral Enum Reset (synchronous) or default (combinatorial) value. When this ``Signal`` is assigned to in synchronous context and the corresponding clock domain is reset, the ``Signal`` assumes the given value. When this ``Signal`` is unassigned in combinatorial context (due to conditional assignments not being taken), the ``Signal`` - assumes its ``reset`` value. Defaults to 0. + assumes its ``init`` value. Defaults to 0. reset_less : bool If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements. - The ``reset`` value is only used as a combinatorial default or as the initial value. + The ``init`` value is only used as a combinatorial default or as the initial value. Defaults to ``False``. attrs : dict Dictionary of synthesis attributes. @@ -1754,13 +1754,13 @@ class Signal(Value, DUID, metaclass=_SignalMeta): width : int signed : bool name : str - reset : int + init : int reset_less : bool attrs : dict decoder : function """ - def __init__(self, shape=None, *, name=None, reset=None, reset_less=False, + def __init__(self, shape=None, *, name=None, init=None, reset=None, reset_less=False, attrs=None, decoder=None, src_loc_at=0): super().__init__(src_loc_at=src_loc_at) @@ -1776,53 +1776,61 @@ class Signal(Value, DUID, metaclass=_SignalMeta): self.width = shape.width self.signed = shape.signed - orig_reset = reset + # TODO(amaranth-0.7): remove + if reset is not None: + if init is not None: + raise ValueError("Cannot specify both `reset` and `init`") + warnings.warn("`reset=` is deprecated, use `init=` instead", + DeprecationWarning, stacklevel=2) + init = reset + + orig_init = init if isinstance(orig_shape, ShapeCastable): try: - reset = Const.cast(orig_shape.const(reset)) + init = Const.cast(orig_shape.const(init)) except Exception: - raise TypeError("Reset value must be a constant initializer of {!r}" + raise TypeError("Initial value must be a constant initializer of {!r}" .format(orig_shape)) - if reset.shape() != Shape.cast(orig_shape): + if init.shape() != Shape.cast(orig_shape): raise ValueError("Constant returned by {!r}.const() must have the shape that " "it casts to, {!r}, and not {!r}" .format(orig_shape, Shape.cast(orig_shape), - reset.shape())) + init.shape())) else: - if reset is None: - reset = 0 + if init is None: + init = 0 try: - reset = Const.cast(reset) + init = Const.cast(init) except TypeError: - raise TypeError("Reset value must be a constant-castable expression, not {!r}" - .format(orig_reset)) + raise TypeError("Initial value must be a constant-castable expression, not {!r}" + .format(orig_init)) # Avoid false positives for all-zeroes and all-ones - if orig_reset is not None and not (isinstance(orig_reset, int) and orig_reset in (0, -1)): - if reset.shape().signed and not self.signed: + if orig_init is not None and not (isinstance(orig_init, int) and orig_init in (0, -1)): + if init.shape().signed and not self.signed: warnings.warn( - message="Reset value {!r} is signed, but the signal shape is {!r}" - .format(orig_reset, shape), + message="Initial value {!r} is signed, but the signal shape is {!r}" + .format(orig_init, shape), category=SyntaxWarning, stacklevel=2) - elif (reset.shape().width > self.width or - reset.shape().width == self.width and - self.signed and not reset.shape().signed): + elif (init.shape().width > self.width or + init.shape().width == self.width and + self.signed and not init.shape().signed): warnings.warn( - message="Reset value {!r} will be truncated to the signal shape {!r}" - .format(orig_reset, shape), + message="Initial value {!r} will be truncated to the signal shape {!r}" + .format(orig_init, shape), category=SyntaxWarning, stacklevel=2) - self.reset = reset.value + self.init = init.value self.reset_less = bool(reset_less) - if isinstance(orig_shape, range) and orig_reset is not None and orig_reset not in orig_shape: - if orig_reset == orig_shape.stop: + if isinstance(orig_shape, range) and orig_init is not None and orig_init not in orig_shape: + if orig_init == orig_shape.stop: raise SyntaxError( - f"Reset value {orig_reset!r} equals the non-inclusive end of the signal " + f"Initial value {orig_init!r} equals the non-inclusive end of the signal " f"shape {orig_shape!r}; this is likely an off-by-one error") else: raise SyntaxError( - f"Reset value {orig_reset!r} is not within the signal shape {orig_shape!r}") + f"Initial value {orig_init!r} is not within the signal shape {orig_shape!r}") self.attrs = OrderedDict(() if attrs is None else attrs) @@ -1850,6 +1858,18 @@ class Signal(Value, DUID, metaclass=_SignalMeta): # Any other case is formatted as a plain integer. self._value_repr = (Repr(FormatInt(), self),) + @property + def reset(self): + warnings.warn("`Signal.reset` is deprecated, use `Signal.init` instead", + DeprecationWarning, stacklevel=2) + return self.init + + @reset.setter + def reset(self, value): + warnings.warn("`Signal.reset` is deprecated, use `Signal.init` instead", + DeprecationWarning, stacklevel=2) + self.init = value + @property def decoder(self): return self._decoder @@ -1873,7 +1893,7 @@ class Signal(Value, DUID, metaclass=_SignalMeta): self._decoder = enum_decoder @classmethod - def like(cls, other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs): + def like(cls, other, *, name=None, name_suffix=None, init=None, reset=None, src_loc_at=0, **kwargs): """Create Signal based on another. Parameters @@ -1887,15 +1907,24 @@ class Signal(Value, DUID, metaclass=_SignalMeta): new_name = other.name + str(name_suffix) else: new_name = tracer.get_var_name(depth=2 + src_loc_at, default="$like") + # TODO(amaranth-0.7): remove + if reset is not None: + if init is not None: + raise ValueError("Cannot specify both `reset` and `init`") + warnings.warn("`reset=` is deprecated, use `init=` instead", + DeprecationWarning, stacklevel=2) + init = reset if isinstance(other, ValueCastable): shape = other.shape() else: shape = Value.cast(other).shape() kw = dict(shape=shape, name=new_name) if isinstance(other, Signal): - kw.update(reset=other.reset, reset_less=other.reset_less, + kw.update(init=other.init, reset_less=other.reset_less, attrs=other.attrs, decoder=other.decoder) kw.update(kwargs) + if init is not None: + kw["init"] = init return cls(**kw, src_loc_at=1 + src_loc_at) def shape(self): diff --git a/amaranth/hdl/_dsl.py b/amaranth/hdl/_dsl.py index 8c2d423..9629fe2 100644 --- a/amaranth/hdl/_dsl.py +++ b/amaranth/hdl/_dsl.py @@ -374,14 +374,21 @@ class Module(_ModuleBuilderRoot, Elaboratable): self._statements = _outer_case @contextmanager - def FSM(self, reset=None, domain="sync", name="fsm"): + def FSM(self, init=None, domain="sync", name="fsm", *, reset=None): self._check_context("FSM", context=None) if domain == "comb": raise ValueError(f"FSM may not be driven by the '{domain}' domain") + # TODO(amaranth-0.7): remove + if reset is not None: + if init is not None: + raise ValueError("Cannot specify both `reset` and `init`") + warnings.warn("`reset=` is deprecated, use `init=` instead", + DeprecationWarning, stacklevel=2) + init = reset fsm_data = self._set_ctrl("FSM", { "name": name, "signal": Signal(name=f"{name}_state", src_loc_at=2), - "reset": reset, + "init": init, "domain": domain, "encoding": OrderedDict(), "decoding": OrderedDict(), @@ -489,17 +496,17 @@ class Module(_ModuleBuilderRoot, Elaboratable): src_loc=src_loc, case_src_locs=switch_case_src_locs)) if name == "FSM": - fsm_signal, fsm_reset, fsm_encoding, fsm_decoding, fsm_states = \ - data["signal"], data["reset"], data["encoding"], data["decoding"], data["states"] + fsm_signal, fsm_init, fsm_encoding, fsm_decoding, fsm_states = \ + data["signal"], data["init"], data["encoding"], data["decoding"], data["states"] fsm_state_src_locs = data["state_src_locs"] if not fsm_states: return fsm_signal.width = bits_for(len(fsm_encoding) - 1) - if fsm_reset is None: - fsm_signal.reset = fsm_encoding[next(iter(fsm_states))] + if fsm_init is None: + fsm_signal.init = fsm_encoding[next(iter(fsm_states))] else: - fsm_signal.reset = fsm_encoding[fsm_reset] - # The FSM is encoded such that the state with encoding 0 is always the reset state. + fsm_signal.init = fsm_encoding[fsm_init] + # The FSM is encoded such that the state with encoding 0 is always the init state. fsm_decoding.update((n, s) for s, n in fsm_encoding.items()) fsm_signal.decoder = lambda n: f"{fsm_decoding[n]}/{n}" diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py index 5138de0..f68a3ad 100644 --- a/amaranth/hdl/_ir.py +++ b/amaranth/hdl/_ir.py @@ -691,8 +691,8 @@ class NetlistDriver: def emit_value(self, builder): if self.domain is None: - reset = _ast.Const(self.signal.reset, self.signal.width) - default, _signed = builder.emit_rhs(self.module_idx, reset) + init = _ast.Const(self.signal.init, self.signal.width) + default, _signed = builder.emit_rhs(self.module_idx, init) else: default = builder.emit_signal(self.signal) if len(self.assignments) == 1: @@ -1184,7 +1184,7 @@ class NetlistEmitter: arst = _nir.Net.from_const(0) cell = _nir.FlipFlop(driver.module_idx, data=value, - init=driver.signal.reset, + init=driver.signal.init, clk=clk, clk_edge=driver.domain.clk_edge, arst=arst, @@ -1198,12 +1198,12 @@ class NetlistEmitter: src_loc = driver.signal.src_loc self.connect(self.emit_signal(driver.signal), value, src_loc=src_loc) - # Connect all undriven signal bits to their reset values. This can only happen for entirely + # Connect all undriven signal bits to their initial values. This can only happen for entirely # undriven signals, or signals that are partially driven by instances. for signal, value in self.netlist.signals.items(): for bit, net in enumerate(value): if net.is_late and net not in self.netlist.connections: - self.netlist.connections[net] = _nir.Net.from_const((signal.reset >> bit) & 1) + self.netlist.connections[net] = _nir.Net.from_const((signal.init >> bit) & 1) def emit_fragment(self, fragment: _ir.Fragment, parent_module_idx: 'int | None'): from . import _mem diff --git a/amaranth/hdl/_mem.py b/amaranth/hdl/_mem.py index b4a56e2..8be78fe 100644 --- a/amaranth/hdl/_mem.py +++ b/amaranth/hdl/_mem.py @@ -262,7 +262,7 @@ class ReadPort(Elaboratable): self.data = Signal(memory.width, name=f"{memory.name}_r_data", src_loc_at=1 + src_loc_at) if self.domain != "comb": - self.en = Signal(name=f"{memory.name}_r_en", reset=1, + self.en = Signal(name=f"{memory.name}_r_en", init=1, src_loc_at=1 + src_loc_at) else: self.en = Const(1) diff --git a/amaranth/hdl/_xfrm.py b/amaranth/hdl/_xfrm.py index ec3c057..1356f35 100644 --- a/amaranth/hdl/_xfrm.py +++ b/amaranth/hdl/_xfrm.py @@ -521,7 +521,7 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer) domain = fragment.domains[domain_name] if domain.rst is None: continue - stmts = [signal.eq(Const(signal.reset, signal.width)) + stmts = [signal.eq(Const(signal.init, signal.width)) for signal in signals if not signal.reset_less] fragment.add_statements(domain_name, Switch(domain.rst, {1: stmts})) @@ -559,7 +559,7 @@ class _ControlInserter(FragmentTransformer): class ResetInserter(_ControlInserter): def _insert_control(self, fragment, domain, signals): - stmts = [s.eq(Const(s.reset, s.width)) for s in signals if not s.reset_less] + stmts = [s.eq(Const(s.init, s.width)) for s in signals if not s.reset_less] fragment.add_statements(domain, Switch(self.controls[domain], {1: stmts}, src_loc=self.src_loc)) diff --git a/amaranth/lib/cdc.py b/amaranth/lib/cdc.py index aea0e76..b2a7cdd 100644 --- a/amaranth/lib/cdc.py +++ b/amaranth/lib/cdc.py @@ -1,3 +1,5 @@ +import warnings + from .. import * @@ -26,8 +28,8 @@ class FFSynchronizer(Elaboratable): Signal connected to synchroniser output. o_domain : str Name of output clock domain. - reset : int - Reset value of the flip-flops. On FPGAs, even if ``reset_less`` is ``True``, + init : int + Initial and reset value of the flip-flops. On FPGAs, even if ``reset_less`` is ``True``, the :class:`FFSynchronizer` is still set to this value during initialization. reset_less : bool If ``True`` (the default), this :class:`FFSynchronizer` is unaffected by ``o_domain`` @@ -62,14 +64,24 @@ class FFSynchronizer(Elaboratable): Define the ``get_ff_sync`` platform method to override the implementation of :class:`FFSynchronizer`, e.g. to instantiate library cells directly. """ - def __init__(self, i, o, *, o_domain="sync", reset=0, reset_less=True, stages=2, + def __init__(self, i, o, *, o_domain="sync", init=None, reset=None, reset_less=True, stages=2, max_input_delay=None): _check_stages(stages) self.i = i self.o = o - self._reset = reset + # TODO(amaranth-0.7): remove + if reset is not None: + if init is not None: + raise ValueError("Cannot specify both `reset` and `init`") + warnings.warn("`reset=` is deprecated, use `init=` instead", + DeprecationWarning, stacklevel=2) + init = reset + if init is None: + init = 0 + + self._init = init self._reset_less = reset_less self._o_domain = o_domain self._stages = stages @@ -87,7 +99,7 @@ class FFSynchronizer(Elaboratable): m = Module() flops = [Signal(self.i.shape(), name=f"stage{index}", - reset=self._reset, reset_less=self._reset_less) + init=self._init, reset_less=self._reset_less) for index in range(self._stages)] for i, o in zip((self.i, *flops), flops): m.d[self._o_domain] += o.eq(i) @@ -161,7 +173,7 @@ class AsyncFFSynchronizer(Elaboratable): m = Module() m.domains += ClockDomain("async_ff", async_reset=True, local=True) - flops = [Signal(1, name=f"stage{index}", reset=1) + flops = [Signal(1, name=f"stage{index}", init=1) for index in range(self._stages)] for i, o in zip((0, *flops), flops): m.d.async_ff += o.eq(i) diff --git a/amaranth/lib/crc/__init__.py b/amaranth/lib/crc/__init__.py index 8683c09..9387c0b 100644 --- a/amaranth/lib/crc/__init__.py +++ b/amaranth/lib/crc/__init__.py @@ -383,7 +383,7 @@ class Processor(Elaboratable): def elaborate(self, platform): m = Module() - crc_reg = Signal(self._crc_width, reset=self._initial_crc.value) + crc_reg = Signal(self._crc_width, init=self._initial_crc.value) data_in = Signal(self._data_width) # Optionally bit-reflect input words. diff --git a/amaranth/lib/data.py b/amaranth/lib/data.py index 978f83e..afd775e 100644 --- a/amaranth/lib/data.py +++ b/amaranth/lib/data.py @@ -812,7 +812,7 @@ class _AggregateMeta(ShapeCastable, type): cls = type.__new__(metacls, name, bases, namespace) if cls.__layout_cls is UnionLayout: if len(default) > 1: - raise ValueError("Reset value for at most one field can be provided for " + raise ValueError("Initial value for at most one field can be provided for " "a union class (specified: {})" .format(", ".join(default.keys()))) cls.__layout = cls.__layout_cls(layout) @@ -855,12 +855,12 @@ class Struct(View, metaclass=_AggregateMeta): """Structures defined with annotations. The :class:`Struct` base class is a subclass of :class:`View` that provides a concise way - to describe the structure layout and reset values for the fields using Python + to describe the structure layout and initial values for the fields using Python :term:`variable annotations `. Any annotations containing :ref:`shape-like ` objects are used, in the order in which they appear in the source code, to construct a :class:`StructLayout`. - The values assigned to such annotations are used to populate the reset value of the signal + The values assigned to such annotations are used to populate the initial value of the signal created by the view. Any other annotations are kept as-is. .. testsetup:: @@ -907,15 +907,15 @@ class Struct(View, metaclass=_AggregateMeta): >>> flt.is_subnormal() (== (slice (sig flt) 23:31) (const 1'd0)) - The reset values for individual fields can be overridden during instantiation: + The initial values for individual fields can be overridden during instantiation: .. doctest:: - >>> hex(Signal(IEEE754Single).as_value().reset) + >>> hex(Signal(IEEE754Single).as_value().init) '0x3f800000' - >>> hex(Signal(IEEE754Single, reset={'sign': 1}).as_value().reset) + >>> hex(Signal(IEEE754Single, init={'sign': 1}).as_value().init) '0xbf800000' - >>> hex(Signal(IEEE754Single, reset={'exponent': 0}).as_value().reset) + >>> hex(Signal(IEEE754Single, init={'exponent': 0}).as_value().init) '0x0' Classes inheriting from :class:`Struct` can be used as base classes. The only restrictions @@ -964,8 +964,8 @@ class Union(View, metaclass=_AggregateMeta): annotation>`. It is very similar to the :class:`Struct` class, except that its layout is a :class:`UnionLayout`. - A :class:`Union` can have only one field with a specified reset value. If a reset value is - explicitly provided during instantiation, it overrides the reset value specified with + A :class:`Union` can have only one field with a specified initial value. If an initial value is + explicitly provided during instantiation, it overrides the initial value specified with an annotation: .. testcode:: @@ -976,9 +976,9 @@ class Union(View, metaclass=_AggregateMeta): .. doctest:: - >>> Signal(VarInt).as_value().reset + >>> Signal(VarInt).as_value().init 256 - >>> Signal(VarInt, reset={'int8': 10}).as_value().reset + >>> Signal(VarInt, init={'int8': 10}).as_value().init 10 """ _AggregateMeta__layout_cls = UnionLayout diff --git a/amaranth/lib/enum.py b/amaranth/lib/enum.py index 84b922d..8cb026c 100644 --- a/amaranth/lib/enum.py +++ b/amaranth/lib/enum.py @@ -165,8 +165,8 @@ class EnumMeta(ShapeCastable, py_enum.EnumMeta): def const(cls, init): # Same considerations apply as above. if init is None: - # Signal with unspecified reset value passes ``None`` to :meth:`const`. - # Before RFC 9 was implemented, the unspecified reset value was 0, so this keeps + # Signal with unspecified initial value passes ``None`` to :meth:`const`. + # Before RFC 9 was implemented, the unspecified initial value was 0, so this keeps # the old behavior intact. member = cls(0) else: diff --git a/amaranth/lib/wiring.py b/amaranth/lib/wiring.py index 539c7b0..6b82cb4 100644 --- a/amaranth/lib/wiring.py +++ b/amaranth/lib/wiring.py @@ -59,16 +59,23 @@ class Flow(enum.Enum): return Out assert False # :nocov: - def __call__(self, description, *, reset=None, src_loc_at=0): + def __call__(self, description, *, init=None, reset=None, src_loc_at=0): """Create a :class:`Member` with this data flow and the provided description and - reset value. + initial value. Returns ------- :class:`Member` - :py:`Member(self, description, reset=reset)` + :py:`Member(self, description, init=init)` """ - return Member(self, description, reset=reset, src_loc_at=src_loc_at + 1) + # TODO(amaranth-0.7): remove + if reset is not None: + if init is not None: + raise ValueError("Cannot specify both `reset` and `init`") + warnings.warn("`reset=` is deprecated, use `init=` instead", + DeprecationWarning, stacklevel=2) + init = reset + return Member(self, description, init=init, src_loc_at=src_loc_at + 1) def __repr__(self): return self.name @@ -98,17 +105,24 @@ class Member: object (in which case it is created as a port member). After creation the :class:`Member` instance cannot be modified. - When a :class:`Signal` is created from a description of a port member, the signal's reset value + When a :class:`Signal` is created from a description of a port member, the signal's initial value is taken from the member description. If this signal is never explicitly assigned a value, it - will equal ``reset``. + will equal ``init``. Although instances can be created directly, most often they will be created through :data:`In` and :data:`Out`, e.g. :py:`In(unsigned(1))` or :py:`Out(stream.Signature(RGBPixel))`. """ - def __init__(self, flow, description, *, reset=None, _dimensions=(), src_loc_at=0): + def __init__(self, flow, description, *, init=None, reset=None, _dimensions=(), src_loc_at=0): + # TODO(amaranth-0.7): remove + if reset is not None: + if init is not None: + raise ValueError("Cannot specify both `reset` and `init`") + warnings.warn("`reset=` is deprecated, use `init=` instead", + DeprecationWarning, stacklevel=2) + init = reset self._flow = flow self._description = description - self._reset = reset + self._init = init self._dimensions = _dimensions self.src_loc = tracer.get_src_loc(src_loc_at=src_loc_at) @@ -121,23 +135,23 @@ class Member: except TypeError as e: raise TypeError(f"Port member description must be a shape-castable object or " f"a signature, not {description!r}") from e - # This mirrors the logic that handles Signal(reset=). + # This mirrors the logic that handles Signal(init=). # TODO: We need a simpler way to check for "is this a valid constant initializer" if issubclass(type(self._description), ShapeCastable): try: - self._reset_as_const = Const.cast(self._description.const(self._reset)) + self._init_as_const = Const.cast(self._description.const(self._init)) except Exception as e: - raise TypeError(f"Port member reset value {self._reset!r} is not a valid " + raise TypeError(f"Port member initial value {self._init!r} is not a valid " f"constant initializer for {self._description}") from e else: try: - self._reset_as_const = Const.cast(reset or 0) + self._init_as_const = Const.cast(init or 0) except TypeError: - raise TypeError(f"Port member reset value {self._reset!r} is not a valid " + raise TypeError(f"Port member initial value {self._init!r} is not a valid " f"constant initializer for {shape}") if self.is_signature: - if self._reset is not None: - raise ValueError(f"A signature member cannot have a reset value") + if self._init is not None: + raise ValueError(f"A signature member cannot have an initial value") def flip(self): """Flip the data flow of this member. @@ -148,7 +162,7 @@ class Member: A new :py:`member` with :py:`member.flow` equal to :py:`self.flow.flip()`, and identical to :py:`self` other than that. """ - return Member(self._flow.flip(), self._description, reset=self._reset, + return Member(self._flow.flip(), self._description, init=self._init, _dimensions=self._dimensions) def array(self, *dimensions): @@ -175,7 +189,7 @@ class Member: if not (isinstance(dimension, int) and dimension >= 0): raise TypeError(f"Member array dimensions must be non-negative integers, " f"not {dimension!r}") - return Member(self._flow, self._description, reset=self._reset, + return Member(self._flow, self._description, init=self._init, _dimensions=(*dimensions, *self._dimensions)) @property @@ -231,13 +245,13 @@ class Member: return self._description @property - def reset(self): - """Reset value of a port member. + def init(self): + """Initial value of a port member. Returns ------- :ref:`const-castable object ` - The reset value that was provided when constructing this :class:`Member`. + The initial value that was provided when constructing this :class:`Member`. Raises ------ @@ -245,8 +259,14 @@ class Member: If :py:`self` describes a signature member. """ if self.is_signature: - raise AttributeError(f"A signature member does not have a reset value") - return self._reset + raise AttributeError(f"A signature member does not have an initial value") + return self._init + + @property + def reset(self): + warnings.warn("`Member.reset` is deprecated, use `Member.init` instead", + DeprecationWarning, stacklevel=2) + return self.init @property def signature(self): @@ -288,16 +308,16 @@ class Member: return (type(other) is Member and self._flow == other._flow and self._description == other._description and - self._reset == other._reset and + self._init == other._init and self._dimensions == other._dimensions) def __repr__(self): - reset_repr = dimensions_repr = "" - if self._reset: - reset_repr = f", reset={self._reset!r}" + init_repr = dimensions_repr = "" + if self._init: + init_repr = f", init={self._init!r}" if self._dimensions: dimensions_repr = f".array({', '.join(map(str, self._dimensions))})" - return f"{self._flow!r}({self._description!r}{reset_repr}){dimensions_repr}" + return f"{self._flow!r}({self._description!r}{init_repr}){dimensions_repr}" @final @@ -470,7 +490,7 @@ class SignatureMembers(Mapping): def create(self, *, path=None, src_loc_at=0): """Create members from their descriptions. - For each port member, this function creates a :class:`Signal` with the shape and reset + For each port member, this function creates a :class:`Signal` with the shape and initial value taken from the member description, and the name constructed from the :ref:`paths ` to the member (by concatenating path items with a double underscore, ``__``). @@ -497,7 +517,7 @@ class SignatureMembers(Mapping): # Ideally we would keep both source locations here, but the .src_loc attribute # data structure doesn't currently support that, so keep the more important one: # the one with the name of the signal (the `In()`/`Out()` call site.) - signal = Signal(member.shape, reset=member.reset, src_loc_at=1 + src_loc_at, + signal = Signal(member.shape, init=member.init, src_loc_at=1 + src_loc_at, name="__".join(str(item) for item in path)) signal.src_loc = member.src_loc return signal @@ -775,7 +795,7 @@ class Signature(metaclass=SignatureMeta): def iter_member(value, *, path): if member.is_port: - yield path, Member(member.flow, member.shape, reset=member.reset), value + yield path, Member(member.flow, member.shape, init=member.init), value elif member.is_signature: for sub_path, sub_member, sub_value in member.signature.flatten(value): if member.flow == In: @@ -816,7 +836,7 @@ class Signature(metaclass=SignatureMeta): * for port members, is a :ref:`value-like ` object casting to a :class:`Signal` or a :class:`Const` whose width and signedness is the same as that of the member, and (in case of a :class:`Signal`) which is not reset-less and whose - reset value is that of the member; + initial value is that of the member; * for signature members, matches the description in the signature as verified by :meth:`Signature.is_compliant`. @@ -878,11 +898,11 @@ class Signature(metaclass=SignatureMeta): f"the shape {_format_shape(attr_shape)}") return False if isinstance(attr_value_cast, Signal): - if attr_value_cast.reset != member._reset_as_const.value: + if attr_value_cast.init != member._init_as_const.value: if reasons is not None: reasons.append(f"{_format_path(path)} is expected to have " - f"the reset value {member.reset!r}, but it has " - f"the reset value {attr_value_cast.reset!r}") + f"the initial value {member.init!r}, but it has " + f"the initial value {attr_value_cast.init!r}") return False if attr_value_cast.reset_less: if reasons is not None: @@ -1343,7 +1363,7 @@ def connect(m, *args, **kwargs): * Every interface object must have the same set of port members, and they must have the same :meth:`dimensions `. - * For each path, the port members of every interface object must have the same width and reset + * For each path, the port members of every interface object must have the same width and initial value (for port members corresponding to signals) or constant value (for port members corresponding to constants). Signedness may differ. * For each path, at most one interface object must have the corresponding port member be @@ -1486,8 +1506,8 @@ def connect(m, *args, **kwargs): is_first = False first_path = path first_member_shape = member.shape - first_member_reset = member.reset - first_member_reset_as_const = member._reset_as_const + first_member_init = member.init + first_member_init_as_const = member._init_as_const continue if Shape.cast(first_member_shape).width != Shape.cast(member_shape).width: raise ConnectionError( @@ -1496,13 +1516,13 @@ def connect(m, *args, **kwargs): f"shape {_format_shape(member_shape)} because the shape widths " f"({Shape.cast(first_member_shape).width} and " f"{Shape.cast(member_shape).width}) do not match") - if first_member_reset_as_const.value != member._reset_as_const.value: + if first_member_init_as_const.value != member._init_as_const.value: raise ConnectionError( - f"Cannot connect together the member {_format_path(first_path)} with reset " - f"value {first_member_reset!r} and the member {_format_path(path)} with reset " - f"value {member.reset} because the reset values do not match") + f"Cannot connect together the member {_format_path(first_path)} with initial " + f"value {first_member_init!r} and the member {_format_path(path)} with initial " + f"value {member.init} because the initial values do not match") # If there are no Out members, there is nothing to connect. The In members, while not - # explicitly connected, will stay at the same value since we ensured their reset values + # explicitly connected, will stay at the same value since we ensured their initial values # are all identical. if len(out_kind) == 0: continue diff --git a/amaranth/sim/_pyrtl.py b/amaranth/sim/_pyrtl.py index 7e52eea..2665bf0 100644 --- a/amaranth/sim/_pyrtl.py +++ b/amaranth/sim/_pyrtl.py @@ -436,7 +436,7 @@ class _FragmentCompiler: if domain_name == "comb": for signal in domain_signals: signal_index = self.state.get_signal(signal) - emitter.append(f"next_{signal_index} = {signal.reset}") + emitter.append(f"next_{signal_index} = {signal.init}") inputs = SignalSet() _StatementCompiler(self.state, emitter, inputs=inputs)(domain_stmts) diff --git a/amaranth/sim/core.py b/amaranth/sim/core.py index 0c7ecaa..b757d1d 100644 --- a/amaranth/sim/core.py +++ b/amaranth/sim/core.py @@ -83,7 +83,7 @@ class Simulator: def add_process(self, process): process = self._check_process(process) def wrapper(): - # Only start a bench process after comb settling, so that the reset values are correct. + # Only start a bench process after comb settling, so that the initial values are correct. yield object.__new__(Settle) yield from process() self._engine.add_coroutine_process(wrapper, default_cmd=None) @@ -188,7 +188,7 @@ class Simulator: if phase is None: # By default, delay the first edge by half period. This causes any synchronous activity - # to happen at a non-zero time, distinguishing it from the reset values in the waveform + # to happen at a non-zero time, distinguishing it from the initial values in the waveform # viewer. phase = period // 2 else: @@ -199,7 +199,7 @@ class Simulator: def reset(self): """Reset the simulation. - Assign the reset value to every signal in the simulation, and restart every user process. + Assign the initial value to every signal and memory in the simulation, and restart every user process. """ self._engine.reset() diff --git a/amaranth/sim/pysim.py b/amaranth/sim/pysim.py index cf98935..bedd951 100644 --- a/amaranth/sim/pysim.py +++ b/amaranth/sim/pysim.py @@ -99,7 +99,7 @@ class _VCDWriter: self.vcd_signal_vars[signal] = [] self.gtkw_signal_names[signal] = [] for repr in signal._value_repr: - var_init = self.eval_field(repr.value, signal, signal.reset) + var_init = self.eval_field(repr.value, signal, signal.init) if isinstance(repr.format, FormatInt): var_type = "wire" var_size = repr.value.shape().width @@ -250,7 +250,7 @@ class _PySignalState(BaseSignalState): self.signal = signal self.pending = pending self.waiters = {} - self.curr = self.next = signal.reset + self.curr = self.next = signal.init def set(self, value): if self.next == value: @@ -342,7 +342,7 @@ class _PySimulation(BaseSimulation): for signal, index in self.signals.items(): state = self.slots[index] assert isinstance(state, _PySignalState) - state.curr = state.next = signal.reset + state.curr = state.next = signal.init for index in self.memories.values(): state = self.slots[index] assert isinstance(state, _PyMemoryState) diff --git a/amaranth/vendor/_xilinx.py b/amaranth/vendor/_xilinx.py index 4338f0e..9d6fa7f 100644 --- a/amaranth/vendor/_xilinx.py +++ b/amaranth/vendor/_xilinx.py @@ -1174,7 +1174,7 @@ class XilinxPlatform(TemplatedPlatform): def get_ff_sync(self, ff_sync): m = Module() flops = [Signal(ff_sync.i.shape(), name=f"stage{index}", - reset=ff_sync._reset, reset_less=ff_sync._reset_less, + init=ff_sync._reset, reset_less=ff_sync._reset_less, attrs={"ASYNC_REG": "TRUE"}) for index in range(ff_sync._stages)] if self.toolchain == "Vivado": diff --git a/docs/changes.rst b/docs/changes.rst index 8d7908a..b60e15a 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -29,6 +29,7 @@ Apply the following changes to code written against Amaranth 0.4 to migrate it t * Replace uses of ``Value.matches()`` with no patterns with ``Const(1)`` * Update uses of ``amaranth.utils.log2_int(need_pow2=False)`` to :func:`amaranth.utils.ceil_log2` * Update uses of ``amaranth.utils.log2_int(need_pow2=True)`` to :func:`amaranth.utils.exact_log2` +* Update uses of ``reset=`` keyword argument to ``init=`` * Convert uses of ``Simulator.add_sync_process`` used as testbenches to ``Simulator.add_testbench`` * Convert other uses of ``Simulator.add_sync_process`` to ``Simulator.add_process`` @@ -39,11 +40,13 @@ Implemented RFCs .. _RFC 17: https://amaranth-lang.org/rfcs/0017-remove-log2-int.html .. _RFC 27: https://amaranth-lang.org/rfcs/0027-simulator-testbenches.html .. _RFC 39: https://amaranth-lang.org/rfcs/0039-empty-case.html +.. _RFC 43: https://amaranth-lang.org/rfcs/0043-rename-reset-to-init.html .. _RFC 46: https://amaranth-lang.org/rfcs/0046-shape-range-1.html * `RFC 17`_: Remove ``log2_int`` * `RFC 27`_: Testbench processes for the simulator * `RFC 39`_: Change semantics of no-argument ``m.Case()`` +* `RFC 43`_: Rename ``reset=`` to ``init=`` * `RFC 46`_: Change ``Shape.cast(range(1))`` to ``unsigned(0)`` @@ -56,9 +59,10 @@ Language changes * Added: :func:`amaranth.utils.ceil_log2`, :func:`amaranth.utils.exact_log2`. (`RFC 17`_) * Changed: ``m.Case()`` with no patterns is never active instead of always active. (`RFC 39`_) * Changed: ``Value.matches()`` with no patterns is ``Const(0)`` instead of ``Const(1)``. (`RFC 39`_) -* Changed: ``Signal(range(stop), reset=stop)`` warning has been changed into a hard error and made to trigger on any out-of range value. +* Changed: ``Signal(range(stop), init=stop)`` warning has been changed into a hard error and made to trigger on any out-of range value. * Changed: ``Signal(range(0))`` is now valid without a warning. * Changed: ``Shape.cast(range(1))`` is now ``unsigned(0)``. (`RFC 46`_) +* Changed: the ``reset=`` argument of :class:`Signal`, :meth:`Signal.like`, :class:`amaranth.lib.wiring.Member`, :class:`amaranth.lib.cdc.FFSynchronizer`, and ``m.FSM()`` has been renamed to ``init=``. (`RFC 43`_) * Deprecated: :func:`amaranth.utils.log2_int`. (`RFC 17`_) * Removed: (deprecated in 0.4) :meth:`Const.normalize`. (`RFC 5`_) * Removed: (deprecated in 0.4) :class:`Repl`. (`RFC 10`_) diff --git a/docs/guide.rst b/docs/guide.rst index 2a523e5..7478908 100644 --- a/docs/guide.rst +++ b/docs/guide.rst @@ -407,19 +407,17 @@ The names do not need to be unique; if two signals with the same name end up in Initial signal values --------------------- -Each signal has an *initial value*, specified with the ``reset=`` parameter. If the initial value is not specified explicitly, zero is used by default. An initial value can be specified with an integer or an enumeration member. +Each signal has an *initial value*, specified with the ``init=`` parameter. If the initial value is not specified explicitly, zero is used by default. An initial value can be specified with an integer or an enumeration member. Signals :ref:`assigned ` in a :ref:`combinatorial ` domain assume their initial value when none of the assignments are :ref:`active `. Signals assigned in a :ref:`synchronous ` domain assume their initial value after *power-on reset* and, unless the signal is :ref:`reset-less `, *explicit reset*. Signals that are used but never assigned are equivalent to constants of their initial value. -.. TODO: using "reset" for "initial value" is awful, let's rename it to "init" - .. doctest:: - >>> Signal(4).reset + >>> Signal(4).init 0 - >>> Signal(4, reset=5).reset + >>> Signal(4, init=5).init 5 - >>> Signal(Direction, reset=Direction.LEFT).reset + >>> Signal(Direction, init=Direction.LEFT).init 1 @@ -467,7 +465,7 @@ In contrast, code written in the Amaranth language *describes* computations on a .. doctest:: - >>> a = Signal(8, reset=5) + >>> a = Signal(8, init=5) >>> a + 1 (+ (sig a) (const 1'd1)) @@ -1190,11 +1188,11 @@ Simple `finite state machines `, which is specified using the :py:`with m.FSM(domain="dom")` argument. If not specified, it is the ``sync`` domain. For example, this definition is equivalent to the one at the beginning of this section: @@ -1255,7 +1253,7 @@ Consider the following code: .. testcode:: - a = Signal(8, reset=1) + a = Signal(8, init=1) with m.If(en): m.d.comb += a.eq(b + 1) @@ -1534,7 +1532,7 @@ The application of control flow modifiers in it causes the behavior of the final with m.If(en): m.d.sync += n.eq(n + 1) with m.If(rst): - m.d.sync += n.eq(n.reset) + m.d.sync += n.eq(n.init) m.d.comb += z.eq(n == 0) .. tip:: diff --git a/docs/stdlib/wiring.rst b/docs/stdlib/wiring.rst index 53ed31c..c40a07f 100644 --- a/docs/stdlib/wiring.rst +++ b/docs/stdlib/wiring.rst @@ -555,7 +555,7 @@ Signatures .. autodata:: Out .. autodata:: In -.. autoclass:: Member(flow, description, *, reset=None) +.. autoclass:: Member(flow, description, *, init=None) .. autoexception:: SignatureError diff --git a/examples/basic/ctr.py b/examples/basic/ctr.py index 4e44773..329d5f4 100644 --- a/examples/basic/ctr.py +++ b/examples/basic/ctr.py @@ -4,7 +4,7 @@ from amaranth.cli import main class Counter(Elaboratable): def __init__(self, width): - self.v = Signal(width, reset=2**width-1) + self.v = Signal(width, init=2**width-1) self.o = Signal() def elaborate(self, platform): diff --git a/examples/basic/ctr_en.py b/examples/basic/ctr_en.py index ae67c52..7cbd8fd 100644 --- a/examples/basic/ctr_en.py +++ b/examples/basic/ctr_en.py @@ -5,7 +5,7 @@ from amaranth.back import verilog class Counter(Elaboratable): def __init__(self, width): - self.v = Signal(width, reset=2**width-1) + self.v = Signal(width, init=2**width-1) self.o = Signal() self.en = Signal() diff --git a/examples/basic/por.py b/examples/basic/por.py index 1ed2773..0c64296 100644 --- a/examples/basic/por.py +++ b/examples/basic/por.py @@ -7,7 +7,7 @@ cd_por = ClockDomain(reset_less=True) cd_sync = ClockDomain() m.domains += cd_por, cd_sync -delay = Signal(range(256), reset=255) +delay = Signal(range(256), init=255) with m.If(delay != 0): m.d.por += delay.eq(delay - 1) m.d.comb += [ diff --git a/examples/basic/uart.py b/examples/basic/uart.py index 28ea60c..6003e8b 100644 --- a/examples/basic/uart.py +++ b/examples/basic/uart.py @@ -32,7 +32,7 @@ class UART(Elaboratable): m = Module() tx_phase = Signal(range(self.divisor)) - tx_shreg = Signal(1 + self.data_bits + 1, reset=-1) + tx_shreg = Signal(1 + self.data_bits + 1, init=-1) tx_count = Signal(range(len(tx_shreg) + 1)) m.d.comb += self.tx_o.eq(tx_shreg[0]) @@ -55,7 +55,7 @@ class UART(Elaboratable): ] rx_phase = Signal(range(self.divisor)) - rx_shreg = Signal(1 + self.data_bits + 1, reset=-1) + rx_shreg = Signal(1 + self.data_bits + 1, init=-1) rx_count = Signal(range(len(rx_shreg) + 1)) m.d.comb += self.rx_data.eq(rx_shreg[1:-1]) diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py index 9880ba5..6740c9e 100644 --- a/tests/test_hdl_ast.py +++ b/tests/test_hdl_ast.py @@ -1140,24 +1140,26 @@ class SignalTestCase(FHDLTestCase): s2 = Signal(name="sig") self.assertEqual(s2.name, "sig") - def test_reset(self): - s1 = Signal(4, reset=0b111, reset_less=True) - self.assertEqual(s1.reset, 0b111) + def test_init(self): + s1 = Signal(4, init=0b111, reset_less=True) + self.assertEqual(s1.init, 0b111) self.assertEqual(s1.reset_less, True) + s2 = Signal.like(s1, init=0b011) + self.assertEqual(s2.init, 0b011) - def test_reset_enum(self): - s1 = Signal(2, reset=UnsignedEnum.BAR) - self.assertEqual(s1.reset, 2) + def test_init_enum(self): + s1 = Signal(2, init=UnsignedEnum.BAR) + self.assertEqual(s1.init, 2) with self.assertRaisesRegex(TypeError, - r"^Reset value must be a constant-castable expression, " + r"^Initial value must be a constant-castable expression, " r"not $"): - Signal(1, reset=StringEnum.FOO) + Signal(1, init=StringEnum.FOO) - def test_reset_const_castable(self): - s1 = Signal(4, reset=Cat(Const(0, 1), Const(1, 1), Const(0, 2))) - self.assertEqual(s1.reset, 2) + def test_init_const_castable(self): + s1 = Signal(4, init=Cat(Const(0, 1), Const(1, 1), Const(0, 2))) + self.assertEqual(s1.init, 2) - def test_reset_shape_castable_const(self): + def test_init_shape_castable_const(self): class CastableFromHex(ShapeCastable): def as_shape(self): return unsigned(8) @@ -1168,54 +1170,80 @@ class SignalTestCase(FHDLTestCase): def const(self, init): return int(init, 16) - s1 = Signal(CastableFromHex(), reset="aa") - self.assertEqual(s1.reset, 0xaa) + s1 = Signal(CastableFromHex(), init="aa") + self.assertEqual(s1.init, 0xaa) with self.assertRaisesRegex(ValueError, r"^Constant returned by <.+?CastableFromHex.+?>\.const\(\) must have the shape " r"that it casts to, unsigned\(8\), and not unsigned\(1\)$"): - Signal(CastableFromHex(), reset="01") + Signal(CastableFromHex(), init="01") - def test_reset_shape_castable_enum_wrong(self): + def test_init_shape_castable_enum_wrong(self): class EnumA(AmaranthEnum, shape=1): X = 1 with self.assertRaisesRegex(TypeError, - r"^Reset value must be a constant initializer of $"): - Signal(EnumA) # implied reset=0 + r"^Initial value must be a constant initializer of $"): + Signal(EnumA) # implied init=0 - def test_reset_signed_mismatch(self): + def test_init_signed_mismatch(self): with self.assertWarnsRegex(SyntaxWarning, - r"^Reset value -2 is signed, but the signal shape is unsigned\(2\)$"): - Signal(unsigned(2), reset=-2) + r"^Initial value -2 is signed, but the signal shape is unsigned\(2\)$"): + Signal(unsigned(2), init=-2) - def test_reset_wrong_too_wide(self): + def test_init_wrong_too_wide(self): with self.assertWarnsRegex(SyntaxWarning, - r"^Reset value 2 will be truncated to the signal shape unsigned\(1\)$"): - Signal(unsigned(1), reset=2) + r"^Initial value 2 will be truncated to the signal shape unsigned\(1\)$"): + Signal(unsigned(1), init=2) with self.assertWarnsRegex(SyntaxWarning, - r"^Reset value 1 will be truncated to the signal shape signed\(1\)$"): - Signal(signed(1), reset=1) + r"^Initial value 1 will be truncated to the signal shape signed\(1\)$"): + Signal(signed(1), init=1) with self.assertWarnsRegex(SyntaxWarning, - r"^Reset value -2 will be truncated to the signal shape signed\(1\)$"): - Signal(signed(1), reset=-2) + r"^Initial value -2 will be truncated to the signal shape signed\(1\)$"): + Signal(signed(1), init=-2) - def test_reset_wrong_fencepost(self): + def test_init_wrong_fencepost(self): with self.assertRaisesRegex(SyntaxError, - r"^Reset value 10 equals the non-inclusive end of the signal shape " + r"^Initial value 10 equals the non-inclusive end of the signal shape " r"range\(0, 10\); this is likely an off-by-one error$"): - Signal(range(0, 10), reset=10) + Signal(range(0, 10), init=10) with self.assertRaisesRegex(SyntaxError, - r"^Reset value 0 equals the non-inclusive end of the signal shape " + r"^Initial value 0 equals the non-inclusive end of the signal shape " r"range\(0, 0\); this is likely an off-by-one error$"): - Signal(range(0), reset=0) + Signal(range(0), init=0) - def test_reset_wrong_range(self): + def test_init_wrong_range(self): with self.assertRaisesRegex(SyntaxError, - r"^Reset value 11 is not within the signal shape range\(0, 10\)$"): - Signal(range(0, 10), reset=11) + r"^Initial value 11 is not within the signal shape range\(0, 10\)$"): + Signal(range(0, 10), init=11) with self.assertRaisesRegex(SyntaxError, - r"^Reset value 0 is not within the signal shape range\(1, 10\)$"): - Signal(range(1, 10), reset=0) + r"^Initial value 0 is not within the signal shape range\(1, 10\)$"): + Signal(range(1, 10), init=0) + + def test_reset(self): + with self.assertWarnsRegex(DeprecationWarning, + r"^`reset=` is deprecated, use `init=` instead$"): + s1 = Signal(4, reset=0b111) + self.assertEqual(s1.init, 0b111) + with self.assertWarnsRegex(DeprecationWarning, + r"^`Signal.reset` is deprecated, use `Signal.init` instead$"): + self.assertEqual(s1.reset, 0b111) + with self.assertWarnsRegex(DeprecationWarning, + r"^`Signal.reset` is deprecated, use `Signal.init` instead$"): + s1.reset = 0b010 + self.assertEqual(s1.init, 0b010) + with self.assertWarnsRegex(DeprecationWarning, + r"^`reset=` is deprecated, use `init=` instead$"): + s2 = Signal.like(s1, reset=3) + self.assertEqual(s2.init, 3) + + def test_reset_wrong(self): + with self.assertRaisesRegex(ValueError, + r"^Cannot specify both `reset` and `init`$"): + Signal(4, reset=1, init=1) + s1 = Signal(4) + with self.assertRaisesRegex(ValueError, + r"^Cannot specify both `reset` and `init`$"): + Signal.like(s1, reset=1, init=1) def test_attrs(self): s1 = Signal() @@ -1232,8 +1260,8 @@ class SignalTestCase(FHDLTestCase): self.assertEqual(s1.shape(), unsigned(4)) s2 = Signal.like(Signal(range(-15, 1))) self.assertEqual(s2.shape(), signed(5)) - s3 = Signal.like(Signal(4, reset=0b111, reset_less=True)) - self.assertEqual(s3.reset, 0b111) + s3 = Signal.like(Signal(4, init=0b111, reset_less=True)) + self.assertEqual(s3.init, 0b111) self.assertEqual(s3.reset_less, True) s4 = Signal.like(Signal(attrs={"no_retiming": True})) self.assertEqual(s4.attrs, {"no_retiming": True}) diff --git a/tests/test_hdl_dsl.py b/tests/test_hdl_dsl.py index d3b47e7..c28491d 100644 --- a/tests/test_hdl_dsl.py +++ b/tests/test_hdl_dsl.py @@ -451,7 +451,7 @@ class DSLTestCase(FHDLTestCase): RED = 1 BLUE = 2 m = Module() - se = Signal(Color, reset=Color.RED) + se = Signal(Color, init=Color.RED) with m.Switch(se): with m.Case(Color.RED): m.d.comb += self.c1.eq(1) @@ -638,10 +638,10 @@ class DSLTestCase(FHDLTestCase): 1: "SECOND" })) - def test_FSM_reset(self): + def test_FSM_init(self): a = Signal() m = Module() - with m.FSM(reset="SECOND"): + with m.FSM(init="SECOND"): with m.State("FIRST"): m.d.comb += a.eq(0) m.next = "SECOND" @@ -670,6 +670,55 @@ class DSLTestCase(FHDLTestCase): ) ) """) + self.assertEqual(m._generated["fsm"].state.init, 1) + + def test_FSM_reset(self): + a = Signal() + m = Module() + with self.assertWarnsRegex(DeprecationWarning, + r"^`reset=` is deprecated, use `init=` instead$"): + with m.FSM(reset="SECOND"): + with m.State("FIRST"): + m.d.comb += a.eq(0) + m.next = "SECOND" + with m.State("SECOND"): + m.next = "FIRST" + m._flush() + self.assertRepr(m._statements["comb"], """ + ( + (switch (sig fsm_state) + (case 0 + (eq (sig a) (const 1'd0)) + ) + (case 1 ) + ) + ) + """) + self.assertRepr(m._statements["sync"], """ + ( + (switch (sig fsm_state) + (case 0 + (eq (sig fsm_state) (const 1'd1)) + ) + (case 1 + (eq (sig fsm_state) (const 1'd0)) + ) + ) + ) + """) + self.assertEqual(m._generated["fsm"].state.init, 1) + + def test_FSM_reset_wrong(self): + a = Signal() + m = Module() + with self.assertRaisesRegex(ValueError, + r"^Cannot specify both `reset` and `init`$"): + with m.FSM(reset="SECOND", init="SECOND"): + with m.State("FIRST"): + m.d.comb += a.eq(0) + m.next = "SECOND" + with m.State("SECOND"): + m.next = "FIRST" def test_FSM_ongoing(self): a = Signal() @@ -683,7 +732,7 @@ class DSLTestCase(FHDLTestCase): with m.State("SECOND"): pass m._flush() - self.assertEqual(m._generated["fsm"].state.reset, 1) + self.assertEqual(m._generated["fsm"].state.init, 1) self.maxDiff = 10000 self.assertRepr(m._statements["comb"], """ ( diff --git a/tests/test_hdl_mem.py b/tests/test_hdl_mem.py index 4af2e77..e0ec476 100644 --- a/tests/test_hdl_mem.py +++ b/tests/test_hdl_mem.py @@ -59,7 +59,7 @@ class MemoryTestCase(FHDLTestCase): self.assertEqual(len(rdport.data), 8) self.assertEqual(len(rdport.en), 1) self.assertIsInstance(rdport.en, Signal) - self.assertEqual(rdport.en.reset, 1) + self.assertEqual(rdport.en.init, 1) def test_read_port_non_transparent(self): mem = Memory(width=8, depth=4) @@ -69,7 +69,7 @@ class MemoryTestCase(FHDLTestCase): self.assertEqual(rdport.transparent, False) self.assertEqual(len(rdport.en), 1) self.assertIsInstance(rdport.en, Signal) - self.assertEqual(rdport.en.reset, 1) + self.assertEqual(rdport.en.init, 1) def test_read_port_asynchronous(self): mem = Memory(width=8, depth=4) diff --git a/tests/test_hdl_rec.py b/tests/test_hdl_rec.py index da96b13..b993a1c 100644 --- a/tests/test_hdl_rec.py +++ b/tests/test_hdl_rec.py @@ -199,11 +199,11 @@ class RecordTestCase(FHDLTestCase): self.assertEqual(r1.a.name, "r1__a") self.assertEqual(r1.b.name, "r1__b") self.assertEqual(r1.b.s.name, "r1__b__s") - r1.a.reset = 1 - r1.b.s.reset = 1 + r1.a.init = 1 + r1.b.s.init = 1 r2 = Record.like(r1) - self.assertEqual(r2.a.reset, 1) - self.assertEqual(r2.b.s.reset, 1) + self.assertEqual(r2.a.init, 1) + self.assertEqual(r2.b.s.init, 1) self.assertEqual(r2.a.name, "r2__a") self.assertEqual(r2.b.name, "r2__b") self.assertEqual(r2.b.s.name, "r2__b__s") diff --git a/tests/test_hdl_xfrm.py b/tests/test_hdl_xfrm.py index 56cc2ec..42b6103 100644 --- a/tests/test_hdl_xfrm.py +++ b/tests/test_hdl_xfrm.py @@ -247,8 +247,8 @@ class DomainLowererTestCase(FHDLTestCase): class ResetInserterTestCase(FHDLTestCase): def setUp(self): self.s1 = Signal() - self.s2 = Signal(reset=1) - self.s3 = Signal(reset=1, reset_less=True) + self.s2 = Signal(init=1) + self.s3 = Signal(init=1, reset_less=True) self.c1 = Signal() def test_reset_default(self): diff --git a/tests/test_lib_cdc.py b/tests/test_lib_cdc.py index b5439c4..d86a85c 100644 --- a/tests/test_lib_cdc.py +++ b/tests/test_lib_cdc.py @@ -35,10 +35,10 @@ class FFSynchronizerTestCase(FHDLTestCase): sim.add_process(process) sim.run() - def test_reset_value(self): - i = Signal(reset=1) + def test_init_value(self): + i = Signal(init=1) o = Signal() - frag = FFSynchronizer(i, o, reset=1) + frag = FFSynchronizer(i, o, init=1) sim = Simulator(frag) sim.add_clock(1e-6) @@ -54,6 +54,34 @@ class FFSynchronizerTestCase(FHDLTestCase): sim.add_process(process) sim.run() + def test_reset_value(self): + i = Signal(init=1) + o = Signal() + with self.assertWarnsRegex(DeprecationWarning, + r"^`reset=` is deprecated, use `init=` instead$"): + frag = FFSynchronizer(i, o, reset=1) + + sim = Simulator(frag) + sim.add_clock(1e-6) + def process(): + self.assertEqual((yield o), 1) + yield i.eq(0) + yield Tick() + self.assertEqual((yield o), 1) + yield Tick() + self.assertEqual((yield o), 1) + yield Tick() + self.assertEqual((yield o), 0) + sim.add_process(process) + sim.run() + + def test_reset_wrong(self): + i = Signal(init=1) + o = Signal() + with self.assertRaisesRegex(ValueError, + r"^Cannot specify both `reset` and `init`$"): + FFSynchronizer(i, o, reset=1, init=1) + class AsyncFFSynchronizerTestCase(FHDLTestCase): def test_stages_wrong(self): @@ -115,7 +143,7 @@ class AsyncFFSynchronizerTestCase(FHDLTestCase): sim.run() def test_neg_edge(self): - i = Signal(reset=1) + i = Signal(init=1) o = Signal() m = Module() m.domains += ClockDomain("sync") @@ -166,7 +194,7 @@ class ResetSynchronizerTestCase(FHDLTestCase): m = Module() m.domains += ClockDomain("sync") m.submodules += ResetSynchronizer(arst) - s = Signal(reset=1) + s = Signal(init=1) m.d.sync += s.eq(0) sim = Simulator(m) diff --git a/tests/test_lib_data.py b/tests/test_lib_data.py index 486e1e0..cfe4cec 100644 --- a/tests/test_lib_data.py +++ b/tests/test_lib_data.py @@ -430,13 +430,13 @@ class LayoutTestCase(FHDLTestCase): sl = StructLayout({"f": unsigned(1)}) self.assertRepr(sl.const({"f": Const(1)}).as_value(), "(const 1'd1)") - def test_signal_reset(self): + def test_signal_init(self): sl = StructLayout({ "a": unsigned(1), "b": unsigned(2) }) - self.assertEqual(Signal(sl).as_value().reset, 0) - self.assertEqual(Signal(sl, reset={"a": 0b1, "b": 0b10}).as_value().reset, 5) + self.assertEqual(Signal(sl).as_value().init, 0) + self.assertEqual(Signal(sl, init={"a": 0b1, "b": 0b10}).as_value().init, 5) class ViewTestCase(FHDLTestCase): @@ -454,17 +454,17 @@ class ViewTestCase(FHDLTestCase): self.assertEqual(cv.shape(), unsigned(3)) self.assertEqual(cv.name, "v") - def test_construct_signal_reset(self): + def test_construct_signal_init(self): v1 = Signal(StructLayout({"a": unsigned(1), "b": unsigned(2)}), - reset={"a": 0b1, "b": 0b10}) - self.assertEqual(Value.cast(v1).reset, 0b101) + init={"a": 0b1, "b": 0b10}) + self.assertEqual(Value.cast(v1).init, 0b101) v2 = Signal(StructLayout({"a": unsigned(1), "b": StructLayout({"x": unsigned(1), "y": unsigned(1)})}), - reset={"a": 0b1, "b": {"x": 0b0, "y": 0b1}}) - self.assertEqual(Value.cast(v2).reset, 0b101) + init={"a": 0b1, "b": {"x": 0b0, "y": 0b1}}) + self.assertEqual(Value.cast(v2).init, 0b101) v3 = Signal(ArrayLayout(unsigned(2), 2), - reset=[0b01, 0b10]) - self.assertEqual(Value.cast(v3).reset, 0b1001) + init=[0b01, 0b10]) + self.assertEqual(Value.cast(v3).init, 0b1001) def test_layout_wrong(self): with self.assertRaisesRegex(TypeError, @@ -625,13 +625,13 @@ class ViewTestCase(FHDLTestCase): def test_bug_837_array_layout_getitem_str(self): with self.assertRaisesRegex(TypeError, r"^Views with array layout may only be indexed with an integer or a value, " - r"not 'reset'$"): - Signal(ArrayLayout(unsigned(1), 1), reset=[0])["reset"] + r"not 'init'$"): + Signal(ArrayLayout(unsigned(1), 1), init=[0])["init"] def test_bug_837_array_layout_getattr(self): with self.assertRaisesRegex(AttributeError, r"^View of \(sig \$signal\) with an array layout does not have fields$"): - Signal(ArrayLayout(unsigned(1), 1), reset=[0]).reset + Signal(ArrayLayout(unsigned(1), 1), init=[0]).init def test_eq(self): s1 = Signal(StructLayout({"a": unsigned(2)})) @@ -735,7 +735,7 @@ class StructTestCase(FHDLTestCase): self.assertRepr(v.b.q.r, "(s (slice (slice (slice (sig v) 1:9) 4:8) 0:2))") self.assertRepr(v.b.q.s, "(s (slice (slice (slice (sig v) 1:9) 4:8) 2:4))") - def test_construct_reset(self): + def test_construct_init(self): class S(Struct): p: 4 q: 2 = 1 @@ -744,11 +744,11 @@ class StructTestCase(FHDLTestCase): S.q v1 = Signal(S) - self.assertEqual(v1.as_value().reset, 0b010000) - v2 = Signal(S, reset=dict(p=0b0011)) - self.assertEqual(v2.as_value().reset, 0b010011) - v3 = Signal(S, reset=dict(p=0b0011, q=0b00)) - self.assertEqual(v3.as_value().reset, 0b000011) + self.assertEqual(v1.as_value().init, 0b010000) + v2 = Signal(S, init=dict(p=0b0011)) + self.assertEqual(v2.as_value().init, 0b010011) + v3 = Signal(S, init=dict(p=0b0011, q=0b00)) + self.assertEqual(v3.as_value().init, 0b000011) def test_shape_undefined_wrong(self): class S(Struct): @@ -835,33 +835,33 @@ class UnionTestCase(FHDLTestCase): self.assertRepr(v.a, "(slice (sig v) 0:1)") self.assertRepr(v.b, "(s (slice (sig v) 0:3))") - def test_define_reset_two_wrong(self): + def test_define_init_two_wrong(self): with self.assertRaisesRegex(ValueError, - r"^Reset value for at most one field can be provided for a union class " + r"^Initial value for at most one field can be provided for a union class " r"\(specified: a, b\)$"): class U(Union): a: unsigned(1) = 1 b: unsigned(2) = 1 - def test_construct_reset_two_wrong(self): + def test_construct_init_two_wrong(self): class U(Union): a: unsigned(1) b: unsigned(2) with self.assertRaisesRegex(TypeError, - r"^Reset value must be a constant initializer of $") as cm: - Signal(U, reset=dict(a=1, b=2)) + r"^Initial value must be a constant initializer of $") as cm: + Signal(U, init=dict(a=1, b=2)) self.assertRegex(cm.exception.__cause__.message, r"^Initializer for at most one field can be provided for a union " r"class \(specified: a, b\)$") - def test_construct_reset_override(self): + def test_construct_init_override(self): class U(Union): a: unsigned(1) = 1 b: unsigned(2) - self.assertEqual(Signal(U).as_value().reset, 0b01) - self.assertEqual(Signal(U, reset=dict(b=0b10)).as_value().reset, 0b10) + self.assertEqual(Signal(U).as_value().init, 0b01) + self.assertEqual(Signal(U, init=dict(b=0b10)).as_value().init, 0b10) # Examples from https://github.com/amaranth-lang/amaranth/issues/693 diff --git a/tests/test_lib_wiring.py b/tests/test_lib_wiring.py index 1682f78..35570ab 100644 --- a/tests/test_lib_wiring.py +++ b/tests/test_lib_wiring.py @@ -36,7 +36,7 @@ class MemberTestCase(unittest.TestCase): self.assertEqual(member.flow, In) self.assertEqual(member.is_port, True) self.assertEqual(member.shape, unsigned(1)) - self.assertEqual(member.reset, None) + self.assertEqual(member.init, None) self.assertEqual(member.is_signature, False) with self.assertRaisesRegex(AttributeError, r"^A port member does not have a signature$"): @@ -50,33 +50,58 @@ class MemberTestCase(unittest.TestCase): r"not 'whatever'$"): Member(In, "whatever") - def test_port_member_reset(self): - member = Member(Out, unsigned(1), reset=1) + def test_port_member_init(self): + member = Member(Out, unsigned(1), init=1) self.assertEqual(member.flow, Out) self.assertEqual(member.shape, unsigned(1)) - self.assertEqual(member.reset, 1) - self.assertEqual(repr(member._reset_as_const), repr(Const(1, 1))) - self.assertEqual(repr(member), "Out(unsigned(1), reset=1)") + self.assertEqual(member.init, 1) + self.assertEqual(repr(member._init_as_const), repr(Const(1, 1))) + self.assertEqual(repr(member), "Out(unsigned(1), init=1)") - def test_port_member_reset_wrong(self): + def test_port_member_init_wrong(self): with self.assertRaisesRegex(TypeError, - r"^Port member reset value 'no' is not a valid constant initializer " + r"^Port member initial value 'no' is not a valid constant initializer " r"for unsigned\(1\)$"): - Member(In, 1, reset="no") + Member(In, 1, init="no") - def test_port_member_reset_shape_castable(self): + def test_port_member_init_shape_castable(self): layout = data.StructLayout({"a": 32}) - member = Member(In, layout, reset={"a": 1}) + member = Member(In, layout, init={"a": 1}) self.assertEqual(member.flow, In) self.assertEqual(member.shape, layout) - self.assertEqual(member.reset, {"a": 1}) - self.assertEqual(repr(member), "In(StructLayout({'a': 32}), reset={'a': 1})") + self.assertEqual(member.init, {"a": 1}) + self.assertEqual(repr(member), "In(StructLayout({'a': 32}), init={'a': 1})") - def test_port_member_reset_shape_castable_wrong(self): + def test_port_member_init_shape_castable_wrong(self): with self.assertRaisesRegex(TypeError, - r"^Port member reset value 'no' is not a valid constant initializer " + r"^Port member initial value 'no' is not a valid constant initializer " r"for StructLayout\({'a': 32}\)$"): - Member(In, data.StructLayout({"a": 32}), reset="no") + Member(In, data.StructLayout({"a": 32}), init="no") + + def test_port_member_reset(self): + with self.assertWarnsRegex(DeprecationWarning, + r"^`reset=` is deprecated, use `init=` instead$"): + member = Member(Out, unsigned(1), reset=1) + self.assertEqual(member.flow, Out) + self.assertEqual(member.shape, unsigned(1)) + self.assertEqual(member.init, 1) + self.assertEqual(repr(member._init_as_const), repr(Const(1, 1))) + self.assertEqual(repr(member), "Out(unsigned(1), init=1)") + with self.assertWarnsRegex(DeprecationWarning, + r"^`Member.reset` is deprecated, use `Member.init` instead$"): + self.assertEqual(member.reset, 1) + with self.assertWarnsRegex(DeprecationWarning, + r"^`reset=` is deprecated, use `init=` instead$"): + member = Out(unsigned(1), reset=1) + self.assertEqual(member.init,1) + + def test_port_member_reset_wrong(self): + with self.assertRaisesRegex(ValueError, + r"^Cannot specify both `reset` and `init`$"): + Member(Out, unsigned(1), reset=1, init=1) + with self.assertRaisesRegex(ValueError, + r"^Cannot specify both `reset` and `init`$"): + Out(unsigned(1), reset=1, init=1) def test_signature_member_out(self): sig = Signature({"data": Out(unsigned(32))}) @@ -87,8 +112,8 @@ class MemberTestCase(unittest.TestCase): r"^A signature member does not have a shape$"): member.shape with self.assertRaisesRegex(AttributeError, - r"^A signature member does not have a reset value$"): - member.reset + r"^A signature member does not have an initial value$"): + member.init self.assertEqual(member.is_signature, True) self.assertEqual(member.signature, sig) self.assertEqual(member.dimensions, ()) @@ -103,8 +128,8 @@ class MemberTestCase(unittest.TestCase): r"^A signature member does not have a shape$"): member.shape with self.assertRaisesRegex(AttributeError, - r"^A signature member does not have a reset value$"): - member.reset + r"^A signature member does not have an initial value$"): + member.init self.assertEqual(member.is_signature, True) self.assertEqual(member.signature, sig.flip()) self.assertEqual(member.dimensions, ()) @@ -112,8 +137,8 @@ class MemberTestCase(unittest.TestCase): def test_signature_member_wrong(self): with self.assertRaisesRegex(ValueError, - r"^A signature member cannot have a reset value$"): - Member(In, Signature({}), reset=1) + r"^A signature member cannot have an initial value$"): + Member(In, Signature({}), init=1) def test_array(self): array_2 = Member(In, unsigned(1)).array(2) @@ -143,8 +168,8 @@ class MemberTestCase(unittest.TestCase): def test_equality(self): self.assertEqual(In(1), In(1)) self.assertNotEqual(In(1), Out(1)) - self.assertNotEqual(In(1), In(1, reset=1)) - self.assertNotEqual(In(1), In(1, reset=0)) + self.assertNotEqual(In(1), In(1, init=1)) + self.assertNotEqual(In(1), In(1, init=0)) self.assertEqual(In(1), In(1).array()) self.assertNotEqual(In(1), In(1).array(1)) sig = Signature({}) @@ -237,12 +262,12 @@ class SignatureMembersTestCase(unittest.TestCase): self.assertEqual(attrs["s"].b.shape(), unsigned(2)) self.assertEqual(attrs["s"].b.name, "attrs__s__b") - def test_create_reset(self): + def test_create_init(self): members = SignatureMembers({ - "a": In(1, reset=1), + "a": In(1, init=1), }) attrs = members.create() - self.assertEqual(attrs["a"].reset, 1) + self.assertEqual(attrs["a"].init, 1) def test_create_tuple(self): sig = SignatureMembers({ @@ -421,12 +446,12 @@ class SignatureTestCase(unittest.TestCase): sig=Signature({"a": In(unsigned(1))}), obj=NS(a=Signal(signed(1)))) self.assertNotCompliant( - r"^'obj\.a' is expected to have the reset value None, but it has the reset value 1$", + r"^'obj\.a' is expected to have the initial value None, but it has the initial value 1$", sig=Signature({"a": In(1)}), - obj=NS(a=Signal(reset=1))) + obj=NS(a=Signal(init=1))) self.assertNotCompliant( - r"^'obj\.a' is expected to have the reset value 1, but it has the reset value 0$", - sig=Signature({"a": In(1, reset=1)}), + r"^'obj\.a' is expected to have the initial value 1, but it has the initial value 0$", + sig=Signature({"a": In(1, init=1)}), obj=NS(a=Signal(1))) self.assertNotCompliant( r"^'obj\.a' is expected to not be reset-less$", @@ -820,21 +845,21 @@ class ConnectTestCase(unittest.TestCase): q=NS(signature=Signature({"a": In(Cycle)}), a=Signal(Cycle))) - def test_reset_mismatch(self): + def test_init_mismatch(self): m = Module() with self.assertRaisesRegex(ConnectionError, - r"^Cannot connect together the member 'q\.a' with reset value 1 and the member " - r"'p\.a' with reset value 0 because the reset values do not match$"): + r"^Cannot connect together the member 'q\.a' with initial value 1 and the member " + r"'p\.a' with initial value 0 because the initial values do not match$"): connect(m, - p=NS(signature=Signature({"a": Out(1, reset=0)}), + p=NS(signature=Signature({"a": Out(1, init=0)}), a=Signal()), - q=NS(signature=Signature({"a": In(1, reset=1)}), - a=Signal(reset=1))) + q=NS(signature=Signature({"a": In(1, init=1)}), + a=Signal(init=1))) - def test_reset_none_match(self): + def test_init_none_match(self): m = Module() connect(m, - p=NS(signature=Signature({"a": Out(1, reset=0)}), + p=NS(signature=Signature({"a": Out(1, init=0)}), a=Signal()), q=NS(signature=Signature({"a": In(1)}), a=Signal())) diff --git a/tests/test_sim.py b/tests/test_sim.py index 7950fe6..8cac7f8 100644 --- a/tests/test_sim.py +++ b/tests/test_sim.py @@ -18,12 +18,12 @@ from amaranth._utils import _ignore_deprecated class SimulatorUnitTestCase(FHDLTestCase): - def assertStatement(self, stmt, inputs, output, reset=0): + def assertStatement(self, stmt, inputs, output, init=0): inputs = [Value.cast(i) for i in inputs] output = Value.cast(output) isigs = [Signal(i.shape(), name=n) for i, n in zip(inputs, "abcd")] - osig = Signal(output.shape(), name="y", reset=reset) + osig = Signal(output.shape(), name="y", init=init) stmt = stmt(osig, *isigs) frag = Fragment() @@ -243,9 +243,9 @@ class SimulatorUnitTestCase(FHDLTestCase): def test_slice_lhs(self): stmt1 = lambda y, a: y[2].eq(a) - self.assertStatement(stmt1, [C(0b0, 1)], C(0b11111011, 8), reset=0b11111111) + self.assertStatement(stmt1, [C(0b0, 1)], C(0b11111011, 8), init=0b11111111) stmt2 = lambda y, a: y[2:4].eq(a) - self.assertStatement(stmt2, [C(0b01, 2)], C(0b11110111, 8), reset=0b11111011) + self.assertStatement(stmt2, [C(0b01, 2)], C(0b11110111, 8), init=0b11111011) def test_bit_select(self): stmt = lambda y, a, b: y.eq(a.bit_select(b, 3)) @@ -255,9 +255,9 @@ class SimulatorUnitTestCase(FHDLTestCase): def test_bit_select_lhs(self): stmt = lambda y, a, b: y.bit_select(a, 3).eq(b) - self.assertStatement(stmt, [C(0), C(0b100, 3)], C(0b11111100, 8), reset=0b11111111) - self.assertStatement(stmt, [C(2), C(0b101, 3)], C(0b11110111, 8), reset=0b11111111) - self.assertStatement(stmt, [C(3), C(0b110, 3)], C(0b11110111, 8), reset=0b11111111) + self.assertStatement(stmt, [C(0), C(0b100, 3)], C(0b11111100, 8), init=0b11111111) + self.assertStatement(stmt, [C(2), C(0b101, 3)], C(0b11110111, 8), init=0b11111111) + self.assertStatement(stmt, [C(3), C(0b110, 3)], C(0b11110111, 8), init=0b11111111) def test_word_select(self): stmt = lambda y, a, b: y.eq(a.word_select(b, 3)) @@ -267,9 +267,9 @@ class SimulatorUnitTestCase(FHDLTestCase): def test_word_select_lhs(self): stmt = lambda y, a, b: y.word_select(a, 3).eq(b) - self.assertStatement(stmt, [C(0), C(0b100, 3)], C(0b11111100, 8), reset=0b11111111) - self.assertStatement(stmt, [C(1), C(0b101, 3)], C(0b11101111, 8), reset=0b11111111) - self.assertStatement(stmt, [C(2), C(0b110, 3)], C(0b10111111, 8), reset=0b11111111) + self.assertStatement(stmt, [C(0), C(0b100, 3)], C(0b11111100, 8), init=0b11111111) + self.assertStatement(stmt, [C(1), C(0b101, 3)], C(0b11101111, 8), init=0b11111111) + self.assertStatement(stmt, [C(2), C(0b110, 3)], C(0b10111111, 8), init=0b11111111) def test_cat(self): stmt = lambda y, *xs: y.eq(Cat(*xs)) @@ -315,9 +315,9 @@ class SimulatorUnitTestCase(FHDLTestCase): self.assertStatement(stmt, [C(4)], C(10)) def test_array_lhs(self): - l = Signal(3, reset=1) - m = Signal(3, reset=4) - n = Signal(3, reset=7) + l = Signal(3, init=1) + m = Signal(3, init=4) + n = Signal(3, init=7) array = Array([l, m, n]) stmt = lambda y, a, b: [array[a].eq(b), y.eq(Cat(*array))] self.assertStatement(stmt, [C(0), C(0b000)], C(0b111100000)) @@ -426,7 +426,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase): sim.run_until(deadline) def setUp_counter(self): - self.count = Signal(3, reset=4) + self.count = Signal(3, init=4) self.sync = ClockDomain() self.m = Module() @@ -876,7 +876,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase): def test_comb_bench_process(self): m = Module() - a = Signal(reset=1) + a = Signal(init=1) b = Signal() m.d.comb += b.eq(a) with self.assertSimulation(m) as sim: @@ -890,7 +890,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase): def test_sync_bench_process(self): m = Module() - a = Signal(reset=1) + a = Signal(init=1) b = Signal() m.d.sync += b.eq(a) t = Signal()