Handle arrays of class objects.

This goes all the way down to the vvp level, where we create support
for arrays of objects, generate the new code in the -tvvp code
generator, and elaborate the arrays in the first place.
This commit is contained in:
Stephen Williams 2014-08-29 20:31:51 -07:00
parent 0cd6fbaf41
commit dec4cd5071
17 changed files with 296 additions and 15 deletions

View File

@ -3113,8 +3113,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned) const
ivl_type_t ntype, unsigned flags) const
{
bool need_const = NEED_CONST & flags;
NetNet* net = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
@ -3185,7 +3187,69 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
ivl_assert(*this, ntype->type_compatible(net->net_type()));
NetESignal*tmp = new NetESignal(net);
const name_component_t&use_comp = path_.back();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Typed ident " << net->name()
<< " with " << use_comp.index.size() << " indices"
<< " and " << net->unpacked_dimensions() << " expected."
<< endl;
}
if (net->unpacked_dimensions() != use_comp.index.size()) {
cerr << get_fileline() << ": sorry: "
<< "Net " << net->name()
<< " expects " << net->unpacked_dimensions()
<< ", but got " << use_comp.index.size() << "."
<< endl;
des->errors += 1;
NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
if (net->unpacked_dimensions() == 0) {
NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
// Convert a set of index expressions to a single expression
// that addresses the canonical element.
list<NetExpr*>unpacked_indices;
list<long> unpacked_indices_const;
indices_flags idx_flags;
indices_to_expressions(des, scope, this,
use_comp.index, net->unpacked_dimensions(),
need_const,
idx_flags,
unpacked_indices,
unpacked_indices_const);
NetExpr*canon_index = 0;
if (idx_flags.invalid) {
// Nothing to do
} else if (idx_flags.undefined) {
cerr << get_fileline() << ": warning: "
<< "returning 'bx for undefined array access "
<< net->name() << as_indices(unpacked_indices)
<< "." << endl;
} else if (idx_flags.variable) {
ivl_assert(*this, unpacked_indices.size() == net->unpacked_dimensions());
canon_index = normalize_variable_unpacked(net, unpacked_indices);
} else {
ivl_assert(*this, unpacked_indices_const.size() == net->unpacked_dimensions());
canon_index = normalize_variable_unpacked(net, unpacked_indices_const);
}
ivl_assert(*this, canon_index);
NetESignal*tmp = new NetESignal(net, canon_index);
tmp->set_line(*this);
return tmp;

View File

@ -1222,13 +1222,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
ivl_assert(*this, use_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Create class instance signal " << wtype
<< " " << name_ << endl;
<< " " << packed_dimensions << name_ << unpacked_dimensions << endl;
}
// (No arrays of classes)
list<netrange_t> use_unpacked;
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
// If this is a struct type, then build the net with the

View File

@ -4600,15 +4600,19 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": PForeach::elaborate: "
<< "Scan array " << array_sig->name()
<< " with " << array_sig->unpacked_dims().size() << " unpacked"
<< " and " << array_sig->packed_dims().size()
<< " of " << array_sig->data_type()
<< " with " << array_sig->unpacked_dimensions() << " unpacked"
<< " and " << array_sig->packed_dimensions()
<< " packed dimensions." << endl;
}
// Classic arrays are processed this way.
if (array_sig->data_type()==IVL_VT_BOOL)
return elaborate_static_array_(des, scope, array_sig);
if (array_sig->data_type()==IVL_VT_LOGIC)
return elaborate_static_array_(des, scope, array_sig);
if (array_sig->unpacked_dimensions() >= index_vars_.size())
return elaborate_static_array_(des, scope, array_sig);
if (index_vars_.size() != 1) {
cerr << get_fileline() << ": sorry: "

View File

@ -519,7 +519,17 @@ static struct vector_info draw_binary_expr_eq_class(ivl_expr_t expr)
}
if (ivl_expr_type(re) == IVL_EX_NULL && ivl_expr_type(le)==IVL_EX_SIGNAL) {
fprintf(vvp_out, " %%test_nul v%p_0;\n", ivl_expr_signal(le));
ivl_signal_t sig = ivl_expr_signal(le);
if (ivl_signal_dimensions(sig) == 0) {
fprintf(vvp_out, " %%test_nul v%p_0;\n", sig);
} else {
ivl_expr_t word_ex = ivl_expr_oper1(le);
int word_ix = allocate_word();
draw_eval_expr_into_integer(word_ex, word_ix);
fprintf(vvp_out, " %%test_nula v%p, %d;\n", sig, word_ix);
clr_word(word_ix);
}
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
if (ivl_expr_opcode(expr) == 'n')
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);

View File

@ -195,10 +195,25 @@ static int eval_object_shallowcopy(ivl_expr_t ex)
return 0;
}
static int eval_object_signal(ivl_expr_t ex)
static int eval_object_signal(ivl_expr_t expr)
{
ivl_signal_t sig = ivl_expr_signal(ex);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
ivl_signal_t sig = ivl_expr_signal(expr);
/* Simple case: This is a simple variable. Generate a load
statement to load the string into the stack. */
if (ivl_signal_dimensions(sig) == 0) {
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
return 0;
}
/* There is a word select expression, so load the index into a
register and load from the array. */
ivl_expr_t word_ex = ivl_expr_oper1(expr);
int word_ix = allocate_word();
draw_eval_expr_into_integer(word_ex, word_ix);
fprintf(vvp_out, " %%load/obja v%p, %d;\n", sig, word_ix);
clr_word(word_ix);
return 0;
}

View File

@ -1066,7 +1066,19 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
as an object and assign the entire object to the
variable. */
errors += draw_eval_object(rval);
fprintf(vvp_out, " %%store/obj v%p_0;\n", sig);
if (ivl_signal_array_count(sig) > 1) {
unsigned ix;
ivl_expr_t aidx = ivl_lval_idx(lval);
draw_eval_expr_into_integer(aidx, (ix = allocate_word()));
fprintf(vvp_out, " %%store/obja v%p, %u;\n", sig, ix);
clr_word(ix);
} else {
/* Not an array, so no index expression */
fprintf(vvp_out, " %%store/obj v%p_0;\n", sig);
}
}
return errors;

View File

@ -469,6 +469,10 @@ static void draw_reg_in_scope(ivl_signal_t sig)
datatype_flag = "/str";
vector_dims = 0;
break;
case IVL_VT_CLASS:
datatype_flag = "/obj";
vector_dims = 0;
break;
default:
break;
}

View File

@ -1055,6 +1055,18 @@ void array_set_word(vvp_array_t arr, unsigned address, const string&val)
array_word_change(arr, address);
}
void array_set_word(vvp_array_t arr, unsigned address, const vvp_object_t&val)
{
assert(arr->vals != 0);
assert(arr->nets == 0);
if (address >= arr->vals->get_size())
return;
arr->vals->set_word(address, val);
array_word_change(arr, address);
}
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
{
if (arr->vals4) {
@ -1129,6 +1141,28 @@ double array_get_word_r(vvp_array_t arr, unsigned address)
}
void array_get_word_obj(vvp_array_t arr, unsigned address, vvp_object_t&val)
{
if (arr->vals) {
assert(arr->vals4 == 0);
assert(arr->nets == 0);
// In this context, address out of bounds returns 0.0
// instead of an error.
if (address >= arr->vals->get_size()) {
val = vvp_object_t();
return;
}
arr->vals->get_word(address, val);
return;
}
assert(arr->nets);
// Arrays of string nets not implemented!
assert(0);
return;
}
string array_get_word_str(vvp_array_t arr, unsigned address)
{
if (arr->vals) {
@ -1354,6 +1388,23 @@ void compile_string_array(char*label, char*name, int last, int first)
delete[] name;
}
void compile_object_array(char*label, char*name, int last, int first)
{
vpiHandle obj = vpip_make_array(label, name, first, last, true);
struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
/* Make the words. */
arr->vals = new vvp_darray_object(arr->array_count);
arr->vals_width = 1;
count_real_arrays += 1;
count_real_array_words += arr->array_count;
free(label);
delete[] name;
}
void compile_net_array(char*label, char*name, int last, int first)
{
// At this point we don't know the array data type, so we

View File

@ -45,9 +45,12 @@ extern void array_set_word(vvp_array_t arr, unsigned idx,
double val);
extern void array_set_word(vvp_array_t arr, unsigned idx,
const std::string&val);
extern void array_set_word(vvp_array_t arr, unsigned idx,
const vvp_object_t&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);
extern void array_get_word_obj(vvp_array_t array, unsigned address, vvp_object_t&val);
extern std::string array_get_word_str(vvp_array_t array, unsigned address);
/* VPI hooks */

View File

@ -133,6 +133,7 @@ extern bool of_LOAD_REAL(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_OBJA(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STRA(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
@ -203,6 +204,7 @@ extern bool of_STORE_QB_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_QF_R(vthread_t thr, vvp_code_t code);
extern bool of_STORE_QF_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_STORE_OBJA(vthread_t thr, vvp_code_t code);
extern bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_STORE_PROP_R(vthread_t thr, vvp_code_t code);
extern bool of_STORE_PROP_STR(vthread_t thr, vvp_code_t code);
@ -217,6 +219,7 @@ extern bool of_SUBI(vthread_t thr, vvp_code_t code);
extern bool of_SUBSTR(vthread_t thr, vvp_code_t code);
extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code);
extern bool of_TEST_NUL(vthread_t thr, vvp_code_t code);
extern bool of_TEST_NULA(vthread_t thr, vvp_code_t code);
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);
extern bool of_WAIT(vthread_t thr, vvp_code_t code);
extern bool of_WAIT_FORK(vthread_t thr, vvp_code_t code);

View File

@ -180,6 +180,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%load/dar/r", of_LOAD_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE}},
{ "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/obja", of_LOAD_OBJA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/stra", of_LOAD_STRA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
@ -246,6 +247,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%store/dar/r", of_STORE_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/dar/str",of_STORE_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/obja", of_STORE_OBJA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/prop/obj",of_STORE_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
@ -264,6 +266,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%substr", of_SUBSTR, 2,{OA_BIT1, OA_BIT2, OA_NONE} },
{ "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%test_nula", of_TEST_NULA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%wait/fork",of_WAIT_FORK,0,{OA_NONE, OA_NONE, OA_NONE} },
{ "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -373,6 +373,8 @@ extern void compile_real_array(char*label, char*name,
int last, int first);
extern void compile_string_array(char*label, char*name,
int last, int first);
extern void compile_object_array(char*label, char*name,
int last, int first);
extern void compile_net_array(char*label, char*name,
int last, int first);
extern void compile_array_alias(char*label, char*name, char*src);

View File

@ -124,6 +124,7 @@ static char* strdupnew(char const *str)
".array/2s" { return K_ARRAY_2S; }
".array/2u" { return K_ARRAY_2U; }
".array/i" { return K_ARRAY_I; }
".array/obj" { return K_ARRAY_OBJ; }
".array/real" { return K_ARRAY_R; }
".array/s" { return K_ARRAY_S; }
".array/str" { return K_ARRAY_STR; }

View File

@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0;
%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_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT
%token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_OBJ K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CLASS
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ
@ -234,6 +234,9 @@ statement
| T_LABEL K_ARRAY_STR T_STRING ',' signed_t_number signed_t_number ';'
{ compile_string_array($1, $3, $5, $6); }
| T_LABEL K_ARRAY_OBJ T_STRING ',' signed_t_number signed_t_number ';'
{ compile_object_array($1, $3, $5, $6); }
| T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ';'
{ compile_net_array($1, $3, $5, $6); }

View File

@ -3531,6 +3531,23 @@ bool of_LOAD_OBJ(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_LOAD_OBJA(vthread_t thr, vvp_code_t cp)
{
unsigned idx = cp->bit_idx[0];
unsigned adr = thr->words[idx].w_int;
vvp_object_t word;
/* The result is 0.0 if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
; // Return nil
} else {
array_get_word_obj(cp->array, adr, word);
}
thr->push_object(word);
return true;
}
/*
* %load/real <var-label>
*/
@ -5444,6 +5461,23 @@ bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %store/obja <array-label> <index>
*/
bool of_STORE_OBJA(vthread_t thr, vvp_code_t cp)
{
unsigned idx = cp->bit_idx[0];
unsigned adr = thr->words[idx].w_int;
vvp_object_t val;
thr->pop_object(val);
array_set_word(cp->array, adr, val);
return true;
}
/*
* %store/prop/obj <id>
*
@ -5798,6 +5832,27 @@ bool of_TEST_NUL(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_TEST_NULA(vthread_t thr, vvp_code_t cp)
{
unsigned idx = cp->bit_idx[0];
unsigned adr = thr->words[idx].w_int;
vvp_object_t word;
/* If the address is undefined, return true. */
if (thr_get_bit(thr, 4) == BIT4_1) {
thr_put_bit(thr, 4, BIT4_1);
return true;
}
array_get_word_obj(cp->array, adr, word);
if (word.test_nil())
thr_put_bit(thr, 4, BIT4_1);
else
thr_put_bit(thr, 4, BIT4_0);
return true;
}
bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
{
vpip_execute_vpi_call(thr, cp->handle);

View File

@ -43,6 +43,11 @@ void vvp_darray::set_word(unsigned, const string&)
cerr << "XXXX set_word(string) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::set_word(unsigned, const vvp_object_t&)
{
cerr << "XXXX set_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, vvp_vector4_t&)
{
cerr << "XXXX get_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
@ -58,6 +63,11 @@ void vvp_darray::get_word(unsigned, string&)
cerr << "XXXX get_word(string) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, vvp_object_t&)
{
cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
}
template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom()
{
}
@ -101,6 +111,32 @@ template class vvp_darray_atom<int16_t>;
template class vvp_darray_atom<int32_t>;
template class vvp_darray_atom<int64_t>;
vvp_darray_object::~vvp_darray_object()
{
}
size_t vvp_darray_object::get_size() const
{
return array_.size();
}
void vvp_darray_object::set_word(unsigned adr, const vvp_object_t&value)
{
if (adr >= array_.size())
return;
array_[adr] = value;
}
void vvp_darray_object::get_word(unsigned adr, vvp_object_t&value)
{
if (adr >= array_.size()) {
value = vvp_object_t();
return;
}
value = array_[adr];
}
vvp_darray_real::~vvp_darray_real()
{
}

View File

@ -42,6 +42,9 @@ class vvp_darray : public vvp_object {
virtual void set_word(unsigned adr, const std::string&value);
virtual void get_word(unsigned adr, std::string&value);
virtual void set_word(unsigned adr, const vvp_object_t&value);
virtual void get_word(unsigned adr, vvp_object_t&value);
};
template <class TYPE> class vvp_darray_atom : public vvp_darray {
@ -86,6 +89,19 @@ class vvp_darray_string : public vvp_darray {
std::vector<std::string> array_;
};
class vvp_darray_object : public vvp_darray {
public:
inline vvp_darray_object(size_t siz) : array_(siz) { }
~vvp_darray_object();
size_t get_size(void) const;
void set_word(unsigned adr, const vvp_object_t&value);
void get_word(unsigned adr, vvp_object_t&value);
private:
std::vector<vvp_object_t> array_;
};
class vvp_queue : public vvp_darray {