From afe849249c6205e76c16f2e622250597a64ac815 Mon Sep 17 00:00:00 2001 From: mjoekhan Date: Wed, 1 Jul 2026 12:45:16 +0500 Subject: [PATCH] SV: reverse(), sort(), rsort(), shuffle() for queues/darrays Add ordering methods for queues and dynamic arrays. Update ivtest gold files for always_*_warn, br1005, and br_gh710b LXT per review. Split from steveicarus/iverilog#1330 (part 06/6). --- elaborate.cc | 98 ++++++-- ivtest/gold/always_comb_warn.gold | 2 +- ivtest/gold/always_ff_warn.gold | 2 +- ivtest/gold/always_latch_warn.gold | 2 +- .../ivltests/sv_class_darray_prop_locators.v | 14 ++ .../ivltests/sv_class_queue_prop_locators.v | 14 ++ ivtest/ivltests/sv_darray_reverse.v | 32 +++ ivtest/ivltests/sv_darray_sort.v | 33 +++ ivtest/ivltests/sv_queue_reverse.v | 31 +++ ivtest/ivltests/sv_queue_sort.v | 33 +++ ivtest/regress-vvp.list | 4 + ivtest/vvp_tests/sv_darray_reverse.json | 9 + ivtest/vvp_tests/sv_darray_sort.json | 9 + ivtest/vvp_tests/sv_queue_reverse.json | 9 + ivtest/vvp_tests/sv_queue_sort.json | 9 + netlist.cc | 8 +- tgt-vvp/vvp_process.c | 74 +++++- vvp/codes.h | 8 + vvp/compile.cc | 8 + vvp/vthread.cc | 198 +++++++++++++++ vvp/vvp_darray.cc | 226 ++++++++++++++++++ vvp/vvp_darray.h | 34 +++ vvp/vvp_object.h | 7 + 23 files changed, 835 insertions(+), 29 deletions(-) create mode 100644 ivtest/ivltests/sv_darray_reverse.v create mode 100644 ivtest/ivltests/sv_darray_sort.v create mode 100644 ivtest/ivltests/sv_queue_reverse.v create mode 100644 ivtest/ivltests/sv_queue_sort.v create mode 100644 ivtest/vvp_tests/sv_darray_reverse.json create mode 100644 ivtest/vvp_tests/sv_darray_sort.json create mode 100644 ivtest/vvp_tests/sv_queue_reverse.json create mode 100644 ivtest/vvp_tests/sv_queue_sort.json diff --git a/elaborate.cc b/elaborate.cc index aa868614d..214a72f88 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4385,6 +4385,34 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, &netvector_t::atom2s32, method_name, "$size"); } + if (method_name == "reverse") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$reverse", + parm_names); + } + if (method_name == "sort") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$sort", + parm_names); + } + if (method_name == "rsort") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$rsort", + parm_names); + } + if (method_name == "shuffle") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$shuffle", + parm_names); + } } else if (ptype && ptype->base_type() == IVL_VT_DARRAY) { if (method_name == "delete") { static const std::vector parm_names = { @@ -4400,6 +4428,34 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, &netvector_t::atom2s32, method_name, "$size"); } + if (method_name == "reverse") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$reverse", + parm_names); + } + if (method_name == "sort") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$sort", + parm_names); + } + if (method_name == "rsort") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$rsort", + parm_names); + } + if (method_name == "shuffle") { + static const std::vector parm_names; + return elaborate_sys_task_property_method_(des, scope, net, pidx, + method_name, + "$ivl_darray_method$shuffle", + parm_names); + } } } } @@ -4460,29 +4516,25 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, &netvector_t::atom2s32, method_name, "$size"); } else if (method_name == "reverse") { - cerr << get_fileline() << ": sorry: 'reverse()' " - "array sorting method is not currently supported." - << endl; - des->errors += 1; - return 0; - } else if (method_name=="sort") { - cerr << get_fileline() << ": sorry: 'sort()' " - "array sorting method is not currently supported." - << endl; - des->errors += 1; - return 0; - } else if (method_name=="rsort") { - cerr << get_fileline() << ": sorry: 'rsort()' " - "array sorting method is not currently supported." - << endl; - des->errors += 1; - return 0; - } else if (method_name=="shuffle") { - cerr << get_fileline() << ": sorry: 'shuffle()' " - "array sorting method is not currently supported." - << endl; - des->errors += 1; - return 0; + static const std::vector parm_names; + return elaborate_sys_task_method_(des, scope, net, method_name, + "$ivl_darray_method$reverse", + parm_names); + } else if (method_name == "sort") { + static const std::vector parm_names; + return elaborate_sys_task_method_(des, scope, net, method_name, + "$ivl_darray_method$sort", + parm_names); + } else if (method_name == "rsort") { + static const std::vector parm_names; + return elaborate_sys_task_method_(des, scope, net, method_name, + "$ivl_darray_method$rsort", + parm_names); + } else if (method_name == "shuffle") { + static const std::vector parm_names; + return elaborate_sys_task_method_(des, scope, net, method_name, + "$ivl_darray_method$shuffle", + parm_names); } } diff --git a/ivtest/gold/always_comb_warn.gold b/ivtest/gold/always_comb_warn.gold index d9f2df207..183d31c11 100644 --- a/ivtest/gold/always_comb_warn.gold +++ b/ivtest/gold/always_comb_warn.gold @@ -23,7 +23,7 @@ ./ivltests/always_comb_warn.v:32: warning: A for statement step must be a simple binary +/- to be synthesized in an always_comb process. ./ivltests/always_comb_warn.v:32: warning: System task ($display) cannot be synthesized in an always_comb process. ./ivltests/always_comb_warn.v:33: warning: System task ($display) cannot be synthesized in an always_comb process. -./ivltests/always_comb_warn.v:34: warning: Dynamic array delete method cannot be synthesized in an always_comb process. +./ivltests/always_comb_warn.v:34: warning: Dynamic array ordering/delete method cannot be synthesized in an always_comb process. ./ivltests/always_comb_warn.v:35: warning: System task ($display) cannot be synthesized in an always_comb process. ./ivltests/always_comb_warn.v:14: warning: An event (tevt) cannot be synthesized in an always_comb process. ./ivltests/always_comb_warn.v:13: warning: A non-integral variable (trl) cannot be synthesized in an always_comb process. diff --git a/ivtest/gold/always_ff_warn.gold b/ivtest/gold/always_ff_warn.gold index 8f13486a6..335e4a82f 100644 --- a/ivtest/gold/always_ff_warn.gold +++ b/ivtest/gold/always_ff_warn.gold @@ -21,7 +21,7 @@ ./ivltests/always_ff_warn.v:33: warning: A for statement step must be a simple binary +/- to be synthesized in an always_ff process. ./ivltests/always_ff_warn.v:33: warning: System task ($display) cannot be synthesized in an always_ff process. ./ivltests/always_ff_warn.v:34: warning: System task ($display) cannot be synthesized in an always_ff process. -./ivltests/always_ff_warn.v:35: warning: Dynamic array delete method cannot be synthesized in an always_ff process. +./ivltests/always_ff_warn.v:35: warning: Dynamic array ordering/delete method cannot be synthesized in an always_ff process. ./ivltests/always_ff_warn.v:36: warning: System task ($display) cannot be synthesized in an always_ff process. ./ivltests/always_ff_warn.v:15: warning: An event (tevt) cannot be synthesized in an always_ff process. ./ivltests/always_ff_warn.v:14: warning: A non-integral variable (trl) cannot be synthesized in an always_ff process. diff --git a/ivtest/gold/always_latch_warn.gold b/ivtest/gold/always_latch_warn.gold index deab07d67..2cef5b242 100644 --- a/ivtest/gold/always_latch_warn.gold +++ b/ivtest/gold/always_latch_warn.gold @@ -21,7 +21,7 @@ ./ivltests/always_latch_warn.v:32: warning: A for statement step must be a simple binary +/- to be synthesized in an always_latch process. ./ivltests/always_latch_warn.v:32: warning: System task ($display) cannot be synthesized in an always_latch process. ./ivltests/always_latch_warn.v:33: warning: System task ($display) cannot be synthesized in an always_latch process. -./ivltests/always_latch_warn.v:34: warning: Dynamic array delete method cannot be synthesized in an always_latch process. +./ivltests/always_latch_warn.v:34: warning: Dynamic array ordering/delete method cannot be synthesized in an always_latch process. ./ivltests/always_latch_warn.v:35: warning: System task ($display) cannot be synthesized in an always_latch process. ./ivltests/always_latch_warn.v:14: warning: An event (tevt) cannot be synthesized in an always_latch process. ./ivltests/always_latch_warn.v:13: warning: A non-integral variable (trl) cannot be synthesized in an always_latch process. diff --git a/ivtest/ivltests/sv_class_darray_prop_locators.v b/ivtest/ivltests/sv_class_darray_prop_locators.v index 7458e8ffe..58f584f45 100644 --- a/ivtest/ivltests/sv_class_darray_prop_locators.v +++ b/ivtest/ivltests/sv_class_darray_prop_locators.v @@ -59,6 +59,20 @@ module test; c.d = '{2, 3, 4}; `check(c.d.product(), 24); + `check(c.d.sum() with (item + 1), 12); + `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); + + c.d = '{3, 1, 2}; + c.d.sort(); + `check(c.d[0], 1); + `check(c.d[1], 2); + `check(c.d[2], 3); if (!failed) $display("PASSED"); diff --git a/ivtest/ivltests/sv_class_queue_prop_locators.v b/ivtest/ivltests/sv_class_queue_prop_locators.v index c6e5adf0b..eabb557d4 100644 --- a/ivtest/ivltests/sv_class_queue_prop_locators.v +++ b/ivtest/ivltests/sv_class_queue_prop_locators.v @@ -51,6 +51,20 @@ module test; c.q = '{2, 3, 4}; `check(c.q.product(), 24); + `check(c.q.sum() with (item + 1), 12); + `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); + + c.q = '{3, 1, 2}; + c.q.sort(); + `check(c.q[0], 1); + `check(c.q[1], 2); + `check(c.q[2], 3); if (!failed) $display("PASSED"); diff --git a/ivtest/ivltests/sv_darray_reverse.v b/ivtest/ivltests/sv_darray_reverse.v new file mode 100644 index 000000000..b55ddf6c9 --- /dev/null +++ b/ivtest/ivltests/sv_darray_reverse.v @@ -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 diff --git a/ivtest/ivltests/sv_darray_sort.v b/ivtest/ivltests/sv_darray_sort.v new file mode 100644 index 000000000..14a04a21c --- /dev/null +++ b/ivtest/ivltests/sv_darray_sort.v @@ -0,0 +1,33 @@ +// Regression: dynamic array sort(), rsort(), shuffle(). + +module top; + + bit failed = 0; + + `define CHK(cond) \ + if (!(cond)) begin \ + $display("FAILED line %0d", `__LINE__); \ + failed = 1; \ + end + + int a[]; + int sum0; + + initial begin + a = '{3, 1, 4, 1, 5}; + a.sort(); + `CHK(a[0] === 1 && a[1] === 1 && a[2] === 3 && a[3] === 4 && a[4] === 5); + + a = '{3, 1, 4}; + a.rsort(); + `CHK(a[0] === 4 && a[1] === 3 && a[2] === 1); + + a = '{10, -2, 7}; + sum0 = a.sum(); + a.shuffle(); + `CHK(a.sum() === sum0); + + if (!failed) + $display("PASSED"); + end +endmodule diff --git a/ivtest/ivltests/sv_queue_reverse.v b/ivtest/ivltests/sv_queue_reverse.v new file mode 100644 index 000000000..5e7574cfb --- /dev/null +++ b/ivtest/ivltests/sv_queue_reverse.v @@ -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 diff --git a/ivtest/ivltests/sv_queue_sort.v b/ivtest/ivltests/sv_queue_sort.v new file mode 100644 index 000000000..f48b2e4dd --- /dev/null +++ b/ivtest/ivltests/sv_queue_sort.v @@ -0,0 +1,33 @@ +// Regression: queue sort(), rsort(), shuffle(). + +module top; + + bit failed = 0; + + `define CHK(cond) \ + if (!(cond)) begin \ + $display("FAILED line %0d", `__LINE__); \ + failed = 1; \ + end + + int q[$]; + int sum0; + + initial begin + q = '{3, 1, 4, 1, 5}; + q.sort(); + `CHK(q[0] === 1 && q[1] === 1 && q[2] === 3 && q[3] === 4 && q[4] === 5); + + q = '{3, 1, 4}; + q.rsort(); + `CHK(q[0] === 4 && q[1] === 3 && q[2] === 1); + + q = '{10, -2, 7}; + sum0 = q.sum(); + q.shuffle(); + `CHK(q.sum() === sum0); + + if (!failed) + $display("PASSED"); + end +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 7fd80304e..46f62b1aa 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -319,6 +319,8 @@ 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_product vvp_tests/sv_darray_product.json sv_darray_product_with vvp_tests/sv_darray_product_with.json +sv_darray_reverse vvp_tests/sv_darray_reverse.json +sv_darray_sort vvp_tests/sv_darray_sort.json sv_darray_sum vvp_tests/sv_darray_sum.json sv_darray_sum_with vvp_tests/sv_darray_sum_with.json sv_darray_unique vvp_tests/sv_darray_unique.json @@ -422,6 +424,8 @@ 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_product vvp_tests/sv_queue_product.json sv_queue_product_with vvp_tests/sv_queue_product_with.json +sv_queue_reverse vvp_tests/sv_queue_reverse.json +sv_queue_sort vvp_tests/sv_queue_sort.json sv_queue_sum vvp_tests/sv_queue_sum.json sv_queue_sum_with vvp_tests/sv_queue_sum_with.json sv_queue_unique vvp_tests/sv_queue_unique.json diff --git a/ivtest/vvp_tests/sv_darray_reverse.json b/ivtest/vvp_tests/sv_darray_reverse.json new file mode 100644 index 000000000..11b7c17d9 --- /dev/null +++ b/ivtest/vvp_tests/sv_darray_reverse.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_darray_reverse.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "SystemVerilog dynamic array reverse()", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_darray_sort.json b/ivtest/vvp_tests/sv_darray_sort.json new file mode 100644 index 000000000..dac245910 --- /dev/null +++ b/ivtest/vvp_tests/sv_darray_sort.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_darray_sort.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "SystemVerilog dynamic array sort/rsort/shuffle", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_queue_reverse.json b/ivtest/vvp_tests/sv_queue_reverse.json new file mode 100644 index 000000000..771b7dbea --- /dev/null +++ b/ivtest/vvp_tests/sv_queue_reverse.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_queue_reverse.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "SystemVerilog queue reverse()", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_queue_sort.json b/ivtest/vvp_tests/sv_queue_sort.json new file mode 100644 index 000000000..a37d4b395 --- /dev/null +++ b/ivtest/vvp_tests/sv_queue_sort.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_queue_sort.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "SystemVerilog queue sort/rsort/shuffle", + "type" : "CE" + } +} diff --git a/netlist.cc b/netlist.cc index 79b5f6cfb..dd7b4c261 100644 --- a/netlist.cc +++ b/netlist.cc @@ -3461,9 +3461,13 @@ bool NetScope::check_synth(ivl_process_type_t pr_type, bool NetSTask::check_synth(ivl_process_type_t pr_type, 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 || + strcmp(name(), "$ivl_darray_method$sort") == 0 || + strcmp(name(), "$ivl_darray_method$rsort") == 0 || + strcmp(name(), "$ivl_darray_method$shuffle") == 0) { 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; } else { cerr << get_fileline() << ": warning: System task (" diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index d01611671..cff3f90ef 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1691,11 +1691,68 @@ static int show_delete_method(ivl_statement_t net) draw_eval_expr_into_integer(ivl_stmt_parm(net, 1), 3); fprintf(vvp_out, " %%delete/elem v%p_0;\n", var); } else { - fprintf(vvp_out, " %%delete/obj v%p_0;\n", var); + fprintf(vvp_out, " %%delete/obj v%p_0;\n", var); } 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_array_order_method(ivl_statement_t net, const char*descr, + const char*op_signal, const char*op_prop) +{ + show_stmt_file_line(net, descr); + + 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, " %s %u;\n", op_prop, 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, " %s v%p_0;\n", op_signal, var); + return 0; +} + static int show_insert_method(ivl_statement_t net) { show_stmt_file_line(net, "queue: insert"); @@ -1881,6 +1938,21 @@ static int show_system_task_call(ivl_statement_t net) if (strcmp(stmt_name,"$ivl_darray_method$delete") == 0) return show_delete_method(net); + if (strcmp(stmt_name,"$ivl_darray_method$reverse") == 0) + return show_reverse_method(net); + + if (strcmp(stmt_name,"$ivl_darray_method$sort") == 0) + return show_array_order_method(net, "sort dynamic array or queue", + "%sort/obj", "%sort/prop/obj"); + + if (strcmp(stmt_name,"$ivl_darray_method$rsort") == 0) + return show_array_order_method(net, "rsort dynamic array or queue", + "%rsort/obj", "%rsort/prop/obj"); + + if (strcmp(stmt_name,"$ivl_darray_method$shuffle") == 0) + return show_array_order_method(net, "shuffle dynamic array or queue", + "%shuffle/obj", "%shuffle/prop/obj"); + if (strcmp(stmt_name,"$ivl_queue_method$insert") == 0) return show_insert_method(net); diff --git a/vvp/codes.h b/vvp/codes.h index 65fe2b13b..fa3c2e73f 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -214,6 +214,14 @@ 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_STR(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_RSORT_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_RSORT_PROP_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_SHUFFLE_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_SHUFFLE_PROP_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_SORT_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_SORT_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_STR(vthread_t thr, vvp_code_t code); extern bool of_RETLOAD_VEC4(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 9fce0507f..8fdce1abf 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -324,6 +324,10 @@ static const struct opcode_table_s opcode_table[] = { { "%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/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} }, + { "%rsort/obj", of_RSORT_OBJ, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%rsort/prop/obj", of_RSORT_PROP_OBJ, 1, {OA_NUMBER, 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/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} }, @@ -331,6 +335,10 @@ static const struct opcode_table_s opcode_table[] = { { "%shiftl", of_SHIFTL, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%shiftr", of_SHIFTR, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%shiftr/s", of_SHIFTR_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%shuffle/obj", of_SHUFFLE_OBJ, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%shuffle/prop/obj", of_SHUFFLE_PROP_OBJ, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%sort/obj", of_SORT_OBJ, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%sort/prop/obj", of_SORT_PROP_OBJ, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%split/vec4", of_SPLIT_VEC4, 1,{OA_NUMBER, OA_NONE, OA_NONE} }, { "%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} }, diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 185ad41c5..b70a81334 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2610,6 +2610,204 @@ bool of_DELETE_OBJ(vthread_t thr, vvp_code_t cp) return true; } +/* %reverse/obj