mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +08:00
437 lines
14 KiB
TeX
437 lines
14 KiB
TeX
\documentclass{howto}
|
|
% \usepackage{distutils}
|
|
\usepackage{palatino}
|
|
\renewcommand{\ttdefault}{cmtt}
|
|
\renewcommand{\sfdefault}{cmss}
|
|
\newcommand{\myhdl}{\protect \mbox{MyHDL}}
|
|
\usepackage{graphicx}
|
|
% $Id$
|
|
|
|
\title{What's New in \myhdl\ 0.3}
|
|
\release{0.3}
|
|
\author{Jan Decaluwe}
|
|
\authoraddress{\email{jan@jandecaluwe.com}}
|
|
|
|
\begin{document}
|
|
\maketitle
|
|
\tableofcontents
|
|
|
|
|
|
\section{VCD output for waveform viewing\label{section-wave}}
|
|
|
|
\ifpdf
|
|
\includegraphics{tbfsm.png}
|
|
\fi
|
|
|
|
\myhdl\ now has support for waveform viewing. During simulation, signal
|
|
changes can be written to a VCD output file. The VCD file can then be
|
|
loaded and viewed in a waveform viewer tool such as \program{gtkwave}.
|
|
|
|
The user interface of this feature consists of a single function,
|
|
\function{traceSignals()}. To explain how it works, recall that in
|
|
\myhdl{}, an instance is created by calling a function that returns a
|
|
sequence of generators, and by assigning the result to an instance
|
|
name. For example:
|
|
|
|
\begin{verbatim}
|
|
tb_fsm = testbench()
|
|
\end{verbatim}
|
|
|
|
To enable VCD tracing, the instance should be created as follows
|
|
instead:
|
|
|
|
\begin{verbatim}
|
|
tb_fsm = traceSignals(testbench)
|
|
\end{verbatim}
|
|
|
|
All signals in the instance hierarchy will be traced in
|
|
an output VCD file called \file{tb_fsm.vcd}. Note that the argument of
|
|
\function{traceSignals()} consists of the uncalled function. By calling
|
|
the function under its control, \function{traceSignals()} gathers
|
|
information about the hierarchy and the signals to be traced. In
|
|
addition to a function argument, \function{traceSignals()} accepts an
|
|
arbitrary number of non-keyword and keyword arguments that will be
|
|
passed to the function call.
|
|
|
|
The restrictions on VCD tracing are as follows. First, only
|
|
\class{Signal} objects can be traced. Second, only a hierarchy of
|
|
instances returned by a pre-simulation top level function call can be
|
|
traced.
|
|
|
|
Signals are dumped in a suitable format. This format is inferred at
|
|
the \class{Signal} construction time, from the type of the initial
|
|
value. In particular, \class{bool} signals are dumped as single
|
|
bits. (This only works starting with Python2.3, when \class{bool} has
|
|
become a separate type). Likewise, \class{intbv} signals with a
|
|
defined bit width are dumped as bit vectors. To support the general
|
|
case, other types of signals are dumped as a string representation, as
|
|
returned by the standard \function{str()} function.
|
|
|
|
\begin{notice}[warning]
|
|
Support for literal string representations is not part of the VCD
|
|
standard. It is specific to \program{gtkwave}. To generate a
|
|
standard VCD file, you need to use signals with a defined bit width
|
|
only.
|
|
\end{notice}
|
|
|
|
\section{An enumeration type\label{section-enum}}
|
|
|
|
It is often desirable to define a set of identifiers. A standard
|
|
Python idiom for this purpose is to assign a range of integers to a
|
|
tuple of identifiers, like so:
|
|
|
|
\begin{verbatim}
|
|
>>> SEARCH, CONFIRM, SYNC = range(3)
|
|
>>> CONFIRM
|
|
1
|
|
\end{verbatim}
|
|
|
|
However, this technique has some drawbacks. Though it is clearly
|
|
the intention that the identifiers belong together, this information
|
|
is lost as soon as they are defined. Also, the identifiers evaluate to
|
|
integers, whereas a string representation of the identifiers
|
|
would be preferable. To solve these issues, we need an
|
|
\emph{enumeration type}.
|
|
|
|
\myhdl\ 0.3 supports enumeration types by providing a function
|
|
\function{enum()}. The arguments to \function{enum()} are the string
|
|
representations of the identifiers, and its return value is an
|
|
enumeration type. The identifiers are available as attributes of the
|
|
type. For example:
|
|
|
|
\begin{verbatim}
|
|
>>> from myhdl import enum
|
|
>>> t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
|
|
>>> t_State
|
|
<Enum: SEARCH, CONFIRM, SYNC>
|
|
>>> t_State.CONFIRM
|
|
CONFIRM
|
|
\end{verbatim}
|
|
|
|
Enumeration types are often used for the state variable in a finite
|
|
state machine. In the waveform in Section~\ref{section-wave}, you see
|
|
a \class{Signal} called \code{state} which as been constructed with an
|
|
enumeration type identifier as initial value, as follows:
|
|
|
|
\begin{verbatim}
|
|
state = Signal(t_State.SEARCH)
|
|
\end{verbatim}
|
|
|
|
Note that the waveforms show the string representation of the
|
|
enumeration type identifiers.
|
|
|
|
|
|
\section{Inferring the sensitivity list for combinatorial
|
|
logic\label{section-combinatorial}}
|
|
|
|
In \myhdl{}, combinatorial logic is described by a generator function with
|
|
a sensitivity list that contains all inputs signals (the signals that
|
|
are read inside the function).
|
|
|
|
It may be easy to forget some input signals, especially it there are a
|
|
lot of them or if the code is being modified. There are various ways
|
|
to solve this. One way is to use a sophisticated editor. Another way
|
|
is direct language support. For example, recent versions of Verilog
|
|
have the \code{always~@*} construct, that infers all input
|
|
signals. The SystemVerilog 3.1 standard improves on this by
|
|
introducing the \code{always_comb} block with slightly enhanced
|
|
semantics.
|
|
|
|
\myhdl\ 0.3 provides a function called \function{always_comb()} which
|
|
is named and modeled after the SystemVerilog counterpart.
|
|
\function{always_comb()} takes a single classic function as its
|
|
argument. This function should be a locally defined function that
|
|
specifies what should happen when one of its input signals
|
|
changes. \function{always_comb()} returns a generator that is
|
|
sensitive to all inputs, and that will run the function whenever an
|
|
input changes.
|
|
|
|
For example, suppose that we have a mux module described as follows:
|
|
|
|
\begin{verbatim}
|
|
def mux(z, a, b, sel):
|
|
|
|
""" Multiplexer.
|
|
|
|
z -- mux output
|
|
a, b -- data inputs
|
|
sel -- control input
|
|
|
|
"""
|
|
|
|
def logic()
|
|
while 1:
|
|
yield a, b, sel
|
|
if sel == 1:
|
|
z.next = a
|
|
else:
|
|
z.next = b
|
|
mux_logic = logic()
|
|
|
|
return mux_logic
|
|
\end{verbatim}
|
|
|
|
Using \function{always_comb()}, we can describe it as follows instead:
|
|
|
|
\begin{verbatim}
|
|
def mux(z, a, b, sel):
|
|
|
|
""" Multiplexer.
|
|
|
|
z -- mux output
|
|
a, b -- data inputs
|
|
sel -- control input
|
|
|
|
"""
|
|
|
|
def logic()
|
|
if sel == 1:
|
|
z.next = a
|
|
else:
|
|
z.next = b
|
|
mux_logic = always_comb(logic)
|
|
|
|
return mux_logic
|
|
\end{verbatim}
|
|
|
|
|
|
\section{Inferring the list of all instances\label{section-instances}}
|
|
|
|
In \myhdl{}, the instances defined in a top level function
|
|
need to be returned explicitly. The following is a schematic
|
|
example:
|
|
|
|
\begin{verbatim}
|
|
def top(...):
|
|
...
|
|
instance_1 = module_1(...)
|
|
instance_2 = module_2(...)
|
|
...
|
|
instance_n = module_n(...)
|
|
...
|
|
return instance_1, instance_2, ... , instance_n
|
|
\end{verbatim}
|
|
|
|
|
|
This permits fine grained control: for example, it
|
|
is possible to return a different set of instances
|
|
under parameter control.
|
|
However, having to return instances explicitly can be inconvenient,
|
|
especially if there are a large number of them. Therefore, \myhdl\ 0.3
|
|
provides a function \function{instances()} which assembles a list of
|
|
all instances automatically. It is used as follows:
|
|
|
|
\begin{verbatim}
|
|
from myhdl import instances
|
|
|
|
def top(...):
|
|
...
|
|
instance_1 = module_1(...)
|
|
instance_2 = module_2(...)
|
|
...
|
|
instance_n = module_n(...)
|
|
...
|
|
return instances()
|
|
\end{verbatim}
|
|
|
|
Function \function{instances()} uses introspection to inspect the type
|
|
of the local variables defined by the calling function. In \myhdl {},
|
|
an instance is defined as a nested sequence of generators: all such
|
|
variables are looked up and assembled in a list.
|
|
|
|
\section{Inferring the list of all processes\label{section-processes}}
|
|
|
|
In addition to instances, a top level function may
|
|
also define local generators functions, which I will
|
|
call \emph{processes} because of the analogy with VHDL.
|
|
Like instances, processes need to be returned explicitly,
|
|
with the qualification that they have to be called first
|
|
to turn them into generators. The following is a schematic
|
|
example:
|
|
|
|
\begin{verbatim}
|
|
def top(...):
|
|
...
|
|
def process_1():
|
|
...
|
|
def process_2():
|
|
...
|
|
...
|
|
def process_n():
|
|
...
|
|
...
|
|
return process_1(), process_2(), ..., process_n()
|
|
\end{verbatim}
|
|
|
|
As for instances, it may be more convenient to assemble the list of
|
|
processes automatically. One option is to turn each process into an
|
|
instance by calling it and assigning the returned generator to a local
|
|
variable. Those instances will then be found by the
|
|
\function{instances()} function described in
|
|
Section~\ref{section-instances}.
|
|
|
|
Another option is to use the function \function{processes()} provided
|
|
by \myhdl\ 0.3 . This function uses introspection to find the
|
|
processes, calls each of them, and assembles the returned generators
|
|
into a list. It can be used as follows:
|
|
|
|
\begin{verbatim}
|
|
from myhdl import processes
|
|
|
|
def top(...):
|
|
...
|
|
def process_1():
|
|
...
|
|
def process_2():
|
|
...
|
|
...
|
|
def process_n():
|
|
...
|
|
...
|
|
return processes()
|
|
\end{verbatim}
|
|
|
|
To conclude, a top level function with both instances and processes
|
|
can use the following idiomatic code to return all of them:
|
|
|
|
\begin{verbatim}
|
|
return instances(), processes()
|
|
\end{verbatim}
|
|
|
|
\section{Class \class{intbv} enhancements\label{section-intbv}}
|
|
|
|
Class \class{intbv} has been enhanced with new features.
|
|
|
|
It is now possible to leave the left index of a slicing operation
|
|
unspecified. The meaning is to access ``all'' higher order bits. For
|
|
example:
|
|
|
|
\begin{verbatim}
|
|
>>> from myhdl import intbv
|
|
>>> n = intbv()
|
|
>>> hex(n)
|
|
'0x0'
|
|
>>> n[:] = 0xde
|
|
>>> hex(n)
|
|
'0xde'
|
|
>>> n[:8] = 0xfa
|
|
>>> hex(n)
|
|
'0xfade'
|
|
>>> n[8:] = 0xb4
|
|
>>> hex(n)
|
|
'0xfab4'
|
|
\end{verbatim}
|
|
|
|
\class{intbv} objects now have \var{min} and \var{max} attributes
|
|
that can be specified at construction time. The meaning is that that
|
|
only values within \code{range(min, max)} are permitted. The default
|
|
values for these attributes is \var{None}, meaning ``infinite''. For
|
|
example (traceback output shortened for clarity):
|
|
|
|
\begin{verbatim}
|
|
>>> n = intbv(min=-17, max=53)
|
|
>>> n
|
|
intbv(0)
|
|
>>> n.min
|
|
-17
|
|
>>> n.max
|
|
53
|
|
>>> n[:] = 28
|
|
>>> n
|
|
intbv(28)
|
|
>>> n[:] = -18
|
|
Traceback (most recent call last):
|
|
....
|
|
ValueError: intbv value -18 < minimum -17
|
|
>>> n[:] = 53
|
|
Traceback (most recent call last):
|
|
....
|
|
ValueError: intbv value 53 >= maximum 53
|
|
\end{verbatim}
|
|
|
|
When a slice is taken from an \class{intbv} object, the return value
|
|
is a new \class{intbv} object with a defined bit width. As in
|
|
Verilog, the value of the new \class{intbv} object is always
|
|
positive, regardless of the sign of the original value. In addition,
|
|
the \var{min} and \var{max} attributes are set implicitly:
|
|
|
|
\begin{verbatim}
|
|
>>> v = intbv()[6:]
|
|
>>> v
|
|
intbv(0)
|
|
>>> v.min
|
|
0
|
|
>>> v.max
|
|
64
|
|
\end{verbatim}
|
|
|
|
Lastly, a small change was implemented with regard to
|
|
binary operations. In previous versions, both numeric
|
|
and bit-wise operations always returned a new \class{intbv}
|
|
object, even in mixed-mode operations with \class{int}
|
|
objects. This has changed: numeric operations
|
|
return an \class{int}, and bitwise operations return
|
|
a \class{intbv}. In this way, the return value corresponds
|
|
better to the nature of the operation.
|
|
|
|
\section{Function \function{concat()} \label{section-concat}}
|
|
|
|
In previous versions, the \class{intbv} class provided a
|
|
\method{concat()} method. This method is no longer
|
|
available. Instead, there is now a \function{concat()} function in
|
|
\myhdl{}, which supports a much broader range of objects.
|
|
|
|
A function is more natural because \myhdl\ objects of various types
|
|
can be concatenated: \class{intbv} objects with a defined bit width,
|
|
\class{bool} objects, the corresponding signal objects, and bit
|
|
strings. All these objects have a defined bit width. Moreover, the
|
|
first argument doesn't need to have a defined bit width. It can also be
|
|
an unsized \class{intbv}, an \class{int}, a \class{long}, or a
|
|
corresponding signal object. Function \function{concat()} returns an
|
|
\class{intbv} object.
|
|
|
|
|
|
\section{Python 2.3 support\label{section-Python}}
|
|
|
|
Python 2.3 was released on July 29, 2003, and as of this writing, it
|
|
is the latest stable Python release.
|
|
|
|
\myhdl\ 0.3 works with both Python 2.2 and Python 2.3. In good Python
|
|
tradition, \myhdl\ code developed with Python 2.2 should run without
|
|
changes or problems in Python 2.3.
|
|
|
|
In general, I am not that keen on early upgrading. However, as it
|
|
happens, the evolution of Python enables features that are really
|
|
important or even crucial to \myhdl{}. Python 2.2 generators are the
|
|
best example: they are the cornerstone of \myhdl{}. But Python 2.3
|
|
also has significant benefits, which I will summarize below.
|
|
|
|
First, generators and the \code{yield} statement are a default Python
|
|
2.3 feature. This means that \code{from __future__ import generators}
|
|
statements are no longer required.
|
|
|
|
Second, Python 2.3 has a \class{bool} type, which is implemented as a
|
|
subtype of \class{int}. For general Python use, the implications are
|
|
rather limited - the main difference is that logical result values
|
|
will print as \code{False} and \code{True} instead of \code{0} and
|
|
\code{1}. However, in \myhdl{}, I can use the \class{bool} type to
|
|
infer a bit width. If a \class{Signal} is constructed with a
|
|
\class{bool} value, it is a single bit \class{Signal}. One application
|
|
is waveform viewing as in Section~\ref{section-wave}. In the waveform,
|
|
note how single bit signals are displayed as level changes. With
|
|
Python 2.2, the waveforms of these signals would only show value
|
|
changes, which is not as clear for single bits.
|
|
|
|
Finally, Python 2.3 is significantly faster. \myhdl\ code runs
|
|
25--35\% faster in Python 2.3. This is a very nice speedup compared to
|
|
the small burden of a straightforward upgrade.
|
|
|
|
Python is a very stable language, so upgrading to Python 2.3 is
|
|
virtually risk free. Given the additional benefits, I recommend
|
|
\myhdl\ users to do so as soon as possible. For the next major
|
|
release, the new features will become crucial and only Python 2.3 (and
|
|
higher) will be supported.
|
|
|
|
|
|
\end{document}
|