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;
|
||||
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;
|
||||
|
||||
|
|
|
|||
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);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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} },
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue