ivl & vvp: Enabled 'string' as the return type in VPI functions.
This commit is contained in:
parent
9886b8cb36
commit
df6b24fd3a
|
|
@ -384,6 +384,11 @@ The function returns an integer.
|
|||
The function returns a vector with the given width, and is signed or
|
||||
unsigned according to the flag.
|
||||
|
||||
.TP 8
|
||||
.B vpiSysFuncString
|
||||
The function returns a string. This is an Icarus-specific extension, not
|
||||
available in the VPI standard.
|
||||
|
||||
.SH "COMMAND FILES"
|
||||
The command file allows the user to place source file names and
|
||||
certain command line switches into a text file instead of on a long
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ EXTERN_C_START
|
|||
/********* Many-to-One ***********/
|
||||
#define vpiMember 742
|
||||
|
||||
/* Icarus-specific function type to use string as the return type */
|
||||
#define vpiStringFunc 10
|
||||
#define vpiSysFuncString vpiSysFuncString
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif /* SV_VPI_USER_H */
|
||||
|
|
|
|||
11
sys_funcs.cc
11
sys_funcs.cc
|
|
@ -204,6 +204,17 @@ int load_sys_func_table(const char*path)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(stype,"vpiSysFuncString") == 0) {
|
||||
cell = new struct sfunc_return_type_cell;
|
||||
cell->name = lex_strings.add(name);
|
||||
cell->type = IVL_VT_STRING;
|
||||
cell->wid = 0; // string is a dynamic length type
|
||||
cell->signed_flag = false;
|
||||
cell->next = sfunc_stack;
|
||||
sfunc_stack = cell;
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%s: Unknown type: %s\n",
|
||||
path, name, stype);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -513,3 +513,14 @@ void draw_vpi_rfunc_call(ivl_expr_t fnet)
|
|||
|
||||
draw_vpi_taskfunc_args(call_string, 0, fnet);
|
||||
}
|
||||
|
||||
void draw_vpi_sfunc_call(ivl_expr_t fnet)
|
||||
{
|
||||
char call_string[1024];
|
||||
|
||||
sprintf(call_string, " %%vpi_func/s %u %u \"%s\"",
|
||||
ivl_file_table_index(ivl_expr_file(fnet)),
|
||||
ivl_expr_lineno(fnet), ivl_expr_name(fnet));
|
||||
|
||||
draw_vpi_taskfunc_args(call_string, 0, fnet);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@ static void string_ex_pop(ivl_expr_t expr)
|
|||
fprintf(vvp_out, " %%qpop/%s/str v%p_0;\n", fb, ivl_expr_signal(arg));
|
||||
}
|
||||
|
||||
static void draw_sfunc_string(ivl_expr_t expr)
|
||||
{
|
||||
assert(ivl_expr_value(expr) == IVL_VT_STRING);
|
||||
draw_vpi_sfunc_call(expr);
|
||||
}
|
||||
|
||||
void draw_eval_string(ivl_expr_t expr)
|
||||
{
|
||||
|
||||
|
|
@ -195,7 +201,7 @@ void draw_eval_string(ivl_expr_t expr)
|
|||
else if (strcmp(ivl_expr_name(expr), "$ivl_darray_method$pop_front")==0)
|
||||
string_ex_pop(expr);
|
||||
else
|
||||
fallback_eval(expr);
|
||||
draw_sfunc_string(expr);
|
||||
break;
|
||||
|
||||
case IVL_EX_UFUNC:
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ extern void draw_vpi_task_call(ivl_statement_t net);
|
|||
|
||||
extern void draw_vpi_func_call(ivl_expr_t expr);
|
||||
extern void draw_vpi_rfunc_call(ivl_expr_t expr);
|
||||
extern void draw_vpi_sfunc_call(ivl_expr_t expr);
|
||||
|
||||
extern void draw_class_in_scope(ivl_type_t classtype);
|
||||
|
||||
|
|
|
|||
|
|
@ -841,6 +841,7 @@ instructions. The formats are:
|
|||
%vpi_call/i <file-index> <lineno> <name>, <args>... ;
|
||||
%vpi_func <file-index> <lineno> <name>, <args>... ;
|
||||
%vpi_func/r <file-index> <lineno> <name>, <args>... ;
|
||||
%vpi_func/s <file-index> <lineno> <name>, <args>... ;
|
||||
|
||||
The <file-index> is an index into the string table. The indexed string
|
||||
is the source code file name where this call appears. The <lineno> is
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ static char* strdupnew(char const *str)
|
|||
"%vpi_call/i" { return K_vpi_call_i; }
|
||||
"%vpi_func" { return K_vpi_func; }
|
||||
"%vpi_func/r" { return K_vpi_func_r; }
|
||||
"%vpi_func/s" { return K_vpi_func_s; }
|
||||
"%file_line" { return K_file_line; }
|
||||
|
||||
/* Handle the specialized variable access functions. */
|
||||
|
|
|
|||
|
|
@ -1213,6 +1213,7 @@ stack when the call returns.
|
|||
|
||||
* %vpi_func <file> <line> <name> [, ...] {<vec4> <real> <str>}
|
||||
* %vpi_func/r <file> <line> <name> [, ...] {<vec4> <real> <str>}
|
||||
* %vpi_func/s <file> <line> <name> [, ...] {<vec4> <real> <str>}
|
||||
|
||||
This instruction is similar to %vpi_call, except that it is for
|
||||
calling system functions. The difference here is the return value from
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_VAR_QUEUE
|
||||
%token K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
|
||||
%token K_vpi_call K_vpi_call_w K_vpi_call_i
|
||||
%token K_vpi_func K_vpi_func_r
|
||||
%token K_vpi_func K_vpi_func_r K_vpi_func_s
|
||||
%token K_ivl_version K_ivl_delay_selection
|
||||
%token K_vpi_module K_vpi_time_precision K_file_names K_file_line
|
||||
%token K_PORT_INPUT K_PORT_OUTPUT K_PORT_INOUT K_PORT_MIXED K_PORT_NODIR
|
||||
|
|
@ -663,6 +663,10 @@ statement
|
|||
{ compile_vpi_func_call($1, $5, -vpiRealVal, 0, $3, $4,
|
||||
$6.argc, $6.argv, $8, $9, $10); }
|
||||
|
||||
| label_opt K_vpi_func_s T_NUMBER T_NUMBER T_STRING
|
||||
argument_opt '{' T_NUMBER T_NUMBER T_NUMBER '}' ';'
|
||||
{ compile_vpi_func_call($1, $5, -vpiStringVal, 0, $3, $4,
|
||||
$6.argc, $6.argv, $8, $9, $10); }
|
||||
|
||||
/* Scope statements come in two forms. There are the scope
|
||||
declaration and the scope recall. The declarations create the
|
||||
|
|
|
|||
|
|
@ -211,6 +211,51 @@ vpiHandle sysfunc_real::vpi_put_value(p_vpi_value vp, int)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct sysfunc_string : public __vpiSysTaskCall {
|
||||
inline sysfunc_string() { }
|
||||
int get_type_code(void) const { return vpiSysFuncCall; }
|
||||
int vpi_get(int code);
|
||||
char* vpi_get_str(int code) { return systask_get_str(code, this); }
|
||||
vpiHandle vpi_put_value(p_vpi_value val, int flags);
|
||||
vpiHandle vpi_handle(int code) { return systask_handle(code, this); }
|
||||
vpiHandle vpi_iterate(int code) { return systask_iter(code, this); }
|
||||
|
||||
std::string return_value_;
|
||||
};
|
||||
|
||||
int sysfunc_string::vpi_get(int code)
|
||||
{
|
||||
switch (code) {
|
||||
case vpiSize:
|
||||
return return_value_.size();
|
||||
|
||||
case vpiLineNo:
|
||||
return lineno;
|
||||
|
||||
case vpiUserDefn:
|
||||
return defn->is_user_defn;
|
||||
|
||||
default:
|
||||
return vpiUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
vpiHandle sysfunc_string::vpi_put_value(p_vpi_value vp, int)
|
||||
{
|
||||
put_value = true;
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiStringVal:
|
||||
return_value_ = std::string(vp->value.str);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported format %d.\n", (int)vp->format);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class sysfunc_vec4 : public __vpiSysTaskCall {
|
||||
public:
|
||||
explicit inline sysfunc_vec4(unsigned wid): return_value_(wid, BIT4_X) { }
|
||||
|
|
@ -845,6 +890,9 @@ vpiHandle vpip_build_vpi_call(const char*name, int val_code, unsigned return_wid
|
|||
} else if (val_code == -vpiVectorVal) {
|
||||
obj = new sysfunc_vec4(return_width);
|
||||
|
||||
} else if (val_code == -vpiStringVal) {
|
||||
obj = new sysfunc_string;
|
||||
|
||||
} else if (val_code == 0 && fnet == 0) {
|
||||
obj = new sysfunc_no;
|
||||
|
||||
|
|
@ -957,11 +1005,14 @@ void vpip_execute_vpi_call(vthread_t thr, vpiHandle ref)
|
|||
if (vpip_cur_task->string_stack > 0)
|
||||
vthread_pop_str(thr, vpip_cur_task->string_stack);
|
||||
|
||||
/* If the function has a real value, then push the value
|
||||
to the thread stack. */
|
||||
/* If the function returns a value, then push the value
|
||||
to the appropriate thread stack. */
|
||||
if (sysfunc_real*func_real = dynamic_cast<sysfunc_real*>(ref)) {
|
||||
vthread_push_real(thr, func_real->return_value_);
|
||||
}
|
||||
if (sysfunc_string*func_string = dynamic_cast<sysfunc_string*>(ref)) {
|
||||
vthread_push_str(thr, func_string->return_value_);
|
||||
}
|
||||
if (sysfunc_vec4*func_vec4 = dynamic_cast<sysfunc_vec4*>(ref)) {
|
||||
vthread_push_vec4(thr, func_vec4->return_value());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -328,6 +328,11 @@ void vthread_push_real(struct vthread_s*thr, double val)
|
|||
thr->push_real(val);
|
||||
}
|
||||
|
||||
void vthread_push_str(struct vthread_s*thr, const string&val)
|
||||
{
|
||||
thr->push_str(val);
|
||||
}
|
||||
|
||||
void vthread_pop_vec4(struct vthread_s*thr, unsigned depth)
|
||||
{
|
||||
thr->pop_vec4(depth);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ extern vvp_context_item_t vthread_get_rd_context_item(unsigned context_idx);
|
|||
* Access value stacks from thread space.
|
||||
*/
|
||||
extern void vthread_push_vec4(struct vthread_s*thr, const vvp_vector4_t&val);
|
||||
extern void vthread_push_str(struct vthread_s*thr, const std::string&val);
|
||||
extern void vthread_push_real(struct vthread_s*thr, double val);
|
||||
|
||||
extern void vthread_pop_vec4(struct vthread_s*thr, unsigned count);
|
||||
|
|
|
|||
Loading…
Reference in New Issue