Better VPI reference to part of array word.

Create the &APV<> token in vvp that create a VPI handle for a
part of an array word. This works better with things like $monitor.
This commit is contained in:
Stephen Williams 2012-01-10 18:22:52 -08:00
parent 498bfcd24b
commit 6662a3f78a
5 changed files with 183 additions and 12 deletions

View File

@ -170,6 +170,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
case IVL_EX_SELECT: {
ivl_expr_t vexpr = ivl_expr_oper1(expr);
ivl_expr_t bexpr;
ivl_expr_t wexpr;
assert(vexpr);
@ -179,20 +180,38 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
/* The signal is part of an array. */
/* Add &APV<> code here when it is finished. */
if (ivl_expr_oper1(vexpr)) return 0;
bexpr = ivl_expr_oper2(expr);
/* This is a pad operation. */
if (!bexpr) return 0;
wexpr = ivl_expr_oper1(vexpr);
/* If vexpr has an operand, then that operand is a word
index and we are taking a select from an array
word. This would come up in expressions like
"array[<word>][<part>]" where wexpr is <word> */
if (wexpr && number_is_immediate(wexpr, 64, 1)
&& number_is_immediate(bexpr, 64, 1)) {
assert(! number_is_unknown(bexpr));
assert(! number_is_unknown(wexpr));
snprintf(buffer, sizeof buffer, "&APV<v%p, %ld, %ld, %u>",
ivl_expr_signal(vexpr),
get_number_immediate(wexpr),
get_number_immediate(bexpr),
ivl_expr_width(expr));
} else if (wexpr) {
return 0;
/* This is a constant bit/part select. */
if (number_is_immediate(bexpr, 64, 1)) {
} else if (number_is_immediate(bexpr, 64, 1)) {
assert(! number_is_unknown(bexpr));
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
ivl_expr_signal(vexpr),
get_number_immediate(bexpr),
ivl_expr_width(expr));
/* This is an indexed bit/part select. */
} else if (ivl_expr_type(bexpr) == IVL_EX_SIGNAL ||
ivl_expr_type(bexpr) == IVL_EX_SELECT) {

View File

@ -182,6 +182,15 @@ struct __vpiArrayVthrA {
}
};
struct __vpiArrayVthrAPV {
struct __vpiHandle base;
struct __vpiArray*array;
unsigned word_sel;
unsigned part_bit;
unsigned part_wid;
};
/* Get the array word size. */
unsigned get_array_word_size(vvp_array_t array)
{
@ -270,6 +279,10 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp);
static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int);
static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref);
static int vpi_array_vthr_APV_get(int code, vpiHandle);
static char*vpi_array_vthr_APV_get_str(int code, vpiHandle);
static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp);
static const struct __vpirt vpip_arraymem_rt = {
vpiMemory,
vpi_array_get,
@ -357,6 +370,20 @@ static const struct __vpirt vpip_array_vthr_A_rt = {
0
};
static const struct __vpirt vpip_array_vthr_APV_rt = {
vpiMemoryWord,
&vpi_array_vthr_APV_get,
&vpi_array_vthr_APV_get_str,
&vpi_array_vthr_APV_get_value,
0, //&vpi_array_vthr_A_put_value,
0, //&vpi_array_vthr_A_get_handle,
0,
0,
0,
0,
0
};
# define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \
(struct __vpiArray*)ref)
@ -390,6 +417,16 @@ static struct __vpiArrayVthrA* array_vthr_a_from_handle(vpiHandle ref)
return (struct __vpiArrayVthrA*) ref;
}
static struct __vpiArrayVthrAPV* array_vthr_apv_from_handle(vpiHandle ref)
{
if (ref == 0)
return 0;
if (ref->vpi_type != &vpip_array_vthr_APV_rt)
return 0;
return (struct __vpiArrayVthrAPV*) ref;
}
static void array_make_vals_words(struct __vpiArray*parent)
{
assert(parent->vals_words == 0);
@ -862,6 +899,72 @@ static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref)
return 0;
}
static int vpi_array_vthr_APV_get(int code, vpiHandle ref)
{
struct __vpiArrayVthrAPV*obj = array_vthr_apv_from_handle(ref);
struct __vpiArray*parent = obj->array;
switch (code) {
case vpiLineNo:
return 0; // Not implemented for now!
case vpiSize:
return obj->part_wid;
case vpiLeftRange:
return parent->msb.value;
case vpiRightRange:
return parent->lsb.value;
case vpiIndex:
return (int)obj->word_sel;
case vpiAutomatic:
return (int) parent->scope->is_automatic;
case vpiConstantSelect:
return 1;
default:
return 0;
}
}
static char*vpi_array_vthr_APV_get_str(int code, vpiHandle ref)
{
struct __vpiArrayVthrAPV*obj = array_vthr_apv_from_handle(ref);
assert(obj);
struct __vpiArray*parent = obj->array;
if (code == vpiFile) { // Not implemented for now!
return simple_set_rbuf_str(file_names[0]);
}
char sidx [64];
snprintf(sidx, 63, "%u", obj->word_sel + parent->first_addr.value);
return generic_get_str(code, &parent->scope->base, parent->name, sidx);
}
static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp)
{
struct __vpiArrayVthrAPV*obj = array_vthr_apv_from_handle(ref);
assert(obj);
struct __vpiArray*parent = obj->array;
assert(parent);
unsigned index = obj->word_sel;
if (vpi_array_is_real(parent)) {
double tmp = array_get_word_r(parent, index);
vpip_real_get_value(tmp, vp);
} else {
vvp_vector4_t tmp = array_get_word(parent, index);
tmp = tmp.subvalue(obj->part_bit, obj->part_wid);
vpip_vec4_get_value(tmp, obj->part_wid, parent->signed_flag, vp);
}
}
void array_set_word(vvp_array_t arr,
unsigned address,
unsigned part_off,
@ -1517,6 +1620,10 @@ void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle obj)
} else if (struct __vpiArrayVthrA*tword = array_vthr_a_from_handle(obj)) {
parent = tword->array;
cb->extra_data = tword->address;
} else if (struct __vpiArrayVthrAPV*apvword = array_vthr_apv_from_handle(obj)) {
parent = apvword->array;
cb->extra_data = apvword->word_sel;
}
assert(parent);
@ -1592,14 +1699,20 @@ void compile_array_alias(char*label, char*name, char*src)
assert(!array_find(label));
array_table->sym_set_value(label, obj);
compile_vpi_symbol(label, &obj->base);
vpip_attach_to_current_scope(&obj->base);
compile_vpi_symbol(label, vpi_handle(obj));
vpip_attach_to_current_scope(vpi_handle(obj));
free(label);
free(name);
free(src);
}
/*
* &A<label,addr>
* This represents a VPI handle for an addressed array. This comes
* from expressions like "label[addr]" where "label" is the array and
* "addr" is the canonical address of the desired word.
*/
vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
{
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
@ -1617,9 +1730,16 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
obj->address = addr;
obj->wid = 0;
return &(obj->base);
return vpi_handle(obj);
}
/*
* &A<label,tbase,twid,s>
* This represents a VPI handle for an addressed word, where the word
* address in thread vector space. The tbase/twod/is_signed variables
* are the location and interpretation of the bits. This comes from
* source expressions that look like label[<expr>].
*/
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
char*is_signed)
{
@ -1641,9 +1761,15 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
delete [] is_signed;
return &(obj->base);
return vpi_handle(obj);
}
/*
* &A<label,symbol>
* This represents a VPI handle for an addressed word, where the
* word address is calculated from the VPI object that symbol
* represents. The expression that leads to this looks like label[symbol].
*/
vpiHandle vpip_make_vthr_A(char*label, char*symbol)
{
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
@ -1662,8 +1788,9 @@ vpiHandle vpip_make_vthr_A(char*label, char*symbol)
obj->address = 0;
obj->wid = 0;
return &(obj->base);
return vpi_handle(obj);
}
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
{
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
@ -1681,7 +1808,27 @@ vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
obj->address = 0;
obj->wid = 0;
return &(obj->base);
return vpi_handle(obj);
}
vpiHandle vpip_make_vthr_APV(char*label, unsigned index, unsigned bit, unsigned wid)
{
struct __vpiArrayVthrAPV*obj = (struct __vpiArrayVthrAPV*)
malloc(sizeof (struct __vpiArrayVthrAPV));
obj->base.vpi_type = &vpip_array_vthr_APV_rt;
array_resolv_list_t*resolv_mem
= new array_resolv_list_t(label);
resolv_mem->array = &obj->array;
resolv_submit(resolv_mem);
obj->word_sel = index;
obj->part_bit = bit;
obj->part_wid = wid;
return vpi_handle(obj);
}
void compile_array_cleanup(void)

View File

@ -220,6 +220,7 @@ static char* strdupnew(char const *str)
/* Handle the specialized variable access functions. */
"&A" { return K_A; }
"&APV" { return K_APV; }
"&PV" { return K_PV; }
"%"[.$_/a-zA-Z0-9]+ {

View File

@ -70,7 +70,7 @@ static struct __vpiModPath*modpath_dst = 0;
vvp_delay_t*cdelay;
};
%token K_A K_ALIAS K_ALIAS_R
%token K_A K_ALIAS K_ALIAS_R K_APV
%token K_ARITH_ABS K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD
%token K_ARITH_MOD_R K_ARITH_MOD_S
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
@ -971,6 +971,9 @@ symbol_access
{ $$ = vpip_make_PV($3, $5, $7); }
| K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER T_STRING ',' T_NUMBER '>'
{ $$ = vpip_make_PV($3, $5, $6, $7, $9); }
| K_APV '<' T_SYMBOL ',' T_NUMBER ',' T_NUMBER ',' T_NUMBER '>'
{ $$ = vpip_make_vthr_APV($3, $5, $7, $9); }
;
/* functor operands can only be a list of symbols. */
symbols

View File

@ -127,10 +127,10 @@ struct __vpirt {
* "base" that is a __vpiHandle object. This template can convert any
* of those structures into a vpiHandle object.
*/
template <class T> vpiHandle vpi_handle(T obj)
template <class T> inline vpiHandle vpi_handle(T obj)
{ return &obj->base; }
template <class T> char*vpip_get_str(int code, T obj)
template <class T> inline char*vpip_get_str(int code, T obj)
{ return obj->base.vpi_type->vpi_get_str_(code, vpi_handle(obj)); }
/*
@ -519,6 +519,7 @@ vpiHandle vpip_make_vthr_A(char*label, char*symbol);
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
char*is_signed);
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle);
vpiHandle vpip_make_vthr_APV(char*label, unsigned index, unsigned bit, unsigned wid);
/*
* This function is called before any compilation to load VPI