SystemVerilog: add min/max locator methods for queue and darray
Implement queue and dynamic-array min()/max() for integral vec4 element types, with VVP support for both queue-backed and darray-backed storage and regressions in ivtest. Keep min/max as no-arg methods and document current behavior alongside existing locator tests. Made-with: Cursor
This commit is contained in:
parent
20bd360aec
commit
30b4afa7d2
112
elab_expr.cc
112
elab_expr.cc
|
|
@ -1736,7 +1736,8 @@ 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 == "min" || method_name == "max") {
|
||||
expr_type_ = IVL_VT_QUEUE;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
|
|
@ -1791,7 +1792,8 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
if (method_name == "unique" || method_name == "unique_index") {
|
||||
if (method_name == "unique" || method_name == "unique_index" ||
|
||||
method_name == "min" || method_name == "max") {
|
||||
expr_type_ = IVL_VT_QUEUE;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
|
|
@ -3788,6 +3790,26 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
sys_expr->parm(0, prop);
|
||||
return sys_expr;
|
||||
}
|
||||
if (method_name == "min" || method_name == "max") {
|
||||
if (parms_.size() != 0) {
|
||||
cerr << get_fileline() << ": error: " << method_name
|
||||
<< "() method takes no arguments" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: queue " << method_name
|
||||
<< "() for this element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*sys_expr = new NetESFunc(
|
||||
method_name == "min" ? "$ivl_queue_method$min"
|
||||
: "$ivl_queue_method$max",
|
||||
static_cast<ivl_type_t>(queue), 1);
|
||||
sys_expr->set_line(*this);
|
||||
sys_expr->parm(0, prop);
|
||||
return sys_expr;
|
||||
}
|
||||
if (method_name == "find") {
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: queue find() for this "
|
||||
|
|
@ -4289,6 +4311,32 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
sys_expr->parm(1, cmp);
|
||||
return sys_expr;
|
||||
}
|
||||
if (method_name == "min" || method_name == "max") {
|
||||
if (parms_.size() != 0) {
|
||||
cerr << get_fileline() << ": error: " << method_name
|
||||
<< "() method takes no arguments" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: dynamic array " << method_name
|
||||
<< "() for this element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (with_expr_) {
|
||||
cerr << get_fileline() << ": sorry: dynamic array " << method_name
|
||||
<< "() with a `with` clause is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*sys_expr = new NetESFunc(
|
||||
method_name == "min" ? "$ivl_queue_method$min"
|
||||
: "$ivl_queue_method$max",
|
||||
queue_rtype, 1);
|
||||
sys_expr->set_line(*this);
|
||||
sys_expr->parm(0, sub_expr);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Method " << method_name
|
||||
<< " is not a dynamic array method." << endl;
|
||||
|
|
@ -4381,6 +4429,32 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
sys_expr->parm(0, sub_expr);
|
||||
return sys_expr;
|
||||
}
|
||||
if (method_name == "min" || method_name == "max") {
|
||||
if (parms_.size() != 0) {
|
||||
cerr << get_fileline() << ": error: " << method_name
|
||||
<< "() method takes no arguments" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
cerr << get_fileline() << ": sorry: queue " << method_name
|
||||
<< "() for this element type is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (with_expr_) {
|
||||
cerr << get_fileline() << ": sorry: queue " << method_name
|
||||
<< "() with a `with` clause is not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetESFunc*sys_expr = new NetESFunc(
|
||||
method_name == "min" ? "$ivl_queue_method$min"
|
||||
: "$ivl_queue_method$max",
|
||||
static_cast<ivl_type_t>(queue), 1);
|
||||
sys_expr->set_line(*this);
|
||||
sys_expr->parm(0, sub_expr);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
if (method_name == "find") {
|
||||
if (!queue_method_element_is_integral_vec4(element_type)) {
|
||||
|
|
@ -5798,6 +5872,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;
|
||||
|
|
@ -6112,6 +6203,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.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ This directory includes regression tests for IEEE 1800 locator methods
|
|||
on unpacked queues (int q[$]) and dynamic arrays (int da[]):
|
||||
|
||||
find, find_index, find_first, find_first_index, find_last,
|
||||
find_last_index, unique, unique_index
|
||||
find_last_index, min, max, unique, unique_index
|
||||
|
||||
Behavior notes (LRM-oriented):
|
||||
|
||||
|
|
@ -17,6 +17,9 @@ Behavior notes (LRM-oriented):
|
|||
queue with zero or one element; no match yields an empty queue (not a
|
||||
scalar sentinel).
|
||||
|
||||
* min() and max() return queues containing all elements equal to the
|
||||
selected extrema.
|
||||
|
||||
* For dynamic arrays, runtime support treats storage as vvp_darray (including
|
||||
atom-backed integral arrays), not only vvp_queue_vec4. See vvp/vthread.cc:
|
||||
get_queue_or_darray_vec4_from_net() and the %queue/* opcodes used for
|
||||
|
|
@ -37,3 +40,5 @@ Regression tests (see ivtest/vvp_tests/*.json and regress-vvp.list):
|
|||
sv_queue_find_locators_ext.v Longer queue, compound predicates.
|
||||
sv_queue_unique.v unique / unique_index.
|
||||
sv_darray_find_locators.v Same locator patterns on int[] dynamic array.
|
||||
sv_queue_min_max.v min() and max() on queue values.
|
||||
sv_darray_min_max.v min() and max() on dynamic array values.
|
||||
|
|
|
|||
|
|
@ -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,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
|
||||
|
|
@ -253,6 +253,7 @@ 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_default_port_value1 vvp_tests/sv_default_port_value1.json
|
||||
sv_default_port_value2 vvp_tests/sv_default_port_value2.json
|
||||
sv_default_port_value3 vvp_tests/sv_default_port_value3.json
|
||||
|
|
@ -276,6 +277,7 @@ sv_queue_unique vvp_tests/sv_queue_unique.json
|
|||
sv_queue_find vvp_tests/sv_queue_find.json
|
||||
sv_queue_find_locators_ext vvp_tests/sv_queue_find_locators_ext.json
|
||||
sv_queue_find_with vvp_tests/sv_queue_find_with.json
|
||||
sv_queue_min_max vvp_tests/sv_queue_min_max.json
|
||||
sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json
|
||||
sdf_header vvp_tests/sdf_header.json
|
||||
task_return1 vvp_tests/task_return1.json
|
||||
|
|
|
|||
|
|
@ -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_queue_min_max.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "SystemVerilog queue min/max locator methods",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -315,6 +315,26 @@ static int eval_queue_method_unique(ivl_expr_t expr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(name, "$ivl_queue_method$min") == 0 ||
|
||||
strcmp(name, "$ivl_queue_method$max") == 0) {
|
||||
const char* opname = strcmp(name, "$ivl_queue_method$min") == 0
|
||||
? "min"
|
||||
: "max";
|
||||
if (ivl_expr_type(arg) == IVL_EX_PROPERTY) {
|
||||
ivl_signal_t cl = ivl_expr_signal(arg);
|
||||
unsigned pidx = ivl_expr_property_idx(arg);
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", cl);
|
||||
fprintf(vvp_out, " %%queue/%s/prop/v %u, %u;\n", opname, pidx,
|
||||
elem_wid);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
} else {
|
||||
ivl_signal_t sig = ivl_expr_signal(arg);
|
||||
fprintf(vvp_out, " %%queue/%s/v v%p_0, %u;\n", opname, sig,
|
||||
elem_wid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -269,6 +269,10 @@ 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_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_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);
|
||||
|
|
|
|||
|
|
@ -291,6 +291,10 @@ 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/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/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/prop/v", of_QUEUE_UNIQUE_INDEX_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||
|
|
|
|||
125
vvp/vthread.cc
125
vvp/vthread.cc
|
|
@ -6357,6 +6357,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();
|
||||
|
|
@ -6621,6 +6656,96 @@ bool of_QUEUE_FIND_LAST_INDEX_PROP_V(vthread_t thr, vvp_code_t cp)
|
|||
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_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 = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_darray* dsrc = 0;
|
||||
if (!qsrc) {
|
||||
vvp_darray* dany = qobj.peek<vvp_darray>();
|
||||
if (dany && dynamic_cast<vvp_queue*>(dany) == 0)
|
||||
dsrc = dany;
|
||||
}
|
||||
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_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 = qobj.peek<vvp_queue_vec4>();
|
||||
vvp_darray* dsrc = 0;
|
||||
if (!qsrc) {
|
||||
vvp_darray* dany = qobj.peek<vvp_darray>();
|
||||
if (dany && dynamic_cast<vvp_queue*>(dany) == 0)
|
||||
dsrc = dany;
|
||||
}
|
||||
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_V(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_net_t*net = cp->net;
|
||||
|
|
|
|||
Loading…
Reference in New Issue