Support the delete method for objects.
This commit is contained in:
parent
d0e6b24ca2
commit
18714e2efd
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
41
elaborate.cc
41
elaborate.cc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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} },
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue