VPI access to atom2 types.

Create the .var/2u and .var/2s variable records and give them
basic implementations. Make available to VPI the proper types
for the SystemVerilog types that these variables represent.
This commit is contained in:
Stephen Williams 2010-10-07 18:01:11 -07:00
parent af6fd66648
commit 6a0cbc5fa8
13 changed files with 177 additions and 65 deletions

View File

@ -292,7 +292,7 @@ else
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
endif
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/sv_vpi_user.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
@ -313,6 +313,9 @@ $(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(includedir)/_pli_types.h: _pli_types.h
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_pli_types.h"
$(includedir)/sv_vpi_user.h: $(srcdir)/sv_vpi_user.h
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"

View File

@ -1047,6 +1047,10 @@ static int sys_check_args(vpiHandle callh, vpiHandle argv, const PLI_BYTE8*name,
case vpiNet:
case vpiReg:
case vpiIntegerVar:
case vpiByteVar:
case vpiShortIntVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiTimeVar:
case vpiRealVar:
case vpiSysFuncCall:

View File

@ -20,7 +20,7 @@
*/
#include "vpi_config.h"
#include "vpi_user.h"
#include "sv_vpi_user.h"
/*
* Context structure for PRNG in mt19937int.c

View File

@ -278,8 +278,10 @@ A variable is a bit vector that can be written by behavioral code (so
has no structural input) and propagates its output to a functor. The
general syntax of a variable is:
<label> .var "name", <msb>, <lsb>; Unsigned logic variable
<label> .var/s "name", <msb>, <lsb>; Signed logic variable
<label> .var "name", <msb> <lsb>; Unsigned logic variable
<label> .var/s "name", <msb> <lsb>; Signed logic variable
<label> .var/2u "name", <msb> <lsb>; Unsigned bool/bit variable
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
<label> .var/real "name", <msb>, <lsb>; real varibale
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar variable

View File

@ -52,9 +52,6 @@ extern void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle word);
extern void vpip_array_change(struct __vpiCallback*cb, vpiHandle word);
/* Compile hooks */
extern void compile_variablew(char*label, vvp_array_t array,
unsigned long array_addr,
int msb, int lsb, char signed_flag);
extern void compile_varw_real(char*label, vvp_array_t array,
unsigned long array_addr,
int msb, int lsb);

View File

@ -285,6 +285,10 @@ vvp_net_t* vvp_net_lookup(const char*label)
switch (vpi->vpi_type->type_code) {
case vpiNet:
case vpiReg:
case vpiByteVar:
case vpiShortIntVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiIntegerVar: {
__vpiSignal*sig = (__vpiSignal*)vpi;
return sig->node;

View File

@ -23,7 +23,7 @@
# include <fstream>
# include <vector>
# include "parse_misc.h"
# include "vpi_user.h"
# include "sv_vpi_user.h"
# include "vvp_net.h"
using namespace std;
@ -431,10 +431,15 @@ extern void compile_thread(char*start_sym, char*flag);
/*
* This function is called to create a var vector with the given name.
*
* The vpi_type_code argument of compile_variable() is one of the vpi
* object codes that identify the type: vpiReg, vpiIntegerVar,
* vpiIntVar, etc.
*/
extern void compile_variable(char*label, char*name,
int msb, int lsb, char signed_flag,
bool local_flag);
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag);
extern void compile_var_real(char*label, char*name,
int msb, int lsb);

View File

@ -188,6 +188,8 @@ static char* strdupnew(char const *str)
".var/real" { return K_VAR_R; }
".var/s" { return K_VAR_S; }
".var/i" { return K_VAR_I; /* integer */ }
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
".udp" { return K_UDP; }
".udp/c"(omb)? { return K_UDP_C; }
".udp/s"(equ)? { return K_UDP_S; }

View File

@ -84,7 +84,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_S K_VAR_I K_VAR_R K_vpi_call K_vpi_call_w K_vpi_call_i
%token K_VAR K_VAR_S 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
%token K_ivl_version K_ivl_delay_selection
@ -650,13 +651,19 @@ statement
the variable in the netlist. */
| T_LABEL K_VAR local_flag T_STRING ',' signed_t_number signed_t_number ';'
{ compile_variable($1, $4, $6, $7, 0 /* unsigned */, $3); }
{ compile_variable($1, $4, $6, $7, vpiLogicVar, false, $3); }
| T_LABEL K_VAR_S local_flag T_STRING ',' signed_t_number signed_t_number ';'
{ compile_variable($1, $4, $6, $7, 1 /* signed */, $3); }
{ compile_variable($1, $4, $6, $7, vpiLogicVar, true, $3); }
| T_LABEL K_VAR_I local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
{ compile_variable($1, $4, $6, $7, 2 /* integer */, $3); }
{ compile_variable($1, $4, $6, $7, vpiIntegerVar, true, $3); }
| T_LABEL K_VAR_2S local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
{ compile_variable($1, $4, $6, $7, vpiIntVar, true, $3); }
| T_LABEL K_VAR_2U local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
{ compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); }
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
{ compile_var_real($1, $3, $5, $6); }

View File

@ -255,14 +255,20 @@ static const char* vpi_type_values(PLI_INT32 code)
{
static char buf[32];
switch (code) {
case vpiByteVar:
return "vpiByteVar";
case vpiConstant:
return "vpiConstant";
case vpiFunction:
return "vpiFunction";
case vpiIntVar:
return "vpiIntVar";
case vpiIntegerVar:
return "vpiIntegerVar";
case vpiIterator:
return "vpiIterator";
case vpiLongIntVar:
return "vpiLongIntVar";
case vpiMemory:
return "vpiMemory";
case vpiMemoryWord:
@ -287,6 +293,8 @@ static const char* vpi_type_values(PLI_INT32 code)
return "vpiRealVar";
case vpiReg:
return "vpiReg";
case vpiShortIntVar:
return "vpiShortIntVar";
case vpiSysFuncCall:
return "vpiSysFuncCall";
case vpiSysTaskCall:
@ -318,9 +326,7 @@ PLI_INT32 vpi_get(int property, vpiHandle ref)
}
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
return vpiIntegerVar;
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
return vpiNetArray;
else
return ref->vpi_type->type_code;
@ -375,9 +381,7 @@ char* vpi_get_str(PLI_INT32 property, vpiHandle ref)
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
PLI_INT32 type;
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
type = vpiIntegerVar;
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
type = vpiNetArray;
else
type = ref->vpi_type->type_code;

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vpi_user.h"
# include "sv_vpi_user.h"
# include "vvp_net.h"
# include "config.h"
@ -243,7 +243,6 @@ struct __vpiSignal {
int msb, lsb;
/* Flags */
unsigned signed_flag : 1;
unsigned isint_ : 1; // original type was integer
unsigned is_netarray : 1; // This is word of a net array
/* The represented value is here. */
vvp_net_t*node;
@ -251,12 +250,14 @@ struct __vpiSignal {
extern unsigned vpip_size(__vpiSignal *sig);
extern struct __vpiScope* vpip_scope(__vpiSignal*sig);
extern vpiHandle vpip_make_int(const char*name, int msb, int lsb,
extern vpiHandle vpip_make_int2(const char*name, int msb, int lsb,
vvp_net_t*vec);
extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb,
vvp_net_t*vec);
extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*net);
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
/*
* This is used by system calls to represent a bit/part select of

View File

@ -506,11 +506,19 @@ static void format_vpiVectorVal(vvp_signal_value*sig, int base, unsigned wid,
struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref)
{
if ((ref->vpi_type->type_code != vpiNet)
&& (ref->vpi_type->type_code != vpiReg))
return 0;
switch (ref->vpi_type->type_code) {
case vpiNet:
case vpiReg:
case vpiIntegerVar:
case vpiByteVar:
case vpiShortIntVar:
case vpiIntVar:
case vpiLongIntVar:
return (struct __vpiSignal*)ref;
return (struct __vpiSignal*)ref;
default:
return 0;
}
}
/*
@ -870,6 +878,17 @@ static const struct __vpirt vpip_reg_rt = {
0
};
static const struct __vpirt vpip_integer_rt = {
vpiIntegerVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_net_rt = {
vpiNet,
signal_get,
@ -881,31 +900,97 @@ static const struct __vpirt vpip_net_rt = {
0
};
static const struct __vpirt vpip_byte_rt = {
vpiByteVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_shortint_rt = {
vpiShortIntVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_int_rt = {
vpiIntVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_longint_rt = {
vpiLongIntVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
/*
* Construct a vpiIntegerVar object. Indicate the type using a flag
* to minimize the code modifications. Icarus implements integers
* as 'reg signed [31:0]'.
*/
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net(name, msb,lsb, true, vec);
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
obj->vpi_type = &vpip_reg_rt;
rfp->isint_ = true;
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
obj->vpi_type = &vpip_integer_rt;
return obj;
}
vpiHandle vpip_make_int2(const char*name, int msb, int lsb, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
assert(lsb == 0);
switch (msb) {
case 7:
obj->vpi_type = &vpip_byte_rt;
break;
case 15:
obj->vpi_type = &vpip_shortint_rt;
break;
case 31:
obj->vpi_type = &vpip_int_rt;
break;
case 63:
obj->vpi_type = &vpip_longint_rt;
break;
}
return obj;
}
/*
* Construct a vpiReg object. It's like a net, except for the type.
* Construct a vpiReg/vpiLogicVar object. It's like a net, except for the type.
*/
vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
vpiHandle obj = vpip_make_net4(name, msb,lsb, signed_flag, vec);
obj->vpi_type = &vpip_reg_rt;
return obj;
}
#ifdef CHECK_WITH_VALGRIND
static struct __vpiSignal **signal_pool = 0;
static unsigned signal_pool_count = 0;
@ -981,7 +1066,7 @@ void signal_pool_delete()
* The name is the PLI name for the object. If it is an array it is
* <name>[<index>].
*/
vpiHandle vpip_make_net(const char*name, int msb, int lsb,
vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node)
{
struct __vpiSignal*obj = allocate_vpiSignal();
@ -990,7 +1075,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
obj->msb = msb;
obj->lsb = lsb;
obj->signed_flag = signed_flag? 1 : 0;
obj->isint_ = 0;
obj->is_netarray = 0;
obj->node = node;

View File

@ -84,7 +84,8 @@ void compile_varw_real(char*label, vvp_array_t array,
*/
static void __compile_var(char*label, char*name,
vvp_array_t array, unsigned long array_addr,
int msb, int lsb, char signed_flag, bool local_flag)
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
@ -105,9 +106,21 @@ static void __compile_var(char*label, char*name,
vpiHandle obj = 0;
if (! local_flag && !array) {
/* Make the vpiHandle for the reg. */
obj = (signed_flag > 1) ?
vpip_make_int(name, msb, lsb, net) :
vpip_make_reg(name, msb, lsb, signed_flag!=0, net);
switch (vpi_type_code) {
case vpiLogicVar:
obj = vpip_make_var4(name, msb, lsb, signed_flag, net);
break;
case vpiIntegerVar:
obj = vpip_make_int4(name, msb, lsb, net);
break;
case vpiIntVar: // This handles all the atom2 int types
obj = vpip_make_int2(name, msb, lsb, net);
break;
default:
fprintf(stderr, "internal error: %s: vpi_type_code=%d\n", name, vpi_type_code);
break;
}
assert(obj);
compile_vpi_symbol(label, obj);
}
// If the signal has a name, then it goes into the current
@ -132,24 +145,10 @@ static void __compile_var(char*label, char*name,
}
void compile_variable(char*label, char*name,
int msb, int lsb, char signed_flag, bool local_flag)
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag)
{
__compile_var(label, name, 0, 0, msb, lsb, signed_flag, local_flag);
}
/*
* In this case, the variable it intended to be attached to the array
* as a word. The array_addr is the *canonical* address of the word in
* the array.
*
* This function is actually used by the compile_array function,
* instead of directly by the parser.
*/
void compile_variablew(char*label, vvp_array_t array,
unsigned long array_addr,
int msb, int lsb, char signed_flag)
{
__compile_var(label, 0, array, array_addr, msb, lsb, signed_flag, false);
__compile_var(label, name, 0, 0, msb, lsb, vpi_type_code, signed_flag, local_flag);
}
vvp_net_t* create_constant_node(const char*label, const char*val_str)
@ -238,7 +237,7 @@ class __compile_net_resolv : public base_net_resolv {
* references into the net.
*/
static void __compile_net2(vvp_net_t*node, vvp_array_t array,
static void do_compile_net(vvp_net_t*node, vvp_array_t array,
struct __vpiScope*scope,
char*my_label, char*name,
int msb, int lsb, unsigned array_addr,
@ -260,7 +259,7 @@ static void __compile_net2(vvp_net_t*node, vvp_array_t array,
vpiHandle obj = 0;
if (! local_flag) {
/* Make the vpiHandle for the reg. */
obj = vpip_make_net(name, msb, lsb, signed_flag, node);
obj = vpip_make_net4(name, msb, lsb, signed_flag, node);
/* This attaches the label to the vpiHandle */
compile_vpi_symbol(my_label, obj);
}
@ -321,7 +320,7 @@ static void __compile_net(char*label,
assert(node);
struct __vpiScope*scope = vpip_peek_current_scope();
__compile_net2(node, array, scope, label, name, msb, lsb, array_addr,
do_compile_net(node, array, scope, label, name, msb, lsb, array_addr,
signed_flag, net8_flag, local_flag);
free(argv[0].text);
@ -335,7 +334,7 @@ bool __compile_net_resolv::resolve(bool msg_flag)
return false;
}
__compile_net2(node, array_, scope_, my_label_, name_, msb_, lsb_, array_addr_, signed_flag_, net8_flag_, local_flag_);
do_compile_net(node, array_, scope_, my_label_, name_, msb_, lsb_, array_addr_, signed_flag_, net8_flag_, local_flag_);
return true;
}