From 9bdadbff094056e707b374ce53629eae6ae41a54 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 19 Aug 2019 21:29:53 +0000 Subject: [PATCH] back.pysim: index domains by identity, not by name. Changed in preparation for introducing local clock domains. --- nmigen/back/pysim.py | 60 +++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index 93329c4..445acf0 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -381,14 +381,14 @@ class Simulator: self._signal_slots = SignalDict() # Signal -> int/slot self._slot_signals = list() # int/slot -> Signal - self._domains = dict() # str/domain -> ClockDomain - self._domain_triggers = list() # int/slot -> str/domain + self._domains = list() # [ClockDomain] + self._domain_triggers = list() # int/slot -> ClockDomain self._signals = SignalSet() # {Signal} self._comb_signals = bitarray() # {Signal} self._sync_signals = bitarray() # {Signal} self._user_signals = bitarray() # {Signal} - self._domain_signals = dict() # str/domain -> {Signal} + self._domain_signals = dict() # ClockDomain -> {Signal} self._started = False self._timestamp = 0. @@ -463,7 +463,9 @@ class Simulator: half_period = period / 2 if phase is None: phase = half_period - clk = self._domains[domain].clk + for domain_obj in self._domains: + if not domain_obj.local and domain_obj.name == domain: + clk = domain_obj.clk def clk_process(): yield Passive() yield Delay(phase) @@ -481,17 +483,19 @@ class Simulator: comment="Generated by nMigen") root_fragment = self._fragment.prepare() - self._domains = root_fragment.domains hierarchy = {} + domains = set() def add_fragment(fragment, scope=()): hierarchy[fragment] = scope + domains.update(fragment.domains.values()) for index, (subfragment, name) in enumerate(fragment.subfragments): if name is None: add_fragment(subfragment, (*scope, "U{}".format(index))) else: add_fragment(subfragment, (*scope, name)) add_fragment(root_fragment, scope=("top",)) + self._domains = list(domains) def add_signal(signal): if signal not in self._signals: @@ -526,10 +530,10 @@ class Simulator: for signal in fragment.iter_signals(): add_signal(signal) - for domain, cd in fragment.domains.items(): - add_domain_signal(cd.clk, domain) - if cd.rst is not None: - add_domain_signal(cd.rst, domain) + for domain_name, domain in fragment.domains.items(): + add_domain_signal(domain.clk, domain) + if domain.rst is not None: + add_domain_signal(domain.rst, domain) for fragment, fragment_scope in hierarchy.items(): for signal in fragment.iter_signals(): @@ -571,31 +575,31 @@ class Simulator: except KeyError: suffix = (suffix or 0) + 1 - for domain, signals in fragment.drivers.items(): + for domain_name, signals in fragment.drivers.items(): signals_bits = bitarray(len(self._signals)) signals_bits.setall(False) for signal in signals: signals_bits[self._signal_slots[signal]] = True - if domain is None: + if domain_name is None: self._comb_signals |= signals_bits else: self._sync_signals |= signals_bits - self._domain_signals[domain] |= signals_bits + self._domain_signals[fragment.domains[domain_name]] |= signals_bits statements = [] - for domain, signals in fragment.drivers.items(): + for domain_name, signals in fragment.drivers.items(): reset_stmts = [] hold_stmts = [] for signal in signals: reset_stmts.append(signal.eq(signal.reset)) hold_stmts .append(signal.eq(signal)) - if domain is None: + if domain_name is None: statements += reset_stmts else: - if self._domains[domain].async_reset: - statements.append(Switch(self._domains[domain].rst, + if fragment.domains[domain_name].async_reset: + statements.append(Switch(fragment.domains[domain_name].rst, {0: hold_stmts, 1: reset_stmts})) else: statements += hold_stmts @@ -610,10 +614,10 @@ class Simulator: for signal in compiler.sensitivity: add_funclet(signal, funclet) - for domain, cd in fragment.domains.items(): - add_funclet(cd.clk, funclet) - if cd.rst is not None: - add_funclet(cd.rst, funclet) + for domain in fragment.domains.values(): + add_funclet(domain.clk, funclet) + if domain.rst is not None: + add_funclet(domain.rst, funclet) self._user_signals = bitarray(len(self._signals)) self._user_signals.setall(True) @@ -670,7 +674,7 @@ class Simulator: def _commit_sync_signals(self, domains): """Perform the sync part of IR processes (aka RTLIL posedge).""" - # At entry, `domains` contains a list of every simultaneously triggered sync update. + # At entry, `domains` contains a set of every simultaneously triggered sync update. while domains: # Advance the timeline a bit (purely for observational purposes) and commit all of them # at the same timestamp. @@ -681,8 +685,8 @@ class Simulator: domain = curr_domains.pop() # Wake up any simulator processes that wait for a domain tick. - for process, wait_domain in list(self._wait_tick.items()): - if domain == wait_domain: + for process, wait_domain_name in list(self._wait_tick.items()): + if domain.name == wait_domain_name: del self._wait_tick[process] self._suspended.remove(process) @@ -860,11 +864,11 @@ class Simulator: suffix = "" gtkw_save.trace(self._vcd_names[signal_slot] + suffix, **kwargs) - for domain, cd in self._domains.items(): - with gtkw_save.group("d.{}".format(domain)): - if cd.rst is not None: - add_trace(cd.rst) - add_trace(cd.clk) + for domain in self._domains: + with gtkw_save.group("d.{}".format(domain.name)): + if domain.rst is not None: + add_trace(domain.rst) + add_trace(domain.clk) for signal in self._traces: add_trace(signal) -- 2.30.2