# print(rtlil.convert(frag, ports=[ctr.o, ctr.ce]))
print(verilog.convert(frag, ports=[ctr.o, ctr.ce]))
-sim = pysim.Simulator(frag,
- vcd_file=open("ctrl.vcd", "w"),
- gtkw_file=open("ctrl.gtkw", "w"),
- gtkw_signals=[ctr.ce, ctr.v, ctr.o])
-sim.add_clock("sync", 1e-6)
-def ce_proc():
- yield; yield; yield
- yield ctr.ce.eq(1)
- yield; yield; yield
- yield ctr.ce.eq(0)
- yield; yield; yield
- yield ctr.ce.eq(1)
-sim.add_sync_process(ce_proc())
-with sim: sim.run_until(100e-6, run_passive=True)
+with pysim.Simulator(frag,
+ vcd_file=open("ctrl.vcd", "w"),
+ gtkw_file=open("ctrl.gtkw", "w"),
+ gtkw_signals=[ctr.ce, ctr.v, ctr.o]) as sim:
+ sim.add_clock(1e-6)
+ def ce_proc():
+ yield; yield; yield
+ yield ctr.ce.eq(1)
+ yield; yield; yield
+ yield ctr.ce.eq(0)
+ yield; yield; yield
+ yield ctr.ce.eq(1)
+ sim.add_sync_process(ce_proc())
+ sim.run_until(100e-6, run_passive=True)
class Simulator:
def __init__(self, fragment, vcd_file=None, gtkw_file=None, gtkw_signals=()):
- self._fragments = {} # fragment -> hierarchy
+ self._fragment = fragment
self._domains = {} # str/domain -> ClockDomain
self._domain_triggers = ValueDict() # Signal -> str/domain
self._gtkw_file = gtkw_file
self._gtkw_signals = gtkw_signals
- fragment = fragment.prepare()
-
- def add_fragment(fragment, hierarchy=("top",)):
- self._fragments[fragment] = hierarchy
- for subfragment, name in fragment.subfragments:
- add_fragment(subfragment, (*hierarchy, name))
- add_fragment(fragment)
-
- self._domains = fragment.domains
- for domain, cd in self._domains.items():
- self._domain_triggers[cd.clk] = domain
- if cd.rst is not None:
- self._domain_triggers[cd.rst] = domain
- self._domain_signals[domain] = ValueSet()
-
def add_process(self, process):
self._processes.add(process)
- def add_clock(self, domain, period):
+ def add_clock(self, period, domain="sync"):
if self._fastest_clock == self._epsilon or period < self._fastest_clock:
self._fastest_clock = period
self._vcd_writer = VCDWriter(self._vcd_file, timescale="100 ps",
comment="Generated by nMigen")
- for fragment in self._fragments:
+ root_fragment = self._fragment.prepare()
+
+ self._domains = root_fragment.domains
+ for domain, cd in self._domains.items():
+ self._domain_triggers[cd.clk] = domain
+ if cd.rst is not None:
+ self._domain_triggers[cd.rst] = domain
+ self._domain_signals[domain] = ValueSet()
+
+ fragment_names = {}
+ def add_fragment(fragment, hierarchy=("top",)):
+ fragment_names[fragment] = hierarchy
+ for subfragment, name in fragment.subfragments:
+ add_fragment(subfragment, (*hierarchy, name))
+ add_fragment(root_fragment)
+
+ for fragment, fragment_name in fragment_names.items():
for signal in fragment.iter_signals():
self._signals.add(signal)
else:
var_name_suffix = "{}${}".format(var_name, suffix)
self._vcd_signals[signal].add(self._vcd_writer.register_var(
- scope=".".join(self._fragments[fragment]), name=var_name_suffix,
+ scope=".".join(fragment_name), name=var_name_suffix,
var_type=var_type, size=var_size, init=var_init))
if signal not in self._vcd_names:
- self._vcd_names[signal] = \
- ".".join(self._fragments[fragment] + (var_name_suffix,))
+ self._vcd_names[signal] = ".".join(fragment_name + (var_name_suffix,))
break
except KeyError:
suffix = (suffix or 0) + 1
self._user_signals = self._signals - self._comb_signals - self._sync_signals
+ return self
+
def _update_dirty_signals(self):
"""Perform the statement part of IR processes (aka RTLIL case)."""
# First, for all dirty signals, use sensitivity lists to determine the set of fragments
# No processes, or all processes are passive. Nothing to do!
return False
+ def run(self):
+ while self.step():
+ pass
+
def run_until(self, deadline, run_passive=False):
while self._timestamp < deadline:
if not self.step(run_passive):