Implement RFC 59: Get rid of upwards propagation of clock domains
This commit is contained in:
parent
09d5540430
commit
0e4c2de725
4 changed files with 62 additions and 4 deletions
|
|
@ -67,6 +67,7 @@ class Fragment:
|
|||
self.generated = OrderedDict()
|
||||
self.src_loc = src_loc
|
||||
self.origins = None
|
||||
self.domains_propagated_up = {}
|
||||
|
||||
def add_driver(self, signal, domain="comb"):
|
||||
assert isinstance(domain, str)
|
||||
|
|
@ -179,22 +180,37 @@ class Fragment:
|
|||
self.subfragments[i] = (DomainRenamer(domain_name_map)(subfrag), name, src_loc)
|
||||
|
||||
# Finally, collect the (now unique) subfragment domains, and merge them into our domains.
|
||||
for subfrag, name, src_loc in self.subfragments:
|
||||
for i, (subfrag, name, src_loc) in enumerate(self.subfragments):
|
||||
hier_name = name
|
||||
if hier_name is None:
|
||||
hier_name = f"<unnamed #{i}>"
|
||||
for domain_name, domain in subfrag.domains.items():
|
||||
if domain.local:
|
||||
continue
|
||||
self.add_domains(domain)
|
||||
if domain_name in subfrag.domains_propagated_up:
|
||||
_used_in, defined_in = subfrag.domains_propagated_up[domain_name]
|
||||
else:
|
||||
defined_in = (*hierarchy, hier_name)
|
||||
self.domains_propagated_up[domain_name] = (hierarchy, defined_in)
|
||||
|
||||
def _propagate_domains_down(self):
|
||||
def _propagate_domains_down(self, hierarchy=("top",)):
|
||||
# For each domain defined in this fragment, ensure it also exists in all subfragments.
|
||||
for subfrag, name, src_loc in self.subfragments:
|
||||
for i, (subfrag, name, src_loc) in enumerate(self.subfragments):
|
||||
hier_name = name
|
||||
if hier_name is None:
|
||||
hier_name = f"<unnamed #{i}>"
|
||||
|
||||
for domain in self.iter_domains():
|
||||
if domain in subfrag.domains:
|
||||
assert self.domains[domain] is subfrag.domains[domain]
|
||||
else:
|
||||
subfrag.add_domains(self.domains[domain])
|
||||
if domain in self.domains_propagated_up:
|
||||
_used_in, defined_in = self.domains_propagated_up[domain]
|
||||
subfrag.domains_propagated_up[domain] = (hierarchy + (hier_name,)), defined_in
|
||||
|
||||
subfrag._propagate_domains_down()
|
||||
subfrag._propagate_domains_down(hierarchy + (hier_name,))
|
||||
|
||||
def _create_missing_domains(self, missing_domain, *, platform=None):
|
||||
from ._xfrm import DomainCollector
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import warnings
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
|
|
@ -539,11 +540,26 @@ class DomainRenamer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
|||
class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer):
|
||||
def __init__(self, domains=None):
|
||||
self.domains = domains
|
||||
self.domains_propagated_up = {}
|
||||
|
||||
def _warn_on_propagation_up(self, domain, src_loc):
|
||||
if domain in self.domains_propagated_up:
|
||||
used_in, defined_in = self.domains_propagated_up[domain]
|
||||
common_prefix = []
|
||||
for u, d in zip(used_in, defined_in):
|
||||
if u == d:
|
||||
common_prefix.append(u)
|
||||
warnings.warn_explicit(f"Domain '{domain}' is used in '{'.'.join(used_in)}', but "
|
||||
f"defined in '{'.'.join(defined_in)}', which will not be "
|
||||
f"supported in Amaranth 0.6; define the domain in "
|
||||
f"'{'.'.join(common_prefix)}' or one of its parents",
|
||||
DeprecationWarning, filename=src_loc[0], lineno=src_loc[1])
|
||||
|
||||
def _resolve(self, domain, context):
|
||||
if domain not in self.domains:
|
||||
raise DomainError("Signal {!r} refers to nonexistent domain '{}'"
|
||||
.format(context, domain))
|
||||
self._warn_on_propagation_up(domain, context.src_loc)
|
||||
return self.domains[domain]
|
||||
|
||||
def map_drivers(self, fragment, new_fragment):
|
||||
|
|
@ -569,6 +585,14 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
|||
|
||||
def on_fragment(self, fragment):
|
||||
self.domains = fragment.domains
|
||||
self.domains_propagated_up = fragment.domains_propagated_up
|
||||
for domain, statements in fragment.statements.items():
|
||||
self._warn_on_propagation_up(domain, statements[0].src_loc)
|
||||
if isinstance(fragment, MemoryInstance):
|
||||
for port in fragment._read_ports:
|
||||
self._warn_on_propagation_up(port._domain, fragment.src_loc)
|
||||
for port in fragment._write_ports:
|
||||
self._warn_on_propagation_up(port._domain, fragment.src_loc)
|
||||
return super().on_fragment(fragment)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue