diff --git a/amaranth/back/rtlil.py b/amaranth/back/rtlil.py index 34e4db0..f495eb2 100644 --- a/amaranth/back/rtlil.py +++ b/amaranth/back/rtlil.py @@ -988,8 +988,8 @@ class EmptyModuleChecker: return module_idx in self.empty -def convert_fragment(fragment, ports, name="top", *, emit_src=True, **kwargs): - assert isinstance(fragment, _ir.Fragment) +def convert_fragment(fragment, ports=(), name="top", *, emit_src=True, **kwargs): + assert isinstance(fragment, (_ir.Fragment, _ir.Design)) name_map = _ast.SignalDict() netlist = _ir.build_netlist(fragment, ports=ports, name=name, **kwargs) empty_checker = EmptyModuleChecker(netlist) diff --git a/amaranth/build/plat.py b/amaranth/build/plat.py index 1088201..12d2bd3 100644 --- a/amaranth/build/plat.py +++ b/amaranth/build/plat.py @@ -9,8 +9,8 @@ import jinja2 from .. import __version__ from .._toolchain import * from ..hdl import * -from ..hdl._ir import IOBufferInstance -from ..hdl._xfrm import DomainLowerer +from ..hdl._ir import IOBufferInstance, Design +from ..hdl._xfrm import DomainLowerer, AssignmentLegalizer from ..lib.cdc import ResetSynchronizer from ..back import rtlil, verilog from .res import * @@ -164,11 +164,13 @@ class Platform(ResourceManager, metaclass=ABCMeta): if pin.dir == "io": add_pin_fragment(pin, self.get_diff_input_output(pin, port, attrs, invert)) - ports = list(self.iter_ports()) - return self.toolchain_prepare(fragment, name, ports=ports, **kwargs) + ports = [(None, signal, None) for signal in self.iter_ports()] + fragment = AssignmentLegalizer()(fragment) + fragment = Design(fragment, ports, hierarchy=(name,)) + return self.toolchain_prepare(fragment, name, **kwargs) @abstractmethod - def toolchain_prepare(self, fragment, name, *, ports, **kwargs): + def toolchain_prepare(self, fragment, name, **kwargs): """ Convert the ``fragment`` and constraints recorded in this :class:`Platform` into a :class:`BuildPlan`. @@ -291,7 +293,7 @@ class TemplatedPlatform(Platform): continue yield net_signal, port_signal, frequency - def toolchain_prepare(self, fragment, name, *, ports, emit_src=True, **kwargs): + def toolchain_prepare(self, fragment, name, *, emit_src=True, **kwargs): # Restrict the name of the design to a strict alphanumeric character set. Platforms will # interpolate the name of the design in many different contexts: filesystem paths, Python # scripts, Tcl scripts, ad-hoc constraint files, and so on. It is not practical to add @@ -307,8 +309,8 @@ class TemplatedPlatform(Platform): # and to incorporate the Amaranth version into generated code. autogenerated = f"Automatically generated by Amaranth {__version__}. Do not edit." - rtlil_text, self._name_map = rtlil.convert_fragment(fragment, ports=ports, name=name, - emit_src=emit_src) + rtlil_text, self._name_map = rtlil.convert_fragment(fragment, name=name, + emit_src=emit_src, propagate_domains=False) # Retrieve an override specified in either the environment or as a kwarg. # expected_type parameter is used to assert the type of kwargs, passing `None` will disable diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py index 16c1371..733e276 100644 --- a/amaranth/hdl/_ir.py +++ b/amaranth/hdl/_ir.py @@ -386,16 +386,17 @@ class Fragment: return new_ports - def prepare(self, ports=(), *, hierarchy=("top",), legalize_assignments=False, missing_domain=lambda name: _cd.ClockDomain(name)): + def prepare(self, ports=(), *, hierarchy=("top",), legalize_assignments=False, missing_domain=lambda name: _cd.ClockDomain(name), propagate_domains=True): from ._xfrm import DomainLowerer ports = self._prepare_ports(ports) - new_domains = self._propagate_domains(missing_domain) - for domain in new_domains: - ports.append((None, domain.clk, PortDirection.Input)) - if domain.rst is not None: - ports.append((None, domain.rst, PortDirection.Input)) + if propagate_domains: + new_domains = self._propagate_domains(missing_domain) + for domain in new_domains: + ports.append((None, domain.clk, PortDirection.Input)) + if domain.rst is not None: + ports.append((None, domain.rst, PortDirection.Input)) def resolve_signal(signal): if isinstance(signal, _ast.ClockSignal): @@ -1369,8 +1370,11 @@ def _compute_ports(netlist: _nir.Netlist): top_module.ports[name] = (value, _nir.ModuleNetFlow.Output) -def build_netlist(fragment, ports, *, name="top", **kwargs): - design = fragment.prepare(ports=ports, hierarchy=(name,), legalize_assignments=True, **kwargs) +def build_netlist(fragment, ports=(), *, name="top", **kwargs): + if isinstance(fragment, Design): + design = fragment + else: + design = fragment.prepare(ports=ports, hierarchy=(name,), legalize_assignments=True, **kwargs) netlist = _nir.Netlist() _emit_netlist(netlist, design) netlist.resolve_all_nets()