iverilog/vvp
steve 5b89249f10 Add the hello example program. 2001-03-18 04:37:35 +00:00
..
examples Add the hello example program. 2001-03-18 04:37:35 +00:00
.cvsignore Functor values and propagation. 2001-03-11 22:42:11 +00:00
Makefile.in Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
README.txt Copyright notice. 2001-03-14 19:26:15 +00:00
codes.cc Compact the vvp_code_s structure. 2001-03-11 23:06:49 +00:00
codes.h Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
compile.cc Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
compile.h Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
config.guess Add the vvp engine to cvs. 2001-03-11 00:29:38 +00:00
config.h.in Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
config.sub Add the vvp engine to cvs. 2001-03-11 00:29:38 +00:00
configure.in Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
draw_tt.c Functor values and propagation. 2001-03-11 22:42:11 +00:00
functor.cc Functor values and propagation. 2001-03-11 22:42:11 +00:00
functor.h Functor values and propagation. 2001-03-11 22:42:11 +00:00
functor.txt Functor values and propagation. 2001-03-11 22:42:11 +00:00
install-sh Add the vvp engine to cvs. 2001-03-11 00:29:38 +00:00
ivl_dlfcn.h Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
lexor.lex Add support for vpi scopes. 2001-03-18 00:37:55 +00:00
main.cc Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
opcodes.txt Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
parse.y Accept empty statements. 2001-03-18 04:37:16 +00:00
parse_misc.cc Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
parse_misc.h Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
pointers.h Add the vvp engine to cvs. 2001-03-11 00:29:38 +00:00
schedule.cc Functor values and propagation. 2001-03-11 22:42:11 +00:00
schedule.h Functor values and propagation. 2001-03-11 22:42:11 +00:00
symbols.cc Add support for vpi scopes. 2001-03-18 00:37:55 +00:00
symbols.h Add support for vpi scopes. 2001-03-18 00:37:55 +00:00
vpi.txt Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
vpi_const.cc Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
vpi_iter.cc Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
vpi_mcd.cc Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
vpi_modules.cc Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
vpi_priv.cc Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
vpi_priv.h Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
vpi_scope.cc Add support for vpi scopes. 2001-03-18 00:37:55 +00:00
vpi_tasks.cc Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
vthread.cc Add structures for VPI support, and all the %vpi_call 2001-03-16 01:44:34 +00:00
vthread.h Add the vvp engine to cvs. 2001-03-11 00:29:38 +00:00
vthread.txt Thread details 2001-03-14 19:26:40 +00:00

README.txt

/*
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
 *
 *  $Id: README.txt,v 1.4 2001/03/14 19:26:15 steve Exp $
 */

VVP SIMULATION ENGINE

The VVP simulator takes as input source code not unlike assembly
language for a conventional processor. It is intended to be machine
generated code emitted by other tools, including the Icarus Verilog
compiler, so the syntax, though readable, is not necessarily
convenient for humans.


GENERAL FORMAT

The source file is a collection of statements. Each statement may have
a label, an opcode, and operands that depend on the opcode. For some
opcodes, the label is optional (or meaningless) and for others it is
required.

Every statement is terminated by a semicolon. The semicolon is also
the start of a comment line, so you can put comment text after the
semicolon that terminates a statement. Like so:

	Label .functor and, 0x5a, x, y  ; This is a comment.

The semicolon is required, whether the comment is there or not.

Statements may span multiple lines, as long as there is no text (other
then the first character of a label) in the first column of hte
continuation line.


LABELS AND SYMBOLS

Labels and symbols consist of the characters:

	a-z
	A-Z
	0-9
	.$_

Labels and symbols may not start with a digit or a '.', so that they
are easily distinguished from keywords and numbers. A Label is a
symbol that starts a statement. If a label is present in a statement,
it must start in the first text column. This is how the lexical
analyzer distinguishes a label from a symbol. If a symbol is present
in a statement, it is in the operand. Opcodes of statements must be a
keyword.

Symbols are references to labels. It is not necessary for a label to
be declared before its use in a symbol, but it must be declared
eventually.


FUNCTOR STATEMENTS:

A functor statement is a statement that uses the ``.functor''
opcode. Functors are the basic structural units of a simulation, and
include a type (in the form of a truth table) and up to four inputs. A
label is required for functors.

The general syntax of a functor is:

	<label> .functor <type>, <init> [, symbol_list]

The symbol list is 0-4 names of labels of other functors. These
connect inputs of the functor of the statement to the output of other
functors. The type is the label of a .ftype statement elsewhere in the
program. The references .ftype describes the behavoir of the
functor.

The <init> value is the 8-bit initial value of the 4 input ports. The
LSB is port 0, and the MSB port 3.

Almost all of the structural aspects of a simulation can be
represented by functors, which perform the very basic task of
combining up to four inputs down to one output.

VARIABLE STATEMENTS:

A variable is a bit that can be written by behavioral code (so has no
structural input) and propagates its output to a functor. The general
syntax of a variable is:

	<label> .var

A variable does not take inputs, since its value is set behaviorally
by assignment events. It does have an output, though, and its output
is propagated into the net of functors in the usual way.

Therefore, the .var statement implicitly also creates a .functor of
the same name as the variable. It is in fact the functor that
behavioral code reads when the value of the variable (or net) is read
by behavioral code.

The variable .functor implicitly has three inputs. The first is the
value that gets set by assignments or procedural continuous
assignments. The second is a forced value that can be connected to a
force expression (as a functor) when a value is being forced. And the
third input selects the source to use. The default is to select the
assignment input.

Note that nets in a design do not necessarily have a specific functor
or object allocated to them. Nets are just something that behavioral
code can read, so it is enough to give to the behavioral code the
vvp_ipoint_t object of the .functor that drives the net.


THREAD STATEMENTS:

Thread statements create the initial threads for a simulation. These
represent the initial and always blocks, and possibly other causes to
create threads at startup.

	.thread <symbol>

This statement creates a thread with a starting address at the
instruction given by <symbol>.


TRUTH TABLES

The logic that a functor represents is expressed as a truth table. The
functor has four inputs and one output. Each input and output has one
of four possible values (0, 1, x and z) so two bits are needed to
represent them. So the input of the functor is 8 bits, and the output
2 bits. A complete lookup table for generating the 2-bit output from
an 8-bit input is 512 bits. That can be packed into 64 bytes. This is
small enough that the table should take less space then the code to
implement the logic.

To implement the truth table, we need to assign 2-bit encodings for
the 4-value signals. I choose, pseudo-randomly, the following
encoding:

	1'b0  : 00
	1'b1  : 01
	1'bx  : 10
	1'bz  : 11

The table is an array of 64 bytes, each byte holding 4 2-bit
outputs. Construct a 6-bit byte address with inputs 1, 2 and 3 like
so:
	 332211

The input 0 2-bits can then be used to select which of the 4 2-bit
pairs in the 8-bit byte are the output:

	MSB -> zzxx1100 <- LSB

A complete truth table, then is described as 64 8-bit bytes.

The vvp engine includes truth tables for the primitive gate types, so
none needs to be given by the programmer. It is sufficient to name the
type to get that truth table.


EXECUTABLE INSTRUCTIONS

Threads run executable code, much like a processor executes machine
code. VVP has a variety of opcodes for executable instructions. All of
those instructions start with '%' and go into a single address
space. Labels attached to executable instructions get assigned the
address of the instruction, and can be the target of %jmp instructions
and starting points for threads.

The opcodes.txt file has a more detailed description of all the
various instructions.


THE RELATIONSHIP BETWEEN FUNCTORS, THREADS AND EVENTS

Given the above summary of the major components of vvp, some
description of their relationship is warrented. Functors provide a
structural description of the design (so far as it can be described
structurally) and these functors run independently of the threads. In
particular, when an input to a functor is set, it calculates a new
output value; and if that output is different from the existing
output, a propagation event is created. Functor output is calculated
by truth table lookup, without the aid of threads.

Propagation events are one of three kinds of events in vvp. They are
scheduled to execute at some time, and they simply point to the functor
that is to have its output propagated. When the event expires, the
output of the referenced functor is propagated to all the inputs that
it is connected to, and those functors in turn create new events if
needed.

Assignment events (the second of three types of events) are created
by non-blocking assignments in behavioral code. When the ``<='' is
executed (a %assign in vvp) an assign event is created, which includes
the vvp_ipoint_t pointer to the functor input to receive the value,
as well as the value. These are distinct from propagation events because:

	a) There is no functor that has as its output the value to be
	   assigned (this is how values get into the functor net in
	   the first place), and

	b) This allows for behavioral code to create waveforms of
	   arbitrary length that feed into a variable. Verilog allows
	   this of non-blocking assignments, but not of gate outputs.

The last type of event is the thread schedule event. This event simply
points to a thread to be executed. Threads are made up of a virtual
processor with a program counter and some private storage. Threads
can execute %assign instructions to create assignment events, and can
execute %set instructions to do blocking assignments. Threads can also
use %load to read the output of functors.

The core event scheduler takes these three kinds of events and calls
the right kind of code to cause things to happen in the design. If the
event is a propagate or assignment event, the network of functors is
tickled; if the event is a thread schedule, then a thread is run. The
implementation of the event queue is not important, but currently is
implemented as a ``skip list''. That is, it is a sorted singly linked
list with skip pointers that skip over delta-time events.

The functor net and the threads are distinct. They communicate through
thread instructions %set, %assign, %waitfor and %load. So far as a thread
is concerned, the functor net is a blob of structure that it pokes and
prods via certain functor access instructions.


HOW TO GET FROM THERE TO HERE

The vvp simulation engine is designed to be able to take as input a
compiled form of Verilog. That implies that there is a compiler that
compiles Verilog into a form that the vvp engine can read.


* Boolean logic gates

Gates like AND, OR and NAND are implemented simply and obviously by
functor statements. Any logic up to 4 inputs can be implemented with a
single functor. For example:

	and gate (out, i1, i2, i3);

becomes:

	gate	.functor and, i1, i2, i3;

Notice the first parameter of the .functor is the type. The type
includes a truth table that describes the output with a given
input. If the gate is wider then four inputs, then cascade
functors. For example:

	and gate (out, i1, i2, i3, i4, i5, i6, i7, i8);

becomes:

	gate.0	.functor and, i1, i2, i3, i4;
	gate.1	.functor and, i5, i6, i7, i8;
	gate	.functor and, gate.0, gate.1;


* reg and other variables

Reg and integer are cases of what Verilog calls ``variables.''
Variables are, simply put, things that behavioral code can assign
to. These are not the same as ``nets,'' which include wires and the
like.

Each bit of a variable is created by a ``.var'' statement. For example:

	reg a;

becomes:

	a	.var;

/*
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */