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_usr(Design*des, NetScope*scope) const;
NetProc*elaborate_method_(Design*des, NetScope*scope) const;
pform_name_t path_;
vector<PExpr*> parms_;
};

View File

@ -1305,12 +1305,12 @@ void NetSTask::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << name_;
if (parms_.count() > 0) {
if (parms_.size() > 0) {
o << "(";
if (parms_[0])
parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
o << ", ";
if (parms_[idx])
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))
parm_count = 0;
svector<NetExpr*>eparms (parm_count);
vector<NetExpr*>eparms (parm_count);
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_);
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 "
<< "``" << path_ << "''." << endl;
des->errors += 1;
@ -3169,6 +3175,39 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
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
* 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)
{
if (parms_.count() == 0)
if (parms_.size() == 0)
return new NexusSet;
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
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]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
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,
const svector<NetExpr*>&pa)
const vector<NetExpr*>&pa)
: name_(0), sfunc_as_task_(sfat), parms_(pa)
{
name_ = lex_strings.add(na);
@ -2098,7 +2098,7 @@ NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
NetSTask::~NetSTask()
{
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
delete parms_[idx];
/* 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
{
return parms_.count();
return parms_.size();
}
const NetExpr* NetSTask::parm(unsigned idx) const

View File

@ -3191,7 +3191,7 @@ class NetSTask : public NetProc {
public:
NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
const svector<NetExpr*>&);
const std::vector<NetExpr*>&);
~NetSTask();
const char* name() const;
@ -3209,7 +3209,7 @@ class NetSTask : public NetProc {
private:
const char* name_;
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;
}
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)
{
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.");
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_DELAY(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_DIV(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} },
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, 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/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%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
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>
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
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.

View File

@ -2011,6 +2011,21 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
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)
{
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);
if (needs_init_ || value_ != bit) {
if (value_) delete value_;
value_ = bit;
needs_init_ = false;