| import migen
from litex.build import io
from amaranth.lib import wiring
class PadsProxy:
def __init__(self, wrapper, name, migen_pads, dir, xdr):
self.signature = wiring.Signature(members = [])
if isinstance(migen_pads, migen.Record):
if dir is None:
dir = {}
elif isinstance(dir, str):
dir = {subname: dir for subname, *_ in migen_pads.layout}
if xdr is None:
xdr = {}
assert isinstance(dir, dict) or isinstance(dir, str)
assert isinstance(xdr, dict)
for subname, *_ in migen_pads.layout:
subsignal = PadsProxy(wrapper, f'{name}_{subname}', getattr(migen_pads, subname), dir.get(subname), xdr.get(subname))
setattr(self, subname, subsignal)
self.signature.members[subname] = wiring.Out(subsignal.signature)
elif isinstance(migen_pads, migen.Signal):
if dir is None:
dir = '-'
if xdr is None:
xdr = 0
if dir == '-':
pass
elif xdr == 0:
if dir == 'i':
self.i = wrapper.from_migen(migen_pads, name = f'{name}_i')
self.signature.members['i'] = wiring.Out(self.i.shape())
elif dir == 'o':
self.o = wrapper.from_migen(migen_pads, name = f'{name}_o')
self.signature.members['o'] = wiring.In(self.o.shape())
elif dir == 'io':
i = migen.Signal.like(migen_pads)
o = migen.Signal.like(migen_pads)
oe = migen.Signal()
wrapper.specials += io.Tristate(migen_pads, o, migen.Replicate(oe, migen_pads.nbits), i)
self.i = wrapper.from_migen(i, name = f'{name}_i')
self.signature.members['i'] = wiring.Out(self.i.shape())
self.o = wrapper.from_migen(o, name = f'{name}_o')
self.signature.members['o'] = wiring.In(self.o.shape())
self.oe = wrapper.from_migen(oe, name = f'{name}_oe')
self.signature.members['oe'] = wiring.In(self.oe.shape())
elif dir == 'oe':
i = migen.Signal.like(migen_pads)
o = migen.Signal.like(migen_pads)
oe = migen.Signal()
wrapper.specials += io.Tristate(migen_pads, i = i, o = o, oe = migen.Replicate(oe, migen_pads.nbits))
self.o = wrapper.from_migen(o, name = f'{name}_o')
self.signature.members['o'] = wiring.In(self.o.shape())
self.oe = wrapper.from_migen(oe, name = f'{name}_oe')
self.signature.members['oe'] = wiring.In(self.oe.shape())
else:
raise RuntimeError(f'{xdr=} and {dir=} not supported yet')
elif xdr == 1:
if dir == 'i':
i = migen.Signal.like(migen_pads)
i_clk = migen.Signal()
wrapper.specials += io.SDRInput(i = migen_pads, o = i, clk = i_clk)
self.i = wrapper.from_migen(i, name = f'{name}_i')
self.signature.members['i'] = wiring.Out(self.i.shape())
self.i_clk = wrapper.from_migen(i_clk, name = f'{name}_i_clk')
self.signature.members['i_clk'] = wiring.In(self.i_clk.shape())
elif dir == 'o':
o = migen.Signal.like(migen_pads)
o_clk = migen.Signal()
wrapper.specials += io.SDROutput(i = o, o = migen_pads, clk = o_clk)
self.o = wrapper.from_migen(o, name = f'{name}_o')
self.signature.members['o'] = wiring.In(self.o.shape())
self.o_clk = wrapper.from_migen(o_clk, name = f'{name}_o_clk')
self.signature.members['o_clk'] = wiring.In(self.o_clk.shape())
elif dir == 'io':
i = migen.Signal.like(migen_pads)
_i = migen.Signal.like(migen_pads)
o = migen.Signal.like(migen_pads)
_o = migen.Signal.like(migen_pads)
oe = migen.Signal()
i_clk = migen.Signal()
o_clk = migen.Signal()
wrapper.specials += io.Tristate(migen_pads, i = _i, o = _o, oe = migen.Replicate(oe, migen_pads.nbits))
for idx in range(migen_pads.nbits):
wrapper.specials += io.SDRInput(i = _i[idx], o = i[idx], clk = i_clk)
wrapper.specials += io.SDROutput(i = o[idx], o = _o[idx], clk = o_clk)
self.i = wrapper.from_migen(i, name = f'{name}_i')
self.signature.members['i'] = wiring.Out(self.i.shape())
self.o = wrapper.from_migen(o, name = f'{name}_o')
self.signature.members['o'] = wiring.In(self.o.shape())
self.oe = wrapper.from_migen(oe, name = f'{name}_oe')
self.signature.members['oe'] = wiring.In(self.oe.shape())
self.i_clk = wrapper.from_migen(i_clk, name = f'{name}_i_clk')
self.signature.members['i_clk'] = wiring.In(self.i_clk.shape())
self.o_clk = wrapper.from_migen(o_clk, name = f'{name}_o_clk')
self.signature.members['o_clk'] = wiring.In(self.o_clk.shape())
elif dir == 'oe':
_i = migen.Signal.like(migen_pads)
o = migen.Signal.like(migen_pads)
_o = migen.Signal.like(migen_pads)
oe = migen.Signal()
o_clk = migen.Signal()
wrapper.specials += io.Tristate(migen_pads, i = _i, o = _o, oe = migen.Replicate(oe, migen_pads.nbits))
for idx in range(migen_pads.nbits):
wrapper.specials += io.SDROutput(i = o[idx], o = _o[idx], clk = o_clk)
self.o = wrapper.from_migen(o, name = f'{name}_o')
self.signature.members['o'] = wiring.In(self.o.shape())
self.oe = wrapper.from_migen(oe, name = f'{name}_oe')
self.signature.members['oe'] = wiring.In(self.oe.shape())
self.o_clk = wrapper.from_migen(o_clk, name = f'{name}_o_clk')
self.signature.members['o_clk'] = wiring.In(self.o_clk.shape())
else:
raise RuntimeError(f'{xdr=} and {dir=} not supported yet')
else:
raise RuntimeError(f'{xdr=} not supported yet')
assert self.signature.is_compliant(self)
def __str__(self):
return f'<PadsProxy: {self.signature}>'
class PlatformProxy:
def __init__(self, wrapper):
self.wrapper = wrapper
def request(self, name, number = None, *, dir = None, xdr = None):
migen_pads = self.wrapper.platform.request(name, number)
if number is not None:
name = f'{name}_{number}'
return PadsProxy(self.wrapper, f'pad_{name}', migen_pads, dir, xdr)
|