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'' 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)