diff --git a/Makefile.in b/Makefile.in index 93263909a..77eb2d52a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -108,8 +108,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \ net_design.o netdarray.o \ - netenum.o netstruct.o net_event.o net_expr.o net_func.o net_func_eval.o \ - net_link.o net_modulo.o \ + netenum.o netparray.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \ + net_func_eval.o net_link.o net_modulo.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \ pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \ 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/design_dump.cc b/design_dump.cc index af1483e65..3e14e52b8 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -29,6 +29,7 @@ # include "compiler.h" # include "discipline.h" # include "netdarray.h" +# include "netvector.h" # include "ivl_assert.h" # include "PExpr.h" @@ -140,6 +141,24 @@ ostream& operator << (ostream&o, ivl_switch_type_t val) return o; } +ostream& ivl_type_s::debug_dump(ostream&o) const +{ + o << typeid(*this).name(); + return o; +} + +ostream& netdarray_t::debug_dump(ostream&o) const +{ + o << "dynamic array of " << *element_type(); + return o; +} + +ostream& netvector_t::debug_dump(ostream&o) const +{ + o << type_ << (signed_? " signed" : " unsigned") << packed_dims_; + return o; +} + static inline void dump_scope_path(ostream&o, const NetScope*scope) { const NetScope*parent = scope->parent(); @@ -230,14 +249,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const { o << setw(ind) << "" << type() << ": " << name() << unpacked_dims_ << " unpacked dims=" << unpacked_dimensions(); - if (!packed_dims_.empty()) - o << " packed dims=" << packed_dims_; o << " pin_count=" << pin_count(); if (local_flag_) o << " (local)"; - o << " " << data_type_; - if (signed_) - o << " signed"; switch (port_type_) { case NetNet::NOT_A_PORT: break; @@ -261,14 +275,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const if (ivl_discipline_t dis = get_discipline()) o << " discipline=" << dis->name(); - if (netdarray_t*darray = darray_type()) - o << " dynamic array of " << darray->data_type(); - - if (! packed_dims_.empty()) - o << " packed dims: " << packed_dims_; - - if (net_type_) - o << " net_type_=" << typeid(*net_type_).name(); + if (net_type_) o << " " << *net_type_; o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")"; if (scope()) @@ -1098,7 +1105,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const if (result_sig_) { o << setw(ind+2) << "" << "Return signal: "; if (result_sig_->get_signed()) o << "+"; - o << result_sig_->name() << result_sig_->packed_dims() << endl; + o << result_sig_->name() << endl; } o << setw(ind+2) << "" << "Arguments: "; if (port_count() == 0) o << ""; @@ -1120,7 +1127,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const break; } if (port(idx)->get_signed()) o << "+"; - o << port(idx)->name() << port(idx)->packed_dims() << endl; + o << port(idx)->name() << endl; } if (statement_) statement_->dump(o, ind+2); @@ -1520,7 +1527,14 @@ void NetESelect::dump(ostream&o) const else o << "(0)"; - o << "+:" << expr_width() << "]>"; + o << "+:" << expr_width() << "]"; + if (ivl_type_t nt = net_type()) { + o << " net_type=(" << *nt << ")"; + } else { + o << " expr_type=" << expr_type(); + } + + o << ">"; } void NetESFunc::dump(ostream&o) const @@ -1539,7 +1553,8 @@ void NetESignal::dump(ostream&o) const o << "+"; o << name(); if (word_) o << "[word=" << *word_ << "]"; - o << sig()->packed_dims(); + vectortmp = net_->net_type()->slice_dimensions(); + o << tmp; } void NetETernary::dump(ostream&o) const diff --git a/elab_expr.cc b/elab_expr.cc index d377e3b61..5af8443ec 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -27,6 +27,7 @@ # include "pform.h" # include "netlist.h" # include "netenum.h" +# include "netvector.h" # include "discipline.h" # include "netmisc.h" # include "netdarray.h" @@ -130,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" @@ -1480,7 +1492,7 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li, perm_string method_name, unsigned long&off) { - netstruct_t*type = net->struct_type(); + const netstruct_t*type = net->struct_type(); ivl_assert(*li, type); if (! type->packed()) { @@ -2354,8 +2366,8 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) if (netdarray_t*darray = net? net->darray_type() : 0) { if (use_sel == index_component_t::SEL_BIT) { - expr_type_ = darray->data_type(); - expr_width_ = darray->vector_width(); + expr_type_ = darray->element_base_type(); + expr_width_ = darray->element_width(); min_width_ = expr_width_; signed_flag_ = net->get_signed(); } else { @@ -2382,6 +2394,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) expr_width_ = net->vector_width(); min_width_ = expr_width_; signed_flag_ = net->get_signed(); + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::test_width: " + << net->name() << " is a net, width=" << expr_width_ << endl; + } return expr_width_; } @@ -3550,7 +3566,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope, long lsv = base_c->value().as_long(); long offset = 0; // Get the signal range. - const list&packed = net->sig()->packed_dims(); + const vector&packed = net->sig()->packed_dims(); ivl_assert(*this, packed.size() == prefix_indices.size()+1); // We want the last range, which is where we work. @@ -3744,7 +3760,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, cerr << get_fileline() << ": debug: " << "Bit select of a dynamic array becomes NetESelect." << endl; } - NetESelect*res = new NetESelect(net, mux, darray->vector_width()); + NetESelect*res = new NetESelect(net, mux, darray->element_width()); res->set_line(*net); return res; } @@ -3779,7 +3795,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, long msv = msc->value().as_long(); - const list& sig_packed = net->sig()->packed_dims(); + const vector& sig_packed = net->sig()->packed_dims(); if (prefix_indices.size()+2 <= sig_packed.size()) { // Special case: this is a slice of a multi-dimensional // packed array. For example: @@ -3872,7 +3888,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, return res; } - const list& sig_packed = net->sig()->packed_dims(); + const vector& sig_packed = net->sig()->packed_dims(); if (prefix_indices.size()+2 <= sig_packed.size()) { // Special case: this is a slice of a multi-dimensional // packed array. For example: @@ -3965,7 +3981,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope, return node; } -unsigned PENew::test_width(Design*des, NetScope*, width_mode_t&) +unsigned PENew::test_width(Design*, NetScope*, width_mode_t&) { expr_type_ = IVL_VT_DARRAY; expr_width_ = 1; @@ -3974,6 +3990,23 @@ unsigned PENew::test_width(Design*des, 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 { @@ -4503,9 +4536,9 @@ NetNet* Design::find_discipline_reference(ivl_discipline_t dis, NetScope*scope) if (gnd) return gnd; string name = string(dis->name()) + "$gnd"; - gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, 1); + netvector_t*gnd_vec = new netvector_t(IVL_VT_REAL,0,0); + gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, gnd_vec); gnd->set_discipline(dis); - gnd->data_type(IVL_VT_REAL); discipline_references_[dis->name()] = gnd; if (debug_elaborate) diff --git a/elab_lval.cc b/elab_lval.cc index 2db622e9c..d5119e0fc 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -507,7 +507,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des, NetNet*reg = lv->sig(); ivl_assert(*this, reg); - const list&packed = reg->packed_dims(); + const vector&packed = reg->packed_dims(); // Part selects cannot select slices. So there must be enough // prefix_indices to get all the way to the final dimension. @@ -596,7 +596,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des, long lsv = base_c->value().as_long(); long offset = 0; // Get the signal range. - const list&packed = reg->packed_dims(); + const vector&packed = reg->packed_dims(); ivl_assert(*this, packed.size() == prefix_indices.size()+1); // We want the last range, which is where we work. @@ -680,7 +680,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, NetNet*reg = lv->sig(); ivl_assert(*this, reg); - netstruct_t*struct_type = reg->struct_type(); + const netstruct_t*struct_type = reg->struct_type(); ivl_assert(*this, struct_type); if (debug_elaborate) { diff --git a/elab_net.cc b/elab_net.cc index ba1b68316..abd98a62e 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -24,6 +24,7 @@ # include "netlist.h" # include "netmisc.h" # include "netstruct.h" +# include "netvector.h" # include "compiler.h" # include @@ -98,12 +99,12 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, concat operator from most significant to least significant, which is the order they are given in the concat list. */ + netvector_t*tmp2_vec = new netvector_t(nets[0]->data_type(),width-1,0); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, width); + NetNet::IMPLICIT, tmp2_vec); /* Assume that the data types of the nets are all the same, so we can take the data type of any, the first will do. */ - osig->data_type(nets[0]->data_type()); osig->local_flag(true); osig->set_line(*this); @@ -154,8 +155,6 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, assert(width == 0); } - osig->data_type(nets[0]->data_type()); - osig->local_flag(true); return osig; } @@ -431,11 +430,18 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, remove the member and store it into method_name, and retry the search with "a.b". */ if (sig == 0 && path_.size() >= 2) { + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + "Symbol not found, try again with path_prefix=" << path_prefix + << " and method_name=" << path_tail.name << endl; + } method_name = path_tail.name; symbol_search(this, des, scope, path_prefix, sig, par, eve); // Whoops, not a struct signal, so give up on this avenue. if (sig && sig->struct_type() == 0) { + cerr << get_fileline() << ": XXXXX: sig=" << sig->name() + << " is found, but not a struct with member " << method_name << endl; method_name = perm_string(); sig = 0; } @@ -475,7 +481,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, list unpacked_indices_const; - netstruct_t*struct_type = 0; + const netstruct_t*struct_type = 0; if ((struct_type = sig->struct_type()) && !method_name.nil()) { // Detect the variable is a structure and there was a @@ -655,11 +661,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, return 0; } + netvector_t*tmp2_vec = new netvector_t(sig->data_type(), + sig->vector_width()-1,0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - sig->type(), sig->vector_width()); + sig->type(), tmp2_vec); tmp->set_line(*this); tmp->local_flag(true); - tmp->data_type( sig->data_type() ); connect(sig->pin(widx), tmp->pin(0)); sig = tmp; } @@ -683,10 +690,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, << " wid=" << subnet_wid <<"]" << endl; + netvector_t*tmp2_vec = new netvector_t(sig->data_type(), + subnet_wid-1,0); NetNet*subsig = new NetNet(sig->scope(), sig->scope()->local_symbol(), - NetNet::WIRE, subnet_wid); - subsig->data_type( sig->data_type() ); + NetNet::WIRE, tmp2_vec); subsig->local_flag(true); subsig->set_line(*this); @@ -800,10 +808,10 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const unsigned swid = abs(midx - lidx) + 1; ivl_assert(*this, swid > 0 && swid < sig->vector_width()); + netvector_t*tmp2_vec = new netvector_t(sig->data_type(),swid-1,0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, swid); + NetNet::WIRE, tmp2_vec); tmp->port_type(sig->port_type()); - tmp->data_type(sig->data_type()); tmp->set_line(*this); tmp->local_flag(true); NetNode*ps = 0; diff --git a/elab_sig.cc b/elab_sig.cc index 5eb3915a2..9cc281518 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -36,6 +36,7 @@ # include "netmisc.h" # include "netenum.h" # include "netstruct.h" +# include "netvector.h" # include "netdarray.h" # include "netparray.h" # include "util.h" @@ -485,6 +486,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const } NetNet*ret_sig = 0; + netvector_t*ret_vec = 0; /* Create the signals/variables of the return value and write them into the function scope. */ @@ -520,50 +522,51 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const des->errors += 1; } - list packed; + vector packed; packed.push_back(netrange_t(mnum, lnum)); - ret_sig = new NetNet(scope, fname, NetNet::REG, packed); - ret_sig->set_scalar(false); + ret_vec = new netvector_t(packed, IVL_VT_LOGIC); + ret_vec->set_signed(return_type_.type == PTF_REG_S); + ret_vec->set_scalar(false); + ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec); } else { - ret_sig = new NetNet(scope, fname, NetNet::REG); - ret_sig->set_scalar(true); + ret_vec = new netvector_t(IVL_VT_LOGIC); + ret_vec->set_signed(return_type_.type == PTF_REG_S); + ret_vec->set_scalar(true); + ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec); } ret_sig->set_line(*this); - ret_sig->set_signed(return_type_.type == PTF_REG_S); ret_sig->port_type(NetNet::POUTPUT); - ret_sig->data_type(IVL_VT_LOGIC); break; case PTF_INTEGER: - ret_sig = new NetNet(scope, fname, NetNet::REG, integer_width); + ret_vec = new netvector_t(IVL_VT_LOGIC, integer_width-1,0); + ret_vec->set_signed(true); + ret_vec->set_isint(true); + ret_vec->set_scalar(false); + ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec); ret_sig->set_line(*this); - ret_sig->set_signed(true); - ret_sig->set_isint(true); - ret_sig->set_scalar(false); ret_sig->port_type(NetNet::POUTPUT); - ret_sig->data_type(IVL_VT_LOGIC); break; case PTF_TIME: - ret_sig = new NetNet(scope, fname, NetNet::REG, 64); + ret_vec = new netvector_t(IVL_VT_LOGIC, 64-1,0); + ret_vec->set_isint(false); + ret_vec->set_scalar(false); + ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec); ret_sig->set_line(*this); - ret_sig->set_signed(false); - ret_sig->set_isint(false); - ret_sig->set_scalar(false); ret_sig->port_type(NetNet::POUTPUT); - ret_sig->data_type(IVL_VT_LOGIC); break; case PTF_REAL: case PTF_REALTIME: - ret_sig = new NetNet(scope, fname, NetNet::REG, 1); + ret_vec = new netvector_t(IVL_VT_REAL); + ret_vec->set_signed(true); + ret_vec->set_isint(false); + ret_vec->set_scalar(true); + ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec); ret_sig->set_line(*this); - ret_sig->set_signed(true); - ret_sig->set_isint(false); - ret_sig->set_scalar(true); ret_sig->port_type(NetNet::POUTPUT); - ret_sig->data_type(IVL_VT_REAL); break; case PTF_ATOM2: @@ -598,13 +601,13 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const use_wid = mnum - lnum + 1; } - ret_sig = new NetNet(scope, fname, NetNet::REG, use_wid); + ret_vec = new netvector_t(IVL_VT_BOOL, use_wid-1, 0); + ret_vec->set_isint(true); + ret_vec->set_scalar(false); + ret_vec->set_signed(return_type_.type == PTF_ATOM2_S? true : false); + ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec); ret_sig->set_line(*this); - ret_sig->set_signed(return_type_.type == PTF_ATOM2_S? true : false); - ret_sig->set_isint(true); - ret_sig->set_scalar(false); ret_sig->port_type(NetNet::POUTPUT); - ret_sig->data_type(IVL_VT_BOOL); break; case PTF_STRING: @@ -820,7 +823,7 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const } static bool evaluate_ranges(Design*des, NetScope*scope, - list&llist, + vector&llist, const list&rlist) { bool bad_msb = false, bad_lsb = false; @@ -871,7 +874,7 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, for (list::iterator cur = struct_type->members->begin() ; cur != struct_type->members->end() ; ++ cur) { - listpacked_dimensions; + vectorpacked_dimensions; struct_member_t*curp = *cur; if (curp->range.get() && ! curp->range->empty()) { @@ -897,22 +900,8 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, return res; } -static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, - parray_type_t*data_type) -{ - - listpacked_dimensions; - bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims); - ivl_assert(*data_type, !bad_range); - - netparray_t*res = new netparray_t(packed_dimensions); - //res->set_line(*data_type); - - return res; -} - -static nettype_base_t*elaborate_type(Design*des, NetScope*scope, - data_type_t*pform_type) +static ivl_type_s*elaborate_type(Design*des, NetScope*scope, + data_type_t*pform_type) { if (struct_type_t*struct_type = dynamic_cast(pform_type)) { netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type); @@ -926,13 +915,29 @@ static nettype_base_t*elaborate_type(Design*des, NetScope*scope, return 0; } -bool test_ranges_eeq(const list&lef, const list&rig) +static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, + parray_type_t*data_type) +{ + + vectorpacked_dimensions; + bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims); + ivl_assert(*data_type, !bad_range); + + ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type); + + netparray_t*res = new netparray_t(packed_dimensions, element_type); + //res->set_line(*data_type); + + return res; +} + +bool test_ranges_eeq(const vector&lef, const vector&rig) { if (lef.size() != rig.size()) return false; - list::const_iterator lcur = lef.begin(); - list::const_iterator rcur = rig.begin(); + vector::const_iterator lcur = lef.begin(); + vector::const_iterator rcur = rig.begin(); while (lcur != lef.end()) { if (lcur->get_msb() != rcur->get_msb()) return false; @@ -967,7 +972,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } unsigned wid = 1; - listpacked_dimensions; + vectorpacked_dimensions; des->errors += error_cnt_; @@ -1008,7 +1013,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const if (port_set_ || net_set_) { bool bad_range = false; - list plist, nlist; + vector plist, nlist; /* If they exist get the port definition MSB and LSB */ if (port_set_ && !port_.empty()) { bad_range |= evaluate_ranges(des, scope, plist, port_); @@ -1095,9 +1100,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const // dimensions, then turn this into a dynamic array and // put all the packed dimensions there. if (use_lidx==0 && use_ridx==0) { - ivl_assert(*this, netarray==0); - netarray = new netdarray_t(packed_dimensions, data_type_, wid); + netvector_t*vec = new netvector_t(packed_dimensions, data_type_); packed_dimensions.clear(); + ivl_assert(*this, netarray==0); + netarray = new netdarray_t(vec); continue; } @@ -1218,7 +1224,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const << " and packed_width=" << use_enum->packed_width() << endl; } - sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum); + ivl_assert(*this, packed_dimensions.empty()); + sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum); } else if (netarray) { @@ -1252,14 +1259,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const << " in scope " << scope_path(scope) << endl; } - nettype_base_t*base_type = elaborate_type(des, scope, parray_type->base_type); -#if 0 - cerr << get_fileline() << ": sorry: Packed array of " - << typeid(*parray_type->base_type).name() - << " not supported." << endl; - des->errors += 1; -#endif - sig = new NetNet(scope, name_, wtype, use_type->packed_dimensions(), unpacked_dimensions, base_type); + sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type); } else { @@ -1272,29 +1272,30 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const cerr << " in scope " << scope_path(scope) << endl; } - sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions); + ivl_variable_type_t use_data_type = data_type_; + if (use_data_type == IVL_VT_NO_TYPE) { + use_data_type = IVL_VT_LOGIC; + if (debug_elaborate) { + cerr << get_fileline() << ": debug: " + << "Signal " << name_ + << " in scope " << scope_path(scope) + << " defaults to data type " << use_data_type << endl; + } + } + + netvector_t*vec = new netvector_t(packed_dimensions, use_data_type); + vec->set_signed(get_signed()); + vec->set_isint(get_isint()); + if (is_implicit_scalar) vec->set_scalar(true); + else vec->set_scalar(get_scalar()); + packed_dimensions.clear(); + sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec); + } if (wtype == NetNet::WIRE) sig->devirtualize_pins(); - - ivl_variable_type_t use_data_type = data_type_; - if (use_data_type == IVL_VT_NO_TYPE) { - use_data_type = IVL_VT_LOGIC; - if (debug_elaborate) { - cerr << get_fileline() << ": debug: " - << "Signal " << name_ - << " in scope " << scope_path(scope) - << " defaults to data type " << use_data_type << endl; - } - } - - sig->data_type(use_data_type); sig->set_line(*this); sig->port_type(port_type_); - sig->set_signed(get_signed()); - sig->set_isint(get_isint()); - if (is_implicit_scalar) sig->set_scalar(true); - else sig->set_scalar(get_scalar()); if (ivl_discipline_t dis = get_discipline()) { sig->set_discipline(dis); diff --git a/elaborate.cc b/elaborate.cc index 60dc888da..0d8e10cf1 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -35,6 +35,7 @@ # include "PGenerate.h" # include "PSpec.h" # include "netlist.h" +# include "netvector.h" # include "netmisc.h" # include "util.h" # include "parse_api.h" @@ -75,8 +76,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const if (debug_elaborate) { cerr << get_fileline() << ": debug: PGAssign: elaborated l-value" - << " width=" << lval->vector_width() - << ", type=" << lval->data_type() << endl; + << " width=" << lval->vector_width() << endl; } NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->data_type(), @@ -115,7 +115,6 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const cerr << get_fileline() << ": debug: PGAssign: elaborated r-value" << " width="<< rval->vector_width() << ", type="<< rval->data_type() - << ", signed="<< rval->get_signed() << ", expr=" << *rval_expr << endl; } @@ -164,11 +163,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const NetPartSelect::VP); des->add_node(tmp); tmp->set_line(*this); + netvector_t*osig_vec = new netvector_t(rval->data_type(), + lval->vector_width()-1,0); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::TRI, lval->vector_width()); + NetNet::TRI, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(rval->data_type()); connect(osig->pin(0), tmp->pin(0)); rval = osig; need_driver_flag = false; @@ -190,10 +190,11 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const connect(rval->pin(0), driver->pin(1)); + netvector_t*tmp_vec = new netvector_t(rval->data_type(), + rval->vector_width()-1,0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, rval->vector_width()); + NetNet::WIRE, tmp_vec); tmp->set_line(*this); - tmp->data_type(rval->data_type()); tmp->local_flag(true); connect(driver->pin(0), tmp->pin(0)); @@ -868,10 +869,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const des->add_node(rep); connect(rep->pin(1), sig->pin(0)); + netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC, + instance_width-1,0); sig = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, instance_width); + NetNet::WIRE, osig_vec); sig->set_line(*this); - sig->data_type(IVL_VT_LOGIC); sig->local_flag(true); connect(rep->pin(0), sig->pin(0)); @@ -948,12 +950,12 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const unsigned dev = gdx*gate_count; connect(cur[dev+idx]->pin(0), cc->pin(gdx+1)); + netvector_t*tmp2_vec = new netvector_t(IVL_VT_LOGIC); NetNet*tmp2 = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, 1); + NetNet::WIRE, tmp2_vec); tmp2->set_line(*this); tmp2->local_flag(true); - tmp2->data_type(IVL_VT_LOGIC); connect(cc->pin(gdx+1), tmp2->pin(0)); } @@ -965,11 +967,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const tmp1->set_line(*this); des->add_node(tmp1); connect(tmp1->pin(1), sig->pin(0)); + netvector_t*tmp2_vec = new netvector_t(sig->data_type()); NetNet*tmp2 = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, 1); + NetNet::WIRE, tmp2_vec); tmp2->set_line(*this); tmp2->local_flag(true); - tmp2->data_type(sig->data_type()); connect(tmp1->pin(0), tmp2->pin(0)); unsigned use_idx = idx - gate_count + 1; unsigned dev = gdx*gate_count; @@ -996,8 +998,9 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope, ivl_assert(*this, dir != NetNet::NOT_A_PORT); ivl_assert(*this, dir != NetNet::PIMPLICIT); + netvector_t*tmp_type = new netvector_t(IVL_VT_LOGIC, port_wid-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, port_wid); + NetNet::WIRE, tmp_type); tmp->local_flag(true); tmp->set_line(*this); @@ -1415,6 +1418,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const << "too complicated for elaboration." << endl; continue; } + + if (debug_elaborate) { + cerr << get_fileline() << ": debug: " + << "Elaborating INPUT port expression: " << *tmp_expr << endl; + } + sig = tmp_expr->synthesize(des, scope, tmp_expr); if (sig == 0) { cerr << pins[idx]->get_fileline() @@ -1432,11 +1441,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const des->add_node(tmp); connect(tmp->pin(1), sig->pin(0)); + netvector_t*tmp2_vec = new netvector_t(sig->data_type(), + sig->vector_width()-1,0); NetNet*tmp2 = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, sig->vector_width()); + NetNet::WIRE, tmp2_vec); tmp2->local_flag(true); tmp2->set_line(*this); - tmp2->data_type(sig->data_type()); connect(tmp->pin(0), tmp2->pin(0)); sig = tmp2; } @@ -2184,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 @@ -2355,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); @@ -2382,11 +2414,11 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const if (delay || event_) { unsigned wid = count_lval_width(lv); + netvector_t*tmp2_vec = new netvector_t(rv->expr_type(),wid-1,0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::REG, wid); + NetNet::REG, tmp2_vec); tmp->local_flag(true); tmp->set_line(*this); - tmp->data_type(rv->expr_type()); NetESignal*sig = new NetESignal(tmp); @@ -2477,10 +2509,17 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) { if (debug_elaborate) - cerr << get_fileline() << ": debug: Cast expression to int2" << endl; + cerr << get_fileline() << ": debug: " + << "Cast expression to int2" << endl; rv = cast_to_int2(rv); } + if (lv->expr_type() == IVL_VT_REAL && rv->expr_type() != IVL_VT_REAL) { + if (debug_elaborate) + cerr << get_fileline() << ": debug: " + << "Cast expression to real." << endl; + rv = cast_to_real(rv); + } if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) { cerr << get_fileline() << ": error: " << "Enumeration type mismatch in assignment." << endl; diff --git a/eval_tree.cc b/eval_tree.cc index 12e5f0b35..d677e774d 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -53,6 +53,9 @@ static bool get_real_arg_(const NetExpr*expr, verireal&val) break; } + case IVL_VT_DARRAY: + return false; + default: assert(0); } diff --git a/expr_synth.cc b/expr_synth.cc index fa0a69f2c..9f5cc0e3f 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -24,6 +24,7 @@ # include # include "netlist.h" +# include "netvector.h" # include "netmisc.h" # include "ivl_assert.h" @@ -118,11 +119,11 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope, NetExpr*root) } perm_string path = lsig->scope()->local_symbol(); - NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); + osig_vec->set_signed(has_sign()); + NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(expr_type()); - osig->set_signed(has_sign()); perm_string oname = osig->scope()->local_symbol(); NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width); @@ -173,11 +174,11 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope, NetExpr*root) rsig = pad_to_width(des, rsig, width, *this); assert(lsig->vector_width() == rsig->vector_width()); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, width); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(expr_type()); perm_string oname = scope->local_symbol(); NetLogic*gate; @@ -243,11 +244,11 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) rsig = pad_to_width(des, rsig, width, *this); } + netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, 1); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(IVL_VT_LOGIC); // Test if the comparison is signed. // @@ -390,11 +391,11 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root) connect(powr->pin_DataA(), lsig->pin(0)); connect(powr->pin_DataB(), rsig->pin(0)); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); + osig_vec->set_signed(has_sign()); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, width); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); - osig->set_signed(has_sign()); osig->local_flag(true); connect(powr->pin_Result(), osig->pin(0)); @@ -427,11 +428,11 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root) connect(mult->pin_DataA(), lsig->pin(0)); connect(mult->pin_DataB(), rsig->pin(0)); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); + osig_vec->set_signed(has_sign()); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, width); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); - osig->set_signed(has_sign()); osig->local_flag(true); connect(mult->pin_Result(), osig->pin(0)); @@ -452,11 +453,11 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope, NetExpr*root) if (real_args) width = 1; else width = expr_width(); + netvector_t*osig_vec = new netvector_t(lsig->data_type(), width-1, 0); + osig_vec->set_signed(has_sign()); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, width); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(lsig->data_type()); - osig->set_signed(has_sign()); osig->local_flag(true); switch (op()) { @@ -530,10 +531,10 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root) return 0; } + netvector_t*osig_tmp = new netvector_t(expr_type()); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, 1); + NetNet::IMPLICIT, osig_tmp); osig->set_line(*this); - osig->data_type(expr_type()); osig->local_flag(true); NetLogic*olog; @@ -597,10 +598,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root) if (shift == 0) return lsig; + netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1,0); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, expr_width()); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); osig->local_flag(true); // ushift is the amount of pad created by the shift. @@ -618,10 +619,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root) psel->set_line(*this); des->add_node(psel); + netvector_t*psig_vec = new netvector_t(expr_type(), part_width-1, 0); NetNet*psig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, part_width); + NetNet::IMPLICIT, psig_vec); psig->set_line(*this); - psig->data_type(expr_type()); psig->local_flag(true); connect(psig->pin(0), psel->pin(0)); @@ -646,10 +647,11 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root) znum); des->add_node(zcon); + netvector_t*zsig_vec = new netvector_t(osig->data_type(), + znum.len()-1, 0); NetNet*zsig = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, znum.len()); + NetNet::WIRE, zsig_vec); zsig->set_line(*this); - zsig->data_type(osig->data_type()); zsig->local_flag(true); connect(zcon->pin(0), zsig->pin(0)); @@ -676,10 +678,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root) if (rsig == 0) return 0; + netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1, 0); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, expr_width()); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); osig->local_flag(true); NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(), @@ -739,10 +741,10 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root) /* Make a NetNet object to carry the output vector. */ perm_string path = scope->local_symbol(); - NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width()); + netvector_t*osig_vec = new netvector_t(data_type, expr_width()-1, 0); + NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(data_type); NetConcat*concat = new NetConcat(scope, scope->local_symbol(), osig->vector_width(), @@ -785,11 +787,11 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*) return 0; } - NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); + osig_vec->set_signed(has_sign()); + NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(expr_type()); - osig->set_signed(has_sign()); NetConst*con = new NetConst(scope, scope->local_symbol(), value()); con->set_line(*this); @@ -806,11 +808,11 @@ NetNet* NetECReal::synthesize(Design*des, NetScope*scope, NetExpr*) { perm_string path = scope->local_symbol(); - NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1); + netvector_t*osig_vec = new netvector_t(IVL_VT_REAL); + osig_vec->set_signed(has_sign()); + NetNet*osig = new NetNet(scope, path, NetNet::WIRE, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(IVL_VT_REAL); - osig->set_signed(has_sign()); NetLiteral*con = new NetLiteral(scope, scope->local_symbol(), value_); con->set_line(*this); @@ -839,10 +841,10 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope, NetExpr*root) } unsigned width = isig->vector_width(); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, width); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); osig->local_flag(true); perm_string oname = scope->local_symbol(); @@ -882,11 +884,12 @@ NetNet* NetEUnary::synthesize(Design*des, NetScope*scope, NetExpr*root) if (expr_->has_sign() == false) return sub; + netvector_t*sig_vec = new netvector_t(sub->data_type(), + sub->vector_width()-1, 0); NetNet*sig = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, sub->vector_width()); + NetNet::WIRE, sig_vec); sig->set_line(*this); sig->local_flag(true); - sig->data_type(sub->data_type()); NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width()); tmp->set_line(*this); @@ -956,10 +959,10 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope, NetExpr*root) gate->set_line(*this); des->add_node(gate); + netvector_t*osig_vec = new netvector_t(expr_type()); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, 1); + NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); osig->local_flag(true); connect(gate->pin(0), osig->pin(0)); @@ -1063,10 +1066,11 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) des->add_node(sel); ivl_assert(*this, select_width > 0); + netvector_t*tmp_vec = new netvector_t(sub->data_type(), + select_width-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, select_width); + NetNet::WIRE, tmp_vec); tmp->set_line(*this); - tmp->data_type(sub->data_type()); tmp->local_flag(true); connect(sel->pin(0), tmp->pin(0)); @@ -1090,10 +1094,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) connect(cat->pin(concat_count), above->pin(0)); } + tmp_vec = new netvector_t(sub->data_type(), expr_width()-1, 0); tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, expr_width()); + NetNet::WIRE, tmp_vec); tmp->set_line(*this); - tmp->data_type(sub->data_type()); tmp->local_flag(true); connect(cat->pin(0), tmp->pin(0)); } @@ -1111,9 +1115,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) sel->set_line(*this); des->add_node(sel); + netvector_t*tmp_vec = new netvector_t(sub->data_type(), + expr_width()-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, expr_width()); - tmp->data_type(sub->data_type()); + NetNet::IMPLICIT, tmp_vec); tmp->local_flag(true); tmp->set_line(*this); sub = tmp; @@ -1134,10 +1139,11 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) // extension or 0 extension, depending on the has_sign() mode // of the expression. + netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0); + net_vec->set_signed(has_sign()); NetNet*net = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, expr_width()); + NetNet::IMPLICIT, net_vec); net->set_line(*this); - net->data_type(expr_type()); net->local_flag(true); if (has_sign()) { NetSignExtend*pad = new NetSignExtend(scope, @@ -1148,7 +1154,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) connect(pad->pin(1), sub->pin(0)); connect(pad->pin(0), net->pin(0)); - net->set_signed(true); } else { @@ -1165,10 +1170,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) con->set_line(*this); des->add_node(con); + netvector_t*tmp_vec = new netvector_t(expr_type(), pad_width-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, pad_width); + NetNet::IMPLICIT, tmp_vec); tmp->set_line(*this); - tmp->data_type(expr_type()); tmp->local_flag(true); connect(tmp->pin(0), con->pin(0)); @@ -1220,9 +1225,9 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root) ivl_assert(*this, csig->vector_width() == 1); unsigned width=expr_width(); - NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width); + netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0); + NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, osig_vec); osig->set_line(*this); - osig->data_type(expr_type()); osig->local_flag(true); /* Make sure the types match. */ @@ -1265,11 +1270,12 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root) if (word_ == 0) return net_; + netvector_t*tmp_vec = new netvector_t(net_->data_type(), + net_->vector_width()-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, net_->vector_width()); + NetNet::IMPLICIT, tmp_vec); tmp->set_line(*this); tmp->local_flag(true); - tmp->data_type(net_->data_type()); // For NetExpr objects, the word index is already converted to // a canonical (lsb==0) address. Just use the index directly. @@ -1354,12 +1360,12 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) net->set_line(*this); des->add_node(net); + netvector_t*osig_vec = new netvector_t(def->type, def->wid-1, 0); + osig_vec->set_signed(def->type==IVL_VT_REAL? true : false); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, def->wid); + NetNet::WIRE, osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->set_signed(def->type==IVL_VT_REAL? true : false); - osig->data_type(def->type); connect(net->pin(0), osig->pin(0)); @@ -1422,11 +1428,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) des->add_node(net); /* Create an output signal and connect it to the function. */ + netvector_t*osig_vec = new netvector_t(result_sig_->expr_type(), + result_sig_->vector_width()-1, 0); NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE, - result_sig_->vector_width()); + osig_vec); osig->set_line(*this); osig->local_flag(true); - osig->data_type(result_sig_->expr_type()); connect(net->pin(0), osig->pin(0)); /* Connect the pins to the arguments. */ diff --git a/ivl_target.h b/ivl_target.h index ed63d5c62..be25028be 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -21,12 +21,19 @@ # include +/* Re the _CLASS define: clang++ wants this to be class to match the + * definition, but clang (the C) compiler needs it to be a struct + * since class is not defined in C. They are effecively both pointers + * to an object so everything works out. */ + #ifdef __cplusplus #define _BEGIN_DECL extern "C" { #define _END_DECL } +#define _CLASS class #else #define _BEGIN_DECL #define _END_DECL +#define _CLASS struct #endif #ifndef __GNUC__ @@ -157,21 +164,8 @@ typedef struct ivl_array_s *ivl_array_t; typedef struct ivl_branch_s *ivl_branch_t; typedef struct ivl_delaypath_s*ivl_delaypath_t; typedef struct ivl_design_s *ivl_design_t; -/* clang++ wants this to be class to match the definition, but clang - * (the C) compiler needs it to be a struct since class is not defined - * in C. They are effecively both pointers to an object so everything - * works out. */ -#ifdef __cplusplus -typedef class ivl_discipline_s*ivl_discipline_t; -#else -typedef struct ivl_discipline_s*ivl_discipline_t; -#endif -/* See the comments above. */ -#ifdef __cplusplus -typedef class netenum_t *ivl_enumtype_t; -#else -typedef struct netenum_t *ivl_enumtype_t; -#endif +typedef _CLASS ivl_discipline_s*ivl_discipline_t; +typedef _CLASS netenum_t *ivl_enumtype_t; typedef struct ivl_event_s *ivl_event_t; typedef struct ivl_expr_s *ivl_expr_t; typedef struct ivl_island_s *ivl_island_t; @@ -180,12 +174,7 @@ typedef struct ivl_lval_s *ivl_lval_t; typedef struct ivl_net_const_s*ivl_net_const_t; typedef struct ivl_net_logic_s*ivl_net_logic_t; typedef struct ivl_udp_s *ivl_udp_t; -/* See the comments above. */ -#ifdef __cplusplus -typedef class ivl_nature_s *ivl_nature_t; -#else -typedef struct ivl_nature_s *ivl_nature_t; -#endif +typedef _CLASS ivl_nature_s *ivl_nature_t; typedef struct ivl_net_probe_s*ivl_net_probe_t; typedef struct ivl_nexus_s *ivl_nexus_t; typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t; @@ -193,10 +182,11 @@ typedef struct ivl_parameter_s*ivl_parameter_t; typedef struct ivl_process_s *ivl_process_t; typedef struct ivl_scope_s *ivl_scope_t; typedef struct ivl_signal_s *ivl_signal_t; -typedef struct ivl_port_info_s *ivl_port_info_t; +typedef struct ivl_port_info_s*ivl_port_info_t; typedef struct ivl_switch_s *ivl_switch_t; typedef struct ivl_memory_s *ivl_memory_t; //XXXX __attribute__((deprecated)); typedef struct ivl_statement_s*ivl_statement_t; +typedef const _CLASS ivl_type_s*ivl_type_t; /* * These are types that are defined as enumerations. These have @@ -774,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 @@ -851,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); @@ -1907,6 +1903,7 @@ extern unsigned ivl_signal_npath(ivl_signal_t net); extern ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx); extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net); extern ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net); +extern ivl_type_t ivl_signal_net_type(ivl_signal_t net); extern const char* ivl_signal_name(ivl_signal_t net); extern const char* ivl_signal_basename(ivl_signal_t net); extern const char* ivl_signal_attr(ivl_signal_t net, const char*key); @@ -1994,7 +1991,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net); * Statements that have event arguments (TRIGGER and WAIT) make * those event objects available through these methods. * - * ivl_stmt_lval +* ivl_stmt_lval * ivl_stmt_lvals * Return the number of l-values for an assignment statement, or * the specific l-value. If there is more than 1 l-value, then the @@ -2195,6 +2192,25 @@ extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx); extern const char* ivl_switch_file(ivl_switch_t net); extern unsigned ivl_switch_lineno(ivl_switch_t net); +/* TYPES + * + * ivl_type_base + * This returns the base type for the type. See the + * ivl_variable_type_t definition for the various base types. + * + * ivl_type_element + * Return the type of the element of an array. This is only valid + * for array types. + * + * SEMANTIC NOTES + */ +extern ivl_variable_type_t ivl_type_base(ivl_type_t net); +extern ivl_type_t ivl_type_element(ivl_type_t net); +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); + + #if defined(__MINGW32__) || defined (__CYGWIN32__) # define DLLEXPORT __declspec(dllexport) #else diff --git a/net_assign.cc b/net_assign.cc index 2f5602a2a..aface2b08 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -89,7 +89,7 @@ unsigned NetAssign_::lwidth() const if (word_ == 0) return 1; else - return darray->vector_width(); + return darray->element_width(); } return lwid_; @@ -101,7 +101,7 @@ ivl_variable_type_t NetAssign_::expr_type() const if (word_ == 0) return IVL_VT_DARRAY; else - return darray->data_type(); + return darray->element_base_type(); } return sig_->data_type(); diff --git a/net_expr.cc b/net_expr.cc index 76d1fba0e..ab204a3e1 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. @@ -317,6 +348,32 @@ ivl_select_type_t NetESelect::select_type() const return sel_type_; } +ivl_variable_type_t NetESelect::expr_type() const +{ + ivl_variable_type_t type = expr_->expr_type(); + + // Special case: If the sub-expression is an IVL_VT_STRING, + // then this node is representing a character select. The + // width is the width of a byte, and the data type is BOOL. + if (type == IVL_VT_STRING && expr_width()==8) + return IVL_VT_BOOL; + + if (type != IVL_VT_DARRAY) + return type; + + ivl_assert(*this, type == IVL_VT_DARRAY); + + // Special case: If the expression is a DARRAY, then the + // sub-expression must be a NetESignal and the type of the + // NetESelect expression is the element type of the arrayed signal. + NetESignal*sig = dynamic_cast(expr_); + ivl_assert(*this, sig); + const netarray_t*array_type = dynamic_cast (sig->sig()->net_type()); + ivl_assert(*this, array_type); + + return array_type->element_type()->base_type(); +} + bool NetESelect::has_width() const { return true; @@ -330,6 +387,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/netdarray.cc b/netdarray.cc index 55a121cbd..b1845831a 100644 --- a/netdarray.cc +++ b/netdarray.cc @@ -21,12 +21,16 @@ using namespace std; -netdarray_t::netdarray_t(const std::list&packed, - ivl_variable_type_t type, unsigned long wid) -: packed_dims_(packed), type_(type), width_(wid) +netdarray_t::netdarray_t(ivl_type_t vec) +: netarray_t(vec) { } netdarray_t::~netdarray_t() { } + +ivl_variable_type_t netdarray_t::base_type(void) const +{ + return IVL_VT_DARRAY; +} diff --git a/netdarray.h b/netdarray.h index 568ea2696..8068896dd 100644 --- a/netdarray.h +++ b/netdarray.h @@ -21,23 +21,30 @@ # include "nettypes.h" # include "ivl_target.h" -# include -class netdarray_t : public nettype_base_t { +class netdarray_t : public netarray_t { public: - explicit netdarray_t(const std::list&packed, - ivl_variable_type_t type, - unsigned long wid); + explicit netdarray_t(ivl_type_t vec); ~netdarray_t(); - inline ivl_variable_type_t data_type() const { return type_; } - inline unsigned long vector_width(void) const { return width_; } + // This is the "base_type()" virtual method of the + // nettype_base_t. The ivl_target api expects this to return + // IVL_VT_DARRAY for dynamic arrays? + ivl_variable_type_t base_type() const; + + // This is the base_type() of the element of the array. We + // need this in some cases in order to get the base type of + // the element, and not the IVL_VT_DARRAY of the array itself. + inline ivl_variable_type_t element_base_type() const { return element_type()->base_type(); } + + // This is a convenience function for getting the width of an + // element. Strictly speaking it's not necessary. + inline unsigned long element_width(void) const { return element_type()->packed_width(); } + + std::ostream& debug_dump(std::ostream&) const; private: - std::list packed_dims_; - ivl_variable_type_t type_; - unsigned long width_; }; #endif diff --git a/netenum.cc b/netenum.cc index 238e00261..614a9618a 100644 --- a/netenum.cc +++ b/netenum.cc @@ -21,6 +21,8 @@ # include "compiler.h" # include +using namespace std; + netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, long msb, long lsb, size_t name_count) : base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb), @@ -32,6 +34,11 @@ netenum_t::~netenum_t() { } +bool netenum_t::get_signed() const +{ + return signed_flag_; +} + long netenum_t::packed_width() const { if (msb_ >= lsb_) @@ -40,6 +47,14 @@ long netenum_t::packed_width() const return lsb_ - msb_ + 1; } +vector netenum_t::slice_dimensions() const +{ + vector tmp (1); + tmp[0] = netrange_t(msb_, lsb_); + return tmp; +} + + bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val) { std::pair::iterator, bool> res; diff --git a/netenum.h b/netenum.h index c254ae95a..80704bd0c 100644 --- a/netenum.h +++ b/netenum.h @@ -29,7 +29,7 @@ class NetScope; -class netenum_t : public LineInfo, public nettype_base_t { +class netenum_t : public LineInfo, public ivl_type_s { public: explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag, @@ -38,7 +38,8 @@ class netenum_t : public LineInfo, public nettype_base_t { ivl_variable_type_t base_type() const; long packed_width() const; - bool has_sign() const; + std::vector slice_dimensions() const; + bool get_signed() const; // The size() is the number of enumeration literals. size_t size() const; @@ -75,6 +76,4 @@ inline ivl_variable_type_t netenum_t::base_type() const inline size_t netenum_t::size() const { return names_.size(); } -inline bool netenum_t::has_sign() const { return signed_flag_; } - #endif diff --git a/netlist.cc b/netlist.cc index 57e9e3be1..a7f407540 100644 --- a/netlist.cc +++ b/netlist.cc @@ -29,7 +29,9 @@ # include "netmisc.h" # include "netdarray.h" # include "netenum.h" +# include "netparray.h" # include "netstruct.h" +# include "netvector.h" # include "ivl_assert.h" @@ -463,44 +465,6 @@ PortType::Enum PortType::merged( Enum lhs, Enum rhs ) return PINOUT; } -NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) -: NetObj(s, n, 1), - type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), - signed_(false), isint_(false), is_scalar_(false), local_flag_(false), - net_type_(0), discipline_(0), - eref_count_(0), lref_count_(0), - port_index_(-1) -{ - assert(s); - assert(npins>0); - - // Synthesize a single range to describe this canonical vector. - packed_dims_.push_back(netrange_t(npins-1, 0)); - calculate_slice_widths_from_packed_dims_(); - - Link::DIR dir = Link::PASSIVE; - - switch (t) { - case REG: - case INTEGER: - case IMPLICIT_REG: - dir = Link::OUTPUT; - break; - case SUPPLY0: - dir = Link::OUTPUT; - break; - case SUPPLY1: - dir = Link::OUTPUT; - break; - default: - break; - } - - pin(0).set_dir(dir); - - s->add_signal(this); -} - void NetNet::initialize_dir_(Link::DIR dir) { if (pins_are_virtual()) { @@ -513,40 +477,6 @@ void NetNet::initialize_dir_(Link::DIR dir) } } -NetNet::NetNet(NetScope*s, perm_string n, Type t, - const list&packed) -: NetObj(s, n, 1), type_(t), - port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false), - isint_(false), is_scalar_(false), local_flag_(false), - net_type_(0), discipline_(0), - eref_count_(0), lref_count_(0) -{ - packed_dims_ = packed; - calculate_slice_widths_from_packed_dims_(); - assert(s); - - Link::DIR dir = Link::PASSIVE; - - switch (t) { - case REG: - case IMPLICIT_REG: - dir = Link::OUTPUT; - break; - case SUPPLY0: - dir = Link::OUTPUT; - break; - case SUPPLY1: - dir = Link::OUTPUT; - break; - default: - break; - } - - initialize_dir_(dir); - - s->add_signal(this); -} - static unsigned calculate_count(const list&unpacked) { unsigned long sum = 1; @@ -577,35 +507,35 @@ template static unsigned calculate_count(T*type) void NetNet::calculate_slice_widths_from_packed_dims_(void) { - if (packed_dims_.empty()) { - slice_wids_.clear(); + ivl_assert(*this, net_type_); + slice_dims_ = net_type_->slice_dimensions(); + + // Special case: There are no actual packed dimensions, so + // build up a fake dimension of "1". + if (slice_dims_.size() == 0) { + slice_wids_.resize(1); + slice_wids_[0] = net_type_->packed_width(); return; } - slice_wids_.resize(packed_dims_.size()); + slice_wids_.resize(slice_dims_.size()); - slice_wids_[0] = netrange_width(packed_dims_); - list::const_iterator cur = packed_dims_.begin(); + ivl_assert(*this, slice_wids_.size() >= 1); + slice_wids_[0] = netrange_width(slice_dims_); + vector::const_iterator cur = slice_dims_.begin(); for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) { slice_wids_[idx] = slice_wids_[idx-1] / cur->width(); } - } NetNet::NetNet(NetScope*s, perm_string n, Type t, - const list&packed, - const list&unpacked, - nettype_base_t*net_type) + const list&unpacked, ivl_type_s*use_net_type) : NetObj(s, n, calculate_count(unpacked)), type_(t), port_type_(NOT_A_PORT), - data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false), - is_scalar_(false), local_flag_(false), net_type_(net_type), + local_flag_(false), net_type_(use_net_type), discipline_(0), unpacked_dims_(unpacked.size()), eref_count_(0), lref_count_(0) { - packed_dims_ = packed; - if (net_type) - packed_dims_.push_back(netrange_t(calculate_count(net_type)-1, 0)); calculate_slice_widths_from_packed_dims_(); size_t idx = 0; for (list::const_iterator cur = unpacked.begin() @@ -650,12 +580,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty) : NetObj(s, n, 1), type_(t), port_type_(NOT_A_PORT), - data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false), - is_scalar_(false), local_flag_(false), net_type_(ty), + local_flag_(false), net_type_(ty), discipline_(0), eref_count_(0), lref_count_(0) { - packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0)); + //XXXX packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0)); calculate_slice_widths_from_packed_dims_(); Link::DIR dir = Link::PASSIVE; @@ -682,8 +611,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty) NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty) : NetObj(s, n, 1), type_(t), port_type_(NOT_A_PORT), - data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false), - is_scalar_(false), local_flag_(false), net_type_(ty), + local_flag_(false), net_type_(ty), discipline_(0), eref_count_(0), lref_count_(0) { @@ -709,6 +637,36 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty) s->add_signal(this); } +NetNet::NetNet(NetScope*s, perm_string n, Type t, netvector_t*ty) +: NetObj(s, n, 1), + type_(t), port_type_(NOT_A_PORT), + local_flag_(false), net_type_(ty), + discipline_(0), + eref_count_(0), lref_count_(0) +{ + calculate_slice_widths_from_packed_dims_(); + Link::DIR dir = Link::PASSIVE; + + switch (t) { + case REG: + case IMPLICIT_REG: + dir = Link::OUTPUT; + break; + case SUPPLY0: + dir = Link::OUTPUT; + break; + case SUPPLY1: + dir = Link::OUTPUT; + break; + default: + break; + } + + initialize_dir_(dir); + + s->add_signal(this); +} + NetNet::~NetNet() { if (eref_count_ > 0) { @@ -787,45 +745,34 @@ void NetNet::set_module_port_index(unsigned idx) ivl_variable_type_t NetNet::data_type() const { - return data_type_; -} - -void NetNet::data_type(ivl_variable_type_t t) -{ - data_type_ = t; + if (net_type_==0) + return IVL_VT_LOGIC; + else + return net_type_->base_type(); } bool NetNet::get_signed() const { - if (data_type_ == IVL_VT_REAL) - return true; + if (net_type_==0) + return false; else - return signed_; -} - -void NetNet::set_signed(bool flag) -{ - signed_ = flag; + return net_type_->get_signed(); } bool NetNet::get_isint() const { - return isint_; -} - -void NetNet::set_isint(bool flag) -{ - isint_ = flag; + if (netvector_t*vec = dynamic_cast (net_type_)) + return vec->get_isint(); + else + return false; } bool NetNet::get_scalar() const { - return is_scalar_; -} - -void NetNet::set_scalar(bool flag) -{ - is_scalar_ = flag; + if (netvector_t*vec = dynamic_cast (net_type_)) + return vec->get_scalar(); + else + return false; } netenum_t*NetNet::enumeration(void) const @@ -833,9 +780,26 @@ netenum_t*NetNet::enumeration(void) const return dynamic_cast (net_type_); } -netstruct_t*NetNet::struct_type(void) const +const netstruct_t*NetNet::struct_type(void) const { - return dynamic_cast (net_type_); + const ivl_type_s*cur_type = net_type_; + while (cur_type) { + if (const netdarray_t*da = dynamic_cast (cur_type)) { + cur_type = da->element_type(); + continue; + } + if (const netparray_t*da = dynamic_cast (cur_type)) { + cur_type = da->element_type(); + continue; + } + if (const netstruct_t*st = dynamic_cast (cur_type)) + return st; + else + return 0; + } + + assert(0); + return 0; } netdarray_t* NetNet::darray_type(void) const @@ -875,9 +839,9 @@ void NetNet::set_discipline(ivl_discipline_t dis) bool NetNet::sb_is_valid(const list&indices, long sb) const { - ivl_assert(*this, indices.size()+1 == packed_dims_.size()); - assert(packed_dims_.size() == 1); - const netrange_t&rng = packed_dims_.back(); + ivl_assert(*this, indices.size()+1 == packed_dims().size()); + assert(packed_dims().size() == 1); + const netrange_t&rng = packed_dims().back(); if (rng.get_msb() >= rng.get_lsb()) return (sb <= rng.get_msb()) && (sb >= rng.get_lsb()); else @@ -886,9 +850,9 @@ bool NetNet::sb_is_valid(const list&indices, long sb) const long NetNet::sb_to_idx(const list&indices, long sb) const { - ivl_assert(*this, indices.size()+1 == packed_dims_.size()); + ivl_assert(*this, indices.size()+1 == packed_dims().size()); - list::const_iterator pcur = packed_dims_.end(); + vector::const_iterator pcur = packed_dims().end(); -- pcur; long acc_off; @@ -924,8 +888,8 @@ long NetNet::sb_to_idx(const list&indices, long sb) const bool NetNet::sb_to_slice(const list&indices, long sb, long&loff, unsigned long&lwid) const { - ivl_assert(*this, indices.size() < packed_dims_.size()); - return prefix_to_slice(packed_dims_, indices, sb, loff, lwid); + ivl_assert(*this, indices.size() < packed_dims().size()); + return prefix_to_slice(packed_dims(), indices, sb, loff, lwid); } unsigned NetNet::unpacked_count() const @@ -2265,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. @@ -2480,14 +2425,14 @@ NetNet* NetESignal::sig() */ long NetESignal::lsi() const { - const list&packed = net_->packed_dims(); + const vector&packed = net_->packed_dims(); ivl_assert(*this, packed.size() == 1); return packed.back().get_lsb(); } long NetESignal::msi() const { - const list&packed = net_->packed_dims(); + const vector&packed = net_->packed_dims(); ivl_assert(*this, packed.size() == 1); return packed.back().get_msb(); } diff --git a/netlist.h b/netlist.h index bd5af11b0..f75a6121c 100644 --- a/netlist.h +++ b/netlist.h @@ -80,6 +80,7 @@ class netdarray_t; class netparray_t; class netenum_t; class netstruct_t; +class netvector_t; struct target; struct functor_t; @@ -596,26 +597,18 @@ class NetNet : public NetObj, public PortType { typedef PortType::Enum PortType; public: - // The width in this case is a shorthand for ms=width-1 and - // ls=0. Only one pin is created, the width is of the vector - // that passed through. - explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1); - - // This form supports an array of vectors. The [ms:ls] define - // the base vector, and the [s0:e0] define the array - // dimensions. If s0==e0, then this is not an array after - // all. + // This form is the more generic form of the constructor. For + // now, the unpacked type is not burried into an ivl_type_s object. explicit NetNet(NetScope*s, perm_string n, Type t, - const std::list&packed); - explicit NetNet(NetScope*s, perm_string n, Type t, - const std::list&packed, const std::list&unpacked, - nettype_base_t*type =0); + ivl_type_s*type =0); - // This form builds a NetNet from its record/enum definition. + // This form builds a NetNet from its record/enum/darray + // definition. They should probably be replaced with a single + // version that takes an ivl_type_s* base. explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type); explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type); - //explicit NetNet(NetScope*s, perm_string n, Type t, netparray_t*type); + explicit NetNet(NetScope*s, perm_string n, Type t, netvector_t*type); virtual ~NetNet(); @@ -631,23 +624,20 @@ class NetNet : public NetObj, public PortType { void set_module_port_index(unsigned idx); ivl_variable_type_t data_type() const; - void data_type(ivl_variable_type_t t); /* If a NetNet is signed, then its value is to be treated as signed. Otherwise, it is unsigned. */ bool get_signed() const; - void set_signed(bool); /* Used to maintain original type of net since integers are implemented as 'reg signed [31:0]' in Icarus */ bool get_isint() const; - void set_isint(bool); bool get_scalar() const; - void set_scalar(bool); + inline const ivl_type_s* net_type(void) const { return net_type_; } netenum_t*enumeration(void) const; - netstruct_t*struct_type(void) const; + const netstruct_t*struct_type(void) const; netdarray_t*darray_type(void) const; /* Attach a discipline to the net. */ @@ -657,8 +647,9 @@ class NetNet : public NetObj, public PortType { /* This method returns a reference to the packed dimensions for the vector. These are arranged as a list where the first range in the list (front) is the left-most range in - the verilog declaration. */ - const std::list& packed_dims() const { return packed_dims_; } + the verilog declaration. These packed dims are compressed + to represent the dimensions of all the subtypes. */ + const std::vector& packed_dims() const { return slice_dims_; } const std::vector& unpacked_dims() const { return unpacked_dims_; } @@ -698,7 +689,7 @@ class NetNet : public NetObj, public PortType { /* This methor returns 0 for scalars, but vectors and other PACKED arrays have packed dimensions. */ - inline size_t packed_dimensions() const { return packed_dims_.size(); } + inline size_t packed_dimensions() const { return slice_dims_.size(); } // This is the number of array elements. unsigned unpacked_count() const; @@ -733,15 +724,10 @@ class NetNet : public NetObj, public PortType { private: Type type_ : 5; PortType port_type_ : 3; - ivl_variable_type_t data_type_ : 3; - bool signed_ : 1; - bool isint_ : 1; // original type of integer - bool is_scalar_ : 1; bool local_flag_: 1; - nettype_base_t*net_type_; + ivl_type_s*net_type_; ivl_discipline_t discipline_; - std::list packed_dims_; std::vector unpacked_dims_; // These are the widths of the various slice depths. There is @@ -750,6 +736,7 @@ class NetNet : public NetObj, public PortType { // // For example: slice_wids_[0] is vector_width(). void calculate_slice_widths_from_packed_dims_(void); + std::vector slice_dims_; std::vector slice_wids_; unsigned eref_count_; @@ -764,7 +751,6 @@ class NetNet : public NetObj, public PortType { int port_index_; }; -extern std::ostream&operator << (std::ostream&out, const std::list&rlist); /* * This object type is used to contain a logical scope within a @@ -1753,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; @@ -1826,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_; @@ -3813,6 +3807,10 @@ class NetESelect : public NetExpr { const NetExpr*select() const; ivl_select_type_t select_type() const; + // The type of a NetESelect is the base type of the + // sub-expression. + virtual ivl_variable_type_t expr_type() const; + virtual NexusSet* nex_input(bool rem_out = true); virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; @@ -3906,6 +3904,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/netmisc.cc b/netmisc.cc index da0504494..b71439fc2 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -21,6 +21,7 @@ # include # include "netlist.h" +# include "netvector.h" # include "netmisc.h" # include "PExpr.h" # include "pform_types.h" @@ -30,10 +31,11 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig) { + netvector_t*zero_vec = new netvector_t(sig->data_type(), + sig->vector_width()-1, 0); NetNet*zero_net = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, sig->vector_width()); + NetNet::WIRE, zero_vec); zero_net->set_line(*sig); - zero_net->data_type(sig->data_type()); zero_net->local_flag(true); if (sig->data_type() == IVL_VT_REAL) { @@ -62,10 +64,11 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig) connect(zero_net->pin(0), adder->pin_DataA()); connect(adder->pin_DataB(), sig->pin(0)); + netvector_t*tmp_vec = new netvector_t(sig->data_type(), + sig->vector_width()-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, sig->vector_width()); + NetNet::WIRE, tmp_vec); tmp->set_line(*sig); - tmp->data_type(sig->data_type()); tmp->local_flag(true); connect(adder->pin_Result(), tmp->pin(0)); @@ -78,9 +81,9 @@ NetNet* cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid) if (src->data_type() == IVL_VT_BOOL) return src; - NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid); + netvector_t*tmp_vec = new netvector_t(IVL_VT_BOOL, wid-1, 0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec); tmp->set_line(*src); - tmp->data_type(IVL_VT_BOOL); tmp->local_flag(true); NetCastInt2*cast = new NetCastInt2(scope, scope->local_symbol(), wid); @@ -98,9 +101,9 @@ NetNet* cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid) if (src->data_type() != IVL_VT_REAL) return src; - NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid); + netvector_t*tmp_vec = new netvector_t(IVL_VT_LOGIC, wid-1, 0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec); tmp->set_line(*src); - tmp->data_type(IVL_VT_LOGIC); tmp->local_flag(true); NetCastInt4*cast = new NetCastInt4(scope, scope->local_symbol(), wid); @@ -118,9 +121,9 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src) if (src->data_type() == IVL_VT_REAL) return src; - NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE); + netvector_t*tmp_vec = new netvector_t(IVL_VT_REAL); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec); tmp->set_line(*src); - tmp->data_type(IVL_VT_REAL); tmp->local_flag(true); NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed()); @@ -149,6 +152,16 @@ NetExpr* cast_to_int2(NetExpr*expr) return cast; } +NetExpr* cast_to_real(NetExpr*expr) +{ + if (expr->expr_type() == IVL_VT_REAL) + return expr; + + NetECast*cast = new NetECast('r', expr, 1, true); + cast->set_line(*expr); + return cast; +} + /* * Add a signed constant to an existing expression. Generate a new * NetEBAdd node that has the input expression and an expression made @@ -350,7 +363,7 @@ NetExpr *normalize_variable_base(NetExpr *base, NetExpr *normalize_variable_bit_base(const list&indices, NetExpr*base, const NetNet*reg) { - const list&packed_dims = reg->packed_dims(); + const vector&packed_dims = reg->packed_dims(); ivl_assert(*base, indices.size()+1 == packed_dims.size()); // Get the canonical offset of the slice within which we are @@ -366,7 +379,7 @@ NetExpr *normalize_variable_part_base(const list&indices, NetExpr*base, const NetNet*reg, unsigned long wid, bool is_up) { - const list&packed_dims = reg->packed_dims(); + const vector&packed_dims = reg->packed_dims(); ivl_assert(*base, indices.size()+1 == packed_dims.size()); // Get the canonical offset of the slice within which we are @@ -381,10 +394,10 @@ NetExpr *normalize_variable_part_base(const list&indices, NetExpr*base, NetExpr *normalize_variable_slice_base(const list&indices, NetExpr*base, const NetNet*reg, unsigned long&lwid) { - const list&packed_dims = reg->packed_dims(); + const vector&packed_dims = reg->packed_dims(); ivl_assert(*base, indices.size() < packed_dims.size()); - list::const_iterator pcur = packed_dims.end(); + vector::const_iterator pcur = packed_dims.end(); for (size_t idx = indices.size() ; idx < packed_dims.size(); idx += 1) { -- pcur; } @@ -630,9 +643,9 @@ NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid) NetConst*res = new NetConst(scope, scope->local_symbol(), xxx); des->add_node(res); - NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid); + netvector_t*sig_vec = new netvector_t(IVL_VT_LOGIC, wid-1, 0); + NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, sig_vec); sig->local_flag(true); - sig->data_type(IVL_VT_LOGIC); connect(sig->pin(0), res->pin(0)); return sig; @@ -1179,8 +1192,8 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope, return *exprs.begin(); } - const std::list&pdims = net->packed_dims(); - std::list::const_iterator pcur = pdims.begin(); + const std::vector&pdims = net->packed_dims(); + std::vector::const_iterator pcur = pdims.begin(); list::iterator ecur = exprs.begin(); NetExpr* base = 0; diff --git a/netmisc.h b/netmisc.h index 4eb35c04b..792f62ac8 100644 --- a/netmisc.h +++ b/netmisc.h @@ -79,6 +79,7 @@ extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid) extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src); extern NetExpr*cast_to_int2(NetExpr*expr); +extern NetExpr*cast_to_real(NetExpr*expr); /* * Take the input expression and return a variation that assures that diff --git a/netparray.cc b/netparray.cc new file mode 100644 index 000000000..d8779a92d --- /dev/null +++ b/netparray.cc @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012 Picture Elements, Inc. + * 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 "netparray.h" + +using namespace std; + +netparray_t::~netparray_t() +{ +} + +/* + * The packed width of a packed array is the packed width of the + * element times the dimension width of the array itself. + */ +long netparray_t::packed_width(void) const +{ + long cur_width = element_type()->packed_width(); + + for (vector::const_iterator cur = packed_dims_.begin() + ; cur != packed_dims_.end() ; ++cur) { + cur_width *= cur->width(); + } + + return cur_width; +} + +vector netparray_t::slice_dimensions() const +{ + vector elem_dims = element_type()->slice_dimensions(); + + vector res (packed_dims_.size() + elem_dims.size()); + + for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1) + res[idx] = packed_dims_[0]; + for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1) + res[idx+packed_dims_.size()] = elem_dims[idx]; + + return res; +} diff --git a/netparray.h b/netparray.h index 70be869ec..4850059b5 100644 --- a/netparray.h +++ b/netparray.h @@ -20,33 +20,36 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "LineInfo.h" # include "nettypes.h" # include /* * Packed arrays. */ -class netparray_t : public nettype_base_t, public LineInfo { +class netparray_t : public netarray_t { public: - explicit netparray_t(const std::list&packed); + explicit netparray_t(const std::vector&packed, + ivl_type_t etype); ~netparray_t(); - inline const std::list& packed_dimensions() const + public: + // Virtual methods from the ivl_type_s type... + long packed_width(void) const; + std::vector slice_dimensions() const; + + public: + inline const std::vector& packed_dimensions() const { return packed_dims_; } private: - std::list packed_dims_; + std::vector packed_dims_; }; -inline netparray_t::netparray_t(const std::list&packed) -: packed_dims_(packed) -{ -} - -inline netparray_t::~netparray_t() +inline netparray_t::netparray_t(const std::vector&packed, + ivl_type_t etype) +: netarray_t(etype), packed_dims_(packed) { } diff --git a/netstruct.cc b/netstruct.cc index 2db490eee..b4c372599 100644 --- a/netstruct.cc +++ b/netstruct.cc @@ -66,3 +66,23 @@ long netstruct_t::packed_width(void) const return res; } + +vector netstruct_t::slice_dimensions() const +{ + vector tmp; + tmp .push_back(netrange_t(packed_width()-1, 0)); + return tmp; +} + +ivl_variable_type_t netstruct_t::base_type() const +{ + if (! packed_) + return IVL_VT_NO_TYPE; + + for (size_t idx = 0 ; idx < members_.size() ; idx += 1) { + if (members_[idx].data_type() != IVL_VT_BOOL) + return members_[idx].data_type(); + } + + return IVL_VT_BOOL; +} diff --git a/netstruct.h b/netstruct.h index 02ff90cb6..9d971961e 100644 --- a/netstruct.h +++ b/netstruct.h @@ -20,17 +20,17 @@ */ # include "LineInfo.h" -# include +# include # include "ivl_target.h" # include "nettypes.h" -class netstruct_t : public LineInfo, public nettype_base_t { +class netstruct_t : public LineInfo, public ivl_type_s { public: struct member_t { perm_string name; ivl_variable_type_t type; - list packed_dims; + std::vector packed_dims; long width() const; ivl_variable_type_t data_type() const { return type; }; // We need to keep the individual element sign information. @@ -54,6 +54,11 @@ class netstruct_t : public LineInfo, public nettype_base_t { // Return the width (in bits) of the packed record, or -1 if // the record is not packed. long packed_width() const; + std::vector slice_dimensions() const; + + // Return the base type of the packed record, or + // IVL_VT_NO_TYPE if the record is not packed. + ivl_variable_type_t base_type() const; private: bool packed_; diff --git a/nettypes.cc b/nettypes.cc index 9d31c81c2..6b5797146 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -22,19 +22,43 @@ using namespace std; -nettype_base_t::~nettype_base_t() +ivl_type_s::~ivl_type_s() { } -long nettype_base_t::packed_width(void) const +long ivl_type_s::packed_width(void) const { - return 0; + return 1; } -unsigned long netrange_width(const list&packed) +vector ivl_type_s::slice_dimensions() const +{ + return vector(); +} + +ivl_variable_type_t ivl_type_s::base_type() const +{ + return IVL_VT_NO_TYPE; +} + +bool ivl_type_s::get_signed() const +{ + return false; +} + +netarray_t::~netarray_t() +{ +} + +ivl_variable_type_t netarray_t::base_type() const +{ + return element_type_->base_type(); +} + +unsigned long netrange_width(const vector&packed) { unsigned wid = 1; - for (list::const_iterator cur = packed.begin() + for (vector::const_iterator cur = packed.begin() ; cur != packed.end() ; ++cur) { unsigned use_wid = cur->width(); wid *= use_wid; @@ -49,14 +73,14 @@ unsigned long netrange_width(const list&packed) * and width of the resulting slice. In this case, the "sb" argument * is an extra index of the prefix. */ -bool prefix_to_slice(const std::list&dims, +bool prefix_to_slice(const std::vector&dims, const std::list&prefix, long sb, long&loff, unsigned long&lwid) { assert(prefix.size() < dims.size()); size_t acc_wid = 1; - list::const_iterator pcur = dims.end(); + vector::const_iterator pcur = dims.end(); for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) { -- pcur; acc_wid *= pcur->width(); diff --git a/nettypes.h b/nettypes.h index 3292ffc8c..df7779edb 100644 --- a/nettypes.h +++ b/nettypes.h @@ -19,20 +19,58 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -# include -# include -# include +# include "ivl_target.h" +# include +# include +# include +# include +# include + +class netrange_t; /* * This is a fully abstract type that is a type that can be attached * to a NetNet object. */ -class nettype_base_t { +class ivl_type_s { public: - virtual ~nettype_base_t() =0; + virtual ~ivl_type_s() =0; virtual long packed_width(void) const; + virtual std::vector slice_dimensions() const; + + // Some types have a base variable type. + virtual ivl_variable_type_t base_type() const; + virtual bool get_signed() const; + + virtual std::ostream& debug_dump(std::ostream&) const; }; +/* + * There are a couple types of array types. This class represents the + * common bits of array types. + */ +class netarray_t : public ivl_type_s { + + public: + inline explicit netarray_t(ivl_type_t etype) : element_type_(etype) { } + ~netarray_t(); + + public: + // Some virtual methods have a common implementation for arrays. + ivl_variable_type_t base_type() const; + + public: + inline ivl_type_t element_type() const { return element_type_; } + + private: + ivl_type_t element_type_; +}; + +inline static std::ostream& operator << (std::ostream&out, const ivl_type_s&obj) +{ + return obj.debug_dump(out); +} + class netrange_t { public: @@ -65,14 +103,17 @@ class netrange_t { long lsb_; }; -extern unsigned long netrange_width(const std::list&dims); +extern std::ostream&operator << (std::ostream&out, const std::list&rlist); +extern std::ostream&operator << (std::ostream&out, const std::vector&rlist); + +extern unsigned long netrange_width(const std::vector&dims); /* * Take as input a list of packed dimensions and a list of prefix * indices, and calculate the offset/width of the resulting slice into * the packed array. */ -extern bool prefix_to_slice(const std::list&dims, +extern bool prefix_to_slice(const std::vector&dims, const std::list&prefix, long sb, long&loff, unsigned long&lwid); diff --git a/netvector.cc b/netvector.cc new file mode 100644 index 000000000..859b76110 --- /dev/null +++ b/netvector.cc @@ -0,0 +1,52 @@ +/* + * 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 "netvector.h" + +using namespace std; + +netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb) +: type_(type), signed_(false) +{ + packed_dims_.push_back(netrange_t(msb,lsb)); +} + +netvector_t::netvector_t(ivl_variable_type_t type) +: type_(type), signed_(false) +{ +} + +netvector_t::~netvector_t() +{ +} + +ivl_variable_type_t netvector_t::base_type() const +{ + return type_; +} + +long netvector_t::packed_width() const +{ + return netrange_width(packed_dims_); +} + +vector netvector_t::slice_dimensions() const +{ + return packed_dims_; +} diff --git a/netvector.h b/netvector.h new file mode 100644 index 000000000..770ac22d8 --- /dev/null +++ b/netvector.h @@ -0,0 +1,91 @@ +#ifndef __netvector_H +#define __netvector_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 "nettypes.h" +# include "ivl_target.h" +# include + +class netvector_t : public ivl_type_s { + + public: + explicit netvector_t(const std::vector&packed, + ivl_variable_type_t type); + + // This is a variant of the vector form. Some code processes + // the list of packed ranges as a list, but we will store them + // as a vector in this constructor. + explicit netvector_t(const std::list&packed, + ivl_variable_type_t type); + + // special case: there is a single packed dimension and we + // know it in the form [:]. This step saves me + // creating a netrange_t for this single item. + explicit netvector_t(ivl_variable_type_t type, long msb, long lsb); + + // Special case: scaler object--no packed dimenions at all. + explicit netvector_t(ivl_variable_type_t type); + + ~netvector_t(); + + // Vectors can be interpreted as signed or unsigned when + // handled as vectors. + inline void set_signed(bool flag) { signed_ = flag; } + inline bool get_signed(void) const { return signed_; } + + inline void set_isint(bool flag) { isint_ = flag; } + inline bool get_isint(void) const { return isint_; } + + inline void set_scalar(bool flag) { is_scalar_ = flag; } + inline bool get_scalar(void) const { return is_scalar_; } + + ivl_variable_type_t base_type() const; + const std::vector&packed_dims() const; + + long packed_width() const; + std::vector slice_dimensions() const; + + std::ostream& debug_dump(std::ostream&) const; + + private: + std::vector packed_dims_; + ivl_variable_type_t type_; + bool signed_ : 1; + bool isint_ : 1; // original type of integer + bool is_scalar_ : 1; +}; + +inline netvector_t::netvector_t(const std::vector&packed, + ivl_variable_type_t type) +: packed_dims_(packed), type_(type), signed_(false) +{ +} + +inline const std::vector& netvector_t::packed_dims() const +{ + return packed_dims_; +} + +inline static std::ostream& operator << (std::ostream&out, const netvector_t&obj) +{ + return obj.debug_dump(out); +} + +#endif diff --git a/pad_to_width.cc b/pad_to_width.cc index 8004c046b..32ba6c61d 100644 --- a/pad_to_width.cc +++ b/pad_to_width.cc @@ -20,6 +20,7 @@ # include "config.h" # include "netlist.h" +# include "netvector.h" # include "netmisc.h" @@ -77,19 +78,20 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid, const LineInfo&info) connect(cc->pin(2), con->pin(0)); // Make a NetNet for the NetConst to NetConcat link. + netvector_t*tmp_vec = new netvector_t(net->data_type(), + wid - net->vector_width() - 1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, wid - net->vector_width()); + NetNet::WIRE, tmp_vec); tmp->set_line(info); - tmp->data_type( net->data_type() ); tmp->local_flag(true); connect(cc->pin(2), tmp->pin(0)); // Create a NetNet of the output width and connect it to the // NetConcat node output pin. + tmp_vec = new netvector_t(net->data_type(), wid-1, 0); tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, wid); + NetNet::WIRE, tmp_vec); tmp->set_line(info); - tmp->data_type( net->data_type() ); tmp->local_flag(true); connect(cc->pin(0), tmp->pin(0)); @@ -109,11 +111,11 @@ NetNet*pad_to_width_signed(Design*des, NetNet*net, unsigned wid, se->set_line(info); des->add_node(se); - NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid); + netvector_t*tmp_vec = new netvector_t(net->data_type(), wid-1, 0); + tmp_vec->set_signed(true); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec); tmp->set_line(info); tmp->local_flag(true); - tmp->data_type(net->data_type()); - tmp->set_signed(true); connect(tmp->pin(0), se->pin(0)); connect(se->pin(1), net->pin(0)); @@ -132,10 +134,10 @@ NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid) ps->set_line(*net); des->add_node(ps); + netvector_t*tmp_vec = new netvector_t(net->data_type(), wid-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, wid); + NetNet::WIRE, tmp_vec); tmp->set_line(*net); - tmp->data_type(net->data_type()); tmp->local_flag(true); connect(ps->pin(0), tmp->pin(0)); diff --git a/pform_dump.cc b/pform_dump.cc index 0ce59a91a..4a6c60ae5 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -153,6 +153,28 @@ void parray_type_t::pform_dump(ostream&out, unsigned indent) const base_type->pform_dump(out, indent+4); } +void struct_type_t::pform_dump(ostream&out, unsigned indent) const +{ + out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked") + << " with " << members->size() << " members" << endl; + for (list::iterator cur = members->begin() + ; cur != members->end() ; ++ cur) { + struct_member_t*curp = *cur; + curp->pform_dump(out, indent+4); + } +} + +void struct_member_t::pform_dump(ostream&out, unsigned indent) const +{ + out << setw(indent) << "" << type; + for (list::iterator cur = names->begin() + ; cur != names->end() ; ++cur) { + decl_assignment_t*curp = *cur; + out << " " << curp->name; + } + out << ";" << endl; +} + static void dump_attributes_map(ostream&out, const map&attributes, int ind) diff --git a/pform_types.h b/pform_types.h index a47b671fa..df2c8f9b8 100644 --- a/pform_types.h +++ b/pform_types.h @@ -97,10 +97,13 @@ struct struct_member_t : public LineInfo { ivl_variable_type_t type; std::auto_ptr< list > range; std::auto_ptr< list > names; + void pform_dump(std::ostream&out, unsigned indent) const; }; struct struct_type_t : public data_type_t { virtual ivl_variable_type_t figure_packed_base_type(void)const; + virtual void pform_dump(std::ostream&out, unsigned indent) const; + bool packed_flag; std::auto_ptr< list > members; }; diff --git a/synth2.cc b/synth2.cc index b62a05e9f..f1e8d6371 100644 --- a/synth2.cc +++ b/synth2.cc @@ -21,6 +21,7 @@ # include "functor.h" # include "netlist.h" +# include "netvector.h" # include "netmisc.h" # include "compiler.h" # include @@ -221,10 +222,10 @@ bool NetCase::synth_async(Design*des, NetScope*scope, continue; } + netvector_t*isig_vec = new netvector_t(mux_data_type, mux_width-1, 0); isig = new NetNet(scope, scope->local_symbol(), - NetNet::TRI, mux_width); + NetNet::TRI, isig_vec); isig->local_flag(true); - isig->data_type(mux_data_type); connect(mux->pin_Data(idx), isig->pin(0)); diff --git a/t-dll-api.cc b/t-dll-api.cc index a2444f81b..592aa59a0 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -21,7 +21,9 @@ # include "StringHeap.h" # include "t-dll.h" # include "discipline.h" +# include "netdarray.h" # include "netenum.h" +# include "netvector.h" # include # include # include @@ -265,7 +267,7 @@ extern "C" unsigned ivl_enum_width(ivl_enumtype_t net) extern "C" int ivl_enum_signed(ivl_enumtype_t net) { assert(net); - return net->has_sign(); + return net->get_signed(); } extern "C" const char*ivl_enum_file(ivl_enumtype_t net) @@ -411,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_) { @@ -1422,7 +1429,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net) case IVL_LPM_REPEAT: return 0; case IVL_LPM_ARRAY: // Array ports take the signedness of the array. - return net->u_.array.sig->signed_; + return net->u_.array.sig->net_type->get_signed()? 1 : 0; default: assert(0); return 0; @@ -2231,7 +2238,7 @@ extern "C" ivl_scope_t ivl_signal_scope(ivl_signal_t net) extern "C" unsigned ivl_signal_width(ivl_signal_t net) { - return net->width_; + return net->net_type->packed_width(); } extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net) @@ -2251,7 +2258,7 @@ extern "C" int ivl_signal_local(ivl_signal_t net) extern "C" int ivl_signal_signed(ivl_signal_t net) { - return net->signed_; + return net->net_type->get_signed()? 1 : 0; } extern "C" unsigned ivl_signal_forced_net(ivl_signal_t net) @@ -2273,12 +2280,20 @@ extern "C" unsigned ivl_signal_lineno(ivl_signal_t net) extern "C" int ivl_signal_integer(ivl_signal_t net) { - return net->isint_; + if (const netvector_t*vec = dynamic_cast (net->net_type)) + return vec->get_isint()? 1 : 0; + else + return 0; } extern "C" ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net) { - return net->data_type; + return net->net_type->base_type(); +} + +extern "C" ivl_type_t ivl_signal_net_type(ivl_signal_t net) +{ + return net->net_type; } extern "C" unsigned ivl_signal_npath(ivl_signal_t net) @@ -2773,3 +2788,38 @@ extern "C" unsigned ivl_switch_lineno(ivl_switch_t net) { return net->lineno; } + +extern "C" ivl_variable_type_t ivl_type_base(ivl_type_t net) +{ + if (net == 0) return IVL_VT_NO_TYPE; + else return net->base_type(); +} + +extern "C" ivl_type_t ivl_type_element(ivl_type_t net) +{ + if (const netarray_t*da = dynamic_cast (net)) + return da->element_type(); + + assert(0); + return 0; +} + +extern "C" unsigned ivl_type_packed_dimensions(ivl_type_t net) +{ + vector slice = net->slice_dimensions(); + return slice.size(); +} + +extern "C" int ivl_type_packed_lsb(ivl_type_t net, unsigned dim) +{ + vector slice = net->slice_dimensions(); + assert(dim < slice.size()); + return slice[dim].get_lsb(); +} + +extern "C" int ivl_type_packed_msb(ivl_type_t net, unsigned dim) +{ + vector slice = net->slice_dimensions(); + assert(dim < slice.size()); + return slice[dim].get_msb(); +} diff --git a/t-dll-expr.cc b/t-dll-expr.cc index c5aaf1cb2..87164c6a2 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(); } @@ -370,7 +383,8 @@ void dll_target::expr_select(const NetESelect*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->type_ = IVL_EX_SELECT; - expr_->value_= IVL_VT_VECTOR; + expr_->value_= net->expr_type(); + 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.cc b/t-dll.cc index 6a0cb4260..8b620a5e7 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -2374,7 +2374,7 @@ void dll_target::signal(const NetNet*net) ivl_signal_t object. */ { size_t idx = 0; - list::const_iterator cur; + vector::const_iterator cur; obj->packed_dims.resize(net->packed_dims().size()); for (cur = net->packed_dims().begin(), idx = 0 ; cur != net->packed_dims().end() ; ++cur, idx += 1) { @@ -2382,9 +2382,7 @@ void dll_target::signal(const NetNet*net) } } - obj->width_ = net->vector_width(); - obj->signed_= net->get_signed()? 1 : 0; - obj->isint_ = false; + obj->net_type = net->net_type(); obj->local_ = net->local_flag()? 1 : 0; obj->forced_net_ = (net->type() != NetNet::REG) && (net->peek_lref() > 0) ? 1 : 0; @@ -2418,7 +2416,6 @@ void dll_target::signal(const NetNet*net) case NetNet::REG: obj->type_ = IVL_SIT_REG; - obj->isint_ = net->get_isint(); break; /* The SUPPLY0/1 net types are replaced with pulldown/up @@ -2469,15 +2466,9 @@ void dll_target::signal(const NetNet*net) obj->npath = 0; obj->path = 0; - obj->data_type = net->data_type(); obj->nattr = net->attr_cnt(); obj->attr = fill_in_attributes(net); - /* If this is a dynamic array, then set the type to DARRAY. */ - if (net->darray_type()) { - obj->data_type = IVL_VT_DARRAY; - } - /* Get the nexus objects for all the pins of the signal. If the signal has only one pin, then write the single ivl_nexus_t object into n.pin_. Otherwise, make an array of diff --git a/t-dll.h b/t-dll.h index c3486e5f7..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; @@ -677,14 +678,12 @@ struct ivl_signal_s { ivl_signal_type_t type_; ivl_signal_port_t port_; int module_port_index_; - ivl_variable_type_t data_type; ivl_discipline_t discipline; perm_string file; unsigned lineno; - unsigned width_; - unsigned signed_ : 1; - unsigned isint_ : 1; + // This is the type for the signal + ivl_type_t net_type; unsigned local_ : 1; unsigned forced_net_ : 1; diff --git a/tgt-stub/Makefile.in b/tgt-stub/Makefile.in index 22d051fb2..d44973801 100644 --- a/tgt-stub/Makefile.in +++ b/tgt-stub/Makefile.in @@ -44,7 +44,7 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@ CFLAGS = @WARNING_FLAGS@ @CFLAGS@ LDFLAGS = @LDFLAGS@ -O = stub.o enumerate.o expression.o statement.o switches.o +O = stub.o enumerate.o expression.o statement.o switches.o types.o all: dep stub.tgt diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index ecf2a61b1..8cc2cbe21 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -169,6 +169,7 @@ static void show_select_expression(ivl_expr_t net, unsigned ind) { unsigned width = ivl_expr_width(net); const char*sign = ivl_expr_signed(net)? "signed" : "unsigned"; + const char*vt = vt_type_string(net); ivl_expr_t oper1 = ivl_expr_oper1(net); ivl_expr_t oper2 = ivl_expr_oper2(net); @@ -177,17 +178,26 @@ static void show_select_expression(ivl_expr_t net, unsigned ind) substring and the code generator will handle it differently. */ fprintf(out, "%*s\n", ind, "", width, width/8); - if (width%8 != 0) + if (width%8 != 0) { fprintf(out, "%*sERROR: Width should be a multiple of 8 bits.\n", ind, ""); + stub_errors += 1; + } + assert(oper1); show_expression(oper1, ind+3); - show_expression(oper2, ind+3); + + if (oper2) { + show_expression(oper2, ind+3); + } else { + fprintf(out, "%*sERROR: oper2 missing! Pad makes no sense for IVL_VT_STRING expressions.\n", ind+3, ""); + stub_errors += 1; + } } else if (oper2) { /* If oper2 is present, then it is the base of a part select. The width of the expression defines the range of the part select. */ - fprintf(out, "%*s\n", ind, "", - width, sign); + fprintf(out, "%*s\n", ind, "", + width, sign, vt); show_expression(oper1, ind+3); show_expression(oper2, ind+3); @@ -233,6 +243,14 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind) fprintf(out, "%*sERROR: Missing word expression\n", ind+2, ""); stub_errors += 1; } + /* If this is not an array, then the expression with must + match the signal width. We have IVL_EX_SELECT expressions + for casting signal widths. */ + if (dimensions == 0 && ivl_signal_width(sig) != width) { + fprintf(out, "%*sERROR: Expression width (%u) doesn't match ivl_signal_width(sig)=%u\n", + ind+2, "", width, ivl_signal_width(sig)); + stub_errors += 1; + } if (word != 0) { fprintf(out, "%*sAddress-0 word address:\n", ind+2, ""); @@ -294,9 +312,10 @@ void show_unary_expression(ivl_expr_t net, unsigned ind) void show_expression(ivl_expr_t net, unsigned ind) { + assert(net); unsigned idx; - const ivl_expr_type_t code = ivl_expr_type(net); ivl_parameter_t par = ivl_expr_parameter(net); + const ivl_expr_type_t code = ivl_expr_type(net); unsigned width = ivl_expr_width(net); const char*sign = ivl_expr_signed(net)? "signed" : "unsigned"; const char*sized = ivl_expr_sized(net)? "sized" : "unsized"; diff --git a/tgt-stub/priv.h b/tgt-stub/priv.h index 0a70d13be..d8c301bef 100644 --- a/tgt-stub/priv.h +++ b/tgt-stub/priv.h @@ -61,6 +61,11 @@ extern void show_expression(ivl_expr_t net, unsigned ind); */ extern void show_statement(ivl_statement_t net, unsigned ind); +/* + * Show the type of the signal, in one line. + */ +extern void show_type_of_signal(ivl_signal_t); + extern void show_switch(ivl_switch_t net); /* diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 83be3a195..5f9cda357 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -31,7 +31,9 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind) assert(sig); if (ivl_lval_idx(lval)) { - fprintf(out, "%*sAddress-0 select of dynamic array:\n", ind+4, ""); + fprintf(out, "%*sAddress-0 select of ", ind+4, ""); + show_type_of_signal(sig); + fprintf(out, ":\n"); show_expression(ivl_lval_idx(lval), ind+6); } diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index f8a1630ff..f87face83 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1222,7 +1222,6 @@ static void show_signal(ivl_signal_t net) const char*type = "?"; const char*port = ""; - const char*data_type = "?"; const char*sign = ivl_signal_signed(net)? "signed" : "unsigned"; switch (ivl_signal_type(net)) { @@ -1263,32 +1262,6 @@ static void show_signal(ivl_signal_t net) break; } - data_type = "?data?"; - switch (ivl_signal_data_type(net)) { - - case IVL_VT_NO_TYPE: - data_type = ""; - break; - case IVL_VT_BOOL: - data_type = "bool"; - break; - case IVL_VT_LOGIC: - data_type = "logic"; - break; - case IVL_VT_REAL: - data_type = "real"; - break; - case IVL_VT_STRING: - data_type = "string"; - break; - case IVL_VT_DARRAY: - data_type = "darray"; - break; - case IVL_VT_VOID: - data_type = "void"; - break; - } - const char*discipline_txt = "NONE"; if (ivl_signal_discipline(net)) { ivl_discipline_t dis = ivl_signal_discipline(net); @@ -1298,13 +1271,9 @@ static void show_signal(ivl_signal_t net) for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) { ivl_nexus_t nex = ivl_signal_nex(net, idx); - unsigned dim; - fprintf(out, " %s %s %s%s", type, sign, port, data_type); - for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) { - fprintf(out, "[%d:%d]", ivl_signal_packed_msb(net,dim), - ivl_signal_packed_lsb(net,dim)); - } + fprintf(out, " %s %s %s", type, sign, port); + show_type_of_signal(net); fprintf(out, " %s[word=%u, adr=%d] ", ivl_signal_basename(net), idx, ivl_signal_array_base(net)+idx, @@ -1371,7 +1340,7 @@ static void show_signal(ivl_signal_t net) switch (ivl_signal_data_type(net)) { case IVL_VT_NO_TYPE: case IVL_VT_VOID: - fprintf(out, " ERROR: Invalid type for signal: %s\n", data_type); + fprintf(out, " ERROR: Invalid type for signal.\n"); stub_errors += 1; break; default: diff --git a/tgt-stub/types.c b/tgt-stub/types.c new file mode 100644 index 000000000..0a7e143f5 --- /dev/null +++ b/tgt-stub/types.c @@ -0,0 +1,123 @@ +/* + * 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 "config.h" +# include "priv.h" +# include + +static void show_net_type(ivl_type_t net_type); + +static void show_net_type_darray(ivl_type_t net_type) +{ + /* Dynamic arrays have a single element type. */ + ivl_type_t element_type = ivl_type_element(net_type); + + fprintf(out, "darray of "); + show_net_type(element_type); +} + +static void show_net_type(ivl_type_t net_type) +{ + ivl_variable_type_t data_type = ivl_type_base(net_type); + + switch (data_type) { + case IVL_VT_NO_TYPE: + fprintf(out, ""); + stub_errors += 1; + break; + case IVL_VT_BOOL: + fprintf(out, "bool"); + break; + case IVL_VT_LOGIC: + fprintf(out, "logic"); + break; + case IVL_VT_REAL: + fprintf(out, "real"); + break; + case IVL_VT_STRING: + fprintf(out, "string"); + break; + case IVL_VT_DARRAY: + show_net_type_darray(net_type); + break; + case IVL_VT_VOID: + fprintf(out, "void"); + break; + } + + unsigned packed_dimensions = ivl_type_packed_dimensions(net_type); + unsigned idx; + for (idx = 0 ; idx < packed_dimensions ; idx += 1) { + fprintf(out, "[%d:%d]", ivl_type_packed_msb(net_type, idx), + ivl_type_packed_lsb(net_type, idx)); + } +} + +void show_type_of_signal(ivl_signal_t net) +{ + unsigned dim; + + /* The data_type is the base type of the signal. This the the + starting point for the type. In the long run I think I want + to remove this in favor of the ivl_signal_net_type below. */ + ivl_variable_type_t data_type = ivl_signal_data_type(net); + + /* This gets the more general type description. This is a + newer form so doesn't yet handle all the cases. Newer + types, such DARRAY types, REQUIRE this method to get at the + type details. */ + ivl_type_t net_type = ivl_signal_net_type(net); + + if (net_type) { + show_net_type(net_type); + return; + } + + switch (data_type) { + case IVL_VT_NO_TYPE: + fprintf(out, ""); + break; + case IVL_VT_BOOL: + fprintf(out, "bool"); + break; + case IVL_VT_LOGIC: + fprintf(out, "logic"); + break; + case IVL_VT_REAL: + fprintf(out, "real"); + break; + case IVL_VT_STRING: + fprintf(out, "string"); + break; + case IVL_VT_DARRAY: + /* The DARRAY type MUST be described by an + ivl_signal_net_type object. */ + fprintf(out, "ERROR-DARRAY"); + stub_errors += 1; + break; + case IVL_VT_VOID: + fprintf(out, "void"); + break; + } + + for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) { + fprintf(out, "[%d:%d]", ivl_signal_packed_msb(net,dim), + ivl_signal_packed_lsb(net,dim)); + } +} diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 799b43746..2f3464eaa 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -419,6 +419,9 @@ static void draw_vpi_taskfunc_args(const char*call_string, buffer[0] = 0; break; default: + fprintf(vvp_out, "\nXXXX Unexpected argument: call_string=<%s>, arg=%d, type=%d\n", + call_string, idx, ivl_expr_value(expr)); + fflush(vvp_out); assert(0); } args[idx].text = strdup(buffer); diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 4c59512d7..20307ca33 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -2471,6 +2471,17 @@ static struct vector_info draw_select_signal(ivl_expr_t expr, unsigned use_word = 0; unsigned use_wid, lab_x, lab_end; + /* Special case: the sub expression is a DARRAY variable, so + do a dynamic array word load. */ + if (ivl_signal_data_type(sig) == IVL_VT_DARRAY) { + res.base = allocate_vector(wid); + res.wid = wid; + draw_eval_expr_into_integer(bit_idx, 3); + fprintf(vvp_out, " %%load/dar %u, v%p_0, %u;\n", + res.base, sig, res.wid); + return res; + } + /* If this is an access to an array, try to get the index as a constant. If it is (and the array is not a reg array then this reduces to a signal access and we stay here. If it is diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 4a0938968..a48ca77d6 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -28,8 +28,41 @@ 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); + + switch (ivl_type_base(element_type)) { + case IVL_VT_REAL: + // REAL objects are not packable. + assert(ivl_type_packed_dimensions(element_type) == 0); + fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg); + break; + case IVL_VT_STRING: + // STRING objects are not packable. + assert(ivl_type_packed_dimensions(element_type) == 0); + fprintf(vvp_out, " %%new/darray %u, \"S\";\n", size_reg); + break; + case IVL_VT_BOOL: + // bool objects are vectorable, but for now only support + // a single dimensions. + 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; + + fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid); + break; + + default: + assert(0); + break; + } return 0; } diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 20b6d5710..77dedf262 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -256,6 +256,21 @@ static void draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag) clr_vector(sv); } +static void draw_select_real(ivl_expr_t expr) +{ + /* The sube references the expression to be selected from. */ + ivl_expr_t sube = ivl_expr_oper1(expr); + /* This is the select expression */ + ivl_expr_t shift= ivl_expr_oper2(expr); + + /* Assume the sub-expression is a signal */ + ivl_signal_t sig = ivl_expr_signal(sube); + assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY); + + draw_eval_expr_into_integer(shift, 3); + fprintf(vvp_out, " %%load/dar/r v%p_0;\n", sig); +} + static void draw_sfunc_real(ivl_expr_t expr) { switch (ivl_expr_value(expr)) { @@ -492,6 +507,10 @@ void draw_eval_real(ivl_expr_t expr) draw_realnum_real(expr); break; + case IVL_EX_SELECT: + draw_select_real(expr); + break; + case IVL_EX_SFUNC: draw_sfunc_real(expr); break; diff --git a/tgt-vvp/eval_string.c b/tgt-vvp/eval_string.c index 4ddb42eb2..01d6613fa 100644 --- a/tgt-vvp/eval_string.c +++ b/tgt-vvp/eval_string.c @@ -71,6 +71,21 @@ static void string_ex_signal(ivl_expr_t expr) fallback_eval(expr); } +static void string_ex_select(ivl_expr_t expr) +{ + /* The sube references the expression to be selected from. */ + ivl_expr_t sube = ivl_expr_oper1(expr); + /* This is the select expression */ + ivl_expr_t shift= ivl_expr_oper2(expr); + + /* Assume the sub-expression is a signal */ + ivl_signal_t sig = ivl_expr_signal(sube); + assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY); + + draw_eval_expr_into_integer(shift, 3); + fprintf(vvp_out, " %%load/dar/str v%p_0;\n", sig); +} + void draw_eval_string(ivl_expr_t expr) { @@ -87,6 +102,10 @@ void draw_eval_string(ivl_expr_t expr) string_ex_concat(expr); break; + case IVL_EX_SELECT: + string_ex_select(expr); + break; + default: fallback_eval(expr); break; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 0a771311c..c0b8c8472 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -767,6 +767,10 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t part = ivl_lval_part_off(lval); ivl_signal_t var= ivl_lval_sig(lval); + ivl_type_t var_type= ivl_signal_net_type(var); + assert(ivl_type_base(var_type) == IVL_VT_DARRAY); + ivl_type_t element_type = ivl_type_element(var_type); + ivl_expr_t mux = ivl_lval_idx(lval); assert(ivl_stmt_lvals(net) == 1); @@ -774,7 +778,27 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) assert(ivl_lval_mux(lval) == 0); assert(part == 0); - if (mux) { + if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) { + draw_eval_real(rval); + + /* The %set/dar expects the array index to be in index + register 3. Calculate the index in place. */ + draw_eval_expr_into_integer(mux, 3); + + fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); + + } else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) { + + /* Evaluate the rval into the top of the string stack. */ + draw_eval_string(rval); + + /* The %store/dar/s expects the array index to me in index + register 3. Calculate the index in place. */ + draw_eval_expr_into_integer(mux, 3); + + fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var); + + } else if (mux) { struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval), STUFF_OK_XZ); /* The %set/dar expects the array index to be in index diff --git a/vvp/codes.h b/vvp/codes.h index 9cc38f20a..2c9f83532 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -128,6 +128,8 @@ extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code); 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_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); @@ -173,6 +175,8 @@ extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code); extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code); extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code); 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_REAL(vthread_t thr, vvp_code_t code); extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 78ff817d5..5731b13ad 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -171,13 +171,15 @@ static const struct opcode_table_s opcode_table[] = { { "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} }, { "%load/ar",of_LOAD_AR,2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, - { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, - { "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, + { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, + { "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1,OA_ARR_PTR, OA_BIT2} }, { "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, - { "%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} }, + { "%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/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} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, @@ -220,6 +222,8 @@ static const struct opcode_table_s opcode_table[] = { { "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%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} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 8637555a9..e22d282a4 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -612,12 +612,15 @@ out of range, then x is loaded. The index value is incremented by one if it is defined (bit 4 is not 1). * %load/dar , , +* %load/dar/r This instruction loads an array word from a dynamic array. The