SV: and/or/xor reductions and item.index for array methods

Complete chipsalliance sv-tests section 7.12 by adding bitwise
and/or/xor reductions (7.12.3) and iterator item.index querying (7.12.4).
This commit is contained in:
mjoekhan 2026-07-21 12:46:58 +05:00
parent 95a80901de
commit b8583dff86
11 changed files with 465 additions and 36 deletions

View File

@ -96,8 +96,12 @@ static NetExpr* elab_array_locator_noparens(Design* des, const LineInfo& loc,
if (method_name == "unique" || method_name == "unique_index" ||
method_name == "min" || method_name == "max" ||
method_name == "sum" || method_name == "product") {
if (method_name == "sum" || method_name == "product") {
method_name == "sum" || method_name == "product" ||
method_name == "and" || method_name == "or" ||
method_name == "xor") {
if (method_name == "sum" || method_name == "product" ||
method_name == "and" || method_name == "or" ||
method_name == "xor") {
if (!queue_method_element_is_integral_vec4(element_type)) {
cerr << loc.get_fileline() << ": sorry: " << kind << " "
<< method_name << "() for this "
@ -118,7 +122,9 @@ static NetExpr* elab_array_locator_noparens(Design* des, const LineInfo& loc,
if (method_name == "unique_index") {
result_type = &ivl_queue_unique_index_ret;
snprintf(sfunc, sizeof sfunc, "$ivl_queue_method$unique_index");
} else if (method_name == "sum" || method_name == "product") {
} else if (method_name == "sum" || method_name == "product" ||
method_name == "and" || method_name == "or" ||
method_name == "xor") {
result_type = element_type;
snprintf(sfunc, sizeof sfunc, "$ivl_queue_method$%s",
method_name.str());
@ -208,7 +214,9 @@ static NetExpr* elab_queue_locator_with_predicate(
index_net->local_flag(true);
NetExpr* pred = 0;
if (method_suffix == "sum" || method_suffix == "product") {
if (method_suffix == "sum" || method_suffix == "product" ||
method_suffix == "and" || method_suffix == "or" ||
method_suffix == "xor") {
pred = elab_and_eval(des, ws, with_expr, (int)ew, false, false,
ivl_type_base(element_type));
} else {
@ -242,6 +250,12 @@ static NetExpr* elab_queue_locator_with_predicate(
sfunc_name = lex_strings.make("$ivl_queue_method$sum_with");
} else if (method_suffix == "product") {
sfunc_name = lex_strings.make("$ivl_queue_method$product_with");
} else if (method_suffix == "and") {
sfunc_name = lex_strings.make("$ivl_queue_method$and_with");
} else if (method_suffix == "or") {
sfunc_name = lex_strings.make("$ivl_queue_method$or_with");
} else if (method_suffix == "xor") {
sfunc_name = lex_strings.make("$ivl_queue_method$xor_with");
} else {
ivl_assert(loc, 0);
}
@ -346,11 +360,41 @@ static NetExpr* elab_array_locator_method(Design* des, NetScope* scope,
static bool is_array_reduction_method(perm_string name)
{
return name == "sum" || name == "product";
return name == "sum" || name == "product" ||
name == "and" || name == "or" || name == "xor";
}
/*
* Elaborate sum()/product() on a queue or dynamic array expression.
* LRM 7.12.4: iterator index querying. In `with` predicates the iterator
* exposes `.index`. Icarus models that as a sibling local net named `index`
* in the synthetic `$ivl_qwith*` scope; map `item.index` to that net.
*/
static NetExpr* elab_array_iterator_index_query(const LineInfo& loc,
const symbol_search_results& sr)
{
if (!sr.net || sr.path_tail.size() != 1)
return 0;
if (sr.path_tail.front().name != "index" ||
!sr.path_tail.front().index.empty())
return 0;
if (sr.net->name() != "item")
return 0;
NetScope* sc = sr.net->scope();
if (!sc)
return 0;
perm_string sn = sc->basename();
if (!sn.str() || strncmp(sn.str(), "$ivl_qwith", 10) != 0)
return 0;
NetNet* idx = sc->find_signal(lex_strings.make("index"));
if (!idx)
return 0;
NetESignal* tmp = new NetESignal(idx);
tmp->set_line(loc);
return tmp;
}
/*
* Elaborate sum()/product()/and()/or()/xor() on a queue or dynamic array.
* Returns an integral value with the element type/width.
*/
static NetExpr* elab_array_reduction_method(Design* des, NetScope* scope,
@ -2009,7 +2053,9 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
return expr_width_;
}
if (method_name == "sum" || method_name == "product") {
if (method_name == "sum" || method_name == "product" ||
method_name == "and" || method_name == "or" ||
method_name == "xor") {
expr_type_ = darray->element_base_type();
expr_width_ = darray->element_width();
min_width_ = expr_width_;
@ -5254,6 +5300,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetNet *net = sr.net;
if (NetExpr* idxq = elab_array_iterator_index_query(*this, sr))
return idxq;
if (!sr.path_tail.empty()) {
if (net->struct_type()) {
return check_for_struct_members(this, des, scope, net,
@ -5370,6 +5419,24 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
fun->parm(0, arg);
return fun;
}
if (member_comp.name == "and" || member_comp.name == "or" ||
member_comp.name == "xor") {
if (!queue_method_element_is_integral_vec4(element_type)) {
cerr << get_fileline() << ": sorry: queue " << member_comp.name
<< "() for this element type is not yet supported." << endl;
des->errors += 1;
return 0;
}
char sfunc[64];
snprintf(sfunc, sizeof sfunc, "$ivl_queue_method$%s",
member_comp.name.str());
NetESFunc*fun = new NetESFunc(sfunc, element_type, 1);
fun->set_line(*this);
NetESignal*arg = new NetESignal(sr.net);
arg->set_line(*sr.net);
fun->parm(0, arg);
return fun;
}
if (member_comp.name == "min" || member_comp.name == "max") {
if (!queue_method_element_is_integral_vec4(element_type)) {
cerr << get_fileline() << ": sorry: queue " << member_comp.name
@ -5597,6 +5664,9 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
if (!check_interface_modport_access(this, des, sr, false))
return 0;
if (NetExpr* idxq = elab_array_iterator_index_query(*this, sr))
return idxq;
if (NEED_CONST & flags) {
cerr << get_fileline() << ": error: A reference to a net "
"or variable (`" << path_ << "') is not allowed in "
@ -5735,6 +5805,27 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
fun->parm(0, arg);
return fun;
}
if (member_comp.name == "product" ||
member_comp.name == "and" || member_comp.name == "or" ||
member_comp.name == "xor") {
if (!queue_method_element_is_integral_vec4(element_type)) {
cerr << get_fileline() << ": sorry: queue "
<< member_comp.name
<< "() for this element type is not yet supported."
<< endl;
des->errors += 1;
return 0;
}
char sfunc[64];
snprintf(sfunc, sizeof sfunc, "$ivl_queue_method$%s",
member_comp.name.str());
NetESFunc*fun = new NetESFunc(sfunc, element_type, 1);
fun->set_line(*this);
NetESignal*arg = new NetESignal(sr.net);
arg->set_line(*sr.net);
fun->parm(0, arg);
return fun;
}
if (member_comp.name == "min" || member_comp.name == "max") {
if (!queue_method_element_is_integral_vec4(element_type)) {
cerr << get_fileline() << ": sorry: queue " << member_comp.name
@ -5774,26 +5865,6 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
"dynamic array");
if (tmp) return tmp;
if (des->errors) return 0;
if (member_comp.name == "and") {
cerr << get_fileline() << ": sorry: 'and()' "
"array reduction method is not currently "
"implemented." << endl;
des->errors += 1;
return 0;
} else if (member_comp.name == "or") {
cerr << get_fileline() << ": sorry: 'or()' "
"array reduction method is not currently "
"implemented." << endl;
des->errors += 1;
return 0;
} else if (member_comp.name == "xor") {
cerr << get_fileline() << ": sorry: 'xor()' "
"array reduction method is not currently "
"implemented." << endl;
des->errors += 1;
return 0;
}
}
if ((sr.net->data_type() == IVL_VT_STRING) && !sr.path_tail.empty()) {

View File

@ -0,0 +1,38 @@
// Regression: dynamic array and()/or()/xor() reductions (LRM 7.12.3).
module top;
bit failed = 0;
`define CHK(cond) \
if (!(cond)) begin \
$display("FAILED line %0d", `__LINE__); \
failed = 1; \
end
byte b[];
int y;
initial begin
b = '{1, 3, 5, 7};
y = b.and;
`CHK(y === 1);
b = '{1, 2, 3, 4};
y = b.or;
`CHK(y === 7);
y = b.xor;
`CHK(y === 4);
b = new[0];
y = b.and;
`CHK(y === -1);
y = b.or;
`CHK(y === 0);
y = b.xor;
`CHK(y === 0);
if (!failed)
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,26 @@
// Regression: iterator index querying item.index in with() (LRM 7.12.4).
module top;
bit failed = 0;
`define CHK(cond) \
if (!(cond)) begin \
$display("FAILED line %0d", `__LINE__); \
failed = 1; \
end
int arr[] = '{0, 1, 3, 3};
int q[$];
initial begin
q = arr.find with (item == item.index);
`CHK(q.size == 3);
`CHK(q[0] == 0);
`CHK(q[1] == 1);
`CHK(q[2] == 3);
if (!failed)
$display("PASSED");
end
endmodule

View File

@ -314,7 +314,9 @@ sv_const_fail7 vvp_tests/sv_const_fail7.json
sv_const_fail8 vvp_tests/sv_const_fail8.json
sv_const_fail9 vvp_tests/sv_const_fail9.json
sv_darray_assign_op vvp_tests/sv_darray_assign_op.json
sv_darray_and_or_xor vvp_tests/sv_darray_and_or_xor.json
sv_darray_find_locators vvp_tests/sv_darray_find_locators.json
sv_darray_item_index vvp_tests/sv_darray_item_index.json
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

View File

@ -0,0 +1,9 @@
{
"type" : "normal",
"source" : "sv_darray_and_or_xor.v",
"iverilog-args" : [ "-g2005-sv" ],
"vlog95" : {
"__comment" : "SystemVerilog dynamic array and/or/xor reductions",
"type" : "CE"
}
}

View File

@ -0,0 +1,9 @@
{
"type" : "normal",
"source" : "sv_darray_item_index.v",
"iverilog-args" : [ "-g2005-sv" ],
"vlog95" : {
"__comment" : "SystemVerilog array iterator item.index querying",
"type" : "CE"
}
}

View File

@ -450,7 +450,10 @@ enum queue_locator_with_mode_e {
QUEUE_WITH_UNIQUE,
QUEUE_WITH_UNIQUE_INDEX,
QUEUE_WITH_SUM,
QUEUE_WITH_PRODUCT
QUEUE_WITH_PRODUCT,
QUEUE_WITH_AND,
QUEUE_WITH_OR,
QUEUE_WITH_XOR
};
static enum queue_locator_with_mode_e queue_locator_with_mode_from_name(
@ -480,6 +483,12 @@ static enum queue_locator_with_mode_e queue_locator_with_mode_from_name(
return QUEUE_WITH_SUM;
} else if (strcmp(name, "$ivl_queue_method$product_with") == 0) {
return QUEUE_WITH_PRODUCT;
} else if (strcmp(name, "$ivl_queue_method$and_with") == 0) {
return QUEUE_WITH_AND;
} else if (strcmp(name, "$ivl_queue_method$or_with") == 0) {
return QUEUE_WITH_OR;
} else if (strcmp(name, "$ivl_queue_method$xor_with") == 0) {
return QUEUE_WITH_XOR;
}
return (enum queue_locator_with_mode_e) -1;
}
@ -499,12 +508,19 @@ static int queue_with_multi(enum queue_locator_with_mode_e mode)
mode == QUEUE_WITH_UNIQUE ||
mode == QUEUE_WITH_UNIQUE_INDEX ||
mode == QUEUE_WITH_SUM ||
mode == QUEUE_WITH_PRODUCT;
mode == QUEUE_WITH_PRODUCT ||
mode == QUEUE_WITH_AND ||
mode == QUEUE_WITH_OR ||
mode == QUEUE_WITH_XOR;
}
static int queue_with_expr_value(enum queue_locator_with_mode_e mode)
{
return mode == QUEUE_WITH_SUM || mode == QUEUE_WITH_PRODUCT;
return mode == QUEUE_WITH_SUM ||
mode == QUEUE_WITH_PRODUCT ||
mode == QUEUE_WITH_AND ||
mode == QUEUE_WITH_OR ||
mode == QUEUE_WITH_XOR;
}
static int queue_with_as_index(enum queue_locator_with_mode_e mode)
@ -613,6 +629,27 @@ static void emit_queue_with_finish(enum queue_locator_with_mode_e mode,
}
return;
}
if (mode == QUEUE_WITH_AND) {
fprintf(vvp_out, " %%queue/and/obj/v %u;\n", elem_wid);
if (is_prop) {
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
}
return;
}
if (mode == QUEUE_WITH_OR) {
fprintf(vvp_out, " %%queue/or/obj/v %u;\n", elem_wid);
if (is_prop) {
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
}
return;
}
if (mode == QUEUE_WITH_XOR) {
fprintf(vvp_out, " %%queue/xor/obj/v %u;\n", elem_wid);
if (is_prop) {
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
}
return;
}
if (queue_with_multi(mode)) {
if (is_prop) {
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
@ -648,11 +685,13 @@ static int eval_queue_method_find_with(ivl_expr_t expr)
queue_locator_with_mode_from_name(name);
if ((int) mode < 0) return 1;
/* String unique/min/max/sum/product with() not implemented yet. */
/* String unique/min/max/sum/product/and/or/xor with() not implemented yet. */
if (is_string &&
(mode == QUEUE_WITH_UNIQUE || mode == QUEUE_WITH_UNIQUE_INDEX ||
mode == QUEUE_WITH_MIN || mode == QUEUE_WITH_MAX ||
mode == QUEUE_WITH_SUM || mode == QUEUE_WITH_PRODUCT)) {
mode == QUEUE_WITH_SUM || mode == QUEUE_WITH_PRODUCT ||
mode == QUEUE_WITH_AND || mode == QUEUE_WITH_OR ||
mode == QUEUE_WITH_XOR)) {
return 1;
}

View File

@ -1131,13 +1131,23 @@ static void draw_sfunc_vec4(ivl_expr_t expr)
}
if ((strcmp(ivl_expr_name(expr), "$ivl_queue_method$sum") == 0 ||
strcmp(ivl_expr_name(expr), "$ivl_queue_method$product") == 0) &&
strcmp(ivl_expr_name(expr), "$ivl_queue_method$product") == 0 ||
strcmp(ivl_expr_name(expr), "$ivl_queue_method$and") == 0 ||
strcmp(ivl_expr_name(expr), "$ivl_queue_method$or") == 0 ||
strcmp(ivl_expr_name(expr), "$ivl_queue_method$xor") == 0) &&
parm_count == 1) {
ivl_expr_t arg = ivl_expr_parm(expr, 0);
unsigned wid = ivl_expr_width(expr);
const char* op = strcmp(ivl_expr_name(expr), "$ivl_queue_method$product") == 0
? "product"
: "sum";
const char* name = ivl_expr_name(expr);
const char* op = "sum";
if (strcmp(name, "$ivl_queue_method$product") == 0)
op = "product";
else if (strcmp(name, "$ivl_queue_method$and") == 0)
op = "and";
else if (strcmp(name, "$ivl_queue_method$or") == 0)
op = "or";
else if (strcmp(name, "$ivl_queue_method$xor") == 0)
op = "xor";
if (ivl_expr_type(arg) == IVL_EX_PROPERTY) {
ivl_signal_t clas = ivl_expr_signal(arg);
unsigned pidx = ivl_expr_property_idx(arg);

View File

@ -258,10 +258,16 @@ extern bool of_QPOP_PROP_F_REAL(vthread_t thr, vvp_code_t code);
extern bool of_QPOP_PROP_F_STR(vthread_t thr, vvp_code_t code);
extern bool of_QPOP_PROP_F_V(vthread_t thr, vvp_code_t code);
extern bool of_PROP_QUEUE_SIZE(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_AND_OBJ_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_AND_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_AND_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_APPEND_WORD_STR(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_APPEND_WORD_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_NEW_EMPTY_STR(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_NEW_EMPTY_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_OR_OBJ_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_OR_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_OR_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_PRODUCT_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_PRODUCT_OBJ_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_PRODUCT_V(vthread_t thr, vvp_code_t code);
@ -271,6 +277,9 @@ extern bool of_QUEUE_SUM_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_SUM_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_WORD_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_WORD_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_XOR_OBJ_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_XOR_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_QUEUE_XOR_V(vthread_t thr, vvp_code_t code);
extern bool of_CMPIX_LTU(vthread_t thr, vvp_code_t code);
extern bool of_CMPIX_SLT0(vthread_t thr, vvp_code_t code);
extern bool of_PUSH_IX_VEC4(vthread_t thr, vvp_code_t code);

View File

@ -279,6 +279,9 @@ static const struct opcode_table_s opcode_table[] = {
{ "%qpop/prop/f/r", of_QPOP_PROP_F_REAL, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%qpop/prop/f/str", of_QPOP_PROP_F_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%qpop/prop/f/v", of_QPOP_PROP_F_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%queue/and/obj/v", of_QUEUE_AND_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
{ "%queue/and/prop/v", of_QUEUE_AND_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%queue/and/v", of_QUEUE_AND_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%queue/append_word/str", of_QUEUE_APPEND_WORD_STR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%queue/append_word/v", of_QUEUE_APPEND_WORD_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
{ "%queue/find/index/prop/v", of_QUEUE_FIND_INDEX_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
@ -301,6 +304,9 @@ static const struct opcode_table_s opcode_table[] = {
{ "%queue/min/v", of_QUEUE_MIN_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%queue/new_empty/str", of_QUEUE_NEW_EMPTY_STR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%queue/new_empty/v", of_QUEUE_NEW_EMPTY_V, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%queue/or/obj/v", of_QUEUE_OR_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
{ "%queue/or/prop/v", of_QUEUE_OR_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%queue/or/v", of_QUEUE_OR_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%queue/product/obj/v", of_QUEUE_PRODUCT_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
{ "%queue/product/prop/v", of_QUEUE_PRODUCT_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%queue/product/v", of_QUEUE_PRODUCT_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
@ -316,6 +322,9 @@ static const struct opcode_table_s opcode_table[] = {
{ "%queue/unique/v", of_QUEUE_UNIQUE_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%queue/word/prop/v", of_QUEUE_WORD_PROP_V, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
{ "%queue/word/v", of_QUEUE_WORD_V, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%queue/xor/obj/v", of_QUEUE_XOR_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
{ "%queue/xor/prop/v", of_QUEUE_XOR_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%queue/xor/v", of_QUEUE_XOR_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%release/wr", of_RELEASE_WR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },

View File

@ -6551,6 +6551,45 @@ static vvp_vector4_t queue_product_words_src(SRC* src, unsigned wid)
return acc;
}
template <class SRC>
static vvp_vector4_t queue_and_words_src(SRC* src, unsigned wid)
{
vvp_vector4_t acc(wid, BIT4_1);
if (!src) return acc;
for (size_t i = 0; i < src->get_size(); i += 1) {
vvp_vector4_t vi(wid);
src->get_word(i, vi);
acc &= vi;
}
return acc;
}
template <class SRC>
static vvp_vector4_t queue_or_words_src(SRC* src, unsigned wid)
{
vvp_vector4_t acc(wid, BIT4_0);
if (!src) return acc;
for (size_t i = 0; i < src->get_size(); i += 1) {
vvp_vector4_t vi(wid);
src->get_word(i, vi);
acc |= vi;
}
return acc;
}
template <class SRC>
static vvp_vector4_t queue_xor_words_src(SRC* src, unsigned wid)
{
vvp_vector4_t acc(wid, BIT4_0);
if (!src) return acc;
for (size_t i = 0; i < src->get_size(); i += 1) {
vvp_vector4_t vi(wid);
src->get_word(i, vi);
acc ^= vi;
}
return acc;
}
bool of_QUEUE_PRODUCT_V(vthread_t thr, vvp_code_t cp)
{
vvp_net_t* net = cp->net;
@ -6663,6 +6702,174 @@ bool of_QUEUE_SUM_OBJ_V(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_QUEUE_AND_V(vthread_t thr, vvp_code_t cp)
{
vvp_net_t* net = cp->net;
unsigned wid = cp->bit_idx[0];
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_net(thr, net, qsrc, dsrc);
vvp_vector4_t acc;
if (qsrc) acc = queue_and_words_src(qsrc, wid);
else if (dsrc) acc = queue_and_words_src(dsrc, wid);
else {
vvp_queue* src_q = get_queue_object<vvp_queue_vec4>(thr, net);
vvp_queue_vec4* src = dynamic_cast<vvp_queue_vec4*>(src_q);
acc = queue_and_words_src(src, wid);
}
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_AND_PROP_V(vthread_t thr, vvp_code_t cp)
{
size_t pid = cp->number;
unsigned wid = cp->bit_idx[0];
vvp_object_t& top = thr->peek_object();
vvp_cobject*cobj = top.peek<vvp_cobject>();
assert(cobj);
vvp_object_t qobj;
cobj->get_object(pid, qobj, 0);
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
vvp_vector4_t acc =
qsrc ? queue_and_words_src(qsrc, wid)
: queue_and_words_src(dsrc, wid);
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_AND_OBJ_V(vthread_t thr, vvp_code_t cp)
{
unsigned wid = cp->bit_idx[0];
vvp_object_t src_obj;
thr->pop_object(src_obj);
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_object(src_obj, qsrc, dsrc);
vvp_vector4_t acc =
qsrc ? queue_and_words_src(qsrc, wid)
: queue_and_words_src(dsrc, wid);
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_OR_V(vthread_t thr, vvp_code_t cp)
{
vvp_net_t* net = cp->net;
unsigned wid = cp->bit_idx[0];
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_net(thr, net, qsrc, dsrc);
vvp_vector4_t acc;
if (qsrc) acc = queue_or_words_src(qsrc, wid);
else if (dsrc) acc = queue_or_words_src(dsrc, wid);
else {
vvp_queue* src_q = get_queue_object<vvp_queue_vec4>(thr, net);
vvp_queue_vec4* src = dynamic_cast<vvp_queue_vec4*>(src_q);
acc = queue_or_words_src(src, wid);
}
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_OR_PROP_V(vthread_t thr, vvp_code_t cp)
{
size_t pid = cp->number;
unsigned wid = cp->bit_idx[0];
vvp_object_t& top = thr->peek_object();
vvp_cobject*cobj = top.peek<vvp_cobject>();
assert(cobj);
vvp_object_t qobj;
cobj->get_object(pid, qobj, 0);
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
vvp_vector4_t acc =
qsrc ? queue_or_words_src(qsrc, wid)
: queue_or_words_src(dsrc, wid);
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_OR_OBJ_V(vthread_t thr, vvp_code_t cp)
{
unsigned wid = cp->bit_idx[0];
vvp_object_t src_obj;
thr->pop_object(src_obj);
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_object(src_obj, qsrc, dsrc);
vvp_vector4_t acc =
qsrc ? queue_or_words_src(qsrc, wid)
: queue_or_words_src(dsrc, wid);
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_XOR_V(vthread_t thr, vvp_code_t cp)
{
vvp_net_t* net = cp->net;
unsigned wid = cp->bit_idx[0];
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_net(thr, net, qsrc, dsrc);
vvp_vector4_t acc;
if (qsrc) acc = queue_xor_words_src(qsrc, wid);
else if (dsrc) acc = queue_xor_words_src(dsrc, wid);
else {
vvp_queue* src_q = get_queue_object<vvp_queue_vec4>(thr, net);
vvp_queue_vec4* src = dynamic_cast<vvp_queue_vec4*>(src_q);
acc = queue_xor_words_src(src, wid);
}
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_XOR_PROP_V(vthread_t thr, vvp_code_t cp)
{
size_t pid = cp->number;
unsigned wid = cp->bit_idx[0];
vvp_object_t& top = thr->peek_object();
vvp_cobject*cobj = top.peek<vvp_cobject>();
assert(cobj);
vvp_object_t qobj;
cobj->get_object(pid, qobj, 0);
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
vvp_vector4_t acc =
qsrc ? queue_xor_words_src(qsrc, wid)
: queue_xor_words_src(dsrc, wid);
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_XOR_OBJ_V(vthread_t thr, vvp_code_t cp)
{
unsigned wid = cp->bit_idx[0];
vvp_object_t src_obj;
thr->pop_object(src_obj);
vvp_queue_vec4* qsrc = 0;
vvp_darray* dsrc = 0;
get_queue_or_darray_vec4_from_object(src_obj, qsrc, dsrc);
vvp_vector4_t acc =
qsrc ? queue_xor_words_src(qsrc, wid)
: queue_xor_words_src(dsrc, wid);
thr->push_vec4(acc);
return true;
}
bool of_QUEUE_FIND_V(vthread_t thr, vvp_code_t cp)
{
vvp_vector4_t cmp = thr->pop_vec4();