diff --git a/dup_expr.cc b/dup_expr.cc index 16b79f196..4e4f2225a 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -148,7 +148,7 @@ NetEConst* NetEConst::dup_expr() const NetEConstEnum* NetEConstEnum::dup_expr() const { - NetEConstEnum*tmp = new NetEConstEnum(name_, enum_set_, value()); + NetEConstEnum*tmp = new NetEConstEnum(name_, enumeration(), value()); ivl_assert(*this, tmp); tmp->set_line(*this); return tmp; diff --git a/elab_expr.cc b/elab_expr.cc index 49d7e6166..0dc689e3e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -116,7 +116,9 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, << endl; } + NetExpr *rval; int context_wid = -1; + bool fallback = true; switch (lv_type) { case IVL_VT_DARRAY: case IVL_VT_QUEUE: @@ -124,8 +126,11 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, // For these types, use a different elab_and_eval that // uses the lv_net_type. We should eventually transition // all the types to this new form. - if (lv_net_type) - return elab_and_eval(des, scope, expr, lv_net_type, need_const); + if (lv_net_type) { + rval = elab_and_eval(des, scope, expr, lv_net_type, need_const); + fallback = false; + } + break; case IVL_VT_REAL: case IVL_VT_STRING: @@ -140,8 +145,26 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, break; } - return elab_and_eval(des, scope, expr, context_wid, need_const, - false, lv_type, force_unsigned); + if (fallback) { + rval = elab_and_eval(des, scope, expr, context_wid, need_const, + false, lv_type, force_unsigned); + } + + const netenum_t *lval_enum = dynamic_cast(lv_net_type); + if (lval_enum) { + const netenum_t *rval_enum = rval->enumeration(); + if (!rval_enum) { + cerr << expr->get_fileline() << ": error: " + "This assignment requires an explicit cast." << endl; + des->errors += 1; + } else if (!lval_enum->matches(rval_enum)) { + cerr << expr->get_fileline() << ": error: " + "Enumeration type mismatch in assignment." << endl; + des->errors += 1; + } + } + + return rval; } /* diff --git a/elab_lval.cc b/elab_lval.cc index bc6c24396..16604aba5 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -596,10 +596,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); @@ -1171,6 +1170,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 { @@ -1242,6 +1242,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 @@ -1311,6 +1313,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 @@ -1475,7 +1478,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/elaborate.cc b/elaborate.cc index f3232c951..bf285903c 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -150,18 +150,6 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const return; } - if (lval->enumeration()) { - if (! rval_expr->enumeration()) { - cerr << get_fileline() << ": error: " - "This assignment requires an explicit cast." << endl; - des->errors += 1; - } else if (! lval->enumeration()->matches(rval_expr->enumeration())) { - cerr << get_fileline() << ": error: " - "Enumeration type mismatch in assignment." << endl; - des->errors += 1; - } - } - NetNet*rval = rval_expr->synthesize(des, scope, rval_expr); if (rval == 0) { @@ -2395,7 +2383,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, { ivl_assert(*this, rval_); - NetExpr*rv = elab_and_eval(des, scope, rval_, net_type, is_constant_); + NetExpr*rv = elaborate_rval_expr(des, scope, net_type, rval_, + is_constant_); if (!is_constant_ || !rv) return rv; @@ -2416,10 +2405,6 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, { ivl_assert(*this, rval_); - // Don't have a good value for the lv_net_type argument to - // elaborate_rval_expr, so punt and pass nil. In the future we - // should look into fixing calls to this method to pass a - // net_type instead of the separate lv_width/lv_type values. NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width, rval(), is_constant_, force_unsigned); @@ -2790,18 +2775,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const return bl; } - if (lv->enumeration()) { - if (! rv->enumeration()) { - cerr << get_fileline() << ": error: " - "This assignment requires an explicit cast." << endl; - des->errors += 1; - } else if (! lv->enumeration()->matches(rv->enumeration())) { - cerr << get_fileline() << ": error: " - "Enumeration type mismatch in assignment." << endl; - des->errors += 1; - } - } - NetAssign*cur = new NetAssign(lv, rv); cur->set_line(*this); @@ -2851,7 +2824,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const << endl; } - NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv)); + NetExpr*rv = elaborate_rval_(des, scope, lv->net_type(), lv->expr_type(), count_lval_width(lv)); if (rv == 0) return 0; NetExpr*delay = 0; @@ -4481,11 +4454,7 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const unsigned lwid = count_lval_width(lval); ivl_variable_type_t ltype = lval->expr_type(); - // Need to figure out a better thing to do about the - // lv_net_type argument to elaborate_rval_expr here. This - // would entail getting the NetAssign_ to give us an - // ivl_type_t as needed. - NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_); + NetExpr*rexp = elaborate_rval_expr(des, scope, lval->net_type(), ltype, lwid, expr_); if (rexp == 0) return 0; diff --git a/ivtest/ivltests/enum_compatibility4.v b/ivtest/ivltests/enum_compatibility4.v new file mode 100644 index 000000000..0bb059c4b --- /dev/null +++ b/ivtest/ivltests/enum_compatibility4.v @@ -0,0 +1,23 @@ +// Check that assigning to a enum types variable from an enum typed class +// array element works. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + E e; + E ea[2]; + + initial begin + ea[0] = B; + e = ea[0]; + if (e === B) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility5.v b/ivtest/ivltests/enum_compatibility5.v new file mode 100644 index 000000000..29287c7cd --- /dev/null +++ b/ivtest/ivltests/enum_compatibility5.v @@ -0,0 +1,25 @@ +// Check that assigning to a enum types variable from an enum typed function +// call works. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + function E f(); + return B; + endfunction + + E e; + + initial begin + e = f(); + if (e === B) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility6.v b/ivtest/ivltests/enum_compatibility6.v new file mode 100644 index 000000000..72a4c1181 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility6.v @@ -0,0 +1,21 @@ +// Check that passing an enum type task argument works. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + task t(E e); + if (e === B) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + endtask + + initial begin + t(B); + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility7.v b/ivtest/ivltests/enum_compatibility7.v new file mode 100644 index 000000000..875dcb9ee --- /dev/null +++ b/ivtest/ivltests/enum_compatibility7.v @@ -0,0 +1,26 @@ +// Check that assigning to a enum types variable from an enum typed struct +// member works. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + struct packed { + E e; + } s; + + E e; + + initial begin + s.e = B; + e = s.e; + if (e === B) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility8.v b/ivtest/ivltests/enum_compatibility8.v new file mode 100644 index 000000000..94421437f --- /dev/null +++ b/ivtest/ivltests/enum_compatibility8.v @@ -0,0 +1,28 @@ +// Check that assigning to a enum types variable from an enum typed class +// property works. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + class C; + E e; + endclass + + C c; + E e; + + initial begin + c = new; + c.e = B; + e = c.e; + if (e === B) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail.v b/ivtest/ivltests/enum_compatibility_fail1.v similarity index 100% rename from ivtest/ivltests/enum_compatibility_fail.v rename to ivtest/ivltests/enum_compatibility_fail1.v diff --git a/ivtest/ivltests/enum_compatibility_fail2.v b/ivtest/ivltests/enum_compatibility_fail2.v new file mode 100644 index 000000000..c1f9cba93 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail2.v @@ -0,0 +1,17 @@ +// Check that an error is reported for implicit cast to enum when assigning +// to an array element. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + E ea[2]; + + initial begin + ea[0] = 10; // This should fail. Implicit cast to enum. + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail3.v b/ivtest/ivltests/enum_compatibility_fail3.v new file mode 100644 index 000000000..f005e1afb --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail3.v @@ -0,0 +1,19 @@ +// Check that an error is reported for implicit cast to enum when assigning +// from an array element. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + E e; + int ea[2]; + + initial begin + ea[0] = B; // This is OK. + e = ea[0]; // This should fail. Implicit cast to enum. + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail4.v b/ivtest/ivltests/enum_compatibility_fail4.v new file mode 100644 index 000000000..341b6b3d0 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail4.v @@ -0,0 +1,21 @@ +// Check that an error is reported for implicit cast to enum when assigning +// from a function call. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + function integer f(); + return B; + endfunction + + E e; + + initial begin + e = f(); // This should fail. Implicit cast to enum type. + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail5.v b/ivtest/ivltests/enum_compatibility_fail5.v new file mode 100644 index 000000000..e12bed9f2 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail5.v @@ -0,0 +1,17 @@ +// Check that an error is reported for implicit cast to enum for task arguments. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + task t(E e); + $display("FAILED"); + endtask + + initial begin + t(10); // This should fail. Implicit cast to enum. + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail6.v b/ivtest/ivltests/enum_compatibility_fail6.v new file mode 100644 index 000000000..1619b9f63 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail6.v @@ -0,0 +1,19 @@ +// Check that an error is reported for implicit cast to enum when assigning to +// struct members. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + struct packed { + E e; + } s; + + initial begin + s.e = 10; // This should fail. Implicit cast to enum. + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail7.v b/ivtest/ivltests/enum_compatibility_fail7.v new file mode 100644 index 000000000..d456bb7a2 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail7.v @@ -0,0 +1,22 @@ +// Check that an error is reported for implicit cast to enum when assigning to +// class properties. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + class C; + E e; + endclass + + C c; + + initial begin + c = new; + c.e = 10; // This should fail. Implicit cast to enum. + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail8.v b/ivtest/ivltests/enum_compatibility_fail8.v new file mode 100644 index 000000000..e487af825 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail8.v @@ -0,0 +1,21 @@ +// Check that an error is reported for implicit cast to enum in function return +// statements. + +module test; + + typedef enum reg [31:0] { + A, B + } E; + + function E f(); + return 10; // This should fail. Implicit cast to enum. + endfunction + + E e; + + initial begin + e = f(); + $display("FAILED"); + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 8779ecccc..a78c4db97 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -278,7 +278,19 @@ enum_base_typename2 normal,-g2005-sv ivltests enum_compatibility1 normal,-g2005-sv ivltests enum_compatibility2 normal,-g2005-sv ivltests enum_compatibility3 normal,-g2005-sv ivltests -enum_compatibility_fail CE,-g2005-sv ivltests +enum_compatibility4 normal,-g2005-sv ivltests +enum_compatibility5 normal,-g2005-sv ivltests +enum_compatibility6 normal,-g2005-sv ivltests +enum_compatibility7 normal,-g2005-sv ivltests +enum_compatibility8 normal,-g2005-sv ivltests +enum_compatibility_fail1 CE,-g2005-sv ivltests +enum_compatibility_fail2 CE,-g2005-sv ivltests +enum_compatibility_fail3 CE,-g2005-sv ivltests +enum_compatibility_fail4 CE,-g2005-sv ivltests +enum_compatibility_fail5 CE,-g2005-sv ivltests +enum_compatibility_fail6 CE,-g2005-sv ivltests +enum_compatibility_fail7 CE,-g2005-sv ivltests +enum_compatibility_fail8 CE,-g2005-sv ivltests enum_elem_ranges normal,-g2005-sv ivltests enum_dims_invalid CE,-g2005-sv ivltests enum_in_struct normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 6f6938d5a..d3d42d576 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -390,6 +390,7 @@ br_gh391 CE,-g2009 ivltests br_gh437 CE,-g2009 ivltests br_gh445 CE,-g2009 ivltests br_gh461 CE,-g2009 ivltests +enum_compatibility8 CE,-g2005-sv ivltests enum_in_class CE,-g2005-sv ivltests enum_in_class_name_coll CE,-g2005-sv ivltests sv_class1 CE,-g2009 ivltests diff --git a/net_assign.cc b/net_assign.cc index 45379b265..6f8334d77 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -22,6 +22,7 @@ # include "netlist.h" # include "netclass.h" # include "netdarray.h" +# include "netparray.h" # include "netenum.h" # include "ivl_assert.h" @@ -116,105 +117,59 @@ unsigned NetAssign_::lwidth() const // the type of the member. If this returns nil, then resort to // the lwid_ value. ivl_type_t ntype = net_type(); - if (ntype == 0) - return lwid_; + if (ntype) + return ntype->packed_width(); - // If the type is a darray, and there is a word index, then we - // actually want the width of the elements. - if (const netdarray_t*darray = dynamic_cast (ntype)) { - if (word_ == 0) - return 1; - else - return darray->element_width(); - } - - return ntype->packed_width(); + return lwid_; } ivl_variable_type_t NetAssign_::expr_type() const { ivl_type_t ntype = net_type(); - if (const netdarray_t*darray = dynamic_cast(ntype)) { - if (word_ == 0) - return IVL_VT_DARRAY; - else - return darray->element_base_type(); - } - - if (sig_ && sig_->data_type()==IVL_VT_STRING && base_!=0) - return IVL_VT_BOOL; - - if (ntype) return ntype->base_type(); + if (ntype) + return ntype->base_type(); ivl_assert(*this, sig_); return sig_->data_type(); } -const ivl_type_s* NetAssign_::net_type() const +ivl_type_t NetAssign_::net_type() const { + // 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_) { - const ivl_type_s*ntype = nest_->net_type(); - if (member_.nil()) - return ntype; - - if (const netclass_t*class_type = dynamic_cast(ntype)) { - return class_type->get_prop_type(member_idx_); - } - - if (const netdarray_t*darray = dynamic_cast (ntype)) { - if (word_ == 0) - return ntype; - else - return darray->element_type(); - } - - return 0; - } - - if (const netclass_t*class_type = sig_->class_type()) { - if (member_.nil()) - return sig_->net_type(); - - return class_type->get_prop_type(member_idx_); - } - - if (const netdarray_t*darray = dynamic_cast (sig_->net_type())) { - if (word_ == 0) - return sig_->net_type(); - else - return darray->element_type(); - } - - return 0; -} - -const netenum_t*NetAssign_::enumeration() const -{ - const netenum_t*tmp = 0; - ivl_type_t ntype = net_type(); - if (ntype == 0) { - + ntype = nest_->net_type(); + } else { ivl_assert(*this, sig_); - // If the base signal is not an enumeration, return nil. - if ( (tmp = sig_->enumeration()) == 0 ) - return 0; + // We don't have types for array signals yet. + if (sig_->unpacked_dimensions() && !word_) + return nullptr; - } else { - tmp = dynamic_cast(ntype); - if (tmp == 0) - return 0; + ntype = sig_->net_type(); } - // Part select of an enumeration is not an enumeration. - if (base_ != 0) - return 0; + if (!member_.nil()) { + const netclass_t *class_type = dynamic_cast(ntype); + ivl_assert(*this, class_type); + ntype = class_type->get_prop_type(member_idx_); + } - // Concatenation of enumerations is not an enumeration. - if (more != 0) - return 0; + if (word_) { + if (const netdarray_t *darray = dynamic_cast(ntype)) + ntype = darray->element_type(); + else if (const netuarray_t *uarray = dynamic_cast(ntype)) + ntype = uarray->element_type(); + } - return tmp; + return ntype; } perm_string NetAssign_::name() const @@ -240,6 +195,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/net_expr.cc b/net_expr.cc index 25f10dcb5..e398fa42b 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -38,6 +38,10 @@ NetExpr::NetExpr(unsigned w) NetExpr::NetExpr(ivl_type_t t) : net_type_(t), width_(0), signed_flag_(false) { + if (t) { + width_ = t->packed_width(); + signed_flag_ = t->get_signed(); + } } NetExpr::~NetExpr() @@ -49,6 +53,15 @@ ivl_type_t NetExpr::net_type() const return net_type_; } +void NetExpr::set_net_type(ivl_type_t type) +{ + net_type_ = type; + if (type) { + width_ = type->packed_width(); + signed_flag_ = type->get_signed(); + } +} + void NetExpr::cast_signed(bool flag) { cast_signed_base_(flag); @@ -72,7 +85,7 @@ ivl_variable_type_t NetExpr::expr_type() const const netenum_t*NetExpr::enumeration() const { - return 0; + return dynamic_cast(net_type_); } NetEArrayPattern::NetEArrayPattern(ivl_type_t lv_type, vector&items) @@ -258,8 +271,9 @@ void NetEConcat::set(unsigned idx, NetExpr*e) expr_width( expr_width() + repeat_ * e->expr_width() ); } -NetEConstEnum::NetEConstEnum(perm_string n, const netenum_t*eset, const verinum&v) -: NetEConst(v), enum_set_(eset), name_(n) +NetEConstEnum::NetEConstEnum(perm_string n, const netenum_t *enum_set, + const verinum &val) +: NetEConst(enum_set, val), name_(n) { assert(has_width()); } @@ -268,11 +282,6 @@ NetEConstEnum::~NetEConstEnum() { } -const netenum_t*NetEConstEnum::enumeration() const -{ - return enum_set_; -} - NetECReal::NetECReal(const verireal&val) : value_(val) { @@ -356,12 +365,12 @@ const netenum_t* NetENetenum::netenum() const } NetENew::NetENew(ivl_type_t t) -: obj_type_(t), size_(0), init_val_(0) +: NetExpr(t), size_(0), init_val_(0) { } NetENew::NetENew(ivl_type_t t, NetExpr*size, NetExpr*init_val) -: obj_type_(t), size_(size), init_val_(init_val) +: NetExpr(t), size_(size), init_val_(init_val) { } @@ -389,33 +398,23 @@ NetEProperty::NetEProperty(NetNet*net, size_t pidx, NetExpr*idx) assert(use_type); ivl_type_t prop_type = use_type->get_prop_type(pidx_); - expr_width(prop_type->packed_width()); - cast_signed(prop_type->get_signed()); + set_net_type(prop_type); } NetEProperty::~NetEProperty() { } -ivl_variable_type_t NetEProperty::expr_type() const -{ - const netclass_t*use_type = dynamic_cast(net_->net_type()); - assert(use_type); - - ivl_type_t prop_type = use_type->get_prop_type(pidx_); - return prop_type->base_type(); -} - NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid, ivl_select_type_t sel_type) -: expr_(exp), base_(base), use_type_(0), sel_type_(sel_type) +: expr_(exp), base_(base), sel_type_(sel_type) { expr_width(wid); } NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid, ivl_type_t use_type) -: expr_(exp), base_(base), use_type_(use_type), sel_type_(IVL_SEL_OTHER) +: NetExpr(use_type), expr_(exp), base_(base), sel_type_(IVL_SEL_OTHER) { expr_width(wid); } @@ -443,8 +442,8 @@ ivl_select_type_t NetESelect::select_type() const ivl_variable_type_t NetESelect::expr_type() const { - if (use_type_) - return use_type_->base_type(); + if (net_type()) + return net_type()->base_type(); ivl_variable_type_t type = expr_->expr_type(); @@ -457,27 +456,19 @@ ivl_variable_type_t NetESelect::expr_type() const return type; } -const netenum_t* NetESelect::enumeration() const -{ - return dynamic_cast (use_type_); -} - NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t, unsigned width, unsigned np, bool is_overridden) -: name_(0), type_(t), enum_type_(0), parms_(np), is_overridden_(is_overridden) +: name_(0), type_(t), parms_(np), is_overridden_(is_overridden) { name_ = lex_strings.add(n); expr_width(width); } NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np) -: NetExpr(rtype), name_(0), type_(rtype->base_type()), - enum_type_(dynamic_cast(rtype)), parms_(np), +: NetExpr(rtype), name_(0), type_(rtype->base_type()), parms_(np), is_overridden_(false) { name_ = lex_strings.add(n); - expr_width(rtype->packed_width()); - cast_signed_base_(rtype->get_signed()); } NetESFunc::~NetESFunc() @@ -523,11 +514,6 @@ ivl_variable_type_t NetESFunc::expr_type() const return type_; } -const netenum_t* NetESFunc::enumeration() const -{ - return enum_type_; -} - NetEShallowCopy::NetEShallowCopy(NetExpr*arg1, NetExpr*arg2) : arg1_(arg1), arg2_(arg2) { diff --git a/netlist.cc b/netlist.cc index bd9ef6168..b1daa0b95 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2156,10 +2156,8 @@ const NetExpr* NetSTask::parm(unsigned idx) const NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res, vector&p, bool nc) -: scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc) +: NetExpr(res->net_type()), scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc) { - expr_width(result_sig_->expr_width()); - cast_signed_base_(result_sig_->has_sign()); } NetEUFunc::~NetEUFunc() @@ -2194,22 +2192,6 @@ const NetScope* NetEUFunc::func() const return func_; } -ivl_variable_type_t NetEUFunc::expr_type() const -{ - if (result_sig_) - return result_sig_->expr_type(); - - return IVL_VT_VOID; -} - -const netenum_t* NetEUFunc::enumeration() const -{ - if (result_sig_) - return result_sig_->enumeration(); - - return 0; -} - NetUTask::NetUTask(NetScope*def) : task_(def) { @@ -2308,6 +2290,14 @@ NetEConst::NetEConst(const verinum&val) cast_signed_base_(value_.has_sign()); } +NetEConst::NetEConst(ivl_type_t type, const verinum&val) +: NetExpr(type), value_(val) +{ + ivl_assert(*this, type->packed()); + ivl_assert(*this, type->packed_width() == val.len()); + ivl_assert(*this, type->get_signed() == val.has_sign()); +} + NetEConst::~NetEConst() { } @@ -2401,11 +2391,10 @@ const NetScope* NetEScope::scope() const } NetESignal::NetESignal(NetNet*n) -: NetExpr(n->vector_width()), net_(n), enum_type_(n->enumeration()), word_(0) +: NetExpr(n->net_type()), net_(n), word_(0) { net_->incr_eref(); set_line(*n); - cast_signed_base_(net_->get_signed()); } NetESignal::NetESignal(NetNet*n, NetExpr*w) @@ -2413,7 +2402,11 @@ NetESignal::NetESignal(NetNet*n, NetExpr*w) { net_->incr_eref(); set_line(*n); - cast_signed_base_(net_->get_signed()); + + // If it is an array we don't have a type for it yet. But for array + // elements the NetNet returns the element type. + if (word_) + set_net_type(net_->net_type()); } NetESignal::~NetESignal() @@ -2426,11 +2419,6 @@ perm_string NetESignal::name() const return net_->name(); } -const netenum_t* NetESignal::enumeration() const -{ - return enum_type_; -} - const NetExpr* NetESignal::word_index() const { return word_; diff --git a/netlist.h b/netlist.h index 37fd61f48..56ae221ff 100644 --- a/netlist.h +++ b/netlist.h @@ -2077,6 +2077,7 @@ class NetExpr : public LineInfo { protected: void expr_width(unsigned wid) { width_ = wid; } void cast_signed_base_(bool flag) { signed_flag_ = flag; } + void set_net_type(ivl_type_t type); private: ivl_type_t net_type_; @@ -2116,6 +2117,7 @@ class NetEArrayPattern : public NetExpr { class NetEConst : public NetExpr { public: + explicit NetEConst(ivl_type_t type, const verinum&val); explicit NetEConst(const verinum&val); ~NetEConst(); @@ -2153,7 +2155,6 @@ class NetEConstEnum : public NetEConst { ~NetEConstEnum(); perm_string name() const; - const netenum_t*enumeration() const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(std::ostream&) const; @@ -2161,7 +2162,6 @@ class NetEConstEnum : public NetEConst { virtual NetEConstEnum* dup_expr() const; private: - const netenum_t*enum_set_; perm_string name_; }; @@ -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); @@ -2856,11 +2861,7 @@ class NetAssign_ { // Get the expression type of the l-value. This may be // different from the type of the contained signal if for // example a darray is indexed. - const ivl_type_s* net_type() const; - - // Return the enumeration type of this l-value, or nil if it's - // not an enumeration. - const netenum_t*enumeration() const; + ivl_type_t net_type() const; // Get the name of the underlying object. perm_string name() const; @@ -2905,6 +2906,7 @@ class NetAssign_ { NetExpr*base_; unsigned lwid_; ivl_select_type_t sel_type_; + ivl_type_t part_data_type_ = nullptr; }; class NetAssignBase : public NetProc { @@ -3924,8 +3926,6 @@ class NetEUFunc : public NetExpr { const NetScope* func() const; - virtual ivl_variable_type_t expr_type() const; - virtual const netenum_t* enumeration() const; virtual void dump(std::ostream&) const; virtual void expr_scan(struct expr_scan_t*) const; @@ -4470,7 +4470,6 @@ class NetESelect : public NetExpr { // sub-expression. The type of an array/member select is // the base type of the element/member. virtual ivl_variable_type_t expr_type() const; - virtual const netenum_t* enumeration() const; virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false, bool nested_func = false) const; @@ -4485,7 +4484,6 @@ class NetESelect : public NetExpr { private: NetExpr*expr_; NetExpr*base_; - ivl_type_t use_type_; ivl_select_type_t sel_type_; }; @@ -4543,7 +4541,6 @@ class NetENew : public NetExpr { explicit NetENew(ivl_type_t, NetExpr*size, NetExpr* init_val=0); ~NetENew(); - inline ivl_type_t get_type() const { return obj_type_; } inline const NetExpr*size_expr() const { return size_; } inline const NetExpr*init_expr() const { return init_val_; } @@ -4557,7 +4554,6 @@ class NetENew : public NetExpr { virtual void dump(std::ostream&os) const; private: - ivl_type_t obj_type_; NetExpr*size_; NetExpr*init_val_; }; @@ -4598,7 +4594,6 @@ class NetEProperty : public NetExpr { inline const NetExpr*get_index() const { return index_; } public: // Overridden methods - ivl_variable_type_t expr_type() const; virtual void expr_scan(struct expr_scan_t*) const; virtual NetEProperty* dup_expr() const; virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false, @@ -4663,7 +4658,6 @@ class NetESFunc : public NetExpr { virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false, bool nested_func = false) const; - virtual const netenum_t* enumeration() const; virtual void dump(std::ostream&) const; virtual void expr_scan(struct expr_scan_t*) const; @@ -4739,7 +4733,6 @@ class NetESFunc : public NetExpr { const char* name_; ivl_variable_type_t type_; - const netenum_t*enum_type_; std::vectorparms_; bool is_overridden_; @@ -4969,7 +4962,6 @@ class NetESignal : public NetExpr { bool nested_func = false) const; NexusSet* nex_input_base(bool rem_out, bool always_sens, bool nested_func, unsigned base, unsigned width) const; - const netenum_t*enumeration() const; virtual NetExpr*evaluate_function(const LineInfo&loc, std::map&ctx) const; @@ -4994,7 +4986,6 @@ class NetESignal : public NetExpr { private: NetNet*net_; - const netenum_t*enum_type_; // Expression to select a word from the net. NetExpr*word_; }; diff --git a/t-dll-expr.cc b/t-dll-expr.cc index f46dd9c9e..96dd59bc0 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -403,7 +403,7 @@ void dll_target::expr_new(const NetENew*net) expr_->type_ = IVL_EX_NEW; FILE_NAME(expr_, net); expr_->value_ = net->expr_type(); // May be IVL_VT_DARRAY or _CLASS - expr_->net_type= net->get_type(); + expr_->net_type= net->net_type(); expr_->u_.new_.size = size; expr_->u_.new_.init_val = init_val; }