Stub class object variables.

Create stub class objects at the vvp level and generate the code
to invoke that stub. Implement the routines needed to implement
a test for null object references.
This commit is contained in:
Stephen Williams 2012-11-16 19:13:06 -08:00
parent 6278a5760c
commit 3e7adbeda0
17 changed files with 211 additions and 57 deletions

View File

@ -48,6 +48,7 @@ EXTERN_C_START
#define vpiIntVar 612 #define vpiIntVar 612
#define vpiByteVar 614 #define vpiByteVar 614
#define vpiLogicVar vpiReg #define vpiLogicVar vpiReg
#define vpiClassVar 615
#define vpiStringVar 616 #define vpiStringVar 616
#define vpiBitVar 620 #define vpiBitVar 620
#define vpiArrayVar vpiRegArray #define vpiArrayVar vpiRegArray

View File

@ -485,6 +485,53 @@ static struct vector_info draw_binary_expr_eq_string(ivl_expr_t expr)
return res; 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, static struct vector_info draw_binary_expr_eq(ivl_expr_t expr,
unsigned ewid, unsigned ewid,
int stuff_ok_flag) 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); 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)) if (number_is_immediate(re,16,0) && !number_is_unknown(re))
return draw_eq_immediate(expr, ewid, le, re, stuff_ok_flag); return draw_eq_immediate(expr, ewid, le, re, stuff_ok_flag);

View File

@ -512,6 +512,11 @@ static void draw_reg_in_scope(ivl_signal_t sig)
vvp_mangle_name(ivl_signal_basename(sig)), vvp_mangle_name(ivl_signal_basename(sig)),
ivl_signal_local(sig)? " Local signal" : ""); 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 { } else {
fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n", fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",

View File

@ -65,7 +65,8 @@ dllib=@DLLIB@
MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"' 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_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 \ vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
vpip_to_dec.o vpip_format.o vvp_vpi.o vpip_to_dec.o vpip_format.o vvp_vpi.o

View File

@ -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_SUB_WR(vthread_t thr, vvp_code_t code);
extern bool of_SUBI(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_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_VPI_CALL(vthread_t thr, vvp_code_t code);
extern bool of_WAIT(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); extern bool of_XNOR(vthread_t thr, vvp_code_t code);

View File

@ -232,6 +232,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%substr/v",of_SUBSTR_V,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} }, { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%xnor/r", of_XNORR, 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; return sig->net;
} }
case vpiStringVar: { case vpiStringVar:
__vpiStringVar*sig = dynamic_cast<__vpiStringVar*>(vpi); case vpiArrayVar:
case vpiClassVar: {
__vpiBaseVar*sig = dynamic_cast<__vpiBaseVar*>(vpi);
return sig->get_net(); return sig->get_net();
} }
@ -344,11 +347,6 @@ vvp_net_t* vvp_net_lookup(const char*label)
return tmp->funct; return tmp->funct;
} }
case vpiArrayVar: {
__vpiDarrayVar*tmp = dynamic_cast<__vpiDarrayVar*>(vpi);
return tmp->get_net();
}
default: default:
fprintf(stderr, "Unsupported type %d.\n", fprintf(stderr, "Unsupported type %d.\n",
vpi->get_type_code()); vpi->get_type_code());

View File

@ -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_real(char*label, char*name);
extern void compile_var_string(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_darray(char*label, char*name);
extern void compile_var_cobject(char*label, char*name);
/* /*
* This function is used to create a scope port * This function is used to create a scope port

View File

@ -195,6 +195,7 @@ static char* strdupnew(char const *str)
".ufunc" { return K_UFUNC; } ".ufunc" { return K_UFUNC; }
".ufunc/e" { return K_UFUNC_E; } ".ufunc/e" { return K_UFUNC_E; }
".var" { return K_VAR; } ".var" { return K_VAR; }
".var/cobj" { return K_VAR_COBJECT; }
".var/darray" { return K_VAR_DARRAY; } ".var/darray" { return K_VAR_DARRAY; }
".var/real" { return K_VAR_R; } ".var/real" { return K_VAR_R; }
".var/s" { return K_VAR_S; } ".var/s" { return K_VAR_S; }

View File

@ -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. values into the vector space. The string value is NOT popped.
* %test_nul <var-label>
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
(<var>==null), where <var> is a class variable.
* %vpi_call <name> [, ...] {<real> <str>} * %vpi_call <name> [, ...] {<real> <str>}
This instruction makes a call to a system task that was declared using This instruction makes a call to a system task that was declared using

View File

@ -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_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_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_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_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
%token K_disable K_fork %token K_disable K_fork
@ -709,6 +710,9 @@ statement
| T_LABEL K_VAR_DARRAY T_STRING ';' | T_LABEL K_VAR_DARRAY T_STRING ';'
{ compile_var_darray($1, $3); } { 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 /* Net statements are similar to .var statements, except that they
declare nets, and they have an input list. */ declare nets, and they have an input list. */

50
vvp/vpi_cobject.cc Normal file
View File

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

View File

@ -34,7 +34,7 @@
using namespace std; using namespace std;
__vpiDarrayVar::__vpiDarrayVar(__vpiScope*sc, const char*na, vvp_net_t*ne) __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) int __vpiDarrayVar::vpi_get(int code)
{ {
vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (net_->fun); vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (get_net()->fun);
assert(fun); assert(fun);
vvp_object_t val = fun->get_object(); vvp_object_t val = fun->get_object();
vvp_darray*aval = dynamic_cast<vvp_darray*> (val); vvp_darray*aval = dynamic_cast<vvp_darray*> (val);

View File

@ -64,6 +64,11 @@ void __vpiHandle::vpi_get_delays(p_vpi_delay)
void __vpiHandle::vpi_put_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 * The default behavior for the vpi_free_object to an object is to
* suppress the actual operation. This is because handles are * suppress the actual operation. This is because handles are

View File

@ -476,7 +476,20 @@ struct __vpiRealVar : public __vpiHandle {
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig); extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net); 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: public:
__vpiStringVar(__vpiScope*scope, const char*name, vvp_net_t*net); __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 get_type_code(void) const;
int vpi_get(int code); int vpi_get(int code);
void vpi_get_value(p_vpi_value val); 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); extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net);
class __vpiDarrayVar : public __vpiHandle { class __vpiDarrayVar : public __vpiBaseVar {
public: public:
__vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net); __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 get_type_code(void) const;
int vpi_get(int code); int vpi_get(int code);
void vpi_get_value(p_vpi_value val); 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); 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 * When a loaded VPI module announces a system task/function, one
* __vpiUserSystf object is created to hold the definition of that * __vpiUserSystf object is created to hold the definition of that

View File

@ -33,7 +33,7 @@
using namespace std; using namespace std;
__vpiStringVar::__vpiStringVar(__vpiScope*sc, const char*na, vvp_net_t*ne) __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) int __vpiStringVar::vpi_get(int code)
{ {
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net_->fun); vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (get_net()->fun);
assert(fun); assert(fun);
string str = fun->get_string(); string str = fun->get_string();
@ -58,7 +58,7 @@ int __vpiStringVar::vpi_get(int code)
void __vpiStringVar::vpi_get_value(p_vpi_value val) void __vpiStringVar::vpi_get_value(p_vpi_value val)
{ {
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net_->fun); vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (get_net()->fun);
assert(fun); assert(fun);
string str = fun->get_string(); string str = fun->get_string();

View File

@ -5108,6 +5108,25 @@ bool of_FILE_LINE(vthread_t, vvp_code_t cp)
return true; return true;
} }
/*
* %test_nul <var-label>;
*/
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<vvp_fun_signal_object*> (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) bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
{ {
vpip_execute_vpi_call(thr, cp->handle); vpip_execute_vpi_call(thr, cp->handle);

View File

@ -78,8 +78,7 @@ void compile_varw_real(char*label, vvp_array_t array,
__compile_var_real(label, 0, array, addr); __compile_var_real(label, 0, array, addr);
} }
static void __compile_var_string(char*label, char*name, void compile_var_string(char*label, char*name)
vvp_array_t array, unsigned long array_addr)
{ {
vvp_net_t*net = new vvp_net_t; 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); vpiHandle obj = vpip_make_string_var(name, net);
compile_vpi_symbol(label, obj); compile_vpi_symbol(label, obj);
if (name) { vpip_attach_to_current_scope(obj);
assert(!array);
vpip_attach_to_current_scope(obj);
}
if (array) {
assert(!name);
array_attach_word(array, array_addr, obj);
}
free(label); free(label);
delete[] name; delete[] name;
} }
void compile_var_string(char*label, char*name) void compile_var_darray(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)
{ {
vvp_net_t*net = new vvp_net_t; 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); vpiHandle obj = vpip_make_darray_var(name, net);
compile_vpi_symbol(label, obj); compile_vpi_symbol(label, obj);
if (name) { vpip_attach_to_current_scope(obj);
assert(!array);
vpip_attach_to_current_scope(obj);
}
if (array) {
assert(!name);
array_attach_word(array, array_addr, obj);
}
free(label); free(label);
delete[] name; 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;
} }
/* /*