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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
* 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()) {
|
||||
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;
|
||||
case 'r':
|
||||
isig = cast_to_real(des, scope, isig);
|
||||
|
|
|
|||
|
|
@ -4187,6 +4187,9 @@ class NetECast : public NetEUnary {
|
|||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||
virtual NetECast* dup_expr() 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)
|
||||
{
|
||||
// Special case: The expression is alreadt BOOL
|
||||
// Special case: The expression is already BOOL
|
||||
if (expr->expr_type() == IVL_VT_BOOL)
|
||||
return expr;
|
||||
|
||||
|
|
@ -153,11 +153,45 @@ NetExpr* cast_to_int2(NetExpr*expr)
|
|||
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)
|
||||
{
|
||||
if (expr->expr_type() == IVL_VT_REAL)
|
||||
return expr;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << expr->get_fileline() << ": debug: "
|
||||
<< "Cast expression to real." << endl;
|
||||
|
||||
NetECast*cast = new NetECast('r', expr, 1, true);
|
||||
cast->set_line(*expr);
|
||||
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,
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
|
||||
if (NetEConst*ce = dynamic_cast<NetEConst*>(tmp)) {
|
||||
|
|
|
|||
13
netmisc.h
13
netmisc.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* 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_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_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
|
||||
* treated as standard self-determined if the gn_strict_expr_width flag
|
||||
* 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;
|
||||
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
PExpr*pe, int context_width,
|
||||
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
|
||||
|
|
|
|||
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
|
||||
* 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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (that.len() >= width)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* 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.
|
||||
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
|
||||
// methods.
|
||||
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
|
||||
* 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_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
|
||||
|
|
|
|||
Loading…
Reference in New Issue