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 vpiByteVar 614
#define vpiLogicVar vpiReg
#define vpiClassVar 615
#define vpiStringVar 616
#define vpiBitVar 620
#define vpiArrayVar vpiRegArray

View File

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

View File

@ -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",

View File

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

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_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);

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} },
{ "%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());

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_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

View File

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

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.
* %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>}
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_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. */

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;
__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<vvp_fun_signal_object*> (net_->fun);
vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (get_net()->fun);
assert(fun);
vvp_object_t val = fun->get_object();
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)
{ }
__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

View File

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

View File

@ -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<vvp_fun_signal_string*> (net_->fun);
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (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<vvp_fun_signal_string*> (net_->fun);
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (get_net()->fun);
assert(fun);
string str = fun->get_string();

View File

@ -5108,6 +5108,25 @@ bool of_FILE_LINE(vthread_t, vvp_code_t cp)
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)
{
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);
}
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;
}
/*