diff --git a/PExpr.h b/PExpr.h index 6420e057d..93ddae44d 100644 --- a/PExpr.h +++ b/PExpr.h @@ -1007,6 +1007,7 @@ class PECastType : public PExpr { private: data_type_t* target_; + ivl_type_t target_type_; PExpr* base_; }; diff --git a/dup_expr.cc b/dup_expr.cc index 64afcba7e..16b79f196 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(scope_, name_, enum_set_, value()); + NetEConstEnum*tmp = new NetEConstEnum(name_, enum_set_, value()); ivl_assert(*this, tmp); tmp->set_line(*this); return tmp; diff --git a/elab_expr.cc b/elab_expr.cc index ca71a89b6..a6cb6b447 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1969,8 +1969,7 @@ static NetExpr* check_for_enum_methods(const LineInfo*li, des->errors += 1; } netenum_t::iterator item = netenum->first_name(); - NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, - netenum, item->second); + NetEConstEnum*tmp = new NetEConstEnum(item->first, netenum, item->second); tmp->set_line(*li); delete expr; // The elaborated enum variable is not needed. return tmp; @@ -1987,8 +1986,7 @@ static NetExpr* check_for_enum_methods(const LineInfo*li, des->errors += 1; } netenum_t::iterator item = netenum->last_name(); - NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, - netenum, item->second); + NetEConstEnum*tmp = new NetEConstEnum(item->first, netenum, item->second); tmp->set_line(*li); delete expr; // The elaborated enum variable is not needed. return tmp; @@ -3351,25 +3349,25 @@ NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope, unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&) { - ivl_type_t t = target_->elaborate_type(des, scope); + target_type_ = target_->elaborate_type(des, scope); width_mode_t tmp_mode = PExpr::SIZED; base_->test_width(des, scope, tmp_mode); - if (const netdarray_t*use_darray = dynamic_cast(t)) { + if (const netdarray_t*use_darray = dynamic_cast(target_type_)) { expr_type_ = use_darray->element_base_type(); expr_width_ = use_darray->element_width(); - } else if (const netstring_t*use_string = dynamic_cast(t)) { + } else if (const netstring_t*use_string = dynamic_cast(target_type_)) { expr_type_ = use_string->base_type(); expr_width_ = 8; } else { - expr_type_ = t->base_type(); - expr_width_ = t->packed_width(); + expr_type_ = target_type_->base_type(); + expr_width_ = target_type_->packed_width(); } min_width_ = expr_width_; - signed_flag_ = t->get_signed(); + signed_flag_ = target_type_->get_signed(); return expr_width_; } @@ -3427,11 +3425,8 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, } NetExpr*tmp = 0; - if (dynamic_cast(target_)) { - tmp = cast_to_int2(sub, expr_width_); - } - if (const vector_type_t*vec = dynamic_cast(target_)) { - switch (vec->base_type) { + if (target_type_ && target_type_->packed()) { + switch (target_type_->base_type()) { case IVL_VT_BOOL: tmp = cast_to_int2(sub, expr_width_); break; @@ -3452,7 +3447,7 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, // the signedness pushed down from the main expression. tmp = cast_to_width(sub, expr_width_, sub->has_sign(), *this); } - return pad_to_width(tmp, expr_wid, signed_flag_, *this); + return pad_to_width(tmp, expr_wid, signed_flag_, *this, target_type_); } if (dynamic_cast(target_)) { diff --git a/ivtest/ivltests/br_gh130b.v b/ivtest/ivltests/br_gh130b.v index 7f40f0d22..cec7c6322 100644 --- a/ivtest/ivltests/br_gh130b.v +++ b/ivtest/ivltests/br_gh130b.v @@ -1,4 +1,4 @@ -// This is currently unsupported, but is legal code. +// Test that cast to enum works in procedural assignments module test(); typedef enum { a, b, c } enum_type; @@ -7,6 +7,12 @@ enum_type enum_value; initial begin enum_value = enum_type'(1); + + if (enum_value == b) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end end endmodule diff --git a/ivtest/ivltests/br_gh386d.v b/ivtest/ivltests/br_gh386d.v index ccd5771a7..992752911 100644 --- a/ivtest/ivltests/br_gh386d.v +++ b/ivtest/ivltests/br_gh386d.v @@ -1,4 +1,4 @@ -// This is currently unsupported, but is legal code. +// Test that cast to enum works in continuous assignments module test(); typedef enum { a, b, c } enum_type; @@ -7,4 +7,12 @@ enum_type enum_value; assign enum_value = enum_type'(1); +initial begin + if (enum_value == b) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end +end + endmodule diff --git a/ivtest/ivltests/sv_cast_packed_array.v b/ivtest/ivltests/sv_cast_packed_array.v new file mode 100644 index 000000000..17c5e4b29 --- /dev/null +++ b/ivtest/ivltests/sv_cast_packed_array.v @@ -0,0 +1,43 @@ +// This tests SystemVerilog casting support +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Iztok Jeras. +// Extended by Maciej Suminski +// Copied and modified by Martin Whitaker +// Copied and modified again by Lars-Peter Clausen + +module test(); + + typedef logic [7:0] pa08; + typedef pa08 [1:0] pa16; + typedef pa16 [1:0] pa32; + typedef pa32 [1:0] pa64; + + // variables used in casting + pa08 var_08; + pa16 var_16; + pa32 var_32; + pa64 var_64; + real var_real; + + // error counter + bit err = 0; + + initial begin + var_08 = pa08'(4'h5); if (var_08 !== 8'h05) begin $display("FAILED -- var_08 = 'h%0h != 8'h05", var_08); err=1; end + var_16 = pa16'(var_08); if (var_16 !== 16'h05) begin $display("FAILED -- var_16 = 'h%0h != 16'h05", var_16); err=1; end + var_32 = pa32'(var_16); if (var_32 !== 32'h05) begin $display("FAILED -- var_32 = 'h%0h != 32'h05", var_32); err=1; end + var_64 = pa64'(var_32); if (var_64 !== 64'h05) begin $display("FAILED -- var_64 = 'h%0h != 64'h05", var_64); err=1; end + + var_real = 13.4; var_08 = pa08'(var_real); if (var_08 !== 13) begin $display("FAILED -- var_08 = %d != 13", var_08); err=1; end + var_real = 14.5; var_16 = pa16'(var_real); if (var_16 !== 15) begin $display("FAILED -- var_16 = %d != 15", var_16); err=1; end + var_real = 15.6; var_32 = pa32'(var_real); if (var_32 !== 16) begin $display("FAILED -- var_32 = %d != 16", var_32); err=1; end + var_real = -15.6; var_64 = pa64'(var_real); if (var_64 !== -16) begin $display("FAILED -- var_64 = %d != -16", var_64); err=1; end + + var_08 = pa08'(4'hf); if (var_08 !== 8'h0f) begin $display("FAILED -- var_08 = 'h%0h != 8'h0f", var_08); err=1; end + var_16 = pa08'(16'h0f0f); if (var_16 !== 16'h0f) begin $display("FAILED -- var_16 = 'h%0h != 16'h0f", var_16); err=1; end + + if (!err) $display("PASSED"); + end + +endmodule // test diff --git a/ivtest/ivltests/sv_cast_packed_struct.v b/ivtest/ivltests/sv_cast_packed_struct.v new file mode 100644 index 000000000..4fe55672c --- /dev/null +++ b/ivtest/ivltests/sv_cast_packed_struct.v @@ -0,0 +1,45 @@ +// This tests SystemVerilog casting support +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Iztok Jeras. +// Extended by Maciej Suminski +// Copied and modified by Martin Whitaker +// Copied and modified again by Lars-Peter Clausen + +module test(); + + typedef struct packed signed { logic [7:0] x; } s08; + typedef struct packed signed { logic [15:0] x; } s16; + typedef struct packed signed { int x; } s32; + typedef struct packed signed { int x; shortint y; byte z; logic [7:0] w; } s64; + + // variables used in casting + s08 var_08; + s16 var_16; + s32 var_32; + s64 var_64; + real var_real; + + // error counter + bit err = 0; + + initial begin + var_08 = s08'(4'sh5); if (var_08 !== 8'sh05) begin $display("FAILED -- var_08 = 'h%0h != 8'h05", var_08); err=1; end + var_16 = s16'(var_08); if (var_16 !== 16'sh05) begin $display("FAILED -- var_16 = 'h%0h != 16'h05", var_16); err=1; end + var_32 = s32'(var_16); if (var_32 !== 32'sh05) begin $display("FAILED -- var_32 = 'h%0h != 32'h05", var_32); err=1; end + var_64 = s64'(var_32); if (var_64 !== 64'sh05) begin $display("FAILED -- var_64 = 'h%0h != 64'h05", var_64); err=1; end + + var_real = 13.4; var_08 = s08'(var_real); if (var_08 !== 13) begin $display("FAILED -- var_08 = %d != 13", var_08); err=1; end + var_real = 14.5; var_16 = s16'(var_real); if (var_16 !== 15) begin $display("FAILED -- var_16 = %d != 15", var_16); err=1; end + var_real = 15.6; var_32 = s32'(var_real); if (var_32 !== 16) begin $display("FAILED -- var_32 = %d != 16", var_32); err=1; end + var_real = -15.6; var_64 = s64'(var_real); if (var_64 !== -16) begin $display("FAILED -- var_64 = %d != -16", var_64); err=1; end + + var_08 = s08'(4'hf); if (var_08 !== 8'sh0f) begin $display("FAILED -- var_08 = 'h%0h != 8'h0f", var_08); err=1; end + var_08 = s08'(4'shf); if (var_08 !== 8'shff) begin $display("FAILED -- var_08 = 'h%0h != 8'hff", var_08); err=1; end + var_16 = s08'(16'h0f0f); if (var_16 !== 16'sh0f) begin $display("FAILED -- var_16 = 'h%0h != 16'h0f", var_16); err=1; end + var_16 = s08'(4'shf) + 'd0; if (var_16 !== 16'shff) begin $display("FAILED -- var_16 = 'h%0h != 16'hff", var_16); err=1; end + + if (!err) $display("PASSED"); + end + +endmodule // test diff --git a/ivtest/regress-fsv.list b/ivtest/regress-fsv.list index a6eb46a0e..777f40427 100644 --- a/ivtest/regress-fsv.list +++ b/ivtest/regress-fsv.list @@ -115,8 +115,6 @@ br605b normal ivltests br971 normal ivltests br1005 normal ivltests br1015b normal ivltests -br_gh130b normal ivltests -br_gh386d normal ivltests br_ml20150315b normal ivltests sv_deferred_assert1 normal ivltests sv_deferred_assert2 normal ivltests diff --git a/ivtest/regress-ivl1.list b/ivtest/regress-ivl1.list index 53304ecc0..97ead6058 100644 --- a/ivtest/regress-ivl1.list +++ b/ivtest/regress-ivl1.list @@ -294,8 +294,6 @@ br605b EF ivltests br971 EF ivltests br1005 CE,-g2009 ivltests br1015b CE,-g2009 ivltests -br_gh130b CE,-g2009 ivltests -br_gh386d CE,-g2009 ivltests br_ml20150315b CE,-g2009 ivltests sv_deferred_assert1 CE,-g2009 ivltests gold=sv_deferred_assert1.gold sv_deferred_assert2 CE,-g2009 ivltests gold=sv_deferred_assert2.gold diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 80d054047..b42729baf 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -149,6 +149,7 @@ br_gh112e normal,-g2009 ivltests br_gh112f normal,-g2009 ivltests br_gh129 normal,-g2009 ivltests br_gh130a CE,-g2009 ivltests +br_gh130b normal,-g2009 ivltests br_gh165 normal,-g2009 ivltests gold=br_gh165.gold br_gh164a normal,-g2009 ivltests br_gh164b normal,-g2009 ivltests @@ -184,6 +185,7 @@ br_gh374 normal,-g2009 ivltests gold=br_gh374.gold br_gh386a normal,-g2009 ivltests br_gh386b normal,-g2009 ivltests br_gh386c CE,-g2009 ivltests +br_gh386d normal,-g2009 ivltests br_gh388 normal,-g2009 ivltests gold=br_gh388.gold br_gh391 normal,-g2009 ivltests gold=br_gh391.gold br_gh411 normal,-g2009 ivltests @@ -388,6 +390,8 @@ sv-constants normal,-g2005-sv ivltests sv_array_assign_pattern2 normal,-g2009 ivltests sv_cast_integer normal,-g2005-sv ivltests sv_cast_integer2 normal,-g2005-sv ivltests +sv_cast_packed_array normal,-g2005-sv ivltests +sv_cast_packed_struct normal,-g2005-sv ivltests sv_cast_string normal,-g2005-sv ivltests sv_class1 normal,-g2009 ivltests sv_class2 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index a595d4969..402e8e351 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -118,6 +118,7 @@ cast_real_signed CE,-pallowsigned=1 ivltests cast_real_unsigned CE ivltests sv_cast_integer normal,-g2005-sv,-pallowsigned=1 ivltests sv_cast_integer2 normal,-g2005-sv,-pallowsigned=1 ivltests +sv_cast_packed_struct normal,-g2005-sv,-pallowsigned=1 ivltests sv_cast_string CE ivltests clog2 CE ivltests # Also big int delayed_sfunc CE ivltests @@ -733,6 +734,7 @@ br_gh99r normal,-pallowsigned=1 ivltests br_gh112e normal,-g2009,-pallowsigned=1 ivltests br_gh112f normal,-g2009,-pallowsigned=1 ivltests br_gh129 normal,-g2009,-pallowsigned=1 ivltests +br_gh130b normal,-g2009,-pallowsigned=1 ivltests br_gh198 normal,-pallowsigned=1 ivltests gold=br_gh198.gold br_gh199a normal,-pallowsigned=1 ivltests br_gh199b normal,-pallowsigned=1 ivltests @@ -743,6 +745,7 @@ br_gh283a normal,-pallowsigned=1 ivltests br_gh283b normal,-pallowsigned=1 ivltests br_gh283c normal,-pallowsigned=1 ivltests br_gh289b normal,-g2009,-pallowsigned=1 ivltests +br_gh386d normal,-g2009,-pallowsigned=1 ivltests br_gh477 normal,-g2009,-pallowsigned=1 ivltests br_gh540 normal,-g2009,-pallowsigned=1 ivltests ca_mult normal,-pallowsigned=1 ivltests gold=ca_mult.gold diff --git a/net_expr.cc b/net_expr.cc index f3c552fe6..4a0ee3008 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -263,8 +263,8 @@ void NetEConcat::set(unsigned idx, NetExpr*e) expr_width( expr_width() + repeat_ * e->expr_width() ); } -NetEConstEnum::NetEConstEnum(Definitions*s, perm_string n, const netenum_t*eset, const verinum&v) -: NetEConst(v), scope_(s), enum_set_(eset), name_(n) +NetEConstEnum::NetEConstEnum(perm_string n, const netenum_t*eset, const verinum&v) +: NetEConst(v), enum_set_(eset), name_(n) { assert(has_width()); } diff --git a/net_scope.cc b/net_scope.cc index d5e086c02..1a4216069 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -55,7 +55,7 @@ bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name) netenum_t::iterator enum_val = enum_set->find_name(name); assert(enum_val != enum_set->end_name()); - NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second); + NetEConstEnum*val = new NetEConstEnum(name, enum_set, enum_val->second); pair::iterator, bool> cur; cur = enum_names_.insert(make_pair(name,val)); diff --git a/netlist.h b/netlist.h index db53c9f55..85dc8ce8b 100644 --- a/netlist.h +++ b/netlist.h @@ -2153,8 +2153,8 @@ class NetEConst : public NetExpr { class NetEConstEnum : public NetEConst { public: - explicit NetEConstEnum(Definitions*scope, perm_string name, - const netenum_t*enum_set, const verinum&val); + explicit NetEConstEnum(perm_string name, const netenum_t*enum_set, + const verinum&val); ~NetEConstEnum(); perm_string name() const; @@ -2166,7 +2166,6 @@ class NetEConstEnum : public NetEConst { virtual NetEConstEnum* dup_expr() const; private: - Definitions*scope_; const netenum_t*enum_set_; perm_string name_; }; diff --git a/netmisc.h b/netmisc.h index 4a7d23f8a..17f3d20b9 100644 --- a/netmisc.h +++ b/netmisc.h @@ -161,13 +161,13 @@ inline NetScope* symbol_search(const LineInfo*li, * signed_flag. */ extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag, - const LineInfo&info); + const LineInfo&info, ivl_type_t use_type = 0); /* * This version determines the extension method from the base expression type. */ -inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info) +inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info, ivl_type_t use_type = 0) { - return pad_to_width(expr, wid, expr->has_sign(), info); + return pad_to_width(expr, wid, expr->has_sign(), info, use_type); } /* diff --git a/pad_to_width.cc b/pad_to_width.cc index 32db9e6c4..5ec66a862 100644 --- a/pad_to_width.cc +++ b/pad_to_width.cc @@ -19,15 +19,16 @@ # include "config.h" +# include "netenum.h" # include "netlist.h" # include "netvector.h" # include "netmisc.h" NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag, - const LineInfo&info) + const LineInfo&info, ivl_type_t use_type) { - if (wid <= expr->expr_width()) { + if (wid <= expr->expr_width() && !use_type) { expr->cast_signed(signed_flag); return expr; } @@ -38,13 +39,19 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag, verinum oval = tmp->value(); oval.has_sign(signed_flag); oval = pad_to_width(oval, wid); - tmp = new NetEConst(oval); + if (const netenum_t *enum_type = dynamic_cast(use_type)) { + // The name of the enum is set to here, but the name is + // only used in debugging output, so this is ok + tmp = new NetEConstEnum(perm_string(), enum_type, oval); + } else { + tmp = new NetEConst(oval); + } tmp->set_line(info); delete expr; return tmp; } - NetESelect*tmp = new NetESelect(expr, 0, wid); + NetESelect*tmp = new NetESelect(expr, 0, wid, use_type); tmp->cast_signed(signed_flag); tmp->set_line(info); return tmp;