Generators are a relatively recent Python feature. They were introduced in Python 2.2. Because generators are the key concept in MyHDL, a small tutorial is included a here.
Consider the following nonsensical function:
def function():
for i in range(5):
return i
You can see why it doesn't make a lot of sense. As soon as the first loop iteration is entered, the function returns:
>>> function() 0
Returning is fatal for the function call. Further loop iterations never get a chance, and nothing is left over from the function call when it returns.
To change the function into a generator function, we replace return with yield:
def generator():
for i in range(5):
yield i
Now we get:
>>> generator() <generator object at 0x815d5a8>
When a generator function is called, it returns a generator object. A generator object supports the iterator protocol, which is an expensive way of saying that you can let it generate subsequent values by calling its next() method:
>>> g = generator() >>> g.next() 0 >>> g.next() 1 >>> g.next() 2 >>> g.next() 3 >>> g.next() 4 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration
Now we can generate the subsequent values from the for loop on demand, until they are exhausted. What happens is that the yield statement is like a return, except that it is non-fatal: the generator remembers its state and the point in the code when it yielded. A higher order agent can decide when to get the next value by calling the generator's next() method. We say that generators are resumable functions.
If you are familiar with hardware description languages, this may ring a bell. In hardware simulations, there is also a higher order agent, the Simulator, that interacts with such resumable functions; they are called processes in VHDL and always blocks in Verilog. Similarly, Python generators provide an elegant and efficient method to model concurrency, without having to resort to some form of threading.
The use of generators to model concurrency is the first key concept in MyHDL. The second key concept is a related one: in MyHDL, the yielded values are used to specify the conditions on which the generator should wait before resuming. In other words, yield statements work as general sensitivity lists.
For more info about generators, consult the on-line Python documentation, e.g. at http://www.python.org/doc/2.2.2/whatsnew.
About this document