mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
Added
This commit is contained in:
parent
05983f3e65
commit
516fb7bf38
@ -2,15 +2,17 @@ NAME = manual
|
|||||||
|
|
||||||
default: $(NAME).dvi $(NAME).ps $(NAME).pdf
|
default: $(NAME).dvi $(NAME).ps $(NAME).pdf
|
||||||
|
|
||||||
%.pdf: %.ps
|
#%.pdf: %.ps
|
||||||
ps2pdf $<
|
# ps2pdf $<; \
|
||||||
|
|
||||||
%.ps: %.dvi
|
%.ps: %.dvi
|
||||||
dvips -o $@ -t a4 -Ppdf -G0 $<
|
dvips -o $@ -t a4 -Ppdf -G0 $<
|
||||||
|
|
||||||
%.dvi: %.tex
|
%.dvi: %.tex
|
||||||
latex $<; \
|
latex $<; \
|
||||||
latex $<
|
python tools/toc2bkm.py -c chapter $(NAME).toc
|
||||||
|
latex $<; \
|
||||||
|
pdflatex $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm *.dvi *.log *.toc *.ps *.pdf *.aux *.out
|
-rm *.dvi *.log *.toc *.ps *.pdf *.aux *.out
|
||||||
|
@ -39,22 +39,22 @@ explain the \samp{import *} syntax}.
|
|||||||
|
|
||||||
Next, we define a generator function called
|
Next, we define a generator function called
|
||||||
\code{sayHello}. This is a generator function (as opposed to
|
\code{sayHello}. This is a generator function (as opposed to
|
||||||
a classic Python function) because it contains a \code{yield}
|
a classic Python function) because it contains a \keyword{yield}
|
||||||
statement (instead of \code{return} statement). In \myhdl\, a
|
statement (instead of \keyword{return} statement). In \myhdl\, a
|
||||||
\code{yield} statement has a similar purpose as a \code{wait}
|
\keyword{yield} statement has a similar purpose as a \keyword{wait}
|
||||||
statement in VHDL: the statement suspends execution of the function,
|
statement in VHDL: the statement suspends execution of the function,
|
||||||
and its clauses specify when the function should resume. In this case,
|
and its clauses specify when the function should resume. In this case,
|
||||||
there is a \code{delay} clause, that specifies the required delay.
|
there is a \code{delay} clause, that specifies the required delay.
|
||||||
|
|
||||||
To make sure that the generator runs ``forever'', we wrap its behavior
|
To make sure that the generator runs ``forever'', we wrap its behavior
|
||||||
in a \code{while 1} loop. This is as standard Python idiom, and it is
|
in a \code{while 1} loop. This is as standard Python idiom, and it is
|
||||||
the \myhdl\ equivalent to a Verilog \code{always} block or a
|
the \myhdl\ equivalent to a Verilog \keyword{always} block or a
|
||||||
VHDL \code{process}.
|
VHDL \keyword{process}.
|
||||||
|
|
||||||
In \myhdl\, the basic simulation objects are generators. Generators
|
In \myhdl\, the basic simulation objects are generators. Generators
|
||||||
are created by calling a generator function. For example, variable
|
are created by calling generator functions. For example, variable
|
||||||
\code{gen} refers to a generator. To simulate this generator, we pass
|
\code{gen} refers to a generator. To simulate this generator, we pass
|
||||||
it as an argument to a code{Simulation} object constructor. We then
|
it as an argument to a \class{Simulation} object constructor. We then
|
||||||
run the simulation for the desired amount of time.
|
run the simulation for the desired amount of time.
|
||||||
|
|
||||||
|
|
||||||
@ -64,14 +64,15 @@ In the previous section, we simulated a single generator. Of course,
|
|||||||
real hardware descriptions are not like that: in fact, they are
|
real hardware descriptions are not like that: in fact, they are
|
||||||
typically massively concurrent. \myhdl\ supports this by allowing an
|
typically massively concurrent. \myhdl\ supports this by allowing an
|
||||||
arbitrary number of concurrent generators. More specifically, a
|
arbitrary number of concurrent generators. More specifically, a
|
||||||
\code{Simulation} constructor can take an arbitrary number of
|
\class{Simulation} constructor can take an arbitrary number of
|
||||||
arguments, each of which can be a generator or a nested list of
|
arguments, each of which can be a generator or a nested list of
|
||||||
generators.
|
generators.
|
||||||
|
|
||||||
With concurrency comes the problem of determinism. Therefore, hardware
|
With concurrency comes the problem of deterministic
|
||||||
languages use special objects to support deterministic communication
|
communication. Therefore, hardware languages use special objects to
|
||||||
between concurrent regions. \myhdl\ has as \code{Signal} object which
|
support deterministic communication between concurrent
|
||||||
is roughly modelled after VHDL signals.
|
regions. \myhdl\ has as \class{Signal} object which is roughly modelled
|
||||||
|
after VHDL signals.
|
||||||
|
|
||||||
We will demonstrate these concepts by extending our first example. We
|
We will demonstrate these concepts by extending our first example. We
|
||||||
introduce a clock signal, driven by a second generator. The
|
introduce a clock signal, driven by a second generator. The
|
||||||
@ -120,21 +121,22 @@ attribute. This is the \myhdl\ equivalent of VHDL signal assignments
|
|||||||
and Verilog's non-blocking assignments.
|
and Verilog's non-blocking assignments.
|
||||||
|
|
||||||
The \code{sayHello} generator function shows a second form of a
|
The \code{sayHello} generator function shows a second form of a
|
||||||
\code{yield} statement: \samp{yield posedge(\var{aSignal})}. Again,
|
\keyword{yield} statement: \samp{yield posedge(\var{aSignal})}. Again,
|
||||||
the generator will suspend execution at that point, but in this case
|
the generator will suspend execution at that point, but in this case
|
||||||
it specifies that it should resume when there is a rising edge on the
|
it specifies that it should resume when there is a rising edge on the
|
||||||
signal.
|
signal.
|
||||||
|
|
||||||
The \code{Simulation} constructor now takes two generator arguments
|
The \class{Simulation} constructor now takes two generator arguments
|
||||||
that run concurrently throughout the simulation.
|
that run concurrently throughout the simulation.
|
||||||
|
|
||||||
\section{Parameters and instantiations}
|
\section{Parameters and instantiations}
|
||||||
|
|
||||||
So far, the generator function examples had no parameters. The signals
|
So far, the generator function examples had no parameters. For
|
||||||
they operated on were defined in their enclosing scope. However,
|
example, the \code{clk} signal was defined in the enclosing scope of
|
||||||
to make the code reusable we will want to pass arguments through a
|
the generator functions. However, to make the code reusable we will
|
||||||
parameter list. For example, we can change the clock generator
|
want to pass arguments through a parameter list. For example, we can
|
||||||
function as follows to make it more general and reusable:
|
change the clock generator function to make it more general
|
||||||
|
and reusable, as follows:
|
||||||
|
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
def clkGen(clock, period=20):
|
def clkGen(clock, period=20):
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
\myhdl\ is implemented as a Python package called \code{myhdl}. This
|
\myhdl\ is implemented as a Python package called \code{myhdl}. This
|
||||||
chapter describes all objects that are expored by this package.
|
chapter describes the objects that are expored by this package.
|
||||||
|
|
||||||
\section{The \class{Simulation} class}
|
\section{The \class{Simulation} class}
|
||||||
\begin{classdesc}{Simulation}{arg \optional{, arg \moreargs}}
|
\begin{classdesc}{Simulation}{arg \optional{, arg \moreargs}}
|
||||||
@ -17,7 +17,7 @@ object.
|
|||||||
A \class{Simulation} instance has the following method:
|
A \class{Simulation} instance has the following method:
|
||||||
|
|
||||||
\begin{methoddesc}[Simulation]{run}{\optional{duration}}
|
\begin{methoddesc}[Simulation]{run}{\optional{duration}}
|
||||||
Run the simulation forever or for a specified duration.
|
Run the simulation forever (by default) or for a specified duration.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
\section{The \class{Signal} class}
|
\section{The \class{Signal} class}
|
||||||
@ -44,16 +44,16 @@ statements are called \emph{sensitivity lists}. The general format is:
|
|||||||
|
|
||||||
\keyword{yield} \var{clause \optional{, clause ...}}
|
\keyword{yield} \var{clause \optional{, clause ...}}
|
||||||
|
|
||||||
After a simulator executes a \keyword{yield} statement, it suspends
|
After a simulation object executes a \keyword{yield} statement, it
|
||||||
execution of the generator. At the same time, each \var{clause} is a
|
suspends execution of the generator. At the same time, each
|
||||||
\emph{trigger object} which defines the condition upon which the
|
\var{clause} is a \emph{trigger object} which defines the condition
|
||||||
generator should be resumed. However, per invocation of a \keyword{yield}
|
upon which the generator should be resumed. However, per invocation of a
|
||||||
statement, the generator is resumed exactly once, regardless of the
|
\keyword{yield} statement, the generator is resumed exactly once,
|
||||||
number of clauses. This happens when the \emph{first} trigger object
|
regardless of the number of clauses. This happens when the
|
||||||
triggers; subsequent triggers are neglected. (However, as a result of
|
\emph{first} trigger object triggers; subsequent triggers are
|
||||||
the resumption, it is possible that the same \keyword{yield} statement
|
neglected. (However, as a result of the resumption, it is possible
|
||||||
is invoked again, and that a subsequent trigger still triggers the
|
that the same \keyword{yield} statement is invoked again, and that a
|
||||||
generator.)
|
subsequent trigger still triggers the generator.)
|
||||||
|
|
||||||
In this section, the trigger objects and their functionality will be
|
In this section, the trigger objects and their functionality will be
|
||||||
described. When referring to ``the generator'' we mean the generator
|
described. When referring to ``the generator'' we mean the generator
|
||||||
@ -139,10 +139,10 @@ assignment to indexes and slices, as is common in hardware design. For
|
|||||||
the same reason, \class{intbv} is not a subclass from \class{int},
|
the same reason, \class{intbv} is not a subclass from \class{int},
|
||||||
even though \class{int} provides most of the desired
|
even though \class{int} provides most of the desired
|
||||||
functionality. (It is not possible to derive a mutable subtype from
|
functionality. (It is not possible to derive a mutable subtype from
|
||||||
and immutable type.)
|
an immutable base type.)
|
||||||
|
|
||||||
An \class{intbv} object supports all comparison, numberic, bitwise,
|
An \class{intbv} object supports the same comparison, numberic,
|
||||||
and logical operations as \class{int} objects. See
|
bitwise, logical, and conversion operations as \class{int} objects. See
|
||||||
\url{http://www.python.org/doc/current/lib/typesnumeric.html} for more
|
\url{http://www.python.org/doc/current/lib/typesnumeric.html} for more
|
||||||
information on such operations. In all binary operations,
|
information on such operations. In all binary operations,
|
||||||
\class{intbv} objects can work together with \class{int} objects; in
|
\class{intbv} objects can work together with \class{int} objects; in
|
||||||
@ -153,7 +153,7 @@ operations:
|
|||||||
|
|
||||||
\begin{tableiii}{clc}{code}{Operation}{Result}{Notes}
|
\begin{tableiii}{clc}{code}{Operation}{Result}{Notes}
|
||||||
\lineiii{\var{bv}[\var{i}]}
|
\lineiii{\var{bv}[\var{i}]}
|
||||||
{\var{i}'th item of \var{bv}}
|
{item \var{i} of \var{bv}}
|
||||||
{(1)}
|
{(1)}
|
||||||
\lineiii{\var{bv}[\var{i}] = \var{x}}
|
\lineiii{\var{bv}[\var{i}] = \var{x}}
|
||||||
{item \var{i} of \var{bv} is replaced by \var{x}}
|
{item \var{i} of \var{bv} is replaced by \var{x}}
|
||||||
@ -162,7 +162,7 @@ operations:
|
|||||||
{slice of \var{bv} from \var{i} downto \var{j}}
|
{slice of \var{bv} from \var{i} downto \var{j}}
|
||||||
{(2)(3)}
|
{(2)(3)}
|
||||||
\lineiii{\var{bv}[\var{i}:\var{j}] = \var{t}}
|
\lineiii{\var{bv}[\var{i}:\var{j}] = \var{t}}
|
||||||
{slice of \var{bv} from \var{i} downto to \var{j} is replaced
|
{slice of \var{bv} from \var{i} downto \var{j} is replaced
|
||||||
by \var{t}}
|
by \var{t}}
|
||||||
{(2)(4)}
|
{(2)(4)}
|
||||||
\end{tableiii}
|
\end{tableiii}
|
||||||
@ -171,14 +171,29 @@ operations:
|
|||||||
\item[(1)] Indexing follows the most common hardware design
|
\item[(1)] Indexing follows the most common hardware design
|
||||||
conventions: the lsb bit is the rightmost bit, and it has
|
conventions: the lsb bit is the rightmost bit, and it has
|
||||||
index 0. This has the following desirable property: if the
|
index 0. This has the following desirable property: if the
|
||||||
value is decomposed as a sum of powers of 2, the bit with
|
\class{intbv} value is decomposed as a sum of powers of 2,
|
||||||
index \var{i} corresponds to the term \code{2**i}.
|
the bit with index \var{i} corresponds to the term
|
||||||
|
\code{2**i}.
|
||||||
|
|
||||||
\item[(2)] slicing
|
\item[(2)] It follows from the indexing convention that slicing ranges
|
||||||
|
are downward, in contrast to standard Python. However, the
|
||||||
|
Python convention of half-open ranges is followed. In
|
||||||
|
accordance with standard Python, the high index is not
|
||||||
|
included, however, it is the \emph{leftmost} index in this
|
||||||
|
case. As in standard Python, this takes care of one-off
|
||||||
|
issues in many practical cases: in particular,
|
||||||
|
\code{bv[\var{i}:]} returns \var{i} bits;
|
||||||
|
\code{bv[\var{i}:\var{j}]} has \code{\var{i}-\var{j}}
|
||||||
|
bits. As \class{intbv} objects have an undefined bit width,
|
||||||
|
the high index \var{j} has no default value and cannot be
|
||||||
|
ommitted, while the low index \var{j} defaults to \code{0}.
|
||||||
|
|
||||||
\item[(3)] positive return
|
\item[(3)] The value returned from a slicing operation is always
|
||||||
|
positive; higher order bits are implicitly assumed to be
|
||||||
|
zero.
|
||||||
|
|
||||||
\item[(4)] value check
|
\item[(4)] In setting a slice, it is checked whether the slice is wide
|
||||||
|
enough to accept all significant bits of the value.
|
||||||
|
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
143
doc/tools/toc2bkm.py
Executable file
143
doc/tools/toc2bkm.py
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
|
||||||
|
"""Convert a LaTeX .toc file to some PDFTeX magic to create that neat outline.
|
||||||
|
|
||||||
|
The output file has an extension of '.bkm' instead of '.out', since hyperref
|
||||||
|
already uses that extension.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import getopt
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# Ench item in an entry is a tuple of:
|
||||||
|
#
|
||||||
|
# Section #, Title String, Page #, List of Sub-entries
|
||||||
|
#
|
||||||
|
# The return value of parse_toc() is such a tuple.
|
||||||
|
|
||||||
|
cline_re = r"""^
|
||||||
|
\\contentsline\ \{([a-z]*)} # type of section in $1
|
||||||
|
\{(?:\\numberline\ \{([0-9.A-Z]+)})? # section number
|
||||||
|
(.*)} # title string
|
||||||
|
\{(\d+)}$""" # page number
|
||||||
|
|
||||||
|
cline_rx = re.compile(cline_re, re.VERBOSE)
|
||||||
|
|
||||||
|
OUTER_TO_INNER = -1
|
||||||
|
|
||||||
|
_transition_map = {
|
||||||
|
('chapter', 'section'): OUTER_TO_INNER,
|
||||||
|
('section', 'subsection'): OUTER_TO_INNER,
|
||||||
|
('subsection', 'subsubsection'): OUTER_TO_INNER,
|
||||||
|
('subsubsection', 'subsection'): 1,
|
||||||
|
('subsection', 'section'): 1,
|
||||||
|
('section', 'chapter'): 1,
|
||||||
|
('subsection', 'chapter'): 2,
|
||||||
|
('subsubsection', 'section'): 2,
|
||||||
|
('subsubsection', 'chapter'): 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
INCLUDED_LEVELS = ("chapter", "section", "subsection", "subsubsection")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_toc(fp, bigpart=None):
|
||||||
|
toc = top = []
|
||||||
|
stack = [toc]
|
||||||
|
level = bigpart or 'chapter'
|
||||||
|
lineno = 0
|
||||||
|
while 1:
|
||||||
|
line = fp.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
lineno = lineno + 1
|
||||||
|
m = cline_rx.match(line)
|
||||||
|
if m:
|
||||||
|
stype, snum, title, pageno = m.group(1, 2, 3, 4)
|
||||||
|
title = clean_title(title)
|
||||||
|
entry = (stype, snum, title, string.atoi(pageno), [])
|
||||||
|
if stype == level:
|
||||||
|
toc.append(entry)
|
||||||
|
else:
|
||||||
|
if stype not in INCLUDED_LEVELS:
|
||||||
|
# we don't want paragraphs & subparagraphs
|
||||||
|
continue
|
||||||
|
direction = _transition_map[(level, stype)]
|
||||||
|
if direction == OUTER_TO_INNER:
|
||||||
|
toc = toc[-1][-1]
|
||||||
|
stack.insert(0, toc)
|
||||||
|
toc.append(entry)
|
||||||
|
else:
|
||||||
|
for i in range(direction):
|
||||||
|
del stack[0]
|
||||||
|
toc = stack[0]
|
||||||
|
toc.append(entry)
|
||||||
|
level = stype
|
||||||
|
else:
|
||||||
|
sys.stderr.write("l.%s: " + line)
|
||||||
|
return top
|
||||||
|
|
||||||
|
|
||||||
|
hackscore_rx = re.compile(r"\\hackscore\s*{[^}]*}")
|
||||||
|
raisebox_rx = re.compile(r"\\raisebox\s*{[^}]*}")
|
||||||
|
title_rx = re.compile(r"\\([a-zA-Z])+\s+")
|
||||||
|
title_trans = string.maketrans("", "")
|
||||||
|
|
||||||
|
def clean_title(title):
|
||||||
|
title = raisebox_rx.sub("", title)
|
||||||
|
title = hackscore_rx.sub(r"\\_", title)
|
||||||
|
pos = 0
|
||||||
|
while 1:
|
||||||
|
m = title_rx.search(title, pos)
|
||||||
|
if m:
|
||||||
|
start = m.start()
|
||||||
|
if title[start:start+15] != "\\textunderscore":
|
||||||
|
title = title[:start] + title[m.end():]
|
||||||
|
pos = start + 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
title = string.translate(title, title_trans, "{}")
|
||||||
|
return title
|
||||||
|
|
||||||
|
|
||||||
|
def write_toc(toc, fp):
|
||||||
|
for entry in toc:
|
||||||
|
write_toc_entry(entry, fp, 0)
|
||||||
|
|
||||||
|
def write_toc_entry(entry, fp, layer):
|
||||||
|
stype, snum, title, pageno, toc = entry
|
||||||
|
s = "\\pdfoutline goto name{page%03d}" % pageno
|
||||||
|
if toc:
|
||||||
|
s = "%s count -%d" % (s, len(toc))
|
||||||
|
if snum:
|
||||||
|
title = "%s %s" % (snum, title)
|
||||||
|
s = "%s {%s}\n" % (s, title)
|
||||||
|
fp.write(s)
|
||||||
|
for entry in toc:
|
||||||
|
write_toc_entry(entry, fp, layer + 1)
|
||||||
|
|
||||||
|
|
||||||
|
def process(ifn, ofn, bigpart=None):
|
||||||
|
toc = parse_toc(open(ifn), bigpart)
|
||||||
|
write_toc(toc, open(ofn, "w"))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bigpart = None
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "c:")
|
||||||
|
if opts:
|
||||||
|
bigpart = opts[0][1]
|
||||||
|
if not args:
|
||||||
|
usage()
|
||||||
|
sys.exit(2)
|
||||||
|
for filename in args:
|
||||||
|
base, ext = os.path.splitext(filename)
|
||||||
|
ext = ext or ".toc"
|
||||||
|
process(base + ext, base + ".bkm", bigpart)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
x
Reference in New Issue
Block a user