parent
e4e26717be
commit
e18385b613
|
@ -17,5 +17,4 @@ __all__ = [
|
||||||
"Memory",
|
"Memory",
|
||||||
"Record",
|
"Record",
|
||||||
"DomainRenamer", "ResetInserter", "EnableInserter",
|
"DomainRenamer", "ResetInserter", "EnableInserter",
|
||||||
"CEInserter", # TODO(nmigen-0.2): remove this
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,6 +7,7 @@ from ...hdl.mem import Memory as NativeMemory
|
||||||
from ...hdl.ir import Fragment, Instance
|
from ...hdl.ir import Fragment, Instance
|
||||||
from ...hdl.dsl import Module
|
from ...hdl.dsl import Module
|
||||||
from .module import Module as CompatModule
|
from .module import Module as CompatModule
|
||||||
|
from .structure import Signal
|
||||||
from ...lib.io import Pin
|
from ...lib.io import Pin
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
|
import builtins
|
||||||
|
import warnings
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from ...utils import bits_for
|
||||||
from ..._utils import deprecated, extend
|
from ..._utils import deprecated, extend
|
||||||
from ...hdl import ast
|
from ...hdl import ast
|
||||||
from ...hdl.ast import (DUID, Value, Signal, Mux, Slice as _Slice, Cat, Repl, Const, C,
|
from ...hdl.ast import (DUID,
|
||||||
|
Shape, signed, unsigned,
|
||||||
|
Value, Const, C, Mux, Slice as _Slice, Part, Cat, Repl,
|
||||||
|
Signal as NativeSignal,
|
||||||
ClockSignal, ResetSignal,
|
ClockSignal, ResetSignal,
|
||||||
Array, ArrayProxy as _ArrayProxy)
|
Array, ArrayProxy as _ArrayProxy)
|
||||||
from ...hdl.cd import ClockDomain
|
from ...hdl.cd import ClockDomain
|
||||||
|
@ -17,11 +23,47 @@ def wrap(v):
|
||||||
return Value.cast(v)
|
return Value.cast(v)
|
||||||
|
|
||||||
|
|
||||||
@extend(Cat)
|
class CompatSignal(NativeSignal):
|
||||||
@property
|
def __init__(self, bits_sign=None, name=None, variable=False, reset=0,
|
||||||
@deprecated("instead of `Cat.l`, use `Cat.parts`")
|
reset_less=False, name_override=None, min=None, max=None,
|
||||||
def l(self):
|
related=None, attr=None, src_loc_at=0, **kwargs):
|
||||||
return self.parts
|
if min is not None or max is not None:
|
||||||
|
warnings.warn("instead of `Signal(min={min}, max={max})`, "
|
||||||
|
"use `Signal(range({min}, {max}))`"
|
||||||
|
.format(min=min or 0, max=max or 2),
|
||||||
|
DeprecationWarning, stacklevel=2 + src_loc_at)
|
||||||
|
|
||||||
|
if bits_sign is None:
|
||||||
|
if min is None:
|
||||||
|
min = 0
|
||||||
|
if max is None:
|
||||||
|
max = 2
|
||||||
|
max -= 1 # make both bounds inclusive
|
||||||
|
if min > max:
|
||||||
|
raise ValueError("Lower bound {} should be less or equal to higher bound {}"
|
||||||
|
.format(min, max + 1))
|
||||||
|
sign = min < 0 or max < 0
|
||||||
|
if min == max:
|
||||||
|
bits = 0
|
||||||
|
else:
|
||||||
|
bits = builtins.max(bits_for(min, sign), bits_for(max, sign))
|
||||||
|
shape = signed(bits) if sign else unsigned(bits)
|
||||||
|
else:
|
||||||
|
if not (min is None and max is None):
|
||||||
|
raise ValueError("Only one of bits/signedness or bounds may be specified")
|
||||||
|
shape = bits_sign
|
||||||
|
|
||||||
|
super().__init__(shape=shape, name=name_override or name,
|
||||||
|
reset=reset, reset_less=reset_less,
|
||||||
|
attrs=attr, src_loc_at=1 + src_loc_at, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
Signal = CompatSignal
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated("instead of `Constant`, use `Const`")
|
||||||
|
def Constant(value, bits_sign=None):
|
||||||
|
return Const(value, bits_sign)
|
||||||
|
|
||||||
|
|
||||||
@deprecated("instead of `Replicate`, use `Repl`")
|
@deprecated("instead of `Replicate`, use `Repl`")
|
||||||
|
@ -29,9 +71,45 @@ def Replicate(v, n):
|
||||||
return Repl(v, n)
|
return Repl(v, n)
|
||||||
|
|
||||||
|
|
||||||
@deprecated("instead of `Constant`, use `Const`")
|
@extend(Const)
|
||||||
def Constant(value, bits_sign=None):
|
@property
|
||||||
return Const(value, bits_sign)
|
@deprecated("instead of `.nbits`, use `.width`")
|
||||||
|
def nbits(self):
|
||||||
|
return self.width
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeSignal)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `.nbits`, use `.width`")
|
||||||
|
def nbits(self):
|
||||||
|
return self.width
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeSignal)
|
||||||
|
@NativeSignal.nbits.setter
|
||||||
|
@deprecated("instead of `.nbits = x`, use `.width = x`")
|
||||||
|
def nbits(self, value):
|
||||||
|
self.width = value
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeSignal)
|
||||||
|
@deprecated("instead of `.part`, use `.bit_select`")
|
||||||
|
def part(self, offset, width):
|
||||||
|
return Part(self, offset, width, src_loc_at=2)
|
||||||
|
|
||||||
|
|
||||||
|
@extend(Cat)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `.l`, use `.parts`")
|
||||||
|
def l(self):
|
||||||
|
return self.parts
|
||||||
|
|
||||||
|
|
||||||
|
@extend(ast.Operator)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `.op`, use `.operator`")
|
||||||
|
def op(self):
|
||||||
|
return self.operator
|
||||||
|
|
||||||
|
|
||||||
@extend(_ArrayProxy)
|
@extend(_ArrayProxy)
|
||||||
|
@ -47,7 +125,7 @@ class If(ast.Switch):
|
||||||
cond = Value.cast(cond)
|
cond = Value.cast(cond)
|
||||||
if len(cond) != 1:
|
if len(cond) != 1:
|
||||||
cond = cond.bool()
|
cond = cond.bool()
|
||||||
super().__init__(cond, {("1",): ast.Statement.wrap(stmts)})
|
super().__init__(cond, {("1",): ast.Statement.cast(stmts)})
|
||||||
|
|
||||||
@deprecated("instead of `.Elif(cond, ...)`, use `with m.Elif(cond): ...`")
|
@deprecated("instead of `.Elif(cond, ...)`, use `with m.Elif(cond): ...`")
|
||||||
def Elif(self, cond, *stmts):
|
def Elif(self, cond, *stmts):
|
||||||
|
@ -55,13 +133,13 @@ class If(ast.Switch):
|
||||||
if len(cond) != 1:
|
if len(cond) != 1:
|
||||||
cond = cond.bool()
|
cond = cond.bool()
|
||||||
self.cases = OrderedDict((("-" + k,), v) for (k,), v in self.cases.items())
|
self.cases = OrderedDict((("-" + k,), v) for (k,), v in self.cases.items())
|
||||||
self.cases[("1" + "-" * len(self.test),)] = ast.Statement.wrap(stmts)
|
self.cases[("1" + "-" * len(self.test),)] = ast.Statement.cast(stmts)
|
||||||
self.test = Cat(self.test, cond)
|
self.test = Cat(self.test, cond)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@deprecated("instead of `.Else(...)`, use `with m.Else(): ...`")
|
@deprecated("instead of `.Else(...)`, use `with m.Else(): ...`")
|
||||||
def Else(self, *stmts):
|
def Else(self, *stmts):
|
||||||
self.cases[()] = ast.Statement.wrap(stmts)
|
self.cases[()] = ast.Statement.cast(stmts)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,7 +178,7 @@ class Case(ast.Switch):
|
||||||
elif isinstance(key, str) and key == "default":
|
elif isinstance(key, str) and key == "default":
|
||||||
key = ()
|
key = ()
|
||||||
else:
|
else:
|
||||||
key = ("{:0{}b}".format(wrap(key).value, len(self.test)),)
|
key = ("{:0{}b}".format(ast.Value.cast(key).value, len(self.test)),)
|
||||||
stmts = self.cases[key]
|
stmts = self.cases[key]
|
||||||
del self.cases[key]
|
del self.cases[key]
|
||||||
self.cases[()] = stmts
|
self.cases[()] = stmts
|
||||||
|
|
|
@ -14,6 +14,90 @@ class CompatFIFOInterface(NativeFIFOInterface):
|
||||||
del self.fwft
|
del self.fwft
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `fifo.din`, use `fifo.w_data`")
|
||||||
|
def din(self):
|
||||||
|
return self.w_data
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@NativeFIFOInterface.din.setter
|
||||||
|
@deprecated("instead of `fifo.din = x`, use `fifo.w_data = x`")
|
||||||
|
def din(self, w_data):
|
||||||
|
self.w_data = w_data
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `fifo.writable`, use `fifo.w_rdy`")
|
||||||
|
def writable(self):
|
||||||
|
return self.w_rdy
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@NativeFIFOInterface.writable.setter
|
||||||
|
@deprecated("instead of `fifo.writable = x`, use `fifo.w_rdy = x`")
|
||||||
|
def writable(self, w_rdy):
|
||||||
|
self.w_rdy = w_rdy
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `fifo.we`, use `fifo.w_en`")
|
||||||
|
def we(self):
|
||||||
|
return self.w_en
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@NativeFIFOInterface.we.setter
|
||||||
|
@deprecated("instead of `fifo.we = x`, use `fifo.w_en = x`")
|
||||||
|
def we(self, w_en):
|
||||||
|
self.w_en = w_en
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `fifo.dout`, use `fifo.r_data`")
|
||||||
|
def dout(self):
|
||||||
|
return self.r_data
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@NativeFIFOInterface.dout.setter
|
||||||
|
@deprecated("instead of `fifo.dout = x`, use `fifo.r_data = x`")
|
||||||
|
def dout(self, r_data):
|
||||||
|
self.r_data = r_data
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `fifo.readable`, use `fifo.r_rdy`")
|
||||||
|
def readable(self):
|
||||||
|
return self.r_rdy
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@NativeFIFOInterface.readable.setter
|
||||||
|
@deprecated("instead of `fifo.readable = x`, use `fifo.r_rdy = x`")
|
||||||
|
def readable(self, r_rdy):
|
||||||
|
self.r_rdy = r_rdy
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@property
|
||||||
|
@deprecated("instead of `fifo.re`, use `fifo.r_en`")
|
||||||
|
def re(self):
|
||||||
|
return self.r_en
|
||||||
|
|
||||||
|
|
||||||
|
@extend(NativeFIFOInterface)
|
||||||
|
@NativeFIFOInterface.re.setter
|
||||||
|
@deprecated("instead of `fifo.re = x`, use `fifo.r_en = x`")
|
||||||
|
def re(self, r_en):
|
||||||
|
self.r_en = r_en
|
||||||
|
|
||||||
|
|
||||||
@extend(NativeFIFOInterface)
|
@extend(NativeFIFOInterface)
|
||||||
def read(self):
|
def read(self):
|
||||||
"""Read method for simulation."""
|
"""Read method for simulation."""
|
||||||
|
|
|
@ -3,8 +3,9 @@ from collections import OrderedDict
|
||||||
from ..._utils import deprecated, _ignore_deprecated
|
from ..._utils import deprecated, _ignore_deprecated
|
||||||
from ...hdl.xfrm import ValueTransformer, StatementTransformer
|
from ...hdl.xfrm import ValueTransformer, StatementTransformer
|
||||||
from ...hdl.ast import *
|
from ...hdl.ast import *
|
||||||
|
from ...hdl.ast import Signal as NativeSignal
|
||||||
from ..fhdl.module import CompatModule, CompatFinalizeError
|
from ..fhdl.module import CompatModule, CompatFinalizeError
|
||||||
from ..fhdl.structure import If, Case
|
from ..fhdl.structure import Signal, If, Case
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["AnonymousState", "NextState", "NextValue", "FSM"]
|
__all__ = ["AnonymousState", "NextState", "NextValue", "FSM"]
|
||||||
|
@ -33,7 +34,7 @@ def _target_eq(a, b):
|
||||||
ty = type(a)
|
ty = type(a)
|
||||||
if ty == Const:
|
if ty == Const:
|
||||||
return a.value == b.value
|
return a.value == b.value
|
||||||
elif ty == Signal:
|
elif ty == NativeSignal or ty == Signal:
|
||||||
return a is b
|
return a is b
|
||||||
elif ty == Cat:
|
elif ty == Cat:
|
||||||
return all(_target_eq(x, y) for x, y in zip(a.l, b.l))
|
return all(_target_eq(x, y) for x, y in zip(a.l, b.l))
|
||||||
|
@ -164,7 +165,7 @@ class FSM(CompatModule):
|
||||||
self.decoding = {n: s for s, n in self.encoding.items()}
|
self.decoding = {n: s for s, n in self.encoding.items()}
|
||||||
|
|
||||||
decoder = lambda n: "{}/{}".format(self.decoding[n], n)
|
decoder = lambda n: "{}/{}".format(self.decoding[n], n)
|
||||||
self.state = Signal(max=nstates, reset=self.encoding[self.reset_state], decoder=decoder)
|
self.state = Signal(range(nstates), reset=self.encoding[self.reset_state], decoder=decoder)
|
||||||
self.next_state = Signal.like(self.state)
|
self.next_state = Signal.like(self.state)
|
||||||
|
|
||||||
for state, signal in self.before_leaving_signals.items():
|
for state, signal in self.before_leaving_signals.items():
|
||||||
|
|
|
@ -5,8 +5,7 @@ from .cd import ClockDomain
|
||||||
from .ir import Elaboratable, Fragment, Instance
|
from .ir import Elaboratable, Fragment, Instance
|
||||||
from .mem import Memory
|
from .mem import Memory
|
||||||
from .rec import Record
|
from .rec import Record
|
||||||
from .xfrm import DomainRenamer, ResetInserter, EnableInserter, \
|
from .xfrm import DomainRenamer, ResetInserter, EnableInserter
|
||||||
CEInserter # TODO(nmigen-0.2): remove this
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -18,5 +17,4 @@ __all__ = [
|
||||||
"Memory",
|
"Memory",
|
||||||
"Record",
|
"Record",
|
||||||
"DomainRenamer", "ResetInserter", "EnableInserter",
|
"DomainRenamer", "ResetInserter", "EnableInserter",
|
||||||
"CEInserter", # TODO(nmigen-0.2): remove this
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
import builtins
|
|
||||||
import traceback
|
import traceback
|
||||||
import warnings
|
import warnings
|
||||||
import typing
|
import typing
|
||||||
|
@ -124,12 +123,6 @@ class Value(metaclass=ABCMeta):
|
||||||
return Const(obj.value, Shape.cast(type(obj)))
|
return Const(obj.value, Shape.cast(type(obj)))
|
||||||
raise TypeError("Object {!r} cannot be converted to an nMigen value".format(obj))
|
raise TypeError("Object {!r} cannot be converted to an nMigen value".format(obj))
|
||||||
|
|
||||||
# TODO(nmigen-0.2): remove this
|
|
||||||
@classmethod
|
|
||||||
@deprecated("instead of `Value.wrap`, use `Value.cast`")
|
|
||||||
def wrap(cls, obj):
|
|
||||||
return cls.cast(obj)
|
|
||||||
|
|
||||||
def __init__(self, *, src_loc_at=0):
|
def __init__(self, *, src_loc_at=0):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.src_loc = tracer.get_src_loc(1 + src_loc_at)
|
self.src_loc = tracer.get_src_loc(1 + src_loc_at)
|
||||||
|
@ -281,11 +274,6 @@ class Value(metaclass=ABCMeta):
|
||||||
"""
|
"""
|
||||||
return ~premise | conclusion
|
return ~premise | conclusion
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@deprecated("instead of `.part`, use `.bit_select`")
|
|
||||||
def part(self, offset, width):
|
|
||||||
return Part(self, offset, width, src_loc_at=1)
|
|
||||||
|
|
||||||
def bit_select(self, offset, width):
|
def bit_select(self, offset, width):
|
||||||
"""Part-select with bit granularity.
|
"""Part-select with bit granularity.
|
||||||
|
|
||||||
|
@ -471,12 +459,6 @@ class Const(Value):
|
||||||
self.width, self.signed = shape
|
self.width, self.signed = shape
|
||||||
self.value = self.normalize(self.value, shape)
|
self.value = self.normalize(self.value, shape)
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `const.nbits`, use `const.width`")
|
|
||||||
def nbits(self):
|
|
||||||
return self.width
|
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.width, self.signed)
|
return Shape(self.width, self.signed)
|
||||||
|
|
||||||
|
@ -527,12 +509,6 @@ class Operator(Value):
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.operands = [Value.cast(op) for op in operands]
|
self.operands = [Value.cast(op) for op in operands]
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `.op`, use `.operator`")
|
|
||||||
def op(self):
|
|
||||||
return self.operator
|
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
def _bitwise_binary_shape(a_shape, b_shape):
|
def _bitwise_binary_shape(a_shape, b_shape):
|
||||||
a_bits, a_sign = a_shape
|
a_bits, a_sign = a_shape
|
||||||
|
@ -644,13 +620,7 @@ class Slice(Value):
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.value = Value.cast(value)
|
self.value = Value.cast(value)
|
||||||
self.start = start
|
self.start = start
|
||||||
self.stop = stop
|
self.stop = stop
|
||||||
|
|
||||||
# TODO(nmigen-0.2): remove this
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `slice.end`, use `slice.stop`")
|
|
||||||
def end(self):
|
|
||||||
return self.stop
|
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.stop - self.start)
|
return Shape(self.stop - self.start)
|
||||||
|
@ -782,7 +752,7 @@ class Repl(Value):
|
||||||
return "(repl {!r} {})".format(self.value, self.count)
|
return "(repl {!r} {})".format(self.value, self.count)
|
||||||
|
|
||||||
|
|
||||||
@final
|
# @final
|
||||||
class Signal(Value, DUID):
|
class Signal(Value, DUID):
|
||||||
"""A varying integer value.
|
"""A varying integer value.
|
||||||
|
|
||||||
|
@ -830,46 +800,22 @@ class Signal(Value, DUID):
|
||||||
attrs : dict
|
attrs : dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, shape=None, *, name=None, reset=0, reset_less=False, min=None, max=None,
|
def __init__(self, shape=None, *, name=None, reset=0, 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)
|
||||||
|
|
||||||
if isinstance(reset, Enum):
|
|
||||||
reset = reset.value
|
|
||||||
if not isinstance(reset, int):
|
|
||||||
raise TypeError("Reset value has to be an int or an integral Enum")
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
if min is not None or max is not None:
|
|
||||||
warnings.warn("instead of `Signal(min={min}, max={max})`, "
|
|
||||||
"use `Signal(range({min}, {max}))`"
|
|
||||||
.format(min=min or 0, max=max or 2),
|
|
||||||
DeprecationWarning, stacklevel=2 + src_loc_at)
|
|
||||||
|
|
||||||
if name is not None and not isinstance(name, str):
|
if name is not None and not isinstance(name, str):
|
||||||
raise TypeError("Name must be a string, not {!r}".format(name))
|
raise TypeError("Name must be a string, not {!r}".format(name))
|
||||||
self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal")
|
self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal")
|
||||||
|
|
||||||
if shape is None:
|
if shape is None:
|
||||||
if min is None:
|
shape = unsigned(1)
|
||||||
min = 0
|
self.width, self.signed = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
||||||
if max is None:
|
|
||||||
max = 2
|
|
||||||
max -= 1 # make both bounds inclusive
|
|
||||||
if min > max:
|
|
||||||
raise ValueError("Lower bound {} should be less or equal to higher bound {}"
|
|
||||||
.format(min, max + 1))
|
|
||||||
self.signed = min < 0 or max < 0
|
|
||||||
if min == max:
|
|
||||||
self.width = 0
|
|
||||||
else:
|
|
||||||
self.width = builtins.max(bits_for(min, self.signed),
|
|
||||||
bits_for(max, self.signed))
|
|
||||||
|
|
||||||
else:
|
if isinstance(reset, Enum):
|
||||||
if not (min is None and max is None):
|
reset = reset.value
|
||||||
raise ValueError("Only one of bits/signedness or bounds may be specified")
|
if not isinstance(reset, int):
|
||||||
self.width, self.signed = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
raise TypeError("Reset value has to be an int or an integral Enum")
|
||||||
|
|
||||||
reset_width = bits_for(reset, self.signed)
|
reset_width = bits_for(reset, self.signed)
|
||||||
if reset != 0 and reset_width > self.width:
|
if reset != 0 and reset_width > self.width:
|
||||||
|
@ -878,7 +824,7 @@ class Signal(Value, DUID):
|
||||||
.format(reset, reset_width, self.width),
|
.format(reset, reset_width, self.width),
|
||||||
SyntaxWarning, stacklevel=2 + src_loc_at)
|
SyntaxWarning, stacklevel=2 + src_loc_at)
|
||||||
|
|
||||||
self.reset = int(reset)
|
self.reset = reset
|
||||||
self.reset_less = bool(reset_less)
|
self.reset_less = bool(reset_less)
|
||||||
|
|
||||||
self.attrs = OrderedDict(() if attrs is None else attrs)
|
self.attrs = OrderedDict(() if attrs is None else attrs)
|
||||||
|
@ -895,20 +841,9 @@ class Signal(Value, DUID):
|
||||||
else:
|
else:
|
||||||
self.decoder = decoder
|
self.decoder = decoder
|
||||||
|
|
||||||
@classmethod
|
# Not a @classmethod because nmigen.compat requires it.
|
||||||
@deprecated("instead of `Signal.range(...)`, use `Signal(range(...))`")
|
@staticmethod
|
||||||
def range(cls, *args, src_loc_at=0, **kwargs):
|
def like(other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs):
|
||||||
return cls(range(*args), src_loc_at=2 + src_loc_at, **kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
@deprecated("instead of `Signal.enum(...)`, use `Signal(...)`")
|
|
||||||
def enum(cls, enum_type, *, src_loc_at=0, **kwargs):
|
|
||||||
if not issubclass(enum_type, Enum):
|
|
||||||
raise TypeError("Type {!r} is not an enumeration")
|
|
||||||
return cls(enum_type, src_loc_at=2 + src_loc_at, **kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def like(cls, other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs):
|
|
||||||
"""Create Signal based on another.
|
"""Create Signal based on another.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -922,23 +857,12 @@ class Signal(Value, DUID):
|
||||||
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")
|
||||||
kw = dict(shape=cls.cast(other).shape(), name=new_name)
|
kw = dict(shape=Value.cast(other).shape(), name=new_name)
|
||||||
if isinstance(other, cls):
|
if isinstance(other, Signal):
|
||||||
kw.update(reset=other.reset, reset_less=other.reset_less,
|
kw.update(reset=other.reset, reset_less=other.reset_less,
|
||||||
attrs=other.attrs, decoder=other.decoder)
|
attrs=other.attrs, decoder=other.decoder)
|
||||||
kw.update(kwargs)
|
kw.update(kwargs)
|
||||||
return cls(**kw, src_loc_at=1 + src_loc_at)
|
return Signal(**kw, src_loc_at=1 + src_loc_at)
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `signal.nbits`, use `signal.width`")
|
|
||||||
def nbits(self):
|
|
||||||
return self.width
|
|
||||||
|
|
||||||
@nbits.setter
|
|
||||||
@deprecated("instead of `signal.nbits = x`, use `signal.width = x`")
|
|
||||||
def nbits(self, value):
|
|
||||||
self.width = value
|
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.width, self.signed)
|
return Shape(self.width, self.signed)
|
||||||
|
@ -1269,12 +1193,6 @@ class Statement:
|
||||||
def __init__(self, *, src_loc_at=0):
|
def __init__(self, *, src_loc_at=0):
|
||||||
self.src_loc = tracer.get_src_loc(1 + src_loc_at)
|
self.src_loc = tracer.get_src_loc(1 + src_loc_at)
|
||||||
|
|
||||||
# TODO(nmigen-0.2): remove this
|
|
||||||
@classmethod
|
|
||||||
@deprecated("instead of `Statement.wrap`, use `Statement.cast`")
|
|
||||||
def wrap(cls, obj):
|
|
||||||
return cls.cast(obj)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cast(obj):
|
def cast(obj):
|
||||||
if isinstance(obj, Iterable):
|
if isinstance(obj, Iterable):
|
||||||
|
@ -1507,7 +1425,7 @@ class ValueKey:
|
||||||
self._hash = hash((self.value.operator,
|
self._hash = hash((self.value.operator,
|
||||||
tuple(ValueKey(o) for o in self.value.operands)))
|
tuple(ValueKey(o) for o in self.value.operands)))
|
||||||
elif isinstance(self.value, Slice):
|
elif isinstance(self.value, Slice):
|
||||||
self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.end))
|
self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.stop))
|
||||||
elif isinstance(self.value, Part):
|
elif isinstance(self.value, Part):
|
||||||
self._hash = hash((ValueKey(self.value.value), ValueKey(self.value.offset),
|
self._hash = hash((ValueKey(self.value.value), ValueKey(self.value.offset),
|
||||||
self.value.width, self.value.stride))
|
self.value.width, self.value.stride))
|
||||||
|
@ -1547,7 +1465,7 @@ class ValueKey:
|
||||||
elif isinstance(self.value, Slice):
|
elif isinstance(self.value, Slice):
|
||||||
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
|
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
|
||||||
self.value.start == other.value.start and
|
self.value.start == other.value.start and
|
||||||
self.value.end == other.value.end)
|
self.value.stop == other.value.stop)
|
||||||
elif isinstance(self.value, Part):
|
elif isinstance(self.value, Part):
|
||||||
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
|
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
|
||||||
ValueKey(self.value.offset) == ValueKey(other.value.offset) and
|
ValueKey(self.value.offset) == ValueKey(other.value.offset) and
|
||||||
|
@ -1606,7 +1524,7 @@ class ValueSet(_MappedKeySet):
|
||||||
class SignalKey:
|
class SignalKey:
|
||||||
def __init__(self, signal):
|
def __init__(self, signal):
|
||||||
self.signal = signal
|
self.signal = signal
|
||||||
if type(signal) is Signal:
|
if isinstance(signal, Signal):
|
||||||
self._intern = (0, signal.duid)
|
self._intern = (0, signal.duid)
|
||||||
elif type(signal) is ClockSignal:
|
elif type(signal) is ClockSignal:
|
||||||
self._intern = (1, signal.domain)
|
self._intern = (1, signal.domain)
|
||||||
|
|
|
@ -24,12 +24,6 @@ class Layout:
|
||||||
return obj
|
return obj
|
||||||
return Layout(obj, src_loc_at=1 + src_loc_at)
|
return Layout(obj, src_loc_at=1 + src_loc_at)
|
||||||
|
|
||||||
# TODO(nmigen-0.2): remove this
|
|
||||||
@classmethod
|
|
||||||
@deprecated("instead of `Layout.wrap`, use `Layout.cast`")
|
|
||||||
def wrap(cls, obj, *, src_loc_at=0):
|
|
||||||
return cls.cast(obj, src_loc_at=1 + src_loc_at)
|
|
||||||
|
|
||||||
def __init__(self, fields, *, src_loc_at=0):
|
def __init__(self, fields, *, src_loc_at=0):
|
||||||
self.fields = OrderedDict()
|
self.fields = OrderedDict()
|
||||||
for field in fields:
|
for field in fields:
|
||||||
|
|
|
@ -18,7 +18,7 @@ __all__ = ["ValueVisitor", "ValueTransformer",
|
||||||
"DomainCollector", "DomainRenamer", "DomainLowerer",
|
"DomainCollector", "DomainRenamer", "DomainLowerer",
|
||||||
"SampleDomainInjector", "SampleLowerer",
|
"SampleDomainInjector", "SampleLowerer",
|
||||||
"SwitchCleaner", "LHSGroupAnalyzer", "LHSGroupFilter",
|
"SwitchCleaner", "LHSGroupAnalyzer", "LHSGroupFilter",
|
||||||
"ResetInserter", "EnableInserter", "CEInserter"]
|
"ResetInserter", "EnableInserter"]
|
||||||
|
|
||||||
|
|
||||||
class ValueVisitor(metaclass=ABCMeta):
|
class ValueVisitor(metaclass=ABCMeta):
|
||||||
|
@ -95,7 +95,8 @@ class ValueVisitor(metaclass=ABCMeta):
|
||||||
new_value = self.on_AnyConst(value)
|
new_value = self.on_AnyConst(value)
|
||||||
elif type(value) is AnySeq:
|
elif type(value) is AnySeq:
|
||||||
new_value = self.on_AnySeq(value)
|
new_value = self.on_AnySeq(value)
|
||||||
elif type(value) is Signal:
|
elif isinstance(value, Signal):
|
||||||
|
# Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
|
||||||
new_value = self.on_Signal(value)
|
new_value = self.on_Signal(value)
|
||||||
elif isinstance(value, Record):
|
elif isinstance(value, Record):
|
||||||
# Uses `isinstance()` and not `type() is` to allow inheriting from Record.
|
# Uses `isinstance()` and not `type() is` to allow inheriting from Record.
|
||||||
|
@ -110,8 +111,7 @@ class ValueVisitor(metaclass=ABCMeta):
|
||||||
new_value = self.on_Slice(value)
|
new_value = self.on_Slice(value)
|
||||||
elif type(value) is Part:
|
elif type(value) is Part:
|
||||||
new_value = self.on_Part(value)
|
new_value = self.on_Part(value)
|
||||||
elif isinstance(value, Cat):
|
elif type(value) is Cat:
|
||||||
# Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
|
|
||||||
new_value = self.on_Cat(value)
|
new_value = self.on_Cat(value)
|
||||||
elif type(value) is Repl:
|
elif type(value) is Repl:
|
||||||
new_value = self.on_Repl(value)
|
new_value = self.on_Repl(value)
|
||||||
|
@ -750,7 +750,3 @@ class EnableInserter(_ControlInserter):
|
||||||
en_port = Mux(self.controls[clk_port.domain], en_port, Const(0, len(en_port)))
|
en_port = Mux(self.controls[clk_port.domain], en_port, Const(0, len(en_port)))
|
||||||
new_fragment.named_ports["EN"] = en_port, en_dir
|
new_fragment.named_ports["EN"] = en_port, en_dir
|
||||||
return new_fragment
|
return new_fragment
|
||||||
|
|
||||||
|
|
||||||
CEInserter = staticmethod(
|
|
||||||
deprecated("instead of `CEInserter`, use `EnableInserter`")(EnableInserter))
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ from .. import *
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["FFSynchronizer", "ResetSynchronizer"]
|
__all__ = ["FFSynchronizer", "ResetSynchronizer"]
|
||||||
# TODO(nmigen-0.2): remove this
|
|
||||||
__all__ += ["MultiReg"]
|
|
||||||
|
|
||||||
|
|
||||||
def _check_stages(stages):
|
def _check_stages(stages):
|
||||||
|
@ -97,10 +95,6 @@ class FFSynchronizer(Elaboratable):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): remove this
|
|
||||||
MultiReg = deprecated("instead of `MultiReg`, use `FFSynchronizer`")(FFSynchronizer)
|
|
||||||
|
|
||||||
|
|
||||||
class ResetSynchronizer(Elaboratable):
|
class ResetSynchronizer(Elaboratable):
|
||||||
"""Synchronize deassertion of a clock domain reset.
|
"""Synchronize deassertion of a clock domain reset.
|
||||||
|
|
||||||
|
|
|
@ -79,78 +79,6 @@ class FIFOInterface:
|
||||||
self.r_rdy = Signal() # readable; not empty
|
self.r_rdy = Signal() # readable; not empty
|
||||||
self.r_en = Signal()
|
self.r_en = Signal()
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `fifo.din`, use `fifo.w_data`")
|
|
||||||
def din(self):
|
|
||||||
return self.w_data
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@din.setter
|
|
||||||
@deprecated("instead of `fifo.din = x`, use `fifo.w_data = x`")
|
|
||||||
def din(self, w_data):
|
|
||||||
self.w_data = w_data
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `fifo.writable`, use `fifo.w_rdy`")
|
|
||||||
def writable(self):
|
|
||||||
return self.w_rdy
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@writable.setter
|
|
||||||
@deprecated("instead of `fifo.writable = x`, use `fifo.w_rdy = x`")
|
|
||||||
def writable(self, w_rdy):
|
|
||||||
self.w_rdy = w_rdy
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `fifo.we`, use `fifo.w_en`")
|
|
||||||
def we(self):
|
|
||||||
return self.w_en
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@we.setter
|
|
||||||
@deprecated("instead of `fifo.we = x`, use `fifo.w_en = x`")
|
|
||||||
def we(self, w_en):
|
|
||||||
self.w_en = w_en
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `fifo.dout`, use `fifo.r_data`")
|
|
||||||
def dout(self):
|
|
||||||
return self.r_data
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@dout.setter
|
|
||||||
@deprecated("instead of `fifo.dout = x`, use `fifo.r_data = x`")
|
|
||||||
def dout(self, r_data):
|
|
||||||
self.r_data = r_data
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `fifo.readable`, use `fifo.r_rdy`")
|
|
||||||
def readable(self):
|
|
||||||
return self.r_rdy
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@readable.setter
|
|
||||||
@deprecated("instead of `fifo.readable = x`, use `fifo.r_rdy = x`")
|
|
||||||
def readable(self, r_rdy):
|
|
||||||
self.r_rdy = r_rdy
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@property
|
|
||||||
@deprecated("instead of `fifo.re`, use `fifo.r_en`")
|
|
||||||
def re(self):
|
|
||||||
return self.r_en
|
|
||||||
|
|
||||||
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
|
|
||||||
@re.setter
|
|
||||||
@deprecated("instead of `fifo.re = x`, use `fifo.r_en = x`")
|
|
||||||
def re(self, r_en):
|
|
||||||
self.r_en = r_en
|
|
||||||
|
|
||||||
|
|
||||||
def _incr(signal, modulo):
|
def _incr(signal, modulo):
|
||||||
if modulo == 2 ** len(signal):
|
if modulo == 2 ** len(signal):
|
||||||
|
|
|
@ -712,38 +712,12 @@ class SignalTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s10.shape(), unsigned(0))
|
self.assertEqual(s10.shape(), unsigned(0))
|
||||||
s11 = Signal(range(1))
|
s11 = Signal(range(1))
|
||||||
self.assertEqual(s11.shape(), unsigned(1))
|
self.assertEqual(s11.shape(), unsigned(1))
|
||||||
# deprecated
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
||||||
d6 = Signal(max=16)
|
|
||||||
self.assertEqual(d6.shape(), unsigned(4))
|
|
||||||
d7 = Signal(min=4, max=16)
|
|
||||||
self.assertEqual(d7.shape(), unsigned(4))
|
|
||||||
d8 = Signal(min=-4, max=16)
|
|
||||||
self.assertEqual(d8.shape(), signed(5))
|
|
||||||
d9 = Signal(min=-20, max=16)
|
|
||||||
self.assertEqual(d9.shape(), signed(6))
|
|
||||||
d10 = Signal(max=1)
|
|
||||||
self.assertEqual(d10.shape(), unsigned(0))
|
|
||||||
|
|
||||||
def test_shape_wrong(self):
|
def test_shape_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaises(TypeError,
|
||||||
msg="Width must be a non-negative integer, not -10"):
|
msg="Width must be a non-negative integer, not -10"):
|
||||||
Signal(-10)
|
Signal(-10)
|
||||||
|
|
||||||
def test_min_max_deprecated(self):
|
|
||||||
with self.assertWarns(DeprecationWarning,
|
|
||||||
msg="instead of `Signal(min=0, max=10)`, use `Signal(range(0, 10))`"):
|
|
||||||
Signal(max=10)
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
||||||
with self.assertRaises(ValueError,
|
|
||||||
msg="Lower bound 10 should be less or equal to higher bound 4"):
|
|
||||||
Signal(min=10, max=4)
|
|
||||||
with self.assertRaises(ValueError,
|
|
||||||
msg="Only one of bits/signedness or bounds may be specified"):
|
|
||||||
Signal(2, min=10)
|
|
||||||
|
|
||||||
def test_name(self):
|
def test_name(self):
|
||||||
s1 = Signal()
|
s1 = Signal()
|
||||||
self.assertEqual(s1.name, "s1")
|
self.assertEqual(s1.name, "s1")
|
||||||
|
|
5
nmigen/vendor/lattice_ice40.py
vendored
5
nmigen/vendor/lattice_ice40.py
vendored
|
@ -350,16 +350,18 @@ class LatticeICE40Platform(TemplatedPlatform):
|
||||||
rst_i = Const(0)
|
rst_i = Const(0)
|
||||||
|
|
||||||
m = Module()
|
m = Module()
|
||||||
|
|
||||||
# Power-on-reset domain
|
# Power-on-reset domain
|
||||||
m.domains += ClockDomain("por", reset_less=True, local=True)
|
m.domains += ClockDomain("por", reset_less=True, local=True)
|
||||||
delay = int(15e-6 * self.default_clk_frequency)
|
delay = int(15e-6 * self.default_clk_frequency)
|
||||||
timer = Signal(max=delay)
|
timer = Signal(range(delay))
|
||||||
ready = Signal()
|
ready = Signal()
|
||||||
m.d.comb += ClockSignal("por").eq(clk_i)
|
m.d.comb += ClockSignal("por").eq(clk_i)
|
||||||
with m.If(timer == delay):
|
with m.If(timer == delay):
|
||||||
m.d.por += ready.eq(1)
|
m.d.por += ready.eq(1)
|
||||||
with m.Else():
|
with m.Else():
|
||||||
m.d.por += timer.eq(timer + 1)
|
m.d.por += timer.eq(timer + 1)
|
||||||
|
|
||||||
# Primary domain
|
# Primary domain
|
||||||
m.domains += ClockDomain("sync")
|
m.domains += ClockDomain("sync")
|
||||||
m.d.comb += ClockSignal("sync").eq(clk_i)
|
m.d.comb += ClockSignal("sync").eq(clk_i)
|
||||||
|
@ -367,6 +369,7 @@ class LatticeICE40Platform(TemplatedPlatform):
|
||||||
m.submodules.reset_sync = ResetSynchronizer(~ready | rst_i, domain="sync")
|
m.submodules.reset_sync = ResetSynchronizer(~ready | rst_i, domain="sync")
|
||||||
else:
|
else:
|
||||||
m.d.comb += ResetSignal("sync").eq(~ready)
|
m.d.comb += ResetSignal("sync").eq(~ready)
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def should_skip_port_component(self, port, attrs, component):
|
def should_skip_port_component(self, port, attrs, component):
|
||||||
|
|
Loading…
Reference in a new issue