Add support for system function calls.

This commit is contained in:
steve 2001-05-20 00:46:12 +00:00
parent 983bf5cbab
commit 224af78463
7 changed files with 207 additions and 37 deletions

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.64 2001/05/13 21:05:06 steve Exp $"
#ident "$Id: compile.cc,v 1.65 2001/05/20 00:46:12 steve Exp $"
#endif
# include "compile.h"
@ -910,7 +910,37 @@ void compile_vpi_call(char*label, char*name, unsigned argc, vpiHandle*argv)
/* Create a vpiHandle that bundles the call information, and
store that handle in the instruction. */
code->handle = vpip_build_vpi_call(name, argc, argv);
code->handle = vpip_build_vpi_call(name, 0, 0, argc, argv);
if (code->handle == 0)
compile_errors += 1;
/* Done with the lexor-allocated name string. */
free(name);
}
void compile_vpi_func_call(char*label, char*name,
unsigned vbit, unsigned vwid,
unsigned argc, vpiHandle*argv)
{
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) {
symbol_value_t val;
val.num = ptr;
sym_set_value(sym_codespace, label, val);
free(label);
}
/* Create an instruction in the code space. */
vvp_code_t code = codespace_index(ptr);
code->opcode = &of_VPI_CALL;
/* Create a vpiHandle that bundles the call information, and
store that handle in the instruction. */
code->handle = vpip_build_vpi_call(name, vbit, vwid, argc, argv);
if (code->handle == 0)
compile_errors += 1;
@ -1163,6 +1193,9 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
/*
* $Log: compile.cc,v $
* Revision 1.65 2001/05/20 00:46:12 steve
* Add support for system function calls.
*
* Revision 1.64 2001/05/13 21:05:06 steve
* calculate the output of resolvers.
*

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.22 2001/05/09 04:23:18 steve Exp $"
#ident "$Id: compile.h,v 1.23 2001/05/20 00:46:12 steve Exp $"
#endif
# include <stdio.h>
@ -145,8 +145,14 @@ typedef struct comp_operands_s*comp_operands_t;
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
extern void compile_disable(char*label, struct symb_s symb);
extern void compile_vpi_call(char*label, char*name,
unsigned argc, vpiHandle*argv);
extern void compile_vpi_func_call(char*label, char*name,
unsigned vbit, unsigned vwid,
unsigned argc, vpiHandle*argv);
extern void compile_fork(char*label, struct symb_s targ_s,
struct symb_s scope_s);
extern void compile_codelabel(char*label);
@ -176,6 +182,9 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.23 2001/05/20 00:46:12 steve
* Add support for system function calls.
*
* Revision 1.22 2001/05/09 04:23:18 steve
* Now that the interactive debugger exists,
* there is no use for the output dump.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: lexor.lex,v 1.17 2001/05/10 00:26:53 steve Exp $"
#ident "$Id: lexor.lex,v 1.18 2001/05/20 00:46:12 steve Exp $"
#endif
# include "parse_misc.h"
@ -87,6 +87,7 @@
exceptional parameter requirements) are listed first. */
"%vpi_call" { return K_vpi_call; }
"%vpi_func" { return K_vpi_func; }
"%disable" { return K_disable; }
"%fork" { return K_fork; }
@ -139,6 +140,9 @@ int yywrap()
/*
* $Log: lexor.lex,v $
* Revision 1.18 2001/05/20 00:46:12 steve
* Add support for system function calls.
*
* Revision 1.17 2001/05/10 00:26:53 steve
* VVP support for memories in expressions,
* including general support for thread bit

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.20 2001/05/08 23:59:33 steve Exp $
* $Id: opcodes.txt,v 1.21 2001/05/20 00:46:12 steve Exp $
*/
@ -283,10 +283,19 @@ See also the %add instruction.
* %vpi_call <name> [, ...]
This instruction makes a call to a system task or function that was
declared using VPI. The operands are compiled down to a vpiHandle for
the call. The instruction contains only the vpiHandle for the
call. See the vpi.txt file for more on system task/function calls.
This instruction makes a call to a system task that was declared using
VPI. The operands are compiled down to a vpiHandle for the call. The
instruction contains only the vpiHandle for the call. See the vpi.txt
file for more on system task/function calls.
* %vpi_func <name>, <dst>, <wid> [, ...]
This instruction is similar to %vpi_call, except that it is for
calling system functions. The difference here is the <dst> and <wid>
parameters that specify where the return value is to go. The normal
means that the VPI code uses to write the return value causes those
bits to go here.
* %wait <functor-label>

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: parse.y,v 1.26 2001/05/09 02:53:25 steve Exp $"
#ident "$Id: parse.y,v 1.27 2001/05/20 00:46:12 steve Exp $"
#endif
# include "parse_misc.h"
@ -57,7 +57,7 @@ extern FILE*yyin;
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_RESOLV K_SCOPE K_THREAD
%token K_UDP K_UDP_C K_UDP_S
%token K_MEM K_MEM_P K_MEM_I
%token K_VAR K_VAR_S K_vpi_call K_disable K_fork
%token K_VAR K_VAR_S K_vpi_call K_vpi_func K_disable K_fork
%token K_vpi_module
%token <text> T_INSTR
@ -182,11 +182,17 @@ statement
{ compile_codelabel($1); }
/* %vpi_call statements are instructions that have unusual operand
requirements so are handled by their own rules. */
requirements so are handled by their own rules. The %vpi_func
statement is a variant of %vpi_call that includes a thread vector
after the name, and is used for function calls. */
| label_opt K_vpi_call T_STRING argument_opt ';'
{ compile_vpi_call($1, $3, $4.argc, $4.argv); }
| label_opt K_vpi_func T_STRING ','
T_NUMBER ',' T_NUMBER argument_opt ';'
{ compile_vpi_func_call($1, $3, $5, $7, $8.argc, $8.argv); }
/* %disable statements are instructions that takes a scope reference
as an operand. It therefore is parsed uniquely. */
@ -438,6 +444,9 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.27 2001/05/20 00:46:12 steve
* Add support for system function calls.
*
* Revision 1.26 2001/05/09 02:53:25 steve
* Implement the .resolv syntax.
*

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.15 2001/05/10 00:26:53 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.16 2001/05/20 00:46:12 steve Exp $"
#endif
# include "vpi_user.h"
@ -127,12 +127,20 @@ extern vpiHandle vpip_make_memory(vvp_memory_t mem);
/*
* When a loaded VPI module announces a system task/function, one
* __vpiUserSystf object is created to hold the definition of that
* task/function.
* task/function. The distinction between task and function is stored
* in the vpi_systf_data structure data that was supplied by the
* external module.
*
* When the compiler encounters a %vpi_call statement, it creates a
* __vpiSysTaskCall to represent that particular call. The call refers
* to the definition handle so that when the %vpi_call instruction is
* encountered at run-time, the definition can be located and used.
*
* The vpiSysTaskCall handles both functions and tasks, as the two are
* extremely similar. The different VPI type is reflected in a
* different vpi_type pointer in the base structure. The only
* additional part is the vbit/vwid that is used by the put of the
* system function call to place the values in the vthread bit space.
*/
struct __vpiUserSystf {
struct __vpiHandle base;
@ -145,6 +153,9 @@ struct __vpiSysTaskCall {
struct __vpiUserSystf*defn;
unsigned nargs;
vpiHandle*args;
/* These represent where in the vthread to put the return value. */
unsigned short vbit, vwid;
};
extern struct __vpiSysTaskCall*vpip_cur_task;
@ -194,10 +205,15 @@ extern void vpip_load_module(const char*name, const char*path);
* call. However, the vpiSysTaskCall that is the returned handle,
* holds a parameter argument list that is passed in here.
*
* Note that the argv array is saved in the handle, should should not
* be released by the caller.
* The vbit and vwid fields are used if this turns out to be a system
* function. In that case, the vbit and vwid are used to address the
* vector is thread bit space where the result is supposed to go.
*
* Note that the argv array is saved in the handle, and should should
* not be released by the caller.
*/
extern vpiHandle vpip_build_vpi_call(const char*name,
unsigned vbit, unsigned vwid,
unsigned argc,
vpiHandle*argv);
@ -215,6 +231,9 @@ vpiHandle vpip_sim_time(void);
/*
* $Log: vpi_priv.h,v $
* Revision 1.16 2001/05/20 00:46:12 steve
* Add support for system function calls.
*
* Revision 1.15 2001/05/10 00:26:53 steve
* VVP support for memories in expressions,
* including general support for thread bit

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.6 2001/05/10 00:26:53 steve Exp $"
#ident "$Id: vpi_tasks.cc,v 1.7 2001/05/20 00:46:12 steve Exp $"
#endif
/*
@ -25,7 +25,8 @@
* built up before the input source file is parsed, and is used by the
* compiler when %vpi_call statements are encountered.
*/
# include "vpi_priv.h"
# include "vpi_priv.h"
# include "vthread.h"
# include <stdio.h>
# include <malloc.h>
# include <string.h>
@ -75,15 +76,77 @@ static const struct __vpirt vpip_systask_rt = {
/*
* A value *can* be put to a vpiSysFuncCall object. This is how the
* return value is set. The value that is given should be converted to
* bits and set into the return value bit array.
* bits and set into the thread space bits that were selected at
* compile time.
*/
static vpiHandle sysfunc_put_value(vpiHandle ref, p_vpi_value val,
p_vpi_time t, int flag)
static vpiHandle sysfunc_put_value(vpiHandle ref, p_vpi_value vp,
p_vpi_time t, int flags)
{
assert(0);
assert(ref->vpi_type->type_code == vpiSysFuncCall);
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
/* delays are not allowed. */
assert(flags == vpiNoDelay);
assert(rfp->vbit >= 4);
switch (vp->format) {
case vpiIntVal: {
long val = vp->value.integer;
for (unsigned idx = 0 ; idx < rfp->vwid ; idx += 1) {
vthread_put_bit(vpip_current_vthread,
rfp->vbit+idx, val&1);
val >>= 1;
}
break;
}
case vpiScalarVal:
switch (vp->value.scalar) {
case vpi0:
vthread_put_bit(vpip_current_vthread, rfp->vbit, 0);
break;
case vpi1:
vthread_put_bit(vpip_current_vthread, rfp->vbit, 1);
break;
case vpiX:
vthread_put_bit(vpip_current_vthread, rfp->vbit, 2);
break;
case vpiZ:
vthread_put_bit(vpip_current_vthread, rfp->vbit, 3);
break;
default:
assert(0);
}
break;
case vpiVectorVal: {
assert(rfp->vwid <= sizeof (unsigned long));
unsigned long aval = vp->value.vector->aval;
unsigned long bval = vp->value.vector->bval;
for (unsigned idx = 0 ; idx < rfp->vwid ; idx += 1) {
int bit = (aval&1) | (((bval^aval)<<1)&2);
vthread_put_bit(vpip_current_vthread,
rfp->vbit+idx, bit);
aval >>= 1;
bval >>= 1;
}
break;
}
default:
assert(0);
}
return 0;
}
static const struct __vpirt vpip_sysfunc_rt = {
vpiSysFuncCall,
0,
@ -139,26 +202,46 @@ static struct __vpiUserSystf* vpip_find_systf(const char*name)
* describes the call, and return it. The %vpi_call instruction will
* store this handle for when it is executed.
*/
vpiHandle vpip_build_vpi_call(const char*name,
unsigned argc,
vpiHandle*argv)
vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, unsigned vwid,
unsigned argc, vpiHandle*argv)
{
struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall*)
calloc(1, sizeof (struct __vpiSysTaskCall));
obj->base.vpi_type = &vpip_systask_rt;
obj->scope = vpip_peek_current_scope();
obj->defn = vpip_find_systf(name);
obj->nargs = argc;
obj->args = argv;
if (obj->defn == 0) {
struct __vpiUserSystf*defn = vpip_find_systf(name);
if (defn == 0) {
fprintf(stderr, "%s: This task not defined "
"by any modules. I cannot compile it.\n", name);
free(obj);
return 0;
}
struct __vpiSysTaskCall*obj = new struct __vpiSysTaskCall;
switch (defn->info.type) {
case vpiSysTask:
obj->base.vpi_type = &vpip_systask_rt;
assert(vbit == 0);
assert(vwid == 0);
obj->vbit = 0;
obj->vwid = 0;
break;
case vpiSysFunc:
obj->base.vpi_type = &vpip_sysfunc_rt;
assert(vbit >= 4);
assert(vwid > 0);
obj->vbit = vbit;
obj->vwid = vwid;
break;
default:
assert(0);
}
obj->scope = vpip_peek_current_scope();
obj->defn = defn;
obj->nargs = argc;
obj->args = argv;
/* If there is a compiletf function, call it here. */
if (obj->defn->info.compiletf)
obj->defn->info.compiletf (obj->defn->info.user_data);
@ -179,7 +262,8 @@ void vpip_execute_vpi_call(vthread_t thr, vpiHandle ref)
{
vpip_current_vthread = thr;
assert(ref->vpi_type->type_code == vpiSysTaskCall);
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|| (ref->vpi_type->type_code == vpiSysFuncCall));
vpip_cur_task = (struct __vpiSysTaskCall*)ref;
@ -202,6 +286,9 @@ void vpi_register_systf(const struct t_vpi_systf_data*ss)
/*
* $Log: vpi_tasks.cc,v $
* Revision 1.7 2001/05/20 00:46:12 steve
* Add support for system function calls.
*
* Revision 1.6 2001/05/10 00:26:53 steve
* VVP support for memories in expressions,
* including general support for thread bit