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,
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;

View File

@ -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 << "<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
* parameter name, a signal name or a memory name. It can also be a

View File

@ -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<const PENew*> (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<const PENull*> (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<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())) {
rv = elaborate_rval_(des, scope, lv->sig()->net_type());
} else if (dynamic_cast<const netdarray_t*> (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. */

View File

@ -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<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*tmp = 0;

View File

@ -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;

View File

@ -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 <new>\n",
fprintf(vvp_out, "; ERROR: draw_eval_object: Invalid type (%d) for <new>\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;
}

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_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);

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/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} },

View File

@ -630,6 +630,14 @@ The dar/r variant reads a real-value into a real-valued register.
(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>
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 <var-label>
* %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;
}
/*
* %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>
*/