import builtins import warnings from collections import OrderedDict from ...utils import bits_for from ..._utils import deprecated, extend from ...hdl import ast from ...hdl.ast import (DUID, Shape, signed, unsigned, Value, Const, C, Mux, Slice as _Slice, Part, Cat, Repl, Signal as NativeSignal, ClockSignal, ResetSignal, Array, ArrayProxy as _ArrayProxy) from ...hdl.cd import ClockDomain __all__ = ["DUID", "wrap", "Mux", "Cat", "Replicate", "Constant", "C", "Signal", "ClockSignal", "ResetSignal", "If", "Case", "Array", "ClockDomain"] @deprecated("instead of `wrap`, use `Value.cast`") def wrap(v): return Value.cast(v) class CompatSignal(NativeSignal): def __init__(self, bits_sign=None, name=None, variable=False, reset=0, reset_less=False, name_override=None, min=None, max=None, related=None, attr=None, src_loc_at=0, **kwargs): 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`") def Replicate(v, n): return Repl(v, n) @extend(Const) @property @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) @property @deprecated("instead `_ArrayProxy.choices`, use `ArrayProxy.elems`") def choices(self): return self.elems class If(ast.Switch): @deprecated("instead of `If(cond, ...)`, use `with m.If(cond): ...`") def __init__(self, cond, *stmts): cond = Value.cast(cond) if len(cond) != 1: cond = cond.bool() super().__init__(cond, {("1",): ast.Statement.cast(stmts)}) @deprecated("instead of `.Elif(cond, ...)`, use `with m.Elif(cond): ...`") def Elif(self, cond, *stmts): cond = Value.cast(cond) if len(cond) != 1: cond = cond.bool() self.cases = OrderedDict((("-" + k,), v) for (k,), v in self.cases.items()) self.cases[("1" + "-" * len(self.test),)] = ast.Statement.cast(stmts) self.test = Cat(self.test, cond) return self @deprecated("instead of `.Else(...)`, use `with m.Else(): ...`") def Else(self, *stmts): self.cases[()] = ast.Statement.cast(stmts) return self class Case(ast.Switch): @deprecated("instead of `Case(test, { value: stmts })`, use `with m.Switch(test):` and " "`with m.Case(value): stmts`; instead of `\"default\": stmts`, use " "`with m.Case(): stmts`") def __init__(self, test, cases): new_cases = [] default = None for k, v in cases.items(): if isinstance(k, (bool, int)): k = Const(k) if (not isinstance(k, Const) and not (isinstance(k, str) and k == "default")): raise TypeError("Case object is not a Migen constant") if isinstance(k, str) and k == "default": default = v continue else: k = k.value new_cases.append((k, v)) if default is not None: new_cases.append((None, default)) super().__init__(test, OrderedDict(new_cases)) @deprecated("instead of `Case(...).makedefault()`, use an explicit default case: " "`with m.Case(): ...`") def makedefault(self, key=None): if key is None: for choice in self.cases.keys(): if (key is None or (isinstance(choice, str) and choice == "default") or choice > key): key = choice elif isinstance(key, str) and key == "default": key = () else: key = ("{:0{}b}".format(ast.Value.cast(key).value, len(self.test)),) stmts = self.cases[key] del self.cases[key] self.cases[()] = stmts return self