Merge pull request #862 from larsclausen/enum-compat-check
Improve enum compatbility checks
This commit is contained in:
commit
18192fdba9
|
|
@ -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;
|
||||
|
|
|
|||
29
elab_expr.cc
29
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,10 +145,28 @@ 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,
|
||||
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<const netenum_t*>(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the mode is UPSIZE, make sure the final expression width is at
|
||||
* least integer_width, but return the calculated lossless width to
|
||||
|
|
|
|||
17
elab_lval.cc
17
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<const netvector_t*>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
39
elaborate.cc
39
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
119
net_assign.cc
119
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 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<const netdarray_t*> (ntype)) {
|
||||
if (word_ == 0)
|
||||
return 1;
|
||||
else
|
||||
return darray->element_width();
|
||||
}
|
||||
|
||||
if (ntype)
|
||||
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<const netdarray_t*>(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<const netclass_t*>(ntype)) {
|
||||
return class_type->get_prop_type(member_idx_);
|
||||
}
|
||||
|
||||
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (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<const netdarray_t*> (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<const netenum_t*>(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<const netclass_t*>(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<const netdarray_t*>(ntype))
|
||||
ntype = darray->element_type();
|
||||
else if (const netuarray_t *uarray = dynamic_cast<const netuarray_t*>(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;
|
||||
|
|
|
|||
66
net_expr.cc
66
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<const netenum_t*>(net_type_);
|
||||
}
|
||||
|
||||
NetEArrayPattern::NetEArrayPattern(ivl_type_t lv_type, vector<NetExpr*>&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<const netclass_t*>(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<const netenum_t*> (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<const netenum_t*>(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)
|
||||
{
|
||||
|
|
|
|||
42
netlist.cc
42
netlist.cc
|
|
@ -2156,10 +2156,8 @@ const NetExpr* NetSTask::parm(unsigned idx) const
|
|||
|
||||
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
|
||||
vector<NetExpr*>&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_;
|
||||
|
|
|
|||
27
netlist.h
27
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::vector<NetExpr*>parms_;
|
||||
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<perm_string,LocalVar>&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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue