Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1b7f8c795012
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dd00b5e2d677
Choose a head ref
  • 1 commit
  • 3 files changed
  • 1 contributor

Commits on Dec 14, 2018

  1. back.pysim: more general clean-up.

    whitequark committed Dec 14, 2018
    Copy the full SHA
    dd00b5e View commit details
Showing with 45 additions and 38 deletions.
  1. +4 −3 examples/clkdiv.py
  2. +14 −14 examples/ctrl.py
  3. +27 −21 nmigen/back/pysim.py
7 changes: 4 additions & 3 deletions examples/clkdiv.py
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ def get_fragment(self, platform):
# print(rtlil.convert(frag, ports=[ctr.o]))
print(verilog.convert(frag, ports=[ctr.o]))

sim = pysim.Simulator(frag, vcd_file=open("clkdiv.vcd", "w"))
sim.add_clock("sync", 1e-6)
with sim: sim.run_until(100e-6, run_passive=True)
with pysim.Simulator(frag,
vcd_file=open("clkdiv.vcd", "w")) as sim:
sim.add_clock(1e-6)
sim.run_until(100e-6, run_passive=True)
28 changes: 14 additions & 14 deletions examples/ctrl.py
Original file line number Diff line number Diff line change
@@ -21,17 +21,17 @@ def get_fragment(self, platform):
# 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)
48 changes: 27 additions & 21 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -190,7 +190,7 @@ def run(state):

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
@@ -223,25 +223,10 @@ def __init__(self, fragment, vcd_file=None, gtkw_file=None, gtkw_signals=()):
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

@@ -272,7 +257,23 @@ def __enter__(self):
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)

@@ -307,11 +308,10 @@ def __enter__(self):
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
@@ -344,6 +344,8 @@ def add_funclet(signal, funclet):

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
@@ -502,6 +504,10 @@ def step(self, run_passive=False):
# 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):