hdl.ir: allow adding more than one domain in missing domain callback.
This is useful for injecting complex power-on reset logic.
This commit is contained in:
parent
9c28b61d9f
commit
e0b54b417e
|
@ -363,23 +363,21 @@ class Fragment:
|
||||||
if value is None:
|
if value is None:
|
||||||
raise DomainError("Domain '{}' is used but not defined".format(domain_name))
|
raise DomainError("Domain '{}' is used but not defined".format(domain_name))
|
||||||
if type(value) is ClockDomain:
|
if type(value) is ClockDomain:
|
||||||
domain = value
|
self.add_domains(value)
|
||||||
# Only expose ports on clock domains returned directly, i.e. not as a part of
|
# And expose ports on the newly added clock domain, since it is added directly
|
||||||
# a fragment driving that domain.
|
# and there was no chance to add any logic driving it.
|
||||||
new_domains.append(domain)
|
new_domains.append(value)
|
||||||
else:
|
else:
|
||||||
new_fragment = Fragment.get(value, platform=None)
|
new_fragment = Fragment.get(value, platform=None)
|
||||||
if new_fragment.domains.keys() != {domain_name}:
|
if domain_name not in new_fragment.domains:
|
||||||
|
defined = new_fragment.domains.keys()
|
||||||
raise DomainError(
|
raise DomainError(
|
||||||
"Fragment returned by missing domain callback should define exactly "
|
"Fragment returned by missing domain callback does not define "
|
||||||
"one domain '{}', but defines domain(s) {}."
|
"requested domain '{}' (defines {})."
|
||||||
.format(domain_name,
|
.format(domain_name, ", ".join("'{}'".format(n) for n in defined)))
|
||||||
", ".join("'{}'".format(n)
|
|
||||||
for n in new_fragment.domains.keys())))
|
|
||||||
new_fragment.flatten = True
|
new_fragment.flatten = True
|
||||||
self.add_subfragment(new_fragment)
|
self.add_subfragment(new_fragment)
|
||||||
domain = new_fragment.domains[domain_name]
|
self.add_domains(new_fragment.domains.values())
|
||||||
self.add_domains(domain)
|
|
||||||
return new_domains
|
return new_domains
|
||||||
|
|
||||||
def _propagate_domains(self, missing_domain):
|
def _propagate_domains(self, missing_domain):
|
||||||
|
|
|
@ -421,6 +421,25 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
])
|
])
|
||||||
self.assertTrue(f2.flatten)
|
self.assertTrue(f2.flatten)
|
||||||
|
|
||||||
|
def test_propagate_create_missing_fragment_many_domains(self):
|
||||||
|
s1 = Signal()
|
||||||
|
f1 = Fragment()
|
||||||
|
f1.add_driver(s1, "sync")
|
||||||
|
|
||||||
|
cd_por = ClockDomain("por")
|
||||||
|
cd_sync = ClockDomain("sync")
|
||||||
|
f2 = Fragment()
|
||||||
|
f2.add_domains(cd_por, cd_sync)
|
||||||
|
|
||||||
|
new_domains = f1._propagate_domains(missing_domain=lambda name: f2)
|
||||||
|
self.assertEqual(f1.domains.keys(), {"sync", "por"})
|
||||||
|
self.assertEqual(f2.domains.keys(), {"sync", "por"})
|
||||||
|
self.assertEqual(f1.domains["sync"], f2.domains["sync"])
|
||||||
|
self.assertEqual(new_domains, [])
|
||||||
|
self.assertEqual(f1.subfragments, [
|
||||||
|
(f2, None)
|
||||||
|
])
|
||||||
|
|
||||||
def test_propagate_create_missing_fragment_wrong(self):
|
def test_propagate_create_missing_fragment_wrong(self):
|
||||||
s1 = Signal()
|
s1 = Signal()
|
||||||
f1 = Fragment()
|
f1 = Fragment()
|
||||||
|
@ -430,8 +449,8 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
f2.add_domains(ClockDomain("foo"))
|
f2.add_domains(ClockDomain("foo"))
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaises(DomainError,
|
||||||
msg="Fragment returned by missing domain callback should define exactly "
|
msg="Fragment returned by missing domain callback does not define requested "
|
||||||
"one domain 'sync', but defines domain(s) 'foo'."):
|
"domain 'sync' (defines 'foo')."):
|
||||||
f1._propagate_domains(missing_domain=lambda name: f2)
|
f1._propagate_domains(missing_domain=lambda name: f2)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue