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:
Martin Whitaker 2013-02-25 20:32:56 +00:00 committed by Stephen Williams
parent 03ebd2f98d
commit 22769afd20
9 changed files with 123 additions and 12 deletions

View File

@ -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);
}
/*

View File

@ -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_);

View File

@ -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);

View File

@ -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;
};
/*

View File

@ -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)) {

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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