Handle class-type identifier expressions.

This commit is contained in:
Stephen Williams 2012-11-22 11:08:13 -08:00
parent 79903ecadd
commit f7033ca19a
10 changed files with 120 additions and 14 deletions

View File

@ -312,6 +312,8 @@ class PEIdent : public PExpr {
NetScope*scope, NetScope*scope,
bool is_force) const; 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*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned expr_wid,
unsigned flags) const; unsigned flags) const;

View File

@ -2501,6 +2501,52 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
return expr_width_; 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 << "<nil>";
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 * 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 * parameter name, a signal name or a memory name. It can also be a

View File

@ -36,6 +36,8 @@
# include "PSpec.h" # include "PSpec.h"
# include "netlist.h" # include "netlist.h"
# include "netvector.h" # include "netvector.h"
# include "netdarray.h"
# include "netclass.h"
# include "netmisc.h" # include "netmisc.h"
# include "util.h" # include "util.h"
# include "parse_api.h" # include "parse_api.h"
@ -2377,20 +2379,18 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
delay = elaborate_delay_expr(delay_, des, scope); delay = elaborate_delay_expr(delay_, des, scope);
NetExpr*rv; NetExpr*rv;
if (lv->more==0 && dynamic_cast<const PENew*> (rval())) { const ivl_type_s*lv_net_type = lv->net_type();
/* 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());
} else if (lv->more==0 && dynamic_cast<const PENull*> (rval())) { /* If the l-value is a compound type of some sort, then use
rv = elaborate_rval_(des, scope, lv->sig()->net_type()); the newer net_type form of the elaborate_rval_ method to
handle the new types. */
if (dynamic_cast<const netclass_t*> (lv_net_type)) {
ivl_assert(*this, lv->more==0);
rv = elaborate_rval_(des, scope, lv_net_type);
} else if (lv->more==0 && dynamic_cast<const PENewClass*> (rval())) { } else if (dynamic_cast<const netdarray_t*> (lv_net_type)) {
ivl_assert(*this, lv->more==0);
rv = elaborate_rval_(des, scope, lv->sig()->net_type()); rv = elaborate_rval_(des, scope, lv_net_type);
} else { } else {
/* Elaborate the r-value expression, then try to evaluate it. */ /* Elaborate the r-value expression, then try to evaluate it. */

View File

@ -20,6 +20,7 @@
# include "config.h" # include "config.h"
# include "netlist.h" # include "netlist.h"
# include "netclass.h"
# include "netdarray.h" # include "netdarray.h"
/* /*
@ -107,6 +108,21 @@ ivl_variable_type_t NetAssign_::expr_type() const
return sig_->data_type(); return sig_->data_type();
} }
const ivl_type_s* NetAssign_::net_type() const
{
if (dynamic_cast<const netclass_t*> (sig_->net_type()))
return sig_->net_type();
if (dynamic_cast<const netdarray_t*> (sig_->net_type())) {
if (word_ == 0)
return sig_->net_type();
return 0;
}
return 0;
}
netenum_t*NetAssign_::enumeration() const netenum_t*NetAssign_::enumeration() const
{ {
netenum_t*tmp = 0; netenum_t*tmp = 0;

View File

@ -2453,6 +2453,11 @@ class NetAssign_ {
unsigned lwidth() const; unsigned lwidth() const;
ivl_variable_type_t expr_type() 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 // Return the enumeration type of this l-value, or nil if it's
// not an enumeration. // not an enumeration.
netenum_t*enumeration() const; netenum_t*enumeration() const;

View File

@ -79,6 +79,13 @@ static int eval_object_null(ivl_expr_t ex)
return 0; 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) int draw_eval_object(ivl_expr_t ex)
{ {
switch (ivl_expr_type(ex)) { switch (ivl_expr_type(ex)) {
@ -90,7 +97,7 @@ int draw_eval_object(ivl_expr_t ex)
case IVL_VT_DARRAY: case IVL_VT_DARRAY:
return eval_darray_new(ex); return eval_darray_new(ex);
default: default:
fprintf(vvp_out, "; ERROR: Invalid type (%d) for <new>\n", fprintf(vvp_out, "; ERROR: draw_eval_object: Invalid type (%d) for <new>\n",
ivl_expr_value(ex)); ivl_expr_value(ex));
return 0; return 0;
} }
@ -98,8 +105,11 @@ int draw_eval_object(ivl_expr_t ex)
case IVL_EX_NULL: case IVL_EX_NULL:
return eval_object_null(ex); return eval_object_null(ex);
case IVL_EX_SIGNAL:
return eval_object_signal(ex);
default: 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; return 1;
} }

View File

@ -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_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_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_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_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(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); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);

View File

@ -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",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/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/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/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/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} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },

View File

@ -630,6 +630,14 @@ The dar/r variant reads a real-value into a real-valued register.
(See also %set/dar) (See also %set/dar)
* %load/obj <var-label>
This instruction loads an object handle and pushes it to the top of
the object handle stack.
See also %store/obj.
* %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
@ -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 This pops the top of the object stack and writes it to the object
variable given by the label. variable given by the label.
See also %load/obj.
* %store/real <var-label> * %store/real <var-label>
* %store/reala <var-label> <index> * %store/reala <var-label> <index>

View File

@ -3382,6 +3382,21 @@ bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %load/obj <var-label>
*/
bool of_LOAD_OBJ(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(fun);
vvp_object_t val = fun->get_object();
thr->push_object(val);
return true;
}
/* /*
* %load/real <var-label> * %load/real <var-label>
*/ */