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:
parent
498bfcd24b
commit
6662a3f78a
|
|
@ -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) {
|
||||
|
|
|
|||
159
vvp/array.cc
159
vvp/array.cc
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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]+ {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue