From 224af784637ff24d4239ae655d3d6fc5b8e12067 Mon Sep 17 00:00:00 2001 From: steve Date: Sun, 20 May 2001 00:46:12 +0000 Subject: [PATCH] Add support for system function calls. --- vvp/compile.cc | 37 +++++++++++++- vvp/compile.h | 11 +++- vvp/lexor.lex | 6 ++- vvp/opcodes.txt | 19 +++++-- vvp/parse.y | 15 ++++-- vvp/vpi_priv.h | 27 ++++++++-- vvp/vpi_tasks.cc | 129 +++++++++++++++++++++++++++++++++++++++-------- 7 files changed, 207 insertions(+), 37 deletions(-) diff --git a/vvp/compile.cc b/vvp/compile.cc index cdc4c5f1f..93d95e415 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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. * diff --git a/vvp/compile.h b/vvp/compile.h index 3e21543e4..fb2edf039 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -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 @@ -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. diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 79a9cbb57..b19827bca 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -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 diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index b9c724484..535bf4d94 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -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 [, ...] -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 , , [, ...] + +This instruction is similar to %vpi_call, except that it is for +calling system functions. The difference here is the and +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 diff --git a/vvp/parse.y b/vvp/parse.y index 49315f5cd..063801ae5 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -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 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. * diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 80eb7f666..d60b38a43 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -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 diff --git a/vvp/vpi_tasks.cc b/vvp/vpi_tasks.cc index 5455984a2..e406f05d3 100644 --- a/vvp/vpi_tasks.cc +++ b/vvp/vpi_tasks.cc @@ -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 # include # include @@ -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