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,8 +871,10 @@ void NetAlloc::dump(ostream&o, unsigned ind) const
|
||||||
|
|
||||||
void NetAssign_::dump_lval(ostream&o) const
|
void NetAssign_::dump_lval(ostream&o) const
|
||||||
{
|
{
|
||||||
if (sig_) {
|
if (sig_) o << sig_->name();
|
||||||
o << sig_->name();
|
else if (nest_) nest_->dump_lval(o);
|
||||||
|
else o << "<?>";
|
||||||
|
|
||||||
if (! member_.nil()) {
|
if (! member_.nil()) {
|
||||||
o << "." << member_;
|
o << "." << member_;
|
||||||
}
|
}
|
||||||
|
|
@ -882,9 +884,6 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||||
if (base_) {
|
if (base_) {
|
||||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
o << "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetAssignBase::dump_lval(ostream&o) const
|
void NetAssignBase::dump_lval(ostream&o) const
|
||||||
|
|
|
||||||
1
ivl.def
1
ivl.def
|
|
@ -141,6 +141,7 @@ ivl_lpm_width
|
||||||
|
|
||||||
ivl_lval_idx
|
ivl_lval_idx
|
||||||
ivl_lval_mux
|
ivl_lval_mux
|
||||||
|
ivl_lval_nest
|
||||||
ivl_lval_part_off
|
ivl_lval_part_off
|
||||||
ivl_lval_property_idx
|
ivl_lval_property_idx
|
||||||
ivl_lval_sel_type
|
ivl_lval_sel_type
|
||||||
|
|
|
||||||
|
|
@ -1446,6 +1446,10 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||||
*
|
*
|
||||||
* ivl_lval_mux (* obsolete *)
|
* 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
|
* ivl_lval_sig
|
||||||
* If the l-value is a variable, this method returns the signal
|
* If the l-value is a variable, this method returns the signal
|
||||||
* object that is the target of the assign.
|
* 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 ivl_select_type_t ivl_lval_sel_type(ivl_lval_t net);
|
||||||
extern int ivl_lval_property_idx(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_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||||
|
extern ivl_lval_t ivl_lval_nest(ivl_lval_t net);
|
||||||
|
|
||||||
|
|
||||||
/* NEXUS
|
/* NEXUS
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,7 @@ perm_string NetAssign_::name() const
|
||||||
|
|
||||||
NetNet* NetAssign_::sig() const
|
NetNet* NetAssign_::sig() const
|
||||||
{
|
{
|
||||||
|
assert(sig_? nest_==0 : nest_!=0);
|
||||||
return sig_;
|
return sig_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2594,6 +2594,7 @@ class NetAssign_ {
|
||||||
perm_string name() const;
|
perm_string name() const;
|
||||||
|
|
||||||
NetNet* sig() const;
|
NetNet* sig() const;
|
||||||
|
inline const NetAssign_* nest() const { return nest_; }
|
||||||
|
|
||||||
// Mark that the synthesizer has worked with this l-value, so
|
// Mark that the synthesizer has worked with this l-value, so
|
||||||
// when it is released, the l-value signal should be turned
|
// 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)
|
extern "C" const char* ivl_nature_name(ivl_nature_t net)
|
||||||
{
|
{
|
||||||
return net->name();
|
return net->name();
|
||||||
|
|
@ -2728,6 +2737,7 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
||||||
switch(cur->type_) {
|
switch(cur->type_) {
|
||||||
case IVL_LVAL_REG:
|
case IVL_LVAL_REG:
|
||||||
case IVL_LVAL_ARR:
|
case IVL_LVAL_ARR:
|
||||||
|
case IVL_LVAL_LVAL:
|
||||||
sum += ivl_lval_width(cur);
|
sum += ivl_lval_width(cur);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
# include "netclass.h"
|
# include "netclass.h"
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include "ivl_alloc.h"
|
# include "ivl_alloc.h"
|
||||||
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
bool dll_target::process(const NetProcTop*net)
|
bool dll_target::process(const NetProcTop*net)
|
||||||
{
|
{
|
||||||
|
|
@ -174,10 +175,23 @@ bool dll_target::make_single_lval_(const LineInfo*li, struct ivl_lval_s*cur, con
|
||||||
|
|
||||||
cur->width_ = asn->lwidth();
|
cur->width_ = asn->lwidth();
|
||||||
|
|
||||||
|
ivl_type_t nest_type = 0;
|
||||||
|
|
||||||
if (asn->sig()) {
|
if (asn->sig()) {
|
||||||
cur->type_ = IVL_LVAL_REG;
|
cur->type_ = IVL_LVAL_REG;
|
||||||
cur->n.sig = find_signal(des_, asn->sig());
|
cur->n.sig = find_signal(des_, asn->sig());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
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;
|
cur->idx = 0;
|
||||||
// If there is a word select expression, it is
|
// If there is a word select expression, it is
|
||||||
// really an array index. Note that the word index
|
// really an array index. Note that the word index
|
||||||
|
|
@ -194,15 +208,18 @@ bool dll_target::make_single_lval_(const LineInfo*li, struct ivl_lval_s*cur, con
|
||||||
cur->property_idx = -1;
|
cur->property_idx = -1;
|
||||||
perm_string pname = asn->get_property();
|
perm_string pname = asn->get_property();
|
||||||
if (!pname.nil()) {
|
if (!pname.nil()) {
|
||||||
const netclass_t*use_type = dynamic_cast<const netclass_t*> (cur->n.sig->net_type);
|
const netclass_t*use_type;
|
||||||
cur->property_idx = use_type->property_idx_from_name(pname);
|
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);
|
||||||
} else {
|
cur->property_idx = use_type->property_idx_from_name(pname);
|
||||||
cerr << li->get_fileline() << ": internal error: "
|
|
||||||
<< "I don't know how to handle nested l-values "
|
|
||||||
<< "in ivl_target.h API." << endl;
|
|
||||||
flag = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
|
|
|
||||||
6
t-dll.h
6
t-dll.h
|
|
@ -454,7 +454,8 @@ struct ivl_lpm_s {
|
||||||
|
|
||||||
enum ivl_lval_type_t {
|
enum ivl_lval_type_t {
|
||||||
IVL_LVAL_REG = 0,
|
IVL_LVAL_REG = 0,
|
||||||
IVL_LVAL_ARR = 4
|
IVL_LVAL_ARR = 4,
|
||||||
|
IVL_LVAL_LVAL= 5 // Nested l-value
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ivl_lval_s {
|
struct ivl_lval_s {
|
||||||
|
|
@ -462,10 +463,11 @@ struct ivl_lval_s {
|
||||||
ivl_select_type_t sel_type :3;
|
ivl_select_type_t sel_type :3;
|
||||||
ivl_expr_t idx;
|
ivl_expr_t idx;
|
||||||
unsigned width_;
|
unsigned width_;
|
||||||
unsigned type_ : 8;
|
unsigned type_ : 8; /* values from ivl_lval_type_t */
|
||||||
int property_idx;
|
int property_idx;
|
||||||
union {
|
union {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
ivl_lval_t nest; // type_ == IVL_LVAL_LVAL
|
||||||
} n;
|
} 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 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
|
* Test that a given expression is a valid delay expression, and
|
||||||
* print an error message if not.
|
* 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);
|
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)
|
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);
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
assert(sig);
|
assert(sig);
|
||||||
|
|
||||||
|
|
@ -254,6 +305,7 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
||||||
{
|
{
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
char opcode = 0;
|
char opcode = 0;
|
||||||
|
unsigned lwid = 0;
|
||||||
const ivl_statement_type_t code = ivl_statement_type(net);
|
const ivl_statement_type_t code = ivl_statement_type(net);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
|
@ -270,13 +322,14 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
||||||
ivl_stmt_lwidth(net), opcode);
|
ivl_stmt_lwidth(net), opcode);
|
||||||
|
|
||||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
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))
|
if (ivl_stmt_delay_expr(net))
|
||||||
show_expression(ivl_stmt_delay_expr(net), idx+4);
|
show_expression(ivl_stmt_delay_expr(net), idx+4);
|
||||||
|
|
||||||
if (ivl_stmt_rval(net))
|
if (ivl_stmt_rval(net))
|
||||||
show_expression(ivl_stmt_rval(net), ind+4);
|
show_expression(ivl_stmt_rval(net), ind+4);
|
||||||
|
fprintf(out, "%*sTotal l-value width is %u\n", ind+2, "", lwid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IVL_ST_ASSIGN_NB:
|
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)
|
static void set_vec_to_lval_slice(ivl_lval_t lval, unsigned bit, unsigned wid)
|
||||||
{
|
{
|
||||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
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);
|
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||||
unsigned long use_word = 0;
|
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) {
|
if (part_off_ex == 0) {
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 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",
|
fprintf(vvp_out, " %%store/prop/v %d, %u, %u; Store in bool property %s\n",
|
||||||
prop_idx, val.base, val.wid,
|
prop_idx, val.base, val.wid,
|
||||||
ivl_type_prop_name(sig_type, prop_idx));
|
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);
|
clr_vector(val);
|
||||||
|
|
||||||
} else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) {
|
} 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",
|
fprintf(vvp_out, " %%store/prop/v %d, %u, %u; Store in logic property %s\n",
|
||||||
prop_idx, val.base, val.wid,
|
prop_idx, val.base, val.wid,
|
||||||
ivl_type_prop_name(sig_type, prop_idx));
|
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);
|
clr_vector(val);
|
||||||
|
|
||||||
} else if (ivl_type_base(prop_type) == IVL_VT_REAL) {
|
} 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);
|
draw_eval_real(rval);
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx);
|
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) {
|
} 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);
|
draw_eval_string(rval);
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx);
|
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) {
|
} 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);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
draw_eval_object(rval);
|
draw_eval_object(rval);
|
||||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
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) {
|
} 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);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
draw_eval_object(rval);
|
draw_eval_object(rval);
|
||||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
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 {
|
} else {
|
||||||
fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
|
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", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%or/r", of_ORR, 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} },
|
{ "%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/real",of_POP_REAL,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%pop/str", of_POP_STR, 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} },
|
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
|
|
|
||||||
|
|
@ -646,16 +646,6 @@ the object handle stack.
|
||||||
|
|
||||||
See also %store/obj.
|
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>
|
* %load/real <vpi-label>
|
||||||
|
|
||||||
The %load/real instruction reads a real value from the vpi-like object
|
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/str <num>
|
||||||
* %pop/real <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
|
opposite of the %pushX/str opcode which pushes a string to the
|
||||||
stack. The %pop/str is not normally needed because the %store/str
|
stack. The %pop/str is not normally needed because the %store/str
|
||||||
includes an implicit pop, but sometimes it is necessary to pop
|
includes an implicit pop, but sometimes it is necessary to pop
|
||||||
explicitly.
|
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 <bit-l>, <bit-r>, <wid>
|
||||||
* %pow/s <bit-l>, <bit-r>, <wid>
|
* %pow/s <bit-l>, <bit-r>, <wid>
|
||||||
|
|
||||||
|
|
@ -902,9 +896,10 @@ the result.
|
||||||
* %prop/r <pid>
|
* %prop/r <pid>
|
||||||
* %prop/str <pid>
|
* %prop/str <pid>
|
||||||
|
|
||||||
Write the vector (/v) or real value (/r) or string (/str) into
|
Read a vector (/v) or real value (/r) or string (/str) or object from
|
||||||
property number <pid> of the class object on the top of the object
|
the property number <pid> of the class object on the stop of the
|
||||||
stack.
|
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.
|
The class object stack is NOT popped.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,16 @@ struct vthread_s {
|
||||||
obj = stack_obj_[stack_obj_size_];
|
obj = stack_obj_[stack_obj_size_];
|
||||||
stack_obj_[stack_obj_size_].reset(0);
|
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_);
|
assert((cnt+skip) <= stack_obj_size_);
|
||||||
for (size_t idx = stack_obj_size_-cnt ; idx < stack_obj_size_ ; idx += 1)
|
for (size_t idx = stack_obj_size_-skip-cnt ; idx < stack_obj_size_-skip ; idx += 1)
|
||||||
stack_obj_[idx].reset(0);
|
stack_obj_[idx].reset(0);
|
||||||
stack_obj_size_ -= cnt;
|
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)
|
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)
|
bool of_POP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
unsigned cnt = cp->number;
|
unsigned cnt = cp->bit_idx[0];
|
||||||
thr->pop_object(cnt);
|
unsigned skip = cp->bit_idx[1];
|
||||||
|
|
||||||
|
thr->pop_object(cnt, skip);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue