Support nested l-value objects
This allows for syntax like a.b.c where a is a class with member b, which is a class with member c, and so on. The handling is mostly for the support of compound objects like classes.
This commit is contained in:
parent
37ac1ed474
commit
fa8d35ae9c
|
|
@ -871,19 +871,18 @@ void NetAlloc::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
o << sig_->name();
|
||||
if (! member_.nil()) {
|
||||
o << "." << member_;
|
||||
}
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
} else {
|
||||
o << "";
|
||||
if (sig_) o << sig_->name();
|
||||
else if (nest_) nest_->dump_lval(o);
|
||||
else o << "<?>";
|
||||
|
||||
if (! member_.nil()) {
|
||||
o << "." << member_;
|
||||
}
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
1
ivl.def
1
ivl.def
|
|
@ -141,6 +141,7 @@ ivl_lpm_width
|
|||
|
||||
ivl_lval_idx
|
||||
ivl_lval_mux
|
||||
ivl_lval_nest
|
||||
ivl_lval_part_off
|
||||
ivl_lval_property_idx
|
||||
ivl_lval_sel_type
|
||||
|
|
|
|||
|
|
@ -1446,6 +1446,10 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
|||
*
|
||||
* ivl_lval_mux (* obsolete *)
|
||||
*
|
||||
* ivl_lval_nest
|
||||
* If the l-value is an object more complex than a variable, then
|
||||
* this returns the nested l-value (and ivl_lval_sig==0).
|
||||
*
|
||||
* ivl_lval_sig
|
||||
* If the l-value is a variable, this method returns the signal
|
||||
* object that is the target of the assign.
|
||||
|
|
@ -1493,6 +1497,7 @@ extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
|||
extern ivl_select_type_t ivl_lval_sel_type(ivl_lval_t net);
|
||||
extern int ivl_lval_property_idx(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
extern ivl_lval_t ivl_lval_nest(ivl_lval_t net);
|
||||
|
||||
|
||||
/* NEXUS
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ perm_string NetAssign_::name() const
|
|||
|
||||
NetNet* NetAssign_::sig() const
|
||||
{
|
||||
assert(sig_? nest_==0 : nest_!=0);
|
||||
return sig_;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2594,6 +2594,7 @@ class NetAssign_ {
|
|||
perm_string name() const;
|
||||
|
||||
NetNet* sig() const;
|
||||
inline const NetAssign_* nest() const { return nest_; }
|
||||
|
||||
// Mark that the synthesizer has worked with this l-value, so
|
||||
// when it is released, the l-value signal should be turned
|
||||
|
|
|
|||
10
t-dll-api.cc
10
t-dll-api.cc
|
|
@ -1625,6 +1625,15 @@ extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_lval_t ivl_lval_nest(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->type_ == IVL_LVAL_LVAL)
|
||||
return net->n.nest;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_nature_name(ivl_nature_t net)
|
||||
{
|
||||
return net->name();
|
||||
|
|
@ -2728,6 +2737,7 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
|||
switch(cur->type_) {
|
||||
case IVL_LVAL_REG:
|
||||
case IVL_LVAL_ARR:
|
||||
case IVL_LVAL_LVAL:
|
||||
sum += ivl_lval_width(cur);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
# include "netclass.h"
|
||||
# include <cstdlib>
|
||||
# include "ivl_alloc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
bool dll_target::process(const NetProcTop*net)
|
||||
{
|
||||
|
|
@ -174,35 +175,51 @@ bool dll_target::make_single_lval_(const LineInfo*li, struct ivl_lval_s*cur, con
|
|||
|
||||
cur->width_ = asn->lwidth();
|
||||
|
||||
ivl_type_t nest_type = 0;
|
||||
|
||||
if (asn->sig()) {
|
||||
cur->type_ = IVL_LVAL_REG;
|
||||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
|
||||
cur->idx = 0;
|
||||
// If there is a word select expression, it is
|
||||
// really an array index. Note that the word index
|
||||
// expression is already converted to canonical
|
||||
// form by elaboration.
|
||||
if (asn->word()) {
|
||||
assert(expr_ == 0);
|
||||
asn->word()->expr_scan(this);
|
||||
cur->type_ = IVL_LVAL_ARR;
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
cur->property_idx = -1;
|
||||
perm_string pname = asn->get_property();
|
||||
if (!pname.nil()) {
|
||||
const netclass_t*use_type = dynamic_cast<const netclass_t*> (cur->n.sig->net_type);
|
||||
cur->property_idx = use_type->property_idx_from_name(pname);
|
||||
}
|
||||
|
||||
} else {
|
||||
cerr << li->get_fileline() << ": internal error: "
|
||||
<< "I don't know how to handle nested l-values "
|
||||
<< "in ivl_target.h API." << endl;
|
||||
flag = false;
|
||||
const NetAssign_*asn_nest = asn->nest();
|
||||
ivl_assert(*li, asn_nest);
|
||||
nest_type = asn_nest->net_type();
|
||||
struct ivl_lval_s*cur_nest = new struct ivl_lval_s;
|
||||
make_single_lval_(li, cur_nest, asn_nest);
|
||||
|
||||
cur->type_ = IVL_LVAL_LVAL;
|
||||
cur->n.nest = cur_nest;
|
||||
}
|
||||
|
||||
cur->idx = 0;
|
||||
// If there is a word select expression, it is
|
||||
// really an array index. Note that the word index
|
||||
// expression is already converted to canonical
|
||||
// form by elaboration.
|
||||
if (asn->word()) {
|
||||
assert(expr_ == 0);
|
||||
asn->word()->expr_scan(this);
|
||||
cur->type_ = IVL_LVAL_ARR;
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
cur->property_idx = -1;
|
||||
perm_string pname = asn->get_property();
|
||||
if (!pname.nil()) {
|
||||
const netclass_t*use_type;
|
||||
switch (cur->type_) {
|
||||
case IVL_LVAL_LVAL:
|
||||
assert(nest_type);
|
||||
use_type = dynamic_cast<const netclass_t*> (nest_type);
|
||||
break;
|
||||
default:
|
||||
use_type = dynamic_cast<const netclass_t*> (cur->n.sig->net_type);
|
||||
break;
|
||||
}
|
||||
assert(use_type);
|
||||
cur->property_idx = use_type->property_idx_from_name(pname);
|
||||
}
|
||||
|
||||
return flag;
|
||||
|
|
|
|||
6
t-dll.h
6
t-dll.h
|
|
@ -454,7 +454,8 @@ struct ivl_lpm_s {
|
|||
|
||||
enum ivl_lval_type_t {
|
||||
IVL_LVAL_REG = 0,
|
||||
IVL_LVAL_ARR = 4
|
||||
IVL_LVAL_ARR = 4,
|
||||
IVL_LVAL_LVAL= 5 // Nested l-value
|
||||
};
|
||||
|
||||
struct ivl_lval_s {
|
||||
|
|
@ -462,10 +463,11 @@ struct ivl_lval_s {
|
|||
ivl_select_type_t sel_type :3;
|
||||
ivl_expr_t idx;
|
||||
unsigned width_;
|
||||
unsigned type_ : 8;
|
||||
unsigned type_ : 8; /* values from ivl_lval_type_t */
|
||||
int property_idx;
|
||||
union {
|
||||
ivl_signal_t sig;
|
||||
ivl_lval_t nest; // type_ == IVL_LVAL_LVAL
|
||||
} n;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ extern ivl_variable_type_t type_of_nexus(ivl_nexus_t nex);
|
|||
|
||||
extern ivl_discipline_t discipline_of_nexus(ivl_nexus_t nex);
|
||||
|
||||
extern unsigned width_of_type(ivl_type_t net);
|
||||
|
||||
/*
|
||||
* Test that a given expression is a valid delay expression, and
|
||||
* print an error message if not.
|
||||
|
|
|
|||
|
|
@ -76,8 +76,59 @@ static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind)
|
|||
return ivl_lval_width(lval);
|
||||
}
|
||||
|
||||
unsigned width_of_type(ivl_type_t net)
|
||||
{
|
||||
switch (ivl_type_packed_dimensions(net)) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 1: {
|
||||
int msb = ivl_type_packed_msb(net,0);
|
||||
int lsb = ivl_type_packed_lsb(net,0);
|
||||
if (msb > lsb)
|
||||
return msb-lsb+1;
|
||||
else
|
||||
return lsb-msb+1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ivl_type_t show_assign_lval_nest(ivl_lval_t lval, unsigned ind)
|
||||
{
|
||||
ivl_type_t sub_type;
|
||||
|
||||
if (ivl_lval_nest(lval)) {
|
||||
fprintf(out, "%*s{nested lval property=%d}\n", ind, "",
|
||||
ivl_lval_property_idx(lval));
|
||||
sub_type = show_assign_lval_nest(ivl_lval_nest(lval), ind+4);
|
||||
|
||||
} else {
|
||||
assert(ivl_lval_sig(lval));
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
fprintf(out, "%*s{name=%s property=%d, signal width=%u l-value width=%u}\n",
|
||||
ind, "",
|
||||
ivl_signal_name(sig),
|
||||
ivl_lval_property_idx(lval),
|
||||
ivl_signal_width(sig),
|
||||
ivl_lval_width(lval));
|
||||
|
||||
sub_type = ivl_signal_net_type(sig);
|
||||
}
|
||||
|
||||
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
||||
ivl_type_t lval_type = ivl_type_prop_type(sub_type, ivl_lval_property_idx(lval));
|
||||
return lval_type;
|
||||
}
|
||||
|
||||
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
||||
{
|
||||
ivl_lval_t lval_nest = ivl_lval_nest(lval);
|
||||
if (lval_nest) {
|
||||
ivl_type_t net_type = show_assign_lval_nest(lval, ind);
|
||||
return width_of_type(net_type);
|
||||
}
|
||||
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
assert(sig);
|
||||
|
||||
|
|
@ -254,6 +305,7 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
|||
{
|
||||
unsigned idx;
|
||||
char opcode = 0;
|
||||
unsigned lwid = 0;
|
||||
const ivl_statement_type_t code = ivl_statement_type(net);
|
||||
|
||||
switch (code) {
|
||||
|
|
@ -270,13 +322,14 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
|||
ivl_stmt_lwidth(net), opcode);
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
||||
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
|
||||
if (ivl_stmt_delay_expr(net))
|
||||
show_expression(ivl_stmt_delay_expr(net), idx+4);
|
||||
|
||||
if (ivl_stmt_rval(net))
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
fprintf(out, "%*sTotal l-value width is %u\n", ind+2, "", lwid);
|
||||
break;
|
||||
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
|
|
|
|||
|
|
@ -318,6 +318,38 @@ static void put_vec_to_lval(ivl_statement_t net, struct vec_slice_info*slices,
|
|||
}
|
||||
}
|
||||
|
||||
static ivl_type_t draw_lval_expr(ivl_lval_t lval)
|
||||
{
|
||||
ivl_lval_t lval_nest = ivl_lval_nest(lval);
|
||||
ivl_signal_t lval_sig = ivl_lval_sig(lval);
|
||||
ivl_type_t sub_type;
|
||||
|
||||
if (lval_nest) {
|
||||
sub_type = draw_lval_expr(lval_nest);
|
||||
} else {
|
||||
assert(lval_sig);
|
||||
sub_type = ivl_signal_net_type(lval_sig);
|
||||
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", lval_sig);
|
||||
}
|
||||
|
||||
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
||||
fprintf(vvp_out, " %%prop/obj %d;\n", ivl_lval_property_idx(lval));
|
||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||
return ivl_type_prop_type(sub_type, ivl_lval_property_idx(lval));
|
||||
}
|
||||
|
||||
static void set_vec_to_lval_slice_nest(ivl_lval_t lval, unsigned bit, unsigned wid)
|
||||
{
|
||||
ivl_lval_t lval_nest = ivl_lval_nest(lval);
|
||||
ivl_type_t ltype = draw_lval_expr(lval_nest);
|
||||
assert(ivl_type_base(ltype) == IVL_VT_CLASS);
|
||||
|
||||
fprintf(vvp_out, " %%store/prop/v %d, %u, %u;\n",
|
||||
ivl_lval_property_idx(lval), bit, wid);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
}
|
||||
|
||||
static void set_vec_to_lval_slice(ivl_lval_t lval, unsigned bit, unsigned wid)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
|
|
@ -330,6 +362,13 @@ static void set_vec_to_lval_slice(ivl_lval_t lval, unsigned bit, unsigned wid)
|
|||
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
|
||||
/* If the l-value is nested, then it is something like a class
|
||||
with a chain of member names, so handle that elsewhere. */
|
||||
if (ivl_lval_nest(lval)) {
|
||||
set_vec_to_lval_slice_nest(lval, bit, wid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
|
||||
|
|
@ -953,7 +992,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%store/prop/v %d, %u, %u; Store in bool property %s\n",
|
||||
prop_idx, val.base, val.wid,
|
||||
ivl_type_prop_name(sig_type, prop_idx));
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
clr_vector(val);
|
||||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) {
|
||||
|
|
@ -967,7 +1006,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%store/prop/v %d, %u, %u; Store in logic property %s\n",
|
||||
prop_idx, val.base, val.wid,
|
||||
ivl_type_prop_name(sig_type, prop_idx));
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
clr_vector(val);
|
||||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_REAL) {
|
||||
|
|
@ -978,7 +1017,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
draw_eval_real(rval);
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_STRING) {
|
||||
|
||||
|
|
@ -988,7 +1027,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
draw_eval_string(rval);
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) {
|
||||
|
||||
|
|
@ -998,7 +1037,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_CLASS) {
|
||||
|
||||
|
|
@ -1006,7 +1045,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%pad", of_PAD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%pop/obj", of_POP_OBJ, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%pop/obj", of_POP_OBJ, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%pop/real",of_POP_REAL,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%pop/str", of_POP_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
|
|||
|
|
@ -646,16 +646,6 @@ the object handle stack.
|
|||
|
||||
See also %store/obj.
|
||||
|
||||
|
||||
* %load/prop/v <pid>, <bit>, <wid>
|
||||
|
||||
This instruction loads from a class object property into the specified
|
||||
thread register bit. The <pid> is the number of the property and the
|
||||
<bit> is the location where the loaded value goes.
|
||||
|
||||
The handle for the class object is found on the top of the object
|
||||
stack, and the stack is NOT popped.
|
||||
|
||||
* %load/real <vpi-label>
|
||||
|
||||
The %load/real instruction reads a real value from the vpi-like object
|
||||
|
|
@ -874,14 +864,18 @@ or sign extending a vector.
|
|||
|
||||
* %pop/str <num>
|
||||
* %pop/real <num>
|
||||
* %pop/obj <num>
|
||||
* %pop/obj <num>, <skip>
|
||||
|
||||
Pop this many items from the string/real/object stack. This is the
|
||||
Pop <num> items from the string/real/object stack. This is the
|
||||
opposite of the %pushX/str opcode which pushes a string to the
|
||||
stack. The %pop/str is not normally needed because the %store/str
|
||||
includes an implicit pop, but sometimes it is necessary to pop
|
||||
explicitly.
|
||||
|
||||
The <skip> is the number of top positions on the stack to keep,
|
||||
beforing starting to pop. This allows for popping positions other then
|
||||
the top of the stack.
|
||||
|
||||
* %pow <bit-l>, <bit-r>, <wid>
|
||||
* %pow/s <bit-l>, <bit-r>, <wid>
|
||||
|
||||
|
|
@ -902,9 +896,10 @@ the result.
|
|||
* %prop/r <pid>
|
||||
* %prop/str <pid>
|
||||
|
||||
Write the vector (/v) or real value (/r) or string (/str) into
|
||||
property number <pid> of the class object on the top of the object
|
||||
stack.
|
||||
Read a vector (/v) or real value (/r) or string (/str) or object from
|
||||
the property number <pid> of the class object on the stop of the
|
||||
object stack. Push the resulting value to the appropriate stack. The
|
||||
object that is the source is NOT popped from from object stack.
|
||||
|
||||
The class object stack is NOT popped.
|
||||
|
||||
|
|
|
|||
|
|
@ -187,12 +187,16 @@ struct vthread_s {
|
|||
obj = stack_obj_[stack_obj_size_];
|
||||
stack_obj_[stack_obj_size_].reset(0);
|
||||
}
|
||||
inline void pop_object(unsigned cnt)
|
||||
inline void pop_object(unsigned cnt, unsigned skip =0)
|
||||
{
|
||||
assert(cnt <= stack_obj_size_);
|
||||
for (size_t idx = stack_obj_size_-cnt ; idx < stack_obj_size_ ; idx += 1)
|
||||
assert((cnt+skip) <= stack_obj_size_);
|
||||
for (size_t idx = stack_obj_size_-skip-cnt ; idx < stack_obj_size_-skip ; idx += 1)
|
||||
stack_obj_[idx].reset(0);
|
||||
stack_obj_size_ -= cnt;
|
||||
for (size_t idx = stack_obj_size_-skip ; idx < stack_obj_size_ ; idx += 1)
|
||||
stack_obj_[idx] = stack_obj_[idx+skip];
|
||||
for (size_t idx = stack_obj_size_ ; idx < stack_obj_size_+skip ; idx += 1)
|
||||
stack_obj_[idx].reset(0);
|
||||
}
|
||||
inline void push_object(const vvp_object_t&obj)
|
||||
{
|
||||
|
|
@ -4502,12 +4506,14 @@ bool of_NOR(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
/*
|
||||
* %pop/obj <number>
|
||||
* %pop/obj <num>, <skip>
|
||||
*/
|
||||
bool of_POP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned cnt = cp->number;
|
||||
thr->pop_object(cnt);
|
||||
unsigned cnt = cp->bit_idx[0];
|
||||
unsigned skip = cp->bit_idx[1];
|
||||
|
||||
thr->pop_object(cnt, skip);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue