Merge pull request #590 from larsclausen/packed-type-cast
Add support for explicit cast to packed array, packed struct and enum
This commit is contained in:
commit
9898bffd41
1
PExpr.h
1
PExpr.h
|
|
@ -1007,6 +1007,7 @@ class PECastType : public PExpr {
|
|||
|
||||
private:
|
||||
data_type_t* target_;
|
||||
ivl_type_t target_type_;
|
||||
PExpr* base_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
27
elab_expr.cc
27
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<const netdarray_t*>(t)) {
|
||||
if (const netdarray_t*use_darray = dynamic_cast<const netdarray_t*>(target_type_)) {
|
||||
expr_type_ = use_darray->element_base_type();
|
||||
expr_width_ = use_darray->element_width();
|
||||
|
||||
} else if (const netstring_t*use_string = dynamic_cast<const netstring_t*>(t)) {
|
||||
} else if (const netstring_t*use_string = dynamic_cast<const netstring_t*>(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<const atom2_type_t*>(target_)) {
|
||||
tmp = cast_to_int2(sub, expr_width_);
|
||||
}
|
||||
if (const vector_type_t*vec = dynamic_cast<const vector_type_t*>(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<const string_type_t*>(target_)) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
|
||||
cur = enum_names_.insert(make_pair(name,val));
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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<const netenum_t *>(use_type)) {
|
||||
// The name of the enum is set to <nil> 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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue