build.{plat,res}: post-lib.io
cleanup.
This commit is contained in:
parent
7fe62f810b
commit
cf534489a2
|
@ -142,34 +142,15 @@ class Platform(ResourceManager, metaclass=ABCMeta):
|
||||||
def missing_domain_error(name):
|
def missing_domain_error(name):
|
||||||
raise RuntimeError("Missing domain in pin fragment")
|
raise RuntimeError("Missing domain in pin fragment")
|
||||||
|
|
||||||
def add_pin_fragment(pin, pin_fragment):
|
for pin, port, buffer in self.iter_pins():
|
||||||
pin_fragment = Fragment.get(pin_fragment, self)
|
buffer = Fragment.get(buffer, self)
|
||||||
pin_fragment._propagate_domains(missing_domain_error)
|
buffer._propagate_domains(missing_domain_error)
|
||||||
pin_fragment = DomainLowerer()(pin_fragment)
|
buffer = DomainLowerer()(buffer)
|
||||||
fragment.add_subfragment(pin_fragment, name=f"pin_{pin.name}")
|
fragment.add_subfragment(buffer, name=f"pin_{pin.name}")
|
||||||
|
|
||||||
for pin, port, attrs, invert in self.iter_single_ended_pins():
|
ports = [(port.name, port, None) for port in self.iter_ports()]
|
||||||
if pin.dir == "i":
|
design = Design(fragment, ports, hierarchy=(name,))
|
||||||
add_pin_fragment(pin, self.get_input(pin, port, attrs, invert))
|
return self.toolchain_prepare(design, name, **kwargs)
|
||||||
if pin.dir == "o":
|
|
||||||
add_pin_fragment(pin, self.get_output(pin, port, attrs, invert))
|
|
||||||
if pin.dir == "oe":
|
|
||||||
add_pin_fragment(pin, self.get_tristate(pin, port, attrs, invert))
|
|
||||||
if pin.dir == "io":
|
|
||||||
add_pin_fragment(pin, self.get_input_output(pin, port, attrs, invert))
|
|
||||||
|
|
||||||
for pin, port, attrs, invert in self.iter_differential_pins():
|
|
||||||
if pin.dir == "i":
|
|
||||||
add_pin_fragment(pin, self.get_diff_input(pin, port, attrs, invert))
|
|
||||||
if pin.dir == "o":
|
|
||||||
add_pin_fragment(pin, self.get_diff_output(pin, port, attrs, invert))
|
|
||||||
if pin.dir == "oe":
|
|
||||||
add_pin_fragment(pin, self.get_diff_tristate(pin, port, attrs, invert))
|
|
||||||
if pin.dir == "io":
|
|
||||||
add_pin_fragment(pin, self.get_diff_input_output(pin, port, attrs, invert))
|
|
||||||
|
|
||||||
fragment = Design(fragment, [], hierarchy=(name,))
|
|
||||||
return self.toolchain_prepare(fragment, name, **kwargs)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def toolchain_prepare(self, fragment, name, **kwargs):
|
def toolchain_prepare(self, fragment, name, **kwargs):
|
||||||
|
@ -186,108 +167,6 @@ class Platform(ResourceManager, metaclass=ABCMeta):
|
||||||
raise NotImplementedError("Platform '{}' does not support programming"
|
raise NotImplementedError("Platform '{}' does not support programming"
|
||||||
.format(type(self).__name__))
|
.format(type(self).__name__))
|
||||||
|
|
||||||
def _check_feature(self, feature, pin, attrs, valid_xdrs, valid_attrs):
|
|
||||||
if len(valid_xdrs) == 0:
|
|
||||||
raise NotImplementedError("Platform '{}' does not support {}"
|
|
||||||
.format(type(self).__name__, feature))
|
|
||||||
elif pin.xdr not in valid_xdrs:
|
|
||||||
raise NotImplementedError("Platform '{}' does not support {} for XDR {}"
|
|
||||||
.format(type(self).__name__, feature, pin.xdr))
|
|
||||||
|
|
||||||
if not valid_attrs and attrs:
|
|
||||||
raise NotImplementedError("Platform '{}' does not support attributes for {}"
|
|
||||||
.format(type(self).__name__, feature))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _invert_if(invert, value):
|
|
||||||
if invert:
|
|
||||||
return ~value
|
|
||||||
else:
|
|
||||||
return value
|
|
||||||
|
|
||||||
def get_input(self, pin, port, attrs, invert):
|
|
||||||
self._check_feature("input", pin, attrs,
|
|
||||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
|
||||||
|
|
||||||
m = Module()
|
|
||||||
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
|
|
||||||
|
|
||||||
def get_output(self, pin, port, attrs, invert):
|
|
||||||
self._check_feature("output", pin, attrs,
|
|
||||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
|
||||||
|
|
||||||
m = Module()
|
|
||||||
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
|
|
||||||
|
|
||||||
get_tristate = get_output
|
|
||||||
|
|
||||||
def get_input_output(self, pin, port, attrs, invert):
|
|
||||||
self._check_feature("single-ended input/output", pin, attrs,
|
|
||||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
|
||||||
|
|
||||||
m = Module()
|
|
||||||
if pin.xdr == 0:
|
|
||||||
m.submodules.buf = buf = io.Buffer(io.Direction.Bidir, port)
|
|
||||||
m.d.comb += pin.i.eq(buf.i)
|
|
||||||
m.d.comb += buf.o.eq(pin.o)
|
|
||||||
m.d.comb += buf.oe.eq(pin.oe)
|
|
||||||
elif pin.xdr == 1:
|
|
||||||
m.domains.input = cd_input = ClockDomain(reset_less=True)
|
|
||||||
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
|
|
||||||
|
|
||||||
get_diff_input = get_input
|
|
||||||
get_diff_output = get_output
|
|
||||||
get_diff_tristate = get_tristate
|
|
||||||
get_diff_input_output = get_input_output
|
|
||||||
|
|
||||||
|
|
||||||
class TemplatedPlatform(Platform):
|
class TemplatedPlatform(Platform):
|
||||||
toolchain = property(abstractmethod(lambda: None))
|
toolchain = property(abstractmethod(lambda: None))
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from ..hdl._ast import *
|
from ..hdl import *
|
||||||
from ..lib.io import *
|
from ..hdl._ast import SignalDict
|
||||||
from ..lib import wiring
|
from ..lib import wiring, io
|
||||||
|
|
||||||
from .dsl import *
|
from .dsl import *
|
||||||
|
|
||||||
|
@ -24,6 +24,78 @@ class PortMetadata:
|
||||||
self.attrs = attrs
|
self.attrs = attrs
|
||||||
|
|
||||||
|
|
||||||
|
class PinBuffer(Elaboratable):
|
||||||
|
def __init__(self, pin, port):
|
||||||
|
if pin.xdr not in (0, 1, 2):
|
||||||
|
raise ValueError(f"Unsupported 'xdr' value {pin.xdr}")
|
||||||
|
self.pin = pin
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
def elaborate(self, platform):
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
if self.pin.dir == "i":
|
||||||
|
if self.pin.xdr == 0:
|
||||||
|
m.submodules.buf = buf = io.Buffer(io.Direction.Input, self.port)
|
||||||
|
m.d.comb += self.pin.i.eq(buf.i)
|
||||||
|
elif self.pin.xdr == 1:
|
||||||
|
m.domains.input = cd_input = ClockDomain(reset_less=True)
|
||||||
|
m.submodules.buf = buf = io.FFBuffer(io.Direction.Input, self.port, i_domain="input")
|
||||||
|
m.d.comb += self.pin.i.eq(buf.i)
|
||||||
|
m.d.comb += cd_input.clk.eq(self.pin.i_clk)
|
||||||
|
elif self.pin.xdr == 2:
|
||||||
|
m.domains.input = cd_input = ClockDomain(reset_less=True)
|
||||||
|
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Input, self.port, i_domain="input")
|
||||||
|
m.d.comb += self.pin.i0.eq(buf.i[0])
|
||||||
|
m.d.comb += self.pin.i1.eq(buf.i[1])
|
||||||
|
m.d.comb += cd_input.clk.eq(self.pin.i_clk)
|
||||||
|
if self.pin.dir in ("o", "oe"):
|
||||||
|
if self.pin.xdr == 0:
|
||||||
|
m.submodules.buf = buf = io.Buffer(io.Direction.Output, self.port)
|
||||||
|
m.d.comb += buf.o.eq(self.pin.o)
|
||||||
|
elif self.pin.xdr == 1:
|
||||||
|
m.domains.output = cd_output = ClockDomain(reset_less=True)
|
||||||
|
m.submodules.buf = buf = io.FFBuffer(io.Direction.Output, self.port, o_domain="output")
|
||||||
|
m.d.comb += buf.o.eq(self.pin.o)
|
||||||
|
m.d.comb += cd_output.clk.eq(self.pin.o_clk)
|
||||||
|
elif self.pin.xdr == 2:
|
||||||
|
m.domains.output = cd_output = ClockDomain(reset_less=True)
|
||||||
|
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Output, self.port, o_domain="output")
|
||||||
|
m.d.comb += buf.o[0].eq(self.pin.o0)
|
||||||
|
m.d.comb += buf.o[1].eq(self.pin.o1)
|
||||||
|
m.d.comb += cd_output.clk.eq(self.pin.o_clk)
|
||||||
|
if self.pin.dir == "oe":
|
||||||
|
m.d.comb += buf.oe.eq(self.pin.oe)
|
||||||
|
if self.pin.dir == "io":
|
||||||
|
if self.pin.xdr == 0:
|
||||||
|
m.submodules.buf = buf = io.Buffer(io.Direction.Bidir, self.port)
|
||||||
|
m.d.comb += self.pin.i.eq(buf.i)
|
||||||
|
m.d.comb += buf.o.eq(self.pin.o)
|
||||||
|
m.d.comb += buf.oe.eq(self.pin.oe)
|
||||||
|
elif self.pin.xdr == 1:
|
||||||
|
m.domains.input = cd_input = ClockDomain(reset_less=True)
|
||||||
|
m.domains.output = cd_output = ClockDomain(reset_less=True)
|
||||||
|
m.submodules.buf = buf = io.FFBuffer(io.Direction.Bidir, self.port, i_domain="input", o_domain="output")
|
||||||
|
m.d.comb += self.pin.i.eq(buf.i)
|
||||||
|
m.d.comb += buf.o.eq(self.pin.o)
|
||||||
|
m.d.comb += buf.oe.eq(self.pin.oe)
|
||||||
|
m.d.comb += cd_input.clk.eq(self.pin.i_clk)
|
||||||
|
m.d.comb += cd_output.clk.eq(self.pin.o_clk)
|
||||||
|
elif self.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, self.port, i_domain="input", o_domain="output")
|
||||||
|
m.d.comb += self.pin.i0.eq(buf.i[0])
|
||||||
|
m.d.comb += self.pin.i1.eq(buf.i[1])
|
||||||
|
m.d.comb += buf.o[0].eq(self.pin.o0)
|
||||||
|
m.d.comb += buf.o[1].eq(self.pin.o1)
|
||||||
|
m.d.comb += buf.oe.eq(self.pin.oe)
|
||||||
|
m.d.comb += cd_input.clk.eq(self.pin.i_clk)
|
||||||
|
m.d.comb += cd_output.clk.eq(self.pin.o_clk)
|
||||||
|
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
class ResourceManager:
|
class ResourceManager:
|
||||||
def __init__(self, resources, connectors):
|
def __init__(self, resources, connectors):
|
||||||
self.resources = OrderedDict()
|
self.resources = OrderedDict()
|
||||||
|
@ -33,8 +105,11 @@ class ResourceManager:
|
||||||
self.connectors = OrderedDict()
|
self.connectors = OrderedDict()
|
||||||
self._conn_pins = OrderedDict()
|
self._conn_pins = OrderedDict()
|
||||||
|
|
||||||
# Constraint lists
|
# List of all IOPort instances created
|
||||||
self._ports = []
|
self._ports = []
|
||||||
|
# List of (pin, port, buffer) pairs for non-dir="-" requests.
|
||||||
|
self._pins = []
|
||||||
|
# Constraint list
|
||||||
self._clocks = SignalDict()
|
self._clocks = SignalDict()
|
||||||
|
|
||||||
self.add_resources(resources)
|
self.add_resources(resources)
|
||||||
|
@ -139,11 +214,12 @@ class ResourceManager:
|
||||||
direction = phys.dir
|
direction = phys.dir
|
||||||
if isinstance(phys, Pins):
|
if isinstance(phys, Pins):
|
||||||
phys_names = phys.map_names(self._conn_pins, resource)
|
phys_names = phys.map_names(self._conn_pins, resource)
|
||||||
io = IOPort(len(phys), name="__".join(path) + "__io", metadata=[
|
iop = IOPort(len(phys), name="__".join(path) + "__io", metadata=[
|
||||||
PortMetadata(name, attrs)
|
PortMetadata(name, attrs)
|
||||||
for name in phys_names
|
for name in phys_names
|
||||||
])
|
])
|
||||||
port = SingleEndedPort(io, invert=phys.invert, direction=direction)
|
self._ports.append(iop)
|
||||||
|
port = io.SingleEndedPort(iop, invert=phys.invert, direction=direction)
|
||||||
if isinstance(phys, DiffPairs):
|
if isinstance(phys, DiffPairs):
|
||||||
phys_names_p = phys.p.map_names(self._conn_pins, resource)
|
phys_names_p = phys.p.map_names(self._conn_pins, resource)
|
||||||
phys_names_n = phys.n.map_names(self._conn_pins, resource)
|
phys_names_n = phys.n.map_names(self._conn_pins, resource)
|
||||||
|
@ -156,11 +232,8 @@ class ResourceManager:
|
||||||
PortMetadata(name, attrs)
|
PortMetadata(name, attrs)
|
||||||
for name in phys_names_n
|
for name in phys_names_n
|
||||||
])
|
])
|
||||||
port = DifferentialPort(p, n, invert=phys.invert, direction=direction)
|
self._ports += [p, n]
|
||||||
if dir == "-":
|
port = io.DifferentialPort(p, n, invert=phys.invert, direction=direction)
|
||||||
pin = None
|
|
||||||
else:
|
|
||||||
pin = wiring.flipped(Pin(len(phys), dir, xdr=xdr, path=path))
|
|
||||||
|
|
||||||
for phys_name in phys_names:
|
for phys_name in phys_names:
|
||||||
if phys_name in self._phys_reqd:
|
if phys_name in self._phys_reqd:
|
||||||
|
@ -171,12 +244,16 @@ class ResourceManager:
|
||||||
".".join(self._phys_reqd[phys_name])))
|
".".join(self._phys_reqd[phys_name])))
|
||||||
self._phys_reqd[phys_name] = path
|
self._phys_reqd[phys_name] = path
|
||||||
|
|
||||||
self._ports.append((resource, pin, port, attrs))
|
if dir == "-":
|
||||||
|
return port
|
||||||
|
else:
|
||||||
|
pin = wiring.flipped(io.Pin(len(phys), dir, xdr=xdr, path=path))
|
||||||
|
buffer = PinBuffer(pin, port)
|
||||||
|
self._pins.append((pin, port, buffer))
|
||||||
|
|
||||||
if pin is not None and resource.clock is not None:
|
if resource.clock is not None:
|
||||||
self.add_clock_constraint(pin.i, resource.clock.frequency)
|
self.add_clock_constraint(pin.i, resource.clock.frequency)
|
||||||
|
return pin
|
||||||
return pin if pin is not None else port
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
assert False # :nocov:
|
assert False # :nocov:
|
||||||
|
@ -188,56 +265,19 @@ class ResourceManager:
|
||||||
self._requested[resource.name, resource.number] = value
|
self._requested[resource.name, resource.number] = value
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def iter_single_ended_pins(self):
|
def iter_pins(self):
|
||||||
for res, pin, port, attrs in self._ports:
|
yield from self._pins
|
||||||
if pin is None:
|
|
||||||
continue
|
|
||||||
if isinstance(res.ios[0], Pins):
|
|
||||||
yield pin, port, attrs, res.ios[0].invert
|
|
||||||
|
|
||||||
def iter_differential_pins(self):
|
|
||||||
for res, pin, port, attrs in self._ports:
|
|
||||||
if pin is None:
|
|
||||||
continue
|
|
||||||
if isinstance(res.ios[0], DiffPairs):
|
|
||||||
yield pin, port, attrs, res.ios[0].invert
|
|
||||||
|
|
||||||
def should_skip_port_component(self, port, attrs, component):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def iter_ports(self):
|
def iter_ports(self):
|
||||||
for res, pin, port, attrs in self._ports:
|
yield from self._ports
|
||||||
if isinstance(res.ios[0], Pins):
|
|
||||||
if not self.should_skip_port_component(port, attrs, "io"):
|
|
||||||
yield port.io
|
|
||||||
elif isinstance(res.ios[0], DiffPairs):
|
|
||||||
if not self.should_skip_port_component(port, attrs, "p"):
|
|
||||||
yield port.p
|
|
||||||
if not self.should_skip_port_component(port, attrs, "n"):
|
|
||||||
yield port.n
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
def iter_port_constraints(self):
|
|
||||||
for res, pin, port, attrs in self._ports:
|
|
||||||
if isinstance(res.ios[0], Pins):
|
|
||||||
if not self.should_skip_port_component(port, attrs, "io"):
|
|
||||||
yield port.io.name, res.ios[0].map_names(self._conn_pins, res), attrs
|
|
||||||
elif isinstance(res.ios[0], DiffPairs):
|
|
||||||
if not self.should_skip_port_component(port, attrs, "p"):
|
|
||||||
yield port.p.name, res.ios[0].p.map_names(self._conn_pins, res), attrs
|
|
||||||
if not self.should_skip_port_component(port, attrs, "n"):
|
|
||||||
yield port.n.name, res.ios[0].n.map_names(self._conn_pins, res), attrs
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
def iter_port_constraints_bits(self):
|
def iter_port_constraints_bits(self):
|
||||||
for port_name, pin_names, attrs in self.iter_port_constraints():
|
for port in self._ports:
|
||||||
if len(pin_names) == 1:
|
if len(port) == 1:
|
||||||
yield port_name, pin_names[0], attrs
|
yield port.name, port.metadata[0].name, port.metadata[0].attrs
|
||||||
else:
|
else:
|
||||||
for bit, pin_name in enumerate(pin_names):
|
for bit, meta in enumerate(port.metadata):
|
||||||
yield f"{port_name}[{bit}]", pin_name, attrs
|
yield f"{port.name}[{bit}]", meta.name, meta.attrs
|
||||||
|
|
||||||
def add_clock_constraint(self, clock, frequency):
|
def add_clock_constraint(self, clock, frequency):
|
||||||
if isinstance(clock, ClockSignal):
|
if isinstance(clock, ClockSignal):
|
||||||
|
@ -267,11 +307,11 @@ class ResourceManager:
|
||||||
# Constraints on nets with no corresponding input pin (e.g. PLL or SERDES outputs) are not
|
# Constraints on nets with no corresponding input pin (e.g. PLL or SERDES outputs) are not
|
||||||
# affected.
|
# affected.
|
||||||
pin_i_to_port = SignalDict()
|
pin_i_to_port = SignalDict()
|
||||||
for res, pin, port, attrs in self._ports:
|
for pin, port, _fragment in self._pins:
|
||||||
if hasattr(pin, "i"):
|
if hasattr(pin, "i"):
|
||||||
if isinstance(res.ios[0], Pins):
|
if isinstance(port, io.SingleEndedPort):
|
||||||
pin_i_to_port[pin.i] = port.io
|
pin_i_to_port[pin.i] = port.io
|
||||||
elif isinstance(res.ios[0], DiffPairs):
|
elif isinstance(port, io.DifferentialPort):
|
||||||
pin_i_to_port[pin.i] = port.p
|
pin_i_to_port[pin.i] = port.p
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
|
@ -63,12 +63,15 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
self.assertEqual(user_led.width, 1)
|
self.assertEqual(user_led.width, 1)
|
||||||
self.assertEqual(user_led.dir, "o")
|
self.assertEqual(user_led.dir, "o")
|
||||||
|
|
||||||
ports = list(self.cm.iter_ports())
|
pins = list(self.cm.iter_pins())
|
||||||
self.assertEqual(len(ports), 1)
|
(pin, port, buffer), = pins
|
||||||
|
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
self.assertIs(pin, user_led)
|
||||||
("user_led_0__io", ["A0"], {})
|
self.assertEqual(port.io.name, "user_led_0__io")
|
||||||
])
|
self.assertEqual(port.io.metadata[0].name, "A0")
|
||||||
|
self.assertEqual(port.io.metadata[0].attrs, {})
|
||||||
|
self.assertEqual(port.direction, Direction.Output)
|
||||||
|
self.assertEqual(port.invert, (False,))
|
||||||
|
|
||||||
def test_request_with_dir(self):
|
def test_request_with_dir(self):
|
||||||
i2c = self.cm.request("i2c", 0, dir={"sda": "o"})
|
i2c = self.cm.request("i2c", 0, dir={"sda": "o"})
|
||||||
|
@ -79,24 +82,13 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
i2c = self.cm.request("i2c", 0)
|
i2c = self.cm.request("i2c", 0)
|
||||||
self.assertEqual(i2c.sda.dir, "io")
|
self.assertEqual(i2c.sda.dir, "io")
|
||||||
|
|
||||||
ports = list(self.cm.iter_ports())
|
((scl_pin, scl_port, _), (sda_pin, sda_port, _)) = self.cm.iter_pins()
|
||||||
self.assertEqual(len(ports), 2)
|
self.assertIs(scl_pin, i2c.scl)
|
||||||
scl, sda = ports
|
self.assertIs(sda_pin, i2c.sda)
|
||||||
self.assertEqual(ports[1].name, "i2c_0__sda__io")
|
self.assertEqual(scl_port.io.name, "i2c_0__scl__io")
|
||||||
self.assertEqual(ports[1].width, 1)
|
self.assertEqual(scl_port.io.metadata[0].name, "N10")
|
||||||
|
self.assertEqual(sda_port.io.name, "i2c_0__sda__io")
|
||||||
scl_info, sda_info = self.cm.iter_single_ended_pins()
|
self.assertEqual(sda_port.io.metadata[0].name, "N11")
|
||||||
self.assertIs(scl_info[0], i2c.scl)
|
|
||||||
self.assertIs(scl_info[1].io, scl)
|
|
||||||
self.assertEqual(scl_info[2], {})
|
|
||||||
self.assertEqual(scl_info[3], False)
|
|
||||||
self.assertIs(sda_info[0], i2c.sda)
|
|
||||||
self.assertIs(sda_info[1].io, sda)
|
|
||||||
|
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
|
||||||
("i2c_0__scl__io", ["N10"], {}),
|
|
||||||
("i2c_0__sda__io", ["N11"], {})
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_request_diffpairs(self):
|
def test_request_diffpairs(self):
|
||||||
clk100 = self.cm.request("clk100", 0)
|
clk100 = self.cm.request("clk100", 0)
|
||||||
|
@ -104,25 +96,14 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
self.assertEqual(clk100.dir, "i")
|
self.assertEqual(clk100.dir, "i")
|
||||||
self.assertEqual(clk100.width, 1)
|
self.assertEqual(clk100.width, 1)
|
||||||
|
|
||||||
ports = list(self.cm.iter_ports())
|
(clk100_pin, clk100_port, _), = self.cm.iter_pins()
|
||||||
self.assertEqual(len(ports), 2)
|
self.assertIs(clk100_pin, clk100)
|
||||||
p, n = ports
|
self.assertEqual(clk100_port.p.name, "clk100_0__p")
|
||||||
self.assertEqual(p.name, "clk100_0__p")
|
self.assertEqual(clk100_port.p.width, clk100.width)
|
||||||
self.assertEqual(p.width, clk100.width)
|
self.assertEqual(clk100_port.n.name, "clk100_0__n")
|
||||||
self.assertEqual(n.name, "clk100_0__n")
|
self.assertEqual(clk100_port.n.width, clk100.width)
|
||||||
self.assertEqual(n.width, clk100.width)
|
self.assertEqual(clk100_port.p.metadata[0].name, "H1")
|
||||||
|
self.assertEqual(clk100_port.n.metadata[0].name, "H2")
|
||||||
clk100_info, = self.cm.iter_differential_pins()
|
|
||||||
self.assertIs(clk100_info[0], clk100)
|
|
||||||
self.assertIs(clk100_info[1].p, p)
|
|
||||||
self.assertIs(clk100_info[1].n, n)
|
|
||||||
self.assertEqual(clk100_info[2], {})
|
|
||||||
self.assertEqual(clk100_info[3], False)
|
|
||||||
|
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
|
||||||
("clk100_0__p", ["H1"], {}),
|
|
||||||
("clk100_0__n", ["H2"], {}),
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_request_inverted(self):
|
def test_request_inverted(self):
|
||||||
new_resources = [
|
new_resources = [
|
||||||
|
@ -133,39 +114,27 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
|
|
||||||
cs = self.cm.request("cs")
|
cs = self.cm.request("cs")
|
||||||
clk = self.cm.request("clk")
|
clk = self.cm.request("clk")
|
||||||
cs_io, clk_p, clk_n = self.cm.iter_ports()
|
(
|
||||||
|
(cs_pin, cs_port, _),
|
||||||
|
(clk_pin, clk_port, _),
|
||||||
|
) = self.cm.iter_pins()
|
||||||
|
|
||||||
cs_info, = self.cm.iter_single_ended_pins()
|
self.assertIs(cs_pin, cs)
|
||||||
self.assertIs(cs_info[0], cs)
|
self.assertEqual(cs_port.invert, (True,))
|
||||||
self.assertIs(cs_info[1].io, cs_io)
|
self.assertIs(clk_pin, clk)
|
||||||
self.assertEqual(cs_info[2], {})
|
self.assertEqual(clk_port.invert, (True,))
|
||||||
self.assertEqual(cs_info[3], True)
|
|
||||||
|
|
||||||
clk_info, = self.cm.iter_differential_pins()
|
|
||||||
self.assertIs(clk_info[0], clk)
|
|
||||||
self.assertIs(clk_info[1].p, clk_p)
|
|
||||||
self.assertIs(clk_info[1].n, clk_n)
|
|
||||||
self.assertEqual(clk_info[2], {})
|
|
||||||
self.assertEqual(clk_info[3], True)
|
|
||||||
|
|
||||||
def test_request_raw(self):
|
def test_request_raw(self):
|
||||||
clk50 = self.cm.request("clk50", 0, dir="-")
|
clk50 = self.cm.request("clk50", 0, dir="-")
|
||||||
|
self.assertIsInstance(clk50, SingleEndedPort)
|
||||||
self.assertIsInstance(clk50.io, IOPort)
|
self.assertIsInstance(clk50.io, IOPort)
|
||||||
|
|
||||||
ports = list(self.cm.iter_ports())
|
|
||||||
self.assertEqual(len(ports), 1)
|
|
||||||
self.assertIs(ports[0], clk50.io)
|
|
||||||
|
|
||||||
def test_request_raw_diffpairs(self):
|
def test_request_raw_diffpairs(self):
|
||||||
clk100 = self.cm.request("clk100", 0, dir="-")
|
clk100 = self.cm.request("clk100", 0, dir="-")
|
||||||
|
self.assertIsInstance(clk100, DifferentialPort)
|
||||||
self.assertIsInstance(clk100.p, IOPort)
|
self.assertIsInstance(clk100.p, IOPort)
|
||||||
self.assertIsInstance(clk100.n, IOPort)
|
self.assertIsInstance(clk100.n, IOPort)
|
||||||
|
|
||||||
ports = list(self.cm.iter_ports())
|
|
||||||
self.assertEqual(len(ports), 2)
|
|
||||||
self.assertIs(ports[0], clk100.p)
|
|
||||||
self.assertIs(ports[1], clk100.n)
|
|
||||||
|
|
||||||
def test_request_via_connector(self):
|
def test_request_via_connector(self):
|
||||||
self.cm.add_resources([
|
self.cm.add_resources([
|
||||||
Resource("spi", 0,
|
Resource("spi", 0,
|
||||||
|
@ -176,12 +145,20 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
spi0 = self.cm.request("spi", 0)
|
spi0 = self.cm.request("spi", 0)
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
(
|
||||||
("spi_0__ss__io", ["B0"], {}),
|
(ss_pin, ss_port, _),
|
||||||
("spi_0__clk__io", ["B1"], {}),
|
(clk_pin, clk_port, _),
|
||||||
("spi_0__miso__io", ["B2"], {}),
|
(miso_pin, miso_port, _),
|
||||||
("spi_0__mosi__io", ["B3"], {}),
|
(mosi_pin, mosi_port, _),
|
||||||
])
|
) = self.cm.iter_pins()
|
||||||
|
self.assertIs(ss_pin, spi0.ss)
|
||||||
|
self.assertIs(clk_pin, spi0.clk)
|
||||||
|
self.assertIs(miso_pin, spi0.miso)
|
||||||
|
self.assertIs(mosi_pin, spi0.mosi)
|
||||||
|
self.assertEqual(ss_port.io.metadata[0].name, "B0")
|
||||||
|
self.assertEqual(clk_port.io.metadata[0].name, "B1")
|
||||||
|
self.assertEqual(miso_port.io.metadata[0].name, "B2")
|
||||||
|
self.assertEqual(mosi_port.io.metadata[0].name, "B3")
|
||||||
|
|
||||||
def test_request_via_nested_connector(self):
|
def test_request_via_nested_connector(self):
|
||||||
new_connectors = [
|
new_connectors = [
|
||||||
|
@ -197,20 +174,31 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
spi0 = self.cm.request("spi", 0)
|
spi0 = self.cm.request("spi", 0)
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
(
|
||||||
("spi_0__ss__io", ["B0"], {}),
|
(ss_pin, ss_port, _),
|
||||||
("spi_0__clk__io", ["B1"], {}),
|
(clk_pin, clk_port, _),
|
||||||
("spi_0__miso__io", ["B2"], {}),
|
(miso_pin, miso_port, _),
|
||||||
("spi_0__mosi__io", ["B3"], {}),
|
(mosi_pin, mosi_port, _),
|
||||||
])
|
) = self.cm.iter_pins()
|
||||||
|
self.assertIs(ss_pin, spi0.ss)
|
||||||
|
self.assertIs(clk_pin, spi0.clk)
|
||||||
|
self.assertIs(miso_pin, spi0.miso)
|
||||||
|
self.assertIs(mosi_pin, spi0.mosi)
|
||||||
|
self.assertEqual(ss_port.io.metadata[0].name, "B0")
|
||||||
|
self.assertEqual(clk_port.io.metadata[0].name, "B1")
|
||||||
|
self.assertEqual(miso_port.io.metadata[0].name, "B2")
|
||||||
|
self.assertEqual(mosi_port.io.metadata[0].name, "B3")
|
||||||
|
|
||||||
def test_request_clock(self):
|
def test_request_clock(self):
|
||||||
clk100 = self.cm.request("clk100", 0)
|
clk100 = self.cm.request("clk100", 0)
|
||||||
clk50 = self.cm.request("clk50", 0, dir="i")
|
clk50 = self.cm.request("clk50", 0, dir="i")
|
||||||
clk100_port_p, clk100_port_n, clk50_port = self.cm.iter_ports()
|
(
|
||||||
|
(clk100_pin, clk100_port, _),
|
||||||
|
(clk50_pin, clk50_port, _),
|
||||||
|
) = self.cm.iter_pins()
|
||||||
self.assertEqual(list(self.cm.iter_clock_constraints()), [
|
self.assertEqual(list(self.cm.iter_clock_constraints()), [
|
||||||
(clk100.i, clk100_port_p, 100e6),
|
(clk100.i, clk100_port.p, 100e6),
|
||||||
(clk50.i, clk50_port, 50e6)
|
(clk50.i, clk50_port.io, 50e6)
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_add_clock(self):
|
def test_add_clock(self):
|
||||||
|
|
Loading…
Reference in a new issue