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:
Stephen Williams 2008-11-01 20:44:03 -07:00
parent 520d9b9dd0
commit 6cac1d2cab
14 changed files with 229 additions and 55 deletions

View File

@ -2978,7 +2978,13 @@ real_variable
{ perm_string name = lex_strings.make($1); { perm_string name = lex_strings.make($1);
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0); pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
if ($2 != 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; delete $2;
} }
$$ = $1; $$ = $1;

View File

@ -354,23 +354,17 @@ static int draw_signal_real_real(ivl_expr_t exp)
{ {
ivl_signal_t sig = ivl_expr_signal(exp); ivl_signal_t sig = ivl_expr_signal(exp);
int res = allocate_word(); int res = allocate_word();
unsigned long word = 0;
if (ivl_signal_dimensions(sig) > 0) { if (ivl_signal_dimensions(sig) == 0) {
ivl_expr_t ix = ivl_expr_oper1(exp); fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, sig);
if (!number_is_immediate(ix, IMM_WID, 0)) {
/* XXXX Need to generate a %load/ar instruction. */
assert(0);
return res; return res;
} }
/* The index is constant, so we can return to direct ivl_expr_t word_ex = ivl_expr_oper1(exp);
readout with the specific word selected. */ int word_ix = allocate_word();
word = get_number_immediate(ix); 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);
fprintf(vvp_out, " %%load/wr %d, v%p_%lu;\n", res, sig, word);
return res; return res;
} }

View File

@ -497,16 +497,30 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
ivl_signal_t var; ivl_signal_t var;
res = draw_eval_real(ivl_stmt_rval(net)); res = draw_eval_real(ivl_stmt_rval(net));
clr_word(res);
assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0); lval = ivl_stmt_lval(net, 0);
var = ivl_lval_sig(lval); var = ivl_lval_sig(lval);
assert(var != 0); 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); fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
return 0;
}
// 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; return 0;
} }

View File

@ -53,7 +53,28 @@ vvp_array_t array_find(const char*label)
/* /*
* The vpiArray object holds an array of vpi objects that themselves * 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 { struct __vpiArray {
__vpiArray() { } __vpiArray() { }
@ -70,7 +91,8 @@ struct __vpiArray {
// If this is a net array, nets lists the handles. // If this is a net array, nets lists the handles.
vpiHandle*nets; vpiHandle*nets;
// If this is a var array, then these are used instead of 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; struct __vpiArrayWord*vals_words;
class vvp_fun_arrayport*ports_; class vvp_fun_arrayport*ports_;
@ -127,7 +149,7 @@ struct __vpiArrayVthrA {
/* Get the array word size. This has only been checked for reg arrays. */ /* Get the array word size. This has only been checked for reg arrays. */
unsigned get_array_word_size(vvp_array_t array) unsigned get_array_word_size(vvp_array_t array)
{ {
assert(array->vals); assert(array->vals4);
return array->vals_width; return array->vals_width;
} }
@ -424,7 +446,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
switch (code) { switch (code) {
case vpiSize: case vpiSize:
return (int) parent->vals->width(); return (int) parent->vals4->width();
case vpiLeftRange: case vpiLeftRange:
return parent->msb.value; return parent->msb.value;
@ -461,9 +483,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
assert(obj); assert(obj);
unsigned index = decode_array_word_pointer(obj, parent); 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); parent->signed_flag, value);
} }
@ -539,7 +561,7 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int)
if (obj->array->nets) if (obj->array->nets)
return obj->array->nets[obj->next]; return obj->array->nets[obj->next];
assert(obj->array->vals); assert(obj->array->vals4);
if (obj->array->vals_words == 0) if (obj->array->vals_words == 0)
array_make_vals_words(obj->array); array_make_vals_words(obj->array);
@ -702,10 +724,10 @@ void array_set_word(vvp_array_t arr,
if (address >= arr->array_count) if (address >= arr->array_count)
return; return;
if (arr->vals) { if (arr->vals4) {
assert(arr->nets == 0); assert(arr->nets == 0);
if (part_off != 0 || val.size() != arr->vals_width) { 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()) { if ((part_off + val.size()) > tmp.size()) {
cerr << "part_off=" << part_off cerr << "part_off=" << part_off
<< " val.size()=" << val.size() << " val.size()=" << val.size()
@ -714,9 +736,9 @@ void array_set_word(vvp_array_t arr,
assert(0); assert(0);
} }
tmp.set_vec(part_off, val); tmp.set_vec(part_off, val);
arr->vals->set_word(address, tmp); arr->vals4->set_word(address, tmp);
} else { } else {
arr->vals->set_word(address, val); arr->vals4->set_word(address, val);
} }
array_word_change(arr, address); array_word_change(arr, address);
return; return;
@ -734,15 +756,22 @@ void array_set_word(vvp_array_t arr,
array_word_change(arr, address); array_word_change(arr, address);
} }
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) void array_set_word(vvp_array_t arr, unsigned address, double val)
{ {
if (arr->vals) { assert(arr->valsr!= 0);
assert(arr->nets == 0); assert(arr->nets == 0);
return arr->vals->get_word(address); arr->valsr->set_word(address, val);
} }
assert(arr->vals == 0); vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
{
if (arr->vals4) {
assert(arr->nets == 0);
return arr->vals4->get_word(address);
}
assert(arr->vals4 == 0);
assert(arr->nets != 0); assert(arr->nets != 0);
if (address >= arr->array_count) { if (address >= arr->array_count) {
@ -767,6 +796,26 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
return val; 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, static vpiHandle vpip_make_array(char*label, const char*name,
int first_addr, int last_addr, int first_addr, int last_addr,
bool signed_flag) 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. // Start off now knowing if we are nets or variables.
obj->nets = 0; obj->nets = 0;
obj->vals = 0; obj->vals4 = 0;
obj->valsr = 0;
obj->vals_width = 0; obj->vals_width = 0;
vpip_make_dec_const(&obj->msb, 0); vpip_make_dec_const(&obj->msb, 0);
vpip_make_dec_const(&obj->lsb, 0); vpip_make_dec_const(&obj->lsb, 0);
@ -869,10 +919,10 @@ void compile_var_array(char*label, char*name, int last, int first,
/* Make the words. */ /* Make the words. */
arr->vals_width = labs(msb-lsb) + 1; arr->vals_width = labs(msb-lsb) + 1;
if (vpip_peek_current_scope()->is_automatic) { if (vpip_peek_current_scope()->is_automatic) {
arr->vals = new vvp_vector4array_aa(arr->vals_width, arr->vals4 = new vvp_vector4array_aa(arr->vals_width,
arr->array_count); arr->array_count);
} else { } else {
arr->vals = new vvp_vector4array_sa(arr->vals_width, arr->vals4 = new vvp_vector4array_sa(arr->vals_width,
arr->array_count); arr->array_count);
} }
vpip_make_dec_const(&arr->msb, msb); vpip_make_dec_const(&arr->msb, msb);
@ -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); vpiHandle obj = vpip_make_array(label, name, first, last, true);
struct __vpiArray*arr = ARRAY_HANDLE(obj); struct __vpiArray*arr = ARRAY_HANDLE(obj);
vvp_array_t array = array_find(label);
/* Make the words. */ /* Make the words. */
for (unsigned idx = 0 ; idx < arr->array_count ; idx += 1) { arr->valsr = new vvp_realarray_t(arr->array_count);
char buf[64]; arr->vals_width = 1;
snprintf(buf, sizeof buf, "%s_%u", label, idx);
compile_varw_real(strdup(buf), array, idx, msb, lsb); /* 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_arrays += 1;
count_real_array_words += arr->array_count; 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.cb_rtn != 0) {
if (cur->cb_data.value) 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->vals_width,
array->signed_flag, array->signed_flag,
cur->cb_data.value); 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. // Share the words with the source array.
obj->nets = mem->nets; obj->nets = mem->nets;
obj->vals = mem->vals; obj->vals4 = mem->vals4;
obj->ports_ = 0; obj->ports_ = 0;

View File

@ -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, extern void array_alias_word(vvp_array_t array, unsigned long addr,
vpiHandle word); vpiHandle word);
extern void array_set_word(vvp_array_t arr, extern void array_set_word(vvp_array_t arr, unsigned idx,
unsigned idx, unsigned off, vvp_vector4_t val);
unsigned off, extern void array_set_word(vvp_array_t arr, unsigned idx,
vvp_vector4_t val); double val);
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address); 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 */ /* VPI hooks */

View File

@ -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_JMP0XZ(vthread_t thr, vvp_code_t code);
extern bool of_JMP1(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_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_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(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVP0_S(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_NET(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_REG(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_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_AV(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(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); extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);

View File

@ -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/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%jmp/1", of_JMP1, 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} }, { "%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/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",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} }, { "%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/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/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} }, { "%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/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/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/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", 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} }, { "%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/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} }, { "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },

View File

@ -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/vp0/s) to the desired width.
* %load/wr <bit>, <vpi-label> * %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 The %load/wr instruction reads a real value from the vpi-like object
register. 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> * %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. register 3. This is the address of the word within the array.
* %set/wr <vpi-label>, <bit> * %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> * %set/x0 <var-label>, <bit>, <wid>

View File

@ -369,6 +369,7 @@ struct __vpiRealVar {
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig); extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net); 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 * When a loaded VPI module announces a system task/function, one

View File

@ -28,11 +28,20 @@
#endif #endif
# include <assert.h> # 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) static int real_var_get(int code, vpiHandle ref)
{ {
assert(ref->vpi_type->type_code == vpiRealVar); assert(ref->vpi_type->type_code == vpiRealVar);
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref; struct __vpiRealVar*rfp = vpip_realvar_from_handle(ref);
switch (code) { switch (code) {
case vpiArray: case vpiArray:

View File

@ -2752,6 +2752,20 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
return false; 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> ; * %load/av <bit>, <array-label>, <wid> ;
* *
@ -3936,6 +3950,24 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
return true; 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 implements the "%set/av <label>, <bit>, <wid>" instruction. In
* this case, the <label> is an array label, and the <bit> and <wid> * this case, the <label> is an array label, and the <bit> and <wid>

View File

@ -1299,6 +1299,32 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
return 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__) vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
: width_(width__), words_(words__) : width_(width__), words_(words__)
{ {

View File

@ -467,6 +467,26 @@ extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
#endif #endif
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed); 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 * vvp_vector4array_t
*/ */

View File

@ -270,6 +270,8 @@ void compile_netw_real(char*label, char*array_label, unsigned long array_addr,
int msb, int lsb, int msb, int lsb,
unsigned argc, struct symb_s*argv) 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, __compile_real(label, 0, array_label, array_addr,
msb, lsb, false, argc, argv); msb, lsb, false, argc, argv);
} }