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 int load_sys_func_table(const char*path);
|
||||||
extern void cleanup_sys_func_table();
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -2697,7 +2697,8 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||||
return noop;
|
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);
|
cur->set_line(*this);
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
ivl.def
1
ivl.def
|
|
@ -250,6 +250,7 @@ ivl_stmt_nevent
|
||||||
ivl_stmt_parm
|
ivl_stmt_parm
|
||||||
ivl_stmt_parm_count
|
ivl_stmt_parm_count
|
||||||
ivl_stmt_rval
|
ivl_stmt_rval
|
||||||
|
ivl_stmt_sfunc_as_task
|
||||||
ivl_stmt_sub_stmt
|
ivl_stmt_sub_stmt
|
||||||
|
|
||||||
ivl_switch_a
|
ivl_switch_a
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,13 @@ typedef enum ivl_statement_type_e {
|
||||||
IVL_ST_WHILE = 23
|
IVL_ST_WHILE = 23
|
||||||
} ivl_statement_type_t;
|
} 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
|
/* This is the type of a variable, and also used as the type for an
|
||||||
expression. */
|
expression. */
|
||||||
typedef enum ivl_variable_type_e {
|
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_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_CONTRIB
|
||||||
IVL_ST_FORCE */
|
IVL_ST_FORCE */
|
||||||
extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
|
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_DELAY, IVL_ST_DELAYX, IVL_ST_FOREVER, IVL_ST_REPEAT
|
||||||
IVL_ST_WAIT, IVL_ST_WHILE */
|
IVL_ST_WAIT, IVL_ST_WHILE */
|
||||||
extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
|
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_strict_ca_eval_flag = false;
|
||||||
bool gn_verilog_ams_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;
|
map<string,const char*> flags;
|
||||||
char*vpi_module_list = 0;
|
char*vpi_module_list = 0;
|
||||||
|
|
||||||
|
|
@ -1011,6 +1018,12 @@ int main(int argc, char*argv[])
|
||||||
cout << "ELABORATING DESIGN" << endl;
|
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. */
|
/* On with the process of elaborating the module. */
|
||||||
Design*des = elaborate(roots);
|
Design*des = elaborate(roots);
|
||||||
|
|
||||||
|
|
|
||||||
10
netlist.cc
10
netlist.cc
|
|
@ -1932,8 +1932,9 @@ const NetNet* NetFuncDef::return_sig() const
|
||||||
return result_sig_;
|
return result_sig_;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetSTask::NetSTask(const char*na, const svector<NetExpr*>&pa)
|
NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
|
||||||
: name_(0), parms_(pa)
|
const svector<NetExpr*>&pa)
|
||||||
|
: name_(0), sfunc_as_task_(sfat), parms_(pa)
|
||||||
{
|
{
|
||||||
name_ = lex_strings.add(na);
|
name_ = lex_strings.add(na);
|
||||||
assert(name_[0] == '$');
|
assert(name_[0] == '$');
|
||||||
|
|
@ -1952,6 +1953,11 @@ const char*NetSTask::name() const
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ivl_sfunc_as_task_t NetSTask::sfunc_as_task() const
|
||||||
|
{
|
||||||
|
return sfunc_as_task_;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned NetSTask::nparms() const
|
unsigned NetSTask::nparms() const
|
||||||
{
|
{
|
||||||
return parms_.count();
|
return parms_.count();
|
||||||
|
|
|
||||||
|
|
@ -2969,10 +2969,12 @@ class NetRelease : public NetAssignBase {
|
||||||
class NetSTask : public NetProc {
|
class NetSTask : public NetProc {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetSTask(const char*na, const svector<NetExpr*>&);
|
NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
|
||||||
|
const svector<NetExpr*>&);
|
||||||
~NetSTask();
|
~NetSTask();
|
||||||
|
|
||||||
const char* name() const;
|
const char* name() const;
|
||||||
|
ivl_sfunc_as_task_t sfunc_as_task() const;
|
||||||
|
|
||||||
unsigned nparms() const;
|
unsigned nparms() const;
|
||||||
|
|
||||||
|
|
@ -2985,6 +2987,7 @@ class NetSTask : public NetProc {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* name_;
|
const char* name_;
|
||||||
|
ivl_sfunc_as_task_t sfunc_as_task_;
|
||||||
svector<NetExpr*>parms_;
|
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;
|
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)
|
extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
switch (net->type_) {
|
switch (net->type_) {
|
||||||
|
|
|
||||||
|
|
@ -688,6 +688,7 @@ void dll_target::proc_stask(const NetSTask*net)
|
||||||
stmt_cur_->type_ = IVL_ST_STASK;
|
stmt_cur_->type_ = IVL_ST_STASK;
|
||||||
/* System task names are lex_strings strings. */
|
/* System task names are lex_strings strings. */
|
||||||
stmt_cur_->u_.stask_.name_ = net->name();
|
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_.nparm_= nparms;
|
||||||
stmt_cur_->u_.stask_.parms_= (ivl_expr_t*)
|
stmt_cur_->u_.stask_.parms_= (ivl_expr_t*)
|
||||||
calloc(nparms, sizeof(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 */
|
struct { /* IVL_ST_STASK */
|
||||||
const char*name_;
|
const char*name_;
|
||||||
|
ivl_sfunc_as_task_t sfunc_as_task_;
|
||||||
unsigned nparm_;
|
unsigned nparm_;
|
||||||
ivl_expr_t*parms_;
|
ivl_expr_t*parms_;
|
||||||
} stask_;
|
} stask_;
|
||||||
|
|
|
||||||
|
|
@ -386,11 +386,32 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||||
|
|
||||||
void draw_vpi_task_call(ivl_statement_t tnet)
|
void draw_vpi_task_call(ivl_statement_t tnet)
|
||||||
{
|
{
|
||||||
char call_string[1024];
|
unsigned parm_count = ivl_stmt_parm_count(tnet);
|
||||||
sprintf(call_string, " %%vpi_call %u %u \"%s\"",
|
const char *command = "error";
|
||||||
ivl_file_table_index(ivl_stmt_file(tnet)),
|
|
||||||
ivl_stmt_lineno(tnet), ivl_stmt_name(tnet));
|
switch (ivl_stmt_sfunc_as_task(tnet)) {
|
||||||
draw_vpi_taskfunc_args(call_string, tnet, 0);
|
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)
|
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)
|
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);
|
draw_vpi_task_call(net);
|
||||||
|
|
||||||
/* VPI calls can manipulate anything, so clear the expression
|
/* VPI calls can manipulate anything, so clear the expression
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue