SV: implement reverse() for queues and dynamic arrays
Lower a.reverse() and q.reverse() to $ivl_darray_method$reverse with new VVP opcodes %reverse/obj and %reverse/prop/obj. Implement reverse_elems() on vvp_darray and queue storage types; dispatch queues via peek<vvp_queue> before vvp_darray so virtual overrides apply. Includes regressions for standalone arrays/queues and class properties. README_sv_queue_locators.txt documents behavior and tests. Made-with: Cursor
This commit is contained in:
parent
084db5ef73
commit
e597156d4d
23
elaborate.cc
23
elaborate.cc
|
|
@ -3965,6 +3965,12 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
&netvector_t::atom2s32,
|
&netvector_t::atom2s32,
|
||||||
method_name, "$size");
|
method_name, "$size");
|
||||||
}
|
}
|
||||||
|
if (method_name == "reverse") {
|
||||||
|
static const std::vector<perm_string> parm_names;
|
||||||
|
return elaborate_sys_task_method_(des, scope, prop, method_name,
|
||||||
|
"$ivl_darray_method$reverse",
|
||||||
|
parm_names);
|
||||||
|
}
|
||||||
} else if (ptype && ptype->base_type() == IVL_VT_DARRAY) {
|
} else if (ptype && ptype->base_type() == IVL_VT_DARRAY) {
|
||||||
NetEProperty*prop = new NetEProperty(net, pidx, 0);
|
NetEProperty*prop = new NetEProperty(net, pidx, 0);
|
||||||
prop->set_line(*this);
|
prop->set_line(*this);
|
||||||
|
|
@ -3981,6 +3987,12 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
&netvector_t::atom2s32,
|
&netvector_t::atom2s32,
|
||||||
method_name, "$size");
|
method_name, "$size");
|
||||||
}
|
}
|
||||||
|
if (method_name == "reverse") {
|
||||||
|
static const std::vector<perm_string> parm_names;
|
||||||
|
return elaborate_sys_task_method_(des, scope, prop, method_name,
|
||||||
|
"$ivl_darray_method$reverse",
|
||||||
|
parm_names);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4055,11 +4067,12 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
&netvector_t::atom2s32,
|
&netvector_t::atom2s32,
|
||||||
method_name, "$size");
|
method_name, "$size");
|
||||||
} else if (method_name == "reverse") {
|
} else if (method_name == "reverse") {
|
||||||
cerr << get_fileline() << ": sorry: 'reverse()' "
|
static const std::vector<perm_string> parm_names;
|
||||||
"array sorting method is not currently supported."
|
NetESignal*sig = new NetESignal(net);
|
||||||
<< endl;
|
sig->set_line(*this);
|
||||||
des->errors += 1;
|
return elaborate_sys_task_method_(des, scope, sig, method_name,
|
||||||
return 0;
|
"$ivl_darray_method$reverse",
|
||||||
|
parm_names);
|
||||||
} else if (method_name=="sort") {
|
} else if (method_name=="sort") {
|
||||||
cerr << get_fileline() << ": sorry: 'sort()' "
|
cerr << get_fileline() << ": sorry: 'sort()' "
|
||||||
"array sorting method is not currently supported."
|
"array sorting method is not currently supported."
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ on unpacked queues (int q[$]) and dynamic arrays (int da[]):
|
||||||
|
|
||||||
find, find_index, find_first, find_first_index, find_last,
|
find, find_index, find_first, find_first_index, find_last,
|
||||||
find_last_index, min, max, unique, unique_index,
|
find_last_index, min, max, unique, unique_index,
|
||||||
sum/product (integral)
|
sum/product (integral), reverse (ordering)
|
||||||
|
|
||||||
Behavior notes (LRM-oriented):
|
Behavior notes (LRM-oriented):
|
||||||
|
|
||||||
|
|
@ -29,6 +29,10 @@ Behavior notes (LRM-oriented):
|
||||||
vector types).
|
vector types).
|
||||||
`product() with (expr)` reduces the expression result for each item.
|
`product() with (expr)` reduces the expression result for each item.
|
||||||
|
|
||||||
|
* reverse() reverses the order of elements in place for queues and dynamic
|
||||||
|
arrays (integral, vector, real, string, and class-handle elements as stored
|
||||||
|
by Icarus).
|
||||||
|
|
||||||
* For dynamic arrays, runtime support treats storage as vvp_darray (including
|
* For dynamic arrays, runtime support treats storage as vvp_darray (including
|
||||||
atom-backed integral arrays), not only vvp_queue_vec4. See vvp/vthread.cc:
|
atom-backed integral arrays), not only vvp_queue_vec4. See vvp/vthread.cc:
|
||||||
get_queue_or_darray_vec4_from_net() and the %queue/* opcodes used for
|
get_queue_or_darray_vec4_from_net() and the %queue/* opcodes used for
|
||||||
|
|
@ -39,8 +43,10 @@ Compiler / codegen touchpoints (typical):
|
||||||
* Elaboration: elab_expr.cc — NetESFunc $ivl_queue_method$* and with-predicate
|
* Elaboration: elab_expr.cc — NetESFunc $ivl_queue_method$* and with-predicate
|
||||||
lowering.
|
lowering.
|
||||||
* Code generation: tgt-vvp/eval_object.c — eval_queue_method_find,
|
* Code generation: tgt-vvp/eval_object.c — eval_queue_method_find,
|
||||||
eval_queue_method_find_with; eval_vec4.c for non-with find*.
|
eval_queue_method_find_with; eval_vec4.c for non-with find*;
|
||||||
* VVP: vvp/vthread.cc — opcode implementations; vvp/compile.cc — opcode tables.
|
tgt-vvp/vvp_process.c — reverse/delete as system tasks (`%reverse/obj`, …).
|
||||||
|
* VVP: vvp/vthread.cc — opcode implementations; vvp/vvp_darray.{h,cc} —
|
||||||
|
reverse_elems(); vvp/compile.cc — opcode tables.
|
||||||
|
|
||||||
Regression tests (see ivtest/vvp_tests/*.json and regress-vvp.list):
|
Regression tests (see ivtest/vvp_tests/*.json and regress-vvp.list):
|
||||||
|
|
||||||
|
|
@ -64,6 +70,8 @@ Regression tests (see ivtest/vvp_tests/*.json and regress-vvp.list):
|
||||||
sv_darray_product.v integral product() reduction on dynamic arrays.
|
sv_darray_product.v integral product() reduction on dynamic arrays.
|
||||||
sv_queue_product_with.v product() with expression on queues.
|
sv_queue_product_with.v product() with expression on queues.
|
||||||
sv_darray_product_with.v product() with expression on dynamic arrays.
|
sv_darray_product_with.v product() with expression on dynamic arrays.
|
||||||
|
sv_darray_reverse.v reverse() ordering on dynamic arrays.
|
||||||
|
sv_queue_reverse.v reverse() ordering on queues.
|
||||||
sv_queue_sum.v integral sum() reduction on queues.
|
sv_queue_sum.v integral sum() reduction on queues.
|
||||||
sv_darray_sum.v integral sum() reduction on dynamic arrays.
|
sv_darray_sum.v integral sum() reduction on dynamic arrays.
|
||||||
sv_queue_sum_with.v sum() with expression on queues.
|
sv_queue_sum_with.v sum() with expression on queues.
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,12 @@ module test;
|
||||||
`check(c.d.sum() with (item + 1), 12);
|
`check(c.d.sum() with (item + 1), 12);
|
||||||
`check(c.d.product() with (item + 1), 60);
|
`check(c.d.product() with (item + 1), 60);
|
||||||
|
|
||||||
|
c.d = '{1, 2, 3};
|
||||||
|
c.d.reverse();
|
||||||
|
`check(c.d[0], 3);
|
||||||
|
`check(c.d[1], 2);
|
||||||
|
`check(c.d[2], 1);
|
||||||
|
|
||||||
if (!failed)
|
if (!failed)
|
||||||
$display("PASSED");
|
$display("PASSED");
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,12 @@ module test;
|
||||||
`check(c.q.sum() with (item + 1), 12);
|
`check(c.q.sum() with (item + 1), 12);
|
||||||
`check(c.q.product() with (item + 1), 60);
|
`check(c.q.product() with (item + 1), 60);
|
||||||
|
|
||||||
|
c.q = '{1, 2, 3};
|
||||||
|
c.q.reverse();
|
||||||
|
`check(c.q[0], 3);
|
||||||
|
`check(c.q[1], 2);
|
||||||
|
`check(c.q[2], 1);
|
||||||
|
|
||||||
if (!failed)
|
if (!failed)
|
||||||
$display("PASSED");
|
$display("PASSED");
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Regression: dynamic array reverse() ordering method.
|
||||||
|
|
||||||
|
module top;
|
||||||
|
|
||||||
|
bit failed = 0;
|
||||||
|
|
||||||
|
`define CHK(cond) \
|
||||||
|
if (!(cond)) begin \
|
||||||
|
$display("FAILED line %0d", `__LINE__); \
|
||||||
|
failed = 1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int a[];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
a = '{1, 2, 3, 4};
|
||||||
|
a.reverse();
|
||||||
|
`CHK(a[0] === 4 && a[1] === 3 && a[2] === 2 && a[3] === 1);
|
||||||
|
|
||||||
|
a = new [1];
|
||||||
|
a[0] = 42;
|
||||||
|
a.reverse();
|
||||||
|
`CHK(a[0] === 42);
|
||||||
|
|
||||||
|
a = new [0];
|
||||||
|
a.reverse();
|
||||||
|
`CHK(a.size() === 0);
|
||||||
|
|
||||||
|
if (!failed)
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Regression: queue reverse() ordering method.
|
||||||
|
|
||||||
|
module top;
|
||||||
|
|
||||||
|
bit failed = 0;
|
||||||
|
|
||||||
|
`define CHK(cond) \
|
||||||
|
if (!(cond)) begin \
|
||||||
|
$display("FAILED line %0d", `__LINE__); \
|
||||||
|
failed = 1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int q[$];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
q = '{1, 2, 3, 4};
|
||||||
|
q.reverse();
|
||||||
|
`CHK(q[0] === 4 && q[1] === 3 && q[2] === 2 && q[3] === 1);
|
||||||
|
|
||||||
|
q = '{99};
|
||||||
|
q.reverse();
|
||||||
|
`CHK(q[0] === 99);
|
||||||
|
|
||||||
|
q.delete();
|
||||||
|
q.reverse();
|
||||||
|
`CHK(q.size() === 0);
|
||||||
|
|
||||||
|
if (!failed)
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -259,6 +259,7 @@ sv_darray_min_max vvp_tests/sv_darray_min_max.json
|
||||||
sv_darray_min_max_with vvp_tests/sv_darray_min_max_with.json
|
sv_darray_min_max_with vvp_tests/sv_darray_min_max_with.json
|
||||||
sv_darray_product vvp_tests/sv_darray_product.json
|
sv_darray_product vvp_tests/sv_darray_product.json
|
||||||
sv_darray_product_with vvp_tests/sv_darray_product_with.json
|
sv_darray_product_with vvp_tests/sv_darray_product_with.json
|
||||||
|
sv_darray_reverse vvp_tests/sv_darray_reverse.json
|
||||||
sv_darray_sum vvp_tests/sv_darray_sum.json
|
sv_darray_sum vvp_tests/sv_darray_sum.json
|
||||||
sv_darray_sum_with vvp_tests/sv_darray_sum_with.json
|
sv_darray_sum_with vvp_tests/sv_darray_sum_with.json
|
||||||
sv_darray_unique vvp_tests/sv_darray_unique.json
|
sv_darray_unique vvp_tests/sv_darray_unique.json
|
||||||
|
|
@ -290,6 +291,7 @@ sv_queue_min_max vvp_tests/sv_queue_min_max.json
|
||||||
sv_queue_min_max_with vvp_tests/sv_queue_min_max_with.json
|
sv_queue_min_max_with vvp_tests/sv_queue_min_max_with.json
|
||||||
sv_queue_product vvp_tests/sv_queue_product.json
|
sv_queue_product vvp_tests/sv_queue_product.json
|
||||||
sv_queue_product_with vvp_tests/sv_queue_product_with.json
|
sv_queue_product_with vvp_tests/sv_queue_product_with.json
|
||||||
|
sv_queue_reverse vvp_tests/sv_queue_reverse.json
|
||||||
sv_queue_sum vvp_tests/sv_queue_sum.json
|
sv_queue_sum vvp_tests/sv_queue_sum.json
|
||||||
sv_queue_sum_with vvp_tests/sv_queue_sum_with.json
|
sv_queue_sum_with vvp_tests/sv_queue_sum_with.json
|
||||||
sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json
|
sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_darray_reverse.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ],
|
||||||
|
"vlog95" : {
|
||||||
|
"__comment" : "SystemVerilog dynamic array reverse()",
|
||||||
|
"type" : "CE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_queue_reverse.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ],
|
||||||
|
"vlog95" : {
|
||||||
|
"__comment" : "SystemVerilog queue reverse()",
|
||||||
|
"type" : "CE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3454,9 +3454,10 @@ bool NetScope::check_synth(ivl_process_type_t pr_type,
|
||||||
bool NetSTask::check_synth(ivl_process_type_t pr_type,
|
bool NetSTask::check_synth(ivl_process_type_t pr_type,
|
||||||
const NetScope* /* scope */) const
|
const NetScope* /* scope */) const
|
||||||
{
|
{
|
||||||
if (strcmp(name(), "$ivl_darray_method$delete") == 0) {
|
if (strcmp(name(), "$ivl_darray_method$delete") == 0 ||
|
||||||
|
strcmp(name(), "$ivl_darray_method$reverse") == 0) {
|
||||||
cerr << get_fileline() << ": warning: Dynamic array "
|
cerr << get_fileline() << ": warning: Dynamic array "
|
||||||
"delete method cannot be synthesized "
|
"ordering/delete method cannot be synthesized "
|
||||||
<< get_process_type_as_string(pr_type) << endl;
|
<< get_process_type_as_string(pr_type) << endl;
|
||||||
} else {
|
} else {
|
||||||
cerr << get_fileline() << ": warning: System task ("
|
cerr << get_fileline() << ": warning: System task ("
|
||||||
|
|
|
||||||
|
|
@ -1691,11 +1691,41 @@ static int show_delete_method(ivl_statement_t net)
|
||||||
draw_eval_expr_into_integer(ivl_stmt_parm(net, 1), 3);
|
draw_eval_expr_into_integer(ivl_stmt_parm(net, 1), 3);
|
||||||
fprintf(vvp_out, " %%delete/elem v%p_0;\n", var);
|
fprintf(vvp_out, " %%delete/elem v%p_0;\n", var);
|
||||||
} else {
|
} else {
|
||||||
fprintf(vvp_out, " %%delete/obj v%p_0;\n", var);
|
fprintf(vvp_out, " %%delete/obj v%p_0;\n", var);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int show_reverse_method(ivl_statement_t net)
|
||||||
|
{
|
||||||
|
show_stmt_file_line(net, "reverse dynamic array or queue");
|
||||||
|
|
||||||
|
unsigned parm_count = ivl_stmt_parm_count(net);
|
||||||
|
if (parm_count != 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ivl_expr_t parm = ivl_stmt_parm(net, 0);
|
||||||
|
if (ivl_expr_type(parm) == IVL_EX_PROPERTY) {
|
||||||
|
ivl_signal_t clas = ivl_expr_signal(parm);
|
||||||
|
unsigned pidx = ivl_expr_property_idx(parm);
|
||||||
|
ivl_type_t sig_type = ivl_signal_net_type(clas);
|
||||||
|
ivl_type_t arr_type = ivl_type_prop_type(sig_type, pidx);
|
||||||
|
ivl_variable_type_t bt = ivl_type_base(arr_type);
|
||||||
|
if (bt != IVL_VT_QUEUE && bt != IVL_VT_DARRAY)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", clas);
|
||||||
|
fprintf(vvp_out, " %%reverse/prop/obj %u;\n", pidx);
|
||||||
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(ivl_expr_type(parm) == IVL_EX_SIGNAL);
|
||||||
|
ivl_signal_t var = ivl_expr_signal(parm);
|
||||||
|
fprintf(vvp_out, " %%reverse/obj v%p_0;\n", var);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int show_insert_method(ivl_statement_t net)
|
static int show_insert_method(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
show_stmt_file_line(net, "queue: insert");
|
show_stmt_file_line(net, "queue: insert");
|
||||||
|
|
@ -1881,6 +1911,9 @@ static int show_system_task_call(ivl_statement_t net)
|
||||||
if (strcmp(stmt_name,"$ivl_darray_method$delete") == 0)
|
if (strcmp(stmt_name,"$ivl_darray_method$delete") == 0)
|
||||||
return show_delete_method(net);
|
return show_delete_method(net);
|
||||||
|
|
||||||
|
if (strcmp(stmt_name,"$ivl_darray_method$reverse") == 0)
|
||||||
|
return show_reverse_method(net);
|
||||||
|
|
||||||
if (strcmp(stmt_name,"$ivl_queue_method$insert") == 0)
|
if (strcmp(stmt_name,"$ivl_queue_method$insert") == 0)
|
||||||
return show_insert_method(net);
|
return show_insert_method(net);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,8 @@ extern bool of_REPLICATE(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RET_REAL(vthread_t thr, vvp_code_t code);
|
extern bool of_RET_REAL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RET_STR(vthread_t thr, vvp_code_t code);
|
extern bool of_RET_STR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RET_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_RET_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_REVERSE_OBJ(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_REVERSE_PROP_OBJ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RETLOAD_REAL(vthread_t thr, vvp_code_t code);
|
extern bool of_RETLOAD_REAL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RETLOAD_STR(vthread_t thr, vvp_code_t code);
|
extern bool of_RETLOAD_STR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RETLOAD_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_RETLOAD_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,8 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%retload/real",of_RETLOAD_REAL,1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
{ "%retload/real",of_RETLOAD_REAL,1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
||||||
{ "%retload/str", of_RETLOAD_STR, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
{ "%retload/str", of_RETLOAD_STR, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
||||||
{ "%retload/vec4",of_RETLOAD_VEC4,1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
{ "%retload/vec4",of_RETLOAD_VEC4,1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
||||||
|
{ "%reverse/obj", of_REVERSE_OBJ, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
|
{ "%reverse/prop/obj", of_REVERSE_PROP_OBJ, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
{ "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
||||||
{ "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
{ "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
||||||
|
|
|
||||||
|
|
@ -2610,6 +2610,62 @@ bool of_DELETE_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* %reverse/obj <label>
|
||||||
|
* Reverse element order of the queue or dynamic array object at this net.
|
||||||
|
*/
|
||||||
|
bool of_REVERSE_OBJ(vthread_t /*thr*/, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
vvp_net_t*net = cp->net;
|
||||||
|
|
||||||
|
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*>(net->fun);
|
||||||
|
assert(obj);
|
||||||
|
|
||||||
|
vvp_object_t stor = obj->get_object();
|
||||||
|
if (stor.test_nil())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Match other queue ops: peek queues before vvp_darray so concrete
|
||||||
|
queue types dispatch reverse_elems() correctly. */
|
||||||
|
if (vvp_queue* queue = stor.peek<vvp_queue>()) {
|
||||||
|
queue->reverse_elems();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vvp_darray*darray = stor.peek<vvp_darray>();
|
||||||
|
assert(darray);
|
||||||
|
darray->reverse_elems();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* %reverse/prop/obj <property-index>
|
||||||
|
* Reverse queue/darray property storage inside the class object on stack top.
|
||||||
|
*/
|
||||||
|
bool of_REVERSE_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
size_t pid = cp->number;
|
||||||
|
|
||||||
|
vvp_object_t& top = thr->peek_object();
|
||||||
|
vvp_cobject*cobj = top.peek<vvp_cobject>();
|
||||||
|
assert(cobj);
|
||||||
|
|
||||||
|
vvp_object_t arr_obj;
|
||||||
|
cobj->get_object(pid, arr_obj, 0);
|
||||||
|
if (arr_obj.test_nil())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (vvp_queue* queue = arr_obj.peek<vvp_queue>()) {
|
||||||
|
queue->reverse_elems();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vvp_darray*darray = arr_obj.peek<vvp_darray>();
|
||||||
|
assert(darray);
|
||||||
|
darray->reverse_elems();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* %delete/tail <label>, idx
|
/* %delete/tail <label>, idx
|
||||||
*
|
*
|
||||||
* Remove all elements after the one specified.
|
* Remove all elements after the one specified.
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include "vvp_darray.h"
|
# include "vvp_darray.h"
|
||||||
|
# include <algorithm>
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
|
|
||||||
|
|
@ -27,6 +28,12 @@ vvp_darray::~vvp_darray()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_darray::reverse_elems(void)
|
||||||
|
{
|
||||||
|
cerr << "XXXX reverse_elems() not implemented for "
|
||||||
|
<< typeid(*this).name() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_darray::set_word(unsigned, const vvp_vector4_t&)
|
void vvp_darray::set_word(unsigned, const vvp_vector4_t&)
|
||||||
{
|
{
|
||||||
cerr << "XXXX set_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
|
cerr << "XXXX set_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
|
||||||
|
|
@ -82,6 +89,13 @@ template <class TYPE> size_t vvp_darray_atom<TYPE>::get_size() const
|
||||||
return array_.size();
|
return array_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class TYPE> void vvp_darray_atom<TYPE>::reverse_elems(void)
|
||||||
|
{
|
||||||
|
size_t n = array_.size();
|
||||||
|
for (size_t idx = 0 ; idx < n/2 ; idx += 1)
|
||||||
|
std::swap(array_[idx], array_[n-1-idx]);
|
||||||
|
}
|
||||||
|
|
||||||
template <class TYPE> void vvp_darray_atom<TYPE>::set_word(unsigned adr, const vvp_vector4_t&value)
|
template <class TYPE> void vvp_darray_atom<TYPE>::set_word(unsigned adr, const vvp_vector4_t&value)
|
||||||
{
|
{
|
||||||
if (adr >= array_.size())
|
if (adr >= array_.size())
|
||||||
|
|
@ -225,6 +239,20 @@ vvp_vector4_t vvp_darray_vec4::get_bitstream(bool as_vec4)
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_darray_vec4::reverse_elems(void)
|
||||||
|
{
|
||||||
|
size_t n = array_.size();
|
||||||
|
for (size_t idx = 0 ; idx < n/2 ; idx += 1)
|
||||||
|
std::swap(array_[idx], array_[n-1-idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_darray_vec2::reverse_elems(void)
|
||||||
|
{
|
||||||
|
size_t n = array_.size();
|
||||||
|
for (size_t idx = 0 ; idx < n/2 ; idx += 1)
|
||||||
|
std::swap(array_[idx], array_[n-1-idx]);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_darray_vec2::~vvp_darray_vec2()
|
vvp_darray_vec2::~vvp_darray_vec2()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -322,6 +350,13 @@ void vvp_darray_object::shallow_copy(const vvp_object*obj)
|
||||||
array_[idx] = that->array_[idx];
|
array_[idx] = that->array_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_darray_object::reverse_elems(void)
|
||||||
|
{
|
||||||
|
size_t n = array_.size();
|
||||||
|
for (size_t idx = 0 ; idx < n/2 ; idx += 1)
|
||||||
|
std::swap(array_[idx], array_[n-1-idx]);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_darray_real::~vvp_darray_real()
|
vvp_darray_real::~vvp_darray_real()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -358,6 +393,13 @@ void vvp_darray_real::shallow_copy(const vvp_object*obj)
|
||||||
array_[idx] = that->array_[idx];
|
array_[idx] = that->array_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_darray_real::reverse_elems(void)
|
||||||
|
{
|
||||||
|
size_t n = array_.size();
|
||||||
|
for (size_t idx = 0 ; idx < n/2 ; idx += 1)
|
||||||
|
std::swap(array_[idx], array_[n-1-idx]);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_object* vvp_darray_real::duplicate(void) const
|
vvp_object* vvp_darray_real::duplicate(void) const
|
||||||
{
|
{
|
||||||
vvp_darray_real*that = new vvp_darray_real(array_.size());
|
vvp_darray_real*that = new vvp_darray_real(array_.size());
|
||||||
|
|
@ -430,6 +472,13 @@ void vvp_darray_string::shallow_copy(const vvp_object*obj)
|
||||||
array_[idx] = that->array_[idx];
|
array_[idx] = that->array_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_darray_string::reverse_elems(void)
|
||||||
|
{
|
||||||
|
size_t n = array_.size();
|
||||||
|
for (size_t idx = 0 ; idx < n/2 ; idx += 1)
|
||||||
|
std::swap(array_[idx], array_[n-1-idx]);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_object* vvp_darray_string::duplicate(void) const
|
vvp_object* vvp_darray_string::duplicate(void) const
|
||||||
{
|
{
|
||||||
vvp_darray_string*that = new vvp_darray_string(array_.size());
|
vvp_darray_string*that = new vvp_darray_string(array_.size());
|
||||||
|
|
@ -769,6 +818,16 @@ void vvp_queue_string::erase_tail(unsigned idx)
|
||||||
queue.resize(idx);
|
queue.resize(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_queue_real::reverse_elems(void)
|
||||||
|
{
|
||||||
|
std::reverse(queue.begin(), queue.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_queue_string::reverse_elems(void)
|
||||||
|
{
|
||||||
|
std::reverse(queue.begin(), queue.end());
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_queue_vec4::copy_elems(vvp_object_t src, unsigned max_size)
|
void vvp_queue_vec4::copy_elems(vvp_object_t src, unsigned max_size)
|
||||||
{
|
{
|
||||||
if (vvp_queue*src_queue = src.peek<vvp_queue>())
|
if (vvp_queue*src_queue = src.peek<vvp_queue>())
|
||||||
|
|
@ -876,3 +935,8 @@ void vvp_queue_vec4::erase_tail(unsigned idx)
|
||||||
if (queue.size() > idx)
|
if (queue.size() > idx)
|
||||||
queue.resize(idx);
|
queue.resize(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_queue_vec4::reverse_elems(void)
|
||||||
|
{
|
||||||
|
std::reverse(queue.begin(), queue.end());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ class vvp_darray : public vvp_object {
|
||||||
virtual void get_word(unsigned adr, vvp_object_t&value);
|
virtual void get_word(unsigned adr, vvp_object_t&value);
|
||||||
|
|
||||||
virtual vvp_vector4_t get_bitstream(bool as_vec4);
|
virtual vvp_vector4_t get_bitstream(bool as_vec4);
|
||||||
|
|
||||||
|
/* In-place element order reversal (dynamic arrays and queues). */
|
||||||
|
virtual void reverse_elems(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class TYPE> class vvp_darray_atom : public vvp_darray {
|
template <class TYPE> class vvp_darray_atom : public vvp_darray {
|
||||||
|
|
@ -55,6 +58,7 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
|
||||||
~vvp_darray_atom() override;
|
~vvp_darray_atom() override;
|
||||||
|
|
||||||
size_t get_size(void) const override;
|
size_t get_size(void) const override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
void set_word(unsigned adr, const vvp_vector4_t&value) override;
|
void set_word(unsigned adr, const vvp_vector4_t&value) override;
|
||||||
void get_word(unsigned adr, vvp_vector4_t&value) override;
|
void get_word(unsigned adr, vvp_vector4_t&value) override;
|
||||||
void shallow_copy(const vvp_object*obj) override;
|
void shallow_copy(const vvp_object*obj) override;
|
||||||
|
|
@ -78,6 +82,7 @@ class vvp_darray_vec4 : public vvp_darray {
|
||||||
void shallow_copy(const vvp_object*obj) override;
|
void shallow_copy(const vvp_object*obj) override;
|
||||||
vvp_object* duplicate(void) const override;
|
vvp_object* duplicate(void) const override;
|
||||||
vvp_vector4_t get_bitstream(bool as_vec4) override;
|
vvp_vector4_t get_bitstream(bool as_vec4) override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<vvp_vector4_t> array_;
|
std::vector<vvp_vector4_t> array_;
|
||||||
|
|
@ -92,6 +97,7 @@ class vvp_darray_vec2 : public vvp_darray {
|
||||||
~vvp_darray_vec2() override;
|
~vvp_darray_vec2() override;
|
||||||
|
|
||||||
size_t get_size(void) const override;
|
size_t get_size(void) const override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
void set_word(unsigned adr, const vvp_vector4_t&value) override;
|
void set_word(unsigned adr, const vvp_vector4_t&value) override;
|
||||||
void get_word(unsigned adr, vvp_vector4_t&value) override;
|
void get_word(unsigned adr, vvp_vector4_t&value) override;
|
||||||
void shallow_copy(const vvp_object*obj) override;
|
void shallow_copy(const vvp_object*obj) override;
|
||||||
|
|
@ -114,6 +120,7 @@ class vvp_darray_real : public vvp_darray {
|
||||||
void shallow_copy(const vvp_object*obj) override;
|
void shallow_copy(const vvp_object*obj) override;
|
||||||
vvp_object* duplicate(void) const override;
|
vvp_object* duplicate(void) const override;
|
||||||
vvp_vector4_t get_bitstream(bool as_vec4) override;
|
vvp_vector4_t get_bitstream(bool as_vec4) override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<double> array_;
|
std::vector<double> array_;
|
||||||
|
|
@ -130,6 +137,7 @@ class vvp_darray_string : public vvp_darray {
|
||||||
void get_word(unsigned adr, std::string&value) override;
|
void get_word(unsigned adr, std::string&value) override;
|
||||||
void shallow_copy(const vvp_object*obj) override;
|
void shallow_copy(const vvp_object*obj) override;
|
||||||
vvp_object* duplicate(void) const override;
|
vvp_object* duplicate(void) const override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> array_;
|
std::vector<std::string> array_;
|
||||||
|
|
@ -142,6 +150,7 @@ class vvp_darray_object : public vvp_darray {
|
||||||
~vvp_darray_object() override;
|
~vvp_darray_object() override;
|
||||||
|
|
||||||
size_t get_size(void) const override;
|
size_t get_size(void) const override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
void set_word(unsigned adr, const vvp_object_t&value) override;
|
void set_word(unsigned adr, const vvp_object_t&value) override;
|
||||||
void get_word(unsigned adr, vvp_object_t&value) override;
|
void get_word(unsigned adr, vvp_object_t&value) override;
|
||||||
void shallow_copy(const vvp_object*obj) override;
|
void shallow_copy(const vvp_object*obj) override;
|
||||||
|
|
@ -196,6 +205,7 @@ class vvp_queue_real : public vvp_queue {
|
||||||
void pop_front(void) override { queue.pop_front(); };
|
void pop_front(void) override { queue.pop_front(); };
|
||||||
void erase(unsigned idx) override;
|
void erase(unsigned idx) override;
|
||||||
void erase_tail(unsigned idx) override;
|
void erase_tail(unsigned idx) override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<double> queue;
|
std::deque<double> queue;
|
||||||
|
|
@ -216,6 +226,7 @@ class vvp_queue_string : public vvp_queue {
|
||||||
void pop_front(void) override { queue.pop_front(); };
|
void pop_front(void) override { queue.pop_front(); };
|
||||||
void erase(unsigned idx) override;
|
void erase(unsigned idx) override;
|
||||||
void erase_tail(unsigned idx) override;
|
void erase_tail(unsigned idx) override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<std::string> queue;
|
std::deque<std::string> queue;
|
||||||
|
|
@ -236,6 +247,7 @@ class vvp_queue_vec4 : public vvp_queue {
|
||||||
void pop_front(void) override { queue.pop_front(); };
|
void pop_front(void) override { queue.pop_front(); };
|
||||||
void erase(unsigned idx) override;
|
void erase(unsigned idx) override;
|
||||||
void erase_tail(unsigned idx) override;
|
void erase_tail(unsigned idx) override;
|
||||||
|
void reverse_elems(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<vvp_vector4_t> queue;
|
std::deque<vvp_vector4_t> queue;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue