Add support for real/realtime arrays.
Support arrays of realtime variable arrays and net arrays. This involved a simple fix to the ivl core parser, proper support in the code generator, and rework the runtime support in vvp.
This commit is contained in:
parent
520d9b9dd0
commit
6cac1d2cab
8
parse.y
8
parse.y
|
|
@ -2978,7 +2978,13 @@ real_variable
|
|||
{ perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
if ($2 != 0) {
|
||||
yyerror(@2, "sorry: real variables do not currently support arrays.");
|
||||
index_component_t index;
|
||||
if ($2->size() > 1) {
|
||||
yyerror(@2, "sorry: only 1 dimensional arrays "
|
||||
"are currently supported.");
|
||||
}
|
||||
index = $2->front();
|
||||
pform_set_reg_idx(name, index.msb, index.lsb);
|
||||
delete $2;
|
||||
}
|
||||
$$ = $1;
|
||||
|
|
|
|||
|
|
@ -354,23 +354,17 @@ static int draw_signal_real_real(ivl_expr_t exp)
|
|||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
int res = allocate_word();
|
||||
unsigned long word = 0;
|
||||
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
ivl_expr_t ix = ivl_expr_oper1(exp);
|
||||
if (!number_is_immediate(ix, IMM_WID, 0)) {
|
||||
/* XXXX Need to generate a %load/ar instruction. */
|
||||
assert(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The index is constant, so we can return to direct
|
||||
readout with the specific word selected. */
|
||||
word = get_number_immediate(ix);
|
||||
if (ivl_signal_dimensions(sig) == 0) {
|
||||
fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, sig);
|
||||
return res;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%load/wr %d, v%p_%lu;\n", res, sig, word);
|
||||
|
||||
ivl_expr_t word_ex = ivl_expr_oper1(exp);
|
||||
int word_ix = allocate_word();
|
||||
draw_eval_expr_into_integer(word_ex, word_ix);
|
||||
fprintf(vvp_out, " %%load/ar %d, v%p, %d;\n", res, sig, word_ix);
|
||||
clr_word(word_ix);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -497,16 +497,30 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
|||
ivl_signal_t var;
|
||||
|
||||
res = draw_eval_real(ivl_stmt_rval(net));
|
||||
clr_word(res);
|
||||
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
var = ivl_lval_sig(lval);
|
||||
assert(var != 0);
|
||||
|
||||
assert(ivl_signal_dimensions(var) == 0);
|
||||
if (ivl_signal_dimensions(var) == 0) {
|
||||
clr_word(res);
|
||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
||||
// For now, only support 1-dimensional arrays.
|
||||
assert(ivl_signal_dimensions(var) == 1);
|
||||
|
||||
// Calculate the word index into an index register
|
||||
ivl_expr_t word_ex = ivl_lval_idx(lval);
|
||||
int word_ix = allocate_word();
|
||||
draw_eval_expr_into_integer(word_ex, word_ix);
|
||||
// Generate an assignment to write to the array.
|
||||
fprintf(vvp_out, " %%set/ar v%p, %d, %d;\n", var, word_ix, res);
|
||||
|
||||
clr_word(res);
|
||||
clr_word(word_ix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
108
vvp/array.cc
108
vvp/array.cc
|
|
@ -53,7 +53,28 @@ vvp_array_t array_find(const char*label)
|
|||
|
||||
/*
|
||||
* The vpiArray object holds an array of vpi objects that themselves
|
||||
* represent the words of the array. The vpi_array_t is a pointer to this.
|
||||
* represent the words of the array. The vpi_array_t is a pointer to
|
||||
* a struct __vpiArray.
|
||||
*
|
||||
* The details of the implementation depends on what this is an array
|
||||
* of. The easiest case is if this is an array of nets.
|
||||
*
|
||||
* - Array of Nets:
|
||||
* If this represents an array of nets, then the nets member points to
|
||||
* an array of vpiHandle objects. Each vpiHandle is a word. This is
|
||||
* done because typically each word of a net array is simultaneously
|
||||
* driven and accessed by other means, so there is no advantage to
|
||||
* compacting the array in any other way.
|
||||
*
|
||||
* - Array of vector4 words.
|
||||
* In this case, the nets pointer is nil, and the vals4 member points
|
||||
* to a vvl_vector4array_t object that is a compact representation of
|
||||
* an array of vvp_vector4_t vectors.
|
||||
*
|
||||
* - Array of real variables
|
||||
* The valsr member points to a vvp_realarray_t objects that has an
|
||||
* array of double variables. This is very much line the way the
|
||||
* vector4 array works.
|
||||
*/
|
||||
struct __vpiArray {
|
||||
__vpiArray() { }
|
||||
|
|
@ -70,7 +91,8 @@ struct __vpiArray {
|
|||
// If this is a net array, nets lists the handles.
|
||||
vpiHandle*nets;
|
||||
// If this is a var array, then these are used instead of nets.
|
||||
vvp_vector4array_t *vals;
|
||||
vvp_vector4array_t *vals4;
|
||||
vvp_realarray_t *valsr;
|
||||
struct __vpiArrayWord*vals_words;
|
||||
|
||||
class vvp_fun_arrayport*ports_;
|
||||
|
|
@ -127,7 +149,7 @@ struct __vpiArrayVthrA {
|
|||
/* Get the array word size. This has only been checked for reg arrays. */
|
||||
unsigned get_array_word_size(vvp_array_t array)
|
||||
{
|
||||
assert(array->vals);
|
||||
assert(array->vals4);
|
||||
return array->vals_width;
|
||||
}
|
||||
|
||||
|
|
@ -424,7 +446,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
|||
|
||||
switch (code) {
|
||||
case vpiSize:
|
||||
return (int) parent->vals->width();
|
||||
return (int) parent->vals4->width();
|
||||
|
||||
case vpiLeftRange:
|
||||
return parent->msb.value;
|
||||
|
|
@ -461,9 +483,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
|||
|
||||
assert(obj);
|
||||
unsigned index = decode_array_word_pointer(obj, parent);
|
||||
unsigned width = parent->vals->width();
|
||||
unsigned width = parent->vals4->width();
|
||||
|
||||
vpip_vec4_get_value(parent->vals->get_word(index), width,
|
||||
vpip_vec4_get_value(parent->vals4->get_word(index), width,
|
||||
parent->signed_flag, value);
|
||||
}
|
||||
|
||||
|
|
@ -539,7 +561,7 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int)
|
|||
if (obj->array->nets)
|
||||
return obj->array->nets[obj->next];
|
||||
|
||||
assert(obj->array->vals);
|
||||
assert(obj->array->vals4);
|
||||
|
||||
if (obj->array->vals_words == 0)
|
||||
array_make_vals_words(obj->array);
|
||||
|
|
@ -702,10 +724,10 @@ void array_set_word(vvp_array_t arr,
|
|||
if (address >= arr->array_count)
|
||||
return;
|
||||
|
||||
if (arr->vals) {
|
||||
if (arr->vals4) {
|
||||
assert(arr->nets == 0);
|
||||
if (part_off != 0 || val.size() != arr->vals_width) {
|
||||
vvp_vector4_t tmp = arr->vals->get_word(address);
|
||||
vvp_vector4_t tmp = arr->vals4->get_word(address);
|
||||
if ((part_off + val.size()) > tmp.size()) {
|
||||
cerr << "part_off=" << part_off
|
||||
<< " val.size()=" << val.size()
|
||||
|
|
@ -714,9 +736,9 @@ void array_set_word(vvp_array_t arr,
|
|||
assert(0);
|
||||
}
|
||||
tmp.set_vec(part_off, val);
|
||||
arr->vals->set_word(address, tmp);
|
||||
arr->vals4->set_word(address, tmp);
|
||||
} else {
|
||||
arr->vals->set_word(address, val);
|
||||
arr->vals4->set_word(address, val);
|
||||
}
|
||||
array_word_change(arr, address);
|
||||
return;
|
||||
|
|
@ -734,15 +756,22 @@ void array_set_word(vvp_array_t arr,
|
|||
array_word_change(arr, address);
|
||||
}
|
||||
|
||||
void array_set_word(vvp_array_t arr, unsigned address, double val)
|
||||
{
|
||||
assert(arr->valsr!= 0);
|
||||
assert(arr->nets == 0);
|
||||
|
||||
arr->valsr->set_word(address, val);
|
||||
}
|
||||
|
||||
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||
{
|
||||
if (arr->vals) {
|
||||
if (arr->vals4) {
|
||||
assert(arr->nets == 0);
|
||||
|
||||
return arr->vals->get_word(address);
|
||||
return arr->vals4->get_word(address);
|
||||
}
|
||||
|
||||
assert(arr->vals == 0);
|
||||
assert(arr->vals4 == 0);
|
||||
assert(arr->nets != 0);
|
||||
|
||||
if (address >= arr->array_count) {
|
||||
|
|
@ -767,6 +796,26 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
|||
return val;
|
||||
}
|
||||
|
||||
double array_get_word_r(vvp_array_t arr, unsigned address)
|
||||
{
|
||||
if (arr->valsr) {
|
||||
assert(arr->vals4 == 0);
|
||||
assert(arr->nets == 0);
|
||||
return arr->valsr->get_word(address);
|
||||
}
|
||||
|
||||
assert(arr->nets);
|
||||
vpiHandle word = arr->nets[address];
|
||||
struct __vpiRealVar*vsig = vpip_realvar_from_handle(word);
|
||||
assert(vsig);
|
||||
vvp_fun_signal_real*sig = dynamic_cast<vvp_fun_signal_real*> (vsig->net->fun);
|
||||
assert(sig);
|
||||
|
||||
double val = sig->real_value();
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
static vpiHandle vpip_make_array(char*label, const char*name,
|
||||
int first_addr, int last_addr,
|
||||
bool signed_flag)
|
||||
|
|
@ -792,7 +841,8 @@ static vpiHandle vpip_make_array(char*label, const char*name,
|
|||
|
||||
// Start off now knowing if we are nets or variables.
|
||||
obj->nets = 0;
|
||||
obj->vals = 0;
|
||||
obj->vals4 = 0;
|
||||
obj->valsr = 0;
|
||||
obj->vals_width = 0;
|
||||
vpip_make_dec_const(&obj->msb, 0);
|
||||
vpip_make_dec_const(&obj->lsb, 0);
|
||||
|
|
@ -869,11 +919,11 @@ void compile_var_array(char*label, char*name, int last, int first,
|
|||
/* Make the words. */
|
||||
arr->vals_width = labs(msb-lsb) + 1;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
arr->vals = new vvp_vector4array_aa(arr->vals_width,
|
||||
arr->array_count);
|
||||
arr->vals4 = new vvp_vector4array_aa(arr->vals_width,
|
||||
arr->array_count);
|
||||
} else {
|
||||
arr->vals = new vvp_vector4array_sa(arr->vals_width,
|
||||
arr->array_count);
|
||||
arr->vals4 = new vvp_vector4array_sa(arr->vals_width,
|
||||
arr->array_count);
|
||||
}
|
||||
vpip_make_dec_const(&arr->msb, msb);
|
||||
vpip_make_dec_const(&arr->lsb, lsb);
|
||||
|
|
@ -891,14 +941,16 @@ void compile_real_array(char*label, char*name, int last, int first,
|
|||
vpiHandle obj = vpip_make_array(label, name, first, last, true);
|
||||
|
||||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||
vvp_array_t array = array_find(label);
|
||||
|
||||
/* Make the words. */
|
||||
for (unsigned idx = 0 ; idx < arr->array_count ; idx += 1) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof buf, "%s_%u", label, idx);
|
||||
compile_varw_real(strdup(buf), array, idx, msb, lsb);
|
||||
}
|
||||
arr->valsr = new vvp_realarray_t(arr->array_count);
|
||||
arr->vals_width = 1;
|
||||
|
||||
/* Do these even make sense for real arrays? These are the
|
||||
part select of a vector, but the real value is not
|
||||
vectorable. */
|
||||
vpip_make_dec_const(&arr->msb, msb);
|
||||
vpip_make_dec_const(&arr->lsb, lsb);
|
||||
|
||||
count_real_arrays += 1;
|
||||
count_real_array_words += arr->array_count;
|
||||
|
|
@ -1146,7 +1198,7 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
|||
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
if (cur->cb_data.value)
|
||||
vpip_vec4_get_value(array->vals->get_word(addr),
|
||||
vpip_vec4_get_value(array->vals4->get_word(addr),
|
||||
array->vals_width,
|
||||
array->signed_flag,
|
||||
cur->cb_data.value);
|
||||
|
|
@ -1282,7 +1334,7 @@ void compile_array_alias(char*label, char*name, char*src)
|
|||
|
||||
// Share the words with the source array.
|
||||
obj->nets = mem->nets;
|
||||
obj->vals = mem->vals;
|
||||
obj->vals4 = mem->vals4;
|
||||
|
||||
obj->ports_ = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,13 @@ extern void array_attach_word(vvp_array_t array, unsigned long addr,
|
|||
extern void array_alias_word(vvp_array_t array, unsigned long addr,
|
||||
vpiHandle word);
|
||||
|
||||
extern void array_set_word(vvp_array_t arr,
|
||||
unsigned idx,
|
||||
unsigned off,
|
||||
vvp_vector4_t val);
|
||||
extern void array_set_word(vvp_array_t arr, unsigned idx,
|
||||
unsigned off, vvp_vector4_t val);
|
||||
extern void array_set_word(vvp_array_t arr, unsigned idx,
|
||||
double val);
|
||||
|
||||
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address);
|
||||
extern double array_get_word_r(vvp_array_t array, unsigned address);
|
||||
|
||||
/* VPI hooks */
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -138,6 +139,7 @@ extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_AR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
|
|
@ -181,11 +182,11 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||
{ "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
// { "%set/x0/x",of_SET_X0_X,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -512,9 +512,14 @@ The <wid> is, line the %load/v, the result width. But unlike the
|
|||
(%load/vp0/s) to the desired width.
|
||||
|
||||
* %load/wr <bit>, <vpi-label>
|
||||
* %load/ar <bit>, <array-label>, <index>
|
||||
|
||||
This instruction reads a real value from the vpi-like object to a word
|
||||
register.
|
||||
The %load/wr instruction reads a real value from the vpi-like object
|
||||
to a word register <bit>.
|
||||
|
||||
The %load/ar instruction reads a real value from an array. The <index>
|
||||
is the index register that contains the canonical word address into
|
||||
the array.
|
||||
|
||||
* %load/x1p <bit>, <functor-label>, <wid>
|
||||
|
||||
|
|
@ -708,8 +713,17 @@ The address (in canonical form) is precalculated and loaded into index
|
|||
register 3. This is the address of the word within the array.
|
||||
|
||||
* %set/wr <vpi-label>, <bit>
|
||||
* %set/ar <array-label>, <index>, <bit>
|
||||
|
||||
This instruction writes a real word to the specified VPI-like object.
|
||||
The %set/wr instruction writes a real word to the specified VPI-like
|
||||
object.
|
||||
|
||||
The %set/ar instruction writes a real work to the specified array
|
||||
word. The <array-label> addresses the array, and the <index> is the
|
||||
name of the index register to address into the word. The index
|
||||
register must contain an integer value that is the canonical address
|
||||
of the array word. The <bit> is the index register that contains the
|
||||
real value word to write.
|
||||
|
||||
* %set/x0 <var-label>, <bit>, <wid>
|
||||
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ struct __vpiRealVar {
|
|||
|
||||
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
|
||||
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
|
||||
extern struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj);
|
||||
|
||||
/*
|
||||
* When a loaded VPI module announces a system task/function, one
|
||||
|
|
|
|||
|
|
@ -28,11 +28,20 @@
|
|||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj)
|
||||
{
|
||||
assert(obj);
|
||||
if (obj->vpi_type->type_code == vpiRealVar)
|
||||
return (struct __vpiRealVar*)obj;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int real_var_get(int code, vpiHandle ref)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiRealVar);
|
||||
|
||||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
||||
struct __vpiRealVar*rfp = vpip_realvar_from_handle(ref);
|
||||
|
||||
switch (code) {
|
||||
case vpiArray:
|
||||
|
|
|
|||
|
|
@ -2752,6 +2752,20 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* %load/ar <bit>, <array-label>, <index>;
|
||||
*/
|
||||
bool of_LOAD_AR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
unsigned idx = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
|
||||
double word = array_get_word_r(cp->array, adr);
|
||||
thr->words[bit].w_real = word;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %load/av <bit>, <array-label>, <wid> ;
|
||||
*
|
||||
|
|
@ -3936,6 +3950,24 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %set/av <label>, <index>, <bit>
|
||||
*
|
||||
* Write the real value in register <bit> to the array indexed by the
|
||||
* integer value addressed bin index register <index>.
|
||||
*/
|
||||
bool of_SET_AR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned idx = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
|
||||
double value = thr->words[bit].w_real;
|
||||
array_set_word(cp->array, adr, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implements the "%set/av <label>, <bit>, <wid>" instruction. In
|
||||
* this case, the <label> is an array label, and the <bit> and <wid>
|
||||
|
|
|
|||
|
|
@ -1299,6 +1299,32 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
|
|||
return flag;
|
||||
}
|
||||
|
||||
vvp_realarray_t::vvp_realarray_t(unsigned wor)
|
||||
: words_(wor)
|
||||
{
|
||||
array_ = new double[words_];
|
||||
}
|
||||
|
||||
vvp_realarray_t::~vvp_realarray_t()
|
||||
{
|
||||
delete[]array_;
|
||||
}
|
||||
|
||||
void vvp_realarray_t::set_word(unsigned word, double value)
|
||||
{
|
||||
if (word >= words_)
|
||||
return;
|
||||
array_[word] = value;
|
||||
}
|
||||
|
||||
double vvp_realarray_t::get_word(unsigned word) const
|
||||
{
|
||||
if (word >= words_)
|
||||
return 0.0;
|
||||
else
|
||||
return array_[word];
|
||||
}
|
||||
|
||||
vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
|
||||
: width_(width__), words_(words__)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -467,6 +467,26 @@ extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
|
|||
#endif
|
||||
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
||||
|
||||
/*
|
||||
* The __vpiArray handle uses instances of this to keep an array of
|
||||
* real valued variables.
|
||||
*/
|
||||
class vvp_realarray_t {
|
||||
|
||||
public:
|
||||
vvp_realarray_t(unsigned words);
|
||||
~vvp_realarray_t();
|
||||
|
||||
unsigned words() const { return words_; }
|
||||
|
||||
double get_word(unsigned idx) const;
|
||||
void set_word(unsigned idx, double val);
|
||||
|
||||
private:
|
||||
unsigned words_;
|
||||
double*array_;
|
||||
};
|
||||
|
||||
/*
|
||||
* vvp_vector4array_t
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -270,6 +270,8 @@ void compile_netw_real(char*label, char*array_label, unsigned long array_addr,
|
|||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
cerr << "XXXX compile_netw_real: label=" << label
|
||||
<< ", array_label=" << array_label << endl;
|
||||
__compile_real(label, 0, array_label, array_addr,
|
||||
msb, lsb, false, argc, argv);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue