build.plat: use lib.io.*Buffer in default platform.

This commit is contained in:
Wanda 2024-04-02 14:05:03 +02:00 committed by Catherine
parent 9bd536bbf9
commit 4e3550db43
2 changed files with 90 additions and 46 deletions

View file

@ -12,6 +12,7 @@ from ..hdl import *
from ..hdl._ir import IOBufferInstance, Design from ..hdl._ir import IOBufferInstance, Design
from ..hdl._xfrm import DomainLowerer from ..hdl._xfrm import DomainLowerer
from ..lib.cdc import ResetSynchronizer from ..lib.cdc import ResetSynchronizer
from ..lib import io
from ..back import rtlil, verilog from ..back import rtlil, verilog
from .res import * from .res import *
from .run import * from .run import *
@ -138,8 +139,13 @@ class Platform(ResourceManager, metaclass=ABCMeta):
fragment._propagate_domains(self.create_missing_domain, platform=self) fragment._propagate_domains(self.create_missing_domain, platform=self)
fragment = DomainLowerer()(fragment) fragment = DomainLowerer()(fragment)
def missing_domain_error(name):
raise RuntimeError("Missing domain in pin fragment")
def add_pin_fragment(pin, pin_fragment): def add_pin_fragment(pin, pin_fragment):
pin_fragment = Fragment.get(pin_fragment, self) pin_fragment = Fragment.get(pin_fragment, self)
pin_fragment._propagate_domains(missing_domain_error)
pin_fragment = DomainLowerer()(pin_fragment)
fragment.add_subfragment(pin_fragment, name=f"pin_{pin.name}") fragment.add_subfragment(pin_fragment, name=f"pin_{pin.name}")
for pin, port, attrs, invert in self.iter_single_ended_pins(): for pin, port, attrs, invert in self.iter_single_ended_pins():
@ -162,8 +168,7 @@ class Platform(ResourceManager, metaclass=ABCMeta):
if pin.dir == "io": if pin.dir == "io":
add_pin_fragment(pin, self.get_diff_input_output(pin, port, attrs, invert)) add_pin_fragment(pin, self.get_diff_input_output(pin, port, attrs, invert))
ports = [(None, signal, None) for signal in self.iter_ports()] fragment = Design(fragment, [], hierarchy=(name,))
fragment = Design(fragment, ports, hierarchy=(name,))
return self.toolchain_prepare(fragment, name, **kwargs) return self.toolchain_prepare(fragment, name, **kwargs)
@abstractmethod @abstractmethod
@ -201,63 +206,87 @@ class Platform(ResourceManager, metaclass=ABCMeta):
return value return value
def get_input(self, pin, port, attrs, invert): def get_input(self, pin, port, attrs, invert):
self._check_feature("single-ended input", pin, attrs, self._check_feature("input", pin, attrs,
valid_xdrs=(0,), valid_attrs=None) valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module() m = Module()
m.d.comb += pin.i.eq(self._invert_if(invert, port)) if pin.xdr == 0:
m.submodules.buf = buf = io.Buffer(io.Direction.Input, port)
m.d.comb += pin.i.eq(buf.i)
elif pin.xdr == 1:
m.domains.input = cd_input = ClockDomain(reset_less=True)
m.submodules.buf = buf = io.FFBuffer(io.Direction.Input, port, i_domain="input")
m.d.comb += pin.i.eq(buf.i)
m.d.comb += cd_input.clk.eq(pin.i_clk)
elif pin.xdr == 2:
m.domains.input = cd_input = ClockDomain(reset_less=True)
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Input, port, i_domain="input")
m.d.comb += pin.i0.eq(buf.i[0])
m.d.comb += pin.i1.eq(buf.i[1])
m.d.comb += cd_input.clk.eq(pin.i_clk)
return m return m
def get_output(self, pin, port, attrs, invert): def get_output(self, pin, port, attrs, invert):
self._check_feature("single-ended output", pin, attrs, self._check_feature("output", pin, attrs,
valid_xdrs=(0,), valid_attrs=None) valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module() m = Module()
m.d.comb += port.eq(self._invert_if(invert, pin.o)) if pin.xdr == 0:
m.submodules.buf = buf = io.Buffer(io.Direction.Output, port)
m.d.comb += buf.o.eq(pin.o)
elif pin.xdr == 1:
m.domains.output = cd_output = ClockDomain(reset_less=True)
m.submodules.buf = buf = io.FFBuffer(io.Direction.Output, port, o_domain="output")
m.d.comb += buf.o.eq(pin.o)
m.d.comb += cd_output.clk.eq(pin.o_clk)
elif pin.xdr == 2:
m.domains.output = cd_output = ClockDomain(reset_less=True)
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Output, port, o_domain="output")
m.d.comb += buf.o[0].eq(pin.o0)
m.d.comb += buf.o[1].eq(pin.o1)
m.d.comb += cd_output.clk.eq(pin.o_clk)
if pin.dir == "oe":
m.d.comb += buf.oe.eq(pin.oe)
return m return m
def get_tristate(self, pin, port, attrs, invert): get_tristate = get_output
self._check_feature("single-ended tristate", pin, attrs,
valid_xdrs=(0,), valid_attrs=None)
m = Module()
m.submodules += IOBufferInstance(
port=port,
o=self._invert_if(invert, pin.o),
oe=pin.oe,
)
return m
def get_input_output(self, pin, port, attrs, invert): def get_input_output(self, pin, port, attrs, invert):
self._check_feature("single-ended input/output", pin, attrs, self._check_feature("single-ended input/output", pin, attrs,
valid_xdrs=(0,), valid_attrs=None) valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module() m = Module()
i = Signal.like(pin.i) if pin.xdr == 0:
m.submodules += IOBufferInstance( m.submodules.buf = buf = io.Buffer(io.Direction.Bidir, port)
port=port, m.d.comb += pin.i.eq(buf.i)
i=i, m.d.comb += buf.o.eq(pin.o)
o=self._invert_if(invert, pin.o), m.d.comb += buf.oe.eq(pin.oe)
oe=pin.oe, elif pin.xdr == 1:
) m.domains.input = cd_input = ClockDomain(reset_less=True)
m.d.comb += pin.i.eq(self._invert_if(invert, i)) m.domains.output = cd_output = ClockDomain(reset_less=True)
m.submodules.buf = buf = io.FFBuffer(io.Direction.Bidir, port, i_domain="input", o_domain="output")
m.d.comb += pin.i.eq(buf.i)
m.d.comb += buf.o.eq(pin.o)
m.d.comb += buf.oe.eq(pin.oe)
m.d.comb += cd_input.clk.eq(pin.i_clk)
m.d.comb += cd_output.clk.eq(pin.o_clk)
elif pin.xdr == 2:
m.domains.input = cd_input = ClockDomain(reset_less=True)
m.domains.output = cd_output = ClockDomain(reset_less=True)
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Bidir, port, i_domain="input", o_domain="output")
m.d.comb += pin.i0.eq(buf.i[0])
m.d.comb += pin.i1.eq(buf.i[1])
m.d.comb += buf.o[0].eq(pin.o0)
m.d.comb += buf.o[1].eq(pin.o1)
m.d.comb += buf.oe.eq(pin.oe)
m.d.comb += cd_input.clk.eq(pin.i_clk)
m.d.comb += cd_output.clk.eq(pin.o_clk)
return m return m
def get_diff_input(self, pin, port, attrs, invert): get_diff_input = get_input
self._check_feature("differential input", pin, attrs, get_diff_output = get_output
valid_xdrs=(), valid_attrs=None) get_diff_tristate = get_tristate
get_diff_input_output = get_input_output
def get_diff_output(self, pin, port, attrs, invert):
self._check_feature("differential output", pin, attrs,
valid_xdrs=(), valid_attrs=None)
def get_diff_tristate(self, pin, port, attrs, invert):
self._check_feature("differential tristate", pin, attrs,
valid_xdrs=(), valid_attrs=None)
def get_diff_input_output(self, pin, port, attrs, invert):
self._check_feature("differential input/output", pin, attrs,
valid_xdrs=(), valid_attrs=None)
class TemplatedPlatform(Platform): class TemplatedPlatform(Platform):

View file

@ -18,6 +18,12 @@ class PortGroup:
pass pass
class PortMetadata:
def __init__(self, name, attrs):
self.name = name
self.attrs = attrs
class ResourceManager: class ResourceManager:
def __init__(self, resources, connectors): def __init__(self, resources, connectors):
self.resources = OrderedDict() self.resources = OrderedDict()
@ -133,12 +139,21 @@ class ResourceManager:
direction = phys.dir direction = phys.dir
if isinstance(phys, Pins): if isinstance(phys, Pins):
phys_names = phys.names phys_names = phys.names
io = IOPort(len(phys), name="__".join(path) + "__io") io = IOPort(len(phys), name="__".join(path) + "__io", metadata=[
PortMetadata(name, attrs)
for name in phys.names
])
port = SingleEndedPort(io, invert=phys.invert, direction=direction) port = SingleEndedPort(io, invert=phys.invert, direction=direction)
if isinstance(phys, DiffPairs): if isinstance(phys, DiffPairs):
phys_names = [] phys_names = []
p = IOPort(len(phys), name="__".join(path) + "__p") p = IOPort(len(phys), name="__".join(path) + "__p", metadata=[
n = IOPort(len(phys), name="__".join(path) + "__n") PortMetadata(name, attrs)
for name in phys.p.names
])
n = IOPort(len(phys), name="__".join(path) + "__n", metadata=[
PortMetadata(name, attrs)
for name in phys.n.names
])
if not self.should_skip_port_component(None, attrs, "p"): if not self.should_skip_port_component(None, attrs, "p"):
phys_names += phys.p.names phys_names += phys.p.names
if not self.should_skip_port_component(None, attrs, "n"): if not self.should_skip_port_component(None, attrs, "n"):