SV: sum() and product() reductions on queues/darrays
Add integral sum() and product() reductions, including expression forms, for queues, dynamic arrays, and class properties. Split from steveicarus/iverilog#1330 (part 05/6).
This commit is contained in:
parent
31d1850bc8
commit
e628e6c8c5
213
elab_expr.cc
213
elab_expr.cc
|
|
@ -105,8 +105,14 @@ static NetExpr* elab_queue_locator_with_predicate(
|
|||
index_net->set_line(loc);
|
||||
index_net->local_flag(true);
|
||||
|
||||
NetExpr* pred = elab_and_eval(des, ws, with_expr, 1, false, false,
|
||||
IVL_VT_BOOL);
|
||||
NetExpr* pred = 0;
|
||||
if (method_suffix == "sum" || method_suffix == "product") {
|
||||
pred = elab_and_eval(des, ws, with_expr, (int)ew, false, false,
|
||||
ivl_type_base(element_type));
|
||||
} else {
|
||||
pred = elab_and_eval(des, ws, with_expr, 1, false, false,
|
||||
IVL_VT_BOOL);
|
||||
}
|
||||
if (!pred) return 0;
|
||||
|
||||
perm_string sfunc_name;
|
||||
|
|
@ -130,6 +136,10 @@ static NetExpr* elab_queue_locator_with_predicate(
|
|||
sfunc_name = lex_strings.make("$ivl_queue_method$min_with");
|
||||
} else if (method_suffix == "max") {
|
||||
sfunc_name = lex_strings.make("$ivl_queue_method$max_with");
|
||||
} else if (method_suffix == "sum") {
|
||||
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 {
|
||||
ivl_assert(loc, 0);
|
||||
}
|
||||
|
|
@ -225,6 +235,58 @@ static NetExpr* elab_array_locator_method(Design* des, NetScope* scope,
|
|||
return sys_expr;
|
||||
}
|
||||
|
||||
static bool is_array_reduction_method(perm_string name)
|
||||
{
|
||||
return name == "sum" || name == "product";
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate sum()/product() on a queue or dynamic array expression.
|
||||
* Returns an integral value with the element type/width.
|
||||
*/
|
||||
static NetExpr* elab_array_reduction_method(Design* des, NetScope* scope,
|
||||
const LineInfo& loc,
|
||||
perm_string method_name,
|
||||
NetExpr* array_arg,
|
||||
ivl_type_t element_type,
|
||||
const vector<named_pexpr_t>& parms,
|
||||
PExpr* with_expr, const char* kind)
|
||||
{
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << loc.get_fileline() << ": sorry: " << kind << " "
|
||||
<< method_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", method_name.str());
|
||||
|
||||
if (with_expr) {
|
||||
if (!parms.empty()) {
|
||||
cerr << loc.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, loc, with_expr,
|
||||
array_arg, element_type,
|
||||
element_type, method_name);
|
||||
}
|
||||
|
||||
if (parms.size() != 0) {
|
||||
cerr << loc.get_fileline() << ": error: " << method_name
|
||||
<< "() method takes no arguments" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
NetESFunc*sys_expr = new NetESFunc(sfunc, element_type, 1);
|
||||
sys_expr->set_line(loc);
|
||||
sys_expr->parm(0, array_arg);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
bool type_is_vectorable(ivl_variable_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
|
|
@ -1830,6 +1892,21 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "sum") {
|
||||
expr_type_ = darray->element_base_type();
|
||||
expr_width_ = darray->element_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = darray->get_signed();
|
||||
return expr_width_;
|
||||
}
|
||||
if (method_name == "product") {
|
||||
expr_type_ = darray->element_base_type();
|
||||
expr_width_ = darray->element_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = darray->get_signed();
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "find" || method_name == "find_index" ||
|
||||
method_name == "unique" || method_name == "unique_index" ||
|
||||
method_name == "min" || method_name == "max") {
|
||||
|
|
@ -1887,6 +1964,21 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "sum") {
|
||||
expr_type_ = darray->element_base_type();
|
||||
expr_width_ = darray->element_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = darray->get_signed();
|
||||
return expr_width_;
|
||||
}
|
||||
if (method_name == "product") {
|
||||
expr_type_ = darray->element_base_type();
|
||||
expr_width_ = darray->element_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = darray->get_signed();
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "unique" || method_name == "unique_index" ||
|
||||
method_name == "min" || method_name == "max" ||
|
||||
method_name == "find" || method_name == "find_index") {
|
||||
|
|
@ -3838,8 +3930,15 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
static_cast<ivl_type_t>(queue),
|
||||
parms_, with_expr_, "queue");
|
||||
}
|
||||
if (is_array_reduction_method(method_name)) {
|
||||
return elab_array_reduction_method(des, scope, *this,
|
||||
method_name, prop, element_type,
|
||||
parms_, with_expr_, "queue");
|
||||
}
|
||||
}
|
||||
if (ptype && ptype->base_type() == IVL_VT_DARRAY) {
|
||||
if (ptype &&
|
||||
(ptype->base_type() == IVL_VT_DARRAY ||
|
||||
ptype->base_type() == IVL_VT_QUEUE)) {
|
||||
NetEProperty*prop = new NetEProperty(search_results.net, pidx, nullptr);
|
||||
prop->set_line(*this);
|
||||
perm_string method_name = search_results.path_tail.back().name;
|
||||
|
|
@ -3859,7 +3958,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
return elab_array_locator_method(des, scope, *this,
|
||||
method_name, prop, element_type,
|
||||
ptype, parms_, with_expr_,
|
||||
"dynamic array");
|
||||
"array");
|
||||
}
|
||||
if (is_array_reduction_method(method_name)) {
|
||||
return elab_array_reduction_method(des, scope, *this,
|
||||
method_name, prop, element_type,
|
||||
parms_, with_expr_, "array");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3968,6 +4072,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
queue_rtype, parms_, with_expr_,
|
||||
"dynamic array");
|
||||
}
|
||||
if (is_array_reduction_method(method_name)) {
|
||||
return elab_array_reduction_method(des, scope, *this, method_name,
|
||||
sub_expr, element_type,
|
||||
parms_, with_expr_,
|
||||
"dynamic array");
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Method " << method_name
|
||||
<< " is not a dynamic array method." << endl;
|
||||
|
|
@ -4027,6 +4137,11 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
static_cast<ivl_type_t>(queue),
|
||||
parms_, with_expr_, "queue");
|
||||
}
|
||||
if (is_array_reduction_method(method_name)) {
|
||||
return elab_array_reduction_method(des, scope, *this, method_name,
|
||||
sub_expr, element_type,
|
||||
parms_, with_expr_, "queue");
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Method " << method_name
|
||||
<< " is not a queue method." << endl;
|
||||
|
|
@ -5252,6 +5367,38 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
fun->parm(0, arg);
|
||||
return fun;
|
||||
}
|
||||
if (member_comp.name == "sum") {
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: queue sum() for this "
|
||||
<< "element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc(
|
||||
"$ivl_queue_method$sum",
|
||||
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 == "product") {
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: queue product() for this "
|
||||
<< "element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc(
|
||||
"$ivl_queue_method$product",
|
||||
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
|
||||
|
|
@ -5586,6 +5733,22 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
|
|||
fun->parm(0, arg);
|
||||
return fun;
|
||||
}
|
||||
if (member_comp.name == "sum") {
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: queue sum() for this "
|
||||
<< "element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc(
|
||||
"$ivl_queue_method$sum",
|
||||
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
|
||||
|
|
@ -5666,17 +5829,39 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
// FIXME: Check this is a real or integral type.
|
||||
} else if (member_comp.name == "sum") {
|
||||
cerr << get_fileline() << ": sorry: 'sum()' "
|
||||
"array reduction method is not currently "
|
||||
"implemented." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
const netdarray_t* dar_sum = sr.net->darray_type();
|
||||
ivl_assert(*this, dar_sum);
|
||||
ivl_type_t element_type = dar_sum->element_type();
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: dynamic array sum() for this "
|
||||
<< "element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc("$ivl_queue_method$sum",
|
||||
element_type, 1);
|
||||
fun->set_line(*this);
|
||||
NetESignal*arg = new NetESignal(sr.net);
|
||||
arg->set_line(*sr.net);
|
||||
fun->parm(0, arg);
|
||||
return fun;
|
||||
} else if (member_comp.name == "product") {
|
||||
cerr << get_fileline() << ": sorry: 'product()' "
|
||||
"array reduction method is not currently "
|
||||
"implemented." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
const netdarray_t* dar_sum = sr.net->darray_type();
|
||||
ivl_assert(*this, dar_sum);
|
||||
ivl_type_t element_type = dar_sum->element_type();
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: dynamic array product() for this "
|
||||
<< "element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc("$ivl_queue_method$product",
|
||||
element_type, 1);
|
||||
fun->set_line(*this);
|
||||
NetESignal*arg = new NetESignal(sr.net);
|
||||
arg->set_line(*sr.net);
|
||||
fun->parm(0, arg);
|
||||
return fun;
|
||||
// FIXME: Check this is only an integral type.
|
||||
} else if (member_comp.name == "and") {
|
||||
cerr << get_fileline() << ": sorry: 'and()' "
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ module test;
|
|||
`check(r.size, 1);
|
||||
`check(r[0], 6);
|
||||
|
||||
c.d = '{2, 3, 4};
|
||||
`check(c.d.product(), 24);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
// Regression: class queue 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 q[$];
|
||||
endclass
|
||||
|
||||
C c;
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
c = new;
|
||||
c.q = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
|
||||
|
||||
r = c.q.find() with (item > 3);
|
||||
`check(r.size, 5);
|
||||
`check(r[0], 4);
|
||||
`check(r[4], 6);
|
||||
|
||||
r = c.q.find_last_index() with (item < 3);
|
||||
`check(r.size, 1);
|
||||
`check(r[0], 8);
|
||||
|
||||
r = c.q.unique() with (item > 2);
|
||||
`check(r.size, 5);
|
||||
`check(r[0], 4);
|
||||
`check(r[4], 3);
|
||||
|
||||
r = c.q.unique_index() with (item > 2);
|
||||
`check(r.size, 6);
|
||||
`check(r[0], 0);
|
||||
`check(r[5], 7);
|
||||
|
||||
r = c.q.min();
|
||||
`check(r.size, 2);
|
||||
`check(r[0], 1);
|
||||
`check(r[1], 1);
|
||||
|
||||
r = c.q.max() with (item < 7);
|
||||
`check(r.size, 1);
|
||||
`check(r[0], 6);
|
||||
|
||||
r = c.q.max();
|
||||
`check(r.size, 2);
|
||||
`check(r[0], 7);
|
||||
|
||||
c.q = '{2, 3, 4};
|
||||
`check(c.q.product(), 24);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Regression: dynamic array product() reduction (integral).
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int a[];
|
||||
int p;
|
||||
|
||||
initial begin
|
||||
a = '{2, 3, 4};
|
||||
p = a.product();
|
||||
`CHK(p === 24);
|
||||
|
||||
a = '{-2, 3, 5};
|
||||
p = a.product();
|
||||
`CHK(p === -30);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Regression: dynamic array product() reduction with expression.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int a[];
|
||||
int p;
|
||||
|
||||
initial begin
|
||||
a = '{10, -3, 5};
|
||||
|
||||
p = a.product() with (item > 0);
|
||||
`CHK(p === 0);
|
||||
|
||||
p = a.product() with (item + 1);
|
||||
`CHK(p === -132);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Regression: dynamic array sum() reduction (integral).
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) \
|
||||
if (!(cond)) begin \
|
||||
$display("FAILED line %0d", `__LINE__); \
|
||||
failed = 1; \
|
||||
end
|
||||
|
||||
int a[];
|
||||
int s;
|
||||
|
||||
initial begin
|
||||
a = new[0];
|
||||
s = a.sum();
|
||||
`CHK(s === 0);
|
||||
|
||||
a = '{10, -3, 5};
|
||||
s = a.sum();
|
||||
`CHK(s === 12);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Regression: dynamic array sum() reduction with expression.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int a[];
|
||||
int s;
|
||||
|
||||
initial begin
|
||||
a = '{10, -3, 5};
|
||||
|
||||
s = a.sum() with (item > 0);
|
||||
`CHK(s === 2);
|
||||
|
||||
s = a.sum() with (item + 1);
|
||||
`CHK(s === 15);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Regression: queue product() reduction (integral).
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int q[$];
|
||||
int p;
|
||||
|
||||
initial begin
|
||||
q = '{2, 3, 4};
|
||||
p = q.product();
|
||||
`CHK(p === 24);
|
||||
|
||||
q = '{-2, 3, 5};
|
||||
p = q.product();
|
||||
`CHK(p === -30);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Regression: queue product() reduction with expression.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int q[$];
|
||||
int p;
|
||||
|
||||
initial begin
|
||||
q = '{4, 7, 2};
|
||||
|
||||
p = q.product() with (item > 3);
|
||||
`CHK(p === 0);
|
||||
|
||||
p = q.product() with (item + 1);
|
||||
`CHK(p === 120);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Regression: queue sum() reduction (integral).
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) \
|
||||
if (!(cond)) begin \
|
||||
$display("FAILED line %0d", `__LINE__); \
|
||||
failed = 1; \
|
||||
end
|
||||
|
||||
int q[$];
|
||||
int s;
|
||||
|
||||
initial begin
|
||||
q = '{};
|
||||
s = q.sum();
|
||||
`CHK(s === 0);
|
||||
|
||||
q = '{4, 7, 2};
|
||||
s = q.sum();
|
||||
`CHK(s === 13);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Regression: queue sum() reduction with expression.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int q[$];
|
||||
int s;
|
||||
|
||||
initial begin
|
||||
q = '{4, 7, 2, 5};
|
||||
|
||||
s = q.sum() with (item > 3);
|
||||
`CHK(s === 3);
|
||||
|
||||
s = q.sum() with (item * 2);
|
||||
`CHK(s === 36);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -291,6 +291,7 @@ sv_class_darray_prop_locators vvp_tests/sv_class_darray_prop_locators.json
|
|||
sv_class_prop_packed_dims vvp_tests/sv_class_prop_packed_dims.json
|
||||
sv_class_prop_type_name vvp_tests/sv_class_prop_type_name.json
|
||||
sv_class_prop_wildcard_type_name vvp_tests/sv_class_prop_wildcard_type_name.json
|
||||
sv_class_queue_prop_locators vvp_tests/sv_class_queue_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_real1.json
|
||||
|
|
@ -316,6 +317,10 @@ sv_darray_assign_op vvp_tests/sv_darray_assign_op.json
|
|||
sv_darray_find_locators vvp_tests/sv_darray_find_locators.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
|
||||
sv_darray_product_with vvp_tests/sv_darray_product_with.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
|
||||
sv_darray_unique_with vvp_tests/sv_darray_unique_with.json
|
||||
sv_declaration_after_null_statement_fail vvp_tests/sv_declaration_after_null_statement_fail.json
|
||||
|
|
@ -415,6 +420,10 @@ sv_queue_method_push_front_too_few_arg_fail vvp_tests/sv_queue_method_push_front
|
|||
sv_queue_method_push_front_too_many_arg_fail vvp_tests/sv_queue_method_push_front_too_many_arg_fail.json
|
||||
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_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
|
||||
sv_queue_unique_with vvp_tests/sv_queue_unique_with.json
|
||||
sv_soft_packed_union vvp_tests/sv_soft_packed_union.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_class_queue_prop_locators.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog class queue property locator methods",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_product.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array product() reduction",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_product_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array product() with expression",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_sum.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array sum() reduction",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_sum_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array sum() with expression",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_product.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue product() reduction",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_product_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue product() with expression",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_sum.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue sum() reduction",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_sum_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue sum() with expression",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -173,33 +173,59 @@ static int eval_darray_new(ivl_expr_t ex)
|
|||
return errors;
|
||||
}
|
||||
|
||||
/* Build a dynamic-array object value from an array pattern expression. */
|
||||
static int eval_darray_pattern_object(ivl_expr_t ex)
|
||||
/* Build a queue/dynamic-array object value from an array pattern expression. */
|
||||
static int eval_array_pattern_object(ivl_expr_t ex)
|
||||
{
|
||||
int errors = 0;
|
||||
ivl_type_t net_type = ivl_expr_net_type(ex);
|
||||
if (!net_type || ivl_type_base(net_type) != IVL_VT_DARRAY) return 1;
|
||||
if (!net_type) return 1;
|
||||
ivl_variable_type_t base_type = ivl_type_base(net_type);
|
||||
if (base_type != IVL_VT_DARRAY && base_type != IVL_VT_QUEUE) return 1;
|
||||
|
||||
ivl_type_t element_type = ivl_type_element(net_type);
|
||||
if (!element_type) return 1;
|
||||
|
||||
unsigned size_reg = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", size_reg, ivl_expr_parms(ex));
|
||||
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||
darray_new(element_type, size_reg);
|
||||
unsigned max_elems = ivl_expr_parms(ex);
|
||||
if (base_type == IVL_VT_QUEUE) {
|
||||
unsigned max_size = ivl_type_queue_max(net_type);
|
||||
if (max_size != 0 && max_elems > max_size) {
|
||||
fprintf(stderr, "%s:%u: Warning: Array pattern assignment has more "
|
||||
"elements (%u) than bounded queue supports (%u).\n"
|
||||
" Only using first %u elements.\n",
|
||||
ivl_expr_file(ex), ivl_expr_lineno(ex), max_elems, max_size, max_size);
|
||||
max_elems = max_size;
|
||||
}
|
||||
fprintf(vvp_out, " %%queue/new_empty/v;\n");
|
||||
} else {
|
||||
unsigned size_reg = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", size_reg, max_elems);
|
||||
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||
darray_new(element_type, size_reg);
|
||||
}
|
||||
|
||||
switch (ivl_type_base(element_type)) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
for (unsigned idx = 0; idx < ivl_expr_parms(ex); idx += 1) {
|
||||
for (unsigned idx = 0; idx < max_elems; idx += 1) {
|
||||
draw_eval_vec4(ivl_expr_parm(ex, idx));
|
||||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
|
||||
fprintf(vvp_out, " %%pop/vec4 1;\n");
|
||||
if (base_type == IVL_VT_QUEUE) {
|
||||
fprintf(vvp_out, " %%queue/append_word/v %u;\n",
|
||||
ivl_type_packed_width(element_type));
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
|
||||
fprintf(vvp_out, " %%pop/vec4 1;\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
for (unsigned idx = 0; idx < ivl_expr_parms(ex); idx += 1) {
|
||||
for (unsigned idx = 0; idx < max_elems; idx += 1) {
|
||||
if (base_type == IVL_VT_QUEUE) {
|
||||
fprintf(vvp_out, "; ERROR: eval_array_pattern_object: queue real "
|
||||
"element type not implemented\n");
|
||||
errors += 1;
|
||||
break;
|
||||
}
|
||||
draw_eval_real(ivl_expr_parm(ex, idx));
|
||||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%set/dar/obj/real 3;\n");
|
||||
|
|
@ -207,7 +233,13 @@ static int eval_darray_pattern_object(ivl_expr_t ex)
|
|||
}
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
for (unsigned idx = 0; idx < ivl_expr_parms(ex); idx += 1) {
|
||||
for (unsigned idx = 0; idx < max_elems; idx += 1) {
|
||||
if (base_type == IVL_VT_QUEUE) {
|
||||
fprintf(vvp_out, "; ERROR: eval_array_pattern_object: queue string "
|
||||
"element type not implemented\n");
|
||||
errors += 1;
|
||||
break;
|
||||
}
|
||||
draw_eval_string(ivl_expr_parm(ex, idx));
|
||||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%set/dar/obj/str 3;\n");
|
||||
|
|
@ -215,7 +247,7 @@ static int eval_darray_pattern_object(ivl_expr_t ex)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, "; ERROR: eval_darray_pattern_object: unsupported "
|
||||
fprintf(vvp_out, "; ERROR: eval_array_pattern_object: unsupported "
|
||||
"element type %d\n", ivl_type_base(element_type));
|
||||
errors += 1;
|
||||
break;
|
||||
|
|
@ -397,7 +429,9 @@ enum queue_locator_with_mode_e {
|
|||
QUEUE_WITH_MIN,
|
||||
QUEUE_WITH_MAX,
|
||||
QUEUE_WITH_UNIQUE,
|
||||
QUEUE_WITH_UNIQUE_INDEX
|
||||
QUEUE_WITH_UNIQUE_INDEX,
|
||||
QUEUE_WITH_SUM,
|
||||
QUEUE_WITH_PRODUCT
|
||||
};
|
||||
|
||||
static enum queue_locator_with_mode_e queue_locator_with_mode_from_name(
|
||||
|
|
@ -423,6 +457,10 @@ static enum queue_locator_with_mode_e queue_locator_with_mode_from_name(
|
|||
return QUEUE_WITH_UNIQUE;
|
||||
} else if (strcmp(name, "$ivl_queue_method$unique_index_with") == 0) {
|
||||
return QUEUE_WITH_UNIQUE_INDEX;
|
||||
} else if (strcmp(name, "$ivl_queue_method$sum_with") == 0) {
|
||||
return QUEUE_WITH_SUM;
|
||||
} else if (strcmp(name, "$ivl_queue_method$product_with") == 0) {
|
||||
return QUEUE_WITH_PRODUCT;
|
||||
}
|
||||
return (enum queue_locator_with_mode_e) -1;
|
||||
}
|
||||
|
|
@ -440,7 +478,14 @@ static int queue_with_multi(enum queue_locator_with_mode_e mode)
|
|||
mode == QUEUE_WITH_MIN ||
|
||||
mode == QUEUE_WITH_MAX ||
|
||||
mode == QUEUE_WITH_UNIQUE ||
|
||||
mode == QUEUE_WITH_UNIQUE_INDEX;
|
||||
mode == QUEUE_WITH_UNIQUE_INDEX ||
|
||||
mode == QUEUE_WITH_SUM ||
|
||||
mode == QUEUE_WITH_PRODUCT;
|
||||
}
|
||||
|
||||
static int queue_with_expr_value(enum queue_locator_with_mode_e mode)
|
||||
{
|
||||
return mode == QUEUE_WITH_SUM || mode == QUEUE_WITH_PRODUCT;
|
||||
}
|
||||
|
||||
static int queue_with_as_index(enum queue_locator_with_mode_e mode)
|
||||
|
|
@ -527,6 +572,20 @@ static void emit_queue_with_finish(enum queue_locator_with_mode_e mode,
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (mode == QUEUE_WITH_SUM) {
|
||||
fprintf(vvp_out, " %%queue/sum/obj/v %u;\n", elem_wid);
|
||||
if (is_prop) {
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mode == QUEUE_WITH_PRODUCT) {
|
||||
fprintf(vvp_out, " %%queue/product/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");
|
||||
|
|
@ -608,11 +667,16 @@ static int eval_queue_method_find_with(ivl_expr_t expr)
|
|||
fprintf(vvp_out, " %%push/ix/vec4 %d, 32, 1;\n", i_reg);
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, 32;\n", idx_sig);
|
||||
|
||||
int pf = draw_eval_condition(pred);
|
||||
fprintf(vvp_out, " %%jmp/0 T_%u.%u, %d;\n", thread_count, lab_nom, pf);
|
||||
clr_flag(pf);
|
||||
|
||||
emit_queue_with_on_match(mode, item_sig, i_reg, elem_wid, match_lab);
|
||||
if (queue_with_expr_value(mode)) {
|
||||
draw_eval_vec4(pred);
|
||||
fprintf(vvp_out, " %%queue/append_word/v %u;\n", elem_wid);
|
||||
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_nom);
|
||||
} else {
|
||||
int pf = draw_eval_condition(pred);
|
||||
fprintf(vvp_out, " %%jmp/0 T_%u.%u, %d;\n", thread_count, lab_nom, pf);
|
||||
clr_flag(pf);
|
||||
emit_queue_with_on_match(mode, item_sig, i_reg, elem_wid, match_lab);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "T_%u.%u ; nomatch\n", thread_count, lab_nom);
|
||||
emit_queue_with_step_index(reverse, i_reg, lab_top);
|
||||
|
|
@ -720,7 +784,7 @@ int draw_eval_object(ivl_expr_t ex)
|
|||
return eval_object_ufunc(ex);
|
||||
|
||||
case IVL_EX_ARRAY_PATTERN:
|
||||
return eval_darray_pattern_object(ex);
|
||||
return eval_array_pattern_object(ex);
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
/* Queue locator `with` may report IVL_VT_DARRAY in ivl; handle by name. */
|
||||
|
|
|
|||
|
|
@ -1130,6 +1130,28 @@ 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) &&
|
||||
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";
|
||||
if (ivl_expr_type(arg) == IVL_EX_PROPERTY) {
|
||||
ivl_signal_t clas = ivl_expr_signal(arg);
|
||||
unsigned pidx = ivl_expr_property_idx(arg);
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", clas);
|
||||
fprintf(vvp_out, " %%queue/%s/prop/v %u, %u;\n", op, pidx, wid);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
return;
|
||||
}
|
||||
assert(ivl_expr_type(arg) == IVL_EX_SIGNAL);
|
||||
fprintf(vvp_out, " %%queue/%s/v v%p_0, %u;\n",
|
||||
op, ivl_expr_signal(arg), wid);
|
||||
return;
|
||||
}
|
||||
|
||||
draw_vpi_func_call(expr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -252,7 +252,13 @@ 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_APPEND_WORD_V(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_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);
|
||||
extern bool of_QUEUE_SIZE_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_SUM_OBJ_V(vthread_t thr, vvp_code_t code);
|
||||
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_CMPIX_LTU(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ unsigned compile_errors = 0;
|
|||
* by mnemonic string: compile_code() uses bsearch() on this array.
|
||||
* If the order is wrong, lookup fails and the assembler reports
|
||||
* "Invalid opcode" for otherwise valid instructions (e.g. class
|
||||
* property queue ops must sort among all %delete/*, %qpop/*, %store/*
|
||||
* property queue ops must sort among all %delete*, %qpop*, %store*
|
||||
* names, not grouped by feature).
|
||||
* The opcode_compare function is a helper for that lookup.
|
||||
*/
|
||||
|
|
@ -299,7 +299,13 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%queue/min/prop/v", of_QUEUE_MIN_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/min/v", of_QUEUE_MIN_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/new_empty/v", of_QUEUE_NEW_EMPTY_V, 0, {OA_NONE, OA_NONE, 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} },
|
||||
{ "%queue/size/v", of_QUEUE_SIZE_V, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%queue/sum/obj/v", of_QUEUE_SUM_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
||||
{ "%queue/sum/prop/v", of_QUEUE_SUM_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/sum/v", of_QUEUE_SUM_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/unique/index/obj/v", of_QUEUE_UNIQUE_INDEX_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
||||
{ "%queue/unique/index/prop/v", of_QUEUE_UNIQUE_INDEX_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/unique/index/v", of_QUEUE_UNIQUE_INDEX_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
|
|
|
|||
139
vvp/vthread.cc
139
vvp/vthread.cc
|
|
@ -6326,6 +6326,145 @@ static vvp_queue_vec4* queue_run_min_max_src(SRC* src, unsigned wid, bool want_m
|
|||
return dst;
|
||||
}
|
||||
|
||||
/* sum() reduction returns the scalar sum (Verilog-style addition per word). */
|
||||
template <class SRC>
|
||||
static vvp_vector4_t queue_sum_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.add(vi);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
template <class SRC>
|
||||
static vvp_vector4_t queue_product_words_src(SRC* src, unsigned wid)
|
||||
{
|
||||
vvp_vector4_t acc = queue_unique_ulong_to_vec4(1UL, wid);
|
||||
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.mul(vi);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
bool of_QUEUE_PRODUCT_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 prod;
|
||||
if (qsrc) prod = queue_product_words_src(qsrc, wid);
|
||||
else if (dsrc) prod = queue_product_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);
|
||||
prod = queue_product_words_src(src, wid);
|
||||
}
|
||||
thr->push_vec4(prod);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_PRODUCT_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 prod =
|
||||
qsrc ? queue_product_words_src(qsrc, wid)
|
||||
: queue_product_words_src(dsrc, wid);
|
||||
thr->push_vec4(prod);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_PRODUCT_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 prod =
|
||||
qsrc ? queue_product_words_src(qsrc, wid)
|
||||
: queue_product_words_src(dsrc, wid);
|
||||
thr->push_vec4(prod);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_SUM_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 sum;
|
||||
if (qsrc) sum = queue_sum_words_src(qsrc, wid);
|
||||
else if (dsrc) sum = queue_sum_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);
|
||||
sum = queue_sum_words_src(src, wid);
|
||||
}
|
||||
thr->push_vec4(sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_SUM_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 sum =
|
||||
qsrc ? queue_sum_words_src(qsrc, wid)
|
||||
: queue_sum_words_src(dsrc, wid);
|
||||
thr->push_vec4(sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_SUM_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 sum =
|
||||
qsrc ? queue_sum_words_src(qsrc, wid)
|
||||
: queue_sum_words_src(dsrc, wid);
|
||||
thr->push_vec4(sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_FIND_V(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_vector4_t cmp = thr->pop_vec4();
|
||||
|
|
|
|||
Loading…
Reference in New Issue