mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +08:00
172 lines
5.1 KiB
ReStructuredText
172 lines
5.1 KiB
ReStructuredText
|
|
.. _background:
|
|
|
|
**********************
|
|
Background information
|
|
**********************
|
|
|
|
|
|
.. _prerequisites:
|
|
|
|
Prerequisites
|
|
=============
|
|
|
|
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 [#]_.
|
|
|
|
For starters, http://www.python.org/doc/current/tut/tut.html is probably the
|
|
best choice for an on-line tutorial. For alternatives, see
|
|
http://www.python.org/doc/Newbies.html.
|
|
|
|
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
|
|
:file:`example/manual/`.
|
|
|
|
|
|
.. _tutorial:
|
|
|
|
A small tutorial on generators
|
|
==============================
|
|
|
|
.. index:: single: generators; tutorial on
|
|
|
|
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 :keyword:`return`
|
|
with :keyword:`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 :func:`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 :keyword:`yield` statement is like
|
|
a :keyword:`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 :func:`next` method. We
|
|
say that generators are :dfn:`resumable functions`.
|
|
|
|
.. index::
|
|
single: VHDL; process
|
|
single: Verilog; always block
|
|
|
|
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 :dfn:`processes` in
|
|
VHDL and :dfn:`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.
|
|
|
|
.. %
|
|
.. %
|
|
|
|
.. index:: single: sensitivity list
|
|
|
|
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, :keyword:`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.
|
|
|
|
|
|
.. _deco:
|
|
|
|
About decorators
|
|
================
|
|
|
|
.. index:: single: decorators; about
|
|
|
|
Python 2.4 introduced a new feature called decorators. MyHDL 0.5 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 :func:`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:`func` is automatically reused for
|
|
the final result.
|
|
|
|
MyHDL 0.5 uses decorators to create ready-to-simulate generators from local
|
|
function definitions. Their functionality and usage will be described
|
|
extensively in this manual.
|
|
|
|
For more info about Python decorators, consult the on-line Python documentation,
|
|
e.g. at http://www.python.org/doc/2.4/whatsnew/node6.html.
|
|
|
|
.. warning::
|
|
|
|
Because MyHDL 0.5 uses decorators, it requires Python 2.4 or a later version.
|
|
|
|
.. rubric:: Footnotes
|
|
|
|
.. [#] You must be bored by such claims, but in Python's case it's true.
|
|
|
|
.. [#] I am not biased.
|
|
|