Add run time support for calling system functions as task.

This patch adds two new opcodes and the infrastructure needed to call
system functions as tasks. The normal %vpi_call will generate an error
if a system function is called as a task. %vpi_call/w will generate a
warning and will ignore any value returned by the function. %vpi_call/i
will ignore the system function return value and will not print a
message. Adding this is a feature request and is supported in
SystemVerilog. Next I need to add flags to control this depending on
the compiler generation and possibly other flags.

I may leave the cast to void (%vpi_call/i) functionality unimplemented
for now.
This commit is contained in:
Cary R 2010-06-09 11:56:00 -07:00 committed by Stephen Williams
parent 3d63f664c8
commit 3f6aff47c9
9 changed files with 88 additions and 18 deletions

View File

@ -799,6 +799,8 @@ Threads call vpi tasks with the %vpi_call or %vpi_func
instructions. The formats are:
%vpi_call <file-index> <lineno> <name>, <args>... ;
%vpi_call/w <file-index> <lineno> <name>, <args>... ;
%vpi_call/i <file-index> <lineno> <name>, <args>... ;
%vpi_func <file-index> <lineno> <name>, <args>... ;
%vpi_func/r <file-index> <lineno> <name>, <args>... ;
@ -813,6 +815,12 @@ looked up and compared with the registered system tasks/functions.
The <args>... is a comma (",") separated list of arguments. These are
made available to the VPI code as vpi handles.
The plain %vpi_call will fail with an error message if a system function
is called as a task. The /w suffix version will display a warning message
if a system function is called as a task and will ignore any value that
the function tries to return. The /i suffix version silently ignores any
value returned by a system function called as a task.
* The &A<> argument
The &A<> argument is a reference to the word of a variable array. The

View File

@ -1679,6 +1679,7 @@ void compile_fork(char*label, struct symb_s dest, struct symb_s scope)
}
void compile_vpi_call(char*label, char*name,
bool func_as_task_err, bool func_as_task_warn,
long file_idx, long lineno,
unsigned argc, vpiHandle*argv)
{
@ -1691,8 +1692,9 @@ void compile_vpi_call(char*label, char*name,
/* Create a vpiHandle that bundles the call information, and
store that handle in the instruction. */
code->handle = vpip_build_vpi_call(name, 0, 0, 0, argc, argv,
file_idx, lineno);
code->handle = vpip_build_vpi_call(name, 0, 0, 0,
func_as_task_err, func_as_task_warn,
argc, argv, file_idx, lineno);
if (code->handle == 0)
compile_errors += 1;
@ -1714,8 +1716,8 @@ void compile_vpi_func_call(char*label, char*name,
/* Create a vpiHandle that bundles the call information, and
store that handle in the instruction. */
code->handle = vpip_build_vpi_call(name, vbit, vwid, 0, argc, argv,
file_idx, lineno);
code->handle = vpip_build_vpi_call(name, vbit, vwid, 0, true, false,
argc, argv, file_idx, lineno);
if (code->handle == 0)
compile_errors += 1;

View File

@ -395,6 +395,7 @@ 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,
bool func_as_task_err, bool func_as_task_warn,
long file_idx, long lineno,
unsigned argc, vpiHandle*argv);

View File

@ -198,6 +198,8 @@ static char* strdupnew(char const *str)
exceptional parameter requirements) are listed first. */
"%vpi_call" { return K_vpi_call; }
"%vpi_call/w" { return K_vpi_call_w; }
"%vpi_call/i" { return K_vpi_call_i; }
"%vpi_func" { return K_vpi_func; }
"%vpi_func/r" { return K_vpi_func_r; }
"%disable" { return K_disable; }

View File

@ -84,7 +84,8 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
%token K_UFUNC K_UFUNC_E K_UDP K_UDP_C K_UDP_S
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_call_w K_vpi_call_i
%token K_vpi_func K_vpi_func_r
%token K_disable K_fork
%token K_ivl_version K_ivl_delay_selection
%token K_vpi_module K_vpi_time_precision K_file_names
@ -540,8 +541,22 @@ statement
statement is a variant of %vpi_call that includes a thread vector
after the name, and is used for function calls. */
/* This version does not allow a function to be called as a task. */
| label_opt K_vpi_call T_NUMBER T_NUMBER T_STRING argument_opt ';'
{ compile_vpi_call($1, $5, $3, $4, $6.argc, $6.argv); }
{ compile_vpi_call($1, $5, true, false, $3, $4,
$6.argc, $6.argv); }
/* This version allows a function to be called as a task, but prints a
* warning message. */
| label_opt K_vpi_call_w T_NUMBER T_NUMBER T_STRING argument_opt ';'
{ compile_vpi_call($1, $5, false, true, $3, $4,
$6.argc, $6.argv); }
/* This version allows a function to be called as a task and does not
* print a message. */
| label_opt K_vpi_call_i T_NUMBER T_NUMBER T_STRING argument_opt ';'
{ compile_vpi_call($1, $5, false, false, $3, $4,
$6.argc, $6.argv); }
| label_opt K_vpi_func T_NUMBER T_NUMBER T_STRING ','
T_NUMBER ',' T_NUMBER argument_opt ';'

View File

@ -158,7 +158,8 @@ void compile_sfunc(char*label, char*name, char*format_string,
vvp_net_t*ptr = new vvp_net_t;
vpiHandle sys = vpip_build_vpi_call(name, 0, width_code, ptr,
argc, vpi_argv, file_idx, lineno);
true, false, argc, vpi_argv,
file_idx, lineno);
assert(sys);
/* Create and connect the functor to the label. */

View File

@ -170,8 +170,9 @@ static void cmd_call(unsigned argc, char*argv[])
when we finish. */
if (errors == 0) {
vpiHandle call_handle = vpip_build_vpi_call(argv[0], 0, 0, 0,
vpi_argc, vpi_argv,
1, 0);
true, false,
vpi_argc, vpi_argv,
1, 0);
if (call_handle == 0)
goto out;
@ -532,4 +533,3 @@ void stop_handler(int rc)
vpi_mcd_printf(1,"** Continue **\n");
}

View File

@ -541,6 +541,8 @@ extern unsigned vpip_module_path_cnt;
extern vpiHandle vpip_build_vpi_call(const char*name,
unsigned vbit, int vwid,
class vvp_net_t*fnet,
bool func_as_task_err,
bool func_as_task_warn,
unsigned argc,
vpiHandle*argv,
long file_idx,

View File

@ -458,6 +458,13 @@ static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp, int)
return 0;
}
static vpiHandle sysfunc_put_no_value(vpiHandle ref, p_vpi_value, int)
{
assert(ref->vpi_type->type_code == vpiSysFuncCall);
return 0;
}
static const struct __vpirt vpip_sysfunc_rt = {
vpiSysFuncCall,
@ -499,6 +506,16 @@ static const struct __vpirt vpip_sysfunc_rnet_rt = {
systask_iter
};
static const struct __vpirt vpip_sysfunc_no_rt = {
vpiSysFuncCall,
sysfunc_get,
systask_get_str,
0,
sysfunc_put_no_value,
systask_handle,
systask_iter
};
/* **** Manipulate the internal data structures. **** */
static struct __vpiUserSystf**def_table = 0;
@ -629,7 +646,7 @@ void vpip_make_systf_system_defined(vpiHandle ref)
* information so that we can print the file name.
*/
enum vpi_call_error_type {VPI_CALL_NO_DEF, VPI_CALL_TASK_AS_FUNC,
VPI_CALL_FUNC_AS_TASK};
VPI_CALL_FUNC_AS_TASK, VPI_CALL_FUNC_AS_TASK_WARN};
typedef struct vpi_call_error {
vpi_call_error_type type;
char *name;
@ -662,23 +679,34 @@ void print_vpi_call_errors()
fprintf(stderr, "%s:%d: Error: System task/function %s() is "
"not defined by any module.\n",
file_names[vpi_call_error_lst[idx].file_idx],
vpi_call_error_lst[idx].lineno,
(int)vpi_call_error_lst[idx].lineno,
vpi_call_error_lst[idx].name);
break;
case VPI_CALL_TASK_AS_FUNC:
fprintf(stderr, "%s:%d: Error: %s() is a system task, it "
"cannot be called as a function.\n",
file_names[vpi_call_error_lst[idx].file_idx],
vpi_call_error_lst[idx].lineno,
(int)vpi_call_error_lst[idx].lineno,
vpi_call_error_lst[idx].name);
break;
case VPI_CALL_FUNC_AS_TASK:
fprintf(stderr, "%s:%d: Error: %s() is a system function, it "
"cannot be called as a task.\n",
file_names[vpi_call_error_lst[idx].file_idx],
vpi_call_error_lst[idx].lineno,
(int)vpi_call_error_lst[idx].lineno,
vpi_call_error_lst[idx].name);
break;
case VPI_CALL_FUNC_AS_TASK_WARN:
fprintf(stderr, "%s:%d: Warning: Calling system function "
"%s() as a task.\n",
file_names[vpi_call_error_lst[idx].file_idx],
(int)vpi_call_error_lst[idx].lineno,
vpi_call_error_lst[idx].name);
fprintf(stderr, "%s:%d: The functions return "
"value will be ignored.\n",
file_names[vpi_call_error_lst[idx].file_idx],
(int)vpi_call_error_lst[idx].lineno);
break;
}
free(vpi_call_error_lst[idx].name);
}
@ -699,9 +727,12 @@ void print_vpi_call_errors()
*/
vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
class vvp_net_t*fnet,
bool func_as_task_err, bool func_as_task_warn,
unsigned argc, vpiHandle*argv,
long file_idx, long lineno)
{
assert(!(func_as_task_err && func_as_task_warn));
struct __vpiUserSystf*defn = vpip_find_systf(name);
if (defn == 0) {
add_vpi_call_error(VPI_CALL_NO_DEF, name, file_idx, lineno);
@ -720,14 +751,19 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
case vpiSysFunc:
if (vwid == 0 && fnet == 0) {
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK, name, file_idx,
lineno);
return 0;
if (func_as_task_err) {
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK,
name, file_idx, lineno);
return 0;
} else if (func_as_task_warn) {
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK_WARN,
name, file_idx, lineno);
}
}
break;
default:
fprintf(stderr, "Unsupported call type %d.\n",
fprintf(stderr, "Unsupported vpi_call type %d.\n",
(int)defn->info.type);
assert(0);
}
@ -752,6 +788,9 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
} else if (vwid > 0) {
obj->base.vpi_type = &vpip_sysfunc_rt;
} else if (vwid == 0 && fnet == 0) {
obj->base.vpi_type = &vpip_sysfunc_no_rt;
} else {
assert(0);
}