fhdl.ir: move Fragment prepare logic from back.rtlil.

This commit is contained in:
whitequark 2018-12-13 14:33:39 +00:00
parent ac498414ab
commit 07c818e077
4 changed files with 32 additions and 15 deletions

View file

@ -518,17 +518,8 @@ def convert_fragment(builder, fragment, name, top):
return module.name, port_map return module.name, port_map
def convert(fragment, ports=[]): def convert(fragment, name="top", **kwargs):
fragment._propagate_domains(ensure_sync_exists=True) fragment = fragment.prepare(**kwargs)
# Clock domain reset always takes priority over all other logic. To ensure this, insert
# decision trees for clock domain reset as the very last step before synthesis.
fragment = xfrm.ResetInserter({
cd.name: cd.rst for cd in fragment.domains.values() if cd.rst is not None
})(fragment)
ins, outs = fragment._propagate_ports(ports)
builder = _Builder() builder = _Builder()
convert_fragment(builder, fragment, name="top", top=True) convert_fragment(builder, fragment, name=name, top=True)
return str(builder) return str(builder)

View file

@ -728,6 +728,9 @@ class ValueKey:
else: else:
raise TypeError raise TypeError
def __repr__(self):
return "<{}.ValueKey {!r}>".format(__name__, self.value)
class ValueDict(MutableMapping): class ValueDict(MutableMapping):
def __init__(self, pairs=()): def __init__(self, pairs=()):

View file

@ -48,6 +48,13 @@ class Fragment:
for signal in signals: for signal in signals:
yield domain, signal yield domain, signal
def iter_signals(self):
signals = ValueSet()
signals |= self.ports.keys()
for domain, domain_signals in self.drivers.items():
signals |= domain_signals
return signals
def add_domains(self, *domains): def add_domains(self, *domains):
for domain in domains: for domain in domains:
assert isinstance(domain, ClockDomain) assert isinstance(domain, ClockDomain)
@ -124,12 +131,19 @@ class Fragment:
subfrag._propagate_domains_down() subfrag._propagate_domains_down()
def _propagate_domains(self, ensure_sync_exists=False): def _propagate_domains(self, ensure_sync_exists):
self._propagate_domains_up() self._propagate_domains_up()
if ensure_sync_exists and not self.domains: if ensure_sync_exists and not self.domains:
self.add_domains(ClockDomain("sync")) self.add_domains(ClockDomain("sync"))
self._propagate_domains_down() self._propagate_domains_down()
def _insert_domain_resets(self):
from .xfrm import ResetInserter
return ResetInserter({
cd.name: cd.rst for cd in self.domains.values() if cd.rst is not None
})(self)
def _propagate_ports(self, ports): def _propagate_ports(self, ports):
# Collect all signals we're driving (on LHS of statements), and signals we're using # Collect all signals we're driving (on LHS of statements), and signals we're using
# (on RHS of statements, or in clock domains). # (on RHS of statements, or in clock domains).
@ -167,3 +181,12 @@ class Fragment:
self.add_ports(outs, kind="o") self.add_ports(outs, kind="o")
return ins, outs return ins, outs
def prepare(self, ports=(), ensure_sync_exists=True):
from .xfrm import FragmentTransformer
fragment = FragmentTransformer()(self)
fragment._propagate_domains(ensure_sync_exists)
fragment = fragment._insert_domain_resets()
fragment._propagate_ports(ports)
return fragment

View file

@ -232,11 +232,11 @@ class FragmentDomainsTestCase(FHDLTestCase):
f1.add_domains(cd) f1.add_domains(cd)
f1.add_subfragment(f2) f1.add_subfragment(f2)
f1._propagate_domains() f1._propagate_domains(ensure_sync_exists=False)
self.assertEqual(f1.domains, {"cd": cd}) self.assertEqual(f1.domains, {"cd": cd})
self.assertEqual(f2.domains, {"cd": cd}) self.assertEqual(f2.domains, {"cd": cd})
def test_propagate_default(self): def test_propagate_ensure_sync(self):
f1 = Fragment() f1 = Fragment()
f2 = Fragment() f2 = Fragment()
f1.add_subfragment(f2) f1.add_subfragment(f2)