mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-09-07 11:51:38 +02:00
SV: locator methods on class queue/darray properties
Extend locator methods to class queue and dynamic-array properties, including min/max, unique/min/max with-predicates, and VVP array-pattern object handling. Built on the #1419 locator helpers. Split from steveicarus/iverilog#1330 (part 04/6).
This commit is contained in:
+71
-22
@@ -122,6 +122,14 @@ static NetExpr* elab_queue_locator_with_predicate(
|
||||
sfunc_name = lex_strings.make("$ivl_queue_method$find_last_with");
|
||||
} else if (method_suffix == "find_last_index") {
|
||||
sfunc_name = lex_strings.make("$ivl_queue_method$find_last_index_with");
|
||||
} else if (method_suffix == "unique") {
|
||||
sfunc_name = lex_strings.make("$ivl_queue_method$unique_with");
|
||||
} else if (method_suffix == "unique_index") {
|
||||
sfunc_name = lex_strings.make("$ivl_queue_method$unique_index_with");
|
||||
} else if (method_suffix == "min") {
|
||||
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 {
|
||||
ivl_assert(loc, 0);
|
||||
}
|
||||
@@ -140,7 +148,8 @@ static bool is_array_locator_method(perm_string name)
|
||||
return name == "find" || name == "find_index" ||
|
||||
name == "find_first" || name == "find_first_index" ||
|
||||
name == "find_last" || name == "find_last_index" ||
|
||||
name == "unique" || name == "unique_index";
|
||||
name == "unique" || name == "unique_index" ||
|
||||
name == "min" || name == "max";
|
||||
}
|
||||
|
||||
static bool locator_returns_indices(perm_string name)
|
||||
@@ -178,17 +187,8 @@ static NetExpr* elab_array_locator_method(Design* des, NetScope* scope,
|
||||
char sfunc[64];
|
||||
snprintf(sfunc, sizeof sfunc, "$ivl_queue_method$%s", method_name.str());
|
||||
|
||||
if (method_name == "unique" || method_name == "unique_index") {
|
||||
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, result_type, 1);
|
||||
sys_expr->set_line(loc);
|
||||
sys_expr->parm(0, array_arg);
|
||||
return sys_expr;
|
||||
}
|
||||
bool no_arg = method_name == "unique" || method_name == "unique_index" ||
|
||||
method_name == "min" || method_name == "max";
|
||||
|
||||
if (with_expr) {
|
||||
if (!parms.empty()) {
|
||||
@@ -203,6 +203,18 @@ static NetExpr* elab_array_locator_method(Design* des, NetScope* scope,
|
||||
result_type, method_name);
|
||||
}
|
||||
|
||||
if (no_arg) {
|
||||
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, result_type, 1);
|
||||
sys_expr->set_line(loc);
|
||||
sys_expr->parm(0, array_arg);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
NetExpr* cmp = elab_queue_locator_cmp_arg(des, scope, loc, parms,
|
||||
element_type);
|
||||
if (!cmp) return 0;
|
||||
@@ -1818,7 +1830,9 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "find" || method_name == "find_index") {
|
||||
if (method_name == "find" || method_name == "find_index" ||
|
||||
method_name == "unique" || method_name == "unique_index" ||
|
||||
method_name == "min" || method_name == "max") {
|
||||
expr_type_ = IVL_VT_QUEUE;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
@@ -1873,15 +1887,9 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "unique" || method_name == "unique_index") {
|
||||
expr_type_ = IVL_VT_QUEUE;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
signed_flag_ = false;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "find" || method_name == "find_index") {
|
||||
if (method_name == "unique" || method_name == "unique_index" ||
|
||||
method_name == "min" || method_name == "max" ||
|
||||
method_name == "find" || method_name == "find_index") {
|
||||
expr_type_ = IVL_VT_QUEUE;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
@@ -3835,6 +3843,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
NetEProperty*prop = new NetEProperty(search_results.net, pidx, nullptr);
|
||||
prop->set_line(*this);
|
||||
perm_string method_name = search_results.path_tail.back().name;
|
||||
ivl_type_t element_type = ivl_type_element(ptype);
|
||||
if (method_name == "size") {
|
||||
if (parms_.size() != 0) {
|
||||
cerr << get_fileline() << ": error: size() method "
|
||||
@@ -3846,6 +3855,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
sys_expr->parm(0, prop);
|
||||
return sys_expr;
|
||||
}
|
||||
if (is_array_locator_method(method_name)) {
|
||||
return elab_array_locator_method(des, scope, *this,
|
||||
method_name, prop, element_type,
|
||||
ptype, parms_, with_expr_,
|
||||
"dynamic array");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5237,6 +5252,23 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
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
|
||||
<< "() for this element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc(
|
||||
member_comp.name == "min" ? "$ivl_queue_method$min"
|
||||
: "$ivl_queue_method$max",
|
||||
static_cast<ivl_type_t>(queue), 1);
|
||||
fun->set_line(*this);
|
||||
NetESignal*arg = new NetESignal(sr.net);
|
||||
arg->set_line(*sr.net);
|
||||
fun->parm(0, arg);
|
||||
return fun;
|
||||
}
|
||||
cerr << get_fileline() << ": error: Unknown or unsupported queue "
|
||||
<< "member `" << member_comp.name << "'." << endl;
|
||||
des->errors += 1;
|
||||
@@ -5554,6 +5586,23 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
|
||||
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
|
||||
<< "() for this element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*fun = new NetESFunc(
|
||||
member_comp.name == "min" ? "$ivl_queue_method$min"
|
||||
: "$ivl_queue_method$max",
|
||||
static_cast<ivl_type_t>(queue), 1);
|
||||
fun->set_line(*this);
|
||||
NetESignal*arg = new NetESignal(sr.net);
|
||||
arg->set_line(*sr.net);
|
||||
fun->parm(0, arg);
|
||||
return fun;
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic array (not queue) — array location / reduction methods.
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// Regression: class dynamic-array property locator methods.
|
||||
|
||||
module test;
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
`define check(val, exp) do if ((val) !== (exp)) begin $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); failed = 1'b1; end while(0)
|
||||
|
||||
class C;
|
||||
int d[];
|
||||
endclass
|
||||
|
||||
C c;
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
c = new;
|
||||
c.d = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
|
||||
|
||||
r = c.d.find() with (item > 3);
|
||||
`check(r.size, 5);
|
||||
`check(r[0], 4);
|
||||
`check(r[4], 6);
|
||||
|
||||
r = c.d.find_first() with (item > 6);
|
||||
`check(r.size, 1);
|
||||
`check(r[0], 7);
|
||||
|
||||
r = c.d.find_last_index() with (item < 3);
|
||||
`check(r.size, 1);
|
||||
`check(r[0], 8);
|
||||
|
||||
r = c.d.unique();
|
||||
`check(r.size, 7);
|
||||
`check(r[0], 4);
|
||||
|
||||
r = c.d.unique_index();
|
||||
`check(r.size, 7);
|
||||
`check(r[0], 0);
|
||||
|
||||
r = c.d.unique() with (item > 2);
|
||||
`check(r.size, 5);
|
||||
`check(r[0], 4);
|
||||
`check(r[4], 3);
|
||||
|
||||
r = c.d.unique_index() with (item > 2);
|
||||
`check(r.size, 6);
|
||||
`check(r[0], 0);
|
||||
`check(r[5], 7);
|
||||
|
||||
r = c.d.min();
|
||||
`check(r.size, 2);
|
||||
`check(r[0], 1);
|
||||
`check(r[1], 1);
|
||||
|
||||
r = c.d.max() with (item < 7);
|
||||
`check(r.size, 1);
|
||||
`check(r[0], 6);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,36 @@
|
||||
// Regression: dynamic array min() and max() locator methods return queues.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) \
|
||||
if (!(cond)) begin \
|
||||
$display("FAILED line %0d", `__LINE__); \
|
||||
failed = 1; \
|
||||
end
|
||||
|
||||
int a[] = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
|
||||
int empty[];
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
r = a.min();
|
||||
`CHK(r.size == 2);
|
||||
`CHK(r[0] == 1);
|
||||
`CHK(r[1] == 1);
|
||||
|
||||
r = a.max();
|
||||
`CHK(r.size == 2);
|
||||
`CHK(r[0] == 7);
|
||||
`CHK(r[1] == 7);
|
||||
|
||||
r = empty.min();
|
||||
`CHK(r.size == 0);
|
||||
r = empty.max();
|
||||
`CHK(r.size == 0);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,30 @@
|
||||
// Regression: dynamic array min/max with(predicate) locator methods.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int a[] = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
r = a.min() with (item > 3);
|
||||
`CHK(r.size == 1);
|
||||
`CHK(r[0] == 4);
|
||||
|
||||
r = a.max() with (item < 7);
|
||||
`CHK(r.size == 1);
|
||||
`CHK(r[0] == 6);
|
||||
|
||||
r = a.min() with (item > 99);
|
||||
`CHK(r.size == 0);
|
||||
|
||||
r = a.max() with (item > 99);
|
||||
`CHK(r.size == 0);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,29 @@
|
||||
// Regression: dynamic array unique() and unique_index().
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int a[] = '{1, 2, 1, 3, 2};
|
||||
int u[$];
|
||||
int ix[$];
|
||||
|
||||
initial begin
|
||||
u = a.unique();
|
||||
`CHK(u.size == 3);
|
||||
`CHK(u[0] == 1);
|
||||
`CHK(u[1] == 2);
|
||||
`CHK(u[2] == 3);
|
||||
|
||||
ix = a.unique_index();
|
||||
`CHK(ix.size == 3);
|
||||
`CHK(ix[0] == 0);
|
||||
`CHK(ix[1] == 1);
|
||||
`CHK(ix[2] == 3);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,33 @@
|
||||
// Regression: dynamic array unique()/unique_index() with predicate.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int a[] = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
r = a.unique() with (item > 2);
|
||||
`CHK(r.size == 5);
|
||||
`CHK(r[0] == 4);
|
||||
`CHK(r[1] == 7);
|
||||
`CHK(r[2] == 5);
|
||||
`CHK(r[3] == 6);
|
||||
`CHK(r[4] == 3);
|
||||
|
||||
r = a.unique_index() with (item > 2);
|
||||
`CHK(r.size == 6);
|
||||
`CHK(r[0] == 0);
|
||||
`CHK(r[1] == 1);
|
||||
`CHK(r[2] == 3);
|
||||
`CHK(r[3] == 4);
|
||||
`CHK(r[4] == 6);
|
||||
`CHK(r[5] == 7);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,47 @@
|
||||
// Regression: queue min() and max() locator methods return queues.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) \
|
||||
if (!(cond)) begin \
|
||||
$display("FAILED line %0d", `__LINE__); \
|
||||
failed = 1; \
|
||||
end
|
||||
|
||||
int q[$];
|
||||
int e[$];
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
q.delete();
|
||||
q.push_back(4);
|
||||
q.push_back(7);
|
||||
q.push_back(2);
|
||||
q.push_back(5);
|
||||
q.push_back(7);
|
||||
q.push_back(1);
|
||||
q.push_back(6);
|
||||
q.push_back(3);
|
||||
q.push_back(1);
|
||||
|
||||
r = q.min();
|
||||
`CHK(r.size == 2);
|
||||
`CHK(r[0] == 1);
|
||||
`CHK(r[1] == 1);
|
||||
|
||||
r = q.max();
|
||||
`CHK(r.size == 2);
|
||||
`CHK(r[0] == 7);
|
||||
`CHK(r[1] == 7);
|
||||
|
||||
r = e.min();
|
||||
`CHK(r.size == 0);
|
||||
r = e.max();
|
||||
`CHK(r.size == 0);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,41 @@
|
||||
// Regression: queue min/max with(predicate) locator methods.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int q[$];
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
q.delete();
|
||||
q.push_back(4);
|
||||
q.push_back(7);
|
||||
q.push_back(2);
|
||||
q.push_back(5);
|
||||
q.push_back(7);
|
||||
q.push_back(1);
|
||||
q.push_back(6);
|
||||
q.push_back(3);
|
||||
q.push_back(1);
|
||||
|
||||
r = q.min() with (item > 3);
|
||||
`CHK(r.size == 1);
|
||||
`CHK(r[0] == 4);
|
||||
|
||||
r = q.max() with (item < 7);
|
||||
`CHK(r.size == 1);
|
||||
`CHK(r[0] == 6);
|
||||
|
||||
r = q.min() with (item > 99);
|
||||
`CHK(r.size == 0);
|
||||
|
||||
r = q.max() with (item > 99);
|
||||
`CHK(r.size == 0);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,35 @@
|
||||
// Regression: queue unique()/unique_index() with predicate.
|
||||
|
||||
module top;
|
||||
|
||||
bit failed = 0;
|
||||
|
||||
`define CHK(cond) if (!(cond)) begin $display("FAILED line %0d", `__LINE__); failed = 1; end
|
||||
|
||||
int q[$];
|
||||
int r[$];
|
||||
|
||||
initial begin
|
||||
q = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
|
||||
|
||||
r = q.unique() with (item > 2);
|
||||
`CHK(r.size == 5);
|
||||
`CHK(r[0] == 4);
|
||||
`CHK(r[1] == 7);
|
||||
`CHK(r[2] == 5);
|
||||
`CHK(r[3] == 6);
|
||||
`CHK(r[4] == 3);
|
||||
|
||||
r = q.unique_index() with (item > 2);
|
||||
`CHK(r.size == 6);
|
||||
`CHK(r[0] == 0);
|
||||
`CHK(r[1] == 1);
|
||||
`CHK(r[2] == 3);
|
||||
`CHK(r[3] == 4);
|
||||
`CHK(r[4] == 6);
|
||||
`CHK(r[5] == 7);
|
||||
|
||||
if (!failed)
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
@@ -283,6 +283,7 @@ sv_class_prop_assign_op1 vvp_tests/sv_class_prop_assign_op1.json
|
||||
sv_class_prop_assign_op2 vvp_tests/sv_class_prop_assign_op2.json
|
||||
sv_class_prop_class_name vvp_tests/sv_class_prop_class_name.json
|
||||
sv_class_prop_logic vvp_tests/sv_class_prop_logic.json
|
||||
sv_class_darray_prop_locators vvp_tests/sv_class_darray_prop_locators.json
|
||||
sv_class_prop_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
|
||||
@@ -309,6 +310,10 @@ 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_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_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
|
||||
sv_default_port_value1 vvp_tests/sv_default_port_value1.json
|
||||
sv_default_port_value2 vvp_tests/sv_default_port_value2.json
|
||||
@@ -401,7 +406,10 @@ sv_queue_method_push_back_too_few_arg_fail vvp_tests/sv_queue_method_push_back_t
|
||||
sv_queue_method_push_back_too_many_arg_fail vvp_tests/sv_queue_method_push_back_too_many_arg_fail.json
|
||||
sv_queue_method_push_front_too_few_arg_fail vvp_tests/sv_queue_method_push_front_too_few_arg_fail.json
|
||||
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_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
|
||||
sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json
|
||||
sv_string_method_substr_too_few_arg_fail vvp_tests/sv_string_method_substr_too_few_arg_fail.json
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_class_darray_prop_locators.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "Classes/dynamic arrays are not supported",
|
||||
"type" : "CE",
|
||||
"iverilog-args" : [ "-pallowsigned=1" ]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_min_max.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array min/max locator methods",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_min_max_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array min/max with predicate",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_unique.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog dynamic array unique methods",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_unique_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog darray unique with predicate",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_min_max.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue min/max locator methods",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_min_max_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue min/max with predicate",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_unique_with.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue unique with predicate",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
+115
-13
@@ -173,6 +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)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
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");
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
for (unsigned idx = 0; idx < ivl_expr_parms(ex); idx += 1) {
|
||||
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");
|
||||
fprintf(vvp_out, " %%pop/real 1;\n");
|
||||
}
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
for (unsigned idx = 0; idx < ivl_expr_parms(ex); idx += 1) {
|
||||
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");
|
||||
fprintf(vvp_out, " %%pop/str 1;\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, "; ERROR: eval_darray_pattern_object: unsupported "
|
||||
"element type %d\n", ivl_type_base(element_type));
|
||||
errors += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
static int eval_class_new(ivl_expr_t ex)
|
||||
{
|
||||
ivl_type_t class_type = ivl_expr_net_type(ex);
|
||||
@@ -292,7 +345,7 @@ static int emit_queue_locator_opcode(ivl_expr_t arg, unsigned elem_wid,
|
||||
unsigned pidx = ivl_expr_property_idx(arg);
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", cl);
|
||||
fprintf(vvp_out, " %s %u, %u;\n", op_prop_v, pidx, elem_wid);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
} else {
|
||||
ivl_signal_t sig = ivl_expr_signal(arg);
|
||||
fprintf(vvp_out, " %s v%p_0, %u;\n", op_v, sig, elem_wid);
|
||||
@@ -311,6 +364,10 @@ static int eval_queue_method_unique(ivl_expr_t expr)
|
||||
"%queue/unique/v", "%queue/unique/prop/v" },
|
||||
{ "$ivl_queue_method$unique_index",
|
||||
"%queue/unique/index/v", "%queue/unique/index/prop/v" },
|
||||
{ "$ivl_queue_method$min",
|
||||
"%queue/min/v", "%queue/min/prop/v" },
|
||||
{ "$ivl_queue_method$max",
|
||||
"%queue/max/v", "%queue/max/prop/v" },
|
||||
};
|
||||
|
||||
const char* name = ivl_expr_name(expr);
|
||||
@@ -338,7 +395,11 @@ enum queue_locator_with_mode_e {
|
||||
QUEUE_WITH_FIND_FIRST,
|
||||
QUEUE_WITH_FIND_FIRST_INDEX,
|
||||
QUEUE_WITH_FIND_LAST,
|
||||
QUEUE_WITH_FIND_LAST_INDEX
|
||||
QUEUE_WITH_FIND_LAST_INDEX,
|
||||
QUEUE_WITH_MIN,
|
||||
QUEUE_WITH_MAX,
|
||||
QUEUE_WITH_UNIQUE,
|
||||
QUEUE_WITH_UNIQUE_INDEX
|
||||
};
|
||||
|
||||
static enum queue_locator_with_mode_e queue_locator_with_mode_from_name(
|
||||
@@ -356,6 +417,14 @@ static enum queue_locator_with_mode_e queue_locator_with_mode_from_name(
|
||||
return QUEUE_WITH_FIND_LAST;
|
||||
} else if (strcmp(name, "$ivl_queue_method$find_last_index_with") == 0) {
|
||||
return QUEUE_WITH_FIND_LAST_INDEX;
|
||||
} else if (strcmp(name, "$ivl_queue_method$min_with") == 0) {
|
||||
return QUEUE_WITH_MIN;
|
||||
} else if (strcmp(name, "$ivl_queue_method$max_with") == 0) {
|
||||
return QUEUE_WITH_MAX;
|
||||
} else if (strcmp(name, "$ivl_queue_method$unique_with") == 0) {
|
||||
return QUEUE_WITH_UNIQUE;
|
||||
} else if (strcmp(name, "$ivl_queue_method$unique_index_with") == 0) {
|
||||
return QUEUE_WITH_UNIQUE_INDEX;
|
||||
}
|
||||
return (enum queue_locator_with_mode_e) -1;
|
||||
}
|
||||
@@ -368,14 +437,20 @@ static int queue_with_reverse(enum queue_locator_with_mode_e mode)
|
||||
|
||||
static int queue_with_multi(enum queue_locator_with_mode_e mode)
|
||||
{
|
||||
return mode == QUEUE_WITH_FIND || mode == QUEUE_WITH_FIND_INDEX;
|
||||
return mode == QUEUE_WITH_FIND ||
|
||||
mode == QUEUE_WITH_FIND_INDEX ||
|
||||
mode == QUEUE_WITH_MIN ||
|
||||
mode == QUEUE_WITH_MAX ||
|
||||
mode == QUEUE_WITH_UNIQUE ||
|
||||
mode == QUEUE_WITH_UNIQUE_INDEX;
|
||||
}
|
||||
|
||||
static int queue_with_as_index(enum queue_locator_with_mode_e mode)
|
||||
{
|
||||
return mode == QUEUE_WITH_FIND_INDEX ||
|
||||
mode == QUEUE_WITH_FIND_FIRST_INDEX ||
|
||||
mode == QUEUE_WITH_FIND_LAST_INDEX;
|
||||
mode == QUEUE_WITH_FIND_LAST_INDEX ||
|
||||
mode == QUEUE_WITH_UNIQUE_INDEX;
|
||||
}
|
||||
|
||||
/* On predicate match: append value/index and continue or stop. */
|
||||
@@ -435,6 +510,37 @@ static void emit_queue_with_step_index(int reverse, int i_reg, unsigned lab_top)
|
||||
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top);
|
||||
}
|
||||
|
||||
static void emit_queue_with_finish(enum queue_locator_with_mode_e mode,
|
||||
int is_prop, unsigned elem_wid)
|
||||
{
|
||||
if (mode == QUEUE_WITH_UNIQUE || mode == QUEUE_WITH_UNIQUE_INDEX) {
|
||||
unsigned wid = (mode == QUEUE_WITH_UNIQUE_INDEX) ? 32 : elem_wid;
|
||||
fprintf(vvp_out, " %%queue/unique/obj/v %u;\n", wid);
|
||||
if (is_prop) {
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mode == QUEUE_WITH_MIN || mode == QUEUE_WITH_MAX) {
|
||||
const char* opname = (mode == QUEUE_WITH_MIN) ? "min" : "max";
|
||||
fprintf(vvp_out, " %%queue/%s/obj/v %u;\n", opname, elem_wid);
|
||||
if (is_prop) {
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (queue_with_multi(mode)) {
|
||||
if (is_prop) {
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
fprintf(vvp_out, " %%queue/new_empty/v;\n");
|
||||
if (is_prop) {
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int eval_queue_method_find_with(ivl_expr_t expr)
|
||||
{
|
||||
const char* name = ivl_expr_name(expr);
|
||||
@@ -521,19 +627,12 @@ static int eval_queue_method_find_with(ivl_expr_t expr)
|
||||
|
||||
fprintf(vvp_out, "T_%u.%u ; loop end (prop)\n", thread_count,
|
||||
lab_loop_end);
|
||||
if (multi) {
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
} else {
|
||||
fprintf(vvp_out, " %%queue/new_empty/v;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
}
|
||||
emit_queue_with_finish(mode, 1, elem_wid);
|
||||
fprintf(vvp_out, "T_%u.%u ; with end (prop)\n", thread_count, lab_end);
|
||||
} else {
|
||||
fprintf(vvp_out, "T_%u.%u ; loop end (var)\n", thread_count,
|
||||
lab_loop_end);
|
||||
if (!multi) {
|
||||
fprintf(vvp_out, " %%queue/new_empty/v;\n");
|
||||
}
|
||||
emit_queue_with_finish(mode, 0, elem_wid);
|
||||
fprintf(vvp_out, "T_%u.%u ; with end (var)\n", thread_count, lab_end);
|
||||
}
|
||||
|
||||
@@ -622,6 +721,9 @@ int draw_eval_object(ivl_expr_t ex)
|
||||
case IVL_EX_UFUNC:
|
||||
return eval_object_ufunc(ex);
|
||||
|
||||
case IVL_EX_ARRAY_PATTERN:
|
||||
return eval_darray_pattern_object(ex);
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
/* Queue locator `with` may report IVL_VT_DARRAY in ivl; handle by name. */
|
||||
if (ivl_expr_parms(ex) == 4 &&
|
||||
|
||||
@@ -270,6 +270,14 @@ extern bool of_QUEUE_FIND_LAST_INDEX_PROP_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_FIND_LAST_INDEX_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_FIND_LAST_PROP_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_FIND_LAST_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_MIN_PROP_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_MIN_OBJ_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_MIN_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_MAX_PROP_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_MAX_OBJ_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_MAX_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_UNIQUE_OBJ_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_UNIQUE_INDEX_OBJ_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_UNIQUE_INDEX_PROP_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_UNIQUE_INDEX_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_QUEUE_UNIQUE_PROP_V(vthread_t thr, vvp_code_t code);
|
||||
|
||||
+9
-1
@@ -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.
|
||||
*/
|
||||
@@ -292,10 +292,18 @@ static const struct opcode_table_s opcode_table[] = {
|
||||
{ "%queue/find_last/index/v", of_QUEUE_FIND_LAST_INDEX_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/find_last/prop/v", of_QUEUE_FIND_LAST_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/find_last/v", of_QUEUE_FIND_LAST_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/max/obj/v", of_QUEUE_MAX_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
||||
{ "%queue/max/prop/v", of_QUEUE_MAX_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/max/v", of_QUEUE_MAX_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%queue/min/obj/v", of_QUEUE_MIN_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
||||
{ "%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/size/v", of_QUEUE_SIZE_V, 1, {OA_FUNC_PTR, OA_NONE, 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} },
|
||||
{ "%queue/unique/obj/v", of_QUEUE_UNIQUE_OBJ_V, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
||||
{ "%queue/unique/prop/v", of_QUEUE_UNIQUE_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
{ "%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} },
|
||||
|
||||
+275
-38
@@ -540,6 +540,24 @@ static void get_queue_or_darray_vec4_from_net(vthread_t thr, vvp_net_t* net,
|
||||
dsrc = 0;
|
||||
}
|
||||
|
||||
static void get_queue_or_darray_vec4_from_object(vvp_object_t src_obj,
|
||||
vvp_queue_vec4*& qsrc,
|
||||
vvp_darray*& dsrc)
|
||||
{
|
||||
qsrc = src_obj.peek<vvp_queue_vec4>();
|
||||
if (qsrc) {
|
||||
dsrc = 0;
|
||||
return;
|
||||
}
|
||||
vvp_darray* dany = src_obj.peek<vvp_darray>();
|
||||
if (dany && dynamic_cast<vvp_queue*>(dany) == 0) {
|
||||
dsrc = dany;
|
||||
return;
|
||||
}
|
||||
qsrc = 0;
|
||||
dsrc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following are used to allow a common template to be written for
|
||||
* queue real/string/vec4 operations
|
||||
@@ -6275,6 +6293,41 @@ static vvp_queue_vec4* queue_find_first_last_to_queue_src(SRC* src,
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* min()/max() return all elements equal to the selected extrema. */
|
||||
template <class SRC>
|
||||
static vvp_queue_vec4* queue_run_min_max_src(SRC* src, unsigned wid, bool want_max)
|
||||
{
|
||||
vvp_queue_vec4* dst = new vvp_queue_vec4();
|
||||
if (!src || src->get_size() == 0)
|
||||
return dst;
|
||||
|
||||
vvp_vector4_t best(wid);
|
||||
src->get_word(0, best);
|
||||
dst->push_back(best, 0);
|
||||
|
||||
size_t n = src->get_size();
|
||||
for (size_t i = 1; i < n; i += 1) {
|
||||
vvp_vector4_t vi(wid);
|
||||
src->get_word(i, vi);
|
||||
if (vi.eeq(best)) {
|
||||
dst->push_back(vi, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
vvp_bit4_t ge = compare_gtge(vi, best, BIT4_1);
|
||||
bool replace = want_max ? (ge == BIT4_1) : (ge == BIT4_0);
|
||||
if (!replace)
|
||||
continue;
|
||||
|
||||
best = vi;
|
||||
delete dst;
|
||||
dst = new vvp_queue_vec4();
|
||||
dst->push_back(best, 0);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
bool of_QUEUE_FIND_V(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_vector4_t cmp = thr->pop_vec4();
|
||||
@@ -6309,12 +6362,11 @@ bool of_QUEUE_FIND_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
if (src == 0) {
|
||||
thr->push_object(vvp_object_t(new vvp_queue_vec4()));
|
||||
return true;
|
||||
}
|
||||
vvp_queue_vec4* dst = queue_run_find_matches_src(src, wid, cmp, false);
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst = qsrc ? queue_run_find_matches_src(qsrc, wid, cmp, false)
|
||||
: queue_run_find_matches_src(dsrc, wid, cmp, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6353,12 +6405,11 @@ bool of_QUEUE_FIND_INDEX_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
if (src == 0) {
|
||||
thr->push_object(vvp_object_t(new vvp_queue_vec4()));
|
||||
return true;
|
||||
}
|
||||
vvp_queue_vec4* dst = queue_run_find_matches_src(src, wid, cmp, true);
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst = qsrc ? queue_run_find_matches_src(qsrc, wid, cmp, true)
|
||||
: queue_run_find_matches_src(dsrc, wid, cmp, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6397,9 +6448,12 @@ bool of_QUEUE_FIND_FIRST_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst =
|
||||
queue_find_first_last_to_queue_src(src, wid, cmp, true, false);
|
||||
qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, true, false)
|
||||
: queue_find_first_last_to_queue_src(dsrc, wid, cmp, true, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6438,9 +6492,12 @@ bool of_QUEUE_FIND_FIRST_INDEX_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst =
|
||||
queue_find_first_last_to_queue_src(src, wid, cmp, true, true);
|
||||
qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, true, true)
|
||||
: queue_find_first_last_to_queue_src(dsrc, wid, cmp, true, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6479,9 +6536,12 @@ bool of_QUEUE_FIND_LAST_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst =
|
||||
queue_find_first_last_to_queue_src(src, wid, cmp, false, false);
|
||||
qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, false, false)
|
||||
: queue_find_first_last_to_queue_src(dsrc, wid, cmp, false, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6520,9 +6580,154 @@ bool of_QUEUE_FIND_LAST_INDEX_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst =
|
||||
queue_find_first_last_to_queue_src(src, wid, cmp, false, true);
|
||||
qsrc ? queue_find_first_last_to_queue_src(qsrc, wid, cmp, false, true)
|
||||
: queue_find_first_last_to_queue_src(dsrc, wid, cmp, false, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_MIN_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_queue_vec4* dst;
|
||||
if (qsrc)
|
||||
dst = queue_run_min_max_src(qsrc, wid, false);
|
||||
else if (dsrc)
|
||||
dst = queue_run_min_max_src(dsrc, wid, false);
|
||||
else {
|
||||
vvp_queue* src_q = get_queue_object<vvp_queue_vec4>(thr, net);
|
||||
vvp_queue_vec4* src = dynamic_cast<vvp_queue_vec4*>(src_q);
|
||||
dst = queue_run_min_max_src(src, wid, false);
|
||||
}
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_MIN_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_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, false)
|
||||
: queue_run_min_max_src(dsrc, wid, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_MIN_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_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, false)
|
||||
: queue_run_min_max_src(dsrc, wid, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_MAX_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_queue_vec4* dst;
|
||||
if (qsrc)
|
||||
dst = queue_run_min_max_src(qsrc, wid, true);
|
||||
else if (dsrc)
|
||||
dst = queue_run_min_max_src(dsrc, wid, true);
|
||||
else {
|
||||
vvp_queue* src_q = get_queue_object<vvp_queue_vec4>(thr, net);
|
||||
vvp_queue_vec4* src = dynamic_cast<vvp_queue_vec4*>(src_q);
|
||||
dst = queue_run_min_max_src(src, wid, true);
|
||||
}
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_MAX_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_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, true)
|
||||
: queue_run_min_max_src(dsrc, wid, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_MAX_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_queue_vec4* dst = qsrc ? queue_run_min_max_src(qsrc, wid, true)
|
||||
: queue_run_min_max_src(dsrc, wid, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_UNIQUE_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_queue_vec4* dst = qsrc ? queue_run_unique_src(qsrc, wid, false)
|
||||
: queue_run_unique_src(dsrc, wid, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_QUEUE_UNIQUE_INDEX_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_queue_vec4* dst = qsrc ? queue_run_unique_src(qsrc, wid, true)
|
||||
: queue_run_unique_src(dsrc, wid, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6557,12 +6762,11 @@ bool of_QUEUE_UNIQUE_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
if (src == 0) {
|
||||
thr->push_object(vvp_object_t(new vvp_queue_vec4()));
|
||||
return true;
|
||||
}
|
||||
vvp_queue_vec4* dst = queue_run_unique_src(src, wid, false);
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst = qsrc ? queue_run_unique_src(qsrc, wid, false)
|
||||
: queue_run_unique_src(dsrc, wid, false);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6597,12 +6801,11 @@ bool of_QUEUE_UNIQUE_INDEX_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
if (src == 0) {
|
||||
thr->push_object(vvp_object_t(new vvp_queue_vec4()));
|
||||
return true;
|
||||
}
|
||||
vvp_queue_vec4* dst = queue_run_unique_src(src, wid, true);
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_queue_vec4* dst = qsrc ? queue_run_unique_src(qsrc, wid, true)
|
||||
: queue_run_unique_src(dsrc, wid, true);
|
||||
thr->push_object(vvp_object_t(dst));
|
||||
return true;
|
||||
}
|
||||
@@ -6617,9 +6820,11 @@ bool of_PROP_QUEUE_SIZE(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
const vvp_queue* queue = qobj.peek<vvp_queue>();
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
|
||||
size_t sz = queue ? queue->get_size() : 0;
|
||||
size_t sz = qsrc ? qsrc->get_size() : (dsrc ? dsrc->get_size() : 0);
|
||||
|
||||
vvp_vector4_t val(32, BIT4_0);
|
||||
unsigned long ul = sz;
|
||||
@@ -6716,19 +6921,51 @@ bool of_QUEUE_WORD_PROP_V(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
vvp_object_t saved_top;
|
||||
bool popped_top = false;
|
||||
vvp_object_t& top = thr->peek_object();
|
||||
vvp_cobject*cobj = top.peek<vvp_cobject>();
|
||||
assert(cobj);
|
||||
if (cobj == 0) {
|
||||
// Array-locator with(property) keeps an accumulator queue on top.
|
||||
// Temporarily pop it to access the class object beneath.
|
||||
thr->pop_object(saved_top);
|
||||
popped_top = true;
|
||||
vvp_object_t& below = thr->peek_object();
|
||||
cobj = below.peek<vvp_cobject>();
|
||||
}
|
||||
if (cobj == 0) {
|
||||
if (popped_top)
|
||||
thr->push_object(saved_top);
|
||||
thr->push_vec4(vvp_vector4_t(wid));
|
||||
return true;
|
||||
}
|
||||
|
||||
vvp_object_t qobj;
|
||||
cobj->get_object(pid, qobj, 0);
|
||||
vvp_queue_vec4* src = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_queue_vec4* qsrc = 0;
|
||||
vvp_darray* dsrc = 0;
|
||||
get_queue_or_darray_vec4_from_object(qobj, qsrc, dsrc);
|
||||
vvp_vector4_t out(wid);
|
||||
if (src == 0 || (size_t)adr >= src->get_size()) {
|
||||
if (qsrc) {
|
||||
if ((size_t)adr >= qsrc->get_size()) {
|
||||
thr->push_vec4(out);
|
||||
return true;
|
||||
}
|
||||
qsrc->get_word((unsigned)adr, out);
|
||||
} else if (dsrc) {
|
||||
if ((size_t)adr >= dsrc->get_size()) {
|
||||
thr->push_vec4(out);
|
||||
return true;
|
||||
}
|
||||
dsrc->get_word((unsigned)adr, out);
|
||||
} else {
|
||||
thr->push_vec4(out);
|
||||
if (popped_top)
|
||||
thr->push_object(saved_top);
|
||||
return true;
|
||||
}
|
||||
src->get_word((unsigned)adr, out);
|
||||
if (popped_top)
|
||||
thr->push_object(saved_top);
|
||||
thr->push_vec4(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user