diff --git a/design_dump.cc b/design_dump.cc index 038f30443..f47155a27 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1524,7 +1524,7 @@ void NetENull::dump(ostream&o) const void NetEProperty::dump(ostream&o) const { - o << net_->name() << "." << pname_; + o << net_->name() << ".<" << pidx_ << ">"; } void NetEScope::dump(ostream&o) const diff --git a/ivl_target.h b/ivl_target.h index 27acde38d..9a3343d08 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -805,6 +805,22 @@ extern unsigned ivl_event_lineno(ivl_event_t net); * * - IVL_EX_BINARY * + * - IVL_EX_PROPERTY + * This expression represents the property select from a class + * type, for example "foo.property" where "foo" is a class handle and + * "property" is the name of one of the properties of the class. The + * ivl_expr_signal function returns the ivl_signal_t for "foo" and the + * data_type for the signal will be IVL_VT_CLASS. + * + * The ivl_signal_net_type(sig) for the "foo" signal will be a class + * type and from there you can get access to the type information. + * + * Elaboration reduces the properties of a class to a vector numbered + * from 0 to the number of properties. The ivl_expr_property_idx() + * function gets the index of the selected property into the property + * table. That number can be passed to ivl_type_prop_*() functions to + * get details about the property. + * * - IVL_EX_SELECT * This expression takes two operands, oper1 is the expression to * select from, and oper2 is the selection base. The ivl_expr_width @@ -891,6 +907,8 @@ extern unsigned ivl_expr_repeat(ivl_expr_t net); extern ivl_select_type_t ivl_expr_sel_type(ivl_expr_t net); /* IVL_EX_EVENT */ extern ivl_event_t ivl_expr_event(ivl_expr_t net); + /* IVL_EX_PROPERTY */ +extern int ivl_expr_property_idx(ivl_expr_t net); /* IVL_EX_SCOPE */ extern ivl_scope_t ivl_expr_scope(ivl_expr_t net); /* IVL_EX_PROPERTY IVL_EX_SIGNAL */ @@ -1431,10 +1449,10 @@ extern const char*ivl_lpm_string(ivl_lpm_t net); * ivl_expr_t that represents the index expression. Otherwise, it * returns 0. * - * ivl_lval_property + * ivl_lval_property_idx * If the l-value is a class object, this is the name of a property - * to select from the object. If this property is not present, then - * the l-value represents the class object itself. + * to select from the object. If this property is not present (<0) + * then the l-value represents the class object itself. * * SEMANTIC NOTES * The ivl_lval_width is not necessarily the same as the width of the @@ -1461,7 +1479,7 @@ extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */ extern ivl_expr_t ivl_lval_idx(ivl_lval_t net); 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 const char* ivl_lval_property(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); @@ -2224,9 +2242,9 @@ extern unsigned ivl_type_packed_dimensions(ivl_type_t net); extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim); extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim); extern const char* ivl_type_name(ivl_type_t net); -extern unsigned ivl_type_properties(ivl_type_t net); -extern const char* ivl_type_prop_name(ivl_type_t net, unsigned idx); -extern ivl_type_t ivl_type_prop_type(ivl_type_t net, unsigned idx); +extern int ivl_type_properties(ivl_type_t net); +extern const char* ivl_type_prop_name(ivl_type_t net, int idx); +extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx); #if defined(__MINGW32__) || defined (__CYGWIN32__) diff --git a/net_expr.cc b/net_expr.cc index 5e5c05d76..fcb6db1a7 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -349,8 +349,14 @@ NetENull::~NetENull() } NetEProperty::NetEProperty(NetNet*net, perm_string pnam) -: net_(net), pname_(pnam) +: net_(net) { + const netclass_t*use_type = dynamic_cast(net->net_type()); + assert(use_type); + + pidx_ = use_type->property_idx_from_name(pnam); + ivl_type_t prop_type = use_type->get_prop_type(pidx_); + expr_width(prop_type->packed_width()); } NetEProperty::~NetEProperty() diff --git a/netclass.cc b/netclass.cc index 30acfce3b..6561d824e 100644 --- a/netclass.cc +++ b/netclass.cc @@ -33,13 +33,17 @@ netclass_t::~netclass_t() bool netclass_t::set_property(perm_string pname, ivl_type_s*ptype) { - map::const_iterator cur; + map::const_iterator cur; cur = properties_.find(pname); if (cur != properties_.end()) return false; - properties_[pname] = ptype; - property_table_.push_back(pname); + prop_t tmp; + tmp.name = pname; + tmp.type = ptype; + property_table_.push_back(tmp); + + properties_[pname] = property_table_.size()-1; return true; } @@ -50,22 +54,33 @@ ivl_variable_type_t netclass_t::base_type() const const ivl_type_s* netclass_t::get_property(perm_string pname) const { - map::const_iterator cur; + map::const_iterator cur; cur = properties_.find(pname); if (cur == properties_.end()) return 0; - else - return cur->second; + + assert(property_table_.size() > cur->second); + return property_table_[cur->second].type; +} + +int netclass_t::property_idx_from_name(perm_string pname) const +{ + map::const_iterator cur; + cur = properties_.find(pname); + if (cur == properties_.end()) + return -1; + + return cur->second; } const char*netclass_t::get_prop_name(size_t idx) const { assert(idx < property_table_.size()); - return property_table_[idx]; + return property_table_[idx].name; } ivl_type_t netclass_t::get_prop_type(size_t idx) const { assert(idx < property_table_.size()); - return get_property(property_table_[idx]); + return property_table_[idx].type; } diff --git a/netclass.h b/netclass.h index af1656612..bfbb0285d 100644 --- a/netclass.h +++ b/netclass.h @@ -47,12 +47,18 @@ class netclass_t : public ivl_type_s { const char*get_prop_name(size_t idx) const; ivl_type_t get_prop_type(size_t idx) const; + int property_idx_from_name(perm_string pname) const; + private: perm_string name_; - // Bind properties to their types. - std::map properties_; - // This is to help the get_prop_name() method work. - std::vector property_table_; + // Map properrty names to property table index. + std::map properties_; + // Vector of properties. + struct prop_t { + perm_string name; + ivl_type_s* type; + }; + std::vector property_table_; }; #endif diff --git a/netlist.h b/netlist.h index a45b7a08a..edb2b9448 100644 --- a/netlist.h +++ b/netlist.h @@ -3941,7 +3941,7 @@ class NetEProperty : public NetExpr { ~NetEProperty(); inline const NetNet* get_sig() const { return net_; } - inline const char* get_pname() const { return pname_.str(); } + inline size_t property_idx() const { return pidx_; } virtual void expr_scan(struct expr_scan_t*) const; virtual NetEProperty* dup_expr() const; @@ -3951,7 +3951,7 @@ class NetEProperty : public NetExpr { private: NetNet*net_; - perm_string pname_; + size_t pidx_; }; /* diff --git a/sv_vpi_user.h b/sv_vpi_user.h index d2fdd90c6..ccdc21be5 100644 --- a/sv_vpi_user.h +++ b/sv_vpi_user.h @@ -57,6 +57,8 @@ EXTERN_C_START #define vpiEnumTypespec 633 #define vpiEnumConst 634 +#define vpiClassDefn 652 + /********* One-to-One ***********/ #define vpiBaseTypespec 703 diff --git a/t-dll-api.cc b/t-dll-api.cc index ae8a9f850..52060e793 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -430,7 +430,11 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net) return net->u_.signal_.sig->name_; case IVL_EX_PROPERTY: - return net->u_.property_.pname; + { ivl_signal_t sig = ivl_expr_signal(net); + ivl_type_t use_type = ivl_signal_net_type(sig); + unsigned idx = ivl_expr_property_idx(net); + return ivl_type_prop_name(use_type, idx); + } default: assert(0); @@ -598,6 +602,13 @@ extern "C" ivl_event_t ivl_expr_event(ivl_expr_t net) return net->u_.event_.event; } +extern "C" int ivl_expr_property_idx(ivl_expr_t net) +{ + assert(net); + assert(net->type_ == IVL_EX_PROPERTY); + return net->u_.property_.prop_idx; +} + extern "C" ivl_scope_t ivl_expr_scope(ivl_expr_t net) { assert(net); @@ -1561,13 +1572,10 @@ extern "C" unsigned ivl_lval_width(ivl_lval_t net) return net->width_; } -extern "C" const char* ivl_lval_property(ivl_lval_t net) +extern "C" int ivl_lval_property_idx(ivl_lval_t net) { assert(net); - if (net->property.nil()) - return 0; - else - return net->property.str(); + return net->property_idx; } extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net) @@ -2864,7 +2872,7 @@ extern "C" const char* ivl_type_name(ivl_type_t net) return 0; } -extern "C" unsigned ivl_type_properties(ivl_type_t net) +extern "C" int ivl_type_properties(ivl_type_t net) { const netclass_t*class_type = dynamic_cast(net); assert(class_type); @@ -2872,15 +2880,16 @@ extern "C" unsigned ivl_type_properties(ivl_type_t net) return class_type->get_properties(); } -extern "C" const char* ivl_type_prop_name(ivl_type_t net, unsigned idx) +extern "C" const char* ivl_type_prop_name(ivl_type_t net, int idx) { + if (idx < 0) return 0; const netclass_t*class_type = dynamic_cast(net); assert(class_type); return class_type->get_prop_name(idx); } -extern "C" ivl_type_t ivl_type_prop_type(ivl_type_t net, unsigned idx) +extern "C" ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx) { const netclass_t*class_type = dynamic_cast(net); assert(class_type); diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 4d0f90b28..8809dd177 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -24,6 +24,7 @@ # include # include "t-dll.h" # include "netlist.h" +# include "netclass.h" # include # include # include "ivl_alloc.h" @@ -362,7 +363,7 @@ void dll_target::expr_property(const NetEProperty*net) expr_->value_ = net->expr_type(); expr_->net_type= net->net_type(); expr_->u_.property_.sig = find_signal(des_, net->get_sig()); - expr_->u_.property_.pname = net->get_pname(); + expr_->u_.property_.prop_idx = net->property_idx(); } void dll_target::expr_event(const NetEEvent*net) diff --git a/t-dll-proc.cc b/t-dll-proc.cc index e217afe62..0cf6fe8bb 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -27,6 +27,7 @@ # include "ivl_target.h" # include "compiler.h" # include "t-dll.h" +# include "netclass.h" # include # include "ivl_alloc.h" @@ -162,7 +163,6 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net) } cur->width_ = asn->lwidth(); - cur->property = asn->get_property(); if (asn->sig()) { cur->type_ = IVL_LVAL_REG; @@ -180,6 +180,14 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net) 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 (cur->n.sig->net_type); + cur->property_idx = use_type->property_idx_from_name(pname); + } + } else { assert(0); } diff --git a/t-dll.h b/t-dll.h index 56413b408..1c017f5ae 100644 --- a/t-dll.h +++ b/t-dll.h @@ -328,7 +328,7 @@ struct ivl_expr_s { struct { ivl_signal_t sig; - const char*pname; + unsigned prop_idx; } property_; } u_; }; @@ -451,7 +451,7 @@ struct ivl_lval_s { ivl_expr_t idx; unsigned width_; unsigned type_ : 8; - perm_string property; + int property_idx; union { ivl_signal_t sig; ivl_memory_t mem; diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 51688fa20..c1415f243 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -210,8 +210,8 @@ static void show_property_expression(ivl_expr_t net, unsigned ind) ivl_signal_t sig = ivl_expr_signal(net); const char* pnam = ivl_expr_name(net); - fprintf(out, "%*s%s%s\n", ind, "", - ivl_signal_basename(sig), pnam); + fprintf(out, "%*s\n", ind, "", + ivl_signal_basename(sig), pnam, ivl_expr_width(net)); if (ivl_signal_data_type(sig) != IVL_VT_CLASS) { fprintf(out, "%*sERROR: Property signal must be IVL_VT_CLASS, got %s.\n", ind+3, "", data_type_string(ivl_signal_data_type(sig))); diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 5b8486c26..ea020b6f0 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -60,12 +60,12 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind) static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind) { ivl_signal_t sig = ivl_lval_sig(lval); - const char*sig_prop = ivl_lval_property(lval); + int sig_prop = ivl_lval_property_idx(lval); assert(sig); /* If there is no property select, then this l-value is for the class handle itself. */ - if (sig_prop == 0) { + if (sig_prop < 0) { fprintf(out, "%*s{name=%s class object}\n", ind, "", ivl_signal_name(sig)); if (ivl_lval_width(lval) != 1) { fprintf(out, "%*sERROR: ivl_lval_width should be 1 for class objects\n", @@ -75,7 +75,7 @@ static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind) return ivl_lval_width(lval); } - fprintf(out, "%*s{name=%s%s l-value width=%u}\n", + fprintf(out, "%*s{name=%s. l-value width=%u}\n", ind, "", ivl_signal_name(sig), sig_prop, ivl_lval_width(lval)); return ivl_lval_width(lval); diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index a8f979b0f..0aee3a915 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -47,7 +47,8 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@ CFLAGS = @WARNING_FLAGS@ @CFLAGS@ LDFLAGS = @LDFLAGS@ -O = vvp.o draw_enum.o draw_mux.o draw_net_input.o draw_switch.o draw_ufunc.o draw_vpi.o \ +O = vvp.o draw_class.o draw_enum.o draw_mux.o draw_net_input.o \ + draw_switch.o draw_ufunc.o draw_vpi.o \ eval_bool.o eval_expr.o eval_object.o eval_real.o eval_string.o \ modpath.o stmt_assign.o vector.o \ vvp_process.o vvp_scope.o diff --git a/tgt-vvp/draw_class.c b/tgt-vvp/draw_class.c new file mode 100644 index 000000000..a4d6b6894 --- /dev/null +++ b/tgt-vvp/draw_class.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +# include "vvp_priv.h" +# include +# include +# include +# include + +static void show_prop_type(ivl_type_t ptype) +{ + // XXXX: For now, assume all properties are 32bit integers. + fprintf(vvp_out, "\"b32\""); +} + +void draw_class_in_scope(ivl_type_t classtype) +{ + int idx; + fprintf(vvp_out, "C%p .class \"%s\" [%d]\n", + classtype, ivl_type_name(classtype), ivl_type_properties(classtype)); + + for (idx = 0 ; idx < ivl_type_properties(classtype) ; idx += 1) { + fprintf(vvp_out, " %3d: \"%s\", ", idx, ivl_type_prop_name(classtype,idx)); + show_prop_type(ivl_type_prop_type(classtype,idx)); + fprintf(vvp_out, "\n"); + } + + fprintf(vvp_out, " ;\n"); +} diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index f56c80c15..f965a75f8 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -2108,6 +2108,23 @@ static struct vector_info draw_number_expr(ivl_expr_t expr, unsigned wid) return res; } +static struct vector_info draw_property_expr(ivl_expr_t expr, unsigned wid) +{ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned pidx = ivl_expr_property_idx(expr); + + struct vector_info res; + res.base = allocate_vector(wid); + res.wid = wid; + + assert(res.base != 0); + + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + fprintf(vvp_out, " %%prop/v %u, %u, %u;\n", pidx, res.base, wid); + + return res; +} + /* * This little helper function generates the instructions to pad a * vector in place. It is assumed that the calling function has set up @@ -3641,6 +3658,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t expr, unsigned wid, res = draw_number_expr(expr, wid); break; + case IVL_EX_PROPERTY: + res = draw_property_expr(expr, wid); + break; + case IVL_EX_REALNUM: res = draw_realnum_expr(expr, wid); break; diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 8013a165b..e2b2acb80 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -69,7 +69,8 @@ static int eval_darray_new(ivl_expr_t ex) static int eval_class_new(ivl_expr_t ex) { - fprintf(vvp_out, " %%new/cobj ; XXXX Need to specify the type?\n"); + ivl_type_t class_type = ivl_expr_net_type(ex); + fprintf(vvp_out, " %%new/cobj C%p;\n", class_type); return 0; } diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 08ec69360..8ac438195 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -826,10 +826,32 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) int errors = 0; ivl_lval_t lval = ivl_stmt_lval(net, 0); ivl_expr_t rval = ivl_stmt_rval(net); - ivl_signal_t var= ivl_lval_sig(lval); + ivl_signal_t sig= ivl_lval_sig(lval); + + int prop_idx = ivl_lval_property_idx(lval); + + if (prop_idx >= 0) { + ivl_type_t sig_type = ivl_signal_net_type(sig); + ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); + assert(ivl_type_base(prop_type) == IVL_VT_BOOL); + assert(ivl_type_packed_dimensions(prop_type) == 1); + assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); + int wid = ivl_type_packed_msb(prop_type,0) - ivl_type_packed_lsb(prop_type,0) + 1; + + struct vector_info val = draw_eval_expr_wid(rval, wid, STUFF_OK_XZ); + + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + fprintf(vvp_out, " %%store/prop/v %d, %u, %u;\n", prop_idx, val.base, val.wid); + clr_vector(val); + + } else { + /* There is no property select, so evaluate the r-value + as an object and assign the entire object to the + variable. */ + errors += draw_eval_object(rval); + fprintf(vvp_out, " %%store/obj v%p_0;\n", sig); + } - errors += draw_eval_object(rval); - fprintf(vvp_out, " %%store/obj v%p_0;\n", var); return errors; } diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 01752a110..3c4800fe2 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -131,6 +131,8 @@ extern struct vector_info draw_vpi_func_call(ivl_expr_t expr, unsigned wid); extern void draw_vpi_rfunc_call(ivl_expr_t expr); +extern void draw_class_in_scope(ivl_type_t classtype); + /* * Enumeration draw routine. */ diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 6ef92f2d7..04bada083 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -2228,6 +2228,11 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) } } + for (idx = 0 ; idx < ivl_scope_classes(net) ; idx += 1) { + ivl_type_t class_type = ivl_scope_class(net,idx); + draw_class_in_scope(class_type); + } + /* Scan the scope for enumeration types, and write out enumeration typespecs. */ diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 4c3860dba..b9e260adb 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -72,7 +72,7 @@ V = vpi_modules.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \ vpip_to_dec.o vpip_format.o vvp_vpi.o O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \ - concat.o dff.o enum_type.o extend.o file_line.o npmos.o part.o \ + concat.o dff.o class_type.o enum_type.o extend.o file_line.o npmos.o part.o \ permaheap.o reduce.o resolv.o \ sfunc.o stop.o symbols.o ufunc.o codes.o vthread.o schedule.o \ statistics.o tables.o udp.o vvp_island.o vvp_net.o vvp_net_sig.o \ diff --git a/vvp/class_type.cc b/vvp/class_type.cc new file mode 100644 index 000000000..6770e6715 --- /dev/null +++ b/vvp/class_type.cc @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "class_type.h" +# include "compile.h" +# include "vpi_priv.h" +# include + +using namespace std; + +class_type::class_type(const string&nam, size_t nprop) +: class_name_(nam), properties_(nprop) +{ +} + +void class_type::set_property(size_t idx, const string&name) +{ + assert(idx < properties_.size()); + properties_[idx].name = name; +} + +int class_type::get_type_code(void) const +{ + return vpiClassDefn; +} + +static class_type*compile_class = 0; + +void compile_class_start(char*lab, char*nam, unsigned ntype) +{ + assert(compile_class == 0); + compile_class = new class_type(nam, ntype); + compile_vpi_symbol(lab, compile_class); + delete[]lab; + delete[]nam; +} + +void compile_class_property(unsigned idx, char*nam, char*typ) +{ + assert(compile_class); + compile_class->set_property(idx, nam); +} + +void compile_class_done(void) +{ + struct __vpiScope*scope = vpip_peek_current_scope(); + assert(scope); + scope->classes[compile_class->class_name()] = compile_class; + compile_class = 0; +} + diff --git a/vvp/class_type.h b/vvp/class_type.h new file mode 100644 index 000000000..5a27e5407 --- /dev/null +++ b/vvp/class_type.h @@ -0,0 +1,57 @@ +#ifndef __class_type_H +#define __class_type_H +/* + * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include +# include +# include "vpi_priv.h" + +/* + * This represents the TYPE information for a class. A %new operator + * uses this information to figure out how to construct an actual + * instance. + */ +class class_type : public __vpiHandle { + + public: + explicit class_type(const std::string&nam, size_t nprop); + + // This is the name of the class type. + inline const std::string&class_name(void) const { return class_name_; } + // Number of properties in the class definition. + inline size_t property_count(void) const { return properties_.size(); } + + // Set the details about the property. This is used during + // parse of the .vvp file to fill in the details of the + // property for the class definition. + void set_property(size_t idx, const std::string&name); + + int get_type_code(void) const; + + private: + std::string class_name_; + + struct prop_t { + std::string name; + }; + std::vector properties_; +}; + +#endif diff --git a/vvp/codes.h b/vvp/codes.h index 3a5fd0938..7d3194f76 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -163,6 +163,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_V(vthread_t thr, vvp_code_t code); extern bool of_PUSHI_STR(vthread_t thr, vvp_code_t code); extern bool of_PUSHI_REAL(vthread_t thr, vvp_code_t code); extern bool of_PUSHV_STR(vthread_t thr, vvp_code_t code); @@ -181,6 +182,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_V(vthread_t thr, vvp_code_t code); extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code); extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code); extern bool of_STORE_STR(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 2b1f20194..529a521ef 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -197,8 +197,8 @@ static const struct opcode_table_s opcode_table[] = { { "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%new/cobj", of_NEW_COBJ, 0, {OA_NONE,OA_NONE, OA_NONE} }, - { "%new/darray",of_NEW_DARRAY,2, {OA_BIT1,OA_STRING, OA_NONE} }, + { "%new/cobj", of_NEW_COBJ, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} }, + { "%new/darray",of_NEW_DARRAY,2, {OA_BIT1, OA_STRING,OA_NONE} }, { "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -211,6 +211,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/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pushi/real",of_PUSHI_REAL,2,{OA_BIT1, OA_BIT2, OA_NONE} }, { "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} }, { "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} }, @@ -227,10 +228,11 @@ static const struct opcode_table_s opcode_table[] = { { "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} }, { "%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/real", of_STORE_REAL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, - { "%store/reala",of_STORE_REALA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} }, - { "%store/str", of_STORE_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/prop/v",of_STORE_PROP_V,3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, + { "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, diff --git a/vvp/compile.h b/vvp/compile.h index 4044a2977..a84fba741 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -522,4 +522,8 @@ extern void compile_island_tranvp(char*island, char*ba, char*bb, extern void delete_udp_symbols(void); +extern void compile_class_start(char*lab, char*nam, unsigned nprop); +extern void compile_class_property(unsigned idx, char*nam, char*typ); +extern void compile_class_done(void); + #endif diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 4d0b4578b..710ae1edd 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -129,6 +129,7 @@ static char* strdupnew(char const *str) ".cast/int" { return K_CAST_INT; } ".cast/real" { return K_CAST_REAL; } ".cast/real.s" { return K_CAST_REAL_S; } +".class" { return K_CLASS; } ".cmp/eeq" { return K_CMP_EEQ; } ".cmp/eq" { return K_CMP_EQ; } ".cmp/eq.r" { return K_CMP_EQ_R; } diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 5b074b917..450b6a8fe 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -638,6 +638,15 @@ the object handle stack. See also %store/obj. +* %load/prop/v , , + +This instruction loads from a class object property into the specified +thread register bit. The is the number of the property and the + 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 The %load/real instruction reads a real value from the vpi-like object @@ -779,6 +788,11 @@ means the following: otherwise x +* %new/cobj