parent
9bdadbff09
commit
003ba3b45f
|
@ -25,6 +25,9 @@ class ClockDomain:
|
|||
If ``True``, the domain uses an asynchronous reset, and registers within this domain
|
||||
are initialized to their reset state when reset level changes. Otherwise, registers
|
||||
are initialized to reset state at the next clock cycle when reset is asserted.
|
||||
local : bool
|
||||
If ``True``, the domain will propagate only downwards in the design hierarchy. Otherwise,
|
||||
the domain will propagate everywhere.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
@ -42,7 +45,7 @@ class ClockDomain:
|
|||
else:
|
||||
return "{}_{}".format(domain_name, signal_name)
|
||||
|
||||
def __init__(self, name=None, reset_less=False, async_reset=False):
|
||||
def __init__(self, name=None, reset_less=False, async_reset=False, local=False):
|
||||
if name is None:
|
||||
try:
|
||||
name = tracer.get_var_name()
|
||||
|
@ -62,6 +65,8 @@ class ClockDomain:
|
|||
|
||||
self.async_reset = async_reset
|
||||
|
||||
self.local = local
|
||||
|
||||
def rename(self, new_name):
|
||||
self.name = new_name
|
||||
self.clk.name = self._name_for(new_name, "clk")
|
||||
|
|
|
@ -305,12 +305,14 @@ class Fragment:
|
|||
subfrag._propagate_domains_up(hierarchy + (hier_name,))
|
||||
|
||||
# Second, classify subfragments by domains they define.
|
||||
for domain in subfrag.iter_domains():
|
||||
domain_subfrags[domain].add((subfrag, name, i))
|
||||
for domain_name, domain in subfrag.domains.items():
|
||||
if domain.local:
|
||||
continue
|
||||
domain_subfrags[domain_name].add((subfrag, name, i))
|
||||
|
||||
# For each domain defined by more than one subfragment, rename the domain in each
|
||||
# of the subfragments such that they no longer conflict.
|
||||
for domain, subfrags in domain_subfrags.items():
|
||||
for domain_name, subfrags in domain_subfrags.items():
|
||||
if len(subfrags) == 1:
|
||||
continue
|
||||
|
||||
|
@ -321,7 +323,7 @@ class Fragment:
|
|||
raise DomainError("Domain '{}' is defined by subfragments {} of fragment '{}'; "
|
||||
"it is necessary to either rename subfragment domains "
|
||||
"explicitly, or give names to subfragments"
|
||||
.format(domain, ", ".join(names), ".".join(hierarchy)))
|
||||
.format(domain_name, ", ".join(names), ".".join(hierarchy)))
|
||||
|
||||
if len(names) != len(set(names)):
|
||||
names = sorted("#{}".format(i) for f, n, i in subfrags)
|
||||
|
@ -329,16 +331,18 @@ class Fragment:
|
|||
"some of which have identical names; it is necessary to either "
|
||||
"rename subfragment domains explicitly, or give distinct names "
|
||||
"to subfragments"
|
||||
.format(domain, ", ".join(names), ".".join(hierarchy)))
|
||||
.format(domain_name, ", ".join(names), ".".join(hierarchy)))
|
||||
|
||||
for subfrag, name, i in subfrags:
|
||||
self.subfragments[i] = \
|
||||
(DomainRenamer({domain: "{}_{}".format(name, domain)})(subfrag), name)
|
||||
domain_name_map = {domain_name: "{}_{}".format(name, domain_name)}
|
||||
self.subfragments[i] = (DomainRenamer(domain_name_map)(subfrag), name)
|
||||
|
||||
# Finally, collect the (now unique) subfragment domains, and merge them into our domains.
|
||||
for subfrag, name in self.subfragments:
|
||||
for domain in subfrag.iter_domains():
|
||||
self.add_domains(subfrag.domains[domain])
|
||||
for domain_name, domain in subfrag.domains.items():
|
||||
if domain.local:
|
||||
continue
|
||||
self.add_domains(domain)
|
||||
|
||||
def _propagate_domains_down(self):
|
||||
# For each domain defined in this fragment, ensure it also exists in all subfragments.
|
||||
|
|
|
@ -8,6 +8,7 @@ class ClockDomainTestCase(FHDLTestCase):
|
|||
self.assertEqual(sync.name, "sync")
|
||||
self.assertEqual(sync.clk.name, "clk")
|
||||
self.assertEqual(sync.rst.name, "rst")
|
||||
self.assertEqual(sync.local, False)
|
||||
pix = ClockDomain()
|
||||
self.assertEqual(pix.name, "pix")
|
||||
self.assertEqual(pix.clk.name, "pix_clk")
|
||||
|
@ -19,6 +20,8 @@ class ClockDomainTestCase(FHDLTestCase):
|
|||
with self.assertRaises(ValueError,
|
||||
msg="Clock domain name must be specified explicitly"):
|
||||
ClockDomain()
|
||||
cd_reset = ClockDomain(local=True)
|
||||
self.assertEqual(cd_reset.local, True)
|
||||
|
||||
def test_with_reset(self):
|
||||
pix = ClockDomain()
|
||||
|
|
|
@ -290,6 +290,17 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
|||
f1._propagate_domains_up()
|
||||
self.assertEqual(f1.domains, {"cd": cd})
|
||||
|
||||
def test_propagate_up_local(self):
|
||||
cd = ClockDomain(local=True)
|
||||
|
||||
f1 = Fragment()
|
||||
f2 = Fragment()
|
||||
f1.add_subfragment(f2)
|
||||
f2.add_domains(cd)
|
||||
|
||||
f1._propagate_domains_up()
|
||||
self.assertEqual(f1.domains, {})
|
||||
|
||||
def test_domain_conflict(self):
|
||||
cda = ClockDomain("sync")
|
||||
cdb = ClockDomain("sync")
|
||||
|
|
Loading…
Reference in a new issue