From de771820f95735c98af62ac517fc2916f3027dc3 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 13 Dec 2018 14:33:39 +0000 Subject: [PATCH] fhdl.ir: move Fragment prepare logic from back.rtlil. --- nmigen/back/rtlil.py | 15 +++------------ nmigen/fhdl/ast.py | 3 +++ nmigen/fhdl/ir.py | 25 ++++++++++++++++++++++++- nmigen/test/test_fhdl_ir.py | 4 ++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index d1c7c7a..a8dd7d3 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -518,17 +518,8 @@ def convert_fragment(builder, fragment, name, top): return module.name, port_map -def convert(fragment, ports=[]): - fragment._propagate_domains(ensure_sync_exists=True) - - # 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) - +def convert(fragment, name="top", **kwargs): + fragment = fragment.prepare(**kwargs) builder = _Builder() - convert_fragment(builder, fragment, name="top", top=True) + convert_fragment(builder, fragment, name=name, top=True) return str(builder) diff --git a/nmigen/fhdl/ast.py b/nmigen/fhdl/ast.py index c74a69b..15f67e3 100644 --- a/nmigen/fhdl/ast.py +++ b/nmigen/fhdl/ast.py @@ -728,6 +728,9 @@ class ValueKey: else: raise TypeError + def __repr__(self): + return "<{}.ValueKey {!r}>".format(__name__, self.value) + class ValueDict(MutableMapping): def __init__(self, pairs=()): diff --git a/nmigen/fhdl/ir.py b/nmigen/fhdl/ir.py index 383ef74..8f4efee 100644 --- a/nmigen/fhdl/ir.py +++ b/nmigen/fhdl/ir.py @@ -48,6 +48,13 @@ class Fragment: for signal in signals: 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): for domain in domains: assert isinstance(domain, ClockDomain) @@ -124,12 +131,19 @@ class Fragment: subfrag._propagate_domains_down() - def _propagate_domains(self, ensure_sync_exists=False): + def _propagate_domains(self, ensure_sync_exists): self._propagate_domains_up() if ensure_sync_exists and not self.domains: self.add_domains(ClockDomain("sync")) 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): # Collect all signals we're driving (on LHS of statements), and signals we're using # (on RHS of statements, or in clock domains). @@ -167,3 +181,12 @@ class Fragment: self.add_ports(outs, kind="o") 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 diff --git a/nmigen/test/test_fhdl_ir.py b/nmigen/test/test_fhdl_ir.py index decfa3c..ddd1821 100644 --- a/nmigen/test/test_fhdl_ir.py +++ b/nmigen/test/test_fhdl_ir.py @@ -232,11 +232,11 @@ class FragmentDomainsTestCase(FHDLTestCase): f1.add_domains(cd) f1.add_subfragment(f2) - f1._propagate_domains() + f1._propagate_domains(ensure_sync_exists=False) self.assertEqual(f1.domains, {"cd": cd}) self.assertEqual(f2.domains, {"cd": cd}) - def test_propagate_default(self): + def test_propagate_ensure_sync(self): f1 = Fragment() f2 = Fragment() f1.add_subfragment(f2) -- 2.30.2