Add the ability to delete an element of a queue
This commit is contained in:
parent
e94291c88f
commit
1a4345cce9
|
|
@ -243,6 +243,7 @@ class PCallTask : public Statement {
|
||||||
const char*sys_task_name) const;
|
const char*sys_task_name) const;
|
||||||
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
|
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
|
||||||
NetNet*net,
|
NetNet*net,
|
||||||
|
perm_string method_name,
|
||||||
const char*sys_task_name) const;
|
const char*sys_task_name) const;
|
||||||
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
|
|
|
||||||
38
elaborate.cc
38
elaborate.cc
|
|
@ -3596,6 +3596,23 @@ NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
|
||||||
vector<NetExpr*>argv (1 + nparms);
|
vector<NetExpr*>argv (1 + nparms);
|
||||||
argv[0] = sig;
|
argv[0] = sig;
|
||||||
|
|
||||||
|
if (method_name == "delete") {
|
||||||
|
// The queue delete method takes an optional element.
|
||||||
|
if (net->queue_type()) {
|
||||||
|
if (nparms > 1) {
|
||||||
|
cerr << get_fileline() << ": error: queue method "
|
||||||
|
<< "delete() takes zero or one argument." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (nparms > 0) {
|
||||||
|
cerr << get_fileline() << ": error: darray method "
|
||||||
|
<< "delete() takes no arguments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||||
PExpr*ex = parms_[idx];
|
PExpr*ex = parms_[idx];
|
||||||
if (ex != 0) {
|
if (ex != 0) {
|
||||||
|
|
@ -3618,13 +3635,19 @@ NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
|
||||||
*/
|
*/
|
||||||
NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
|
NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
|
||||||
NetNet*net,
|
NetNet*net,
|
||||||
|
perm_string method_name,
|
||||||
const char*sys_task_name) const
|
const char*sys_task_name) const
|
||||||
{
|
{
|
||||||
NetESignal*sig = new NetESignal(net);
|
NetESignal*sig = new NetESignal(net);
|
||||||
sig->set_line(*this);
|
sig->set_line(*this);
|
||||||
|
|
||||||
unsigned nparms = parms_.size();
|
unsigned nparms = parms_.size();
|
||||||
ivl_assert(*this, nparms == 1);
|
if ((nparms == 0) || (nparms > 1)) {
|
||||||
|
cerr << get_fileline() << ": error: method " << method_name
|
||||||
|
<< "() requires a single argument." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ivl_variable_type_t base_type = net->darray_type()->element_base_type();
|
ivl_variable_type_t base_type = net->darray_type()->element_base_type();
|
||||||
int context_width = -1;
|
int context_width = -1;
|
||||||
|
|
@ -3684,17 +3707,16 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
// Is this a delete method for dynamic arrays?
|
// Is this a delete method for dynamic arrays?
|
||||||
if (net->darray_type() && method_name=="delete") {
|
if (net->darray_type() && method_name=="delete") {
|
||||||
return elaborate_sys_task_method_(des, scope, net,
|
return elaborate_sys_task_method_(des, scope, net, method_name,
|
||||||
method_name,
|
|
||||||
"$ivl_darray_method$delete");
|
"$ivl_darray_method$delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (net->queue_type()) {
|
if (net->queue_type()) {
|
||||||
if (method_name=="push_back")
|
if (method_name=="push_back")
|
||||||
return elaborate_queue_method_(des, scope, net,
|
return elaborate_queue_method_(des, scope, net, method_name,
|
||||||
"$ivl_queue_method$push_back");
|
"$ivl_queue_method$push_back");
|
||||||
if (method_name=="push_front")
|
if (method_name=="push_front")
|
||||||
return elaborate_queue_method_(des, scope, net,
|
return elaborate_queue_method_(des, scope, net, method_name,
|
||||||
"$ivl_queue_method$push_front");
|
"$ivl_queue_method$push_front");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4381,8 +4403,10 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||||
"included)." << endl;
|
"included)." << endl;
|
||||||
# if 0
|
# if 0
|
||||||
unsigned base = nset->at(idx).base;
|
unsigned base = nset->at(idx).base;
|
||||||
// FIXME: Is this needed since you can select past the vector?
|
cerr << get_fileline() << ": base = " << base << endl;
|
||||||
assert((base + wid) <= vwid);
|
// FIXME: make this work with selects that go before the base.
|
||||||
|
assert(base < vwid);
|
||||||
|
if (base + wid > vwid) wid = vwid - base;
|
||||||
cerr << get_fileline() << ": base = " << base << ", width = " << wid
|
cerr << get_fileline() << ": base = " << base << ", width = " << wid
|
||||||
<< ", expr width = " << vwid << endl;
|
<< ", expr width = " << vwid << endl;
|
||||||
nset->at(idx).lnk.dump_link(cerr, 4);
|
nset->at(idx).lnk.dump_link(cerr, 4);
|
||||||
|
|
|
||||||
|
|
@ -1748,14 +1748,22 @@ static int show_delete_method(ivl_statement_t net)
|
||||||
show_stmt_file_line(net, "Delete object");
|
show_stmt_file_line(net, "Delete object");
|
||||||
|
|
||||||
unsigned parm_count = ivl_stmt_parm_count(net);
|
unsigned parm_count = ivl_stmt_parm_count(net);
|
||||||
if (parm_count < 1)
|
if ((parm_count < 1) || (parm_count > 2))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ivl_expr_t parm = ivl_stmt_parm(net, 0);
|
ivl_expr_t parm = ivl_stmt_parm(net, 0);
|
||||||
assert(ivl_expr_type(parm) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(parm) == IVL_EX_SIGNAL);
|
||||||
ivl_signal_t var = ivl_expr_signal(parm);
|
ivl_signal_t var = ivl_expr_signal(parm);
|
||||||
|
|
||||||
fprintf(vvp_out, " %%delete/obj v%p_0;\n", var);
|
/* If this is a queue then it can have an element to delete. */
|
||||||
|
if (parm_count == 2) {
|
||||||
|
if (ivl_type_base(ivl_signal_net_type(var)) != IVL_VT_QUEUE)
|
||||||
|
return 1;
|
||||||
|
draw_eval_expr_into_integer(ivl_stmt_parm(net, 1), 3);
|
||||||
|
fprintf(vvp_out, " %%delete/elem v%p_0;\n", var);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%delete/obj v%p_0;\n", var);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1778,7 +1786,7 @@ static int show_push_frontback_method(ivl_statement_t net, bool is_front)
|
||||||
assert(ivl_expr_type(parm0) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(parm0) == IVL_EX_SIGNAL);
|
||||||
ivl_signal_t var = ivl_expr_signal(parm0);
|
ivl_signal_t var = ivl_expr_signal(parm0);
|
||||||
ivl_type_t var_type = ivl_signal_net_type(var);
|
ivl_type_t var_type = ivl_signal_net_type(var);
|
||||||
assert(ivl_type_base(var_type)== IVL_VT_QUEUE);
|
assert(ivl_type_base(var_type) == IVL_VT_QUEUE);
|
||||||
|
|
||||||
int idx = allocate_word();
|
int idx = allocate_word();
|
||||||
assert(idx >= 0);
|
assert(idx >= 0);
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ extern bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DEBUG_THR(vthread_t thr, vvp_code_t code);
|
extern bool of_DEBUG_THR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
|
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DELAYX(vthread_t thr, vvp_code_t code);
|
extern bool of_DELAYX(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_DELETE_ELEM(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DELETE_OBJ(vthread_t thr, vvp_code_t code);
|
extern bool of_DELETE_OBJ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
|
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_DISABLE_FORK(vthread_t thr, vvp_code_t code);
|
extern bool of_DISABLE_FORK(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%debug/thr", of_DEBUG_THR, 1,{OA_STRING, OA_NONE, OA_NONE} },
|
{ "%debug/thr", of_DEBUG_THR, 1,{OA_STRING, OA_NONE, OA_NONE} },
|
||||||
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
|
{ "%delete/elem",of_DELETE_ELEM,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
||||||
{ "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%disable", of_DISABLE, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
{ "%disable", of_DISABLE, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} },
|
{ "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} },
|
||||||
|
|
|
||||||
|
|
@ -2416,6 +2416,43 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool of_DELETE_ELEM(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
vvp_net_t*net = cp->net;
|
||||||
|
|
||||||
|
int64_t idx_val = thr->words[3].w_int;
|
||||||
|
if (thr->flags[4] == BIT4_1) {
|
||||||
|
cerr << "Warning: skipping queue delete() with undefined index."
|
||||||
|
<< endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (idx_val < 0) {
|
||||||
|
cerr << "Warning: skipping queue delete() with negative index."
|
||||||
|
<< endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size_t idx = idx_val;
|
||||||
|
|
||||||
|
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
|
||||||
|
assert(obj);
|
||||||
|
|
||||||
|
vvp_queue*dqueue = obj->get_object().peek<vvp_queue>();
|
||||||
|
if (dqueue == 0) {
|
||||||
|
cerr << "Warning: skipping delete(" << idx
|
||||||
|
<< ") on empty queue." << endl;
|
||||||
|
} else {
|
||||||
|
size_t size = dqueue->get_size();
|
||||||
|
if (idx >= size) {
|
||||||
|
cerr << "Warning: skipping out of range delete(" << idx
|
||||||
|
<< ") on queue of size " << size << "." << endl;
|
||||||
|
} else {
|
||||||
|
dqueue->erase(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* %delete/obj <label>
|
/* %delete/obj <label>
|
||||||
*
|
*
|
||||||
* This operator works by assigning a nil to the target object. This
|
* This operator works by assigning a nil to the target object. This
|
||||||
|
|
|
||||||
|
|
@ -477,6 +477,13 @@ void vvp_queue_real::push_front(double value, unsigned max_size)
|
||||||
queue.push_front(value);
|
queue.push_front(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_queue_real::erase(unsigned idx)
|
||||||
|
{
|
||||||
|
std::deque<double>::iterator pos = queue.begin();
|
||||||
|
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||||
|
queue.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_queue_string::~vvp_queue_string()
|
vvp_queue_string::~vvp_queue_string()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -514,6 +521,13 @@ void vvp_queue_string::push_front(const string&value, unsigned max_size)
|
||||||
queue.push_front(value);
|
queue.push_front(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_queue_string::erase(unsigned idx)
|
||||||
|
{
|
||||||
|
std::deque<std::string>::iterator pos = queue.begin();
|
||||||
|
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||||
|
queue.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_queue_vec4::~vvp_queue_vec4()
|
vvp_queue_vec4::~vvp_queue_vec4()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -550,3 +564,10 @@ void vvp_queue_vec4::push_front(const vvp_vector4_t&value, unsigned max_size)
|
||||||
}
|
}
|
||||||
queue.push_front(value);
|
queue.push_front(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_queue_vec4::erase(unsigned idx)
|
||||||
|
{
|
||||||
|
std::deque<vvp_vector4_t>::iterator pos = queue.begin();
|
||||||
|
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||||
|
queue.erase(pos);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ class vvp_queue : public vvp_darray {
|
||||||
|
|
||||||
virtual void pop_back(void) =0;
|
virtual void pop_back(void) =0;
|
||||||
virtual void pop_front(void)=0;
|
virtual void pop_front(void)=0;
|
||||||
|
virtual void erase(unsigned idx)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class vvp_queue_real : public vvp_queue {
|
class vvp_queue_real : public vvp_queue {
|
||||||
|
|
@ -179,6 +180,7 @@ class vvp_queue_real : public vvp_queue {
|
||||||
void push_front(double value, unsigned max_size);
|
void push_front(double value, unsigned max_size);
|
||||||
void pop_back(void) { queue.pop_back(); };
|
void pop_back(void) { queue.pop_back(); };
|
||||||
void pop_front(void) { queue.pop_front(); };
|
void pop_front(void) { queue.pop_front(); };
|
||||||
|
void erase(unsigned idx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<double> queue;
|
std::deque<double> queue;
|
||||||
|
|
@ -196,6 +198,7 @@ class vvp_queue_string : public vvp_queue {
|
||||||
void push_front(const std::string&value, unsigned max_size);
|
void push_front(const std::string&value, unsigned max_size);
|
||||||
void pop_back(void) { queue.pop_back(); };
|
void pop_back(void) { queue.pop_back(); };
|
||||||
void pop_front(void) { queue.pop_front(); };
|
void pop_front(void) { queue.pop_front(); };
|
||||||
|
void erase(unsigned idx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<std::string> queue;
|
std::deque<std::string> queue;
|
||||||
|
|
@ -213,6 +216,7 @@ class vvp_queue_vec4 : public vvp_queue {
|
||||||
void push_front(const vvp_vector4_t&value, unsigned max_size);
|
void push_front(const vvp_vector4_t&value, unsigned max_size);
|
||||||
void pop_back(void) { queue.pop_back(); };
|
void pop_back(void) { queue.pop_back(); };
|
||||||
void pop_front(void) { queue.pop_front(); };
|
void pop_front(void) { queue.pop_front(); };
|
||||||
|
void erase(unsigned idx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<vvp_vector4_t> queue;
|
std::deque<vvp_vector4_t> queue;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue