lib.io, build.res: Make Pin
and related objects interfaces.
Fixes #1040.
This commit is contained in:
parent
c30585b47b
commit
f524dd041a
|
@ -1,10 +1,6 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import warnings
|
|
||||||
|
|
||||||
from ..hdl._ast import *
|
from ..hdl._ast import *
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
||||||
from ..hdl.rec import *
|
|
||||||
from ..lib.io import *
|
from ..lib.io import *
|
||||||
from ..lib import wiring
|
from ..lib import wiring
|
||||||
|
|
||||||
|
@ -106,7 +102,7 @@ class ResourceManager:
|
||||||
.format(subsignal.ios[0], xdr))
|
.format(subsignal.ios[0], xdr))
|
||||||
return dir, xdr
|
return dir, xdr
|
||||||
|
|
||||||
def resolve(resource, dir, xdr, name, attrs):
|
def resolve(resource, dir, xdr, path, attrs):
|
||||||
for attr_key, attr_value in attrs.items():
|
for attr_key, attr_value in attrs.items():
|
||||||
if hasattr(attr_value, "__call__"):
|
if hasattr(attr_value, "__call__"):
|
||||||
attr_value = attr_value(self)
|
attr_value = attr_value(self)
|
||||||
|
@ -117,18 +113,21 @@ class ResourceManager:
|
||||||
attrs[attr_key] = attr_value
|
attrs[attr_key] = attr_value
|
||||||
|
|
||||||
if isinstance(resource.ios[0], Subsignal):
|
if isinstance(resource.ios[0], Subsignal):
|
||||||
fields = OrderedDict()
|
members = OrderedDict()
|
||||||
|
sig_members = OrderedDict()
|
||||||
for sub in resource.ios:
|
for sub in resource.ios:
|
||||||
fields[sub.name] = resolve(sub, dir[sub.name], xdr[sub.name],
|
member = resolve(sub, dir[sub.name], xdr[sub.name],
|
||||||
name=f"{name}__{sub.name}",
|
path=path + (sub.name,),
|
||||||
attrs={**attrs, **sub.attrs})
|
attrs={**attrs, **sub.attrs})
|
||||||
rec = Record([
|
members[sub.name] = member
|
||||||
(f_name, f.layout) for (f_name, f) in fields.items()
|
sig_members[sub.name] = wiring.Out(member.signature)
|
||||||
], fields=fields, name=name)
|
signature = wiring.Signature(sig_members)
|
||||||
rec.signature = wiring.Signature({
|
# Provide members ourselves instead of having the constructor
|
||||||
f_name: wiring.Out(f.signature) for (f_name, f) in fields.items()
|
# create ones for us.
|
||||||
})
|
intf = object.__new__(wiring.PureInterface)
|
||||||
return rec
|
intf.signature = signature
|
||||||
|
intf.__dict__.update(members)
|
||||||
|
return intf
|
||||||
|
|
||||||
elif isinstance(resource.ios[0], (Pins, DiffPairs)):
|
elif isinstance(resource.ios[0], (Pins, DiffPairs)):
|
||||||
phys = resource.ios[0]
|
phys = resource.ios[0]
|
||||||
|
@ -137,34 +136,30 @@ class ResourceManager:
|
||||||
# ignore it as well.
|
# ignore it as well.
|
||||||
if isinstance(phys, Pins):
|
if isinstance(phys, Pins):
|
||||||
phys_names = phys.names
|
phys_names = phys.names
|
||||||
port = Record([("io", len(phys))], name=name)
|
port = wiring.Signature({"io": wiring.In(len(phys))}).create(path=path)
|
||||||
port.signature = wiring.Signature({"io": wiring.In(len(phys))})
|
|
||||||
if isinstance(phys, DiffPairs):
|
if isinstance(phys, DiffPairs):
|
||||||
phys_names = []
|
phys_names = []
|
||||||
rec_members = []
|
|
||||||
sig_members = {}
|
sig_members = {}
|
||||||
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
|
||||||
rec_members.append(("p", len(phys)))
|
|
||||||
sig_members["p"] = wiring.In(len(phys))
|
sig_members["p"] = wiring.In(len(phys))
|
||||||
if not self.should_skip_port_component(None, attrs, "n"):
|
if not self.should_skip_port_component(None, attrs, "n"):
|
||||||
phys_names += phys.n.names
|
phys_names += phys.n.names
|
||||||
rec_members.append(("n", len(phys)))
|
|
||||||
sig_members["n"] = wiring.In(len(phys))
|
sig_members["n"] = wiring.In(len(phys))
|
||||||
port = Record(rec_members, name=name)
|
port = wiring.Signature(sig_members).create(path=path)
|
||||||
port.signature = wiring.Signature(sig_members)
|
|
||||||
if dir == "-":
|
if dir == "-":
|
||||||
pin = None
|
pin = None
|
||||||
else:
|
else:
|
||||||
pin = wiring.flipped(Pin(len(phys), dir, xdr=xdr, name=name))
|
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:
|
||||||
raise ResourceError("Resource component {} uses physical pin {}, but it "
|
raise ResourceError("Resource component {} uses physical pin {}, but it "
|
||||||
"is already used by resource component {} that was "
|
"is already used by resource component {} that was "
|
||||||
"requested earlier"
|
"requested earlier"
|
||||||
.format(name, phys_name, self._phys_reqd[phys_name]))
|
.format(".".join(path), phys_name,
|
||||||
self._phys_reqd[phys_name] = name
|
".".join(self._phys_reqd[phys_name])))
|
||||||
|
self._phys_reqd[phys_name] = path
|
||||||
|
|
||||||
self._ports.append((resource, pin, port, attrs))
|
self._ports.append((resource, pin, port, attrs))
|
||||||
|
|
||||||
|
@ -178,7 +173,7 @@ class ResourceManager:
|
||||||
|
|
||||||
value = resolve(resource,
|
value = resolve(resource,
|
||||||
*merge_options(resource, dir, xdr),
|
*merge_options(resource, dir, xdr),
|
||||||
name=f"{resource.name}_{resource.number}",
|
path=(f"{resource.name}_{resource.number}",),
|
||||||
attrs=resource.attrs)
|
attrs=resource.attrs)
|
||||||
self._requested[resource.name, resource.number] = value
|
self._requested[resource.name, resource.number] = value
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -1,74 +1,18 @@
|
||||||
import warnings
|
|
||||||
|
|
||||||
from .. import *
|
from .. import *
|
||||||
with warnings.catch_warnings():
|
from ..lib import wiring
|
||||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
from ..lib.wiring import In, Out
|
||||||
from ..hdl.rec import *
|
|
||||||
from ..lib.wiring import In, Out, Signature, flipped, FlippedInterface
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["pin_layout", "Pin"]
|
__all__ = ["Pin"]
|
||||||
|
|
||||||
|
|
||||||
def _pin_signature(width, dir, xdr=0):
|
class Pin(wiring.PureInterface):
|
||||||
if not isinstance(width, int) or width < 0:
|
|
||||||
raise TypeError("Width must be a non-negative integer, not {!r}"
|
|
||||||
.format(width))
|
|
||||||
if dir not in ("i", "o", "oe", "io"):
|
|
||||||
raise TypeError("Direction must be one of \"i\", \"o\", \"io\", or \"oe\", not {!r}"""
|
|
||||||
.format(dir))
|
|
||||||
if not isinstance(xdr, int) or xdr < 0:
|
|
||||||
raise TypeError("Gearing ratio must be a non-negative integer, not {!r}"
|
|
||||||
.format(xdr))
|
|
||||||
|
|
||||||
members = {}
|
|
||||||
if dir in ("i", "io"):
|
|
||||||
if xdr > 0:
|
|
||||||
members["i_clk"] = In(1)
|
|
||||||
if xdr > 2:
|
|
||||||
members["i_fclk"] = In(1)
|
|
||||||
if xdr in (0, 1):
|
|
||||||
members["i"] = In(width)
|
|
||||||
else:
|
|
||||||
for n in range(xdr):
|
|
||||||
members[f"i{n}"] = In(width)
|
|
||||||
if dir in ("o", "oe", "io"):
|
|
||||||
if xdr > 0:
|
|
||||||
members["o_clk"] = Out(1)
|
|
||||||
if xdr > 2:
|
|
||||||
members["o_fclk"] = Out(1)
|
|
||||||
if xdr in (0, 1):
|
|
||||||
members["o"] = Out(width)
|
|
||||||
else:
|
|
||||||
for n in range(xdr):
|
|
||||||
members[f"o{n}"] = Out(width)
|
|
||||||
if dir in ("oe", "io"):
|
|
||||||
members["oe"] = Out(1)
|
|
||||||
return Signature(members)
|
|
||||||
|
|
||||||
|
|
||||||
def pin_layout(width, dir, xdr=0):
|
|
||||||
"""
|
|
||||||
Layout of the platform interface of a pin or several pins, which may be used inside
|
|
||||||
user-defined records.
|
|
||||||
|
|
||||||
See :class:`Pin` for details.
|
|
||||||
"""
|
|
||||||
fields = []
|
|
||||||
for name, member in _pin_signature(width, dir, xdr).members.items():
|
|
||||||
fields.append((name, member.shape))
|
|
||||||
return Layout(fields)
|
|
||||||
|
|
||||||
|
|
||||||
class Pin(Record):
|
|
||||||
"""
|
"""
|
||||||
An interface to an I/O buffer or a group of them that provides uniform access to input, output,
|
An interface to an I/O buffer or a group of them that provides uniform access to input, output,
|
||||||
or tristate buffers that may include a 1:n gearbox. (A 1:2 gearbox is typically called "DDR".)
|
or tristate buffers that may include a 1:n gearbox. (A 1:2 gearbox is typically called "DDR".)
|
||||||
|
|
||||||
A :class:`Pin` is identical to a :class:`Record` that uses the corresponding :meth:`pin_layout`
|
This is an interface object using :class:`Pin.Signature` as its signature. The signature flows
|
||||||
except that it allows accessing the parameters like ``width`` as attributes. It is legal to use
|
are defined from the point of view of a component that drives the I/O buffer.
|
||||||
a plain :class:`Record` anywhere a :class:`Pin` is used, provided that these attributes are
|
|
||||||
not necessary.
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
|
@ -87,8 +31,8 @@ class Pin(Record):
|
||||||
are present instead, where ``N in range(0, N)``. For example, if ``xdr=2``, the I/O buffer
|
are present instead, where ``N in range(0, N)``. For example, if ``xdr=2``, the I/O buffer
|
||||||
is DDR; the signal ``i0`` reflects the value at the rising edge, and the signal ``i1``
|
is DDR; the signal ``i0`` reflects the value at the rising edge, and the signal ``i1``
|
||||||
reflects the value at the falling edge.
|
reflects the value at the falling edge.
|
||||||
name : str
|
path : tuple of str
|
||||||
Name of the underlying record.
|
As in :class:`PureInterface`, used to name the created signals.
|
||||||
|
|
||||||
Attributes
|
Attributes
|
||||||
----------
|
----------
|
||||||
|
@ -119,23 +63,76 @@ class Pin(Record):
|
||||||
cannot change direction more than once per cycle, so at most one output enable signal
|
cannot change direction more than once per cycle, so at most one output enable signal
|
||||||
is present.
|
is present.
|
||||||
"""
|
"""
|
||||||
def __init__(self, width, dir, *, xdr=0, name=None, src_loc_at=0):
|
|
||||||
self.width = width
|
|
||||||
self.dir = dir
|
|
||||||
self.xdr = xdr
|
|
||||||
|
|
||||||
super().__init__(pin_layout(self.width, self.dir, self.xdr),
|
class Signature(wiring.Signature):
|
||||||
name=name, src_loc_at=src_loc_at + 1)
|
"""A signature for :class:`Pin`. The parameters are as defined on the ``Pin`` class,
|
||||||
|
and are accessible as attributes.
|
||||||
|
"""
|
||||||
|
def __init__(self, width, dir, *, xdr=0):
|
||||||
|
if not isinstance(width, int) or width < 0:
|
||||||
|
raise TypeError("Width must be a non-negative integer, not {!r}"
|
||||||
|
.format(width))
|
||||||
|
if dir not in ("i", "o", "oe", "io"):
|
||||||
|
raise TypeError("Direction must be one of \"i\", \"o\", \"io\", or \"oe\", not {!r}"""
|
||||||
|
.format(dir))
|
||||||
|
if not isinstance(xdr, int) or xdr < 0:
|
||||||
|
raise TypeError("Gearing ratio must be a non-negative integer, not {!r}"
|
||||||
|
.format(xdr))
|
||||||
|
|
||||||
|
self.width = width
|
||||||
|
self.dir = dir
|
||||||
|
self.xdr = xdr
|
||||||
|
|
||||||
|
members = {}
|
||||||
|
if dir in ("i", "io"):
|
||||||
|
if xdr > 0:
|
||||||
|
members["i_clk"] = Out(1)
|
||||||
|
if xdr > 2:
|
||||||
|
members["i_fclk"] = Out(1)
|
||||||
|
if xdr in (0, 1):
|
||||||
|
members["i"] = In(width)
|
||||||
|
else:
|
||||||
|
for n in range(xdr):
|
||||||
|
members[f"i{n}"] = In(width)
|
||||||
|
if dir in ("o", "oe", "io"):
|
||||||
|
if xdr > 0:
|
||||||
|
members["o_clk"] = Out(1)
|
||||||
|
if xdr > 2:
|
||||||
|
members["o_fclk"] = Out(1)
|
||||||
|
if xdr in (0, 1):
|
||||||
|
members["o"] = Out(width)
|
||||||
|
else:
|
||||||
|
for n in range(xdr):
|
||||||
|
members[f"o{n}"] = Out(width)
|
||||||
|
if dir in ("oe", "io"):
|
||||||
|
members["oe"] = Out(1)
|
||||||
|
super().__init__(members)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return (type(self) is type(other) and
|
||||||
|
self.width == other.width and
|
||||||
|
self.dir == other.dir and
|
||||||
|
self.xdr == other.xdr)
|
||||||
|
|
||||||
|
def create(self, *, path=None, src_loc_at=0):
|
||||||
|
return Pin(self.width, self.dir, xdr=self.xdr, path=path, src_loc_at=1 + src_loc_at)
|
||||||
|
|
||||||
|
def __init__(self, width, dir, *, xdr=0, name=None, path=None, src_loc_at=0):
|
||||||
|
if name is not None:
|
||||||
|
if path is None:
|
||||||
|
raise ValueError("Cannot pass both name and path")
|
||||||
|
path = (name,)
|
||||||
|
signature = Pin.Signature(width, dir, xdr=xdr)
|
||||||
|
super().__init__(signature, path=path, src_loc_at=src_loc_at + 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def signature(self):
|
def width(self):
|
||||||
return _pin_signature(self.width, self.dir, self.xdr)
|
return self.signature.width
|
||||||
|
|
||||||
def eq(self, other):
|
@property
|
||||||
first_field, _, _ = next(iter(Pin(1, dir="o").layout))
|
def dir(self):
|
||||||
warnings.warn(f"`pin.eq(...)` is deprecated; use `pin.{first_field}.eq(...)` here",
|
return self.signature.dir
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
if isinstance(self, FlippedInterface):
|
@property
|
||||||
return Record.eq(flipped(self), other)
|
def xdr(self):
|
||||||
else:
|
return self.signature.xdr
|
||||||
return Record.eq(self, other)
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
user_led = self.cm.request("user_led", 0)
|
user_led = self.cm.request("user_led", 0)
|
||||||
|
|
||||||
self.assertIsInstance(flipped(user_led), Pin)
|
self.assertIsInstance(flipped(user_led), Pin)
|
||||||
self.assertEqual(user_led.name, "user_led_0")
|
self.assertEqual(user_led.o.name, "user_led_0__o")
|
||||||
self.assertEqual(user_led.width, 1)
|
self.assertEqual(user_led.width, 1)
|
||||||
self.assertEqual(user_led.dir, "o")
|
self.assertEqual(user_led.dir, "o")
|
||||||
|
|
||||||
|
@ -77,12 +77,14 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
|
|
||||||
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"})
|
||||||
self.assertIsInstance(i2c, Record)
|
self.assertIsInstance(i2c, PureInterface)
|
||||||
self.assertIsInstance(i2c.sda, Pin)
|
self.assertTrue(i2c.signature.is_compliant(i2c))
|
||||||
|
self.assertIsInstance(flipped(i2c.sda), Pin)
|
||||||
self.assertEqual(i2c.sda.dir, "o")
|
self.assertEqual(i2c.sda.dir, "o")
|
||||||
|
|
||||||
def test_request_tristate(self):
|
def test_request_tristate(self):
|
||||||
i2c = self.cm.request("i2c", 0)
|
i2c = self.cm.request("i2c", 0)
|
||||||
|
self.assertTrue(i2c.signature.is_compliant(i2c))
|
||||||
self.assertEqual(i2c.sda.dir, "io")
|
self.assertEqual(i2c.sda.dir, "io")
|
||||||
|
|
||||||
ports = list(self.cm.iter_ports())
|
ports = list(self.cm.iter_ports())
|
||||||
|
@ -92,11 +94,11 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
self.assertEqual(ports[1].width, 1)
|
self.assertEqual(ports[1].width, 1)
|
||||||
|
|
||||||
scl_info, sda_info = self.cm.iter_single_ended_pins()
|
scl_info, sda_info = self.cm.iter_single_ended_pins()
|
||||||
self.assertIs(flipped(scl_info[0]), i2c.scl)
|
self.assertIs(scl_info[0], i2c.scl)
|
||||||
self.assertIs(scl_info[1].io, scl)
|
self.assertIs(scl_info[1].io, scl)
|
||||||
self.assertEqual(scl_info[2], {})
|
self.assertEqual(scl_info[2], {})
|
||||||
self.assertEqual(scl_info[3], False)
|
self.assertEqual(scl_info[3], False)
|
||||||
self.assertIs(flipped(sda_info[0]), i2c.sda)
|
self.assertIs(sda_info[0], i2c.sda)
|
||||||
self.assertIs(sda_info[1].io, sda)
|
self.assertIs(sda_info[1].io, sda)
|
||||||
|
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
self.assertEqual(list(self.cm.iter_port_constraints()), [
|
||||||
|
@ -315,12 +317,3 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
(r"^Cannot add clock constraint on \(sig clk100_0__i\), which is already "
|
(r"^Cannot add clock constraint on \(sig clk100_0__i\), which is already "
|
||||||
r"constrained to 100000000\.0 Hz$")):
|
r"constrained to 100000000\.0 Hz$")):
|
||||||
self.cm.add_clock_constraint(clk100.i, 1e6)
|
self.cm.add_clock_constraint(clk100.i, 1e6)
|
||||||
|
|
||||||
def test_eq_deprecation(self):
|
|
||||||
user_led = self.cm.request("user_led", 0)
|
|
||||||
m = Module()
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
m.d.sync += user_led.eq(1)
|
|
||||||
p = Pin(4, "o")
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
m.d.sync += p.eq(1)
|
|
||||||
|
|
|
@ -1,207 +1,201 @@
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from amaranth.hdl import *
|
from amaranth.hdl import *
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
||||||
from amaranth.hdl.rec import *
|
|
||||||
from amaranth.sim import *
|
from amaranth.sim import *
|
||||||
from amaranth.lib.io import *
|
from amaranth.lib.io import *
|
||||||
|
from amaranth.lib.wiring import *
|
||||||
|
|
||||||
from .utils import *
|
from .utils import *
|
||||||
|
|
||||||
|
|
||||||
class PinLayoutTestCase(FHDLTestCase):
|
class PinSignatureTestCase(FHDLTestCase):
|
||||||
def assertLayoutEqual(self, layout, expected):
|
def assertSignatureEqual(self, signature, expected):
|
||||||
casted_layout = {}
|
self.assertEqual(signature.members, Signature(expected).members)
|
||||||
for name, (shape, dir) in layout.items():
|
|
||||||
casted_layout[name] = (Shape.cast(shape), dir)
|
|
||||||
|
|
||||||
self.assertEqual(casted_layout, expected)
|
|
||||||
|
|
||||||
|
|
||||||
class PinLayoutCombTestCase(PinLayoutTestCase):
|
class PinSignatureCombTestCase(PinSignatureTestCase):
|
||||||
def test_pin_layout_i(self):
|
def test_signature_i(self):
|
||||||
layout_1 = pin_layout(1, dir="i")
|
sig_1 = Pin.Signature(1, dir="i")
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"i": (unsigned(1), DIR_NONE),
|
"i": In(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="i")
|
sig_2 = Pin.Signature(2, dir="i")
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"i": (unsigned(2), DIR_NONE),
|
"i": In(2),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_o(self):
|
def test_signature_o(self):
|
||||||
layout_1 = pin_layout(1, dir="o")
|
sig_1 = Pin.Signature(1, dir="o")
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"o": (unsigned(1), DIR_NONE),
|
"o": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="o")
|
sig_2 = Pin.Signature(2, dir="o")
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"o": (unsigned(2), DIR_NONE),
|
"o": Out(2),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_oe(self):
|
def test_signature_oe(self):
|
||||||
layout_1 = pin_layout(1, dir="oe")
|
sig_1 = Pin.Signature(1, dir="oe")
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"o": (unsigned(1), DIR_NONE),
|
"o": Out(1),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="oe")
|
sig_2 = Pin.Signature(2, dir="oe")
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"o": (unsigned(2), DIR_NONE),
|
"o": Out(2),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_io(self):
|
def test_signature_io(self):
|
||||||
layout_1 = pin_layout(1, dir="io")
|
sig_1 = Pin.Signature(1, dir="io")
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"i": (unsigned(1), DIR_NONE),
|
"i": In(1),
|
||||||
"o": (unsigned(1), DIR_NONE),
|
"o": Out(1),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="io")
|
sig_2 = Pin.Signature(2, dir="io")
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"i": (unsigned(2), DIR_NONE),
|
"i": In(2),
|
||||||
"o": (unsigned(2), DIR_NONE),
|
"o": Out(2),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class PinLayoutSDRTestCase(PinLayoutTestCase):
|
class PinSignatureSDRTestCase(PinSignatureTestCase):
|
||||||
def test_pin_layout_i(self):
|
def test_signature_i(self):
|
||||||
layout_1 = pin_layout(1, dir="i", xdr=1)
|
sig_1 = Pin.Signature(1, dir="i", xdr=1)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i": (unsigned(1), DIR_NONE),
|
"i": In(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="i", xdr=1)
|
sig_2 = Pin.Signature(2, dir="i", xdr=1)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i": (unsigned(2), DIR_NONE),
|
"i": In(2),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_o(self):
|
def test_signature_o(self):
|
||||||
layout_1 = pin_layout(1, dir="o", xdr=1)
|
sig_1 = Pin.Signature(1, dir="o", xdr=1)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o": (unsigned(1), DIR_NONE),
|
"o": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="o", xdr=1)
|
sig_2 = Pin.Signature(2, dir="o", xdr=1)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o": (unsigned(2), DIR_NONE),
|
"o": Out(2),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_oe(self):
|
def test_signature_oe(self):
|
||||||
layout_1 = pin_layout(1, dir="oe", xdr=1)
|
sig_1 = Pin.Signature(1, dir="oe", xdr=1)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o": (unsigned(1), DIR_NONE),
|
"o": Out(1),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="oe", xdr=1)
|
sig_2 = Pin.Signature(2, dir="oe", xdr=1)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o": (unsigned(2), DIR_NONE),
|
"o": Out(2),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_io(self):
|
def test_signature_io(self):
|
||||||
layout_1 = pin_layout(1, dir="io", xdr=1)
|
sig_1 = Pin.Signature(1, dir="io", xdr=1)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i": (unsigned(1), DIR_NONE),
|
"i": In(1),
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o": (unsigned(1), DIR_NONE),
|
"o": Out(1),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="io", xdr=1)
|
sig_2 = Pin.Signature(2, dir="io", xdr=1)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i": (unsigned(2), DIR_NONE),
|
"i": In(2),
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o": (unsigned(2), DIR_NONE),
|
"o": Out(2),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class PinLayoutDDRTestCase(PinLayoutTestCase):
|
class PinSignatureDDRTestCase(PinSignatureTestCase):
|
||||||
def test_pin_layout_i(self):
|
def test_signature_i(self):
|
||||||
layout_1 = pin_layout(1, dir="i", xdr=2)
|
sig_1 = Pin.Signature(1, dir="i", xdr=2)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i0": (unsigned(1), DIR_NONE),
|
"i0": In(1),
|
||||||
"i1": (unsigned(1), DIR_NONE),
|
"i1": In(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="i", xdr=2)
|
sig_2 = Pin.Signature(2, dir="i", xdr=2)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i0": (unsigned(2), DIR_NONE),
|
"i0": In(2),
|
||||||
"i1": (unsigned(2), DIR_NONE),
|
"i1": In(2),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_o(self):
|
def test_signature_o(self):
|
||||||
layout_1 = pin_layout(1, dir="o", xdr=2)
|
sig_1 = Pin.Signature(1, dir="o", xdr=2)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o0": (unsigned(1), DIR_NONE),
|
"o0": Out(1),
|
||||||
"o1": (unsigned(1), DIR_NONE),
|
"o1": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="o", xdr=2)
|
sig_2 = Pin.Signature(2, dir="o", xdr=2)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o0": (unsigned(2), DIR_NONE),
|
"o0": Out(2),
|
||||||
"o1": (unsigned(2), DIR_NONE),
|
"o1": Out(2),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_oe(self):
|
def test_signature_oe(self):
|
||||||
layout_1 = pin_layout(1, dir="oe", xdr=2)
|
sig_1 = Pin.Signature(1, dir="oe", xdr=2)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o0": (unsigned(1), DIR_NONE),
|
"o0": Out(1),
|
||||||
"o1": (unsigned(1), DIR_NONE),
|
"o1": Out(1),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="oe", xdr=2)
|
sig_2 = Pin.Signature(2, dir="oe", xdr=2)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o0": (unsigned(2), DIR_NONE),
|
"o0": Out(2),
|
||||||
"o1": (unsigned(2), DIR_NONE),
|
"o1": Out(2),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_pin_layout_io(self):
|
def test_signature_io(self):
|
||||||
layout_1 = pin_layout(1, dir="io", xdr=2)
|
sig_1 = Pin.Signature(1, dir="io", xdr=2)
|
||||||
self.assertLayoutEqual(layout_1.fields, {
|
self.assertSignatureEqual(sig_1, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i0": (unsigned(1), DIR_NONE),
|
"i0": In(1),
|
||||||
"i1": (unsigned(1), DIR_NONE),
|
"i1": In(1),
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o0": (unsigned(1), DIR_NONE),
|
"o0": Out(1),
|
||||||
"o1": (unsigned(1), DIR_NONE),
|
"o1": Out(1),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
layout_2 = pin_layout(2, dir="io", xdr=2)
|
sig_2 = Pin.Signature(2, dir="io", xdr=2)
|
||||||
self.assertLayoutEqual(layout_2.fields, {
|
self.assertSignatureEqual(sig_2, {
|
||||||
"i_clk": (unsigned(1), DIR_NONE),
|
"i_clk": Out(1),
|
||||||
"i0": (unsigned(2), DIR_NONE),
|
"i0": In(2),
|
||||||
"i1": (unsigned(2), DIR_NONE),
|
"i1": In(2),
|
||||||
"o_clk": (unsigned(1), DIR_NONE),
|
"o_clk": Out(1),
|
||||||
"o0": (unsigned(2), DIR_NONE),
|
"o0": Out(2),
|
||||||
"o1": (unsigned(2), DIR_NONE),
|
"o1": Out(2),
|
||||||
"oe": (unsigned(1), DIR_NONE),
|
"oe": Out(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,3 +205,7 @@ class PinTestCase(FHDLTestCase):
|
||||||
self.assertEqual(pin.width, 2)
|
self.assertEqual(pin.width, 2)
|
||||||
self.assertEqual(pin.dir, "io")
|
self.assertEqual(pin.dir, "io")
|
||||||
self.assertEqual(pin.xdr, 2)
|
self.assertEqual(pin.xdr, 2)
|
||||||
|
self.assertEqual(pin.signature.width, 2)
|
||||||
|
self.assertEqual(pin.signature.dir, "io")
|
||||||
|
self.assertEqual(pin.signature.xdr, 2)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue