diff --git a/PExpr.h b/PExpr.h index 25c4bca4a..c6bd2bc42 100644 --- a/PExpr.h +++ b/PExpr.h @@ -518,6 +518,8 @@ class PENumber : public PExpr { virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode); + virtual NetEConst*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; virtual NetEConst*elaborate_expr(Design*des, NetScope*, unsigned expr_wid, unsigned) const; virtual NetAssign_* elaborate_lval(Design*des, diff --git a/elab_expr.cc b/elab_expr.cc index b92100b43..fa8b3368a 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -144,6 +144,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, ivl_type_t, unsigned) cons << " elaborate (ivl_type_t) this expression. " << endl; cerr << get_fileline() << ": : Expression is: " << *this << endl; + cerr << get_fileline() << ": : Expression type: " << typeid(*this).name() << endl; des->errors += 1; return 0; } @@ -1091,11 +1092,13 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope, if (path_.size() < 2) return 0; + perm_string member_name; + ivl_type_t member_type = 0; pform_name_t use_path = path_; perm_string method_name = peek_tail_name(use_path); use_path.pop_back(); - NetNet *net; + NetNet *net = 0; const NetExpr *par; NetEvent *eve; const NetExpr *ex1, *ex2; @@ -1103,13 +1106,54 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope, symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2); + const netdarray_t*use_darray = 0; + + if (net != 0) + use_darray = net->darray_type(); + + // Net is not found, but maybe it is a member of a + // struct or class. Try to locate net without the member + // name and test if it is a type that has members. + if (net == 0 && use_path.size() >= 2) { + pform_name_t tmp_path = use_path; + member_name = peek_tail_name(tmp_path); + tmp_path.pop_back(); + + net = 0; + symbol_search(this, des, scope, tmp_path, + net, par, eve, ex1, ex2); + if (net && net->class_type()) { + if (debug_elaborate) { + cerr << get_fileline() << ": PECallFunction::test_width_method_: " + << "Found net=" << tmp_path + << ", member_name=" << member_name + << ", method_name=" << method_name + << endl; + } + + netclass_t* class_type = net->class_type(); + member_type = class_type->get_property(member_name); + use_path = tmp_path; + + use_darray = dynamic_cast (member_type); + + } else { + member_name = perm_string(); + net = 0; + } + } + + // After all, no sign of a net match. Give up. if (net == 0) return 0; - netdarray_t*darray = net->darray_type(); - // function int size() - if (darray && method_name == "size") { + if (use_darray && method_name == "size") { + if (debug_elaborate) { + cerr << get_fileline() << ": PECallFunction::test_width_method_: " + << "Match darray size() method." << endl; + } + expr_type_ = IVL_VT_BOOL; expr_width_ = 32; min_width_ = expr_width_; @@ -1866,7 +1910,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, perm_string method_name = peek_tail_name(use_path); use_path.pop_back(); - NetNet *net; + NetNet *net = 0; const NetExpr *par; NetEvent *eve; const NetExpr *ex1, *ex2; @@ -2570,9 +2614,37 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, net, par, eve, ex1, ex2); + if (net == 0 && gn_system_verilog() && path_.size() >= 2) { + pform_name_t use_path = path_; + name_component_t member_comp = use_path.back(); + use_path.pop_back(); + + ivl_assert(*this, net == 0); + symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2); + + if (net == 0) { + // Nope, no struct/class with member. + + } else if (net->struct_type() != 0) { + return check_for_struct_members(this, des, scope, + net, use_path.back().index, + member_comp); + + } else if (net->class_type()!=0) { + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_expr: " + << "Ident " << use_path + << " look for property " << member_comp << endl; + } + + return check_for_class_property(this, des, scope, + net, member_comp); + } + } + if (net == 0) { cerr << get_fileline() << ": internal error: " - << "Expecting idents wtih ntype to be signals." << endl; + << "Expecting idents with ntype to be signals." << endl; des->errors += 1; return 0; } @@ -4192,6 +4264,27 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode) return expr_width_; } +NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const +{ + const netvector_t*use_type = dynamic_cast (ntype); + if (use_type == 0) { + cerr << get_fileline() << ": internal error: " + << "I don't know how cast numbers to this type." + << endl; + des->errors += 1; + return 0; + } + + verinum use_val = value(); + use_val .has_sign( use_type->get_signed() ); + use_val = cast_to_width(use_val, use_type->packed_width()); + + NetEConst*tmp = new NetEConst(use_val); + tmp->set_line(*this); + + return tmp; +} + NetEConst* PENumber::elaborate_expr(Design*, NetScope*, unsigned expr_wid, unsigned) const { diff --git a/elab_lval.cc b/elab_lval.cc index 6a2cb93f0..5dd5d9a8f 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -25,6 +25,7 @@ # include "netmisc.h" # include "netstruct.h" # include "netclass.h" +# include "netdarray.h" # include "compiler.h" # include # include @@ -716,7 +717,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des, return true; } -bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*, +bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope, NetAssign_*lv, const perm_string&method_name) const { @@ -740,6 +741,18 @@ bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*, } lv->set_property(method_name); + + const netdarray_t*mtype = dynamic_cast (ptype); + if (mtype) { + const name_component_t&name_tail = path_.back(); + if (name_tail.index.size() > 0) { + cerr << get_fileline() << ": sorry: " + << "Array index of array properties not supported." + << endl; + des->errors += 1; + } + } + return true; } diff --git a/elab_sig.cc b/elab_sig.cc index 1ca0ad751..eaaac8813 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -865,7 +865,7 @@ static bool evaluate_ranges(Design*des, NetScope*scope, return bad_msb | bad_lsb; } -static netclass_t* locate_class_type(Design*des, NetScope*scope, +static netclass_t* locate_class_type(Design*, NetScope*scope, class_type_t*class_type) { netclass_t*use_class = scope->find_class(class_type->name); @@ -928,7 +928,7 @@ static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, { vectorpacked_dimensions; - bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims); + bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->dims); ivl_assert(*data_type, !bad_range); ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type); diff --git a/elab_type.cc b/elab_type.cc index 313c358a8..8df9fa15a 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -19,6 +19,7 @@ # include "pform_types.h" # include "netlist.h" +# include "netdarray.h" # include "netscalar.h" # include "netvector.h" # include @@ -85,3 +86,15 @@ ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const { return &netstring_t::type_string; } + +ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const +{ + + ivl_type_t btype = base_type->elaborate_type(des, scope); + + assert(dims->size() == 1); + list::const_iterator cur = dims->begin(); + assert(cur->first == 0 && cur->second==0); + ivl_type_s*res = new netdarray_t(btype); + return res; +} diff --git a/elaborate.cc b/elaborate.cc index c618f7d5a..b2336664d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2381,6 +2381,14 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const NetExpr*rv; const ivl_type_s*lv_net_type = lv->net_type(); + if (debug_elaborate) { + cerr << get_fileline() << ": PAssign::elaborate: "; + if (lv_net_type) + cerr << "lv_net_type=" << *lv_net_type << endl; + else + cerr << "lv_net_type=" << endl; + } + /* If the l-value is a compound type of some sort, then use the newer net_type form of the elaborate_rval_ method to handle the new types. */ @@ -2388,9 +2396,21 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const ivl_assert(*this, lv->more==0); rv = elaborate_rval_(des, scope, lv_net_type); - } else if (dynamic_cast (lv_net_type)) { + } else if (const netdarray_t*dtype = dynamic_cast (lv_net_type)) { ivl_assert(*this, lv->more==0); - rv = elaborate_rval_(des, scope, lv_net_type); + if (debug_elaborate) { + if (lv->word()) + cerr << get_fileline() << ": PAssign::elaborate: " + << "lv->word() = " << *lv->word() << endl; + else + cerr << get_fileline() << ": PAssign::elaborate: " + << "lv->word() = " << endl; + } + ivl_type_t use_lv_type = lv_net_type; + if (lv->word()) + use_lv_type = dtype->element_type(); + + rv = elaborate_rval_(des, scope, use_lv_type); } else { /* Elaborate the r-value expression, then try to evaluate it. */ diff --git a/pform_dump.cc b/pform_dump.cc index bbbbc50d8..6d54e3a01 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -154,6 +154,13 @@ void parray_type_t::pform_dump(ostream&out, unsigned indent) const base_type->pform_dump(out, indent+4); } +void uarray_type_t::pform_dump(ostream&out, unsigned indent) const +{ + out << setw(indent) << "" << "Unpacked array " << "[...]" + << " of:" << endl; + base_type->pform_dump(out, indent+4); +} + void struct_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked") diff --git a/pform_pclass.cc b/pform_pclass.cc index 382d3b44f..6189522ce 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -57,7 +57,18 @@ void pform_class_property(const struct vlltype&loc, ; cur != decls->end() ; ++cur) { decl_assignment_t*curp = *cur; - pform_cur_class->type->properties[curp->name] = data_type; + data_type_t*use_type = data_type; + + if (curp->index.size() > 0) { + list*pd = new list (curp->index); + use_type = new uarray_type_t(use_type, pd); + } + + if (curp->expr.get()) { + VLerror(loc, "sorry: Initialization expressions for properties not implemented."); + } + + pform_cur_class->type->properties[curp->name] = use_type; } } diff --git a/pform_types.h b/pform_types.h index d191738d7..adfa050eb 100644 --- a/pform_types.h +++ b/pform_types.h @@ -154,20 +154,39 @@ struct vector_type_t : public data_type_t { std::auto_ptr< list > pdims; }; +struct array_base_t : public data_type_t { + public: + inline explicit array_base_t(data_type_t*btype, std::list*pd) + : base_type(btype), dims(pd) { } + + data_type_t*base_type; + std::auto_ptr< list > dims; +}; + /* - * The array_type_t is a generalization of the vector_type_t in that + * The parray_type_t is a generalization of the vector_type_t in that * the base type is another general data type. Ultimately, the subtype * must also be packed (as this is a packed array) but that may be * worked out during elaboration. */ -struct parray_type_t : public data_type_t { +struct parray_type_t : public array_base_t { inline explicit parray_type_t(data_type_t*btype, std::list*pd) - : base_type(btype), packed_dims(pd) { } + : array_base_t(btype, pd) { } + virtual ivl_variable_type_t figure_packed_base_type(void)const; virtual void pform_dump(std::ostream&out, unsigned indent) const; +}; - data_type_t*base_type; - std::auto_ptr< list > packed_dims; +/* + * The uarray_type_t represents unpacked array types. + */ +struct uarray_type_t : public array_base_t { + inline explicit uarray_type_t(data_type_t*btype, std::list*pd) + : array_base_t(btype, pd) { } + + public: + virtual void pform_dump(std::ostream&out, unsigned indent) const; + virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; }; struct real_type_t : public data_type_t { diff --git a/tgt-vvp/draw_class.c b/tgt-vvp/draw_class.c index 459c9a43f..c0e538831 100644 --- a/tgt-vvp/draw_class.c +++ b/tgt-vvp/draw_class.c @@ -61,9 +61,13 @@ static void show_prop_type(ivl_type_t ptype) case IVL_VT_LOGIC: show_prop_type_vector(ptype); break; + case IVL_VT_DARRAY: + case IVL_VT_CLASS: + fprintf(vvp_out, "\"o\""); + break; default: - assert(0); fprintf(vvp_out, "\"\""); + assert(0); break; } } diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index e2b2acb80..e50f0af16 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -80,6 +80,16 @@ static int eval_object_null(ivl_expr_t ex) return 0; } +static int eval_object_property(ivl_expr_t expr) +{ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned pidx = ivl_expr_property_idx(expr); + + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + fprintf(vvp_out, " %%prop/obj %u;\n", pidx); + return 0; +} + static int eval_object_signal(ivl_expr_t ex) { ivl_signal_t sig = ivl_expr_signal(ex); @@ -106,6 +116,9 @@ int draw_eval_object(ivl_expr_t ex) case IVL_EX_NULL: return eval_object_null(ex); + case IVL_EX_PROPERTY: + return eval_object_property(ex); + case IVL_EX_SIGNAL: return eval_object_signal(ex); diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 72167043e..748cc7a88 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -871,7 +871,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) } else if (ivl_type_base(prop_type) == IVL_VT_STRING) { - /* Calculate the real value into the real value + /* Calculate the string value into the string value stack. The %store/prop/r will pop the stack value. */ draw_eval_string(rval); @@ -879,7 +879,19 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1;\n"); + } else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) { + + /* The property is a darray, and there is no mux + expression to the assignment is of an entire + array object. */ + 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"); + } else { + fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n", + ivl_type_base(prop_type)); assert(0); } diff --git a/vvp/class_type.cc b/vvp/class_type.cc index 1c931a912..3170ef625 100644 --- a/vvp/class_type.cc +++ b/vvp/class_type.cc @@ -56,6 +56,9 @@ class class_property_t { virtual void set_string(char*buf, const std::string&val); virtual string get_string(char*buf); + virtual void set_object(char*buf, const vvp_object_t&val); + virtual void get_object(char*buf, vvp_object_t&val); + protected: size_t offset_; }; @@ -104,6 +107,16 @@ string class_property_t::get_string(char*) return ""; } +void class_property_t::set_object(char*, const vvp_object_t&) +{ + assert(0); +} + +void class_property_t::get_object(char*, vvp_object_t&) +{ + assert(0); +} + /* */ template class property_atom : public class_property_t { @@ -160,6 +173,26 @@ class property_string : public class_property_t { string get_string(char*buf); }; +class property_object : public class_property_t { + public: + inline explicit property_object(void) { } + ~property_object() { } + + size_t instance_size() const { return sizeof(vvp_object_t); } + + public: + void construct(char*buf) const + { /* vvp_object_t*tmp = */ new (buf+offset_) vvp_object_t; } + + void destruct(char*buf) const + { vvp_object_t*tmp = reinterpret_cast (buf+offset_); + tmp->~vvp_object_t(); + } + + void set_object(char*buf, const vvp_object_t&); + void get_object(char*buf, vvp_object_t&); +}; + template void property_atom::set_vec4(char*buf, const vvp_vector4_t&val) { T*tmp = reinterpret_cast (buf+offset_); @@ -204,6 +237,19 @@ string property_string::get_string(char*buf) return *tmp; } +void property_object::set_object(char*buf, const vvp_object_t&val) +{ + vvp_object_t*tmp = reinterpret_cast(buf+offset_); + *tmp = val; +} + +void property_object::get_object(char*buf, vvp_object_t&val) +{ + vvp_object_t*tmp = reinterpret_cast(buf+offset_); + val = *tmp; +} + + /* **** */ class_type::class_type(const string&nam, size_t nprop) @@ -237,6 +283,8 @@ void class_type::set_property(size_t idx, const string&name, const string&type) properties_[idx].type = new property_real; else if (type == "S") properties_[idx].type = new property_string; + else if (type == "o") + properties_[idx].type = new property_object; else properties_[idx].type = 0; } @@ -338,6 +386,21 @@ string class_type::get_string(class_type::inst_t obj, size_t pid) const return properties_[pid].type->get_string(buf); } +void class_type::set_object(class_type::inst_t obj, size_t pid, + const vvp_object_t&val) const +{ + char*buf = reinterpret_cast (obj); + assert(pid < properties_.size()); + properties_[pid].type->set_object(buf, val); +} + +void class_type::get_object(class_type::inst_t obj, size_t pid, vvp_object_t&val) const +{ + char*buf = reinterpret_cast (obj); + assert(pid < properties_.size()); + properties_[pid].type->get_object(buf, val); +} + int class_type::get_type_code(void) const { return vpiClassDefn; diff --git a/vvp/class_type.h b/vvp/class_type.h index 1c617117b..851231deb 100644 --- a/vvp/class_type.h +++ b/vvp/class_type.h @@ -65,6 +65,8 @@ class class_type : public __vpiHandle { double get_real(inst_t inst, size_t pid) const; void set_string(inst_t inst, size_t pid, const std::string&val) const; std::string get_string(inst_t inst, size_t pid) const; + void set_object(inst_t inst, size_t pid, const vvp_object_t&val) const; + void get_object(inst_t inst, size_t pid, vvp_object_t&val) const; public: // VPI related methods int get_type_code(void) const; diff --git a/vvp/codes.h b/vvp/codes.h index 51f050b33..8d3af2804 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -165,6 +165,7 @@ extern bool of_POP_STR(vthread_t thr, vvp_code_t code); extern bool of_POW(vthread_t thr, vvp_code_t code); extern bool of_POW_S(vthread_t thr, vvp_code_t code); extern bool of_POW_WR(vthread_t thr, vvp_code_t code); +extern bool of_PROP_OBJ(vthread_t thr, vvp_code_t code); extern bool of_PROP_R(vthread_t thr, vvp_code_t code); extern bool of_PROP_STR(vthread_t thr, vvp_code_t code); extern bool of_PROP_V(vthread_t thr, vvp_code_t code); @@ -186,6 +187,7 @@ extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code); extern bool of_STORE_DAR_R(vthread_t thr, vvp_code_t code); extern bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t code); extern bool of_STORE_PROP_R(vthread_t thr, vvp_code_t code); extern bool of_STORE_PROP_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_PROP_V(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index b7c66d1e6..a4d08f48a 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -213,6 +213,7 @@ static const struct opcode_table_s opcode_table[] = { { "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pow/s", of_POW_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%prop/obj",of_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%prop/r", of_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%prop/str",of_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%prop/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -233,6 +234,7 @@ static const struct opcode_table_s opcode_table[] = { { "%store/dar/r", of_STORE_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%store/dar/str",of_STORE_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/prop/obj",of_STORE_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%store/prop/v", of_STORE_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 571c67256..d34a098ae 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -889,12 +889,13 @@ This opcode raises the left operand by the right operand, and pushes the result. * %prop/v , , +* %prop/obj * %prop/r * %prop/str Write the vector (/v) or real value (/r) or string (/str) into property number of the class object on the top of the object -stack. The real value is popped. +stack. The class object stack is NOT popped. @@ -1016,6 +1017,7 @@ variable given by the label. See also %load/obj. +* %store/prop/obj * %store/prop/r * %store/prop/str * %store/prop/v , , @@ -1024,6 +1026,10 @@ The %store/prop/r pops a real value from the real stack and stores it into the the property number of a cobject in the top of the object stack. The cobject is NOT popped. +The %store/prop/obj pops an object from the top of the object stack, +then writes it to the property number of the cobject now on +top of the object stack. The cobject is NOT popped. + * %store/real * %store/reala , diff --git a/vvp/vthread.cc b/vvp/vthread.cc index dfe0edcbd..c587e89c6 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -3226,6 +3226,7 @@ bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp) darray->get_word(adr, word); assert(word.size() == wid); + thr_check_addr(thr, bit+word.size()); thr->bits4.set_vec(bit, word); return true; @@ -4533,6 +4534,26 @@ bool of_POW_WR(vthread_t thr, vvp_code_t) return true; } +/* + * %prop/obj + * + * Load an object value from the cobject and push it onto the object stack. + */ +bool of_PROP_OBJ(vthread_t thr, vvp_code_t cp) +{ + unsigned pid = cp->number; + + vvp_object_t&obj = thr->peek_object(); + vvp_cobject*cobj = obj.peek(); + + vvp_object_t val; + cobj->get_object(pid, val); + + thr->push_object(val); + + return true; +} + /* * %prop/r * @@ -5112,6 +5133,28 @@ bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp) return true; } +/* + * %store/prop/obj + * + * Pop an object value from the object stack, and store the value into + * the property of the object references by the top of the stack. Do NOT + * pop the object stack. + */ +bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t cp) +{ + size_t pid = cp->number; + vvp_object_t val; + thr->pop_object(val); + + vvp_object_t&obj = thr->peek_object(); + vvp_cobject*cobj = obj.peek(); + assert(cobj); + + cobj->set_object(pid, val); + + return true; +} + /* * %store/prop/r * diff --git a/vvp/vvp_cobject.cc b/vvp/vvp_cobject.cc index 1c563626f..f9c99affd 100644 --- a/vvp/vvp_cobject.cc +++ b/vvp/vvp_cobject.cc @@ -64,3 +64,13 @@ string vvp_cobject::get_string(size_t pid) { return defn_->get_string(properties_, pid); } + +void vvp_cobject::set_object(size_t pid, const vvp_object_t&val) +{ + defn_->set_object(properties_, pid, val); +} + +void vvp_cobject::get_object(size_t pid, vvp_object_t&val) +{ + return defn_->get_object(properties_, pid, val); +} diff --git a/vvp/vvp_cobject.h b/vvp/vvp_cobject.h index 93ef16fa8..736896c7e 100644 --- a/vvp/vvp_cobject.h +++ b/vvp/vvp_cobject.h @@ -41,6 +41,9 @@ class vvp_cobject : public vvp_object { void set_string(size_t pid, const std::string&val); std::string get_string(size_t pid); + void set_object(size_t pid, const vvp_object_t&val); + void get_object(size_t pid, vvp_object_t&val); + private: const class_type* defn_; // For now, only support 32bit bool signed properties.