Rename nMigen to Amaranth HDL.

This commit is contained in:
whitequark 2021-12-10 05:39:50 +00:00
parent 0b28a97ca0
commit 909a3b8be7
200 changed files with 14493 additions and 14451 deletions

View file

@ -0,0 +1,6 @@
from amaranth.compat.genlib import *
import warnings
warnings.warn("instead of nmigen.compat.genlib, use amaranth.compat.genlib",
DeprecationWarning, stacklevel=2)

View file

@ -1,74 +1,7 @@
from amaranth.compat.genlib.cdc import *
from amaranth.compat.genlib.cdc import __all__
import warnings
from ..._utils import deprecated
from ...lib.cdc import FFSynchronizer as NativeFFSynchronizer
from ...lib.cdc import PulseSynchronizer as NativePulseSynchronizer
from ...hdl.ast import *
from ..fhdl.module import CompatModule
from ..fhdl.structure import If
__all__ = ["MultiReg", "PulseSynchronizer", "GrayCounter", "GrayDecoder"]
class MultiReg(NativeFFSynchronizer):
def __init__(self, i, o, odomain="sync", n=2, reset=0):
old_opts = []
new_opts = []
if odomain != "sync":
old_opts.append(", odomain={!r}".format(odomain))
new_opts.append(", o_domain={!r}".format(odomain))
if n != 2:
old_opts.append(", n={!r}".format(n))
new_opts.append(", stages={!r}".format(n))
warnings.warn("instead of `MultiReg(...{})`, use `FFSynchronizer(...{})`"
.format("".join(old_opts), "".join(new_opts)),
DeprecationWarning, stacklevel=2)
super().__init__(i, o, o_domain=odomain, stages=n, reset=reset)
self.odomain = odomain
@deprecated("instead of `migen.genlib.cdc.PulseSynchronizer`, use `nmigen.lib.cdc.PulseSynchronizer`")
class PulseSynchronizer(NativePulseSynchronizer):
def __init__(self, idomain, odomain):
super().__init__(i_domain=idomain, o_domain=odomain)
@deprecated("instead of `migen.genlib.cdc.GrayCounter`, use `nmigen.lib.coding.GrayEncoder`")
class GrayCounter(CompatModule):
def __init__(self, width):
self.ce = Signal()
self.q = Signal(width)
self.q_next = Signal(width)
self.q_binary = Signal(width)
self.q_next_binary = Signal(width)
###
self.comb += [
If(self.ce,
self.q_next_binary.eq(self.q_binary + 1)
).Else(
self.q_next_binary.eq(self.q_binary)
),
self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:])
]
self.sync += [
self.q_binary.eq(self.q_next_binary),
self.q.eq(self.q_next)
]
@deprecated("instead of `migen.genlib.cdc.GrayDecoder`, use `nmigen.lib.coding.GrayDecoder`")
class GrayDecoder(CompatModule):
def __init__(self, width):
self.i = Signal(width)
self.o = Signal(width, reset_less=True)
# # #
o_comb = Signal(width)
self.comb += o_comb[-1].eq(self.i[-1])
for i in reversed(range(width-1)):
self.comb += o_comb[i].eq(o_comb[i+1] ^ self.i[i])
self.sync += self.o.eq(o_comb)
warnings.warn("instead of nmigen.compat.genlib.cdc, use amaranth.compat.genlib.cdc",
DeprecationWarning, stacklevel=2)

View file

@ -1,4 +1,7 @@
from ...lib.coding import *
from amaranth.compat.genlib.coding import *
from amaranth.compat.genlib.coding import __all__
__all__ = ["Encoder", "PriorityEncoder", "Decoder", "PriorityDecoder"]
import warnings
warnings.warn("instead of nmigen.compat.genlib.coding, use amaranth.compat.genlib.coding",
DeprecationWarning, stacklevel=2)

View file

@ -1,147 +1,7 @@
from ..._utils import deprecated, extend
from ...lib.fifo import (FIFOInterface as NativeFIFOInterface,
SyncFIFO as NativeSyncFIFO, SyncFIFOBuffered as NativeSyncFIFOBuffered,
AsyncFIFO as NativeAsyncFIFO, AsyncFIFOBuffered as NativeAsyncFIFOBuffered)
from amaranth.compat.genlib.fifo import *
from amaranth.compat.genlib.fifo import __all__
__all__ = ["_FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "AsyncFIFOBuffered"]
class CompatFIFOInterface(NativeFIFOInterface):
@deprecated("attribute `fwft` must be provided to FIFOInterface constructor")
def __init__(self, width, depth):
super().__init__(width=width, depth=depth, fwft=False)
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)
def read(self):
"""Read method for simulation."""
assert (yield self.r_rdy)
value = (yield self.r_data)
yield self.r_en.eq(1)
yield
yield self.r_en.eq(0)
yield
return value
@extend(NativeFIFOInterface)
def write(self, data):
"""Write method for simulation."""
assert (yield self.w_rdy)
yield self.w_data.eq(data)
yield self.w_en.eq(1)
yield
yield self.w_en.eq(0)
yield
class CompatSyncFIFO(NativeSyncFIFO):
def __init__(self, width, depth, fwft=True):
super().__init__(width=width, depth=depth, fwft=fwft)
class CompatSyncFIFOBuffered(NativeSyncFIFOBuffered):
def __init__(self, width, depth):
super().__init__(width=width, depth=depth)
class CompatAsyncFIFO(NativeAsyncFIFO):
def __init__(self, width, depth):
super().__init__(width=width, depth=depth)
class CompatAsyncFIFOBuffered(NativeAsyncFIFOBuffered):
def __init__(self, width, depth):
super().__init__(width=width, depth=depth)
_FIFOInterface = CompatFIFOInterface
SyncFIFO = CompatSyncFIFO
SyncFIFOBuffered = CompatSyncFIFOBuffered
AsyncFIFO = CompatAsyncFIFO
AsyncFIFOBuffered = CompatAsyncFIFOBuffered
import warnings
warnings.warn("instead of nmigen.compat.genlib.fifo, use amaranth.compat.genlib.fifo",
DeprecationWarning, stacklevel=2)

View file

@ -1,193 +1,7 @@
from collections import OrderedDict
from ..._utils import deprecated, _ignore_deprecated
from ...hdl.xfrm import ValueTransformer, StatementTransformer
from ...hdl.ast import *
from ...hdl.ast import Signal as NativeSignal
from ..fhdl.module import CompatModule, CompatFinalizeError
from ..fhdl.structure import Signal, If, Case
from amaranth.compat.genlib.fsm import *
from amaranth.compat.genlib.fsm import __all__
__all__ = ["AnonymousState", "NextState", "NextValue", "FSM"]
class AnonymousState:
pass
class NextState(Statement):
def __init__(self, state):
super().__init__()
self.state = state
class NextValue(Statement):
def __init__(self, target, value):
super().__init__()
self.target = target
self.value = value
def _target_eq(a, b):
if type(a) != type(b):
return False
ty = type(a)
if ty == Const:
return a.value == b.value
elif ty == NativeSignal or ty == Signal:
return a is b
elif ty == Cat:
return all(_target_eq(x, y) for x, y in zip(a.l, b.l))
elif ty == Slice:
return (_target_eq(a.value, b.value)
and a.start == b.start
and a.stop == b.stop)
elif ty == Part:
return (_target_eq(a.value, b.value)
and _target_eq(a.offset == b.offset)
and a.width == b.width)
elif ty == ArrayProxy:
return (all(_target_eq(x, y) for x, y in zip(a.choices, b.choices))
and _target_eq(a.key, b.key))
else:
raise ValueError("NextValue cannot be used with target type '{}'"
.format(ty))
class _LowerNext(ValueTransformer, StatementTransformer):
def __init__(self, next_state_signal, encoding, aliases):
self.next_state_signal = next_state_signal
self.encoding = encoding
self.aliases = aliases
# (target, next_value_ce, next_value)
self.registers = []
def _get_register_control(self, target):
for x in self.registers:
if _target_eq(target, x[0]):
return x[1], x[2]
raise KeyError
def on_unknown_statement(self, node):
if isinstance(node, NextState):
try:
actual_state = self.aliases[node.state]
except KeyError:
actual_state = node.state
return self.next_state_signal.eq(self.encoding[actual_state])
elif isinstance(node, NextValue):
try:
next_value_ce, next_value = self._get_register_control(node.target)
except KeyError:
related = node.target if isinstance(node.target, Signal) else None
next_value = Signal(node.target.shape(),
name=None if related is None else "{}_fsm_next".format(related.name))
next_value_ce = Signal(
name=None if related is None else "{}_fsm_next_ce".format(related.name))
self.registers.append((node.target, next_value_ce, next_value))
return next_value.eq(node.value), next_value_ce.eq(1)
else:
return node
@deprecated("instead of `migen.genlib.fsm.FSM()`, use `with m.FSM():`; note that there is no "
"replacement for `{before,after}_{entering,leaving}` and `delayed_enter` methods")
class FSM(CompatModule):
def __init__(self, reset_state=None):
self.actions = OrderedDict()
self.state_aliases = dict()
self.reset_state = reset_state
self.before_entering_signals = OrderedDict()
self.before_leaving_signals = OrderedDict()
self.after_entering_signals = OrderedDict()
self.after_leaving_signals = OrderedDict()
def act(self, state, *statements):
if self.finalized:
raise CompatFinalizeError
if self.reset_state is None:
self.reset_state = state
if state not in self.actions:
self.actions[state] = []
self.actions[state] += statements
def delayed_enter(self, name, target, delay):
if self.finalized:
raise CompatFinalizeError
if delay > 0:
state = name
for i in range(delay):
if i == delay - 1:
next_state = target
else:
next_state = AnonymousState()
self.act(state, NextState(next_state))
state = next_state
else:
self.state_aliases[name] = target
def ongoing(self, state):
is_ongoing = Signal()
self.act(state, is_ongoing.eq(1))
return is_ongoing
def _get_signal(self, d, state):
if state not in self.actions:
self.actions[state] = []
try:
return d[state]
except KeyError:
is_el = Signal()
d[state] = is_el
return is_el
def before_entering(self, state):
return self._get_signal(self.before_entering_signals, state)
def before_leaving(self, state):
return self._get_signal(self.before_leaving_signals, state)
def after_entering(self, state):
signal = self._get_signal(self.after_entering_signals, state)
self.sync += signal.eq(self.before_entering(state))
return signal
def after_leaving(self, state):
signal = self._get_signal(self.after_leaving_signals, state)
self.sync += signal.eq(self.before_leaving(state))
return signal
@_ignore_deprecated
def do_finalize(self):
nstates = len(self.actions)
self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys()))
self.decoding = {n: s for s, n in self.encoding.items()}
decoder = lambda n: "{}/{}".format(self.decoding[n], n)
self.state = Signal(range(nstates), reset=self.encoding[self.reset_state], decoder=decoder)
self.next_state = Signal.like(self.state)
for state, signal in self.before_leaving_signals.items():
encoded = self.encoding[state]
self.comb += signal.eq((self.state == encoded) & ~(self.next_state == encoded))
if self.reset_state in self.after_entering_signals:
self.after_entering_signals[self.reset_state].reset = 1
for state, signal in self.before_entering_signals.items():
encoded = self.encoding[state]
self.comb += signal.eq(~(self.state == encoded) & (self.next_state == encoded))
self._finalize_sync(self._lower_controls())
def _lower_controls(self):
return _LowerNext(self.next_state, self.encoding, self.state_aliases)
def _finalize_sync(self, ls):
cases = dict((self.encoding[k], ls.on_statement(v)) for k, v in self.actions.items() if v)
self.comb += [
self.next_state.eq(self.state),
Case(self.state, cases).makedefault(self.encoding[self.reset_state])
]
self.sync += self.state.eq(self.next_state)
for register, next_value_ce, next_value in ls.registers:
self.sync += If(next_value_ce, register.eq(next_value))
import warnings
warnings.warn("instead of nmigen.compat.genlib.fsm, use amaranth.compat.genlib.fsm",
DeprecationWarning, stacklevel=2)

View file

@ -1,195 +1,6 @@
from ...tracer import *
from ..fhdl.structure import *
from functools import reduce
from operator import or_
from amaranth.compat.genlib.record import *
(DIR_NONE, DIR_S_TO_M, DIR_M_TO_S) = range(3)
# Possible layout elements:
# 1. (name, size)
# 2. (name, size, direction)
# 3. (name, sublayout)
# size can be an int, or a (int, bool) tuple for signed numbers
# sublayout must be a list
def set_layout_parameters(layout, **layout_dict):
def resolve(p):
if isinstance(p, str):
try:
return layout_dict[p]
except KeyError:
return p
else:
return p
r = []
for f in layout:
if isinstance(f[1], (int, tuple, str)): # cases 1/2
if len(f) == 3:
r.append((f[0], resolve(f[1]), f[2]))
else:
r.append((f[0], resolve(f[1])))
elif isinstance(f[1], list): # case 3
r.append((f[0], set_layout_parameters(f[1], **layout_dict)))
else:
raise TypeError
return r
def layout_len(layout):
r = 0
for f in layout:
if isinstance(f[1], (int, tuple)): # cases 1/2
if len(f) == 3:
fname, fsize, fdirection = f
else:
fname, fsize = f
elif isinstance(f[1], list): # case 3
fname, fsublayout = f
fsize = layout_len(fsublayout)
else:
raise TypeError
if isinstance(fsize, tuple):
r += fsize[0]
else:
r += fsize
return r
def layout_get(layout, name):
for f in layout:
if f[0] == name:
return f
raise KeyError(name)
def layout_partial(layout, *elements):
r = []
for path in elements:
path_s = path.split("/")
last = path_s.pop()
copy_ref = layout
insert_ref = r
for hop in path_s:
name, copy_ref = layout_get(copy_ref, hop)
try:
name, insert_ref = layout_get(insert_ref, hop)
except KeyError:
new_insert_ref = []
insert_ref.append((hop, new_insert_ref))
insert_ref = new_insert_ref
insert_ref.append(layout_get(copy_ref, last))
return r
class Record:
def __init__(self, layout, name=None, **kwargs):
try:
self.name = get_var_name()
except NameNotFound:
self.name = ""
self.layout = layout
if self.name:
prefix = self.name + "_"
else:
prefix = ""
for f in self.layout:
if isinstance(f[1], (int, tuple)): # cases 1/2
if(len(f) == 3):
fname, fsize, fdirection = f
else:
fname, fsize = f
finst = Signal(fsize, name=prefix + fname, **kwargs)
elif isinstance(f[1], list): # case 3
fname, fsublayout = f
finst = Record(fsublayout, prefix + fname, **kwargs)
else:
raise TypeError
setattr(self, fname, finst)
def eq(self, other):
return [getattr(self, f[0]).eq(getattr(other, f[0]))
for f in self.layout if hasattr(other, f[0])]
def iter_flat(self):
for f in self.layout:
e = getattr(self, f[0])
if isinstance(e, Signal):
if len(f) == 3:
yield e, f[2]
else:
yield e, DIR_NONE
elif isinstance(e, Record):
yield from e.iter_flat()
else:
raise TypeError
def flatten(self):
return [signal for signal, direction in self.iter_flat()]
def raw_bits(self):
return Cat(*self.flatten())
def connect(self, *slaves, keep=None, omit=None):
if keep is None:
_keep = set([f[0] for f in self.layout])
elif isinstance(keep, list):
_keep = set(keep)
else:
_keep = keep
if omit is None:
_omit = set()
elif isinstance(omit, list):
_omit = set(omit)
else:
_omit = omit
_keep = _keep - _omit
r = []
for f in self.layout:
field = f[0]
self_e = getattr(self, field)
if isinstance(self_e, Signal):
if field in _keep:
direction = f[2]
if direction == DIR_M_TO_S:
r += [getattr(slave, field).eq(self_e) for slave in slaves]
elif direction == DIR_S_TO_M:
r.append(self_e.eq(reduce(or_, [getattr(slave, field) for slave in slaves])))
else:
raise TypeError
else:
for slave in slaves:
r += self_e.connect(getattr(slave, field), keep=keep, omit=omit)
return r
def connect_flat(self, *slaves):
r = []
iter_slaves = [slave.iter_flat() for slave in slaves]
for m_signal, m_direction in self.iter_flat():
if m_direction == DIR_M_TO_S:
for iter_slave in iter_slaves:
s_signal, s_direction = next(iter_slave)
assert(s_direction == DIR_M_TO_S)
r.append(s_signal.eq(m_signal))
elif m_direction == DIR_S_TO_M:
s_signals = []
for iter_slave in iter_slaves:
s_signal, s_direction = next(iter_slave)
assert(s_direction == DIR_S_TO_M)
s_signals.append(s_signal)
r.append(m_signal.eq(reduce(or_, s_signals)))
else:
raise TypeError
return r
def __len__(self):
return layout_len(self.layout)
def __repr__(self):
return "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"
import warnings
warnings.warn("instead of nmigen.compat.genlib.record, use amaranth.compat.genlib.record",
DeprecationWarning, stacklevel=2)

View file

@ -1,16 +1,7 @@
from ..._utils import deprecated
from ...lib.cdc import ResetSynchronizer as NativeResetSynchronizer
from amaranth.compat.genlib.resetsync import *
from amaranth.compat.genlib.resetsync import __all__
__all__ = ["AsyncResetSynchronizer"]
@deprecated("instead of `migen.genlib.resetsync.AsyncResetSynchronizer`, "
"use `nmigen.lib.cdc.ResetSynchronizer`; note that ResetSynchronizer accepts "
"a clock domain name as an argument, not a clock domain object")
class CompatResetSynchronizer(NativeResetSynchronizer):
def __init__(self, cd, async_reset):
super().__init__(async_reset, domain=cd.name)
AsyncResetSynchronizer = CompatResetSynchronizer
import warnings
warnings.warn("instead of nmigen.compat.genlib.resetsync, use amaranth.compat.genlib.resetsync",
DeprecationWarning, stacklevel=2)

View file

@ -1,58 +1,7 @@
from amaranth.compat.genlib.roundrobin import *
from amaranth.compat.genlib.roundrobin import __all__
import warnings
from ..fhdl.structure import Signal, If, Case
from ..fhdl.module import CompatModule
__all__ = ["RoundRobin", "SP_WITHDRAW", "SP_CE"]
(SP_WITHDRAW, SP_CE) = range(2)
class CompatRoundRobin(CompatModule):
def __init__(self, n, switch_policy=SP_WITHDRAW):
self.request = Signal(n)
self.grant = Signal(max=max(2, n))
self.switch_policy = switch_policy
if self.switch_policy == SP_CE:
warnings.warn("instead of `migen.genlib.roundrobin.RoundRobin`, "
"use `nmigen.lib.scheduler.RoundRobin`; note that RoundRobin does not "
"require a policy anymore but to get the same behavior as SP_CE you"
"should use an EnableInserter",
DeprecationWarning, stacklevel=1)
self.ce = Signal()
else:
warnings.warn("instead of `migen.genlib.roundrobin.RoundRobin`, "
"use `nmigen.lib.scheduler.RoundRobin`; note that RoundRobin does not "
"require a policy anymore",
DeprecationWarning, stacklevel=1)
###
if n > 1:
cases = {}
for i in range(n):
switch = []
for j in reversed(range(i+1, i+n)):
t = j % n
switch = [
If(self.request[t],
self.grant.eq(t)
).Else(
*switch
)
]
if self.switch_policy == SP_WITHDRAW:
case = [If(~self.request[i], *switch)]
else:
case = switch
cases[i] = case
statement = Case(self.grant, cases)
if self.switch_policy == SP_CE:
statement = If(self.ce, statement)
self.sync += statement
else:
self.comb += self.grant.eq(0)
RoundRobin = CompatRoundRobin
warnings.warn("instead of nmigen.compat.genlib.roundrobin, use amaranth.compat.genlib.roundrobin",
DeprecationWarning, stacklevel=2)