diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py index f46f6f8..44a21d2 100644 --- a/amaranth/hdl/_ir.py +++ b/amaranth/hdl/_ir.py @@ -1195,6 +1195,22 @@ class NetlistEmitter: def emit_drivers(self): for driver in self.drivers.values(): + if (driver.domain is not None and + driver.domain.rst is not None and + not driver.domain.async_reset and + not driver.signal.reset_less): + cell = _nir.Matches(driver.module_idx, + value=self.emit_signal(driver.domain.rst), + patterns=("1",), + src_loc=driver.domain.rst.src_loc) + cond, = self.netlist.add_value_cell(1, cell) + cell = _nir.PriorityMatch(driver.module_idx, en=_nir.Net.from_const(1), + inputs=_nir.Value(cond), + src_loc=driver.domain.rst.src_loc) + cond, = self.netlist.add_value_cell(1, cell) + init = _nir.Value.from_const(driver.signal.init, driver.signal.width) + driver.assignments.append(_nir.Assignment(cond=cond, start=0, + value=init, src_loc=driver.signal.src_loc)) value = driver.emit_value(self) if driver.domain is not None: clk, = self.emit_signal(driver.domain.clk) diff --git a/amaranth/hdl/_xfrm.py b/amaranth/hdl/_xfrm.py index 7f61b9d..02ee2cd 100644 --- a/amaranth/hdl/_xfrm.py +++ b/amaranth/hdl/_xfrm.py @@ -526,22 +526,9 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer) .format(value, value.domain)) return domain.rst - def _insert_resets(self, fragment): - for domain_name, signals in fragment.drivers.items(): - if domain_name == "comb": - continue - domain = fragment.domains[domain_name] - if domain.rst is None: - continue - stmts = [signal.eq(Const(signal.init, signal.width)) - for signal in signals if not signal.reset_less] - fragment.add_statements(domain_name, Switch(domain.rst, {1: stmts})) - def on_fragment(self, fragment): self.domains = fragment.domains - new_fragment = super().on_fragment(fragment) - self._insert_resets(new_fragment) - return new_fragment + return super().on_fragment(fragment) class _ControlInserter(FragmentTransformer): diff --git a/amaranth/sim/_pyrtl.py b/amaranth/sim/_pyrtl.py index 1966613..93ac452 100644 --- a/amaranth/sim/_pyrtl.py +++ b/amaranth/sim/_pyrtl.py @@ -473,6 +473,18 @@ class _FragmentCompiler: _StatementCompiler(self.state, emitter)(domain_stmts) + if domain.rst is not None: + rhs = _RHSValueCompiler(self.state, emitter, mode="curr") + rst = rhs(domain.rst) + rst = f"(1 & {rst})" + emitter.append(f"if {rst}:") + with emitter.indent(): + emitter.append("pass") + for signal in domain_signals: + if not signal.reset_less: + signal_index = self.state.get_signal(signal) + emitter.append(f"next_{signal_index} = {signal.init}") + if isinstance(fragment, MemoryInstance): memory_index = self.state.memories[fragment._identity] rhs = _RHSValueCompiler(self.state, emitter, mode="curr") diff --git a/tests/test_hdl_ir.py b/tests/test_hdl_ir.py index 1086bb2..8e9eafe 100644 --- a/tests/test_hdl_ir.py +++ b/tests/test_hdl_ir.py @@ -3093,9 +3093,8 @@ class SwitchTestCase(FHDLTestCase): ClockSignal("b"), ResetSignal("b"), ClockSignal("c"), ]) - # TODO: two inefficiencies in NIR emitter: - # - _ignore_resets inserts useless redundant Switch for async reset - # - matches and priority_match duplicated between clock domains — add cache? + # TODO: inefficiency in NIR emitter: + # matches and priority_match duplicated between clock domains — add cache? self.assertRepr(nl, """ ( (module 0 None ('top') @@ -3106,11 +3105,11 @@ class SwitchTestCase(FHDLTestCase): (input 'b_clk' 0.13) (input 'b_rst' 0.14) (input 'c_clk' 0.15) - (output 'o1' 12.0:8) - (output 'o2' 14.0:8) - (output 'o3' 16.0:8) - (output 'o4' 18.0:8) - (output 'o5' 20.0:8) + (output 'o1' 8.0:8) + (output 'o2' 12.0:8) + (output 'o3' 14.0:8) + (output 'o4' 16.0:8) + (output 'o5' 18.0:8) ) (cell 0 0 (top (input 'i1' 2:10) @@ -3120,32 +3119,30 @@ class SwitchTestCase(FHDLTestCase): (input 'b_clk' 13:14) (input 'b_rst' 14:15) (input 'c_clk' 15:16) - (output 'o1' 12.0:8) - (output 'o2' 14.0:8) - (output 'o3' 16.0:8) - (output 'o4' 18.0:8) - (output 'o5' 20.0:8) + (output 'o1' 8.0:8) + (output 'o2' 12.0:8) + (output 'o3' 14.0:8) + (output 'o4' 16.0:8) + (output 'o5' 18.0:8) )) (cell 1 0 (matches 0.10 1)) (cell 2 0 (priority_match 1 1.0)) - (cell 3 0 (matches 0.12 1)) + (cell 3 0 (matches 0.10 1)) (cell 4 0 (priority_match 1 3.0)) (cell 5 0 (matches 0.10 1)) (cell 6 0 (priority_match 1 5.0)) - (cell 7 0 (matches 0.14 1)) - (cell 8 0 (priority_match 1 7.0)) - (cell 9 0 (matches 0.10 1)) + (cell 7 0 (assignment_list 8.0:8 (2.0 0:8 0.2:10))) + (cell 8 0 (flipflop 7.0:8 0 pos 0.11 0)) + (cell 9 0 (matches 0.12 1)) (cell 10 0 (priority_match 1 9.0)) - (cell 11 0 (assignment_list 12.0:8 (2.0 0:8 0.2:10))) - (cell 12 0 (flipflop 11.0:8 0 pos 0.11 0)) - (cell 13 0 (assignment_list 14.0:8 (2.0 0:8 0.2:10) (4.0 0:8 8'd123))) - (cell 14 0 (flipflop 13.0:8 123 pos 0.11 0)) - (cell 15 0 (assignment_list 16.0:8 (6.0 0:8 0.2:10))) - (cell 16 0 (flipflop 15.0:8 45 pos 0.13 0)) - (cell 17 0 (assignment_list 18.0:8 (6.0 0:8 0.2:10) (8.0 0:8 8'd67))) - (cell 18 0 (flipflop 17.0:8 67 pos 0.13 0.14)) - (cell 19 0 (assignment_list 20.0:8 (10.0 0:8 0.2:10))) - (cell 20 0 (flipflop 19.0:8 89 neg 0.15 0)) + (cell 11 0 (assignment_list 12.0:8 (2.0 0:8 0.2:10) (10.0 0:8 8'd123))) + (cell 12 0 (flipflop 11.0:8 123 pos 0.11 0)) + (cell 13 0 (assignment_list 14.0:8 (4.0 0:8 0.2:10))) + (cell 14 0 (flipflop 13.0:8 45 pos 0.13 0)) + (cell 15 0 (assignment_list 16.0:8 (4.0 0:8 0.2:10))) + (cell 16 0 (flipflop 15.0:8 67 pos 0.13 0.14)) + (cell 17 0 (assignment_list 18.0:8 (6.0 0:8 0.2:10))) + (cell 18 0 (flipflop 17.0:8 89 neg 0.15 0)) ) """)