build.{dsl,res}: allow removing attributes from subsignals.
This is useful when most attributes in a large composite resource are the same, but a few signals are different, and also when building abstractions around resources. Fixes #128.
This commit is contained in:
parent
f0c1c2cfeb
commit
0b844da4cf
|
@ -92,15 +92,20 @@ def DiffPairsN(*args, **kwargs):
|
|||
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}"
|
||||
if not (attr_value is None or isinstance(attr_value, str)):
|
||||
raise TypeError("Attribute value must be None or str, not {!r}"
|
||||
.format(attr_value))
|
||||
|
||||
super().__init__(**attrs)
|
||||
|
||||
def __repr__(self):
|
||||
return "(attrs {})".format(" ".join("{}={}".format(k, v)
|
||||
for k, v in self.items()))
|
||||
items = []
|
||||
for key, value in self.items():
|
||||
if value is None:
|
||||
items.append("!" + key)
|
||||
else:
|
||||
items.append(key + "=" + value)
|
||||
return "(attrs {})".format(" ".join(items))
|
||||
|
||||
|
||||
class Clock:
|
||||
|
|
|
@ -106,9 +106,10 @@ class ResourceManager:
|
|||
if isinstance(resource.ios[0], Subsignal):
|
||||
fields = OrderedDict()
|
||||
for sub in resource.ios:
|
||||
sub_attrs = {k: v for k, v in {**attrs, **sub.attrs}.items() if v is not None}
|
||||
fields[sub.name] = resolve(sub, dir[sub.name], xdr[sub.name],
|
||||
name="{}__{}".format(name, sub.name),
|
||||
attrs={**attrs, **sub.attrs})
|
||||
attrs=sub_attrs)
|
||||
return Record([
|
||||
(f_name, f.layout) for (f_name, f) in fields.items()
|
||||
], fields=fields, name=name)
|
||||
|
|
|
@ -113,9 +113,14 @@ class AttrsTestCase(FHDLTestCase):
|
|||
self.assertEqual(a["IO_STANDARD"], "LVCMOS33")
|
||||
self.assertEqual(repr(a), "(attrs IO_STANDARD=LVCMOS33 PULLUP=1)")
|
||||
|
||||
def test_remove(self):
|
||||
a = Attrs(FOO=None)
|
||||
self.assertEqual(a["FOO"], None)
|
||||
self.assertEqual(repr(a), "(attrs !FOO)")
|
||||
|
||||
def test_wrong_value(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Attribute value must be a string, not 1"):
|
||||
msg="Attribute value must be None or str, not 1"):
|
||||
a = Attrs(FOO=1)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue