diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index b99bd6797..1b504ae96 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2020 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -1050,22 +1050,68 @@ static int show_stmt_assign_sig_queue(ivl_statement_t net) int errors = 0; ivl_lval_t lval = ivl_stmt_lval(net, 0); ivl_expr_t rval = ivl_stmt_rval(net); + ivl_expr_t part = ivl_lval_part_off(lval); ivl_signal_t var= ivl_lval_sig(lval); ivl_type_t var_type= ivl_signal_net_type(var); + ivl_type_t element_type = ivl_type_element(var_type); + + ivl_expr_t mux = ivl_lval_idx(lval); + + assert(ivl_stmt_lvals(net) == 1); + assert(ivl_stmt_opcode(net) == 0); + assert(part == 0); + assert(ivl_type_base(var_type) == IVL_VT_QUEUE); - switch (ivl_expr_type(rval)) { - case IVL_EX_NULL: + if (ivl_expr_type(rval) == IVL_EX_NULL) { errors += draw_eval_object(rval); - break; - default: - fprintf(stderr, "XXXX: I don't know how to handle expr_type=%d here\n", ivl_expr_type(rval)); - fprintf(vvp_out, " ; XXXX expr_type=%d\n", ivl_expr_type(rval)); + fprintf(vvp_out, " %%store/obj v%p_0;\n", var); + } else if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) { + draw_eval_real(rval); + /* The %store/dar expects the array index to be in + index register 3. */ + draw_eval_expr_into_integer(mux, 3); + fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); + } else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) { + draw_eval_string(rval); + /* The %store/dar expects the array index to be in + index register 3. */ + draw_eval_expr_into_integer(mux, 3); + fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var); + } else if (mux) { // What is left must be some form of vector + draw_eval_vec4(rval); + resize_vec4_wid(rval, ivl_stmt_lwidth(net)); + /* The %store/dar expects the array index to be in + index register 3. */ + draw_eval_expr_into_integer(mux, 3); + fprintf(vvp_out, " %%store/dar/vec4 v%p_0;\n", var); + } else { + fprintf(stderr, "Sorry: I don't know how to handle expr_type=%d " + "being assigned to a queue.\n", ivl_expr_type(rval)); + fprintf(vvp_out, " ; Sorry: Queues do not currently handle " + "expr_type=%d.\n", ivl_expr_type(rval)); errors += 1; - break; } +// FIXME +#if 0 +static int show_stmt_assign_sig_darray(ivl_statement_t net) +{ - fprintf(vvp_out, " %%store/obj v%p_0;\n", var); + + } else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { + /* There is no l-value mux, but the r-value is an array + pattern. This is a special case of an assignment to + elements of the l-value. */ + errors += show_stmt_assign_darray_pattern(net); + + } else { + /* There is no l-value mux, so this must be an + assignment to the array as a whole. Evaluate the + "object", and store the evaluated result. */ + errors += draw_eval_object(rval); + fprintf(vvp_out, " %%store/obj v%p_0;\n", var); + } +#endif return errors; } diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 242682fe2..370a69348 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -5643,21 +5643,40 @@ bool of_SPLIT_VEC4(vthread_t thr, vvp_code_t cp) return true; } +/* + * %store/dar/real + * In this case, is the name of a dynamic array. Signed index + * register 3 contains the index into the dynamic array. + */ bool of_STORE_DAR_R(vthread_t thr, vvp_code_t cp) { - long adr = thr->words[3].w_int; - - // Pop the real value to be store... - double value = thr->pop_real(); - + int64_t adr = thr->words[3].w_int; + double value = thr->pop_real(); // Pop the real value to store... vvp_net_t*net = cp->net; + unsigned max_size = 0; // FIXME: Need to get this from the compile and how to pass to set_word() + + assert(net); vvp_fun_signal_object*obj = dynamic_cast (net->fun); assert(obj); vvp_darray*darray = obj->get_object().peek(); - assert(darray); - darray->set_word(adr, value); + if (adr < 0) + cerr << "Warning: cannot write to a negative array index (" + << adr << ")." << endl; + else if (thr->flags[4] != BIT4_0) + cerr << "Warning: cannot write to an undefined array index." + << endl; + else if (darray) + darray->set_word(adr, value); + else { + vvp_queue*queue = get_queue_object(thr, net); + if (queue) + queue->push_front(value, max_size); + else + cerr << "Warning: cannot write to an undefined array." + << endl; + } return true; } @@ -5668,38 +5687,71 @@ bool of_STORE_DAR_R(vthread_t thr, vvp_code_t cp) */ bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t cp) { - long adr = thr->words[3].w_int; - - // Pop the string to be stored... - string value = thr->pop_str(); - + int64_t adr = thr->words[3].w_int; + string value = thr->pop_str(); // Pop the string to be stored... vvp_net_t*net = cp->net; + unsigned max_size = 0; // FIXME: Need to get this from the compile and how to pass to set_word() + + assert(net); vvp_fun_signal_object*obj = dynamic_cast (net->fun); assert(obj); vvp_darray*darray = obj->get_object().peek(); - assert(darray); - darray->set_word(adr, value); + if (adr < 0) + cerr << "Warning: cannot write to a negative array index (" + << adr << ")." << endl; + else if (thr->flags[4] != BIT4_0) + cerr << "Warning: cannot write to an undefined array index." + << endl; + else if (darray) + darray->set_word(adr, value); + else { + vvp_queue*queue = get_queue_object(thr, net); + if (queue) + queue->push_front(value, max_size); + else + cerr << "Warning: cannot write to an undefined array." + << endl; + } return true; } +/* + * %store/dar/vec4 + * In this case, is the name of a dynamic array. Signed index + * register 3 contains the index into the dynamic array. + */ bool of_STORE_DAR_VEC4(vthread_t thr, vvp_code_t cp) { - long adr = thr->words[3].w_int; - - // Pop the real value to be store... - vvp_vector4_t value = thr->pop_vec4(); - + int64_t adr = thr->words[3].w_int; + vvp_vector4_t value = thr->pop_vec4(); // Pop the real value to be store... vvp_net_t*net = cp->net; + unsigned max_size = 0; // FIXME: Need to get this from the compile and how to pass to set_word() + + assert(net); vvp_fun_signal_object*obj = dynamic_cast (net->fun); assert(obj); vvp_darray*darray = obj->get_object().peek(); - assert(darray); - darray->set_word(adr, value); + if (adr < 0) + cerr << "Warning: cannot write to a negative array index (" << adr << ")." << endl; + else if (thr->flags[4] != BIT4_0) + cerr << "Warning: cannot write to an undefined array index." << endl; + else if (darray) + darray->set_word(adr, value); + else { + vvp_queue*queue = get_queue_object(thr, net); + if (queue) + queue->push_front(value, max_size); + else + cerr << "Warning: cannot write to an undefined array." << endl; + } return true; } diff --git a/vvp/vvp_darray.cc b/vvp/vvp_darray.cc index 8a68f1f6d..25fde59e4 100644 --- a/vvp/vvp_darray.cc +++ b/vvp/vvp_darray.cc @@ -446,8 +446,17 @@ vvp_queue_real::~vvp_queue_real() void vvp_queue_real::set_word(unsigned adr, double value) { + unsigned max_size = 0; // FIXME: need to get this from the compiler; bounded queues will fail if (adr < queue.size()) queue[adr] = value; + else if (adr == queue.size()) + if (!max_size || (queue.size() < max_size)) queue.push_back(value); + else cerr << "Warning: assigning to queue[" << adr << "] is" + " outside bound (" << max_size << "). " << value + << " was not added." << endl; + else cerr << "Warning: assigning to queue[" << adr << "] is outside " + "of size (" << queue.size() << "). " << value + << " was not added." << endl; } void vvp_queue_real::get_word(unsigned adr, double&value) @@ -498,8 +507,17 @@ vvp_queue_string::~vvp_queue_string() void vvp_queue_string::set_word(unsigned adr, const string&value) { + unsigned max_size = 0; // FIXME: need to get this from the compiler; bounded queues will fail if (adr < queue.size()) queue[adr] = value; + else if (adr == queue.size()) + if (!max_size || (queue.size() < max_size)) queue.push_back(value); + else cerr << "Warning: assigning to queue[" << adr << "] is" + " outside bound (" << max_size << "). " << value + << " was not added." << endl; + else cerr << "Warning: assigning to queue[" << adr << "] is outside " + "of size (" << queue.size() << "). " << value + << " was not added." << endl; } void vvp_queue_string::get_word(unsigned adr, string&value) @@ -550,8 +568,17 @@ vvp_queue_vec4::~vvp_queue_vec4() void vvp_queue_vec4::set_word(unsigned adr, const vvp_vector4_t&value) { + unsigned max_size = 0; // FIXME: need to get this from the compiler; bounded queues will fail if (adr < queue.size()) queue[adr] = value; + else if (adr == queue.size()) + if (!max_size || (queue.size() < max_size)) queue.push_back(value); + else cerr << "Warning: assigning to queue[" << adr << "] is" + " outside bound (" << max_size << "). " << value + << " was not added." << endl; + else cerr << "Warning: assigning to queue[" << adr << "] is outside " + "of size (" << queue.size() << "). " << value + << " was not added." << endl; } void vvp_queue_vec4::get_word(unsigned adr, vvp_vector4_t&value)