Add logical support for real values and error for invalid real arguments.

This patch adds logical support for real values (!, && and ||). It
also prints an appropriate error message when a real value is
incorrectly given to an operator that does not allow real arguments
(bit-wise, reduction, shift and repeat/concatenation).
This commit is contained in:
Cary R 2009-02-13 18:25:54 -08:00 committed by Stephen Williams
parent c2d1038c29
commit 93ad8ff95f
3 changed files with 94 additions and 12 deletions

View File

@ -408,6 +408,14 @@ NetExpr* PEBinary::elaborate_expr_base_bits_(Design*des,
NetExpr*lp, NetExpr*rp, NetExpr*lp, NetExpr*rp,
int expr_wid) const int expr_wid) const
{ {
if (lp->expr_type() == IVL_VT_REAL || rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< " operator may not have REAL operands." << endl;
des->errors += 1;
return 0;
}
// If either of the arguments is unsigned, then process both // If either of the arguments is unsigned, then process both
// of them as unsigned. This only impacts the padding that is // of them as unsigned. This only impacts the padding that is
// done to get the operands to the expr_wid. // done to get the operands to the expr_wid.
@ -465,6 +473,14 @@ NetExpr* PEBinary::elaborate_expr_base_lshift_(Design*des,
NetExpr*lp, NetExpr*rp, NetExpr*lp, NetExpr*rp,
int expr_wid) const int expr_wid) const
{ {
if (lp->expr_type() == IVL_VT_REAL || rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< " operator may not have REAL operands." << endl;
des->errors += 1;
return 0;
}
NetExpr*tmp; NetExpr*tmp;
long use_wid = lp->expr_width(); long use_wid = lp->expr_width();
@ -570,6 +586,14 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
NetExpr*lp, NetExpr*rp, NetExpr*lp, NetExpr*rp,
int expr_wid) const int expr_wid) const
{ {
if (lp->expr_type() == IVL_VT_REAL || rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< " operator may not have REAL operands." << endl;
des->errors += 1;
return 0;
}
NetExpr*tmp; NetExpr*tmp;
long use_wid = lp->expr_width(); long use_wid = lp->expr_width();
@ -853,7 +877,8 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
rp->expr_type() == IVL_VT_REAL) { rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< human_readable_op(op_) << human_readable_op(op_)
<< "may not have real operands." << endl; << " operator may not have REAL operands." << endl;
des->errors += 1;
return 0; return 0;
} }
break; break;
@ -1534,6 +1559,14 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
if (repeat_) { if (repeat_) {
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1); NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
assert(tmp); assert(tmp);
if (tmp->expr_type() == IVL_VT_REAL) {
cerr << tmp->get_fileline() << ": error: concatenation "
<< "repeat expression can not be REAL." << endl;
des->errors += 1;
return 0;
}
NetEConst*rep = dynamic_cast<NetEConst*>(tmp); NetEConst*rep = dynamic_cast<NetEConst*>(tmp);
if (rep == 0) { if (rep == 0) {
@ -1543,6 +1576,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
cerr << get_fileline() << ": : The expression is: " cerr << get_fileline() << ": : The expression is: "
<< *tmp << endl; << *tmp << endl;
des->errors += 1; des->errors += 1;
return 0;
} }
if (!rep->value().is_defined()) { if (!rep->value().is_defined()) {
@ -1597,8 +1631,15 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
ex->set_line(*parms_[idx]); ex->set_line(*parms_[idx]);
if (! ex->has_width()) { if (! ex->has_width()) {
cerr << ex->get_fileline() << ": error: operand of " cerr << ex->get_fileline() << ": error: "
<< "concatenation has indefinite width: " << "concatenation operand has indefinite width: "
<< *ex << endl;
des->errors += 1;
}
if (ex->expr_type() == IVL_VT_REAL) {
cerr << ex->get_fileline() << ": error: "
<< "concatenation operand can not be REAL: "
<< *ex << endl; << *ex << endl;
des->errors += 1; des->errors += 1;
} }
@ -3219,7 +3260,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
constant value. */ constant value. */
verireal val = - ipr->value(); verireal val = - ipr->value();
tmp = new NetECReal(val); tmp = new NetECReal(val);
tmp->set_line( *ip ); tmp->set_line(*this);
delete ip; delete ip;
} else { } else {
@ -3266,8 +3307,21 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
tmp = new NetEConst(vres); tmp = new NetEConst(vres);
tmp->set_line(*this); tmp->set_line(*this);
delete ip; delete ip;
} else if (NetECReal*ipr = dynamic_cast<NetECReal*>(ip)) {
verinum::V res;
if (ipr->value().as_double() == 0.0) res = verinum::V1;
else res = verinum::V0;
verinum vres (res, 1, true);
tmp = new NetEConst(vres);
tmp->set_line(*this);
delete ip;
} else {
if (ip->expr_type() == IVL_VT_REAL) {
tmp = new NetEBComp('e', ip,
new NetECReal(verireal(0.0)));
} else { } else {
tmp = new NetEUReduce(op_, ip); tmp = new NetEUReduce(op_, ip);
}
tmp->set_line(*this); tmp->set_line(*this);
} }
break; break;
@ -3278,6 +3332,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
case 'A': // Reduction NAND (~&) case 'A': // Reduction NAND (~&)
case 'N': // Reduction NOR (~|) case 'N': // Reduction NOR (~|)
case 'X': // Reduction NXOR (~^) case 'X': // Reduction NXOR (~^)
if (ip->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_, true)
<< " operator may not have a REAL operand." << endl;
des->errors += 1;
return 0;
}
tmp = new NetEUReduce(op_, ip); tmp = new NetEUReduce(op_, ip);
tmp->set_line(*this); tmp->set_line(*this);
break; break;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2009 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
@ -233,6 +233,24 @@ NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
NetExpr* condition_reduce(NetExpr*expr) NetExpr* condition_reduce(NetExpr*expr)
{ {
if (expr->expr_type() == IVL_VT_REAL) {
if (NetECReal *tmp = dynamic_cast<NetECReal*>(expr)) {
verinum::V res;
if (tmp->value().as_double() == 0.0) res = verinum::V0;
else res = verinum::V1;
verinum vres (res, 1, true);
NetExpr *rtn = new NetEConst(vres);
rtn->set_line(*expr);
delete expr;
return rtn;
}
NetExpr *rtn = new NetEBComp('n', expr,
new NetECReal(verireal(0.0)));
rtn->set_line(*expr);
return rtn;
}
if (expr->expr_width() == 1) if (expr->expr_width() == 1)
return expr; return expr;
@ -388,7 +406,7 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
/* /*
* Human readable version of op. Used in elaboration error messages. * Human readable version of op. Used in elaboration error messages.
*/ */
const char *human_readable_op(const char op) const char *human_readable_op(const char op, bool unary)
{ {
const char *type; const char *type;
switch (op) { switch (op) {
@ -418,7 +436,10 @@ const char *human_readable_op(const char op)
case 'e': type = "=="; break; case 'e': type = "=="; break;
case 'n': type = "!="; break; case 'n': type = "!="; break;
case 'E': type = "==="; break; // Case equality case 'E': type = "==="; break; // Case equality
case 'N': type = "!=="; break; // Case inequality case 'N':
if (unary) type = "~|"; // NOR
else type = "!=="; // Case inequality
break;
case 'l': type = "<<(<)"; break; // Left shifts case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift case 'r': type = ">>"; break; // Logical right shift

View File

@ -1,7 +1,7 @@
#ifndef __netmisc_H #ifndef __netmisc_H
#define __netmisc_H #define __netmisc_H
/* /*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2009 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
@ -210,7 +210,7 @@ extern bool type_is_vectorable(ivl_variable_type_t type);
/* /*
* Return a human readable version of the operator. * Return a human readable version of the operator.
*/ */
const char *human_readable_op(const char op); const char *human_readable_op(const char op, bool unary = false);
/* /*
* Is the expression a constant value and if so what is its logical * Is the expression a constant value and if so what is its logical