From a2d980540dd34121dbe57db55541f32d1b05026a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 30 Sep 2012 18:03:10 -0700 Subject: [PATCH] Get some type information to the "new" expression for darrays. --- PExpr.h | 9 +++++++++ Statement.h | 1 + elab_expr.cc | 28 ++++++++++++++++++++++++++++ elaborate.cc | 26 ++++++++++++++++++++++++-- ivl_target.h | 6 ++++++ net_expr.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ netlist.cc | 19 ------------------- netlist.h | 9 +++++++++ t-dll-api.cc | 5 +++++ t-dll-expr.cc | 19 +++++++++++++++++++ t-dll.h | 1 + tgt-vvp/eval_object.c | 18 ++++++++++++++++-- vvp/vthread.cc | 12 +++++++++++- vvp/vvp_object.cc | 27 ++++++++++++++++++--------- 14 files changed, 190 insertions(+), 33 deletions(-) diff --git a/PExpr.h b/PExpr.h index d52fa7c1f..ebd530314 100644 --- a/PExpr.h +++ b/PExpr.h @@ -121,6 +121,13 @@ class PExpr : public LineInfo { // to be propagated down to any context-dependant operands. void cast_signed(bool flag) { signed_flag_ = flag; } + // This is the more generic form of the elaborate_expr method + // below. The plan is to replace the simpler elaborate_expr + // method with this version, which can handle more advanced + // types. But for now, this is only implemented in special cases. + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; + // Procedural elaboration of the expression. The expr_width is // the required width of the expression. // @@ -450,6 +457,8 @@ class PENew : public PExpr { virtual void dump(ostream&) const; virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode); + 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/Statement.h b/Statement.h index 2e6a96dde..87b747222 100644 --- a/Statement.h +++ b/Statement.h @@ -106,6 +106,7 @@ class PAssign_ : public Statement { NetAssign_* elaborate_lval(Design*, NetScope*scope) const; NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width, ivl_variable_type_t type) const; + NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const; NetExpr* elaborate_rval_obj_(Design*, NetScope*, ivl_variable_type_t type) const; diff --git a/elab_expr.cc b/elab_expr.cc index 631891647..5af8443ec 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -131,6 +131,17 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&) return 1; } +NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, ivl_type_t, unsigned) const +{ + cerr << get_fileline() << ": internal error: I do not know how to" + << " elaborate (ivl_type_t) this expression. " << endl; + cerr << get_fileline() << ": : Expression is: " << *this + << endl; + des->errors += 1; + return 0; +} + + NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const { cerr << get_fileline() << ": internal error: I do not know how to" @@ -3979,6 +3990,23 @@ unsigned PENew::test_width(Design*, NetScope*, width_mode_t&) return 1; } +NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, + ivl_type_t ntype, unsigned flags) const +{ + // Elaborate the size expression. + width_mode_t mode = LOSSLESS; + unsigned use_wid = size_->test_width(des, scope, mode); + NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags); + + NetESFunc*tmp = new NetESFunc("$ivl_darray_method$new", ntype, 1); + tmp->set_line(*this); + tmp->parm(0, size); + return tmp; +} + +/* + * This method should never actually be called. + */ NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, unsigned, unsigned flags) const { diff --git a/elaborate.cc b/elaborate.cc index 770193866..320aa0af8 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2194,6 +2194,17 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const return lval_->elaborate_lval(des, scope, false); } +NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, + ivl_type_t net_type) const +{ + ivl_assert(*this, rval_); + + NetExpr*rv = rval_->elaborate_expr(des, scope, net_type, 0); + + ivl_assert(*this, !is_constant_); + return rv; +} + NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, unsigned lv_width, ivl_variable_type_t lv_type) const @@ -2365,9 +2376,20 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const if (delay_ != 0) 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()); + + } else { + /* Elaborate the r-value expression, then try to evaluate it. */ + rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); + } - /* Elaborate the r-value expression, then try to evaluate it. */ - NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); if (rv == 0) return 0; assert(rv); diff --git a/ivl_target.h b/ivl_target.h index b8ff60c57..be25028be 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -764,6 +764,11 @@ extern unsigned ivl_event_lineno(ivl_event_t net); * Get the data type of the expression node. This uses the variable * type enum to express the type of the expression node. * + * ivl_expr_net_type + * This is used in some cases to carry more advanced type + * descriptions. Over the long run, all type informatino will be + * moved into the ivl_type_t type description method. + * * ivl_expr_width * This method returns the bit width of the expression at this * node. It can be applied to any expression node, and returns the @@ -841,6 +846,7 @@ extern unsigned ivl_event_lineno(ivl_event_t net); */ extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net); +extern ivl_type_t ivl_expr_net_type(ivl_expr_t net); extern ivl_variable_type_t ivl_expr_value(ivl_expr_t net); extern const char*ivl_expr_file(ivl_expr_t net); extern unsigned ivl_expr_lineno(ivl_expr_t net); diff --git a/net_expr.cc b/net_expr.cc index 76d1fba0e..76fa2caff 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -20,9 +20,40 @@ # include "config.h" # include "netlist.h" # include "netenum.h" +# include "netdarray.h" # include "compiler.h" # include "netmisc.h" # include +# include "ivl_assert.h" + +NetExpr::NetExpr(unsigned w) +: net_type_(0), width_(w), signed_flag_(false) +{ +} + +NetExpr::NetExpr(ivl_type_t t) +: net_type_(t), width_(0), signed_flag_(false) +{ +} + +NetExpr::~NetExpr() +{ +} + +ivl_type_t NetExpr::net_type() const +{ + return net_type_; +} + +void NetExpr::cast_signed(bool flag) +{ + cast_signed_base_(flag); +} + +bool NetExpr::has_width() const +{ + return true; +} /* * the grand default data type is a logic vector. @@ -330,6 +361,18 @@ NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t, expr_width(width); } +NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np) +: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np) +{ + name_ = lex_strings.add(n); + expr_width(rtype->packed_width()); + // FIXME: For now, assume that all uses of this constructor + // are for the IVL_VT_DARRAY type. Eventually, the type_ + // member will go away. + ivl_assert(*this, dynamic_cast(rtype)); + type_ = IVL_VT_DARRAY; +} + NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np) : name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np) { diff --git a/netlist.cc b/netlist.cc index bdf9fe5c8..a7f407540 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2229,25 +2229,6 @@ const NetScope* NetFree::scope() const return scope_; } -NetExpr::NetExpr(unsigned w) -: width_(w), signed_flag_(false) -{ -} - -NetExpr::~NetExpr() -{ -} - -void NetExpr::cast_signed(bool flag) -{ - cast_signed_base_(flag); -} - -bool NetExpr::has_width() const -{ - return true; -} - /* * Create a bitwise operator node from the opcode and the left and * right expressions. diff --git a/netlist.h b/netlist.h index 0728a228a..b0d58b54b 100644 --- a/netlist.h +++ b/netlist.h @@ -1739,11 +1739,18 @@ class NetTran : public NetNode, public IslandBranch { class NetExpr : public LineInfo { public: explicit NetExpr(unsigned w =0); + explicit NetExpr(ivl_type_t t); virtual ~NetExpr() =0; virtual void expr_scan(struct expr_scan_t*) const =0; virtual void dump(ostream&) const; + // This is the advanced description of the type. I think I + // want to replace the other type description members with + // this single method. The default for this method returns + // nil. + ivl_type_t net_type() const; + // Expressions have type. virtual ivl_variable_type_t expr_type() const; @@ -1812,6 +1819,7 @@ class NetExpr : public LineInfo { void cast_signed_base_(bool flag) { signed_flag_ = flag; } private: + ivl_type_t net_type_; unsigned width_; bool signed_flag_; @@ -3892,6 +3900,7 @@ class NetESFunc : public NetExpr { public: NetESFunc(const char*name, ivl_variable_type_t t, unsigned width, unsigned nprms); + NetESFunc(const char*name, ivl_type_t rtype, unsigned nprms); NetESFunc(const char*name, netenum_t*enum_type, unsigned nprms); ~NetESFunc(); diff --git a/t-dll-api.cc b/t-dll-api.cc index b1f0c51fe..592aa59a0 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -413,6 +413,11 @@ extern "C" ivl_enumtype_t ivl_expr_enumtype(ivl_expr_t net) return net->u_.enumtype_.type; } +extern "C" ivl_type_t ivl_expr_net_type(ivl_expr_t net) +{ + return net->net_type; +} + extern "C" const char* ivl_expr_name(ivl_expr_t net) { switch (net->type_) { diff --git a/t-dll-expr.cc b/t-dll-expr.cc index c5aaf1cb2..1ec966637 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -56,6 +56,7 @@ void dll_target::sub_off_from_expr_(long off) ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmpc->type_ = IVL_EX_NUMBER; tmpc->value_ = IVL_VT_VECTOR; + tmpc->net_type= 0; tmpc->width_ = expr_->width_; tmpc->signed_ = expr_->signed_; tmpc->sized_ = 1; @@ -71,6 +72,7 @@ void dll_target::sub_off_from_expr_(long off) ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmps->type_ = IVL_EX_BINARY; tmps->value_ = IVL_VT_VECTOR; + tmps->net_type= 0; tmps->width_ = tmpc->width_; tmps->signed_ = tmpc->signed_; tmps->sized_ = 1; @@ -90,6 +92,7 @@ void dll_target::mul_expr_by_const_(long val) ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmpc->type_ = IVL_EX_NUMBER; tmpc->value_ = IVL_VT_VECTOR; + tmpc->net_type= 0; tmpc->width_ = expr_->width_; tmpc->signed_ = expr_->signed_; tmpc->sized_ = 1; @@ -105,6 +108,7 @@ void dll_target::mul_expr_by_const_(long val) ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmps->type_ = IVL_EX_BINARY; tmps->value_ = IVL_VT_VECTOR; + tmpc->net_type= 0; tmps->width_ = tmpc->width_; tmps->signed_ = tmpc->signed_; tmps->sized_ = 1; @@ -124,6 +128,7 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val) char*bits; expr->type_ = IVL_EX_NUMBER; expr->value_= IVL_VT_VECTOR; + expr->net_type=0; expr->width_= val.len(); expr->signed_ = val.has_sign()? 1 : 0; expr->sized_= 1; @@ -158,6 +163,7 @@ void dll_target::expr_access_func(const NetEAccess*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->type_ = IVL_EX_BACCESS; expr_->value_ = IVL_VT_REAL; + expr_->net_type=0; expr_->width_ = 1; expr_->signed_= 1; expr_->sized_ = 1; @@ -182,6 +188,7 @@ void dll_target::expr_binary(const NetEBinary*net) expr_->type_ = IVL_EX_BINARY; expr_->value_= get_expr_type(net); + expr_->net_type=0; expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; expr_->sized_= 1; @@ -201,6 +208,7 @@ void dll_target::expr_concat(const NetEConcat*net) cur->type_ = IVL_EX_CONCAT; cur->value_ = net->expr_type(); + cur->net_type=0; cur->width_ = net->expr_width(); cur->signed_ = net->has_sign() ? 1 : 0; cur->sized_ = 1; @@ -226,6 +234,7 @@ void dll_target::expr_const(const NetEConst*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->value_= net->expr_type(); + expr_->net_type=0; FILE_NAME(expr_, net); if (net->value().is_string()) { @@ -303,6 +312,7 @@ void dll_target::expr_creal(const NetECReal*net) expr_->type_ = IVL_EX_REALNUM; FILE_NAME(expr_, net); expr_->value_= IVL_VT_REAL; + expr_->net_type=0; expr_->u_.real_.value = net->value().as_double(); } @@ -315,6 +325,7 @@ void dll_target::expr_event(const NetEEvent*net) expr_->type_ = IVL_EX_EVENT; FILE_NAME(expr_, net); expr_->value_= IVL_VT_VOID; + expr_->net_type=0; /* Locate the event by name. Save the ivl_event_t in the expression so that the generator can find it easily. */ @@ -339,6 +350,7 @@ void dll_target::expr_scope(const NetEScope*net) expr_->type_ = IVL_EX_SCOPE; FILE_NAME(expr_, net); expr_->value_= IVL_VT_VOID; + expr_->net_type=0; expr_->u_.scope_.scope = lookup_scope_(net->scope()); } @@ -351,6 +363,7 @@ void dll_target::expr_netenum(const NetENetenum*net) expr_->type_ = IVL_EX_ENUMTYPE; FILE_NAME(expr_, net); expr_->value_= IVL_VT_VOID; + expr_->net_type=0; expr_->u_.enumtype_.type = net->netenum(); } @@ -371,6 +384,7 @@ void dll_target::expr_select(const NetESelect*net) expr_->type_ = IVL_EX_SELECT; expr_->value_= IVL_VT_VECTOR; + expr_->net_type=0; expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; expr_->sized_= 1; @@ -390,6 +404,7 @@ void dll_target::expr_sfunc(const NetESFunc*net) expr->type_ = IVL_EX_SFUNC; FILE_NAME(expr, net); expr->value_= net->expr_type(); + expr->net_type=net->net_type(); expr->width_= net->expr_width(); expr->signed_ = net->has_sign()? 1 : 0; expr->sized_= 1; @@ -420,6 +435,7 @@ void dll_target::expr_ternary(const NetETernary*net) expr->type_ = IVL_EX_TERNARY; expr->value_= net->expr_type(); + expr->net_type=0; expr->width_ = net->expr_width(); expr->signed_ = net->has_sign()? 1 : 0; expr->sized_ = 1; @@ -461,6 +477,7 @@ void dll_target::expr_signal(const NetESignal*net) expr_->type_ = IVL_EX_SIGNAL; expr_->value_= net->expr_type(); + expr_->net_type=0; expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; expr_->sized_= 1; @@ -488,6 +505,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net) expr->type_ = IVL_EX_UFUNC; expr->value_= net->expr_type(); + expr->net_type=0; expr->width_= net->expr_width(); expr->signed_ = net->has_sign()? 1 : 0; expr->sized_= 1; @@ -523,6 +541,7 @@ void dll_target::expr_unary(const NetEUnary*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->type_ = IVL_EX_UNARY; expr_->value_= net->expr_type(); + expr_->net_type=0; expr_->width_ = net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; expr_->sized_ = 1; diff --git a/t-dll.h b/t-dll.h index 79177ca26..b622c576b 100644 --- a/t-dll.h +++ b/t-dll.h @@ -218,6 +218,7 @@ struct ivl_event_s { struct ivl_expr_s { ivl_expr_type_t type_; ivl_variable_type_t value_; + ivl_type_t net_type; perm_string file; unsigned lineno; diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 4a0938968..f0e05b956 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -28,8 +28,22 @@ static int eval_darray_new(ivl_expr_t ex) draw_eval_expr_into_integer(size_expr, size_reg); clr_word(size_reg); - // XXXX: Assume elements are 32bit integers. - fprintf(vvp_out, " %%new/darray %u, \"sb32\";\n", size_reg); + // The new function has a net_type that contains the details + // of the type. + ivl_type_t net_type = ivl_expr_net_type(ex); + assert(net_type); + + ivl_type_t element_type = ivl_type_element(net_type); + assert(element_type); + + assert(ivl_type_packed_dimensions(element_type) == 1); + int msb = ivl_type_packed_msb(element_type, 0); + int lsb = ivl_type_packed_lsb(element_type, 0); + int wid = msb>=lsb? msb - lsb : lsb - msb; + wid += 1; + + // XXXX: Assume elements are signed integers. + fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid); return 0; } diff --git a/vvp/vthread.cc b/vvp/vthread.cc index a6b7939bc..d7c08f8e4 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -3957,7 +3957,17 @@ bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp) size_t size = thr->words[cp->bit_idx[0]].w_int; vvp_object_t obj; - if (strcmp(text,"sb32") == 0) { + if (strcmp(text,"b8") == 0) { + obj = new vvp_darray_atom(size); + } else if (strcmp(text,"b16") == 0) { + obj = new vvp_darray_atom(size); + } else if (strcmp(text,"b32") == 0) { + obj = new vvp_darray_atom(size); + } else if (strcmp(text,"sb8") == 0) { + obj = new vvp_darray_atom(size); + } else if (strcmp(text,"sb16") == 0) { + obj = new vvp_darray_atom(size); + } else if (strcmp(text,"sb32") == 0) { obj = new vvp_darray_atom(size); } else { obj = new vvp_darray (size); diff --git a/vvp/vvp_object.cc b/vvp/vvp_object.cc index 8d7d76128..1fcb1ebed 100644 --- a/vvp/vvp_object.cc +++ b/vvp/vvp_object.cc @@ -32,7 +32,7 @@ vvp_darray::~vvp_darray() { } -void vvp_darray::set_word(unsigned adr, const vvp_vector4_t&) +void vvp_darray::set_word(unsigned, const vvp_vector4_t&) { cerr << "XXXX set_word not implemented for " << typeid(*this).name() << endl; } @@ -42,29 +42,38 @@ void vvp_darray::get_word(unsigned, vvp_vector4_t&) cerr << "XXXX get_word not implemented for " << typeid(*this).name() << endl; } -template <> vvp_darray_atom::~vvp_darray_atom() +template vvp_darray_atom::~vvp_darray_atom() { } -template <> void vvp_darray_atom::set_word(unsigned adr, const vvp_vector4_t&value) +template void vvp_darray_atom::set_word(unsigned adr, const vvp_vector4_t&value) { if (adr >= array_.size()) return; - vector4_to_value(value, array_[adr], true, false); + int32_t tmp; + vector4_to_value(value, tmp, true, false); + array_[adr] = tmp; } -template <> void vvp_darray_atom::get_word(unsigned adr, vvp_vector4_t&value) +template void vvp_darray_atom::get_word(unsigned adr, vvp_vector4_t&value) { if (adr >= array_.size()) { - value = vvp_vector4_t(32, BIT4_X); + value = vvp_vector4_t(8*sizeof(TYPE), BIT4_X); return; } - uint32_t word = array_[adr]; - vvp_vector4_t tmp (32, BIT4_0); - for (unsigned idx = 0 ; idx < 32 ; idx += 1) { + TYPE word = array_[adr]; + vvp_vector4_t tmp (8*sizeof(TYPE), BIT4_0); + for (unsigned idx = 0 ; idx < tmp.size() ; idx += 1) { if (word&1) tmp.set_bit(idx, BIT4_1); word >>= 1; } value = tmp; } + +template class vvp_darray_atom; +template class vvp_darray_atom; +template class vvp_darray_atom; +template class vvp_darray_atom; +template class vvp_darray_atom; +template class vvp_darray_atom;