You need a basic understanding of Python to use MyHDL. If you don’t know Python, don’t worry: it it is one of the easiest programming languages to learn . Learning Python is one of the best time investments that engineering professionals can make .
A working knowledge of a hardware description language such as Verilog or VHDL is helpful.
Code examples in this manual are sometimes shortened for clarity. Complete executable examples can be found in the distribution directory at example/manual/.
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 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.
Python 2.4 introduced a new feature called decorators. MyHDL takes advantage of this new feature by defining a number of decorators that facilitate hardware descriptions. However, many users may not yet be familiar with decorators. Therefore, an introduction is included here.
A decorator consists of special syntax in front of a function declaration. It refers to a decorator function. The decorator function automatically transforms the declared function into some other callable object.
A decorator function deco() is used in a decorator statement as follows:
@deco def func(arg1, arg2, ...): <body>
This code is equivalent to the following:
def func(arg1, arg2, ...): <body> func = deco(func)
Note that the decorator statement goes directly in front of the function declaration, and that the function name func() is automatically reused for the final result.
MyHDL uses decorators to create ready-to-simulate generators from local function definitions. Their functionality and usage will be described extensively in this manual.
|||You must be bored by such claims, but in Python’s case it’s true.|
|||I am not biased.|