From 03f6283203641861ab4f9671feff3ad979e0d09a Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 11 Aug 2010 19:01:58 -0700 Subject: [PATCH] Add support for calling system functions as a task (SystemVerilog) This patch adds the ability to call a system function as a task for the SystemVerilog generation (-g2009). The return value is really calculated, but it is ignored. --- compiler.h | 7 +++++++ elaborate.cc | 3 ++- ivl.def | 1 + ivl_target.h | 9 +++++++++ main.cc | 13 +++++++++++++ netlist.cc | 10 ++++++++-- netlist.h | 5 ++++- t-dll-api.cc | 12 ++++++++++++ t-dll-proc.cc | 1 + t-dll.h | 1 + tgt-vvp/draw_vpi.c | 31 ++++++++++++++++++++++++++----- tgt-vvp/vvp_process.c | 10 ---------- 12 files changed, 84 insertions(+), 19 deletions(-) diff --git a/compiler.h b/compiler.h index 92aa8412e..962c2f531 100644 --- a/compiler.h +++ b/compiler.h @@ -212,4 +212,11 @@ extern const struct sfunc_return_type* lookup_sys_func(const char*name); extern int load_sys_func_table(const char*path); extern void cleanup_sys_func_table(); +/* + * In system Verilog it is allowed with a warning to call a function + * as a task. You can even cast the return value away and have no + * warning message. + */ +extern ivl_sfunc_as_task_t def_sfunc_as_task; + #endif diff --git a/elaborate.cc b/elaborate.cc index 365d2cc75..a53d46733 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2697,7 +2697,8 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const return noop; } - NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms); + NetSTask*cur = new NetSTask(peek_tail_name(path_), def_sfunc_as_task, + eparms); cur->set_line(*this); return cur; } diff --git a/ivl.def b/ivl.def index 1fd54e66e..41ae9b00b 100644 --- a/ivl.def +++ b/ivl.def @@ -250,6 +250,7 @@ ivl_stmt_nevent ivl_stmt_parm ivl_stmt_parm_count ivl_stmt_rval +ivl_stmt_sfunc_as_task ivl_stmt_sub_stmt ivl_switch_a diff --git a/ivl_target.h b/ivl_target.h index 68cf57d61..6e211f8f4 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -388,6 +388,13 @@ typedef enum ivl_statement_type_e { IVL_ST_WHILE = 23 } ivl_statement_type_t; +/* SystemVerilog allows a system function to be called as a task. */ +typedef enum ivl_sfunc_as_task_e { + IVL_SFUNC_AS_TASK_ERROR = 0, + IVL_SFUNC_AS_TASK_WARNING = 1, + IVL_SFUNC_AS_TASK_IGNORE = 2 +} ivl_sfunc_as_task_t; + /* This is the type of a variable, and also used as the type for an expression. */ typedef enum ivl_variable_type_e { @@ -1995,6 +2002,8 @@ extern unsigned ivl_stmt_parm_count(ivl_statement_t net); /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_CONTRIB IVL_ST_FORCE */ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net); + /* IVL_ST_STASK */ +extern ivl_sfunc_as_task_t ivl_stmt_sfunc_as_task(ivl_statement_t net); /* IVL_ST_DELAY, IVL_ST_DELAYX, IVL_ST_FOREVER, IVL_ST_REPEAT IVL_ST_WAIT, IVL_ST_WHILE */ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net); diff --git a/main.cc b/main.cc index fa462dc24..7630a1a70 100644 --- a/main.cc +++ b/main.cc @@ -106,6 +106,13 @@ bool gn_io_range_error_flag = true; bool gn_strict_ca_eval_flag = false; bool gn_verilog_ams_flag = false; +/* + * For some generations we allow a system function to be called + * as a task and only print a warning message. The default for + * this is that it is a run time error. + */ +ivl_sfunc_as_task_t def_sfunc_as_task = IVL_SFUNC_AS_TASK_ERROR; + map flags; char*vpi_module_list = 0; @@ -1011,6 +1018,12 @@ int main(int argc, char*argv[]) cout << "ELABORATING DESIGN" << endl; } + /* Decide if we are going to allow system functions to be called + * as tasks. */ + if (generation_flag >= GN_VER2009) { + def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING; + } + /* On with the process of elaborating the module. */ Design*des = elaborate(roots); diff --git a/netlist.cc b/netlist.cc index e8851ddfa..215aedac8 100644 --- a/netlist.cc +++ b/netlist.cc @@ -1932,8 +1932,9 @@ const NetNet* NetFuncDef::return_sig() const return result_sig_; } -NetSTask::NetSTask(const char*na, const svector&pa) -: name_(0), parms_(pa) +NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat, + const svector&pa) +: name_(0), sfunc_as_task_(sfat), parms_(pa) { name_ = lex_strings.add(na); assert(name_[0] == '$'); @@ -1952,6 +1953,11 @@ const char*NetSTask::name() const return name_; } +ivl_sfunc_as_task_t NetSTask::sfunc_as_task() const +{ + return sfunc_as_task_; +} + unsigned NetSTask::nparms() const { return parms_.count(); diff --git a/netlist.h b/netlist.h index e93d5485d..dd773b25e 100644 --- a/netlist.h +++ b/netlist.h @@ -2969,10 +2969,12 @@ class NetRelease : public NetAssignBase { class NetSTask : public NetProc { public: - NetSTask(const char*na, const svector&); + NetSTask(const char*na, ivl_sfunc_as_task_t sfat, + const svector&); ~NetSTask(); const char* name() const; + ivl_sfunc_as_task_t sfunc_as_task() const; unsigned nparms() const; @@ -2985,6 +2987,7 @@ class NetSTask : public NetProc { private: const char* name_; + ivl_sfunc_as_task_t sfunc_as_task_; svectorparms_; }; diff --git a/t-dll-api.cc b/t-dll-api.cc index a2dd1c157..d33c3f1c2 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2385,6 +2385,18 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net) return 0; } +extern "C" ivl_sfunc_as_task_t ivl_stmt_sfunc_as_task(ivl_statement_t net) +{ + switch (net->type_) { + case IVL_ST_STASK: + return net->u_.stask_.sfunc_as_task_; + default: + assert(0); + } + + return IVL_SFUNC_AS_TASK_ERROR; +} + extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) { switch (net->type_) { diff --git a/t-dll-proc.cc b/t-dll-proc.cc index c0581a6ca..6b18479f0 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -688,6 +688,7 @@ void dll_target::proc_stask(const NetSTask*net) stmt_cur_->type_ = IVL_ST_STASK; /* System task names are lex_strings strings. */ stmt_cur_->u_.stask_.name_ = net->name(); + stmt_cur_->u_.stask_.sfunc_as_task_ = net->sfunc_as_task(); stmt_cur_->u_.stask_.nparm_= nparms; stmt_cur_->u_.stask_.parms_= (ivl_expr_t*) calloc(nparms, sizeof(ivl_expr_t)); diff --git a/t-dll.h b/t-dll.h index 08eac980b..8967c59f0 100644 --- a/t-dll.h +++ b/t-dll.h @@ -753,6 +753,7 @@ struct ivl_statement_s { struct { /* IVL_ST_STASK */ const char*name_; + ivl_sfunc_as_task_t sfunc_as_task_; unsigned nparm_; ivl_expr_t*parms_; } stask_; diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 1ba73ac76..0a2543cc0 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -386,11 +386,32 @@ static void draw_vpi_taskfunc_args(const char*call_string, void draw_vpi_task_call(ivl_statement_t tnet) { - char call_string[1024]; - sprintf(call_string, " %%vpi_call %u %u \"%s\"", - ivl_file_table_index(ivl_stmt_file(tnet)), - ivl_stmt_lineno(tnet), ivl_stmt_name(tnet)); - draw_vpi_taskfunc_args(call_string, tnet, 0); + unsigned parm_count = ivl_stmt_parm_count(tnet); + const char *command = "error"; + + switch (ivl_stmt_sfunc_as_task(tnet)) { + case IVL_SFUNC_AS_TASK_ERROR: + command = "%vpi_call"; + break; + case IVL_SFUNC_AS_TASK_WARNING: + command = "%vpi_call/w"; + break; + case IVL_SFUNC_AS_TASK_IGNORE: + command = "%vpi_call/i"; + break; + } + + if (parm_count == 0) { + fprintf(vvp_out, " %s %u %u \"%s\";\n", command, + ivl_file_table_index(ivl_stmt_file(tnet)), + ivl_stmt_lineno(tnet), ivl_stmt_name(tnet)); + } else { + char call_string[1024]; + sprintf(call_string, " %s %u %u \"%s\"", command, + ivl_file_table_index(ivl_stmt_file(tnet)), + ivl_stmt_lineno(tnet), ivl_stmt_name(tnet)); + draw_vpi_taskfunc_args(call_string, tnet, 0); + } } struct vector_info draw_vpi_func_call(ivl_expr_t fnet, unsigned wid) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 2ed708f5c..2bbaec015 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1824,16 +1824,6 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope) static int show_system_task_call(ivl_statement_t net) { - unsigned parm_count = ivl_stmt_parm_count(net); - - if (parm_count == 0) { - fprintf(vvp_out, " %%vpi_call %u %u \"%s\";\n", - ivl_file_table_index(ivl_stmt_file(net)), - ivl_stmt_lineno(net), ivl_stmt_name(net)); - clear_expression_lookaside(); - return 0; - } - draw_vpi_task_call(net); /* VPI calls can manipulate anything, so clear the expression