Add support for vpi scopes.

This commit is contained in:
steve 2001-03-18 00:37:55 +00:00
parent e03859b834
commit 66f7ef97da
11 changed files with 283 additions and 39 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.4 2001/03/16 01:44:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.5 2001/03/18 00:37:55 steve Exp $"
#
#
SHELL = /bin/sh
@ -54,7 +54,7 @@ clean:
distclean: clean
rm -f config.h Makefile config.cache config.log config.status
V = vpi_modules.o vpi_iter.o vpi_mcd.o vpi_priv.o vpi_tasks.o
V = vpi_modules.o vpi_iter.o vpi_mcd.o vpi_priv.o vpi_scope.o vpi_tasks.o
O = main.o parse.o parse_misc.o lexor.o compile.o functor.o symbols.o \
codes.o vthread.o schedule.o tables.o $V

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.cc,v 1.4 2001/03/16 01:44:34 steve Exp $"
#ident "$Id: compile.cc,v 1.5 2001/03/18 00:37:55 steve Exp $"
#endif
# include "compile.h"
@ -112,6 +112,7 @@ static struct resolv_list_s*resolv_list = 0;
*/
void compile_init(void)
{
scope_init();
sym_functors = new_symbol_table();
functor_init();
sym_codespace = new_symbol_table();
@ -132,7 +133,11 @@ void compile_functor(char*label, char*type, unsigned init,
{
vvp_ipoint_t fdx = functor_allocate();
functor_t obj = functor_index(fdx);
sym_set_value(sym_functors, label, fdx);
{ symbol_value_t val;
val.num = fdx;
sym_set_value(sym_functors, label, val);
}
assert(argc <= 4);
@ -146,7 +151,8 @@ void compile_functor(char*label, char*type, unsigned init,
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]);
symbol_value_t val = sym_get_value(sym_functors, argv[idx]);
vvp_ipoint_t tmp = val.num;
if (tmp) {
functor_t fport = functor_index(tmp);
@ -198,7 +204,9 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
codespace pointer. Don't need the text of the label after
this is done. */
if (label) {
sym_set_value(sym_codespace, label, ptr);
symbol_value_t val;
val.num = ptr;
sym_set_value(sym_codespace, label, val);
free(label);
}
@ -227,6 +235,8 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
list that the parser supplied. */
for (unsigned idx = 0 ; idx < op->argc ; idx += 1) {
symbol_value_t tmp;
switch (op->argt[idx]) {
case OA_NONE:
break;
@ -255,8 +265,8 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
code->cptr = sym_get_value(sym_codespace,
opa->argv[idx].text);
tmp = sym_get_value(sym_codespace, opa->argv[idx].text);
code->cptr = tmp.num;
if (code->cptr == 0) {
yyerror("functor undefined");
break;
@ -271,8 +281,8 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
code->iptr = sym_get_value(sym_functors,
opa->argv[idx].text);
tmp = sym_get_value(sym_functors, opa->argv[idx].text);
code->iptr = tmp.num;
if (code->iptr == 0) {
yyerror("functor undefined");
break;
@ -306,7 +316,9 @@ void compile_vpi_call(char*label, char*name)
codespace pointer. Don't need the text of the label after
this is done. */
if (label) {
sym_set_value(sym_codespace, label, ptr);
symbol_value_t val;
val.num = ptr;
sym_set_value(sym_codespace, label, val);
free(label);
}
@ -329,7 +341,8 @@ void compile_vpi_call(char*label, char*name)
*/
void compile_thread(char*start_sym)
{
vvp_cpoint_t pc = sym_get_value(sym_codespace, start_sym);
symbol_value_t tmp = sym_get_value(sym_codespace, start_sym);
vvp_cpoint_t pc = tmp.num;
if (pc == 0) {
yyerror("unresolved address");
return;
@ -347,7 +360,9 @@ void compile_thread(char*start_sym)
void compile_variable(char*label)
{
vvp_ipoint_t fdx = functor_allocate();
sym_set_value(sym_functors, label, fdx);
symbol_value_t val;
val.num = fdx;
sym_set_value(sym_functors, label, val);
functor_t obj = functor_index(fdx);
obj->table = ft_var;
@ -377,7 +392,8 @@ void compile_cleanup(void)
/* Try again to look up the symbol that was not defined
the first time around. */
vvp_ipoint_t tmp = sym_get_value(sym_functors, res->source);
symbol_value_t val = sym_get_value(sym_functors, res->source);
vvp_ipoint_t tmp = val.num;
if (tmp != 0) {
/* The symbol is defined, link the functor input
@ -395,6 +411,8 @@ void compile_cleanup(void)
resolv_list = res;
}
}
scope_cleanup();
}
void compile_dump(FILE*fd)
@ -405,7 +423,7 @@ void compile_dump(FILE*fd)
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, " %p: %s\n", (void*)cur->port, cur->source);
fprintf(fd, "CODE SPACE SYMBOL TABLE:\n");
sym_dump(sym_codespace, fd);
@ -416,6 +434,9 @@ void compile_dump(FILE*fd)
/*
* $Log: compile.cc,v $
* Revision 1.5 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
* Revision 1.4 2001/03/16 01:44:34 steve
* Add structures for VPI support, and all the %vpi_call
* instruction. Get linking of VPI modules to work.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.h,v 1.3 2001/03/16 01:44:34 steve Exp $"
#ident "$Id: compile.h,v 1.4 2001/03/18 00:37:55 steve Exp $"
#endif
# include <stdio.h>
@ -79,6 +79,13 @@ typedef struct comp_operands_s*comp_operands_t;
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
extern void compile_vpi_call(char*label, char*name);
/*
* The parser uses these functions to compile .scope statements.
* The implementations of these live in the vpi_scope.cc file.
*/
extern void compile_scope_decl(char*lab, char*nam, char*par);
extern void compile_scope_recall(char*sym);
/*
* The parser uses this function to declare a thread. The start_sym is
* the start instruction, and must already be defined.
@ -98,6 +105,9 @@ extern void compile_dump(FILE*fd);
/*
* $Log: compile.h,v $
* Revision 1.4 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
* Revision 1.3 2001/03/16 01:44:34 steve
* Add structures for VPI support, and all the %vpi_call
* instruction. Get linking of VPI modules to work.

View File

@ -23,6 +23,7 @@
/* These are some keywords that are recognized. */
".functor" { return K_FUNCTOR; }
".scope" { return K_SCOPE; }
".thread" { return K_THREAD; }
".var" { return K_VAR; }

View File

@ -21,7 +21,7 @@ extern FILE*yyin;
};
%token K_FUNCTOR K_THREAD K_VAR K_vpi_call
%token K_FUNCTOR K_SCOPE K_THREAD K_VAR K_vpi_call
%token <text> T_INSTR
%token <text> T_LABEL
@ -79,6 +79,18 @@ statement
| K_vpi_call T_STRING ';'
{ compile_vpi_call(0, $2); }
/* Scope statements come in two forms. There are the scope
declaration and the scope recall. */
| T_LABEL K_SCOPE T_STRING ';'
{ compile_scope_decl($1, $3, 0); }
| T_LABEL K_SCOPE T_STRING ',' T_SYMBOL ';'
{ compile_scope_decl($1, $3, $5); }
| K_SCOPE T_SYMBOL ';'
{ compile_scope_recall($2); }
/* Thread statements declare a thread with its starting address. The
starting address must already be defined. */

View File

@ -17,7 +17,7 @@
* 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 $"
#ident "$Id: symbols.cc,v 1.2 2001/03/18 00:37:55 steve Exp $"
#endif
# include "symbols.h"
@ -52,7 +52,7 @@ struct tree_node_ {
union {
struct {
char*key;
unsigned long val;
symbol_value_t val;
} leaf[leaf_width];
struct tree_node_*child[node_width];
@ -142,14 +142,14 @@ static struct tree_node_* split_leaf_(struct tree_node_*cur)
/*
* Thid function searches tree recursively for the key. If the value
* This 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,
static symbol_value_t find_value_(symbol_table_t tbl, struct tree_node_*cur,
const char*key, symbol_value_t val,
bool force_flag)
{
if (cur->leaf_flag) {
@ -218,10 +218,13 @@ static unsigned long find_value_(symbol_table_t tbl, struct tree_node_*cur,
}
assert(0);
return 0;
{ symbol_value_t tmp;
tmp.num = 0;
return tmp;
}
}
void sym_set_value(symbol_table_t tbl, const char*key, unsigned long val)
void sym_set_value(symbol_table_t tbl, const char*key, symbol_value_t val)
{
if (tbl->root->count == 0) {
/* Handle the special case that this is the very first
@ -241,8 +244,11 @@ void sym_set_value(symbol_table_t tbl, const char*key, unsigned long val)
}
}
unsigned long sym_get_value(symbol_table_t tbl, const char*key)
symbol_value_t sym_get_value(symbol_table_t tbl, const char*key)
{
symbol_value_t def;
def.num = 0;
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
@ -252,13 +258,13 @@ unsigned long sym_get_value(symbol_table_t tbl, const char*key)
cur->parent = tbl->root;
cur->count = 1;
cur->leaf[0].key = strdup(key);
cur->leaf[0].val = 0;
cur->leaf[0].val = def;
tbl->root->count = 1;
tbl->root->child[0] = cur;
return 0;
return cur->leaf[0].val;
} else {
return find_value_(tbl, tbl->root, key, 0, false);
return find_value_(tbl, tbl->root, key, def, false);
}
}
@ -270,7 +276,7 @@ static void dump_tree(struct tree_node_*cur, unsigned ind, FILE*fd)
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);
idx, cur->leaf[idx].key, cur->leaf[idx].val.num);
}
} else {
@ -288,6 +294,9 @@ void sym_dump(symbol_table_t tbl, FILE*fd)
/*
* $Log: symbols.cc,v $
* Revision 1.2 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*

View File

@ -19,7 +19,7 @@
* 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 $"
#ident "$Id: symbols.h,v 1.2 2001/03/18 00:37:55 steve Exp $"
#endif
/*
@ -48,6 +48,13 @@
*/
typedef struct symbol_table_s *symbol_table_t;
typedef struct symbol_value_s {
union {
unsigned long num;
void*ptr;
};
} symbol_value_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
@ -62,14 +69,14 @@ 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);
void sym_set_value(symbol_table_t tbl, const char*key, symbol_value_t 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);
symbol_value_t sym_get_value(symbol_table_t tbl, const char*key);
/*
* Diagnostic dump of the symbol table.
@ -78,6 +85,9 @@ extern void sym_dump(symbol_table_t tbl, FILE*fd);
/*
* $Log: symbols.h,v $
* Revision 1.2 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: vpi.txt,v 1.2 2001/03/16 01:44:34 steve Exp $
* $Id: vpi.txt,v 1.3 2001/03/18 00:37:55 steve Exp $
*/
@ -35,7 +35,7 @@ thus be caught before the simulation is run.
Verilog.
The handle that the vvp threads have to the VPI are the vpiHandles of
the system tasks and functions. The %stask instruction, once compiled,
the system tasks and functions. The %vpi_call instruction, once compiled,
carries the vpiHandle of the system task.
@ -85,6 +85,40 @@ the arguments must be some sort of object that can be represented by a
vpiHandle at compile time.
SCOPES
VPI can access scopes as objects of type vpiScope. Scopes have names
and can also contain other sub-scopes, all of which the VPI function
can access by the vpiInternalScope reference. Therefore, the run-time
needs to form a tree of scopes into which other scoped VPI objects are
placed.
A scope is created with a .scope directive, like so:
<label> .scope "name" [, <parent>];
The scope takes a string name as the first parameter. If there is an
additional parameter, it is a label of the directive for the parent
scope. Scopes that have no parent are root scopes. It is an error to
declare a scope with the same name more then once in a parent scope.
The name string given when creating the scope is the basename for the
scope. The vvp automatically constructs full names from the scope
hierarchy, and runtime VPI code can access that full name with the
vpiFullname reference.
Objects that place themselves in a scope place themselves in the
current scope. The current scope is the one that was last mentioned by
a .scope directive. If the wrong scope is current, the label on a
scope directive can be used to resume a scope. The syntax works like
this:
.scope <symbol>;
In this case, the <symbol> is the label of a previous scope directive,
and is used to identify the scope to be resumed. A scope resume
directive cannot have a label.
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_priv.h,v 1.1 2001/03/16 01:44:34 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.2 2001/03/18 00:37:55 steve Exp $"
#endif
# include "vpi_user.h"
@ -72,6 +72,20 @@ struct __vpiIterator {
unsigned next;
};
/*
* Scopes are created by .scope statements in the source.
*/
struct __vpiScope {
struct __vpiHandle base;
/* The scope has a name. */
char*name;
/* Keep an array of internal scope items. */
struct __vpiHandle**intern;
unsigned nintern;
};
extern vpiHandle vpip_peek_current_scope(void);
extern void vpip_attach_to_current_scope(vpiHandle obj);
/*
* When a loaded VPI module announces a system task/function, one
* __vpiUserSystf object is created to hold the definition of that
@ -89,6 +103,7 @@ struct __vpiUserSystf {
struct __vpiSysTaskCall {
struct __vpiHandle base;
vpiHandle scope;
struct __vpiUserSystf*defn;
unsigned nargs;
vpiHandle*args;
@ -119,8 +134,18 @@ extern vpiHandle vpip_build_vpi_call(const char*name);
extern void vpip_execute_vpi_call(vpiHandle obj);
/*
* These are functions used by the compiler to prepare for compilation
* and to finish compilation in preparation for execution.
*/
extern void scope_init(void);
extern void scope_cleanup(void);
/*
* $Log: vpi_priv.h,v $
* Revision 1.2 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
* Revision 1.1 2001/03/16 01:44:34 steve
* Add structures for VPI support, and all the %vpi_call
* instruction. Get linking of VPI modules to work.

109
vvp/vpi_scope.cc Normal file
View File

@ -0,0 +1,109 @@
/*
* 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: vpi_scope.cc,v 1.1 2001/03/18 00:37:55 steve Exp $"
#endif
# include "compile.h"
# include "vpi_priv.h"
# include "symbols.h"
# include <malloc.h>
# include <assert.h>
static symbol_table_t scope_table = 0;
static struct __vpiScope*current_scope = 0;
static void attach_to_scope_(struct __vpiScope*scope, vpiHandle obj)
{
assert(scope);
unsigned idx = scope->nintern++;
if (scope->intern == 0)
scope->intern = (vpiHandle*)
malloc(sizeof(vpiHandle));
else
scope->intern = (vpiHandle*)
realloc(scope->intern, sizeof(vpiHandle)*scope->nintern);
scope->intern[idx] = obj;
}
/*
* When the compiler encounters a scope declaration, this function
* creates and initializes a __vpiScope object with the requested name
* and within the addressed parent. The label is used as a key in the
* symbol table and the name is used to construct the actual object.
*/
void compile_scope_decl(char*label, char*name, char*parent)
{
struct __vpiScope*scope = (struct __vpiScope*)
malloc(sizeof(struct __vpiScope));
scope->name = name;
scope->intern = 0;
scope->nintern = 0;
current_scope = scope;
symbol_value_t val;
val.ptr = scope;
sym_set_value(scope_table, label, val);
free(label);
if (parent) {
val = sym_get_value(scope_table, parent);
struct __vpiScope*sp = (struct __vpiScope*) val.ptr;
attach_to_scope_(sp, &scope->base);
free(parent);
}
}
void compile_scope_recall(char*symbol)
{
symbol_value_t val = sym_get_value(scope_table, symbol);
current_scope = (struct __vpiScope*)val.ptr;
free(symbol);
}
vpiHandle vpip_peek_current_scope(void)
{
return &current_scope->base;
}
void vpip_attach_to_current_scope(vpiHandle obj)
{
attach_to_scope_(current_scope, obj);
}
void scope_init(void)
{
scope_table = new_symbol_table();
}
void scope_cleanup(void)
{
}
/*
* $Log: vpi_scope.cc,v $
* Revision 1.1 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_tasks.cc,v 1.1 2001/03/16 01:44:34 steve Exp $"
#ident "$Id: vpi_tasks.cc,v 1.2 2001/03/18 00:37:55 steve Exp $"
#endif
/*
@ -33,7 +33,16 @@
static vpiHandle systask_handle(int type, vpiHandle ref)
{
return 0;
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|| (ref->vpi_type->type_code == vpiSysFuncCall));
switch (type) {
case vpiScope:
return rfp->scope;
default:
return 0;
};
}
/*
@ -140,9 +149,10 @@ vpiHandle vpip_build_vpi_call(const char*name)
calloc(1, sizeof (struct __vpiSysTaskCall));
obj->base.vpi_type = &vpip_systask_rt;
obj->defn = vpip_find_systf(name);
obj->scope = vpip_peek_current_scope();
obj->defn = vpip_find_systf(name);
obj->nargs = 0;
obj->args = 0;
obj->args = 0;
/* If there is a compiletf function, call it here. */
if (obj->defn->info.compiletf)
@ -182,6 +192,9 @@ void vpi_register_systf(const struct t_vpi_systf_data*ss)
/*
* $Log: vpi_tasks.cc,v $
* Revision 1.2 2001/03/18 00:37:55 steve
* Add support for vpi scopes.
*
* Revision 1.1 2001/03/16 01:44:34 steve
* Add structures for VPI support, and all the %vpi_call
* instruction. Get linking of VPI modules to work.