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: {
|
case IVL_EX_SELECT: {
|
||||||
ivl_expr_t vexpr = ivl_expr_oper1(expr);
|
ivl_expr_t vexpr = ivl_expr_oper1(expr);
|
||||||
ivl_expr_t bexpr;
|
ivl_expr_t bexpr;
|
||||||
|
ivl_expr_t wexpr;
|
||||||
|
|
||||||
assert(vexpr);
|
assert(vexpr);
|
||||||
|
|
||||||
|
|
@ -179,20 +180,38 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
|
|
||||||
/* The signal is part of an array. */
|
/* The signal is part of an array. */
|
||||||
/* Add &APV<> code here when it is finished. */
|
/* Add &APV<> code here when it is finished. */
|
||||||
if (ivl_expr_oper1(vexpr)) return 0;
|
|
||||||
|
|
||||||
bexpr = ivl_expr_oper2(expr);
|
bexpr = ivl_expr_oper2(expr);
|
||||||
|
|
||||||
/* This is a pad operation. */
|
/* This is a pad operation. */
|
||||||
if (!bexpr) return 0;
|
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. */
|
/* 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));
|
assert(! number_is_unknown(bexpr));
|
||||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
||||||
ivl_expr_signal(vexpr),
|
ivl_expr_signal(vexpr),
|
||||||
get_number_immediate(bexpr),
|
get_number_immediate(bexpr),
|
||||||
ivl_expr_width(expr));
|
ivl_expr_width(expr));
|
||||||
|
|
||||||
/* This is an indexed bit/part select. */
|
/* This is an indexed bit/part select. */
|
||||||
} else if (ivl_expr_type(bexpr) == IVL_EX_SIGNAL ||
|
} else if (ivl_expr_type(bexpr) == IVL_EX_SIGNAL ||
|
||||||
ivl_expr_type(bexpr) == IVL_EX_SELECT) {
|
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. */
|
/* Get the array word size. */
|
||||||
unsigned get_array_word_size(vvp_array_t array)
|
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_put_value(vpiHandle ref, p_vpi_value vp, int);
|
||||||
static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref);
|
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 = {
|
static const struct __vpirt vpip_arraymem_rt = {
|
||||||
vpiMemory,
|
vpiMemory,
|
||||||
vpi_array_get,
|
vpi_array_get,
|
||||||
|
|
@ -357,6 +370,20 @@ static const struct __vpirt vpip_array_vthr_A_rt = {
|
||||||
0
|
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), \
|
# define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \
|
||||||
(struct __vpiArray*)ref)
|
(struct __vpiArray*)ref)
|
||||||
|
|
||||||
|
|
@ -390,6 +417,16 @@ static struct __vpiArrayVthrA* array_vthr_a_from_handle(vpiHandle ref)
|
||||||
return (struct __vpiArrayVthrA*) 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)
|
static void array_make_vals_words(struct __vpiArray*parent)
|
||||||
{
|
{
|
||||||
assert(parent->vals_words == 0);
|
assert(parent->vals_words == 0);
|
||||||
|
|
@ -862,6 +899,72 @@ static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref)
|
||||||
return 0;
|
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,
|
void array_set_word(vvp_array_t arr,
|
||||||
unsigned address,
|
unsigned address,
|
||||||
unsigned part_off,
|
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)) {
|
} else if (struct __vpiArrayVthrA*tword = array_vthr_a_from_handle(obj)) {
|
||||||
parent = tword->array;
|
parent = tword->array;
|
||||||
cb->extra_data = tword->address;
|
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);
|
assert(parent);
|
||||||
|
|
@ -1592,14 +1699,20 @@ void compile_array_alias(char*label, char*name, char*src)
|
||||||
assert(!array_find(label));
|
assert(!array_find(label));
|
||||||
array_table->sym_set_value(label, obj);
|
array_table->sym_set_value(label, obj);
|
||||||
|
|
||||||
compile_vpi_symbol(label, &obj->base);
|
compile_vpi_symbol(label, vpi_handle(obj));
|
||||||
vpip_attach_to_current_scope(&obj->base);
|
vpip_attach_to_current_scope(vpi_handle(obj));
|
||||||
|
|
||||||
free(label);
|
free(label);
|
||||||
free(name);
|
free(name);
|
||||||
free(src);
|
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)
|
vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
|
||||||
{
|
{
|
||||||
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
||||||
|
|
@ -1617,9 +1730,16 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
|
||||||
obj->address = addr;
|
obj->address = addr;
|
||||||
obj->wid = 0;
|
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,
|
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
|
||||||
char*is_signed)
|
char*is_signed)
|
||||||
{
|
{
|
||||||
|
|
@ -1641,9 +1761,15 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
|
||||||
|
|
||||||
delete [] is_signed;
|
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)
|
vpiHandle vpip_make_vthr_A(char*label, char*symbol)
|
||||||
{
|
{
|
||||||
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
||||||
|
|
@ -1662,8 +1788,9 @@ vpiHandle vpip_make_vthr_A(char*label, char*symbol)
|
||||||
obj->address = 0;
|
obj->address = 0;
|
||||||
obj->wid = 0;
|
obj->wid = 0;
|
||||||
|
|
||||||
return &(obj->base);
|
return vpi_handle(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
|
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
|
||||||
{
|
{
|
||||||
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
||||||
|
|
@ -1681,7 +1808,27 @@ vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
|
||||||
obj->address = 0;
|
obj->address = 0;
|
||||||
obj->wid = 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)
|
void compile_array_cleanup(void)
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,7 @@ static char* strdupnew(char const *str)
|
||||||
/* Handle the specialized variable access functions. */
|
/* Handle the specialized variable access functions. */
|
||||||
|
|
||||||
"&A" { return K_A; }
|
"&A" { return K_A; }
|
||||||
|
"&APV" { return K_APV; }
|
||||||
"&PV" { return K_PV; }
|
"&PV" { return K_PV; }
|
||||||
|
|
||||||
"%"[.$_/a-zA-Z0-9]+ {
|
"%"[.$_/a-zA-Z0-9]+ {
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
||||||
vvp_delay_t*cdelay;
|
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_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_MOD_R K_ARITH_MOD_S
|
||||||
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
|
%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); }
|
{ $$ = vpip_make_PV($3, $5, $7); }
|
||||||
| K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER T_STRING ',' T_NUMBER '>'
|
| K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER T_STRING ',' T_NUMBER '>'
|
||||||
{ $$ = vpip_make_PV($3, $5, $6, $7, $9); }
|
{ $$ = 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. */
|
/* functor operands can only be a list of symbols. */
|
||||||
symbols
|
symbols
|
||||||
|
|
|
||||||
|
|
@ -127,10 +127,10 @@ struct __vpirt {
|
||||||
* "base" that is a __vpiHandle object. This template can convert any
|
* "base" that is a __vpiHandle object. This template can convert any
|
||||||
* of those structures into a vpiHandle object.
|
* 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; }
|
{ 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)); }
|
{ 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,
|
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
|
||||||
char*is_signed);
|
char*is_signed);
|
||||||
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle);
|
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
|
* This function is called before any compilation to load VPI
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue