Support the delete method for objects.

This commit is contained in:
Stephen Williams 2012-07-16 18:15:29 -07:00
parent d0e6b24ca2
commit 18714e2efd
12 changed files with 96 additions and 11 deletions

View File

@ -210,6 +210,8 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const; NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const; NetProc* elaborate_usr(Design*des, NetScope*scope) const;
NetProc*elaborate_method_(Design*des, NetScope*scope) const;
pform_name_t path_; pform_name_t path_;
vector<PExpr*> parms_; vector<PExpr*> parms_;
}; };

View File

@ -1305,12 +1305,12 @@ void NetSTask::dump(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << name_; o << setw(ind) << "" << name_;
if (parms_.count() > 0) { if (parms_.size() > 0) {
o << "("; o << "(";
if (parms_[0]) if (parms_[0])
parms_[0]->dump(o); parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
o << ", "; o << ", ";
if (parms_[idx]) if (parms_[idx])
parms_[idx]->dump(o); parms_[idx]->dump(o);

View File

@ -2908,7 +2908,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
if ((parm_count== 1) && (parms_[0] == 0)) if ((parm_count== 1) && (parms_[0] == 0))
parm_count = 0; parm_count = 0;
svector<NetExpr*>eparms (parm_count); vector<NetExpr*>eparms (parm_count);
perm_string name = peek_tail_name(path_); perm_string name = peek_tail_name(path_);
@ -2987,6 +2987,12 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
NetScope*task = des->find_task(scope, path_); NetScope*task = des->find_task(scope, path_);
if (task == 0) { if (task == 0) {
// Maybe this is a method attached to a signal?
if (gn_system_verilog()) {
NetProc*tmp = elaborate_method_(des, scope);
if (tmp) return tmp;
}
cerr << get_fileline() << ": error: Enable of unknown task " cerr << get_fileline() << ": error: Enable of unknown task "
<< "``" << path_ << "''." << endl; << "``" << path_ << "''." << endl;
des->errors += 1; des->errors += 1;
@ -3169,6 +3175,39 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
return block; return block;
} }
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
{
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
NetNet *net;
const NetExpr *par;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
if (net == 0)
return 0;
// Is this a delete method for dynamic arrays?
if (net->darray_type() && method_name=="delete") {
NetESignal*sig = new NetESignal(net);
vector<NetExpr*> argv (1);
argv[0] = sig;
NetSTask*sys = new NetSTask("$ivl_darray_method$delete",
IVL_SFUNC_AS_TASK_IGNORE, argv);
sys->set_line(*this);
return sys;
}
return 0;
}
/* /*
* Elaborate a procedural continuous assign. This really looks very * Elaborate a procedural continuous assign. This really looks very
* much like other procedural assignments, at this point, but there * much like other procedural assignments, at this point, but there

View File

@ -397,13 +397,13 @@ NexusSet* NetRepeat::nex_input(bool rem_out)
*/ */
NexusSet* NetSTask::nex_input(bool rem_out) NexusSet* NetSTask::nex_input(bool rem_out)
{ {
if (parms_.count() == 0) if (parms_.size() == 0)
return new NexusSet; return new NexusSet;
NexusSet*result; NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out); if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet; else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) { if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out); NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);

View File

@ -2089,7 +2089,7 @@ const NetNet* NetFuncDef::return_sig() const
} }
NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat, NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
const svector<NetExpr*>&pa) const vector<NetExpr*>&pa)
: name_(0), sfunc_as_task_(sfat), parms_(pa) : name_(0), sfunc_as_task_(sfat), parms_(pa)
{ {
name_ = lex_strings.add(na); name_ = lex_strings.add(na);
@ -2098,7 +2098,7 @@ NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
NetSTask::~NetSTask() NetSTask::~NetSTask()
{ {
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
delete parms_[idx]; delete parms_[idx];
/* The name_ string is perm-allocated in lex_strings. */ /* The name_ string is perm-allocated in lex_strings. */
@ -2116,7 +2116,7 @@ ivl_sfunc_as_task_t NetSTask::sfunc_as_task() const
unsigned NetSTask::nparms() const unsigned NetSTask::nparms() const
{ {
return parms_.count(); return parms_.size();
} }
const NetExpr* NetSTask::parm(unsigned idx) const const NetExpr* NetSTask::parm(unsigned idx) const

View File

@ -3191,7 +3191,7 @@ class NetSTask : public NetProc {
public: public:
NetSTask(const char*na, ivl_sfunc_as_task_t sfat, NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
const svector<NetExpr*>&); const std::vector<NetExpr*>&);
~NetSTask(); ~NetSTask();
const char* name() const; const char* name() const;
@ -3209,7 +3209,7 @@ class NetSTask : public NetProc {
private: private:
const char* name_; const char* name_;
ivl_sfunc_as_task_t sfunc_as_task_; ivl_sfunc_as_task_t sfunc_as_task_;
svector<NetExpr*>parms_; std::vector<NetExpr*>parms_;
}; };
/* /*

View File

@ -1646,8 +1646,29 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
return rc; return rc;
} }
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)
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);
return 0;
}
static int show_system_task_call(ivl_statement_t net) static int show_system_task_call(ivl_statement_t net)
{ {
const char*stmt_name = ivl_stmt_name(net);
if (strcmp(stmt_name,"$ivl_darray_method$delete") == 0)
return show_delete_method(net);
show_stmt_file_line(net, "System task call."); show_stmt_file_line(net, "System task call.");
draw_vpi_task_call(net); draw_vpi_task_call(net);

View File

@ -88,6 +88,7 @@ extern bool of_DEASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t code); extern bool of_DEASSIGN_WR(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_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_DIV(vthread_t thr, vvp_code_t code); extern bool of_DIV(vthread_t thr, vvp_code_t code);
extern bool of_DIV_S(vthread_t thr, vvp_code_t code); extern bool of_DIV_S(vthread_t thr, vvp_code_t code);

View File

@ -139,6 +139,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, 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/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%div/wr", of_DIV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%div/wr", of_DIV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },

View File

@ -375,6 +375,11 @@ This is similar to the %delay opcode, except that the parameter
selects an index register, which contains the actual delay. This selects an index register, which contains the actual delay. This
supports run-time calculated delays. supports run-time calculated delays.
* %delete/obj <var-label>
Arrange for the dynamic object at the target label to be deleted.
This has no effect on the object or string stack.
* %disable <scope-label> * %disable <scope-label>
This instruction terminates threads that are part of a specific This instruction terminates threads that are part of a specific
@ -720,7 +725,7 @@ means the following:
Create a new array (of int objects) with a size. the <idx> is the Create a new array (of int objects) with a size. the <idx> is the
address of an index variable that contains the computed array size to address of an index variable that contains the computed array size to
use. use. See also %delete/obj
NOTE: For now, assume this is an array of int values. NOTE: For now, assume this is an array of int values.

View File

@ -2011,6 +2011,21 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
return false; return false;
} }
/* %delete/obj <label>
*
* This operator works by assigning a nil to the target object. This
* causes any value that might be there to be garbage collected, thus
* deleting the object.
*/
bool of_DELETE_OBJ(vthread_t thr, vvp_code_t cp)
{
/* set the value into port 0 of the destination. */
vvp_net_ptr_t ptr (cp->net, 0);
vvp_send_object(ptr, 0, thr->wt_context);
return true;
}
static bool do_disable(vthread_t thr, vthread_t match) static bool do_disable(vthread_t thr, vthread_t match)
{ {
bool flag = false; bool flag = false;

View File

@ -677,6 +677,7 @@ void vvp_fun_signal_object_sa::recv_object(vvp_net_ptr_t ptr, vvp_object_t bit,
assert(ptr.port() == 0); assert(ptr.port() == 0);
if (needs_init_ || value_ != bit) { if (needs_init_ || value_ != bit) {
if (value_) delete value_;
value_ = bit; value_ = bit;
needs_init_ = false; needs_init_ = false;