diff --git a/sv_vpi_user.h b/sv_vpi_user.h index ac6296d01..d2fdd90c6 100644 --- a/sv_vpi_user.h +++ b/sv_vpi_user.h @@ -48,6 +48,7 @@ EXTERN_C_START #define vpiIntVar 612 #define vpiByteVar 614 #define vpiLogicVar vpiReg +#define vpiClassVar 615 #define vpiStringVar 616 #define vpiBitVar 620 #define vpiArrayVar vpiRegArray diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 20307ca33..f56c80c15 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -485,6 +485,53 @@ static struct vector_info draw_binary_expr_eq_string(ivl_expr_t expr) return res; } +static struct vector_info draw_binary_expr_eq_class(ivl_expr_t expr) +{ + ivl_expr_t le = ivl_expr_oper1(expr); + ivl_expr_t re = ivl_expr_oper2(expr); + + struct vector_info res; + res.base = allocate_vector(1); + res.wid = 1; + assert(res.base); + + if (ivl_expr_type(le) == IVL_EX_NULL) { + ivl_expr_t tmp = le; + le = re; + re = tmp; + } + + /* Special case: If both operands are null, then the + expression has a constant value. */ + if (ivl_expr_type(le)==IVL_EX_NULL && ivl_expr_type(re)==IVL_EX_NULL) { + switch (ivl_expr_opcode(expr)) { + case 'e': /* == */ + fprintf(vvp_out, " %%mov %u, 1, 1;\n", res.base); + break; + case 'n': /* != */ + fprintf(vvp_out, " %%mov %u, 0, 1;\n", res.base); + break; + default: + assert(0); + break; + } + return res; + } + + if (ivl_expr_type(re) == IVL_EX_NULL && ivl_expr_type(le)==IVL_EX_SIGNAL) { + fprintf(vvp_out, " %%test_nul v%p_0;\n", ivl_expr_signal(le)); + fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base); + if (ivl_expr_opcode(expr) == 'n') + fprintf(vvp_out, " %%inv %u, 1;\n", res.base); + return res; + } + + fprintf(stderr, "SORRY: Compare class handles not implemented\n"); + fprintf(vvp_out, " ; XXXX compare class handles.\n"); + vvp_errors += 1; + return res; +} + static struct vector_info draw_binary_expr_eq(ivl_expr_t expr, unsigned ewid, int stuff_ok_flag) @@ -517,6 +564,11 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t expr, return draw_binary_expr_eq_string(expr); } + if ((ivl_expr_value(le) == IVL_VT_CLASS) + && (ivl_expr_value(re) == IVL_VT_CLASS)) { + return draw_binary_expr_eq_class(expr); + } + if (number_is_immediate(re,16,0) && !number_is_unknown(re)) return draw_eq_immediate(expr, ewid, le, re, stuff_ok_flag); diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 789326d6b..6ef92f2d7 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -512,6 +512,11 @@ static void draw_reg_in_scope(ivl_signal_t sig) vvp_mangle_name(ivl_signal_basename(sig)), ivl_signal_local(sig)? " Local signal" : ""); + } else if (ivl_signal_data_type(sig) == IVL_VT_CLASS) { + fprintf(vvp_out, "v%p_0 .var/cobj \"%s\";%s\n", sig, + vvp_mangle_name(ivl_signal_basename(sig)), + ivl_signal_local(sig)? " Local signal" : ""); + } else { fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n", diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 8f1130102..0859743c9 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -65,7 +65,8 @@ dllib=@DLLIB@ MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"' -V = vpi_modules.o vpi_callback.o vpi_const.o vpi_darray.o vpi_event.o vpi_iter.o vpi_mcd.o \ +V = vpi_modules.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \ + vpi_event.o vpi_iter.o vpi_mcd.o \ vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_string.o vpi_tasks.o vpi_time.o \ vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ vpip_to_dec.o vpip_format.o vvp_vpi.o diff --git a/vvp/codes.h b/vvp/codes.h index 2c9f83532..e415476f1 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -185,6 +185,7 @@ extern bool of_SUB(vthread_t thr, vvp_code_t code); extern bool of_SUB_WR(vthread_t thr, vvp_code_t code); extern bool of_SUBI(vthread_t thr, vvp_code_t code); extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code); +extern bool of_TEST_NUL(vthread_t thr, vvp_code_t code); extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code); extern bool of_WAIT(vthread_t thr, vvp_code_t code); extern bool of_XNOR(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 5731b13ad..f65f42d8a 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -232,6 +232,7 @@ static const struct opcode_table_s opcode_table[] = { { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%xnor/r", of_XNORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -334,8 +335,10 @@ vvp_net_t* vvp_net_lookup(const char*label) return sig->net; } - case vpiStringVar: { - __vpiStringVar*sig = dynamic_cast<__vpiStringVar*>(vpi); + case vpiStringVar: + case vpiArrayVar: + case vpiClassVar: { + __vpiBaseVar*sig = dynamic_cast<__vpiBaseVar*>(vpi); return sig->get_net(); } @@ -344,11 +347,6 @@ vvp_net_t* vvp_net_lookup(const char*label) return tmp->funct; } - case vpiArrayVar: { - __vpiDarrayVar*tmp = dynamic_cast<__vpiDarrayVar*>(vpi); - return tmp->get_net(); - } - default: fprintf(stderr, "Unsupported type %d.\n", vpi->get_type_code()); diff --git a/vvp/compile.h b/vvp/compile.h index bb4c60e80..4044a2977 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -463,6 +463,7 @@ extern void compile_variable(char*label, char*name, extern void compile_var_real(char*label, char*name); extern void compile_var_string(char*label, char*name); extern void compile_var_darray(char*label, char*name); +extern void compile_var_cobject(char*label, char*name); /* * This function is used to create a scope port diff --git a/vvp/lexor.lex b/vvp/lexor.lex index a580adb01..4d0b4578b 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -195,6 +195,7 @@ static char* strdupnew(char const *str) ".ufunc" { return K_UFUNC; } ".ufunc/e" { return K_UFUNC_E; } ".var" { return K_VAR; } +".var/cobj" { return K_VAR_COBJECT; } ".var/darray" { return K_VAR_DARRAY; } ".var/real" { return K_VAR_R; } ".var/s" { return K_VAR_S; } diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index e22d282a4..79ea00cc2 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1022,6 +1022,14 @@ that holds the index. This is the general method for getting string values into the vector space. The string value is NOT popped. +* %test_nul + +This instruction tests the contents of the addressed variable to see +if it is null. If it is, set bit 4 to 1. Otherwise, set bit 4 to 0. + +This is intended to implement the SystemVerilog expression +(==null), where is a class variable. + * %vpi_call [, ...] { } This instruction makes a call to a system task that was declared using diff --git a/vvp/parse.y b/vvp/parse.y index 9ff99ca83..5eba1e0c8 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -91,7 +91,8 @@ static struct __vpiModPath*modpath_dst = 0; %token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS %token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP %token K_UFUNC K_UFUNC_E K_UDP K_UDP_C K_UDP_S -%token K_VAR K_VAR_DARRAY K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U +%token K_VAR K_VAR_COBJECT K_VAR_DARRAY +%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_disable K_fork @@ -709,6 +710,9 @@ statement | T_LABEL K_VAR_DARRAY T_STRING ';' { compile_var_darray($1, $3); } + | T_LABEL K_VAR_COBJECT T_STRING ';' + { compile_var_cobject($1, $3); } + /* Net statements are similar to .var statements, except that they declare nets, and they have an input list. */ diff --git a/vvp/vpi_cobject.cc b/vvp/vpi_cobject.cc new file mode 100644 index 000000000..c406573ed --- /dev/null +++ b/vvp/vpi_cobject.cc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012 Picture Elements, Inc. + * Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "compile.h" +# include "vpi_priv.h" + +__vpiCobjectVar::__vpiCobjectVar(__vpiScope*sc, const char*na, vvp_net_t*ne) +: __vpiBaseVar(sc, na, ne) +{ +} + +int __vpiCobjectVar::get_type_code(void) const +{ return vpiClassVar; } + +int __vpiCobjectVar::vpi_get(int) +{ + return 0; +} + +void __vpiCobjectVar::vpi_get_value(p_vpi_value val) +{ + val->format = vpiSuppressVal; +} + +vpiHandle vpip_make_cobject_var(const char*name, vvp_net_t*net) +{ + struct __vpiScope*scope = vpip_peek_current_scope(); + const char*use_name = name ? vpip_name_string(name) : 0; + + class __vpiCobjectVar*obj = new __vpiCobjectVar(scope, use_name, net); + + return obj; +} diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index 74a2825ef..efe37a52f 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -34,7 +34,7 @@ using namespace std; __vpiDarrayVar::__vpiDarrayVar(__vpiScope*sc, const char*na, vvp_net_t*ne) -: scope_(sc), name_(na), net_(ne) +: __vpiBaseVar(sc, na, ne) { } @@ -44,7 +44,7 @@ int __vpiDarrayVar::get_type_code(void) const int __vpiDarrayVar::vpi_get(int code) { - vvp_fun_signal_object*fun = dynamic_cast (net_->fun); + vvp_fun_signal_object*fun = dynamic_cast (get_net()->fun); assert(fun); vvp_object_t val = fun->get_object(); vvp_darray*aval = dynamic_cast (val); diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 71127072e..eb6d497c3 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -64,6 +64,11 @@ void __vpiHandle::vpi_get_delays(p_vpi_delay) void __vpiHandle::vpi_put_delays(p_vpi_delay) { } +__vpiBaseVar::__vpiBaseVar(__vpiScope*scope, const char*name, vvp_net_t*net) +: scope_(scope), name_(name), net_(net) +{ +} + /* * The default behavior for the vpi_free_object to an object is to * suppress the actual operation. This is because handles are diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index d409f512d..723d6a95d 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -476,7 +476,20 @@ struct __vpiRealVar : public __vpiHandle { extern struct __vpiScope* vpip_scope(__vpiRealVar*sig); extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net); -class __vpiStringVar : public __vpiHandle { +class __vpiBaseVar : public __vpiHandle { + + public: + __vpiBaseVar(__vpiScope*scope, const char*name, vvp_net_t*net); + + inline vvp_net_t* get_net() const { return net_; } + + private: + struct __vpiScope* scope_; + const char*name_; + vvp_net_t*net_; +}; + +class __vpiStringVar : public __vpiBaseVar { public: __vpiStringVar(__vpiScope*scope, const char*name, vvp_net_t*net); @@ -484,18 +497,11 @@ class __vpiStringVar : public __vpiHandle { int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); - - inline vvp_net_t* get_net() const { return net_; } - - private: - struct __vpiScope* scope_; - const char*name_; - vvp_net_t*net_; }; extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net); -class __vpiDarrayVar : public __vpiHandle { +class __vpiDarrayVar : public __vpiBaseVar { public: __vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net); @@ -503,17 +509,22 @@ class __vpiDarrayVar : public __vpiHandle { int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); - - inline vvp_net_t* get_net() const { return net_; } - - private: - struct __vpiScope* scope_; - const char*name_; - vvp_net_t*net_; }; extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net); +class __vpiCobjectVar : public __vpiBaseVar { + + public: + __vpiCobjectVar(__vpiScope*scope, const char*name, vvp_net_t*net); + + int get_type_code(void) const; + int vpi_get(int code); + void vpi_get_value(p_vpi_value val); +}; + +extern vpiHandle vpip_make_cobject_var(const char*name, vvp_net_t*net); + /* * When a loaded VPI module announces a system task/function, one * __vpiUserSystf object is created to hold the definition of that diff --git a/vvp/vpi_string.cc b/vvp/vpi_string.cc index 9cddf7775..c2158850b 100644 --- a/vvp/vpi_string.cc +++ b/vvp/vpi_string.cc @@ -33,7 +33,7 @@ using namespace std; __vpiStringVar::__vpiStringVar(__vpiScope*sc, const char*na, vvp_net_t*ne) -: scope_(sc), name_(na), net_(ne) +: __vpiBaseVar(sc, na, ne) { } @@ -42,7 +42,7 @@ int __vpiStringVar::get_type_code(void) const int __vpiStringVar::vpi_get(int code) { - vvp_fun_signal_string*fun = dynamic_cast (net_->fun); + vvp_fun_signal_string*fun = dynamic_cast (get_net()->fun); assert(fun); string str = fun->get_string(); @@ -58,7 +58,7 @@ int __vpiStringVar::vpi_get(int code) void __vpiStringVar::vpi_get_value(p_vpi_value val) { - vvp_fun_signal_string*fun = dynamic_cast (net_->fun); + vvp_fun_signal_string*fun = dynamic_cast (get_net()->fun); assert(fun); string str = fun->get_string(); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index ff0a8a0a1..7ed3f659b 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -5108,6 +5108,25 @@ bool of_FILE_LINE(vthread_t, vvp_code_t cp) return true; } +/* + * %test_nul ; + */ +bool of_TEST_NUL(vthread_t thr, vvp_code_t cp) +{ + vvp_net_t*net = cp->net; + + assert(net); + vvp_fun_signal_object*obj = dynamic_cast (net->fun); + assert(obj); + + if (obj->get_object() == 0) + thr_put_bit(thr, 4, BIT4_1); + else + thr_put_bit(thr, 4, BIT4_0); + + return true; +} + bool of_VPI_CALL(vthread_t thr, vvp_code_t cp) { vpip_execute_vpi_call(thr, cp->handle); diff --git a/vvp/words.cc b/vvp/words.cc index bbbdce56e..9618cc5f4 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -78,8 +78,7 @@ void compile_varw_real(char*label, vvp_array_t array, __compile_var_real(label, 0, array, addr); } -static void __compile_var_string(char*label, char*name, - vvp_array_t array, unsigned long array_addr) +void compile_var_string(char*label, char*name) { vvp_net_t*net = new vvp_net_t; @@ -97,25 +96,12 @@ static void __compile_var_string(char*label, char*name, vpiHandle obj = vpip_make_string_var(name, net); compile_vpi_symbol(label, obj); - if (name) { - assert(!array); - vpip_attach_to_current_scope(obj); - } - if (array) { - assert(!name); - array_attach_word(array, array_addr, obj); - } + vpip_attach_to_current_scope(obj); free(label); delete[] name; } -void compile_var_string(char*label, char*name) -{ - __compile_var_string(label, name, 0, 0); -} - -static void __compile_var_darray(char*label, char*name, - vvp_array_t array, unsigned long array_addr) +void compile_var_darray(char*label, char*name) { vvp_net_t*net = new vvp_net_t; @@ -133,21 +119,32 @@ static void __compile_var_darray(char*label, char*name, vpiHandle obj = vpip_make_darray_var(name, net); compile_vpi_symbol(label, obj); - if (name) { - assert(!array); - vpip_attach_to_current_scope(obj); - } - if (array) { - assert(!name); - array_attach_word(array, array_addr, obj); - } + vpip_attach_to_current_scope(obj); free(label); delete[] name; } -void compile_var_darray(char*label, char*name) +void compile_var_cobject(char*label, char*name) { - __compile_var_darray(label, name, 0, 0); + vvp_net_t*net = new vvp_net_t; + + if (vpip_peek_current_scope()->is_automatic) { + vvp_fun_signal_object_aa*tmp = new vvp_fun_signal_object_aa; + net->fil = tmp; + net->fun = tmp; + } else { + net->fil = 0; + net->fun = new vvp_fun_signal_object_sa; + } + + define_functor_symbol(label, net); + + vpiHandle obj = vpip_make_cobject_var(name, net); + compile_vpi_symbol(label, obj); + + vpip_attach_to_current_scope(obj); + free(label); + delete[] name; } /*