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:
parent
860f8627ba
commit
03f6283203
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
1
ivl.def
1
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
|
||||
|
|
|
|||
|
|
@ -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
13
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<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);
|
||||
|
||||
|
|
|
|||
10
netlist.cc
10
netlist.cc
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
12
t-dll-api.cc
12
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_) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
1
t-dll.h
1
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_;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue