Skip to content

Commit

Permalink
sim: add support for passive generators
Browse files Browse the repository at this point in the history
sbourdeauducq committed Nov 15, 2015
1 parent 598638b commit e50df16
Showing 3 changed files with 46 additions and 3 deletions.
2 changes: 1 addition & 1 deletion migen/sim/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from migen.sim.core import Simulator, run_simulation
from migen.sim.core import Simulator, run_simulation, passive
24 changes: 22 additions & 2 deletions migen/sim/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import operator
import collections
import inspect
from functools import wraps

from migen.fhdl.structure import *
from migen.fhdl.structure import (_Value, _Statement,
@@ -220,6 +221,7 @@ def __init__(self, fragment_or_module, generators, clocks={"sys": 10}, vcd_name=
if not isinstance(generators, dict):
generators = {"sys": generators}
self.generators = dict()
self.passive_generators = set()
for k, v in generators.items():
if (isinstance(v, collections.Iterable)
and not inspect.isgenerator(v)):
@@ -297,6 +299,14 @@ def _process_generators(self, cd):
request = generator.send(reply)
if request is None:
break # next cycle
elif isinstance(request, str):
if request == "passive":
self.passive_generators.add(generator)
elif request == "active":
self.passive_generators.discard(generator)
else:
raise ValueError("Unknown simulator command: '{}'"
.format(request))
else:
reply = self._evalexec_nested_lists(request)
except StopIteration:
@@ -306,8 +316,10 @@ def _process_generators(self, cd):
self.generators[cd].remove(generator)

def _continue_simulation(self):
# TODO: passive generators
return any(self.generators.values())
for cd_generators in self.generators.values():
if set(cd_generators) - self.passive_generators:
return True
return False

def run(self):
self.evaluator.execute(self.fragment.comb)
@@ -333,3 +345,11 @@ def run(self):
def run_simulation(*args, **kwargs):
with Simulator(*args, **kwargs) as s:
s.run()


def passive(generator):
@wraps(generator)
def wrapper(*args, **kwargs):
yield "passive"
yield from generator(*args, **kwargs)
return wrapper
23 changes: 23 additions & 0 deletions migen/test/test_passive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import unittest

from migen import *


class PassiveCase(unittest.TestCase):
def test_terminates_correctly(self):
n = 5

count = 0
@passive
def counter():
nonlocal count
while True:
yield
count += 1

def terminator():
for i in range(n):
yield

run_simulation(Module(), [counter(), terminator()])
self.assertEqual(count, n)

0 comments on commit e50df16

Please sign in to comment.