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.
This commit is contained in:
Cary R 2010-08-11 19:01:58 -07:00 committed by Stephen Williams
parent 860f8627ba
commit 03f6283203
12 changed files with 84 additions and 19 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

13
main.cc
View File

@ -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<string,const char*> 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);

View File

@ -1932,8 +1932,9 @@ const NetNet* NetFuncDef::return_sig() const
return result_sig_;
}
NetSTask::NetSTask(const char*na, const svector<NetExpr*>&pa)
: name_(0), parms_(pa)
NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
const svector<NetExpr*>&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();

View File

@ -2969,10 +2969,12 @@ class NetRelease : public NetAssignBase {
class NetSTask : public NetProc {
public:
NetSTask(const char*na, const svector<NetExpr*>&);
NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
const svector<NetExpr*>&);
~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_;
svector<NetExpr*>parms_;
};

View File

@ -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_) {

View File

@ -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));

View File

@ -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_;

View File

@ -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)

View File

@ -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