diff --git a/elab_expr.cc b/elab_expr.cc index 2535ccb17..824ec71f4 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4023,6 +4023,8 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, NetEProperty*prop = new NetEProperty(search_results.net, pidx, nullptr); prop->set_line(*this); perm_string method_name = search_results.path_tail.back().name; + ivl_type_t element_type = ivl_type_element(ptype); + ivl_type_t darray_rtype = ptype; if (method_name == "size") { if (parms_.size() != 0) { cerr << get_fileline() << ": error: size() method " @@ -4034,6 +4036,276 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, sys_expr->parm(0, prop); return sys_expr; } + if (method_name == "unique") { + if (parms_.size() != 0) { + cerr << get_fileline() << ": error: unique() method " + << "takes no arguments" << endl; + des->errors += 1; + } + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array unique() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + cerr << get_fileline() << ": sorry: dynamic array unique() with a " + << "`with` clause is not yet supported." << endl; + des->errors += 1; + return 0; + } + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$unique", darray_rtype, 1); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + return sys_expr; + } + if (method_name == "unique_index") { + if (parms_.size() != 0) { + cerr << get_fileline() << ": error: unique_index() method " + << "takes no arguments" << endl; + des->errors += 1; + } + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array unique_index() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + cerr << get_fileline() << ": sorry: dynamic array unique_index() with a " + << "`with` clause is not yet supported." << endl; + des->errors += 1; + return 0; + } + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$unique_index", + static_cast(&ivl_queue_unique_index_ret), 1); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + return sys_expr; + } + if (method_name == "find") { + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array find() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, darray_rtype, method_name); + } + NetExpr* cmp = elab_queue_locator_cmp_arg( + des, scope, *this, parms_, element_type); + if (!cmp) + return 0; + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$find", darray_rtype, 2); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + sys_expr->parm(1, cmp); + return sys_expr; + } + if (method_name == "find_index") { + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array find_index() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, + static_cast(&ivl_queue_unique_index_ret), + method_name); + } + NetExpr* cmp = elab_queue_locator_cmp_arg( + des, scope, *this, parms_, element_type); + if (!cmp) + return 0; + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$find_index", + static_cast(&ivl_queue_unique_index_ret), 2); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + sys_expr->parm(1, cmp); + return sys_expr; + } + if (method_name == "find_first") { + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array find_first() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, darray_rtype, method_name); + } + NetExpr* cmp = elab_queue_locator_cmp_arg( + des, scope, *this, parms_, element_type); + if (!cmp) + return 0; + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$find_first", darray_rtype, 2); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + sys_expr->parm(1, cmp); + return sys_expr; + } + if (method_name == "find_first_index") { + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array find_first_index() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, + static_cast(&ivl_queue_unique_index_ret), + method_name); + } + NetExpr* cmp = elab_queue_locator_cmp_arg( + des, scope, *this, parms_, element_type); + if (!cmp) + return 0; + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$find_first_index", + static_cast(&ivl_queue_unique_index_ret), 2); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + sys_expr->parm(1, cmp); + return sys_expr; + } + if (method_name == "find_last") { + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array find_last() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, darray_rtype, method_name); + } + NetExpr* cmp = elab_queue_locator_cmp_arg( + des, scope, *this, parms_, element_type); + if (!cmp) + return 0; + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$find_last", darray_rtype, 2); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + sys_expr->parm(1, cmp); + return sys_expr; + } + if (method_name == "find_last_index") { + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array find_last_index() for this " + << "element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, + static_cast(&ivl_queue_unique_index_ret), + method_name); + } + NetExpr* cmp = elab_queue_locator_cmp_arg( + des, scope, *this, parms_, element_type); + if (!cmp) + return 0; + NetESFunc*sys_expr = new NetESFunc( + "$ivl_queue_method$find_last_index", + static_cast(&ivl_queue_unique_index_ret), 2); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + sys_expr->parm(1, cmp); + return sys_expr; + } + if (method_name == "min" || method_name == "max") { + if (parms_.size() != 0) { + cerr << get_fileline() << ": error: " << method_name + << "() method takes no arguments" << endl; + des->errors += 1; + } + if (!queue_method_element_is_integral_vec4(element_type)) { + cerr << get_fileline() << ": sorry: dynamic array " << method_name + << "() for this element type is not yet supported." << endl; + des->errors += 1; + return 0; + } + if (with_expr_) { + if (!parms_.empty()) { + cerr << get_fileline() << ": error: array locator " + << "`with` clause cannot be combined with a " + << "method argument." << endl; + des->errors += 1; + return 0; + } + return elab_queue_locator_with_predicate( + des, scope, *this, with_expr_, prop, + element_type, darray_rtype, method_name); + } + NetESFunc*sys_expr = new NetESFunc( + method_name == "min" ? "$ivl_queue_method$min" + : "$ivl_queue_method$max", + darray_rtype, 1); + sys_expr->set_line(*this); + sys_expr->parm(0, prop); + return sys_expr; + } } } } diff --git a/ivtest/ivltests/README_sv_queue_locators.txt b/ivtest/ivltests/README_sv_queue_locators.txt index a6233e8b5..71b2600a4 100644 --- a/ivtest/ivltests/README_sv_queue_locators.txt +++ b/ivtest/ivltests/README_sv_queue_locators.txt @@ -45,3 +45,4 @@ Regression tests (see ivtest/vvp_tests/*.json and regress-vvp.list): sv_darray_min_max.v min() and max() on dynamic array values. sv_queue_min_max_with.v min()/max() with predicate on queue values. sv_darray_min_max_with.v min()/max() with predicate on dynamic arrays. + sv_class_darray_prop_locators.v locator methods on class dynamic-array properties. diff --git a/ivtest/ivltests/sv_class_darray_prop_locators.v b/ivtest/ivltests/sv_class_darray_prop_locators.v new file mode 100644 index 000000000..d0a2ec3ac --- /dev/null +++ b/ivtest/ivltests/sv_class_darray_prop_locators.v @@ -0,0 +1,56 @@ +// Regression: class dynamic-array property locator methods. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do if ((val) !== (exp)) begin $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); failed = 1'b1; end while(0) + + class C; + int d[]; + endclass + + C c; + int tmp[]; + int r[$]; + + initial begin + c = new; + tmp = new[9]; + tmp = '{4, 7, 2, 5, 7, 1, 6, 3, 1}; + c.d = tmp; + + r = c.d.find() with (item > 3); + `check(r.size, 5); + `check(r[0], 4); + `check(r[4], 6); + + r = c.d.find_first() with (item > 6); + `check(r.size, 1); + `check(r[0], 7); + + r = c.d.find_last_index() with (item < 3); + `check(r.size, 1); + `check(r[0], 8); + + r = c.d.unique(); + `check(r.size, 7); + `check(r[0], 4); + + r = c.d.unique_index(); + `check(r.size, 7); + `check(r[0], 0); + + r = c.d.min(); + `check(r.size, 2); + `check(r[0], 1); + `check(r[1], 1); + + r = c.d.max() with (item < 7); + `check(r.size, 1); + `check(r[0], 6); + + if (!failed) + $display("PASSED"); + end +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index ab43a5dd7..59973b30a 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -231,6 +231,7 @@ sv_chained_constructor5 vvp_tests/sv_chained_constructor5.json sv_class_prop_assign_op1 vvp_tests/sv_class_prop_assign_op1.json sv_class_prop_assign_op2 vvp_tests/sv_class_prop_assign_op2.json sv_class_prop_logic vvp_tests/sv_class_prop_logic.json +sv_class_darray_prop_locators vvp_tests/sv_class_darray_prop_locators.json sv_class_prop_nest_darray1 vvp_tests/sv_class_prop_nest_darray1.json sv_class_prop_nest_obj1 vvp_tests/sv_class_prop_nest_obj1.json sv_class_prop_nest_real1 vvp_tests/sv_class_prop_nest_str1.json diff --git a/ivtest/vvp_tests/sv_class_darray_prop_locators.json b/ivtest/vvp_tests/sv_class_darray_prop_locators.json new file mode 100644 index 000000000..2cd98f13c --- /dev/null +++ b/ivtest/vvp_tests/sv_class_darray_prop_locators.json @@ -0,0 +1,10 @@ +{ + "type" : "normal", + "source" : "sv_class_darray_prop_locators.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Classes/dynamic arrays are not supported", + "type" : "CE", + "iverilog-args" : [ "-pallowsigned=1" ] + } +} diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index dd83b02c8..602445adb 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -290,7 +290,7 @@ static int eval_queue_method_unique(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/unique/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(arg); fprintf(vvp_out, " %%queue/unique/v v%p_0, %u;\n", sig, @@ -306,7 +306,7 @@ static int eval_queue_method_unique(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/unique/index/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(arg); fprintf(vvp_out, " %%queue/unique/index/v v%p_0, %u;\n", @@ -326,7 +326,7 @@ static int eval_queue_method_unique(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/%s/prop/v %u, %u;\n", opname, pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(arg); fprintf(vvp_out, " %%queue/%s/v v%p_0, %u;\n", opname, sig, @@ -483,7 +483,8 @@ static int eval_queue_method_find_with(ivl_expr_t expr) fprintf(vvp_out, "T_%u.%u ; loop end (prop)\n", thread_count, lab_loop_end); if (mode == 0 || mode == 1) { - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + /* Keep result queue object, drop class object beneath it. */ + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else if (mode == 6 || mode == 7) { fprintf(vvp_out, " %%queue/%s/obj/v %u;\n", mode == 6 ? "min" : "max", elem_wid); @@ -614,7 +615,7 @@ static int eval_queue_method_find(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/find/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(qarg); fprintf(vvp_out, " %%queue/find/v v%p_0, %u;\n", sig, @@ -630,7 +631,7 @@ static int eval_queue_method_find(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/find/index/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(qarg); fprintf(vvp_out, " %%queue/find/index/v v%p_0, %u;\n", @@ -646,7 +647,7 @@ static int eval_queue_method_find(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/find_first/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(qarg); fprintf(vvp_out, " %%queue/find_first/v v%p_0, %u;\n", sig, @@ -661,7 +662,7 @@ static int eval_queue_method_find(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/find_first/index/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(qarg); fprintf(vvp_out, " %%queue/find_first/index/v v%p_0, %u;\n", @@ -676,7 +677,7 @@ static int eval_queue_method_find(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/find_last/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(qarg); fprintf(vvp_out, " %%queue/find_last/v v%p_0, %u;\n", sig, @@ -691,7 +692,7 @@ static int eval_queue_method_find(ivl_expr_t expr) fprintf(vvp_out, " %%load/obj v%p_0;\n", cl); fprintf(vvp_out, " %%queue/find_last/index/prop/v %u, %u;\n", pidx, elem_wid); - fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%pop/obj 1, 1;\n"); } else { ivl_signal_t sig = ivl_expr_signal(qarg); fprintf(vvp_out, " %%queue/find_last/index/v v%p_0, %u;\n", diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 1e46f8642..38dd3ace9 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -540,6 +540,24 @@ static void get_queue_or_darray_vec4_from_net(vthread_t thr, vvp_net_t* net, dsrc = 0; } +static void get_queue_or_darray_vec4_from_object(vvp_object_t src_obj, + vvp_queue_vec4*& qsrc, + vvp_darray*& dsrc) +{ + qsrc = src_obj.peek(); + if (qsrc) { + dsrc = 0; + return; + } + vvp_darray* dany = src_obj.peek(); + if (dany && dynamic_cast(dany) == 0) { + dsrc = dany; + return; + } + qsrc = 0; + dsrc = 0; +} + /* * The following are used to allow a common template to be written for * queue real/string/vec4 operations @@ -6428,12 +6446,11 @@ bool of_QUEUE_FIND_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); - if (src == 0) { - thr->push_object(vvp_object_t(new vvp_queue_vec4())); - return true; - } - vvp_queue_vec4* dst = queue_run_find_matches_src(src, wid, cmp, false); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); + vvp_queue_vec4* dst = qsrc ? queue_run_find_matches_src(qsrc, wid, cmp, false) + : queue_run_find_matches_src(dsrc, wid, cmp, false); thr->push_object(vvp_object_t(dst)); return true; } @@ -6474,12 +6491,11 @@ bool of_QUEUE_FIND_INDEX_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); - if (src == 0) { - thr->push_object(vvp_object_t(new vvp_queue_vec4())); - return true; - } - vvp_queue_vec4* dst = queue_run_find_matches_src(src, wid, cmp, true); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); + vvp_queue_vec4* dst = qsrc ? queue_run_find_matches_src(qsrc, wid, cmp, true) + : queue_run_find_matches_src(dsrc, wid, cmp, true); thr->push_object(vvp_object_t(dst)); return true; } @@ -6520,9 +6536,12 @@ bool of_QUEUE_FIND_FIRST_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_queue_vec4* dst = - queue_find_first_last_to_queue_src(src, wid, cmp, true, false); + qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, true, false) + : queue_find_first_last_to_queue_src(dsrc, wid, cmp, true, false); thr->push_object(vvp_object_t(dst)); return true; } @@ -6563,9 +6582,12 @@ bool of_QUEUE_FIND_FIRST_INDEX_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_queue_vec4* dst = - queue_find_first_last_to_queue_src(src, wid, cmp, true, true); + qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, true, true) + : queue_find_first_last_to_queue_src(dsrc, wid, cmp, true, true); thr->push_object(vvp_object_t(dst)); return true; } @@ -6606,9 +6628,12 @@ bool of_QUEUE_FIND_LAST_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_queue_vec4* dst = - queue_find_first_last_to_queue_src(src, wid, cmp, false, false); + qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, false, false) + : queue_find_first_last_to_queue_src(dsrc, wid, cmp, false, false); thr->push_object(vvp_object_t(dst)); return true; } @@ -6649,9 +6674,12 @@ bool of_QUEUE_FIND_LAST_INDEX_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_queue_vec4* dst = - queue_find_first_last_to_queue_src(src, wid, cmp, false, true); + qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, false, true) + : queue_find_first_last_to_queue_src(dsrc, wid, cmp, false, true); thr->push_object(vvp_object_t(dst)); return true; } @@ -6683,13 +6711,9 @@ bool of_QUEUE_MIN_OBJ_V(vthread_t thr, vvp_code_t cp) vvp_object_t src_obj; thr->pop_object(src_obj); - vvp_queue_vec4* qsrc = src_obj.peek(); + vvp_queue_vec4* qsrc = 0; vvp_darray* dsrc = 0; - if (!qsrc) { - vvp_darray* dany = src_obj.peek(); - if (dany && dynamic_cast(dany) == 0) - dsrc = dany; - } + get_queue_or_darray_vec4_from_object(src_obj, qsrc, dsrc); vvp_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, false) : queue_run_min_max_src(dsrc, wid, false); thr->push_object(vvp_object_t(dst)); @@ -6707,13 +6731,9 @@ bool of_QUEUE_MIN_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* qsrc = qobj.peek(); + vvp_queue_vec4* qsrc = 0; vvp_darray* dsrc = 0; - if (!qsrc) { - vvp_darray* dany = qobj.peek(); - if (dany && dynamic_cast(dany) == 0) - dsrc = dany; - } + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, false) : queue_run_min_max_src(dsrc, wid, false); thr->push_object(vvp_object_t(dst)); @@ -6747,13 +6767,9 @@ bool of_QUEUE_MAX_OBJ_V(vthread_t thr, vvp_code_t cp) vvp_object_t src_obj; thr->pop_object(src_obj); - vvp_queue_vec4* qsrc = src_obj.peek(); + vvp_queue_vec4* qsrc = 0; vvp_darray* dsrc = 0; - if (!qsrc) { - vvp_darray* dany = src_obj.peek(); - if (dany && dynamic_cast(dany) == 0) - dsrc = dany; - } + get_queue_or_darray_vec4_from_object(src_obj, qsrc, dsrc); vvp_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, true) : queue_run_min_max_src(dsrc, wid, true); thr->push_object(vvp_object_t(dst)); @@ -6771,13 +6787,9 @@ bool of_QUEUE_MAX_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* qsrc = qobj.peek(); + vvp_queue_vec4* qsrc = 0; vvp_darray* dsrc = 0; - if (!qsrc) { - vvp_darray* dany = qobj.peek(); - if (dany && dynamic_cast(dany) == 0) - dsrc = dany; - } + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, true) : queue_run_min_max_src(dsrc, wid, true); thr->push_object(vvp_object_t(dst)); @@ -6816,12 +6828,11 @@ bool of_QUEUE_UNIQUE_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); - if (src == 0) { - thr->push_object(vvp_object_t(new vvp_queue_vec4())); - return true; - } - vvp_queue_vec4* dst = queue_run_unique_src(src, wid, false); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); + vvp_queue_vec4* dst = qsrc ? queue_run_unique_src(qsrc, wid, false) + : queue_run_unique_src(dsrc, wid, false); thr->push_object(vvp_object_t(dst)); return true; } @@ -6858,12 +6869,11 @@ bool of_QUEUE_UNIQUE_INDEX_PROP_V(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); - if (src == 0) { - thr->push_object(vvp_object_t(new vvp_queue_vec4())); - return true; - } - vvp_queue_vec4* dst = queue_run_unique_src(src, wid, true); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); + vvp_queue_vec4* dst = qsrc ? queue_run_unique_src(qsrc, wid, true) + : queue_run_unique_src(dsrc, wid, true); thr->push_object(vvp_object_t(dst)); return true; } @@ -6878,9 +6888,11 @@ bool of_PROP_QUEUE_SIZE(vthread_t thr, vvp_code_t cp) vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue* queue = qobj.peek(); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); - size_t sz = queue ? queue->get_size() : 0; + size_t sz = qsrc ? qsrc->get_size() : (dsrc ? dsrc->get_size() : 0); vvp_vector4_t val(32, BIT4_0); unsigned long ul = sz; @@ -6975,19 +6987,51 @@ bool of_QUEUE_WORD_PROP_V(vthread_t thr, vvp_code_t cp) return true; } + vvp_object_t saved_top; + bool popped_top = false; vvp_object_t& top = thr->peek_object(); vvp_cobject*cobj = top.peek(); - assert(cobj); + if (cobj == 0) { + // Array-locator with(property) keeps an accumulator queue on top. + // Temporarily pop it to access the class object beneath. + thr->pop_object(saved_top); + popped_top = true; + vvp_object_t& below = thr->peek_object(); + cobj = below.peek(); + } + if (cobj == 0) { + if (popped_top) + thr->push_object(saved_top); + thr->push_vec4(vvp_vector4_t(wid)); + return true; + } vvp_object_t qobj; cobj->get_object(pid, qobj, 0); - vvp_queue_vec4* src = qobj.peek(); + vvp_queue_vec4* qsrc = 0; + vvp_darray* dsrc = 0; + get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc); vvp_vector4_t out(wid); - if (src == 0 || (size_t)adr >= src->get_size()) { + if (qsrc) { + if ((size_t)adr >= qsrc->get_size()) { + thr->push_vec4(out); + return true; + } + qsrc->get_word((unsigned)adr, out); + } else if (dsrc) { + if ((size_t)adr >= dsrc->get_size()) { + thr->push_vec4(out); + return true; + } + dsrc->get_word((unsigned)adr, out); + } else { thr->push_vec4(out); + if (popped_top) + thr->push_object(saved_top); return true; } - src->get_word((unsigned)adr, out); + if (popped_top) + thr->push_object(saved_top); thr->push_vec4(out); return true; }