build.dsl: replace extras= with Attrs().
This change proved more tricky than expected due to downstream dependencies, so it also includes some secondary refactoring.
This commit is contained in:
parent
c52cd72d3e
commit
ab3f103e5a
7 changed files with 262 additions and 253 deletions
|
|
@ -1,3 +1,3 @@
|
|||
from .dsl import Pins, DiffPairs, Subsignal, Resource, Connector
|
||||
from .res import ConstraintError
|
||||
from .dsl import Pins, DiffPairs, Attrs, Subsignal, Resource, Connector
|
||||
from .res import ResourceError
|
||||
from .plat import Platform, TemplatedPlatform
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
|
||||
__all__ = ["Pins", "DiffPairs", "Subsignal", "Resource", "Connector"]
|
||||
__all__ = ["Pins", "DiffPairs", "Attrs", "Subsignal", "Resource", "Connector"]
|
||||
|
||||
|
||||
class Pins:
|
||||
|
|
@ -32,13 +32,15 @@ class Pins:
|
|||
return iter(self.names)
|
||||
|
||||
def map_names(self, mapping, resource):
|
||||
mapped_names = []
|
||||
for name in self.names:
|
||||
while ":" in name:
|
||||
if name not in mapping:
|
||||
raise NameError("Resource {!r} refers to nonexistent connector pin {}"
|
||||
.format(resource, name))
|
||||
name = mapping[name]
|
||||
yield name
|
||||
mapped_names.append(name)
|
||||
return mapped_names
|
||||
|
||||
def __repr__(self):
|
||||
return "(pins {} {})".format(self.dir, " ".join(self.names))
|
||||
|
|
@ -67,65 +69,66 @@ class DiffPairs:
|
|||
self.dir, " ".join(self.p.names), " ".join(self.n.names))
|
||||
|
||||
|
||||
class Attrs(OrderedDict):
|
||||
def __init__(self, **attrs):
|
||||
for attr_key, attr_value in attrs.items():
|
||||
if not isinstance(attr_value, str):
|
||||
raise TypeError("Attribute value must be a string, not {!r}"
|
||||
.format(attr_value))
|
||||
|
||||
super().__init__(**attrs)
|
||||
|
||||
def __repr__(self):
|
||||
return "(attrs {})".format(" ".join("{}={}".format(k, v)
|
||||
for k, v in self.items()))
|
||||
|
||||
|
||||
class Subsignal:
|
||||
def __init__(self, name, *io, extras=None):
|
||||
self.name = name
|
||||
def __init__(self, name, *args):
|
||||
self.name = name
|
||||
self.ios = []
|
||||
self.attrs = Attrs()
|
||||
|
||||
if not io:
|
||||
raise TypeError("Missing I/O constraints")
|
||||
for c in io:
|
||||
if not isinstance(c, (Pins, DiffPairs, Subsignal)):
|
||||
raise TypeError("I/O constraint must be one of Pins, DiffPairs or Subsignal, "
|
||||
"not {!r}"
|
||||
.format(c))
|
||||
if isinstance(io[0], (Pins, DiffPairs)) and len(io) > 1:
|
||||
raise TypeError("Pins and DiffPairs cannot be followed by more I/O constraints, but "
|
||||
"{!r} is followed by {!r}"
|
||||
.format(io[0], io[1]))
|
||||
if isinstance(io[0], Subsignal):
|
||||
for c in io[1:]:
|
||||
if not isinstance(c, Subsignal):
|
||||
raise TypeError("A Subsignal can only be followed by more Subsignals, but "
|
||||
"{!r} is followed by {!r}"
|
||||
.format(io[0], c))
|
||||
self.io = io
|
||||
self.extras = {}
|
||||
|
||||
if extras is not None:
|
||||
if not isinstance(extras, dict):
|
||||
raise TypeError("Extra constraints must be a dict, not {!r}"
|
||||
.format(extras))
|
||||
for extra_key, extra_value in extras.items():
|
||||
if not isinstance(extra_key, str):
|
||||
raise TypeError("Extra constraint key must be a string, not {!r}"
|
||||
.format(extra_key))
|
||||
if not isinstance(extra_value, str):
|
||||
raise TypeError("Extra constraint value must be a string, not {!r}"
|
||||
.format(extra_value))
|
||||
self.extras[extra_key] = extra_value
|
||||
|
||||
if isinstance(self.io[0], Subsignal):
|
||||
for sub in self.io:
|
||||
sub.extras.update(self.extras)
|
||||
if not args:
|
||||
raise ValueError("Missing I/O constraints")
|
||||
for arg in args:
|
||||
if isinstance(arg, (Pins, DiffPairs)):
|
||||
if not self.ios:
|
||||
self.ios.append(arg)
|
||||
else:
|
||||
raise TypeError("Pins and DiffPairs are incompatible with other location or "
|
||||
"subsignal constraints, but {!r} appears after {!r}"
|
||||
.format(arg, self.ios[-1]))
|
||||
elif isinstance(arg, Subsignal):
|
||||
if not self.ios or isinstance(self.ios[-1], Subsignal):
|
||||
self.ios.append(arg)
|
||||
else:
|
||||
raise TypeError("Subsignal is incompatible with location constraints, but "
|
||||
"{!r} appears after {!r}"
|
||||
.format(arg, self.ios[-1]))
|
||||
elif isinstance(arg, Attrs):
|
||||
self.attrs.update(arg)
|
||||
else:
|
||||
raise TypeError("I/O constraint must be one of Pins, DiffPairs, Subsignal, "
|
||||
"or Attrs, not {!r}"
|
||||
.format(arg))
|
||||
|
||||
def __repr__(self):
|
||||
return "(subsignal {} {} {})".format(self.name,
|
||||
" ".join(map(repr, self.io)),
|
||||
" ".join("{}={}".format(k, v)
|
||||
for k, v in self.extras.items()))
|
||||
" ".join(map(repr, self.ios)),
|
||||
repr(self.attrs))
|
||||
|
||||
|
||||
class Resource(Subsignal):
|
||||
def __init__(self, name, number, *io, extras=None):
|
||||
super().__init__(name, *io, extras=extras)
|
||||
def __init__(self, name, number, *args):
|
||||
super().__init__(name, *args)
|
||||
|
||||
self.number = number
|
||||
|
||||
def __repr__(self):
|
||||
return "(resource {} {} {} {})".format(self.name, self.number,
|
||||
" ".join(map(repr, self.io)),
|
||||
" ".join("{}={}".format(k, v)
|
||||
for k, v in self.extras.items()))
|
||||
" ".join(map(repr, self.ios)),
|
||||
repr(self.attrs))
|
||||
|
||||
|
||||
class Connector:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from .run import *
|
|||
__all__ = ["Platform", "TemplatedPlatform"]
|
||||
|
||||
|
||||
class Platform(ConstraintManager, metaclass=ABCMeta):
|
||||
class Platform(ResourceManager, metaclass=ABCMeta):
|
||||
resources = abstractproperty()
|
||||
connectors = abstractproperty()
|
||||
clocks = abstractproperty()
|
||||
|
|
@ -67,25 +67,25 @@ class Platform(ConstraintManager, metaclass=ABCMeta):
|
|||
pin_fragment.flatten = True
|
||||
fragment.add_subfragment(pin_fragment, name="pin_{}".format(pin.name))
|
||||
|
||||
for pin, port, extras in self.iter_single_ended_pins():
|
||||
for pin, port, attrs in self.iter_single_ended_pins():
|
||||
if pin.dir == "i":
|
||||
add_pin_fragment(pin, self.get_input(pin, port, extras))
|
||||
add_pin_fragment(pin, self.get_input(pin, port, attrs))
|
||||
if pin.dir == "o":
|
||||
add_pin_fragment(pin, self.get_output(pin, port, extras))
|
||||
add_pin_fragment(pin, self.get_output(pin, port, attrs))
|
||||
if pin.dir == "oe":
|
||||
add_pin_fragment(pin, self.get_tristate(pin, port, extras))
|
||||
add_pin_fragment(pin, self.get_tristate(pin, port, attrs))
|
||||
if pin.dir == "io":
|
||||
add_pin_fragment(pin, self.get_input_output(pin, port, extras))
|
||||
add_pin_fragment(pin, self.get_input_output(pin, port, attrs))
|
||||
|
||||
for pin, p_port, n_port, extras in self.iter_differential_pins():
|
||||
for pin, p_port, n_port, attrs in self.iter_differential_pins():
|
||||
if pin.dir == "i":
|
||||
add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, extras))
|
||||
add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, attrs))
|
||||
if pin.dir == "o":
|
||||
add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, extras))
|
||||
add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, attrs))
|
||||
if pin.dir == "oe":
|
||||
add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, extras))
|
||||
add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, attrs))
|
||||
if pin.dir == "io":
|
||||
add_pin_fragment(pin, self.get_diff_input_output(pin, p_port, n_port, extras))
|
||||
add_pin_fragment(pin, self.get_diff_input_output(pin, p_port, n_port, attrs))
|
||||
|
||||
return self.toolchain_prepare(fragment, name, **kwargs)
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ class Platform(ConstraintManager, metaclass=ABCMeta):
|
|||
raise NotImplementedError("Platform {} does not support programming"
|
||||
.format(self.__class__.__name__))
|
||||
|
||||
def _check_feature(self, feature, pin, extras, valid_xdrs, valid_extras):
|
||||
def _check_feature(self, feature, pin, attrs, valid_xdrs, valid_attrs):
|
||||
if not valid_xdrs:
|
||||
raise NotImplementedError("Platform {} does not support {}"
|
||||
.format(self.__class__.__name__, feature))
|
||||
|
|
@ -112,29 +112,29 @@ class Platform(ConstraintManager, metaclass=ABCMeta):
|
|||
raise NotImplementedError("Platform {} does not support {} for XDR {}"
|
||||
.format(self.__class__.__name__, feature, pin.xdr))
|
||||
|
||||
if not valid_extras and extras:
|
||||
raise NotImplementedError("Platform {} does not support extras for {}"
|
||||
if not valid_attrs and attrs:
|
||||
raise NotImplementedError("Platform {} does not support attributes for {}"
|
||||
.format(self.__class__.__name__, feature))
|
||||
|
||||
def get_input(self, pin, port, extras):
|
||||
self._check_feature("single-ended input", pin, extras,
|
||||
valid_xdrs=(0,), valid_extras=None)
|
||||
def get_input(self, pin, port, attrs):
|
||||
self._check_feature("single-ended input", pin, attrs,
|
||||
valid_xdrs=(0,), valid_attrs=None)
|
||||
|
||||
m = Module()
|
||||
m.d.comb += pin.i.eq(port)
|
||||
return m
|
||||
|
||||
def get_output(self, pin, port, extras):
|
||||
self._check_feature("single-ended output", pin, extras,
|
||||
valid_xdrs=(0,), valid_extras=None)
|
||||
def get_output(self, pin, port, attrs):
|
||||
self._check_feature("single-ended output", pin, attrs,
|
||||
valid_xdrs=(0,), valid_attrs=None)
|
||||
|
||||
m = Module()
|
||||
m.d.comb += port.eq(pin.o)
|
||||
return m
|
||||
|
||||
def get_tristate(self, pin, port, extras):
|
||||
self._check_feature("single-ended tristate", pin, extras,
|
||||
valid_xdrs=(0,), valid_extras=None)
|
||||
def get_tristate(self, pin, port, attrs):
|
||||
self._check_feature("single-ended tristate", pin, attrs,
|
||||
valid_xdrs=(0,), valid_attrs=None)
|
||||
|
||||
m = Module()
|
||||
m.submodules += Instance("$tribuf",
|
||||
|
|
@ -145,9 +145,9 @@ class Platform(ConstraintManager, metaclass=ABCMeta):
|
|||
)
|
||||
return m
|
||||
|
||||
def get_input_output(self, pin, port, extras):
|
||||
self._check_feature("single-ended input/output", pin, extras,
|
||||
valid_xdrs=(0,), valid_extras=None)
|
||||
def get_input_output(self, pin, port, attrs):
|
||||
self._check_feature("single-ended input/output", pin, attrs,
|
||||
valid_xdrs=(0,), valid_attrs=None)
|
||||
|
||||
m = Module()
|
||||
m.submodules += Instance("$tribuf",
|
||||
|
|
@ -159,21 +159,21 @@ class Platform(ConstraintManager, metaclass=ABCMeta):
|
|||
m.d.comb += pin.i.eq(port)
|
||||
return m
|
||||
|
||||
def get_diff_input(self, pin, p_port, n_port, extras):
|
||||
self._check_feature("differential input", pin, extras,
|
||||
valid_xdrs=(), valid_extras=None)
|
||||
def get_diff_input(self, pin, p_port, n_port, attrs):
|
||||
self._check_feature("differential input", pin, attrs,
|
||||
valid_xdrs=(), valid_attrs=None)
|
||||
|
||||
def get_diff_output(self, pin, p_port, n_port, extras):
|
||||
self._check_feature("differential output", pin, extras,
|
||||
valid_xdrs=(), valid_extras=None)
|
||||
def get_diff_output(self, pin, p_port, n_port, attrs):
|
||||
self._check_feature("differential output", pin, attrs,
|
||||
valid_xdrs=(), valid_attrs=None)
|
||||
|
||||
def get_diff_tristate(self, pin, p_port, n_port, extras):
|
||||
self._check_feature("differential tristate", pin, extras,
|
||||
valid_xdrs=(), valid_extras=None)
|
||||
def get_diff_tristate(self, pin, p_port, n_port, attrs):
|
||||
self._check_feature("differential tristate", pin, attrs,
|
||||
valid_xdrs=(), valid_attrs=None)
|
||||
|
||||
def get_diff_input_output(self, pin, p_port, n_port, extras):
|
||||
self._check_feature("differential input/output", pin, extras,
|
||||
valid_xdrs=(), valid_extras=None)
|
||||
def get_diff_input_output(self, pin, p_port, n_port, attrs):
|
||||
self._check_feature("differential input/output", pin, attrs,
|
||||
valid_xdrs=(), valid_attrs=None)
|
||||
|
||||
|
||||
class TemplatedPlatform(Platform):
|
||||
|
|
|
|||
|
|
@ -7,21 +7,24 @@ from ..lib.io import *
|
|||
from .dsl import *
|
||||
|
||||
|
||||
__all__ = ["ConstraintError", "ConstraintManager"]
|
||||
__all__ = ["ResourceError", "ResourceManager"]
|
||||
|
||||
|
||||
class ConstraintError(Exception):
|
||||
class ResourceError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ConstraintManager:
|
||||
class ResourceManager:
|
||||
def __init__(self, resources, connectors, clocks):
|
||||
self.resources = OrderedDict()
|
||||
self._requested = OrderedDict()
|
||||
|
||||
self.connectors = OrderedDict()
|
||||
self._conn_pins = OrderedDict()
|
||||
|
||||
self.clocks = OrderedDict()
|
||||
|
||||
self._mapping = OrderedDict()
|
||||
self._requested = OrderedDict()
|
||||
# Constraint lists
|
||||
self._ports = []
|
||||
|
||||
self.add_resources(resources)
|
||||
|
|
@ -50,36 +53,36 @@ class ConstraintManager:
|
|||
self.connectors[conn.name, conn.number] = conn
|
||||
|
||||
for conn_pin, plat_pin in conn:
|
||||
assert conn_pin not in self._mapping
|
||||
self._mapping[conn_pin] = plat_pin
|
||||
assert conn_pin not in self._conn_pins
|
||||
self._conn_pins[conn_pin] = plat_pin
|
||||
|
||||
def add_clock(self, name, number, frequency):
|
||||
resource = self.lookup(name, number)
|
||||
if isinstance(resource.io[0], Subsignal):
|
||||
if isinstance(resource.ios[0], Subsignal):
|
||||
raise TypeError("Cannot constrain frequency of resource {}#{} because it has "
|
||||
"subsignals"
|
||||
.format(resource.name, resource.number, frequency))
|
||||
if (resource.name, resource.number) in self.clocks:
|
||||
other = self.clocks[resource.name, resource.number]
|
||||
raise ConstraintError("Resource {}#{} is already constrained to a frequency of "
|
||||
"{:f} MHz"
|
||||
.format(resource.name, resource.number, other / 1e6))
|
||||
raise ResourceError("Resource {}#{} is already constrained to a frequency of "
|
||||
"{:f} MHz"
|
||||
.format(resource.name, resource.number, other / 1e6))
|
||||
self.clocks[resource.name, resource.number] = frequency
|
||||
|
||||
def lookup(self, name, number=0):
|
||||
if (name, number) not in self.resources:
|
||||
raise ConstraintError("Resource {}#{} does not exist"
|
||||
raise ResourceError("Resource {}#{} does not exist"
|
||||
.format(name, number))
|
||||
return self.resources[name, number]
|
||||
|
||||
def request(self, name, number=0, *, dir=None, xdr=None):
|
||||
resource = self.lookup(name, number)
|
||||
if (resource.name, resource.number) in self._requested:
|
||||
raise ConstraintError("Resource {}#{} has already been requested"
|
||||
.format(name, number))
|
||||
raise ResourceError("Resource {}#{} has already been requested"
|
||||
.format(name, number))
|
||||
|
||||
def merge_options(subsignal, dir, xdr):
|
||||
if isinstance(subsignal.io[0], Subsignal):
|
||||
if isinstance(subsignal.ios[0], Subsignal):
|
||||
if dir is None:
|
||||
dir = dict()
|
||||
if xdr is None:
|
||||
|
|
@ -92,52 +95,54 @@ class ConstraintManager:
|
|||
raise TypeError("Data rate must be a dict, not {!r}, because {!r} "
|
||||
"has subsignals"
|
||||
.format(xdr, subsignal))
|
||||
for sub in subsignal.io:
|
||||
for sub in subsignal.ios:
|
||||
sub_dir = dir.get(sub.name, None)
|
||||
sub_xdr = xdr.get(sub.name, None)
|
||||
dir[sub.name], xdr[sub.name] = merge_options(sub, sub_dir, sub_xdr)
|
||||
else:
|
||||
if dir is None:
|
||||
dir = subsignal.io[0].dir
|
||||
dir = subsignal.ios[0].dir
|
||||
if xdr is None:
|
||||
xdr = 0
|
||||
if dir not in ("i", "o", "oe", "io", "-"):
|
||||
raise TypeError("Direction must be one of \"i\", \"o\", \"oe\", \"io\", "
|
||||
"or \"-\", not {!r}"
|
||||
.format(dir))
|
||||
if dir != subsignal.io[0].dir and not (subsignal.io[0].dir == "io" or dir == "-"):
|
||||
if dir != subsignal.ios[0].dir and \
|
||||
not (subsignal.ios[0].dir == "io" or dir == "-"):
|
||||
raise ValueError("Direction of {!r} cannot be changed from \"{}\" to \"{}\"; "
|
||||
"direction can be changed from \"io\" to \"i\", \"o\", or "
|
||||
"\"oe\", or from anything to \"-\""
|
||||
.format(subsignal.io[0], subsignal.io[0].dir, dir))
|
||||
.format(subsignal.ios[0], subsignal.ios[0].dir, dir))
|
||||
if not isinstance(xdr, int) or xdr < 0:
|
||||
raise ValueError("Data rate of {!r} must be a non-negative integer, not {!r}"
|
||||
.format(subsignal.io[0], xdr))
|
||||
.format(subsignal.ios[0], xdr))
|
||||
return dir, xdr
|
||||
|
||||
def resolve(subsignal, dir, xdr, name):
|
||||
if isinstance(subsignal.io[0], Subsignal):
|
||||
def resolve(resource, dir, xdr, name, attrs):
|
||||
if isinstance(resource.ios[0], Subsignal):
|
||||
fields = OrderedDict()
|
||||
for sub in subsignal.io:
|
||||
for sub in resource.ios:
|
||||
fields[sub.name] = resolve(sub, dir[sub.name], xdr[sub.name],
|
||||
name="{}__{}".format(name, sub.name))
|
||||
name="{}__{}".format(name, sub.name),
|
||||
attrs={**attrs, **sub.attrs})
|
||||
return Record([
|
||||
(f_name, f.layout) for (f_name, f) in fields.items()
|
||||
], fields=fields, name=name)
|
||||
|
||||
elif isinstance(subsignal.io[0], (Pins, DiffPairs)):
|
||||
phys = subsignal.io[0]
|
||||
elif isinstance(resource.ios[0], (Pins, DiffPairs)):
|
||||
phys = resource.ios[0]
|
||||
if isinstance(phys, Pins):
|
||||
port = Record([("io", len(phys))], name=name)
|
||||
if isinstance(phys, DiffPairs):
|
||||
port = Record([("p", len(phys)),
|
||||
("n", len(phys))], name=name)
|
||||
if dir == "-":
|
||||
self._ports.append((subsignal, None, port))
|
||||
self._ports.append((resource, None, port, attrs))
|
||||
return port
|
||||
else:
|
||||
pin = Pin(len(phys), dir, xdr, name=name)
|
||||
self._ports.append((subsignal, pin, port))
|
||||
self._ports.append((resource, pin, port, attrs))
|
||||
return pin
|
||||
|
||||
else:
|
||||
|
|
@ -145,51 +150,61 @@ class ConstraintManager:
|
|||
|
||||
value = resolve(resource,
|
||||
*merge_options(resource, dir, xdr),
|
||||
name="{}_{}".format(resource.name, resource.number))
|
||||
name="{}_{}".format(resource.name, resource.number),
|
||||
attrs=resource.attrs)
|
||||
self._requested[resource.name, resource.number] = value
|
||||
return value
|
||||
|
||||
def iter_single_ended_pins(self):
|
||||
for res, pin, port in self._ports:
|
||||
for res, pin, port, attrs in self._ports:
|
||||
if pin is None:
|
||||
continue
|
||||
if isinstance(res.io[0], Pins):
|
||||
yield pin, port.io, res.extras
|
||||
if isinstance(res.ios[0], Pins):
|
||||
yield pin, port.io, attrs
|
||||
|
||||
def iter_differential_pins(self):
|
||||
for res, pin, port in self._ports:
|
||||
for res, pin, port, attrs in self._ports:
|
||||
if pin is None:
|
||||
continue
|
||||
if isinstance(res.io[0], DiffPairs):
|
||||
yield pin, port.p, port.n, res.extras
|
||||
if isinstance(res.ios[0], DiffPairs):
|
||||
yield pin, port.p, port.n, attrs
|
||||
|
||||
def should_skip_port_component(self, port, attrs, component):
|
||||
return False
|
||||
|
||||
def iter_ports(self):
|
||||
for res, pin, port in self._ports:
|
||||
if isinstance(res.io[0], Pins):
|
||||
yield port.io
|
||||
elif isinstance(res.io[0], DiffPairs):
|
||||
yield port.p
|
||||
yield port.n
|
||||
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
|
||||
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 in self._ports:
|
||||
if isinstance(res.io[0], Pins):
|
||||
yield port.io.name, list(res.io[0].map_names(self._mapping, res)), res.extras
|
||||
elif isinstance(res.io[0], DiffPairs):
|
||||
yield port.p.name, list(res.io[0].p.map_names(self._mapping, res)), res.extras
|
||||
yield port.n.name, list(res.io[0].n.map_names(self._mapping, res)), res.extras
|
||||
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):
|
||||
for port_name, pin_names, extras in self.iter_port_constraints():
|
||||
for port_name, pin_names, attrs in self.iter_port_constraints():
|
||||
if len(pin_names) == 1:
|
||||
yield port_name, pin_names[0], extras
|
||||
yield port_name, pin_names[0], attrs
|
||||
else:
|
||||
for bit, pin_name in enumerate(pin_names):
|
||||
yield "{}[{}]".format(port_name, bit), pin_name, extras
|
||||
yield "{}[{}]".format(port_name, bit), pin_name, attrs
|
||||
|
||||
def iter_clock_constraints(self):
|
||||
for name, number in self.clocks.keys() & self._requested.keys():
|
||||
|
|
@ -197,12 +212,12 @@ class ConstraintManager:
|
|||
period = self.clocks[name, number]
|
||||
pin = self._requested[name, number]
|
||||
if pin.dir == "io":
|
||||
raise ConstraintError("Cannot constrain frequency of resource {}#{} because "
|
||||
"it has been requested as a tristate buffer"
|
||||
.format(name, number))
|
||||
if isinstance(resource.io[0], Pins):
|
||||
raise ResourceError("Cannot constrain frequency of resource {}#{} because "
|
||||
"it has been requested as a tristate buffer"
|
||||
.format(name, number))
|
||||
if isinstance(resource.ios[0], Pins):
|
||||
port_name = "{}__io".format(pin.name)
|
||||
elif isinstance(resource.io[0], DiffPairs):
|
||||
elif isinstance(resource.ios[0], DiffPairs):
|
||||
port_name = "{}__p".format(pin.name)
|
||||
else:
|
||||
assert False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue