diff --git a/PExpr.h b/PExpr.h index e2365c897..1a0d41f5f 100644 --- a/PExpr.h +++ b/PExpr.h @@ -312,6 +312,8 @@ class PEIdent : public PExpr { NetScope*scope, bool is_force) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; virtual NetExpr*elaborate_expr(Design*des, NetScope*, unsigned expr_wid, unsigned flags) const; diff --git a/elab_expr.cc b/elab_expr.cc index 0b302525c..b8c9dab7e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2501,6 +2501,52 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) return expr_width_; } + +NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, + ivl_type_t ntype, unsigned) const +{ + NetNet* net = 0; + const NetExpr*par = 0; + NetEvent* eve = 0; + const NetExpr*ex1, *ex2; + + NetScope*found_in = symbol_search(this, des, scope, path_, + net, par, eve, + ex1, ex2); + + if (net == 0) { + cerr << get_fileline() << ": internal error: " + << "Expecting idents wtih ntype to be signals." << endl; + des->errors += 1; + return 0; + } + + if (net->net_type() != ntype) { + cerr << get_fileline() << ": internal_error: " + << "net type doesn't match context type." << endl; + + cerr << get_fileline() << ": : " + << "net type="; + if (net->net_type()) + net->net_type()->debug_dump(cerr); + else + cerr << ""; + cerr << endl; + + cerr << get_fileline() << ": : " + << "context type="; + ivl_assert(*this, ntype); + ntype->debug_dump(cerr); + cerr << endl; + } + ivl_assert(*this, net->net_type() == ntype); + + NetESignal*tmp = new NetESignal(net); + tmp->set_line(*this); + + return tmp; +} + /* * Elaborate an identifier in an expression. The identifier can be a * parameter name, a signal name or a memory name. It can also be a diff --git a/elaborate.cc b/elaborate.cc index 076260c0b..c618f7d5a 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -36,6 +36,8 @@ # include "PSpec.h" # include "netlist.h" # include "netvector.h" +# include "netdarray.h" +# include "netclass.h" # include "netmisc.h" # include "util.h" # include "parse_api.h" @@ -2377,20 +2379,18 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const delay = elaborate_delay_expr(delay_, des, scope); NetExpr*rv; - if (lv->more==0 && dynamic_cast (rval())) { - /* Special case: The l-value is a single signal, and the - r-value expression is a "new" expression. The l-value - has a new form of type, and the PENew expression - requires the extra information that it contains. So - handle it with this code instead. */ - rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + const ivl_type_s*lv_net_type = lv->net_type(); - } else if (lv->more==0 && dynamic_cast (rval())) { - rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + /* 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. */ + if (dynamic_cast (lv_net_type)) { + ivl_assert(*this, lv->more==0); + rv = elaborate_rval_(des, scope, lv_net_type); - } else if (lv->more==0 && dynamic_cast (rval())) { - - rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + } else if (dynamic_cast (lv_net_type)) { + ivl_assert(*this, lv->more==0); + rv = elaborate_rval_(des, scope, lv_net_type); } else { /* Elaborate the r-value expression, then try to evaluate it. */ diff --git a/net_assign.cc b/net_assign.cc index aface2b08..1ef7cc204 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -20,6 +20,7 @@ # include "config.h" # include "netlist.h" +# include "netclass.h" # include "netdarray.h" /* @@ -107,6 +108,21 @@ ivl_variable_type_t NetAssign_::expr_type() const return sig_->data_type(); } +const ivl_type_s* NetAssign_::net_type() const +{ + if (dynamic_cast (sig_->net_type())) + return sig_->net_type(); + + if (dynamic_cast (sig_->net_type())) { + if (word_ == 0) + return sig_->net_type(); + + return 0; + } + + return 0; +} + netenum_t*NetAssign_::enumeration() const { netenum_t*tmp = 0; diff --git a/netlist.h b/netlist.h index 51be20e33..4e13d849b 100644 --- a/netlist.h +++ b/netlist.h @@ -2453,6 +2453,11 @@ class NetAssign_ { unsigned lwidth() const; ivl_variable_type_t expr_type() const; + // Get the expression type of the l-value. This may be + // different from the type of the contained signal if for + // example a darray is indexed. + const ivl_type_s* net_type() const; + // Return the enumeration type of this l-value, or nil if it's // not an enumeration. netenum_t*enumeration() const; diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index d5a40ec28..8013a165b 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -79,6 +79,13 @@ static int eval_object_null(ivl_expr_t ex) return 0; } +static int eval_object_signal(ivl_expr_t ex) +{ + ivl_signal_t sig = ivl_expr_signal(ex); + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + return 0; +} + int draw_eval_object(ivl_expr_t ex) { switch (ivl_expr_type(ex)) { @@ -90,7 +97,7 @@ int draw_eval_object(ivl_expr_t ex) case IVL_VT_DARRAY: return eval_darray_new(ex); default: - fprintf(vvp_out, "; ERROR: Invalid type (%d) for \n", + fprintf(vvp_out, "; ERROR: draw_eval_object: Invalid type (%d) for \n", ivl_expr_value(ex)); return 0; } @@ -98,8 +105,11 @@ int draw_eval_object(ivl_expr_t ex) case IVL_EX_NULL: return eval_object_null(ex); + case IVL_EX_SIGNAL: + return eval_object_signal(ex); + default: - fprintf(vvp_out, "; ERROR: Invalid expression type %u\n", ivl_expr_type(ex)); + fprintf(vvp_out, "; ERROR: draw_eval_object: Invalid expression type %u\n", ivl_expr_type(ex)); return 1; } diff --git a/vvp/codes.h b/vvp/codes.h index 21e27a178..3a5fd0938 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -130,6 +130,7 @@ extern bool of_LOAD_DAR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_REAL(vthread_t thr, vvp_code_t code); extern bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t code); extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code); +extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code); extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index e0bd89529..2b1f20194 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -177,6 +177,7 @@ static const struct opcode_table_s opcode_table[] = { { "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/dar/r", of_LOAD_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE}}, { "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} }, { "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 28326dab8..5b074b917 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -630,6 +630,14 @@ The dar/r variant reads a real-value into a real-valued register. (See also %set/dar) +* %load/obj + +This instruction loads an object handle and pushes it to the top of +the object handle stack. + +See also %store/obj. + + * %load/real The %load/real instruction reads a real value from the vpi-like object @@ -979,6 +987,8 @@ For a negative shift %shiftr/i0 will pad the value with 'bx. This pops the top of the object stack and writes it to the object variable given by the label. +See also %load/obj. + * %store/real * %store/reala diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 3092a0b1a..7924a1ce7 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -3382,6 +3382,21 @@ bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t cp) return true; } +/* + * %load/obj + */ +bool of_LOAD_OBJ(vthread_t thr, vvp_code_t cp) +{ + vvp_net_t*net = cp->net; + vvp_fun_signal_object*fun = dynamic_cast (net->fun); + assert(fun); + + vvp_object_t val = fun->get_object(); + thr->push_object(val); + + return true; +} + /* * %load/real */