diff --git a/elab_lval.cc b/elab_lval.cc index d197fb8eb..332500b23 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -605,10 +605,9 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des, cerr << get_fileline() << ": debug: " << "Bit select of string becomes character select." << endl; } - if (mux) - lv->set_part(mux, 8); - else - lv->set_part(new NetEConst(verinum(lsb)), 8); + if (!mux) + mux = new NetEConst(verinum(lsb)); + lv->set_part(mux, &netvector_t::atom2s8); } else if (mux) { ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE); @@ -1180,6 +1179,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, // increases, and use_width shrinks. unsigned long off = 0; unsigned long use_width = struct_type->packed_width(); + ivl_type_t member_type; pform_name_t completed_path; do { @@ -1251,6 +1251,8 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, return false; } + member_type = member->net_type; + if (const netvector_t*mem_vec = dynamic_cast(member->net_type)) { // If the member type is a netvector_t, then it is a // vector of atom or scaler objects. For example, if the @@ -1320,6 +1322,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, off += loff; use_width = lwid * tail_wid; + member_type = nullptr; } // The netvector_t only has atom elements, to @@ -1484,7 +1487,11 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, } if (packed_base == 0) { - lv->set_part(new NetEConst(verinum(off)), use_width); + NetExpr *base = new NetEConst(verinum(off)); + if (member_type) + lv->set_part(base, member_type); + else + lv->set_part(base, use_width); return true; } diff --git a/net_assign.cc b/net_assign.cc index e586e36df..fc8ffdb55 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -126,10 +126,6 @@ unsigned NetAssign_::lwidth() const ivl_variable_type_t NetAssign_::expr_type() const { ivl_type_t ntype = net_type(); - - if (sig_ && sig_->data_type()==IVL_VT_STRING && base_!=0) - return IVL_VT_BOOL; - if (ntype) return ntype->base_type(); @@ -139,10 +135,14 @@ ivl_variable_type_t NetAssign_::expr_type() const ivl_type_t NetAssign_::net_type() const { - // This is a concatenation or a part select, it does not have a type - if (more || base_) + // This is a concatenation, it does not have a type + if (more) return nullptr; + // Selected sub-vector can have its own data type + if (base_) + return part_data_type_; + ivl_type_t ntype; if (nest_) { ntype = nest_->net_type(); @@ -200,6 +200,12 @@ void NetAssign_::set_part(NetExpr*base, unsigned wid, sel_type_ = sel_type; } +void NetAssign_::set_part(NetExpr*base, ivl_type_t data_type) +{ + part_data_type_ = data_type; + set_part(base, part_data_type_->packed_width()); +} + void NetAssign_::set_property(const perm_string&mname, unsigned idx) { member_ = mname; diff --git a/netlist.h b/netlist.h index aeedacf33..14e28832c 100644 --- a/netlist.h +++ b/netlist.h @@ -2836,6 +2836,11 @@ class NetAssign_ { // that the expression calculates a CANONICAL bit address. void set_part(NetExpr* loff, unsigned wid, ivl_select_type_t = IVL_SEL_OTHER); + // Set a part select expression for the l-value vector. Note + // that the expression calculates a CANONICAL bit address. + // The part select has a specific type and the width of the select will + // be that of the type. + void set_part(NetExpr *loff, ivl_type_t data_type); // Set the member or property name if the signal type is a // class. void set_property(const perm_string&name, unsigned int idx); @@ -2905,6 +2910,7 @@ class NetAssign_ { NetExpr*base_; unsigned lwid_; ivl_select_type_t sel_type_; + ivl_type_t part_data_type_ = nullptr; }; class NetAssignBase : public NetProc {