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,
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
// of them as unsigned. This only impacts the padding that is
// done to get the operands to the expr_wid.
@ -437,8 +445,8 @@ NetExpr* PEBinary::elaborate_expr_base_div_(Design*des,
baseline Verilog. But we allow it in our extended
form of Verilog. */
if (op_ == '%' && ! gn_icarus_misc_flag) {
if (lp->expr_type()==IVL_VT_REAL ||
rp->expr_type()==IVL_VT_REAL) {
if (lp->expr_type() == IVL_VT_REAL ||
rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: Modulus operator "
"may not have REAL operands." << endl;
des->errors += 1;
@ -465,6 +473,14 @@ NetExpr* PEBinary::elaborate_expr_base_lshift_(Design*des,
NetExpr*lp, NetExpr*rp,
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;
long use_wid = lp->expr_width();
@ -570,6 +586,14 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
NetExpr*lp, NetExpr*rp,
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;
long use_wid = lp->expr_width();
@ -853,7 +877,8 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< "may not have real operands." << endl;
<< " operator may not have REAL operands." << endl;
des->errors += 1;
return 0;
}
break;
@ -1534,6 +1559,14 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
if (repeat_) {
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
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);
if (rep == 0) {
@ -1543,6 +1576,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
cerr << get_fileline() << ": : The expression is: "
<< *tmp << endl;
des->errors += 1;
return 0;
}
if (!rep->value().is_defined()) {
@ -1597,8 +1631,15 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
ex->set_line(*parms_[idx]);
if (! ex->has_width()) {
cerr << ex->get_fileline() << ": error: operand of "
<< "concatenation has indefinite width: "
cerr << ex->get_fileline() << ": error: "
<< "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;
des->errors += 1;
}
@ -3219,7 +3260,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
constant value. */
verireal val = - ipr->value();
tmp = new NetECReal(val);
tmp->set_line( *ip );
tmp->set_line(*this);
delete ip;
} else {
@ -3262,12 +3303,25 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
else
res = verinum::V1;
verinum vres (res, 1, true);
tmp = new NetEConst(vres);
tmp->set_line(*this);
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 {
tmp = new NetEUReduce(op_, ip);
if (ip->expr_type() == IVL_VT_REAL) {
tmp = new NetEBComp('e', ip,
new NetECReal(verireal(0.0)));
} else {
tmp = new NetEUReduce(op_, ip);
}
tmp->set_line(*this);
}
break;
@ -3278,6 +3332,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
case 'A': // Reduction NAND (~&)
case 'N': // Reduction NOR (~|)
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->set_line(*this);
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
* 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)
{
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)
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.
*/
const char *human_readable_op(const char op)
const char *human_readable_op(const char op, bool unary)
{
const char *type;
switch (op) {
@ -418,7 +436,10 @@ const char *human_readable_op(const char op)
case 'e': type = "=="; break;
case 'n': type = "!="; break;
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 'r': type = ">>"; break; // Logical right shift

View File

@ -1,7 +1,7 @@
#ifndef __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
* 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.
*/
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