Add the vvp engine to cvs.

This commit is contained in:
steve 2001-03-11 00:29:38 +00:00
parent debe707097
commit cb65ee5e00
29 changed files with 4769 additions and 1 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.91 2001/02/10 20:29:39 steve Exp $"
#ident "$Id: Makefile.in,v 1.92 2001/03/11 00:29:38 steve Exp $"
#
#
SHELL = /bin/sh
@ -27,6 +27,8 @@ prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
SUBDIRS = @subdirs@
VPATH = $(srcdir)
bindir = @bindir@

View File

@ -148,5 +148,6 @@ AC_SUBST(shared)
AC_MSG_RESULT($shared)
AC_CONFIG_SUBDIRS(vvp)
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)

11
vvp/.cvsignore Normal file
View File

@ -0,0 +1,11 @@
configure
config.log
config.status
config.h
dep
Makefile
lexor.cc
parse.cc
parse.cc.output
parse.h
vvp

79
vvp/Makefile.in Normal file
View File

@ -0,0 +1,79 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library 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 Library General Public License for more details.
#
# You should have received a copy of the GNU Library 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
#
#ident "$Id: Makefile.in,v 1.1 2001/03/11 00:29:38 steve Exp $"
#
#
SHELL = /bin/sh
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
CC = @CC@
CXX = @CXX@ -Wall
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
STRIP = @STRIP@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)
LDFLAGS = @LDFLAGS@
all: vvp
clean:
rm -rf vvp *.o *~ parse.cc parse.cc.output parse.h lexor.cc dep
distclean: clean
rm -f config.h Makefile config.cache config.log config.status
O = main.o parse.o parse_misc.o lexor.o compile.o functor.o symbols.o \
codes.o vthread.o schedule.o
vvp: $O
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o vvp $O
%.o: %.cc
@[ -d dep ] || mkdir dep
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
mv $*.d dep/$*.d
lexor.o: lexor.cc parse.h
parse.o: parse.cc
parse.h parse.cc: $(srcdir)/parse.y
bison --verbose -t -d $(srcdir)/parse.y -o parse.cc
mv parse.cc.h parse.h
lexor.cc: $(srcdir)/lexor.lex
flex -s -olexor.cc $(srcdir)/lexor.lex
-include $(patsubst %.o, dep/%.d, $O)

170
vvp/README.txt Normal file
View File

@ -0,0 +1,170 @@
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, 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> [, 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.
Almost all of the structural aspects of a simulation can be
represented by functors.
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>.
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.
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;

123
vvp/codes.cc Normal file
View File

@ -0,0 +1,123 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: codes.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include "codes.h"
# include <string.h>
# include <assert.h>
const unsigned code_index0_size = 2 << 9;
const unsigned code_index1_size = 2 << 11;
const unsigned code_index2_size = 2 << 10;
struct code_index0 {
struct vvp_code_s table[code_index0_size];
};
struct code_index1 {
struct code_index0* table[code_index1_size];
};
static vvp_cpoint_t code_count = 0;
static struct code_index1*code_table[code_index2_size] = { 0 };
void codespace_init(void)
{
code_table[0] = 0;
code_count = 1;
}
vvp_cpoint_t codespace_allocate(void)
{
vvp_cpoint_t idx = code_count;
idx /= code_index0_size;
unsigned index1 = idx % code_index1_size;
idx /= code_index1_size;
assert(idx < code_index2_size);
if (code_table[idx] == 0) {
code_table[idx] = new struct code_index1;
memset(code_table[idx], 0, sizeof code_table[idx]);
}
if (code_table[idx]->table[index1] == 0) {
code_table[idx]->table[index1] = new struct code_index0;
memset(code_table[idx]->table[index1],
0, sizeof(struct code_index0));
}
vvp_cpoint_t res = code_count;
code_count += 1;
return res;
}
vvp_code_t codespace_index(vvp_cpoint_t point)
{
assert(point < code_count);
unsigned index0 = point % code_index0_size;
point /= code_index0_size;
unsigned index1 = point % code_index1_size;
point /= code_index1_size;
return code_table[point]->table[index1]->table + index0;
}
void codespace_dump(FILE*fd)
{
for (unsigned idx = 0 ; idx < code_count ; idx += 1) {
fprintf(fd, " %8x: ", idx);
vvp_code_t cop = codespace_index(idx);
if (cop->opcode == &of_ASSIGN) {
fprintf(fd, "%%assign 0x%u, %lu, %u\n",
cop->iptr, cop->number, cop->bit_idx);
} else if (cop->opcode == &of_DELAY) {
fprintf(fd, "%%delay %lu\n", cop->number);
} else if (cop->opcode == &of_END) {
fprintf(fd, "%%end\n");
} else if (cop->opcode == &of_SET) {
fprintf(fd, "%%set 0x%lu, %u\n",
cop->iptr, cop->bit_idx);
} else {
fprintf(fd, "opcode %p\n", cop->opcode);
}
}
}
/*
* $Log: codes.cc,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/

88
vvp/codes.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef __codes_H
#define __codes_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: codes.h,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include "pointers.h"
# include "vthread.h"
# include <stdio.h>
typedef struct vvp_code_s *vvp_code_t;
typedef bool (*vvp_code_fun)(vthread_t thr, vvp_code_t code);
/*
* These functions are implementations of executable op-codes. The
* implementation lives in the vthread.cc file so that they have
* access to the thread context.
*/
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_SET(vthread_t thr, vvp_code_t code);
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
/*
* This is the format of a machine code instruction.
*/
struct vvp_code_s {
vvp_code_fun opcode;
unsigned short bit_idx;
unsigned long number;
union {
vvp_ipoint_t iptr;
vvp_cpoint_t cptr;
};
};
/*
* This function clears the code space, ready for initialization. This
* needs to be done exactly once before any instructions are created.
*/
extern void codespace_init(void);
/*
* This function returns a pointer to the next free instruction in the
* code address space.
*/
extern vvp_cpoint_t codespace_allocate(void);
/*
* Return a pointer to the indexed instruction in the codespace. The
* ptr must be a value returned from codespace_allocate. The compiler
* can use this to get a handle on the instruction to be created, and
* the runtime uses this to get the instruction addressed by the PC or
* by a branch instruction.
*/
extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
extern void codespace_dump(FILE*fd);
/*
* $Log: codes.h,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/
#endif

360
vvp/compile.cc Normal file
View File

@ -0,0 +1,360 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: compile.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include "compile.h"
# include "functor.h"
# include "symbols.h"
# include "codes.h"
# include "schedule.h"
# include "vthread.h"
# include "parse_misc.h"
# include <malloc.h>
# include <stdlib.h>
# include <assert.h>
/*
* The opcode table lists all the code mnemonics, along with their
* opcode and operand types. The table is written sorted by mnemonic
* so that it can be searched by binary search. The opcode_compare
* function is a helper function for that lookup.
*/
enum operand_e {
/* Place holder for unused operand */
OA_NONE,
/* The operand is a number, an immediate unsigned long integer */
OA_NUMBER,
/* The operand is a thread bit index */
OA_BIT,
/* The operand is a pointer to code space */
OA_CODE_PTR,
/* The operand is a variable or net pointer */
OA_FUNC_PTR
};
struct opcode_table_s {
const char*mnemonic;
vvp_code_fun opcode;
unsigned argc;
enum operand_e argt[OPERAND_MAX];
};
const static struct opcode_table_s opcode_table[] = {
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_NUMBER, OA_BIT} },
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT, OA_NONE} },
{ 0, of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }
};
static unsigned opcode_count = 0;
static int opcode_compare(const void*k, const void*r)
{
const char*kp = (const char*)k;
const struct opcode_table_s*rp = (const struct opcode_table_s*)r;
return strcmp(kp, rp->mnemonic);
}
/*
* Keep a symbol table of addresses within code space. Labels on
* executable opcodes are mapped to their address here.
*/
static symbol_table_t sym_codespace = 0;
/*
* Keep a symbol table of functors mentioned in the source. This table
* is used to resolve references as they come.
*/
static symbol_table_t sym_functors = 0;
/*
* If a functor parameter makes a forward reference to a functor, then
* I need to save that reference and resolve it after the functors are
* created. Use this structure to keep the unresolved references in an
* unsorted singly linked list.
*/
struct resolv_list_s {
struct resolv_list_s*next;
vvp_ipoint_t port;
char*source;
};
static struct resolv_list_s*resolv_list = 0;
/*
* Initialize the compiler by allocation empty symbol tables and
* initializing the various address spaces.
*/
void compile_init(void)
{
sym_functors = new_symbol_table();
functor_init();
sym_codespace = new_symbol_table();
codespace_init();
opcode_count = 0;
while (opcode_table[opcode_count].mnemonic)
opcode_count += 1;
}
/*
* The parser calls this function to create a functor. I allocate a
* functor, and map the name to the vvp_ipoint_t address for the
* functor. Also resolve the inputs to the functor.
*/
void compile_functor(char*label, char*type, unsigned argc, char**argv)
{
vvp_ipoint_t fdx = functor_allocate();
functor_t obj = functor_index(fdx);
sym_set_value(sym_functors, label, fdx);
assert(argc <= 4);
/* Run through the arguments looking for the functors that are
connected to my input ports. For each source functor that I
find, connect the output of that functor to the indexed
input by inserting myself (complete with the port number in
the vvp_ipoint_t) into the list that the source heads.
If the source functor is not declared yet, then don't do
the link yet. Save the reference to be resolved later. */
for (unsigned idx = 0 ; idx < argc ; idx += 1) {
vvp_ipoint_t tmp = sym_get_value(sym_functors, argv[idx]);
if (tmp) {
functor_t fport = functor_index(tmp);
obj->port[idx] = fport->out;
fport->out = ipoint_make(fdx, idx);
free(argv[idx]);
} else {
struct resolv_list_s*res = (struct resolv_list_s*)
calloc(1, sizeof(struct resolv_list_s));
res->port = ipoint_make(fdx, idx);
res->source = argv[idx];
res->next = resolv_list;
resolv_list = res;
}
}
free(argv);
free(label);
free(type);
}
/*
* The parser uses this function to compile an link an executable
* opcode. I do this by looking up the opcode in the opcode_table. The
* table gives the operand structure that is acceptible, so I can
* process the operands here as well.
*/
void compile_code(char*label, char*mnem, comp_operands_t opa)
{
vvp_cpoint_t ptr = codespace_allocate();
/* First, I can give the label a value that is the current
codespace pointer. Don't need the text of the label after
this is done. */
if (label) {
sym_set_value(sym_codespace, label, ptr);
free(label);
}
/* Lookup the opcode in the opcode table. */
struct opcode_table_s*op = (struct opcode_table_s*)
bsearch(mnem, opcode_table, opcode_count,
sizeof(struct opcode_table_s), &opcode_compare);
if (op == 0) {
yyerror("Invalid opcode");
return;
}
assert(op);
/* Build up the code from the information about the opcode and
the information from the comiler. */
vvp_code_t code = codespace_index(ptr);
code->opcode = op->opcode;
if (op->argc != (opa? opa->argc : 0)) {
yyerror("operand count");
return;
}
/* Pull the operands that the instruction expects from the
list that the parser supplied. */
for (unsigned idx = 0 ; idx < op->argc ; idx += 1) {
switch (op->argt[idx]) {
case OA_NONE:
break;
case OA_BIT:
if (opa->argv[idx].ltype != L_NUMB) {
yyerror("operand format");
break;
}
code->bit_idx = opa->argv[idx].numb;
break;
case OA_CODE_PTR:
if (opa->argv[idx].ltype != L_TEXT) {
yyerror("operand format");
break;
}
code->cptr = sym_get_value(sym_codespace,
opa->argv[idx].text);
if (code->cptr == 0) {
yyerror("functor undefined");
break;
}
free(opa->argv[idx].text);
break;
case OA_FUNC_PTR:
if (opa->argv[idx].ltype != L_TEXT) {
yyerror("operand format");
break;
}
code->iptr = sym_get_value(sym_functors,
opa->argv[idx].text);
if (code->iptr == 0) {
yyerror("functor undefined");
break;
}
free(opa->argv[idx].text);
break;
case OA_NUMBER:
if (opa->argv[idx].ltype != L_NUMB) {
yyerror("operand format");
break;
}
code->number = opa->argv[idx].numb;
break;
}
}
if (opa) free(opa);
free(mnem);
}
/*
* When the parser finds a thread statement, I create a new thread
* with the start address referenced by the program symbol passed to
* me.
*/
void compile_thread(char*start_sym)
{
vvp_cpoint_t pc = sym_get_value(sym_codespace, start_sym);
if (pc == 0) {
yyerror("unresolved address");
return;
}
vthread_t thr = v_newthread(pc);
schedule_vthread(thr, 0);
free(start_sym);
}
/*
* A variable is a special functor, so we allocate that functor and
* write the label into the symbol table.
*/
void compile_variable(char*label)
{
vvp_ipoint_t fdx = functor_allocate();
functor_t obj = functor_index(fdx);
sym_set_value(sym_functors, label, fdx);
free(label);
}
void compile_cleanup(void)
{
struct resolv_list_s*tmp_list = resolv_list;
resolv_list = 0;
while (tmp_list) {
struct resolv_list_s*res = tmp_list;
tmp_list = res->next;
functor_t obj = functor_index(res->port);
unsigned idx = ipoint_port(res->port);
vvp_ipoint_t tmp = sym_get_value(sym_functors, res->source);
if (tmp != 0) {
functor_t fport = functor_index(tmp);
obj->port[idx] = fport->out;
fport->out = res->port;
free(res->source);
free(res);
} else {
/* Still not resolved. put back into the list. */
res->next = resolv_list;
resolv_list = res;
}
}
}
void compile_dump(FILE*fd)
{
fprintf(fd, "FUNCTOR SYMBOL TABLE:\n");
sym_dump(sym_functors, fd);
fprintf(fd, "FUNCTORS:\n");
functor_dump(fd);
fprintf(fd, "UNRESOLVED PORT INPUTS:\n");
for (struct resolv_list_s*cur = resolv_list ; cur ; cur = cur->next)
fprintf(fd, " %p: %s\n", cur->port, cur->source);
fprintf(fd, "CODE SPACE SYMBOL TABLE:\n");
sym_dump(sym_codespace, fd);
fprintf(fd, "CODE SPACE DISASSEMBLY:\n");
codespace_dump(fd);
}
/*
* $Log: compile.cc,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/

104
vvp/compile.h Normal file
View File

@ -0,0 +1,104 @@
#ifndef __compile_H
#define __compile_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: compile.h,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include <stdio.h>
/*
* The functions described here are the compile time support
* functions. Various bits of the compile process are taken care of
* here. What is called when is mostly controlled by the parser.
*
* Before compilation takes place, the compile_init function must be
* called once to set stuff up.
*/
extern void compile_init(void);
extern void compile_cleanup(void);
/*
* This function is called by the parser to compile a functor
* statement. The strings passed in are allocated by the lexor, but
* this function will free them. (Or save them permanently.) This
* includes the argv array and the strings it references.
*
* The argc and argv are a list of char* that are the port paramters
* of the functor. The compile should match those port parameters up
* to existing functors to manage the linking.
*/
extern void compile_functor(char*label, char*type,
unsigned argc, char**argv);
/*
* A code statement is a label, an opcode and up to 3 operands. There
* are a few lexical types that the parser recognizes of the operands,
* given by the ltype_e enumeration. The compile_code function takes
* the label, mnemonic and parsed operands and writes a properly
* formed instruction into the code space. The label is set into the
* symbol table with the address of the instruction.
*/
#define OPERAND_MAX 3
enum ltype_e { L_NUMB, L_TEXT };
struct comp_operands_s {
unsigned argc;
struct {
enum ltype_e ltype;
union {
unsigned long numb;
char*text;
};
} argv[OPERAND_MAX];
};
typedef struct comp_operands_s*comp_operands_t;
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
/*
* The parser uses this function to declare a thread. The start_sym is
* the start instruction, and must already be defined.
*/
extern void compile_thread(char*start_sym);
/*
* This function is called to create a var bit with the given name.
*/
extern void compile_variable(char*label);
/*
* This is a diagnostic aid. Dump all the compiler tables to the file
* descriptor in a readable form.
*/
extern void compile_dump(FILE*fd);
/*
* $Log: compile.h,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/
#endif

912
vvp/config.guess vendored Executable file
View File

@ -0,0 +1,912 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# 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.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit system type (host/target name).
#
# Only a few systems have been added to this list; please add others
# (but try to keep the structure clean).
#
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
alpha:OSF1:*:*)
if test $UNAME_RELEASE = "V4.0"; then
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
fi
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
cat <<EOF >dummy.s
.globl main
.ent main
main:
.frame \$30,0,\$26,0
.prologue 0
.long 0x47e03d80 # implver $0
lda \$2,259
.long 0x47e20c21 # amask $2,$1
srl \$1,8,\$2
sll \$2,2,\$2
sll \$0,3,\$0
addl \$1,\$0,\$0
addl \$2,\$0,\$0
ret \$31,(\$26),1
.end main
EOF
${CC-cc} dummy.s -o dummy 2>/dev/null
if test "$?" = 0 ; then
./dummy
case "$?" in
7)
UNAME_MACHINE="alpha"
;;
15)
UNAME_MACHINE="alphaev5"
;;
14)
UNAME_MACHINE="alphaev56"
;;
10)
UNAME_MACHINE="alphapca56"
;;
16)
UNAME_MACHINE="alphaev6"
;;
esac
fi
rm -f dummy.s dummy
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit 0 ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-cbm-sysv4
exit 0;;
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
arc64:OpenBSD:*:*)
echo mips64el-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
arc:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
hkmips:OpenBSD:*:*)
echo mips-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
pmax:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
sgi:OpenBSD:*:*)
echo mips-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
wgrisc:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
arm32:NetBSD:*:*)
echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
SR2?01:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit 0;;
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit 0 ;;
NILE:*:*:dcosx)
echo pyramid-pyramid-svr4
exit 0 ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
i86pc:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit 0 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit 0 ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit 0 ;;
atari*:NetBSD:*:*)
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mvme68k:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mvme88k:OpenBSD:*:*)
echo m88k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit 0 ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
2020:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit 0 ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
sed 's/^ //' << EOF >dummy.c
int main (argc, argv) int argc; char **argv; {
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
${CC-cc} dummy.c -o dummy \
&& ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
&& rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit 0 ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit 0 ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit 0 ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else echo i586-dg-dgux${UNAME_RELEASE}
fi
exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit 0 ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit 0 ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit 0 ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit 0 ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i?86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
sed 's/^ //' << EOF >dummy.c
#include <sys/systemcfg.h>
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit 0 ;;
*:AIX:*:4)
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=4.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit 0 ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit 0 ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit 0 ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit 0 ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit 0 ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
9000/[3478]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit 0 ;;
3050*:HI-UX:*:*)
sed 's/^ //' << EOF >dummy.c
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
i?86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit 0 ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit 0 ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit 0 ;;
CRAY*X-MP:*:*:*)
echo xmp-cray-unicos
exit 0 ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
exit 0 ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
F300:UNIX_System_V:*:*)
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit 0 ;;
F301:UNIX_System_V:*:*)
echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
hp300:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
i?86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
*:NetBSD:*:*)
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
i*:CYGWIN*:*)
echo i386-pc-cygwin32
exit 0 ;;
i*:MINGW*:*)
echo i386-pc-mingw32
exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin32
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
ld_supported_emulations=`echo $ld_help_string \
| sed -ne '/supported emulations:/!d
s/[ ][ ]*/ /g
s/.*supported emulations: *//
s/ .*//
p'`
case "$ld_supported_emulations" in
i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
elf32ppc)
# Determine Lib Version
cat >dummy.c <<EOF
#include <features.h>
#if defined(__GLIBC__)
extern char __libc_version[];
extern char __libc_release[];
#endif
main(argc, argv)
int argc;
char *argv[];
{
#if defined(__GLIBC__)
printf("%s %s\n", __libc_version, __libc_release);
#else
printf("unkown\n");
#endif
return 0;
}
EOF
LIBC=""
${CC-cc} dummy.c -o dummy 2>/dev/null
if test "$?" = 0 ; then
./dummy | grep 1\.99 > /dev/null
if test "$?" = 0 ; then
LIBC="libc1"
fi
fi
rm -f dummy.c dummy
echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
esac
if test "${UNAME_MACHINE}" = "alpha" ; then
sed 's/^ //' <<EOF >dummy.s
.globl main
.ent main
main:
.frame \$30,0,\$26,0
.prologue 0
.long 0x47e03d80 # implver $0
lda \$2,259
.long 0x47e20c21 # amask $2,$1
srl \$1,8,\$2
sll \$2,2,\$2
sll \$0,3,\$0
addl \$1,\$0,\$0
addl \$2,\$0,\$0
ret \$31,(\$26),1
.end main
EOF
LIBC=""
${CC-cc} dummy.s -o dummy 2>/dev/null
if test "$?" = 0 ; then
./dummy
case "$?" in
7)
UNAME_MACHINE="alpha"
;;
15)
UNAME_MACHINE="alphaev5"
;;
14)
UNAME_MACHINE="alphaev56"
;;
10)
UNAME_MACHINE="alphapca56"
;;
16)
UNAME_MACHINE="alphaev6"
;;
esac
objdump --private-headers dummy | \
grep ld.so.1 > /dev/null
if test "$?" = 0 ; then
LIBC="libc1"
fi
fi
rm -f dummy.s dummy
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
elif test "${UNAME_MACHINE}" = "mips" ; then
cat >dummy.c <<EOF
main(argc, argv)
int argc;
char *argv[];
{
#ifdef __MIPSEB__
printf ("%s-unknown-linux-gnu\n", argv[1]);
#endif
#ifdef __MIPSEL__
printf ("%sel-unknown-linux-gnu\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
else
# Either a pre-BFD a.out linker (linux-gnuoldld)
# or one that does not give us useful --help.
# GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
# If ld does not provide *any* "supported emulations:"
# that means it is gnuoldld.
echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
case "${UNAME_MACHINE}" in
i?86)
VENDOR=pc;
;;
*)
VENDOR=unknown;
;;
esac
# Determine whether the default compiler is a.out or elf
cat >dummy.c <<EOF
#include <features.h>
main(argc, argv)
int argc;
char *argv[];
{
#ifdef __ELF__
# ifdef __GLIBC__
# if __GLIBC__ >= 2
printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
# else
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
# endif
# else
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
# endif
#else
printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
i?86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
i?86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit 0 ;;
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
fi
exit 0 ;;
i?86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit 0 ;;
pc:*:*:*)
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i386.
echo i386-pc-msdosdjgpp
exit 0 ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
exit 0 ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit 0 ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit 0 ;;
M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4.3${OS_REL} && exit 0
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
m68*:LynxOS:2.*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
i?86:LynxOS:2.*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit 0 ;;
PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit 0 ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit 0 ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
news*:NEWS-OS:*:6*)
echo mips-sony-newsos6
exit 0 ;;
R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
cat >dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
printf ("vax-dec-bsd\n"); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit 0 ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
c34*)
echo c34-convex-bsd
exit 0 ;;
c38*)
echo c38-convex-bsd
exit 0 ;;
c4*)
echo c4-convex-bsd
exit 0 ;;
esac
fi
#echo '(Unable to guess system type)' 1>&2
exit 1

35
vvp/config.h.in Normal file
View File

@ -0,0 +1,35 @@
#ifndef __config_H
#define __config_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: config.h.in,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# define SIZEOF_UNSIGNED_LONG 0
# define SIZEOF_UNSIGNED 0
/*
* $Log: config.h.in,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/
#endif

1178
vvp/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

13
vvp/configure.in Normal file
View File

@ -0,0 +1,13 @@
AC_INIT(Makefile.in)
AC_CONFIG_HEADER(config.h)
AC_PROG_CC
AC_PROG_CXX
AC_CHECK_TOOL(STRIP, strip, true)
AC_PROG_INSTALL
AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(unsigned)
AC_OUTPUT(Makefile)

132
vvp/functor.cc Normal file
View File

@ -0,0 +1,132 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: functor.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include "functor.h"
# include <assert.h>
/*
* Functors are created as the source design is read in. Each is
* assigned an ipoint_t address starting from 1. The design is
* expected to have a create many functors, so it makes sense to
* allocate the functors in chunks. This structure describes a chunk
* of functors.
*
* The 32bit vvp_ipoint_t allows for 2**30 functors in the
* design. (2 bits are used to select the input of the functor.) The
* functor address is, for the purpose of lookup up addresses, divided
* into three parts, the index within a chunk, the index of the chunk
* within an index1 table, and the index of the index1 within the root
* table. There is a single root table. The index1 tables and chunk
* tables are allocated as needed.
*/
const unsigned functor_index0_size = 2 << 9;
const unsigned functor_index1_size = 2 << 11;
const unsigned functor_index2_size = 2 << 10;
struct functor_index0 {
struct functor_s table[functor_index0_size];
};
struct functor_index1 {
struct functor_index0* table[functor_index1_size];
};
static vvp_ipoint_t functor_count = 0;
static struct functor_index1*functor_table[functor_index2_size] = { 0 };
/*
* This function initializes the functor address space by creating the
* zero functor. This means creating a functor_index1 and a
* functor_index0, and initializing the count to 1.
*/
void functor_init(void)
{
functor_table[0] = new struct functor_index1;
functor_table[0]->table[0] = new struct functor_index0;
functor_count = 1;
}
/*
* Allocate normall is just a matter of incrementing the functor_count
* and returning a pointer to the next unallocated functor. However,
* if we overrun a chunk or an index, we need to allocate the needed
* bits first.
*/
vvp_ipoint_t functor_allocate(void)
{
vvp_ipoint_t idx = functor_count;
idx /= functor_index0_size;
unsigned index1 = idx % functor_index1_size;
idx /= functor_index1_size;
assert( idx < functor_index2_size);
if (functor_table[idx] == 0)
functor_table[idx] = new struct functor_index1;
if (functor_table[idx]->table[index1] == 0)
functor_table[idx]->table[index1] = new struct functor_index0;
vvp_ipoint_t res = functor_count;
functor_count += 1;
return res * 4;
}
functor_t functor_index(vvp_ipoint_t point)
{
point /= 4;
assert(point < functor_count);
assert(point > 0);
unsigned index0 = point % functor_index0_size;
point /= functor_index0_size;
unsigned index1 = point % functor_index1_size;
point /= functor_index1_size;
return functor_table[point]->table[index1]->table + index0;
}
void functor_dump(FILE*fd)
{
for (unsigned idx = 1 ; idx < functor_count ; idx += 1) {
functor_t cur = functor_index(idx*4);
fprintf(fd, "%10p: out=%x port={%x %x %x %x}\n", idx*4,
cur->out, cur->port[0], cur->port[1],
cur->port[2], cur->port[3]);
}
}
/*
* $Log: functor.cc,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/

87
vvp/functor.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef __functor_H
#define __functor_H
/*
* Copyright (c) 2000 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
*/
#if !defined(WINNT)
#ident "$Id: functor.h,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include "pointers.h"
# include <stdio.h>
typedef struct vvp_truth_s*vvp_truth_t;
/*
* The vvp_ipoint_t is an integral type that is 32bits. The low 2 bits
* select the port of the referenced functor, and the remaining 30
* index the functor itself. All together, the 32 bits can completely
* identify any input of any functor.
*
* Outputs of functors are the heads of a linked list of all the
* inputs that it is connected to. The vvp_ipoint_t in .out points to
* the first port in the list. The .port[x] in turn points to the next
* port, and so on. The last .port[x] contains the null vvp_ipoint_t
* value zero (0). In this way, an output can fan out as wide as the
* original design requires.
*/
struct functor_s {
/* This is the truth table for the device */
vvp_truth_t table;
/* This is the output for the device. */
vvp_ipoint_t out;
/* These are the input ports. */
vvp_ipoint_t port[4];
};
typedef struct functor_s *functor_t;
/*
* Initialize the functors address space. This function must be called
* exactly once before any of the other functor functions may be
* called.
*/
extern void functor_init(void);
/*
* This function allocates a functor and returns the vvp_ipoint_t
* address for it. Every call to functor_allocate is guaranteed to
* return a different vvp_ipoint_t address. The ipoint port bits are 0.
*/
extern vvp_ipoint_t functor_allocate(void);
/*
* Given an ipoint_t pointer, return a C pointer to the functor. This
* is like a pointer dereference. The point parameter must have been
* returned from a previous call to functor_allocate.
*/
extern functor_t functor_index(vvp_ipoint_t point);
/*
* Dump a readable version of the functor address space to the file.
*/
extern void functor_dump(FILE*fd);
/*
* $Log: functor.h,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/
#endif

238
vvp/install-sh Executable file
View File

@ -0,0 +1,238 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

62
vvp/lexor.lex Normal file
View File

@ -0,0 +1,62 @@
%{
# include "parse_misc.h"
# include "compile.h"
# include "parse.h"
# include <string.h>
%}
%%
/* A label is any non-blank text that appears left justified. */
^[.$_a-zA-Z][.$_a-zA-Z0-9]* {
yylval.text = strdup(yytext);
return T_LABEL; }
/* These are some keywords that are recognized. */
".functor" { return K_FUNCTOR; }
".thread" { return K_THREAD; }
".var" { return K_VAR; }
/* instructions start with a % character. The compiler decides what
kind of instruction this really is. */
"%"[.$_/a-zA-Z0-9]+ {
yylval.text = strdup(yytext);
return T_INSTR; }
[0-9][0-9]* {
yylval.numb = strtoul(yytext, 0, 0);
return T_NUMBER; }
"0x"[0-9a-fA-F]+ {
yylval.numb = strtoul(yytext, 0, 0);
return T_NUMBER; }
/* Symbols are pretty much what is left. They are used to refer to
labels so the rule must match a string that a label would match. */
[.$_a-zA-Z][.$_a-zA-Z0-9]* {
yylval.text = strdup(yytext);
return T_SYMBOL; }
/* Accept the common assembler style comments, treat them as white
space. Of course, also skip white space. The semi-colon is
special, though, in that it is also a statement terminator. */
";".* { return ';'; }
"#".* { ; }
[ \t\b] { ; }
\n { yyline += 1; }
. { return yytext[0]; }
%%
int yywrap()
{
return -1;
}

76
vvp/main.cc Normal file
View File

@ -0,0 +1,76 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: main.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
#endif
# include "config.h"
# include "parse_misc.h"
# include "compile.h"
# include "schedule.h"
# include <stdio.h>
# include <getopt.h>
int main(int argc, char*argv[])
{
int opt;
unsigned flag_errors = 0;
const char*dump_path = 0;
const char*design_path = 0;
while ((opt = getopt(argc, argv, "D:")) != EOF) switch (opt) {
case 'D':
dump_path = optarg;
break;
default:
flag_errors += 1;
}
if (flag_errors)
return flag_errors;
if (optind == argc) {
fprintf(stderr, "%s: no input file.\n", argv[0]);
return -1;
}
design_path = argv[optind];
compile_init();
compile_design(design_path);
compile_cleanup();
if (dump_path) {
FILE*fd = fopen(dump_path, "w");
compile_dump(fd);
}
schedule_simulate();
return 0;
}
/*
* $Log: main.cc,v $
* Revision 1.1 2001/03/11 00:29:38 steve
* Add the vvp engine to cvs.
*
*/

39
vvp/opcodes.txt Normal file
View File

@ -0,0 +1,39 @@
EXECUTABLE INSTRUCTION OPCODES
Instruction opcodes all start with a % character and have 0 or more
operands. In no case are there more then 3 operands.
* %assign <var-label>, <delay>, <bit>
This does a non-blocking assignment to a variable. The <label>
identifies the affected variable, and the <delay> gives the delay when
the assignment takes place. The delay may be 0. For blocking
assignments, see %set. The <bit> is the address of the thread register
that contains the bit value to assign.
* %delay <delay>
This opcode pauses the thread, and causes it to be rescheduled for a
time in the future. The <amount> is the number of the ticks in the
future to reschedule, and is >= 0. If the %delay is zero, then the
thread yields the processor for another thread, but will be resumed in
the current time step.
* %load <bit>, <functor-label>
This instruction loads a value from the given functor output into the
specified thread register bit.
* %set <var-label>, <bit>
This sets a bit of a variable, and is used to implement blocking
assignments. The <label> identifies the variable to receive the new
value. Once the set completes, the value is immediately available to
be read out of the variable. The <bit> is the address of the thread
register that contains the bit value to assign.
* %waitfor <functor-label>
XXXX

149
vvp/parse.y Normal file
View File

@ -0,0 +1,149 @@
%{
# include "parse_misc.h"
# include "compile.h"
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
/*
* These are bits in the lexor.
*/
extern FILE*yyin;
%}
%union {
char*text;
unsigned long numb;
struct textv_s textv;
comp_operands_t opa;
};
%token K_FUNCTOR K_THREAD K_VAR
%token <text> T_INSTR
%token <text> T_LABEL
%token <numb> T_NUMBER
%token <text> T_SYMBOL
%type <textv> symbols
%type <opa> operand operands operands_opt
%%
/* A program is simply a list of statements. No other structure. */
program
: statement
| program statement
;
/* A statement can be any of the following. In all cases, the
statment is terminated by a semi-colon. In general, a statement
has a label, an opcode of some source, and operands. The
structure of the operands depends on the opcode. */
statement
/* Functor statements define functors. The functor must have a
label and a type name, and may have operands. */
: T_LABEL K_FUNCTOR T_SYMBOL ',' symbols ';'
{ struct textv_s obj = $5;
compile_functor($1, $3, obj.cnt, obj.text);
}
| T_LABEL K_FUNCTOR T_SYMBOL ';'
{ compile_functor($1, $3, 0, 0); }
/* Instructions may have a label, and have zero or more
operands. The meaning of and restrictions on the operands depends
on the specific instruction. */
| T_LABEL T_INSTR operands_opt ';'
{ compile_code($1, $2, $3);
}
| T_INSTR operands_opt ';'
{ compile_code(0, $1, $2);
}
/* Thread statements declare a thread with its starting address. The
starting address must already be defined. */
| K_THREAD T_SYMBOL ';'
{ compile_thread($2); }
/* Var statements declare a bit of a variable. This also implicitly
creates a functor with the same name that acts as the output of
the variable in the netlist. */
| T_LABEL K_VAR ';'
{ compile_variable($1); }
;
operands_opt
: operands { $$ = $1; }
| { $$ = 0; }
;
operands
: operands ',' operand
{ comp_operands_t opa = $1;
assert(opa->argc < 3);
assert($3->argc == 1);
opa->argv[opa->argc] = $3->argv[0];
opa->argc += 1;
free($3);
$$ = opa;
}
| operand
{ $$ = $1; }
;
operand
: T_SYMBOL
{ comp_operands_t opa = (comp_operands_t)
calloc(1, sizeof(struct comp_operands_s));
opa->argc = 1;
opa->argv[0].ltype = L_TEXT;
opa->argv[0].text = $1;
$$ = opa;
}
| T_NUMBER
{ comp_operands_t opa = (comp_operands_t)
calloc(1, sizeof(struct comp_operands_s));
opa->argc = 1;
opa->argv[0].ltype = L_NUMB;
opa->argv[0].numb = $1;
$$ = opa;
}
;
/* functor operands can only be a list of symbols. */
symbols
: T_SYMBOL
{ struct textv_s obj;
textv_init(&obj);
textv_add(&obj, $1);
$$ = obj;
}
| symbols ',' T_SYMBOL
{ struct textv_s obj = $1;
textv_add(&obj, $3);
$$ = obj;
}
;
%%
int compile_design(const char*path)
{
yypath = path;
yyline = 1;
yyin = fopen(path, "r");
int rc = yyparse();
return rc;
}

54
vvp/parse_misc.cc Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2000 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
*/
#if !defined(WINNT)
#ident "$Id: parse_misc.cc,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
# include "parse_misc.h"
# include <stdio.h>
# include <malloc.h>
const char*yypath;
unsigned yyline;
void yyerror(const char*msg)
{
fprintf(stderr, "%s:%u: %s\n", yypath, yyline, msg);
}
void textv_init(struct textv_s*obj)
{
obj->cnt = 0;
obj->text = 0;
}
void textv_add(struct textv_s*obj, char*item)
{
obj->text = realloc(obj->text, (obj->cnt+1) * sizeof(char*));
obj->text[obj->cnt] = item;
obj->cnt += 1;
}
/*
* $Log: parse_misc.cc,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/

57
vvp/parse_misc.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef __parse_misc_H
#define __parse_misc_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: parse_misc.h,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
/*
* This method is called to compile the design file. The input is read
* and a list of statements is created.
*/
extern int compile_design(const char*path);
/*
* various functions shared by the lexor and the parser.
*/
extern int yylex(void);
extern void yyerror(const char*msg);
/*
* This is the path of the current source file.
*/
extern const char*yypath;
extern unsigned yyline;
struct textv_s {
unsigned cnt;
char**text;
};
extern void textv_init(struct textv_s*obj);
extern void textv_add(struct textv_s*obj, char*item);
/*
* $Log: parse_misc.h,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/
#endif

77
vvp/pointers.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef __pointers_H
#define __pointers_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: pointers.h,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
/*
* This header file describes the various "pointer" integral types
* that are used in vvp, along with functions that can be used to
* manipulate those pointers.
*/
# include "config.h"
/*
* The vvp_ipoint_t is a 32bit integer that encodes the address of a
* functor input port.
*
* The typedef below gets the type properly declared as an integral
* type that is big enough. The config.h header file has the defines
* needed for the following pre-processor magic to work.
*/
# if SIZEOF_UNSIGNED >= 4
typedef unsigned vvp_ipoint_t;
#elif SIZEOF_UNSIGNED_LONG >= 4
typedef unsigned long vvp_ipoint_t;
#else
#error "I need an unsigned type that is 32 bits!"
#endif
/*
* Given a functor generic address and a desired port, this function
* makes a complete vvp_ipoint_t that points to the port of the given
* functor. The The result points to the same functor as the input
* pointer, but addresses the supplied port instead.
*/
inline vvp_ipoint_t ipoint_make(vvp_ipoint_t func, unsigned port)
{
return (func & ~3) | (port & 3);
}
/*
* This function returns the port index of a functor given a complete
* vvp_ipoint_t pointer.
*/
inline unsigned ipoint_port(vvp_ipoint_t func)
{
return func & 3;
}
typedef unsigned vvp_cpoint_t;
/*
* $Log: pointers.h,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/
#endif

148
vvp/schedule.cc Normal file
View File

@ -0,0 +1,148 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: schedule.cc,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
# include "schedule.h"
# include "vthread.h"
# include <malloc.h>
# include <assert.h>
struct event_s {
unsigned delay;
vthread_t thr;
vvp_ipoint_t fun;
struct event_s*next;
struct event_s*last;
};
static struct event_s* list = 0;
static void schedule_event_(struct event_s*cur)
{
cur->last = cur;
if (list == 0) {
list = cur;
cur->next = 0;
return;
}
struct event_s*idx = list;
if (cur->delay < idx->delay) {
idx->delay -= cur->delay;
cur->next = idx;
list = cur;
} else {
struct event_s*prev = idx;
while (cur->delay > idx->delay) {
cur->delay -= idx->delay;
prev = idx->last;
if (prev->next == 0) {
cur->next = 0;
prev->next = cur;
return;
}
idx = prev->next;
}
if (cur->delay < idx->delay) {
idx->delay -= cur->delay;
cur->last = cur;
cur->next = idx;
prev->next = cur;
} else {
assert(cur->delay == idx->delay);
cur->delay = 0;
cur->last = cur;
cur->next = idx->last->next;
idx->last->next = cur;
idx->last = cur;
}
}
}
void schedule_vthread(vthread_t thr, unsigned delay)
{
struct event_s*cur = (struct event_s*)
calloc(1, sizeof(struct event_s));
cur->delay = delay;
cur->thr = thr;
schedule_event_(cur);
}
void schedule_functor(vvp_ipoint_t fun, unsigned delay)
{
struct event_s*cur = (struct event_s*)
calloc(1, sizeof(struct event_s));
cur->delay = delay;
cur->fun = fun;
schedule_event_(cur);
}
static unsigned long schedule_time;
void schedule_simulate(void)
{
schedule_time = 0;
while (list) {
/* Pull the first item off the list. Fixup the last
pointer in the next cell, if necessary. */
struct event_s*cur = list;
list = cur->next;
if (cur->last != cur) {
assert(list->delay == 0);
list->last = cur->last;
} else {
schedule_time += cur->delay;
printf("TIME: %u\n", schedule_time);
}
if (cur->thr) {
vthread_run(cur->thr);
} else if (cur->fun) {
/* XXXX not implemented yet */
}
free(cur);
}
}
/*
* $Log: schedule.cc,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/

40
vvp/schedule.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __schedule_H
#define __schedule_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: schedule.h,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
# include "vthread.h"
# include "pointers.h"
extern void schedule_vthread(vthread_t thr, unsigned delay);
extern void schedule_functor(vvp_ipoint_t fun, unsigned delay);
extern void schedule_simulate(void);
/*
* $Log: schedule.h,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/
#endif

295
vvp/symbols.cc Normal file
View File

@ -0,0 +1,295 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: symbols.cc,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
# include "symbols.h"
# include <string.h>
# include <assert.h>
struct symbol_table_s {
struct tree_node_*root;
};
/*
* This is a B-Tree data structure, where there are nodes and
* leaves.
*
* Nodes have a bunch of pointers to children. Each child pointer has
* associated with it a key that is the largest key referenced by that
* child. So, if the key being searched for has a value <= the first
* key of a node, then the value is in the first child.
*
* leaves have a sorted table of key-value pairs. The search can use a
* simple binary search to find an item. Each key represents an item.
*/
const unsigned leaf_width = 511;
const unsigned node_width = 511;
struct tree_node_ {
bool leaf_flag;
unsigned count;
struct tree_node_*parent;
union {
struct {
char*key;
unsigned long val;
} leaf[leaf_width];
struct tree_node_*child[node_width];
};
};
static inline char* node_last_key(struct tree_node_*node)
{
while (node->leaf_flag == false)
node = node->child[node->count-1];
return node->leaf[node->count-1].key;
}
/*
* Allocate a new symbol table means creating the table structure and
* a root node, and initializing the pointers and members of the root
* node.
*/
symbol_table_t new_symbol_table(void)
{
symbol_table_t tbl = new struct symbol_table_s;
tbl->root = new struct tree_node_;
tbl->root->leaf_flag = false;
tbl->root->count = 0;
tbl->root->parent = 0;
return tbl;
}
static void split_node_(struct tree_node_*cur)
{
assert(0);
}
/*
* This function takes a leaf node and splits in into two. Move half
* the leaf keys into the new node, and add the new leaf into the
* parent node.
*/
static struct tree_node_* split_leaf_(struct tree_node_*cur)
{
assert(cur->leaf_flag);
assert(cur->parent);
assert(! cur->parent->leaf_flag);
/* Create a new leaf to hold half the data from the old leaf. */
struct tree_node_*new_leaf = new struct tree_node_;
new_leaf->leaf_flag = true;
new_leaf->count = cur->count / 2;
new_leaf->parent = cur->parent;
/* Move the last half of the data from the end of the old leaf
to the beggining of the new leaf. At the same time, reduce
the size of the old leaf. */
unsigned idx1 = new_leaf->count;
unsigned idx2 = cur->count;
while (idx1 > 0) {
idx1 -= 1;
idx2 -= 1;
new_leaf->leaf[idx1] = cur->leaf[idx2];
cur->count -= 1;
}
assert(new_leaf->count > 0);
assert(cur->count > 0);
unsigned idx = 0;
while (cur->parent->child[idx] != cur) {
assert(idx < cur->parent->count);
idx += 1;
}
idx += 1;
for (unsigned tmp = cur->parent->count ; tmp > idx ; tmp -= 1)
cur->parent->child[tmp] = cur->parent->child[tmp-1];
cur->parent->child[idx] = new_leaf;
cur->parent->count += 1;
if (cur->parent->count == node_width)
split_node_(cur->parent);
return new_leaf;
}
/*
* Thid function searches tree recursively for the key. If the value
* is not found (and we are at a leaf) then set the key with the given
* value. If the key is found, set the value only if the force_flag is
* true.
*/
static unsigned long find_value_(symbol_table_t tbl, struct tree_node_*cur,
const char*key, unsigned long val,
bool force_flag)
{
if (cur->leaf_flag) {
unsigned idx = 0;
for (;;) {
/* If we run out of keys in the leaf, then add
this at the end of the leaf. */
if (idx == cur->count) {
cur->leaf[idx].key = strdup(key);
cur->leaf[idx].val = val;
cur->count += 1;
if (cur->count == leaf_width)
split_leaf_(cur);
return val;
}
int rc = strcmp(key, cur->leaf[idx].key);
/* If we found the key already in the table, then
set the new value and break. */
if (rc == 0) {
if (force_flag)
cur->leaf[idx].val = val;
return cur->leaf[idx].val;
}
/* If this key goes before the current key, then
push all the following entries back and add
this key here. */
if (rc < 0) {
for (unsigned tmp = cur->count; tmp > idx; tmp -= 1)
cur->leaf[tmp] = cur->leaf[tmp-1];
cur->leaf[idx].key = strdup(key);
cur->leaf[idx].val = val;
cur->count += 1;
if (cur->count == leaf_width)
split_leaf_(cur);
return val;
}
idx += 1;
}
} else {
unsigned idx = 0;
for (;;) {
if (idx == cur->count) {
idx -= 1;
return find_value_(tbl, cur->child[idx],
key, val, force_flag);
}
int rc = strcmp(key, node_last_key(cur->child[idx]));
if (rc <= 0) {
return find_value_(tbl, cur->child[idx],
key, val, force_flag);
}
idx += 1;
}
}
assert(0);
return 0;
}
void sym_set_value(symbol_table_t tbl, const char*key, unsigned long val)
{
if (tbl->root->count == 0) {
/* Handle the special case that this is the very first
value in the symbol table. Create the first leaf node
and initialize the pointers. */
struct tree_node_*cur = new struct tree_node_;
cur->leaf_flag = true;
cur->parent = tbl->root;
cur->count = 1;
cur->leaf[0].key = strdup(key);
cur->leaf[0].val = val;
tbl->root->count = 1;
tbl->root->child[0] = cur;
} else {
find_value_(tbl, tbl->root, key, val, true);
}
}
unsigned long sym_get_value(symbol_table_t tbl, const char*key)
{
if (tbl->root->count == 0) {
/* Handle the special case that this is the very first
value in the symbol table. Create the first leaf node
and initialize the pointers. */
struct tree_node_*cur = new struct tree_node_;
cur->leaf_flag = true;
cur->parent = tbl->root;
cur->count = 1;
cur->leaf[0].key = strdup(key);
cur->leaf[0].val = 0;
tbl->root->count = 1;
tbl->root->child[0] = cur;
return 0;
} else {
return find_value_(tbl, tbl->root, key, 0, false);
}
}
static void dump_tree(struct tree_node_*cur, unsigned ind, FILE*fd)
{
if (cur->leaf_flag) {
fprintf(fd, "%*s%p: %u keys\n", ind, "", cur, cur->count);
for (unsigned idx = 0 ; idx < cur->count ; idx += 1) {
fprintf(fd, "%*s %3d: key=%s, val=0x%lx\n", ind, "",
idx, cur->leaf[idx].key, cur->leaf[idx].val);
}
} else {
fprintf(fd, "%*s%p: %u children\n", ind, "", cur, cur->count);
for (unsigned idx = 0 ; idx < cur->count ; idx += 1) {
dump_tree(cur->child[idx], ind+4, fd);
}
}
}
void sym_dump(symbol_table_t tbl, FILE*fd)
{
dump_tree(tbl->root, 0, fd);
}
/*
* $Log: symbols.cc,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/

85
vvp/symbols.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef __symbols_H
#define __symbols_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: symbols.h,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
/*
* The symbol_table_t is intended as a means to hold and quickly index
* large symbol tables with small symbol values. That is, the value
* should fit in a 32bit unsigned integer (not even necessarily a
* pointer.)
*
* The key is an unstructured ASCII string, terminated by a
* null. Items added to the table are not removed, unless the entire
* table is deleted.
*
* The compiler uses symbol tables to help match up operands to
* referenced objects in the source. The compiler knows by the context
* that the symbol appears what kind of thing is referenced, and so
* what symbol table to look in.
*/
# include "config.h"
# include <stdio.h>
/*
* This is the basic type of a symbol table. It is opaque. Don't even
* try to look inside. The actual implementation is given in the
* symbols.cc source file.
*/
typedef struct symbol_table_s *symbol_table_t;
/*
* Create a new symbol table or release an existing one. A new symbol
* table has no keys and no values. As a symbol table is built up, it
* consumes more and more memory. When the table is no longer needed,
* the delete_symbol_table method will delete the table, including all
* the space for the keys.
*/
extern symbol_table_t new_symbol_table(void);
extern void delete_symbol_table(symbol_table_t tbl);
/*
* This method locates the value in the symbol table and sets its
* value. If the key doesn't yet exist, create it.
*/
void sym_set_value(symbol_table_t tbl, const char*key, unsigned long val);
/*
* This method locates the value in the symbol table and returns
* it. If the value does not exist, create it, initialize it with
* zero and return the zero value.
*/
unsigned long sym_get_value(symbol_table_t tbl, const char*key);
/*
* Diagnostic dump of the symbol table.
*/
extern void sym_dump(symbol_table_t tbl, FILE*fd);
/*
* $Log: symbols.h,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/
#endif

96
vvp/vthread.cc Normal file
View File

@ -0,0 +1,96 @@
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: vthread.cc,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
# include "vthread.h"
# include "codes.h"
# include "schedule.h"
struct vthread_s {
/* This is the program counter. */
unsigned long pc;
};
/*
* Create a new thread with the given start address.
*/
vthread_t v_newthread(unsigned long pc)
{
vthread_t thr = new struct vthread_s;
thr->pc = pc;
return thr;
}
/*
* This function runs a thread by fetching an instruction,
* incrementing the PC, and executing the instruction.
*/
void vthread_run(vthread_t thr)
{
for (;;) {
vvp_code_t cp = codespace_index(thr->pc);
thr->pc += 1;
bool rc = (cp->opcode)(thr, cp);
if (rc == false)
return;
}
}
bool of_ASSIGN(vthread_t thr, vvp_code_t cp)
{
printf("thread %p: %%assign\n");
return true;
}
bool of_DELAY(vthread_t thr, vvp_code_t cp)
{
printf("thread %p: %%delay %u\n", thr, cp->number);
schedule_vthread(thr, cp->number);
return false;
}
bool of_END(vthread_t thr, vvp_code_t cp)
{
printf("thread %p: %%end\n", thr);
return false;
}
bool of_NOOP(vthread_t thr, vvp_code_t cp)
{
return true;
}
bool of_SET(vthread_t thr, vvp_code_t cp)
{
printf("thread %p: %%set\n");
return true;
}
/*
* $Log: vthread.cc,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/

57
vvp/vthread.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef __vthread_H
#define __vthread_H
/*
* 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
*/
#if !defined(WINNT)
#ident "$Id: vthread.h,v 1.1 2001/03/11 00:29:39 steve Exp $"
#endif
/*
* A vthread is a simulation thread that executes instructions when
* they are scheduled. This structure contains all the thread specific
* context needed to run an instruction.
*
* Included in a thread are its program counter, local bits and
* members needed for tracking the thread. The thread runs by fetching
* instructions from code space, interpreting the instruction, then
* fetching the next instruction.
*/
typedef struct vthread_s*vthread_t;
/*
* This creates a new simulation thread, with the given start
* address. The generated thread is ready to run, but is not yet
* scheduled.
*/
extern vthread_t v_newthread(unsigned long sa);
/*
* Cause this thread to execute instructions until in is put to sleep
* by executing some sort of delay or wait instruction.
*/
extern void vthread_run(vthread_t thr);
/*
* $Log: vthread.h,v $
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/
#endif