Add the ability to delete an element of a queue

This commit is contained in:
Cary R 2020-07-25 00:48:57 -07:00
parent e94291c88f
commit 1a4345cce9
8 changed files with 107 additions and 10 deletions

View File

@ -243,6 +243,7 @@ class PCallTask : public Statement {
const char*sys_task_name) const;
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const;

View File

@ -3596,6 +3596,23 @@ NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
vector<NetExpr*>argv (1 + nparms);
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) {
PExpr*ex = parms_[idx];
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,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const
{
NetESignal*sig = new NetESignal(net);
sig->set_line(*this);
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();
int context_width = -1;
@ -3684,17 +3707,16 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
// Is this a delete method for dynamic arrays?
if (net->darray_type() && method_name=="delete") {
return elaborate_sys_task_method_(des, scope, net,
method_name,
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_darray_method$delete");
}
if (net->queue_type()) {
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");
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");
}
@ -4381,8 +4403,10 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
"included)." << endl;
# if 0
unsigned base = nset->at(idx).base;
// FIXME: Is this needed since you can select past the vector?
assert((base + wid) <= vwid);
cerr << get_fileline() << ": base = " << base << endl;
// 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
<< ", expr width = " << vwid << endl;
nset->at(idx).lnk.dump_link(cerr, 4);

View File

@ -1748,14 +1748,22 @@ static int show_delete_method(ivl_statement_t net)
show_stmt_file_line(net, "Delete object");
unsigned parm_count = ivl_stmt_parm_count(net);
if (parm_count < 1)
if ((parm_count < 1) || (parm_count > 2))
return 1;
ivl_expr_t parm = ivl_stmt_parm(net, 0);
assert(ivl_expr_type(parm) == IVL_EX_SIGNAL);
ivl_signal_t var = ivl_expr_signal(parm);
/* 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;
}
@ -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);
ivl_signal_t var = ivl_expr_signal(parm0);
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();
assert(idx >= 0);

View File

@ -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_DELAY(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_DISABLE(vthread_t thr, vvp_code_t code);
extern bool of_DISABLE_FORK(vthread_t thr, vvp_code_t code);

View File

@ -151,6 +151,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%debug/thr", of_DEBUG_THR, 1,{OA_STRING, OA_NONE, OA_NONE} },
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, 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} },
{ "%disable", of_DISABLE, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
{ "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} },

View File

@ -2416,6 +2416,43 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
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>
*
* This operator works by assigning a nil to the target object. This

View File

@ -477,6 +477,13 @@ void vvp_queue_real::push_front(double value, unsigned max_size)
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()
{
}
@ -514,6 +521,13 @@ void vvp_queue_string::push_front(const string&value, unsigned max_size)
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()
{
}
@ -550,3 +564,10 @@ void vvp_queue_vec4::push_front(const vvp_vector4_t&value, unsigned max_size)
}
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);
}

View File

@ -165,6 +165,7 @@ class vvp_queue : public vvp_darray {
virtual void pop_back(void) =0;
virtual void pop_front(void)=0;
virtual void erase(unsigned idx)=0;
};
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 pop_back(void) { queue.pop_back(); };
void pop_front(void) { queue.pop_front(); };
void erase(unsigned idx);
private:
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 pop_back(void) { queue.pop_back(); };
void pop_front(void) { queue.pop_front(); };
void erase(unsigned idx);
private:
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 pop_back(void) { queue.pop_back(); };
void pop_front(void) { queue.pop_front(); };
void erase(unsigned idx);
private:
std::deque<vvp_vector4_t> queue;