Fix implicit casts in assignments (part 1).
This patch adds support for implicit casts to the elaborate_rval_expr() function. This will handle the majority of cases where an implicit cast can occur.
This commit is contained in:
parent
03ebd2f98d
commit
22769afd20
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -111,7 +111,8 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return elab_and_eval(des, scope, expr, context_wid, need_const);
|
return elab_and_eval(des, scope, expr, context_wid, need_const,
|
||||||
|
false, lv_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
33
eval_tree.cc
33
eval_tree.cc
|
|
@ -1591,6 +1591,39 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetExpr* NetECast::eval_arguments_(const NetExpr*ex) const
|
||||||
|
{
|
||||||
|
NetExpr*res = 0;
|
||||||
|
switch (op_) {
|
||||||
|
case 'r':
|
||||||
|
if (const NetEConst*val = dynamic_cast<const NetEConst*>(ex)) {
|
||||||
|
verireal res_val = verireal(val->value().as_double());
|
||||||
|
res = new NetECReal(res_val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
if (const NetEConst*val = dynamic_cast<const NetEConst*>(ex)) {
|
||||||
|
verinum res_val(val->value());
|
||||||
|
res_val.cast_to_int2();
|
||||||
|
res = new NetEConst(res_val);
|
||||||
|
}
|
||||||
|
case 'v':
|
||||||
|
if (const NetECReal*val = dynamic_cast<const NetECReal*>(ex)) {
|
||||||
|
verinum res_val = verinum(val->value().as_double(), false);
|
||||||
|
res = new NetEConst(res_val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ivl_assert(*this, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (res == 0) return 0;
|
||||||
|
|
||||||
|
ivl_assert(*this, res);
|
||||||
|
eval_debug(this, res, op_ == 'r');
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
NetEConst* NetESFunc::evaluate_clog2_(const NetExpr*arg_) const
|
NetEConst* NetESFunc::evaluate_clog2_(const NetExpr*arg_) const
|
||||||
{
|
{
|
||||||
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
|
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -980,7 +980,10 @@ NetNet* NetECast::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
|
|
||||||
switch (op()) {
|
switch (op()) {
|
||||||
case 'v':
|
case 'v':
|
||||||
isig = cast_to_int4(des, scope, isig, isig->vector_width());
|
isig = cast_to_int4(des, scope, isig, expr_width());
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
isig = cast_to_int2(des, scope, isig, expr_width());
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
isig = cast_to_real(des, scope, isig);
|
isig = cast_to_real(des, scope, isig);
|
||||||
|
|
|
||||||
|
|
@ -4187,6 +4187,9 @@ class NetECast : public NetEUnary {
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
virtual NetECast* dup_expr() const;
|
virtual NetECast* dup_expr() const;
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual NetExpr* eval_arguments_(const NetExpr*ex) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
55
netmisc.cc
55
netmisc.cc
|
|
@ -139,7 +139,7 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
|
||||||
|
|
||||||
NetExpr* cast_to_int2(NetExpr*expr)
|
NetExpr* cast_to_int2(NetExpr*expr)
|
||||||
{
|
{
|
||||||
// Special case: The expression is alreadt BOOL
|
// Special case: The expression is already BOOL
|
||||||
if (expr->expr_type() == IVL_VT_BOOL)
|
if (expr->expr_type() == IVL_VT_BOOL)
|
||||||
return expr;
|
return expr;
|
||||||
|
|
||||||
|
|
@ -153,11 +153,45 @@ NetExpr* cast_to_int2(NetExpr*expr)
|
||||||
return cast;
|
return cast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetExpr* cast_to_int2(NetExpr*expr, unsigned width)
|
||||||
|
{
|
||||||
|
// Special case: The expression is already BOOL
|
||||||
|
if (expr->expr_type() == IVL_VT_BOOL)
|
||||||
|
return expr;
|
||||||
|
|
||||||
|
if (debug_elaborate)
|
||||||
|
cerr << expr->get_fileline() << ": debug: "
|
||||||
|
<< "Cast expression to int2, width=" << width << "." << endl;
|
||||||
|
|
||||||
|
NetECast*cast = new NetECast('2', expr, width, expr->has_sign());
|
||||||
|
cast->set_line(*expr);
|
||||||
|
return cast;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr* cast_to_int4(NetExpr*expr, unsigned width)
|
||||||
|
{
|
||||||
|
// Special case: The expression is already LOGIC or BOOL
|
||||||
|
if (expr->expr_type() != IVL_VT_REAL)
|
||||||
|
return expr;
|
||||||
|
|
||||||
|
if (debug_elaborate)
|
||||||
|
cerr << expr->get_fileline() << ": debug: "
|
||||||
|
<< "Cast expression to int4, width=" << width << "." << endl;
|
||||||
|
|
||||||
|
NetECast*cast = new NetECast('v', expr, width, expr->has_sign());
|
||||||
|
cast->set_line(*expr);
|
||||||
|
return cast;
|
||||||
|
}
|
||||||
|
|
||||||
NetExpr* cast_to_real(NetExpr*expr)
|
NetExpr* cast_to_real(NetExpr*expr)
|
||||||
{
|
{
|
||||||
if (expr->expr_type() == IVL_VT_REAL)
|
if (expr->expr_type() == IVL_VT_REAL)
|
||||||
return expr;
|
return expr;
|
||||||
|
|
||||||
|
if (debug_elaborate)
|
||||||
|
cerr << expr->get_fileline() << ": debug: "
|
||||||
|
<< "Cast expression to real." << endl;
|
||||||
|
|
||||||
NetECast*cast = new NetECast('r', expr, 1, true);
|
NetECast*cast = new NetECast('r', expr, 1, true);
|
||||||
cast->set_line(*expr);
|
cast->set_line(*expr);
|
||||||
return cast;
|
return cast;
|
||||||
|
|
@ -728,7 +762,8 @@ static const char*width_mode_name(PExpr::width_mode_t mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
int context_width, bool need_const, bool annotatable)
|
int context_width, bool need_const, bool annotatable,
|
||||||
|
ivl_variable_type_t cast_type)
|
||||||
{
|
{
|
||||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||||
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
||||||
|
|
@ -777,6 +812,22 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
|
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
|
||||||
if (tmp == 0) return 0;
|
if (tmp == 0) return 0;
|
||||||
|
|
||||||
|
if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) {
|
||||||
|
switch (cast_type) {
|
||||||
|
case IVL_VT_REAL:
|
||||||
|
tmp = cast_to_real(tmp);
|
||||||
|
break;
|
||||||
|
case IVL_VT_BOOL:
|
||||||
|
tmp = cast_to_int2(tmp, context_width);
|
||||||
|
break;
|
||||||
|
case IVL_VT_LOGIC:
|
||||||
|
tmp = cast_to_int4(tmp, context_width);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
eval_expr(tmp, context_width);
|
eval_expr(tmp, context_width);
|
||||||
|
|
||||||
if (NetEConst*ce = dynamic_cast<NetEConst*>(tmp)) {
|
if (NetEConst*ce = dynamic_cast<NetEConst*>(tmp)) {
|
||||||
|
|
|
||||||
13
netmisc.h
13
netmisc.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __netmisc_H
|
#ifndef __netmisc_H
|
||||||
#define __netmisc_H
|
#define __netmisc_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -78,6 +78,8 @@ extern NetNet*cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
||||||
extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid);
|
extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid);
|
||||||
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
|
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
|
||||||
|
|
||||||
|
extern NetExpr*cast_to_int4(NetExpr*expr, unsigned width);
|
||||||
|
extern NetExpr*cast_to_int2(NetExpr*expr, unsigned width);
|
||||||
extern NetExpr*cast_to_int2(NetExpr*expr);
|
extern NetExpr*cast_to_int2(NetExpr*expr);
|
||||||
extern NetExpr*cast_to_real(NetExpr*expr);
|
extern NetExpr*cast_to_real(NetExpr*expr);
|
||||||
|
|
||||||
|
|
@ -222,13 +224,20 @@ extern unsigned count_lval_width(const class NetAssign_*first);
|
||||||
* if the expression is lossless self-determined (this last option is
|
* if the expression is lossless self-determined (this last option is
|
||||||
* treated as standard self-determined if the gn_strict_expr_width flag
|
* treated as standard self-determined if the gn_strict_expr_width flag
|
||||||
* is set).
|
* is set).
|
||||||
|
*
|
||||||
|
* cast_type allows the expression to be cast to a different type
|
||||||
|
* (before it is evaluated). If cast to a vector type, the vector
|
||||||
|
* width will be set to the context_width. The default value of
|
||||||
|
* IVL_VT_NO_TYPE causes the expression to retain its self-determined
|
||||||
|
* type.
|
||||||
*/
|
*/
|
||||||
class PExpr;
|
class PExpr;
|
||||||
|
|
||||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||||
PExpr*pe, int context_width,
|
PExpr*pe, int context_width,
|
||||||
bool need_const =false,
|
bool need_const =false,
|
||||||
bool annotatable =false);
|
bool annotatable =false,
|
||||||
|
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is a variant of elab_and_eval that elaborates and
|
* This function is a variant of elab_and_eval that elaborates and
|
||||||
|
|
|
||||||
10
verinum.cc
10
verinum.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -568,6 +568,14 @@ bool verinum::is_negative() const
|
||||||
return (bits_[nbits_-1] == V1) && has_sign();
|
return (bits_[nbits_-1] == V1) && has_sign();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void verinum::cast_to_int2()
|
||||||
|
{
|
||||||
|
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) {
|
||||||
|
if (bits_[idx] == Vx || bits_[idx] == Vz)
|
||||||
|
bits_[idx] = V0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
verinum pad_to_width(const verinum&that, unsigned width)
|
verinum pad_to_width(const verinum&that, unsigned width)
|
||||||
{
|
{
|
||||||
if (that.len() >= width)
|
if (that.len() >= width)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __verinum_H
|
#ifndef __verinum_H
|
||||||
#define __verinum_H
|
#define __verinum_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -86,6 +86,9 @@ class verinum {
|
||||||
// Comparison for use in sorting algorithms.
|
// Comparison for use in sorting algorithms.
|
||||||
bool is_before(const verinum&that) const;
|
bool is_before(const verinum&that) const;
|
||||||
|
|
||||||
|
// Convert 4-state to 2-state
|
||||||
|
void cast_to_int2();
|
||||||
|
|
||||||
// Individual bits can be accessed with the get and set
|
// Individual bits can be accessed with the get and set
|
||||||
// methods.
|
// methods.
|
||||||
V get(unsigned idx) const;
|
V get(unsigned idx) const;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -140,7 +140,7 @@ void vvp_arith_cast_vec2::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
vvp_context_t)
|
vvp_context_t)
|
||||||
{
|
{
|
||||||
vvp_vector2_t tmp = bit;
|
vvp_vector2_t tmp = bit;
|
||||||
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,tmp.size()), 0);
|
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,wid_), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Division
|
// Division
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue