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:
parent
6278a5760c
commit
3e7adbeda0
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
51
vvp/words.cc
51
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue