back.pysim: index domains by identity, not by name.

Changed in preparation for introducing local clock domains.
This commit is contained in:
whitequark 2019-08-19 21:29:53 +00:00
parent 69d36dc139
commit 9bdadbff09

View file

@ -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)