Implement RFC 43: Rename reset=
to init=
.
This commit is contained in:
parent
b30c87fa3e
commit
24a392887a
|
@ -173,7 +173,7 @@ class ShapeCastable:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
value_like = Signal(shape_castable, reset=initializer)
|
value_like = Signal(shape_castable, init=initializer)
|
||||||
|
|
||||||
The code above is equivalent to:
|
The code above is equivalent to:
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ class ShapeCastable:
|
||||||
|
|
||||||
value_like = shape_castable(Signal(
|
value_like = shape_castable(Signal(
|
||||||
shape_castable.as_shape(),
|
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)`.
|
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 : str
|
||||||
Name hint for this signal. If ``None`` (default) the name is inferred from the variable
|
Name hint for this signal. If ``None`` (default) the name is inferred from the variable
|
||||||
name this ``Signal`` is assigned to.
|
name this ``Signal`` is assigned to.
|
||||||
reset : int or integral Enum
|
init : int or integral Enum
|
||||||
Reset (synchronous) or default (combinatorial) value.
|
Reset (synchronous) or default (combinatorial) value.
|
||||||
When this ``Signal`` is assigned to in synchronous context and the corresponding clock
|
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
|
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``
|
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
|
reset_less : bool
|
||||||
If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
|
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``.
|
Defaults to ``False``.
|
||||||
attrs : dict
|
attrs : dict
|
||||||
Dictionary of synthesis attributes.
|
Dictionary of synthesis attributes.
|
||||||
|
@ -1754,13 +1754,13 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
width : int
|
width : int
|
||||||
signed : bool
|
signed : bool
|
||||||
name : str
|
name : str
|
||||||
reset : int
|
init : int
|
||||||
reset_less : bool
|
reset_less : bool
|
||||||
attrs : dict
|
attrs : dict
|
||||||
decoder : function
|
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):
|
attrs=None, decoder=None, src_loc_at=0):
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
|
|
||||||
|
@ -1776,53 +1776,61 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
self.width = shape.width
|
self.width = shape.width
|
||||||
self.signed = shape.signed
|
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):
|
if isinstance(orig_shape, ShapeCastable):
|
||||||
try:
|
try:
|
||||||
reset = Const.cast(orig_shape.const(reset))
|
init = Const.cast(orig_shape.const(init))
|
||||||
except Exception:
|
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))
|
.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 "
|
raise ValueError("Constant returned by {!r}.const() must have the shape that "
|
||||||
"it casts to, {!r}, and not {!r}"
|
"it casts to, {!r}, and not {!r}"
|
||||||
.format(orig_shape, Shape.cast(orig_shape),
|
.format(orig_shape, Shape.cast(orig_shape),
|
||||||
reset.shape()))
|
init.shape()))
|
||||||
else:
|
else:
|
||||||
if reset is None:
|
if init is None:
|
||||||
reset = 0
|
init = 0
|
||||||
try:
|
try:
|
||||||
reset = Const.cast(reset)
|
init = Const.cast(init)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise TypeError("Reset value must be a constant-castable expression, not {!r}"
|
raise TypeError("Initial value must be a constant-castable expression, not {!r}"
|
||||||
.format(orig_reset))
|
.format(orig_init))
|
||||||
# Avoid false positives for all-zeroes and all-ones
|
# 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 orig_init is not None and not (isinstance(orig_init, int) and orig_init in (0, -1)):
|
||||||
if reset.shape().signed and not self.signed:
|
if init.shape().signed and not self.signed:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
message="Reset value {!r} is signed, but the signal shape is {!r}"
|
message="Initial value {!r} is signed, but the signal shape is {!r}"
|
||||||
.format(orig_reset, shape),
|
.format(orig_init, shape),
|
||||||
category=SyntaxWarning,
|
category=SyntaxWarning,
|
||||||
stacklevel=2)
|
stacklevel=2)
|
||||||
elif (reset.shape().width > self.width or
|
elif (init.shape().width > self.width or
|
||||||
reset.shape().width == self.width and
|
init.shape().width == self.width and
|
||||||
self.signed and not reset.shape().signed):
|
self.signed and not init.shape().signed):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
message="Reset value {!r} will be truncated to the signal shape {!r}"
|
message="Initial value {!r} will be truncated to the signal shape {!r}"
|
||||||
.format(orig_reset, shape),
|
.format(orig_init, shape),
|
||||||
category=SyntaxWarning,
|
category=SyntaxWarning,
|
||||||
stacklevel=2)
|
stacklevel=2)
|
||||||
self.reset = reset.value
|
self.init = init.value
|
||||||
self.reset_less = bool(reset_less)
|
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 isinstance(orig_shape, range) and orig_init is not None and orig_init not in orig_shape:
|
||||||
if orig_reset == orig_shape.stop:
|
if orig_init == orig_shape.stop:
|
||||||
raise SyntaxError(
|
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")
|
f"shape {orig_shape!r}; this is likely an off-by-one error")
|
||||||
else:
|
else:
|
||||||
raise SyntaxError(
|
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)
|
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.
|
# Any other case is formatted as a plain integer.
|
||||||
self._value_repr = (Repr(FormatInt(), self),)
|
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
|
@property
|
||||||
def decoder(self):
|
def decoder(self):
|
||||||
return self._decoder
|
return self._decoder
|
||||||
|
@ -1873,7 +1893,7 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
self._decoder = enum_decoder
|
self._decoder = enum_decoder
|
||||||
|
|
||||||
@classmethod
|
@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.
|
"""Create Signal based on another.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -1887,15 +1907,24 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
new_name = other.name + str(name_suffix)
|
new_name = other.name + str(name_suffix)
|
||||||
else:
|
else:
|
||||||
new_name = tracer.get_var_name(depth=2 + src_loc_at, default="$like")
|
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):
|
if isinstance(other, ValueCastable):
|
||||||
shape = other.shape()
|
shape = other.shape()
|
||||||
else:
|
else:
|
||||||
shape = Value.cast(other).shape()
|
shape = Value.cast(other).shape()
|
||||||
kw = dict(shape=shape, name=new_name)
|
kw = dict(shape=shape, name=new_name)
|
||||||
if isinstance(other, Signal):
|
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)
|
attrs=other.attrs, decoder=other.decoder)
|
||||||
kw.update(kwargs)
|
kw.update(kwargs)
|
||||||
|
if init is not None:
|
||||||
|
kw["init"] = init
|
||||||
return cls(**kw, src_loc_at=1 + src_loc_at)
|
return cls(**kw, src_loc_at=1 + src_loc_at)
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
|
|
|
@ -374,14 +374,21 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
||||||
self._statements = _outer_case
|
self._statements = _outer_case
|
||||||
|
|
||||||
@contextmanager
|
@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)
|
self._check_context("FSM", context=None)
|
||||||
if domain == "comb":
|
if domain == "comb":
|
||||||
raise ValueError(f"FSM may not be driven by the '{domain}' domain")
|
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", {
|
fsm_data = self._set_ctrl("FSM", {
|
||||||
"name": name,
|
"name": name,
|
||||||
"signal": Signal(name=f"{name}_state", src_loc_at=2),
|
"signal": Signal(name=f"{name}_state", src_loc_at=2),
|
||||||
"reset": reset,
|
"init": init,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"encoding": OrderedDict(),
|
"encoding": OrderedDict(),
|
||||||
"decoding": OrderedDict(),
|
"decoding": OrderedDict(),
|
||||||
|
@ -489,17 +496,17 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
||||||
src_loc=src_loc, case_src_locs=switch_case_src_locs))
|
src_loc=src_loc, case_src_locs=switch_case_src_locs))
|
||||||
|
|
||||||
if name == "FSM":
|
if name == "FSM":
|
||||||
fsm_signal, fsm_reset, fsm_encoding, fsm_decoding, fsm_states = \
|
fsm_signal, fsm_init, fsm_encoding, fsm_decoding, fsm_states = \
|
||||||
data["signal"], data["reset"], data["encoding"], data["decoding"], data["states"]
|
data["signal"], data["init"], data["encoding"], data["decoding"], data["states"]
|
||||||
fsm_state_src_locs = data["state_src_locs"]
|
fsm_state_src_locs = data["state_src_locs"]
|
||||||
if not fsm_states:
|
if not fsm_states:
|
||||||
return
|
return
|
||||||
fsm_signal.width = bits_for(len(fsm_encoding) - 1)
|
fsm_signal.width = bits_for(len(fsm_encoding) - 1)
|
||||||
if fsm_reset is None:
|
if fsm_init is None:
|
||||||
fsm_signal.reset = fsm_encoding[next(iter(fsm_states))]
|
fsm_signal.init = fsm_encoding[next(iter(fsm_states))]
|
||||||
else:
|
else:
|
||||||
fsm_signal.reset = fsm_encoding[fsm_reset]
|
fsm_signal.init = fsm_encoding[fsm_init]
|
||||||
# The FSM is encoded such that the state with encoding 0 is always the reset state.
|
# 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_decoding.update((n, s) for s, n in fsm_encoding.items())
|
||||||
fsm_signal.decoder = lambda n: f"{fsm_decoding[n]}/{n}"
|
fsm_signal.decoder = lambda n: f"{fsm_decoding[n]}/{n}"
|
||||||
|
|
||||||
|
|
|
@ -691,8 +691,8 @@ class NetlistDriver:
|
||||||
|
|
||||||
def emit_value(self, builder):
|
def emit_value(self, builder):
|
||||||
if self.domain is None:
|
if self.domain is None:
|
||||||
reset = _ast.Const(self.signal.reset, self.signal.width)
|
init = _ast.Const(self.signal.init, self.signal.width)
|
||||||
default, _signed = builder.emit_rhs(self.module_idx, reset)
|
default, _signed = builder.emit_rhs(self.module_idx, init)
|
||||||
else:
|
else:
|
||||||
default = builder.emit_signal(self.signal)
|
default = builder.emit_signal(self.signal)
|
||||||
if len(self.assignments) == 1:
|
if len(self.assignments) == 1:
|
||||||
|
@ -1184,7 +1184,7 @@ class NetlistEmitter:
|
||||||
arst = _nir.Net.from_const(0)
|
arst = _nir.Net.from_const(0)
|
||||||
cell = _nir.FlipFlop(driver.module_idx,
|
cell = _nir.FlipFlop(driver.module_idx,
|
||||||
data=value,
|
data=value,
|
||||||
init=driver.signal.reset,
|
init=driver.signal.init,
|
||||||
clk=clk,
|
clk=clk,
|
||||||
clk_edge=driver.domain.clk_edge,
|
clk_edge=driver.domain.clk_edge,
|
||||||
arst=arst,
|
arst=arst,
|
||||||
|
@ -1198,12 +1198,12 @@ class NetlistEmitter:
|
||||||
src_loc = driver.signal.src_loc
|
src_loc = driver.signal.src_loc
|
||||||
self.connect(self.emit_signal(driver.signal), value, src_loc=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.
|
# undriven signals, or signals that are partially driven by instances.
|
||||||
for signal, value in self.netlist.signals.items():
|
for signal, value in self.netlist.signals.items():
|
||||||
for bit, net in enumerate(value):
|
for bit, net in enumerate(value):
|
||||||
if net.is_late and net not in self.netlist.connections:
|
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'):
|
def emit_fragment(self, fragment: _ir.Fragment, parent_module_idx: 'int | None'):
|
||||||
from . import _mem
|
from . import _mem
|
||||||
|
|
|
@ -262,7 +262,7 @@ class ReadPort(Elaboratable):
|
||||||
self.data = Signal(memory.width,
|
self.data = Signal(memory.width,
|
||||||
name=f"{memory.name}_r_data", src_loc_at=1 + src_loc_at)
|
name=f"{memory.name}_r_data", src_loc_at=1 + src_loc_at)
|
||||||
if self.domain != "comb":
|
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)
|
src_loc_at=1 + src_loc_at)
|
||||||
else:
|
else:
|
||||||
self.en = Const(1)
|
self.en = Const(1)
|
||||||
|
|
|
@ -521,7 +521,7 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
||||||
domain = fragment.domains[domain_name]
|
domain = fragment.domains[domain_name]
|
||||||
if domain.rst is None:
|
if domain.rst is None:
|
||||||
continue
|
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]
|
for signal in signals if not signal.reset_less]
|
||||||
fragment.add_statements(domain_name, Switch(domain.rst, {1: stmts}))
|
fragment.add_statements(domain_name, Switch(domain.rst, {1: stmts}))
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ class _ControlInserter(FragmentTransformer):
|
||||||
|
|
||||||
class ResetInserter(_ControlInserter):
|
class ResetInserter(_ControlInserter):
|
||||||
def _insert_control(self, fragment, domain, signals):
|
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))
|
fragment.add_statements(domain, Switch(self.controls[domain], {1: stmts}, src_loc=self.src_loc))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import warnings
|
||||||
|
|
||||||
from .. import *
|
from .. import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,8 +28,8 @@ class FFSynchronizer(Elaboratable):
|
||||||
Signal connected to synchroniser output.
|
Signal connected to synchroniser output.
|
||||||
o_domain : str
|
o_domain : str
|
||||||
Name of output clock domain.
|
Name of output clock domain.
|
||||||
reset : int
|
init : int
|
||||||
Reset value of the flip-flops. On FPGAs, even if ``reset_less`` is ``True``,
|
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.
|
the :class:`FFSynchronizer` is still set to this value during initialization.
|
||||||
reset_less : bool
|
reset_less : bool
|
||||||
If ``True`` (the default), this :class:`FFSynchronizer` is unaffected by ``o_domain``
|
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
|
Define the ``get_ff_sync`` platform method to override the implementation of
|
||||||
:class:`FFSynchronizer`, e.g. to instantiate library cells directly.
|
: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):
|
max_input_delay=None):
|
||||||
_check_stages(stages)
|
_check_stages(stages)
|
||||||
|
|
||||||
self.i = i
|
self.i = i
|
||||||
self.o = o
|
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._reset_less = reset_less
|
||||||
self._o_domain = o_domain
|
self._o_domain = o_domain
|
||||||
self._stages = stages
|
self._stages = stages
|
||||||
|
@ -87,7 +99,7 @@ class FFSynchronizer(Elaboratable):
|
||||||
|
|
||||||
m = Module()
|
m = Module()
|
||||||
flops = [Signal(self.i.shape(), name=f"stage{index}",
|
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 index in range(self._stages)]
|
||||||
for i, o in zip((self.i, *flops), flops):
|
for i, o in zip((self.i, *flops), flops):
|
||||||
m.d[self._o_domain] += o.eq(i)
|
m.d[self._o_domain] += o.eq(i)
|
||||||
|
@ -161,7 +173,7 @@ class AsyncFFSynchronizer(Elaboratable):
|
||||||
|
|
||||||
m = Module()
|
m = Module()
|
||||||
m.domains += ClockDomain("async_ff", async_reset=True, local=True)
|
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 index in range(self._stages)]
|
||||||
for i, o in zip((0, *flops), flops):
|
for i, o in zip((0, *flops), flops):
|
||||||
m.d.async_ff += o.eq(i)
|
m.d.async_ff += o.eq(i)
|
||||||
|
|
|
@ -383,7 +383,7 @@ class Processor(Elaboratable):
|
||||||
def elaborate(self, platform):
|
def elaborate(self, platform):
|
||||||
m = Module()
|
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)
|
data_in = Signal(self._data_width)
|
||||||
|
|
||||||
# Optionally bit-reflect input words.
|
# Optionally bit-reflect input words.
|
||||||
|
|
|
@ -812,7 +812,7 @@ class _AggregateMeta(ShapeCastable, type):
|
||||||
cls = type.__new__(metacls, name, bases, namespace)
|
cls = type.__new__(metacls, name, bases, namespace)
|
||||||
if cls.__layout_cls is UnionLayout:
|
if cls.__layout_cls is UnionLayout:
|
||||||
if len(default) > 1:
|
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: {})"
|
"a union class (specified: {})"
|
||||||
.format(", ".join(default.keys())))
|
.format(", ".join(default.keys())))
|
||||||
cls.__layout = cls.__layout_cls(layout)
|
cls.__layout = cls.__layout_cls(layout)
|
||||||
|
@ -855,12 +855,12 @@ class Struct(View, metaclass=_AggregateMeta):
|
||||||
"""Structures defined with annotations.
|
"""Structures defined with annotations.
|
||||||
|
|
||||||
The :class:`Struct` base class is a subclass of :class:`View` that provides a concise way
|
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 <python:variable annotation>`.
|
:term:`variable annotations <python:variable annotation>`.
|
||||||
|
|
||||||
Any annotations containing :ref:`shape-like <lang-shapelike>` objects are used,
|
Any annotations containing :ref:`shape-like <lang-shapelike>` objects are used,
|
||||||
in the order in which they appear in the source code, to construct a :class:`StructLayout`.
|
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.
|
created by the view. Any other annotations are kept as-is.
|
||||||
|
|
||||||
.. testsetup::
|
.. testsetup::
|
||||||
|
@ -907,15 +907,15 @@ class Struct(View, metaclass=_AggregateMeta):
|
||||||
>>> flt.is_subnormal()
|
>>> flt.is_subnormal()
|
||||||
(== (slice (sig flt) 23:31) (const 1'd0))
|
(== (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::
|
.. doctest::
|
||||||
|
|
||||||
>>> hex(Signal(IEEE754Single).as_value().reset)
|
>>> hex(Signal(IEEE754Single).as_value().init)
|
||||||
'0x3f800000'
|
'0x3f800000'
|
||||||
>>> hex(Signal(IEEE754Single, reset={'sign': 1}).as_value().reset)
|
>>> hex(Signal(IEEE754Single, init={'sign': 1}).as_value().init)
|
||||||
'0xbf800000'
|
'0xbf800000'
|
||||||
>>> hex(Signal(IEEE754Single, reset={'exponent': 0}).as_value().reset)
|
>>> hex(Signal(IEEE754Single, init={'exponent': 0}).as_value().init)
|
||||||
'0x0'
|
'0x0'
|
||||||
|
|
||||||
Classes inheriting from :class:`Struct` can be used as base classes. The only restrictions
|
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
|
annotation>`. It is very similar to the :class:`Struct` class, except that its layout
|
||||||
is a :class:`UnionLayout`.
|
is a :class:`UnionLayout`.
|
||||||
|
|
||||||
A :class:`Union` can have only one field with a specified reset value. If a reset value is
|
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 reset value specified with
|
explicitly provided during instantiation, it overrides the initial value specified with
|
||||||
an annotation:
|
an annotation:
|
||||||
|
|
||||||
.. testcode::
|
.. testcode::
|
||||||
|
@ -976,9 +976,9 @@ class Union(View, metaclass=_AggregateMeta):
|
||||||
|
|
||||||
.. doctest::
|
.. doctest::
|
||||||
|
|
||||||
>>> Signal(VarInt).as_value().reset
|
>>> Signal(VarInt).as_value().init
|
||||||
256
|
256
|
||||||
>>> Signal(VarInt, reset={'int8': 10}).as_value().reset
|
>>> Signal(VarInt, init={'int8': 10}).as_value().init
|
||||||
10
|
10
|
||||||
"""
|
"""
|
||||||
_AggregateMeta__layout_cls = UnionLayout
|
_AggregateMeta__layout_cls = UnionLayout
|
||||||
|
|
|
@ -165,8 +165,8 @@ class EnumMeta(ShapeCastable, py_enum.EnumMeta):
|
||||||
def const(cls, init):
|
def const(cls, init):
|
||||||
# Same considerations apply as above.
|
# Same considerations apply as above.
|
||||||
if init is None:
|
if init is None:
|
||||||
# Signal with unspecified reset value passes ``None`` to :meth:`const`.
|
# Signal with unspecified initial value passes ``None`` to :meth:`const`.
|
||||||
# Before RFC 9 was implemented, the unspecified reset value was 0, so this keeps
|
# Before RFC 9 was implemented, the unspecified initial value was 0, so this keeps
|
||||||
# the old behavior intact.
|
# the old behavior intact.
|
||||||
member = cls(0)
|
member = cls(0)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -59,16 +59,23 @@ class Flow(enum.Enum):
|
||||||
return Out
|
return Out
|
||||||
assert False # :nocov:
|
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
|
"""Create a :class:`Member` with this data flow and the provided description and
|
||||||
reset value.
|
initial value.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
:class:`Member`
|
: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):
|
def __repr__(self):
|
||||||
return self.name
|
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`
|
object (in which case it is created as a port member). After creation the :class:`Member`
|
||||||
instance cannot be modified.
|
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
|
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
|
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))`.
|
: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._flow = flow
|
||||||
self._description = description
|
self._description = description
|
||||||
self._reset = reset
|
self._init = init
|
||||||
self._dimensions = _dimensions
|
self._dimensions = _dimensions
|
||||||
self.src_loc = tracer.get_src_loc(src_loc_at=src_loc_at)
|
self.src_loc = tracer.get_src_loc(src_loc_at=src_loc_at)
|
||||||
|
|
||||||
|
@ -121,23 +135,23 @@ class Member:
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise TypeError(f"Port member description must be a shape-castable object or "
|
raise TypeError(f"Port member description must be a shape-castable object or "
|
||||||
f"a signature, not {description!r}") from e
|
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"
|
# TODO: We need a simpler way to check for "is this a valid constant initializer"
|
||||||
if issubclass(type(self._description), ShapeCastable):
|
if issubclass(type(self._description), ShapeCastable):
|
||||||
try:
|
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:
|
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
|
f"constant initializer for {self._description}") from e
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self._reset_as_const = Const.cast(reset or 0)
|
self._init_as_const = Const.cast(init or 0)
|
||||||
except TypeError:
|
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}")
|
f"constant initializer for {shape}")
|
||||||
if self.is_signature:
|
if self.is_signature:
|
||||||
if self._reset is not None:
|
if self._init is not None:
|
||||||
raise ValueError(f"A signature member cannot have a reset value")
|
raise ValueError(f"A signature member cannot have an initial value")
|
||||||
|
|
||||||
def flip(self):
|
def flip(self):
|
||||||
"""Flip the data flow of this member.
|
"""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
|
A new :py:`member` with :py:`member.flow` equal to :py:`self.flow.flip()`, and identical
|
||||||
to :py:`self` other than that.
|
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)
|
_dimensions=self._dimensions)
|
||||||
|
|
||||||
def array(self, *dimensions):
|
def array(self, *dimensions):
|
||||||
|
@ -175,7 +189,7 @@ class Member:
|
||||||
if not (isinstance(dimension, int) and dimension >= 0):
|
if not (isinstance(dimension, int) and dimension >= 0):
|
||||||
raise TypeError(f"Member array dimensions must be non-negative integers, "
|
raise TypeError(f"Member array dimensions must be non-negative integers, "
|
||||||
f"not {dimension!r}")
|
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))
|
_dimensions=(*dimensions, *self._dimensions))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -231,13 +245,13 @@ class Member:
|
||||||
return self._description
|
return self._description
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reset(self):
|
def init(self):
|
||||||
"""Reset value of a port member.
|
"""Initial value of a port member.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
:ref:`const-castable object <lang-constcasting>`
|
:ref:`const-castable object <lang-constcasting>`
|
||||||
The reset value that was provided when constructing this :class:`Member`.
|
The initial value that was provided when constructing this :class:`Member`.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
|
@ -245,8 +259,14 @@ class Member:
|
||||||
If :py:`self` describes a signature member.
|
If :py:`self` describes a signature member.
|
||||||
"""
|
"""
|
||||||
if self.is_signature:
|
if self.is_signature:
|
||||||
raise AttributeError(f"A signature member does not have a reset value")
|
raise AttributeError(f"A signature member does not have an initial value")
|
||||||
return self._reset
|
return self._init
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reset(self):
|
||||||
|
warnings.warn("`Member.reset` is deprecated, use `Member.init` instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
return self.init
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def signature(self):
|
def signature(self):
|
||||||
|
@ -288,16 +308,16 @@ class Member:
|
||||||
return (type(other) is Member and
|
return (type(other) is Member and
|
||||||
self._flow == other._flow and
|
self._flow == other._flow and
|
||||||
self._description == other._description and
|
self._description == other._description and
|
||||||
self._reset == other._reset and
|
self._init == other._init and
|
||||||
self._dimensions == other._dimensions)
|
self._dimensions == other._dimensions)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
reset_repr = dimensions_repr = ""
|
init_repr = dimensions_repr = ""
|
||||||
if self._reset:
|
if self._init:
|
||||||
reset_repr = f", reset={self._reset!r}"
|
init_repr = f", init={self._init!r}"
|
||||||
if self._dimensions:
|
if self._dimensions:
|
||||||
dimensions_repr = f".array({', '.join(map(str, 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
|
@final
|
||||||
|
@ -470,7 +490,7 @@ class SignatureMembers(Mapping):
|
||||||
def create(self, *, path=None, src_loc_at=0):
|
def create(self, *, path=None, src_loc_at=0):
|
||||||
"""Create members from their descriptions.
|
"""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
|
value taken from the member description, and the name constructed from
|
||||||
the :ref:`paths <wiring-path>` to the member (by concatenating path items with a double
|
the :ref:`paths <wiring-path>` to the member (by concatenating path items with a double
|
||||||
underscore, ``__``).
|
underscore, ``__``).
|
||||||
|
@ -497,7 +517,7 @@ class SignatureMembers(Mapping):
|
||||||
# Ideally we would keep both source locations here, but the .src_loc attribute
|
# 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:
|
# 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.)
|
# 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))
|
name="__".join(str(item) for item in path))
|
||||||
signal.src_loc = member.src_loc
|
signal.src_loc = member.src_loc
|
||||||
return signal
|
return signal
|
||||||
|
@ -775,7 +795,7 @@ class Signature(metaclass=SignatureMeta):
|
||||||
|
|
||||||
def iter_member(value, *, path):
|
def iter_member(value, *, path):
|
||||||
if member.is_port:
|
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:
|
elif member.is_signature:
|
||||||
for sub_path, sub_member, sub_value in member.signature.flatten(value):
|
for sub_path, sub_member, sub_value in member.signature.flatten(value):
|
||||||
if member.flow == In:
|
if member.flow == In:
|
||||||
|
@ -816,7 +836,7 @@ class Signature(metaclass=SignatureMeta):
|
||||||
* for port members, is a :ref:`value-like <lang-valuelike>` object casting to
|
* for port members, is a :ref:`value-like <lang-valuelike>` object casting to
|
||||||
a :class:`Signal` or a :class:`Const` whose width and signedness is the same as that
|
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
|
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
|
* for signature members, matches the description in the signature as verified by
|
||||||
:meth:`Signature.is_compliant`.
|
:meth:`Signature.is_compliant`.
|
||||||
|
|
||||||
|
@ -878,11 +898,11 @@ class Signature(metaclass=SignatureMeta):
|
||||||
f"the shape {_format_shape(attr_shape)}")
|
f"the shape {_format_shape(attr_shape)}")
|
||||||
return False
|
return False
|
||||||
if isinstance(attr_value_cast, Signal):
|
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:
|
if reasons is not None:
|
||||||
reasons.append(f"{_format_path(path)} is expected to have "
|
reasons.append(f"{_format_path(path)} is expected to have "
|
||||||
f"the reset value {member.reset!r}, but it has "
|
f"the initial value {member.init!r}, but it has "
|
||||||
f"the reset value {attr_value_cast.reset!r}")
|
f"the initial value {attr_value_cast.init!r}")
|
||||||
return False
|
return False
|
||||||
if attr_value_cast.reset_less:
|
if attr_value_cast.reset_less:
|
||||||
if reasons is not None:
|
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
|
* Every interface object must have the same set of port members, and they must have the same
|
||||||
:meth:`dimensions <Member.dimensions>`.
|
:meth:`dimensions <Member.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
|
value (for port members corresponding to signals) or constant value (for port members
|
||||||
corresponding to constants). Signedness may differ.
|
corresponding to constants). Signedness may differ.
|
||||||
* For each path, at most one interface object must have the corresponding port member be
|
* 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
|
is_first = False
|
||||||
first_path = path
|
first_path = path
|
||||||
first_member_shape = member.shape
|
first_member_shape = member.shape
|
||||||
first_member_reset = member.reset
|
first_member_init = member.init
|
||||||
first_member_reset_as_const = member._reset_as_const
|
first_member_init_as_const = member._init_as_const
|
||||||
continue
|
continue
|
||||||
if Shape.cast(first_member_shape).width != Shape.cast(member_shape).width:
|
if Shape.cast(first_member_shape).width != Shape.cast(member_shape).width:
|
||||||
raise ConnectionError(
|
raise ConnectionError(
|
||||||
|
@ -1496,13 +1516,13 @@ def connect(m, *args, **kwargs):
|
||||||
f"shape {_format_shape(member_shape)} because the shape widths "
|
f"shape {_format_shape(member_shape)} because the shape widths "
|
||||||
f"({Shape.cast(first_member_shape).width} and "
|
f"({Shape.cast(first_member_shape).width} and "
|
||||||
f"{Shape.cast(member_shape).width}) do not match")
|
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(
|
raise ConnectionError(
|
||||||
f"Cannot connect together the member {_format_path(first_path)} with reset "
|
f"Cannot connect together the member {_format_path(first_path)} with initial "
|
||||||
f"value {first_member_reset!r} and the member {_format_path(path)} with reset "
|
f"value {first_member_init!r} and the member {_format_path(path)} with initial "
|
||||||
f"value {member.reset} because the reset values do not match")
|
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
|
# 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.
|
# are all identical.
|
||||||
if len(out_kind) == 0:
|
if len(out_kind) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -436,7 +436,7 @@ class _FragmentCompiler:
|
||||||
if domain_name == "comb":
|
if domain_name == "comb":
|
||||||
for signal in domain_signals:
|
for signal in domain_signals:
|
||||||
signal_index = self.state.get_signal(signal)
|
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()
|
inputs = SignalSet()
|
||||||
_StatementCompiler(self.state, emitter, inputs=inputs)(domain_stmts)
|
_StatementCompiler(self.state, emitter, inputs=inputs)(domain_stmts)
|
||||||
|
|
|
@ -83,7 +83,7 @@ class Simulator:
|
||||||
def add_process(self, process):
|
def add_process(self, process):
|
||||||
process = self._check_process(process)
|
process = self._check_process(process)
|
||||||
def wrapper():
|
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 object.__new__(Settle)
|
||||||
yield from process()
|
yield from process()
|
||||||
self._engine.add_coroutine_process(wrapper, default_cmd=None)
|
self._engine.add_coroutine_process(wrapper, default_cmd=None)
|
||||||
|
@ -188,7 +188,7 @@ class Simulator:
|
||||||
|
|
||||||
if phase is None:
|
if phase is None:
|
||||||
# By default, delay the first edge by half period. This causes any synchronous activity
|
# 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.
|
# viewer.
|
||||||
phase = period // 2
|
phase = period // 2
|
||||||
else:
|
else:
|
||||||
|
@ -199,7 +199,7 @@ class Simulator:
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""Reset the simulation.
|
"""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()
|
self._engine.reset()
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ class _VCDWriter:
|
||||||
self.vcd_signal_vars[signal] = []
|
self.vcd_signal_vars[signal] = []
|
||||||
self.gtkw_signal_names[signal] = []
|
self.gtkw_signal_names[signal] = []
|
||||||
for repr in signal._value_repr:
|
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):
|
if isinstance(repr.format, FormatInt):
|
||||||
var_type = "wire"
|
var_type = "wire"
|
||||||
var_size = repr.value.shape().width
|
var_size = repr.value.shape().width
|
||||||
|
@ -250,7 +250,7 @@ class _PySignalState(BaseSignalState):
|
||||||
self.signal = signal
|
self.signal = signal
|
||||||
self.pending = pending
|
self.pending = pending
|
||||||
self.waiters = {}
|
self.waiters = {}
|
||||||
self.curr = self.next = signal.reset
|
self.curr = self.next = signal.init
|
||||||
|
|
||||||
def set(self, value):
|
def set(self, value):
|
||||||
if self.next == value:
|
if self.next == value:
|
||||||
|
@ -342,7 +342,7 @@ class _PySimulation(BaseSimulation):
|
||||||
for signal, index in self.signals.items():
|
for signal, index in self.signals.items():
|
||||||
state = self.slots[index]
|
state = self.slots[index]
|
||||||
assert isinstance(state, _PySignalState)
|
assert isinstance(state, _PySignalState)
|
||||||
state.curr = state.next = signal.reset
|
state.curr = state.next = signal.init
|
||||||
for index in self.memories.values():
|
for index in self.memories.values():
|
||||||
state = self.slots[index]
|
state = self.slots[index]
|
||||||
assert isinstance(state, _PyMemoryState)
|
assert isinstance(state, _PyMemoryState)
|
||||||
|
|
|
@ -1174,7 +1174,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
def get_ff_sync(self, ff_sync):
|
def get_ff_sync(self, ff_sync):
|
||||||
m = Module()
|
m = Module()
|
||||||
flops = [Signal(ff_sync.i.shape(), name=f"stage{index}",
|
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"})
|
attrs={"ASYNC_REG": "TRUE"})
|
||||||
for index in range(ff_sync._stages)]
|
for index in range(ff_sync._stages)]
|
||||||
if self.toolchain == "Vivado":
|
if self.toolchain == "Vivado":
|
||||||
|
|
|
@ -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)``
|
* 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=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 ``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 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``
|
* 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 17: https://amaranth-lang.org/rfcs/0017-remove-log2-int.html
|
||||||
.. _RFC 27: https://amaranth-lang.org/rfcs/0027-simulator-testbenches.html
|
.. _RFC 27: https://amaranth-lang.org/rfcs/0027-simulator-testbenches.html
|
||||||
.. _RFC 39: https://amaranth-lang.org/rfcs/0039-empty-case.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 46: https://amaranth-lang.org/rfcs/0046-shape-range-1.html
|
||||||
|
|
||||||
* `RFC 17`_: Remove ``log2_int``
|
* `RFC 17`_: Remove ``log2_int``
|
||||||
* `RFC 27`_: Testbench processes for the simulator
|
* `RFC 27`_: Testbench processes for the simulator
|
||||||
* `RFC 39`_: Change semantics of no-argument ``m.Case()``
|
* `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)``
|
* `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`_)
|
* 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: ``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: ``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: ``Signal(range(0))`` is now valid without a warning.
|
||||||
* Changed: ``Shape.cast(range(1))`` is now ``unsigned(0)``. (`RFC 46`_)
|
* 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`_)
|
* Deprecated: :func:`amaranth.utils.log2_int`. (`RFC 17`_)
|
||||||
* Removed: (deprecated in 0.4) :meth:`Const.normalize`. (`RFC 5`_)
|
* Removed: (deprecated in 0.4) :meth:`Const.normalize`. (`RFC 5`_)
|
||||||
* Removed: (deprecated in 0.4) :class:`Repl`. (`RFC 10`_)
|
* Removed: (deprecated in 0.4) :class:`Repl`. (`RFC 10`_)
|
||||||
|
|
|
@ -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
|
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 <lang-assigns>` in a :ref:`combinatorial <lang-comb>` domain assume their initial value when none of the assignments are :ref:`active <lang-active>`. Signals assigned in a :ref:`synchronous <lang-sync>` domain assume their initial value after *power-on reset* and, unless the signal is :ref:`reset-less <lang-resetless>`, *explicit reset*. Signals that are used but never assigned are equivalent to constants of their initial value.
|
Signals :ref:`assigned <lang-assigns>` in a :ref:`combinatorial <lang-comb>` domain assume their initial value when none of the assignments are :ref:`active <lang-active>`. Signals assigned in a :ref:`synchronous <lang-sync>` domain assume their initial value after *power-on reset* and, unless the signal is :ref:`reset-less <lang-resetless>`, *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::
|
.. doctest::
|
||||||
|
|
||||||
>>> Signal(4).reset
|
>>> Signal(4).init
|
||||||
0
|
0
|
||||||
>>> Signal(4, reset=5).reset
|
>>> Signal(4, init=5).init
|
||||||
5
|
5
|
||||||
>>> Signal(Direction, reset=Direction.LEFT).reset
|
>>> Signal(Direction, init=Direction.LEFT).init
|
||||||
1
|
1
|
||||||
|
|
||||||
|
|
||||||
|
@ -467,7 +465,7 @@ In contrast, code written in the Amaranth language *describes* computations on a
|
||||||
|
|
||||||
.. doctest::
|
.. doctest::
|
||||||
|
|
||||||
>>> a = Signal(8, reset=5)
|
>>> a = Signal(8, init=5)
|
||||||
>>> a + 1
|
>>> a + 1
|
||||||
(+ (sig a) (const 1'd1))
|
(+ (sig a) (const 1'd1))
|
||||||
|
|
||||||
|
@ -1190,11 +1188,11 @@ Simple `finite state machines <https://en.wikipedia.org/wiki/Finite-state_machin
|
||||||
|
|
||||||
.. TODO: FSM() should require keyword arguments, for good measure
|
.. TODO: FSM() should require keyword arguments, for good measure
|
||||||
|
|
||||||
The reset state of the FSM can be provided when defining it using the :py:`with m.FSM(reset="Name"):` argument. If not provided, it is the first state in the order of definition. For example, this definition is equivalent to the one at the beginning of this section:
|
The initial (and reset) state of the FSM can be provided when defining it using the :py:`with m.FSM(init="Name"):` argument. If not provided, it is the first state in the order of definition. For example, this definition is equivalent to the one at the beginning of this section:
|
||||||
|
|
||||||
.. testcode::
|
.. testcode::
|
||||||
|
|
||||||
with m.FSM(reset="Set Address"):
|
with m.FSM(init="Set Address"):
|
||||||
...
|
...
|
||||||
|
|
||||||
The FSM belongs to a :ref:`clock domain <lang-domains>`, 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:
|
The FSM belongs to a :ref:`clock domain <lang-domains>`, 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::
|
.. testcode::
|
||||||
|
|
||||||
a = Signal(8, reset=1)
|
a = Signal(8, init=1)
|
||||||
with m.If(en):
|
with m.If(en):
|
||||||
m.d.comb += a.eq(b + 1)
|
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):
|
with m.If(en):
|
||||||
m.d.sync += n.eq(n + 1)
|
m.d.sync += n.eq(n + 1)
|
||||||
with m.If(rst):
|
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)
|
m.d.comb += z.eq(n == 0)
|
||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
|
|
|
@ -555,7 +555,7 @@ Signatures
|
||||||
.. autodata:: Out
|
.. autodata:: Out
|
||||||
.. autodata:: In
|
.. autodata:: In
|
||||||
|
|
||||||
.. autoclass:: Member(flow, description, *, reset=None)
|
.. autoclass:: Member(flow, description, *, init=None)
|
||||||
|
|
||||||
.. autoexception:: SignatureError
|
.. autoexception:: SignatureError
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from amaranth.cli import main
|
||||||
|
|
||||||
class Counter(Elaboratable):
|
class Counter(Elaboratable):
|
||||||
def __init__(self, width):
|
def __init__(self, width):
|
||||||
self.v = Signal(width, reset=2**width-1)
|
self.v = Signal(width, init=2**width-1)
|
||||||
self.o = Signal()
|
self.o = Signal()
|
||||||
|
|
||||||
def elaborate(self, platform):
|
def elaborate(self, platform):
|
||||||
|
|
|
@ -5,7 +5,7 @@ from amaranth.back import verilog
|
||||||
|
|
||||||
class Counter(Elaboratable):
|
class Counter(Elaboratable):
|
||||||
def __init__(self, width):
|
def __init__(self, width):
|
||||||
self.v = Signal(width, reset=2**width-1)
|
self.v = Signal(width, init=2**width-1)
|
||||||
self.o = Signal()
|
self.o = Signal()
|
||||||
self.en = Signal()
|
self.en = Signal()
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ cd_por = ClockDomain(reset_less=True)
|
||||||
cd_sync = ClockDomain()
|
cd_sync = ClockDomain()
|
||||||
m.domains += cd_por, cd_sync
|
m.domains += cd_por, cd_sync
|
||||||
|
|
||||||
delay = Signal(range(256), reset=255)
|
delay = Signal(range(256), init=255)
|
||||||
with m.If(delay != 0):
|
with m.If(delay != 0):
|
||||||
m.d.por += delay.eq(delay - 1)
|
m.d.por += delay.eq(delay - 1)
|
||||||
m.d.comb += [
|
m.d.comb += [
|
||||||
|
|
|
@ -32,7 +32,7 @@ class UART(Elaboratable):
|
||||||
m = Module()
|
m = Module()
|
||||||
|
|
||||||
tx_phase = Signal(range(self.divisor))
|
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))
|
tx_count = Signal(range(len(tx_shreg) + 1))
|
||||||
|
|
||||||
m.d.comb += self.tx_o.eq(tx_shreg[0])
|
m.d.comb += self.tx_o.eq(tx_shreg[0])
|
||||||
|
@ -55,7 +55,7 @@ class UART(Elaboratable):
|
||||||
]
|
]
|
||||||
|
|
||||||
rx_phase = Signal(range(self.divisor))
|
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))
|
rx_count = Signal(range(len(rx_shreg) + 1))
|
||||||
|
|
||||||
m.d.comb += self.rx_data.eq(rx_shreg[1:-1])
|
m.d.comb += self.rx_data.eq(rx_shreg[1:-1])
|
||||||
|
|
|
@ -1140,24 +1140,26 @@ class SignalTestCase(FHDLTestCase):
|
||||||
s2 = Signal(name="sig")
|
s2 = Signal(name="sig")
|
||||||
self.assertEqual(s2.name, "sig")
|
self.assertEqual(s2.name, "sig")
|
||||||
|
|
||||||
def test_reset(self):
|
def test_init(self):
|
||||||
s1 = Signal(4, reset=0b111, reset_less=True)
|
s1 = Signal(4, init=0b111, reset_less=True)
|
||||||
self.assertEqual(s1.reset, 0b111)
|
self.assertEqual(s1.init, 0b111)
|
||||||
self.assertEqual(s1.reset_less, True)
|
self.assertEqual(s1.reset_less, True)
|
||||||
|
s2 = Signal.like(s1, init=0b011)
|
||||||
|
self.assertEqual(s2.init, 0b011)
|
||||||
|
|
||||||
def test_reset_enum(self):
|
def test_init_enum(self):
|
||||||
s1 = Signal(2, reset=UnsignedEnum.BAR)
|
s1 = Signal(2, init=UnsignedEnum.BAR)
|
||||||
self.assertEqual(s1.reset, 2)
|
self.assertEqual(s1.init, 2)
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
r"^Reset value must be a constant-castable expression, "
|
r"^Initial value must be a constant-castable expression, "
|
||||||
r"not <StringEnum\.FOO: 'a'>$"):
|
r"not <StringEnum\.FOO: 'a'>$"):
|
||||||
Signal(1, reset=StringEnum.FOO)
|
Signal(1, init=StringEnum.FOO)
|
||||||
|
|
||||||
def test_reset_const_castable(self):
|
def test_init_const_castable(self):
|
||||||
s1 = Signal(4, reset=Cat(Const(0, 1), Const(1, 1), Const(0, 2)))
|
s1 = Signal(4, init=Cat(Const(0, 1), Const(1, 1), Const(0, 2)))
|
||||||
self.assertEqual(s1.reset, 2)
|
self.assertEqual(s1.init, 2)
|
||||||
|
|
||||||
def test_reset_shape_castable_const(self):
|
def test_init_shape_castable_const(self):
|
||||||
class CastableFromHex(ShapeCastable):
|
class CastableFromHex(ShapeCastable):
|
||||||
def as_shape(self):
|
def as_shape(self):
|
||||||
return unsigned(8)
|
return unsigned(8)
|
||||||
|
@ -1168,54 +1170,80 @@ class SignalTestCase(FHDLTestCase):
|
||||||
def const(self, init):
|
def const(self, init):
|
||||||
return int(init, 16)
|
return int(init, 16)
|
||||||
|
|
||||||
s1 = Signal(CastableFromHex(), reset="aa")
|
s1 = Signal(CastableFromHex(), init="aa")
|
||||||
self.assertEqual(s1.reset, 0xaa)
|
self.assertEqual(s1.init, 0xaa)
|
||||||
|
|
||||||
with self.assertRaisesRegex(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
r"^Constant returned by <.+?CastableFromHex.+?>\.const\(\) must have the shape "
|
r"^Constant returned by <.+?CastableFromHex.+?>\.const\(\) must have the shape "
|
||||||
r"that it casts to, unsigned\(8\), and not unsigned\(1\)$"):
|
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):
|
class EnumA(AmaranthEnum, shape=1):
|
||||||
X = 1
|
X = 1
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
r"^Reset value must be a constant initializer of <enum 'EnumA'>$"):
|
r"^Initial value must be a constant initializer of <enum 'EnumA'>$"):
|
||||||
Signal(EnumA) # implied reset=0
|
Signal(EnumA) # implied init=0
|
||||||
|
|
||||||
def test_reset_signed_mismatch(self):
|
def test_init_signed_mismatch(self):
|
||||||
with self.assertWarnsRegex(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
r"^Reset value -2 is signed, but the signal shape is unsigned\(2\)$"):
|
r"^Initial value -2 is signed, but the signal shape is unsigned\(2\)$"):
|
||||||
Signal(unsigned(2), reset=-2)
|
Signal(unsigned(2), init=-2)
|
||||||
|
|
||||||
def test_reset_wrong_too_wide(self):
|
def test_init_wrong_too_wide(self):
|
||||||
with self.assertWarnsRegex(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
r"^Reset value 2 will be truncated to the signal shape unsigned\(1\)$"):
|
r"^Initial value 2 will be truncated to the signal shape unsigned\(1\)$"):
|
||||||
Signal(unsigned(1), reset=2)
|
Signal(unsigned(1), init=2)
|
||||||
with self.assertWarnsRegex(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
r"^Reset value 1 will be truncated to the signal shape signed\(1\)$"):
|
r"^Initial value 1 will be truncated to the signal shape signed\(1\)$"):
|
||||||
Signal(signed(1), reset=1)
|
Signal(signed(1), init=1)
|
||||||
with self.assertWarnsRegex(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
r"^Reset value -2 will be truncated to the signal shape signed\(1\)$"):
|
r"^Initial value -2 will be truncated to the signal shape signed\(1\)$"):
|
||||||
Signal(signed(1), reset=-2)
|
Signal(signed(1), init=-2)
|
||||||
|
|
||||||
def test_reset_wrong_fencepost(self):
|
def test_init_wrong_fencepost(self):
|
||||||
with self.assertRaisesRegex(SyntaxError,
|
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$"):
|
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,
|
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$"):
|
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,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
r"^Reset value 11 is not within the signal shape range\(0, 10\)$"):
|
r"^Initial value 11 is not within the signal shape range\(0, 10\)$"):
|
||||||
Signal(range(0, 10), reset=11)
|
Signal(range(0, 10), init=11)
|
||||||
with self.assertRaisesRegex(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
r"^Reset value 0 is not within the signal shape range\(1, 10\)$"):
|
r"^Initial value 0 is not within the signal shape range\(1, 10\)$"):
|
||||||
Signal(range(1, 10), reset=0)
|
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):
|
def test_attrs(self):
|
||||||
s1 = Signal()
|
s1 = Signal()
|
||||||
|
@ -1232,8 +1260,8 @@ class SignalTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s1.shape(), unsigned(4))
|
self.assertEqual(s1.shape(), unsigned(4))
|
||||||
s2 = Signal.like(Signal(range(-15, 1)))
|
s2 = Signal.like(Signal(range(-15, 1)))
|
||||||
self.assertEqual(s2.shape(), signed(5))
|
self.assertEqual(s2.shape(), signed(5))
|
||||||
s3 = Signal.like(Signal(4, reset=0b111, reset_less=True))
|
s3 = Signal.like(Signal(4, init=0b111, reset_less=True))
|
||||||
self.assertEqual(s3.reset, 0b111)
|
self.assertEqual(s3.init, 0b111)
|
||||||
self.assertEqual(s3.reset_less, True)
|
self.assertEqual(s3.reset_less, True)
|
||||||
s4 = Signal.like(Signal(attrs={"no_retiming": True}))
|
s4 = Signal.like(Signal(attrs={"no_retiming": True}))
|
||||||
self.assertEqual(s4.attrs, {"no_retiming": True})
|
self.assertEqual(s4.attrs, {"no_retiming": True})
|
||||||
|
|
|
@ -451,7 +451,7 @@ class DSLTestCase(FHDLTestCase):
|
||||||
RED = 1
|
RED = 1
|
||||||
BLUE = 2
|
BLUE = 2
|
||||||
m = Module()
|
m = Module()
|
||||||
se = Signal(Color, reset=Color.RED)
|
se = Signal(Color, init=Color.RED)
|
||||||
with m.Switch(se):
|
with m.Switch(se):
|
||||||
with m.Case(Color.RED):
|
with m.Case(Color.RED):
|
||||||
m.d.comb += self.c1.eq(1)
|
m.d.comb += self.c1.eq(1)
|
||||||
|
@ -638,10 +638,10 @@ class DSLTestCase(FHDLTestCase):
|
||||||
1: "SECOND"
|
1: "SECOND"
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def test_FSM_reset(self):
|
def test_FSM_init(self):
|
||||||
a = Signal()
|
a = Signal()
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.FSM(reset="SECOND"):
|
with m.FSM(init="SECOND"):
|
||||||
with m.State("FIRST"):
|
with m.State("FIRST"):
|
||||||
m.d.comb += a.eq(0)
|
m.d.comb += a.eq(0)
|
||||||
m.next = "SECOND"
|
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):
|
def test_FSM_ongoing(self):
|
||||||
a = Signal()
|
a = Signal()
|
||||||
|
@ -683,7 +732,7 @@ class DSLTestCase(FHDLTestCase):
|
||||||
with m.State("SECOND"):
|
with m.State("SECOND"):
|
||||||
pass
|
pass
|
||||||
m._flush()
|
m._flush()
|
||||||
self.assertEqual(m._generated["fsm"].state.reset, 1)
|
self.assertEqual(m._generated["fsm"].state.init, 1)
|
||||||
self.maxDiff = 10000
|
self.maxDiff = 10000
|
||||||
self.assertRepr(m._statements["comb"], """
|
self.assertRepr(m._statements["comb"], """
|
||||||
(
|
(
|
||||||
|
|
|
@ -59,7 +59,7 @@ class MemoryTestCase(FHDLTestCase):
|
||||||
self.assertEqual(len(rdport.data), 8)
|
self.assertEqual(len(rdport.data), 8)
|
||||||
self.assertEqual(len(rdport.en), 1)
|
self.assertEqual(len(rdport.en), 1)
|
||||||
self.assertIsInstance(rdport.en, Signal)
|
self.assertIsInstance(rdport.en, Signal)
|
||||||
self.assertEqual(rdport.en.reset, 1)
|
self.assertEqual(rdport.en.init, 1)
|
||||||
|
|
||||||
def test_read_port_non_transparent(self):
|
def test_read_port_non_transparent(self):
|
||||||
mem = Memory(width=8, depth=4)
|
mem = Memory(width=8, depth=4)
|
||||||
|
@ -69,7 +69,7 @@ class MemoryTestCase(FHDLTestCase):
|
||||||
self.assertEqual(rdport.transparent, False)
|
self.assertEqual(rdport.transparent, False)
|
||||||
self.assertEqual(len(rdport.en), 1)
|
self.assertEqual(len(rdport.en), 1)
|
||||||
self.assertIsInstance(rdport.en, Signal)
|
self.assertIsInstance(rdport.en, Signal)
|
||||||
self.assertEqual(rdport.en.reset, 1)
|
self.assertEqual(rdport.en.init, 1)
|
||||||
|
|
||||||
def test_read_port_asynchronous(self):
|
def test_read_port_asynchronous(self):
|
||||||
mem = Memory(width=8, depth=4)
|
mem = Memory(width=8, depth=4)
|
||||||
|
|
|
@ -199,11 +199,11 @@ class RecordTestCase(FHDLTestCase):
|
||||||
self.assertEqual(r1.a.name, "r1__a")
|
self.assertEqual(r1.a.name, "r1__a")
|
||||||
self.assertEqual(r1.b.name, "r1__b")
|
self.assertEqual(r1.b.name, "r1__b")
|
||||||
self.assertEqual(r1.b.s.name, "r1__b__s")
|
self.assertEqual(r1.b.s.name, "r1__b__s")
|
||||||
r1.a.reset = 1
|
r1.a.init = 1
|
||||||
r1.b.s.reset = 1
|
r1.b.s.init = 1
|
||||||
r2 = Record.like(r1)
|
r2 = Record.like(r1)
|
||||||
self.assertEqual(r2.a.reset, 1)
|
self.assertEqual(r2.a.init, 1)
|
||||||
self.assertEqual(r2.b.s.reset, 1)
|
self.assertEqual(r2.b.s.init, 1)
|
||||||
self.assertEqual(r2.a.name, "r2__a")
|
self.assertEqual(r2.a.name, "r2__a")
|
||||||
self.assertEqual(r2.b.name, "r2__b")
|
self.assertEqual(r2.b.name, "r2__b")
|
||||||
self.assertEqual(r2.b.s.name, "r2__b__s")
|
self.assertEqual(r2.b.s.name, "r2__b__s")
|
||||||
|
|
|
@ -247,8 +247,8 @@ class DomainLowererTestCase(FHDLTestCase):
|
||||||
class ResetInserterTestCase(FHDLTestCase):
|
class ResetInserterTestCase(FHDLTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.s1 = Signal()
|
self.s1 = Signal()
|
||||||
self.s2 = Signal(reset=1)
|
self.s2 = Signal(init=1)
|
||||||
self.s3 = Signal(reset=1, reset_less=True)
|
self.s3 = Signal(init=1, reset_less=True)
|
||||||
self.c1 = Signal()
|
self.c1 = Signal()
|
||||||
|
|
||||||
def test_reset_default(self):
|
def test_reset_default(self):
|
||||||
|
|
|
@ -35,10 +35,10 @@ class FFSynchronizerTestCase(FHDLTestCase):
|
||||||
sim.add_process(process)
|
sim.add_process(process)
|
||||||
sim.run()
|
sim.run()
|
||||||
|
|
||||||
def test_reset_value(self):
|
def test_init_value(self):
|
||||||
i = Signal(reset=1)
|
i = Signal(init=1)
|
||||||
o = Signal()
|
o = Signal()
|
||||||
frag = FFSynchronizer(i, o, reset=1)
|
frag = FFSynchronizer(i, o, init=1)
|
||||||
|
|
||||||
sim = Simulator(frag)
|
sim = Simulator(frag)
|
||||||
sim.add_clock(1e-6)
|
sim.add_clock(1e-6)
|
||||||
|
@ -54,6 +54,34 @@ class FFSynchronizerTestCase(FHDLTestCase):
|
||||||
sim.add_process(process)
|
sim.add_process(process)
|
||||||
sim.run()
|
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):
|
class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
||||||
def test_stages_wrong(self):
|
def test_stages_wrong(self):
|
||||||
|
@ -115,7 +143,7 @@ class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
||||||
sim.run()
|
sim.run()
|
||||||
|
|
||||||
def test_neg_edge(self):
|
def test_neg_edge(self):
|
||||||
i = Signal(reset=1)
|
i = Signal(init=1)
|
||||||
o = Signal()
|
o = Signal()
|
||||||
m = Module()
|
m = Module()
|
||||||
m.domains += ClockDomain("sync")
|
m.domains += ClockDomain("sync")
|
||||||
|
@ -166,7 +194,7 @@ class ResetSynchronizerTestCase(FHDLTestCase):
|
||||||
m = Module()
|
m = Module()
|
||||||
m.domains += ClockDomain("sync")
|
m.domains += ClockDomain("sync")
|
||||||
m.submodules += ResetSynchronizer(arst)
|
m.submodules += ResetSynchronizer(arst)
|
||||||
s = Signal(reset=1)
|
s = Signal(init=1)
|
||||||
m.d.sync += s.eq(0)
|
m.d.sync += s.eq(0)
|
||||||
|
|
||||||
sim = Simulator(m)
|
sim = Simulator(m)
|
||||||
|
|
|
@ -430,13 +430,13 @@ class LayoutTestCase(FHDLTestCase):
|
||||||
sl = StructLayout({"f": unsigned(1)})
|
sl = StructLayout({"f": unsigned(1)})
|
||||||
self.assertRepr(sl.const({"f": Const(1)}).as_value(), "(const 1'd1)")
|
self.assertRepr(sl.const({"f": Const(1)}).as_value(), "(const 1'd1)")
|
||||||
|
|
||||||
def test_signal_reset(self):
|
def test_signal_init(self):
|
||||||
sl = StructLayout({
|
sl = StructLayout({
|
||||||
"a": unsigned(1),
|
"a": unsigned(1),
|
||||||
"b": unsigned(2)
|
"b": unsigned(2)
|
||||||
})
|
})
|
||||||
self.assertEqual(Signal(sl).as_value().reset, 0)
|
self.assertEqual(Signal(sl).as_value().init, 0)
|
||||||
self.assertEqual(Signal(sl, reset={"a": 0b1, "b": 0b10}).as_value().reset, 5)
|
self.assertEqual(Signal(sl, init={"a": 0b1, "b": 0b10}).as_value().init, 5)
|
||||||
|
|
||||||
|
|
||||||
class ViewTestCase(FHDLTestCase):
|
class ViewTestCase(FHDLTestCase):
|
||||||
|
@ -454,17 +454,17 @@ class ViewTestCase(FHDLTestCase):
|
||||||
self.assertEqual(cv.shape(), unsigned(3))
|
self.assertEqual(cv.shape(), unsigned(3))
|
||||||
self.assertEqual(cv.name, "v")
|
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)}),
|
v1 = Signal(StructLayout({"a": unsigned(1), "b": unsigned(2)}),
|
||||||
reset={"a": 0b1, "b": 0b10})
|
init={"a": 0b1, "b": 0b10})
|
||||||
self.assertEqual(Value.cast(v1).reset, 0b101)
|
self.assertEqual(Value.cast(v1).init, 0b101)
|
||||||
v2 = Signal(StructLayout({"a": unsigned(1),
|
v2 = Signal(StructLayout({"a": unsigned(1),
|
||||||
"b": StructLayout({"x": unsigned(1), "y": unsigned(1)})}),
|
"b": StructLayout({"x": unsigned(1), "y": unsigned(1)})}),
|
||||||
reset={"a": 0b1, "b": {"x": 0b0, "y": 0b1}})
|
init={"a": 0b1, "b": {"x": 0b0, "y": 0b1}})
|
||||||
self.assertEqual(Value.cast(v2).reset, 0b101)
|
self.assertEqual(Value.cast(v2).init, 0b101)
|
||||||
v3 = Signal(ArrayLayout(unsigned(2), 2),
|
v3 = Signal(ArrayLayout(unsigned(2), 2),
|
||||||
reset=[0b01, 0b10])
|
init=[0b01, 0b10])
|
||||||
self.assertEqual(Value.cast(v3).reset, 0b1001)
|
self.assertEqual(Value.cast(v3).init, 0b1001)
|
||||||
|
|
||||||
def test_layout_wrong(self):
|
def test_layout_wrong(self):
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
|
@ -625,13 +625,13 @@ class ViewTestCase(FHDLTestCase):
|
||||||
def test_bug_837_array_layout_getitem_str(self):
|
def test_bug_837_array_layout_getitem_str(self):
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
r"^Views with array layout may only be indexed with an integer or a value, "
|
r"^Views with array layout may only be indexed with an integer or a value, "
|
||||||
r"not 'reset'$"):
|
r"not 'init'$"):
|
||||||
Signal(ArrayLayout(unsigned(1), 1), reset=[0])["reset"]
|
Signal(ArrayLayout(unsigned(1), 1), init=[0])["init"]
|
||||||
|
|
||||||
def test_bug_837_array_layout_getattr(self):
|
def test_bug_837_array_layout_getattr(self):
|
||||||
with self.assertRaisesRegex(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
r"^View of \(sig \$signal\) with an array layout does not have fields$"):
|
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):
|
def test_eq(self):
|
||||||
s1 = Signal(StructLayout({"a": unsigned(2)}))
|
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.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))")
|
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):
|
class S(Struct):
|
||||||
p: 4
|
p: 4
|
||||||
q: 2 = 1
|
q: 2 = 1
|
||||||
|
@ -744,11 +744,11 @@ class StructTestCase(FHDLTestCase):
|
||||||
S.q
|
S.q
|
||||||
|
|
||||||
v1 = Signal(S)
|
v1 = Signal(S)
|
||||||
self.assertEqual(v1.as_value().reset, 0b010000)
|
self.assertEqual(v1.as_value().init, 0b010000)
|
||||||
v2 = Signal(S, reset=dict(p=0b0011))
|
v2 = Signal(S, init=dict(p=0b0011))
|
||||||
self.assertEqual(v2.as_value().reset, 0b010011)
|
self.assertEqual(v2.as_value().init, 0b010011)
|
||||||
v3 = Signal(S, reset=dict(p=0b0011, q=0b00))
|
v3 = Signal(S, init=dict(p=0b0011, q=0b00))
|
||||||
self.assertEqual(v3.as_value().reset, 0b000011)
|
self.assertEqual(v3.as_value().init, 0b000011)
|
||||||
|
|
||||||
def test_shape_undefined_wrong(self):
|
def test_shape_undefined_wrong(self):
|
||||||
class S(Struct):
|
class S(Struct):
|
||||||
|
@ -835,33 +835,33 @@ class UnionTestCase(FHDLTestCase):
|
||||||
self.assertRepr(v.a, "(slice (sig v) 0:1)")
|
self.assertRepr(v.a, "(slice (sig v) 0:1)")
|
||||||
self.assertRepr(v.b, "(s (slice (sig v) 0:3))")
|
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,
|
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\)$"):
|
r"\(specified: a, b\)$"):
|
||||||
class U(Union):
|
class U(Union):
|
||||||
a: unsigned(1) = 1
|
a: unsigned(1) = 1
|
||||||
b: unsigned(2) = 1
|
b: unsigned(2) = 1
|
||||||
|
|
||||||
def test_construct_reset_two_wrong(self):
|
def test_construct_init_two_wrong(self):
|
||||||
class U(Union):
|
class U(Union):
|
||||||
a: unsigned(1)
|
a: unsigned(1)
|
||||||
b: unsigned(2)
|
b: unsigned(2)
|
||||||
|
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
r"^Reset value must be a constant initializer of <class '.+?\.U'>$") as cm:
|
r"^Initial value must be a constant initializer of <class '.+?\.U'>$") as cm:
|
||||||
Signal(U, reset=dict(a=1, b=2))
|
Signal(U, init=dict(a=1, b=2))
|
||||||
self.assertRegex(cm.exception.__cause__.message,
|
self.assertRegex(cm.exception.__cause__.message,
|
||||||
r"^Initializer for at most one field can be provided for a union "
|
r"^Initializer for at most one field can be provided for a union "
|
||||||
r"class \(specified: a, b\)$")
|
r"class \(specified: a, b\)$")
|
||||||
|
|
||||||
def test_construct_reset_override(self):
|
def test_construct_init_override(self):
|
||||||
class U(Union):
|
class U(Union):
|
||||||
a: unsigned(1) = 1
|
a: unsigned(1) = 1
|
||||||
b: unsigned(2)
|
b: unsigned(2)
|
||||||
|
|
||||||
self.assertEqual(Signal(U).as_value().reset, 0b01)
|
self.assertEqual(Signal(U).as_value().init, 0b01)
|
||||||
self.assertEqual(Signal(U, reset=dict(b=0b10)).as_value().reset, 0b10)
|
self.assertEqual(Signal(U, init=dict(b=0b10)).as_value().init, 0b10)
|
||||||
|
|
||||||
|
|
||||||
# Examples from https://github.com/amaranth-lang/amaranth/issues/693
|
# Examples from https://github.com/amaranth-lang/amaranth/issues/693
|
||||||
|
|
|
@ -36,7 +36,7 @@ class MemberTestCase(unittest.TestCase):
|
||||||
self.assertEqual(member.flow, In)
|
self.assertEqual(member.flow, In)
|
||||||
self.assertEqual(member.is_port, True)
|
self.assertEqual(member.is_port, True)
|
||||||
self.assertEqual(member.shape, unsigned(1))
|
self.assertEqual(member.shape, unsigned(1))
|
||||||
self.assertEqual(member.reset, None)
|
self.assertEqual(member.init, None)
|
||||||
self.assertEqual(member.is_signature, False)
|
self.assertEqual(member.is_signature, False)
|
||||||
with self.assertRaisesRegex(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
r"^A port member does not have a signature$"):
|
r"^A port member does not have a signature$"):
|
||||||
|
@ -50,33 +50,58 @@ class MemberTestCase(unittest.TestCase):
|
||||||
r"not 'whatever'$"):
|
r"not 'whatever'$"):
|
||||||
Member(In, "whatever")
|
Member(In, "whatever")
|
||||||
|
|
||||||
def test_port_member_reset(self):
|
def test_port_member_init(self):
|
||||||
member = Member(Out, unsigned(1), reset=1)
|
member = Member(Out, unsigned(1), init=1)
|
||||||
self.assertEqual(member.flow, Out)
|
self.assertEqual(member.flow, Out)
|
||||||
self.assertEqual(member.shape, unsigned(1))
|
self.assertEqual(member.shape, unsigned(1))
|
||||||
self.assertEqual(member.reset, 1)
|
self.assertEqual(member.init, 1)
|
||||||
self.assertEqual(repr(member._reset_as_const), repr(Const(1, 1)))
|
self.assertEqual(repr(member._init_as_const), repr(Const(1, 1)))
|
||||||
self.assertEqual(repr(member), "Out(unsigned(1), reset=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,
|
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\)$"):
|
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})
|
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.flow, In)
|
||||||
self.assertEqual(member.shape, layout)
|
self.assertEqual(member.shape, layout)
|
||||||
self.assertEqual(member.reset, {"a": 1})
|
self.assertEqual(member.init, {"a": 1})
|
||||||
self.assertEqual(repr(member), "In(StructLayout({'a': 32}), reset={'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,
|
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}\)$"):
|
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):
|
def test_signature_member_out(self):
|
||||||
sig = Signature({"data": Out(unsigned(32))})
|
sig = Signature({"data": Out(unsigned(32))})
|
||||||
|
@ -87,8 +112,8 @@ class MemberTestCase(unittest.TestCase):
|
||||||
r"^A signature member does not have a shape$"):
|
r"^A signature member does not have a shape$"):
|
||||||
member.shape
|
member.shape
|
||||||
with self.assertRaisesRegex(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
r"^A signature member does not have a reset value$"):
|
r"^A signature member does not have an initial value$"):
|
||||||
member.reset
|
member.init
|
||||||
self.assertEqual(member.is_signature, True)
|
self.assertEqual(member.is_signature, True)
|
||||||
self.assertEqual(member.signature, sig)
|
self.assertEqual(member.signature, sig)
|
||||||
self.assertEqual(member.dimensions, ())
|
self.assertEqual(member.dimensions, ())
|
||||||
|
@ -103,8 +128,8 @@ class MemberTestCase(unittest.TestCase):
|
||||||
r"^A signature member does not have a shape$"):
|
r"^A signature member does not have a shape$"):
|
||||||
member.shape
|
member.shape
|
||||||
with self.assertRaisesRegex(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
r"^A signature member does not have a reset value$"):
|
r"^A signature member does not have an initial value$"):
|
||||||
member.reset
|
member.init
|
||||||
self.assertEqual(member.is_signature, True)
|
self.assertEqual(member.is_signature, True)
|
||||||
self.assertEqual(member.signature, sig.flip())
|
self.assertEqual(member.signature, sig.flip())
|
||||||
self.assertEqual(member.dimensions, ())
|
self.assertEqual(member.dimensions, ())
|
||||||
|
@ -112,8 +137,8 @@ class MemberTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def test_signature_member_wrong(self):
|
def test_signature_member_wrong(self):
|
||||||
with self.assertRaisesRegex(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
r"^A signature member cannot have a reset value$"):
|
r"^A signature member cannot have an initial value$"):
|
||||||
Member(In, Signature({}), reset=1)
|
Member(In, Signature({}), init=1)
|
||||||
|
|
||||||
def test_array(self):
|
def test_array(self):
|
||||||
array_2 = Member(In, unsigned(1)).array(2)
|
array_2 = Member(In, unsigned(1)).array(2)
|
||||||
|
@ -143,8 +168,8 @@ class MemberTestCase(unittest.TestCase):
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
self.assertEqual(In(1), In(1))
|
self.assertEqual(In(1), In(1))
|
||||||
self.assertNotEqual(In(1), Out(1))
|
self.assertNotEqual(In(1), Out(1))
|
||||||
self.assertNotEqual(In(1), In(1, reset=1))
|
self.assertNotEqual(In(1), In(1, init=1))
|
||||||
self.assertNotEqual(In(1), In(1, reset=0))
|
self.assertNotEqual(In(1), In(1, init=0))
|
||||||
self.assertEqual(In(1), In(1).array())
|
self.assertEqual(In(1), In(1).array())
|
||||||
self.assertNotEqual(In(1), In(1).array(1))
|
self.assertNotEqual(In(1), In(1).array(1))
|
||||||
sig = Signature({})
|
sig = Signature({})
|
||||||
|
@ -237,12 +262,12 @@ class SignatureMembersTestCase(unittest.TestCase):
|
||||||
self.assertEqual(attrs["s"].b.shape(), unsigned(2))
|
self.assertEqual(attrs["s"].b.shape(), unsigned(2))
|
||||||
self.assertEqual(attrs["s"].b.name, "attrs__s__b")
|
self.assertEqual(attrs["s"].b.name, "attrs__s__b")
|
||||||
|
|
||||||
def test_create_reset(self):
|
def test_create_init(self):
|
||||||
members = SignatureMembers({
|
members = SignatureMembers({
|
||||||
"a": In(1, reset=1),
|
"a": In(1, init=1),
|
||||||
})
|
})
|
||||||
attrs = members.create()
|
attrs = members.create()
|
||||||
self.assertEqual(attrs["a"].reset, 1)
|
self.assertEqual(attrs["a"].init, 1)
|
||||||
|
|
||||||
def test_create_tuple(self):
|
def test_create_tuple(self):
|
||||||
sig = SignatureMembers({
|
sig = SignatureMembers({
|
||||||
|
@ -421,12 +446,12 @@ class SignatureTestCase(unittest.TestCase):
|
||||||
sig=Signature({"a": In(unsigned(1))}),
|
sig=Signature({"a": In(unsigned(1))}),
|
||||||
obj=NS(a=Signal(signed(1))))
|
obj=NS(a=Signal(signed(1))))
|
||||||
self.assertNotCompliant(
|
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)}),
|
sig=Signature({"a": In(1)}),
|
||||||
obj=NS(a=Signal(reset=1)))
|
obj=NS(a=Signal(init=1)))
|
||||||
self.assertNotCompliant(
|
self.assertNotCompliant(
|
||||||
r"^'obj\.a' is expected to have the reset value 1, but it has the reset value 0$",
|
r"^'obj\.a' is expected to have the initial value 1, but it has the initial value 0$",
|
||||||
sig=Signature({"a": In(1, reset=1)}),
|
sig=Signature({"a": In(1, init=1)}),
|
||||||
obj=NS(a=Signal(1)))
|
obj=NS(a=Signal(1)))
|
||||||
self.assertNotCompliant(
|
self.assertNotCompliant(
|
||||||
r"^'obj\.a' is expected to not be reset-less$",
|
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)}),
|
q=NS(signature=Signature({"a": In(Cycle)}),
|
||||||
a=Signal(Cycle)))
|
a=Signal(Cycle)))
|
||||||
|
|
||||||
def test_reset_mismatch(self):
|
def test_init_mismatch(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaisesRegex(ConnectionError,
|
with self.assertRaisesRegex(ConnectionError,
|
||||||
r"^Cannot connect together the member 'q\.a' with reset value 1 and the member "
|
r"^Cannot connect together the member 'q\.a' with initial value 1 and the member "
|
||||||
r"'p\.a' with reset value 0 because the reset values do not match$"):
|
r"'p\.a' with initial value 0 because the initial values do not match$"):
|
||||||
connect(m,
|
connect(m,
|
||||||
p=NS(signature=Signature({"a": Out(1, reset=0)}),
|
p=NS(signature=Signature({"a": Out(1, init=0)}),
|
||||||
a=Signal()),
|
a=Signal()),
|
||||||
q=NS(signature=Signature({"a": In(1, reset=1)}),
|
q=NS(signature=Signature({"a": In(1, init=1)}),
|
||||||
a=Signal(reset=1)))
|
a=Signal(init=1)))
|
||||||
|
|
||||||
def test_reset_none_match(self):
|
def test_init_none_match(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
connect(m,
|
connect(m,
|
||||||
p=NS(signature=Signature({"a": Out(1, reset=0)}),
|
p=NS(signature=Signature({"a": Out(1, init=0)}),
|
||||||
a=Signal()),
|
a=Signal()),
|
||||||
q=NS(signature=Signature({"a": In(1)}),
|
q=NS(signature=Signature({"a": In(1)}),
|
||||||
a=Signal()))
|
a=Signal()))
|
||||||
|
|
|
@ -18,12 +18,12 @@ from amaranth._utils import _ignore_deprecated
|
||||||
|
|
||||||
|
|
||||||
class SimulatorUnitTestCase(FHDLTestCase):
|
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]
|
inputs = [Value.cast(i) for i in inputs]
|
||||||
output = Value.cast(output)
|
output = Value.cast(output)
|
||||||
|
|
||||||
isigs = [Signal(i.shape(), name=n) for i, n in zip(inputs, "abcd")]
|
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)
|
stmt = stmt(osig, *isigs)
|
||||||
frag = Fragment()
|
frag = Fragment()
|
||||||
|
@ -243,9 +243,9 @@ class SimulatorUnitTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_slice_lhs(self):
|
def test_slice_lhs(self):
|
||||||
stmt1 = lambda y, a: y[2].eq(a)
|
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)
|
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):
|
def test_bit_select(self):
|
||||||
stmt = lambda y, a, b: y.eq(a.bit_select(b, 3))
|
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):
|
def test_bit_select_lhs(self):
|
||||||
stmt = lambda y, a, b: y.bit_select(a, 3).eq(b)
|
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(0), C(0b100, 3)], C(0b11111100, 8), init=0b11111111)
|
||||||
self.assertStatement(stmt, [C(2), C(0b101, 3)], C(0b11110111, 8), reset=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), reset=0b11111111)
|
self.assertStatement(stmt, [C(3), C(0b110, 3)], C(0b11110111, 8), init=0b11111111)
|
||||||
|
|
||||||
def test_word_select(self):
|
def test_word_select(self):
|
||||||
stmt = lambda y, a, b: y.eq(a.word_select(b, 3))
|
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):
|
def test_word_select_lhs(self):
|
||||||
stmt = lambda y, a, b: y.word_select(a, 3).eq(b)
|
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(0), C(0b100, 3)], C(0b11111100, 8), init=0b11111111)
|
||||||
self.assertStatement(stmt, [C(1), C(0b101, 3)], C(0b11101111, 8), reset=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), reset=0b11111111)
|
self.assertStatement(stmt, [C(2), C(0b110, 3)], C(0b10111111, 8), init=0b11111111)
|
||||||
|
|
||||||
def test_cat(self):
|
def test_cat(self):
|
||||||
stmt = lambda y, *xs: y.eq(Cat(*xs))
|
stmt = lambda y, *xs: y.eq(Cat(*xs))
|
||||||
|
@ -315,9 +315,9 @@ class SimulatorUnitTestCase(FHDLTestCase):
|
||||||
self.assertStatement(stmt, [C(4)], C(10))
|
self.assertStatement(stmt, [C(4)], C(10))
|
||||||
|
|
||||||
def test_array_lhs(self):
|
def test_array_lhs(self):
|
||||||
l = Signal(3, reset=1)
|
l = Signal(3, init=1)
|
||||||
m = Signal(3, reset=4)
|
m = Signal(3, init=4)
|
||||||
n = Signal(3, reset=7)
|
n = Signal(3, init=7)
|
||||||
array = Array([l, m, n])
|
array = Array([l, m, n])
|
||||||
stmt = lambda y, a, b: [array[a].eq(b), y.eq(Cat(*array))]
|
stmt = lambda y, a, b: [array[a].eq(b), y.eq(Cat(*array))]
|
||||||
self.assertStatement(stmt, [C(0), C(0b000)], C(0b111100000))
|
self.assertStatement(stmt, [C(0), C(0b000)], C(0b111100000))
|
||||||
|
@ -426,7 +426,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
||||||
sim.run_until(deadline)
|
sim.run_until(deadline)
|
||||||
|
|
||||||
def setUp_counter(self):
|
def setUp_counter(self):
|
||||||
self.count = Signal(3, reset=4)
|
self.count = Signal(3, init=4)
|
||||||
self.sync = ClockDomain()
|
self.sync = ClockDomain()
|
||||||
|
|
||||||
self.m = Module()
|
self.m = Module()
|
||||||
|
@ -876,7 +876,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_comb_bench_process(self):
|
def test_comb_bench_process(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
a = Signal(reset=1)
|
a = Signal(init=1)
|
||||||
b = Signal()
|
b = Signal()
|
||||||
m.d.comb += b.eq(a)
|
m.d.comb += b.eq(a)
|
||||||
with self.assertSimulation(m) as sim:
|
with self.assertSimulation(m) as sim:
|
||||||
|
@ -890,7 +890,7 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_sync_bench_process(self):
|
def test_sync_bench_process(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
a = Signal(reset=1)
|
a = Signal(init=1)
|
||||||
b = Signal()
|
b = Signal()
|
||||||
m.d.sync += b.eq(a)
|
m.d.sync += b.eq(a)
|
||||||
t = Signal()
|
t = Signal()
|
||||||
|
|
Loading…
Reference in a new issue