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:
parent
c2d1038c29
commit
93ad8ff95f
75
elab_expr.cc
75
elab_expr.cc
|
|
@ -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.
|
||||||
|
|
@ -437,8 +445,8 @@ NetExpr* PEBinary::elaborate_expr_base_div_(Design*des,
|
||||||
baseline Verilog. But we allow it in our extended
|
baseline Verilog. But we allow it in our extended
|
||||||
form of Verilog. */
|
form of Verilog. */
|
||||||
if (op_ == '%' && ! gn_icarus_misc_flag) {
|
if (op_ == '%' && ! gn_icarus_misc_flag) {
|
||||||
if (lp->expr_type()==IVL_VT_REAL ||
|
if (lp->expr_type() == IVL_VT_REAL ||
|
||||||
rp->expr_type()==IVL_VT_REAL) {
|
rp->expr_type() == IVL_VT_REAL) {
|
||||||
cerr << get_fileline() << ": error: Modulus operator "
|
cerr << get_fileline() << ": error: Modulus operator "
|
||||||
"may not have REAL operands." << endl;
|
"may not have REAL operands." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
|
|
@ -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 {
|
||||||
|
|
@ -3262,12 +3303,25 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
else
|
else
|
||||||
res = verinum::V1;
|
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);
|
verinum vres (res, 1, true);
|
||||||
tmp = new NetEConst(vres);
|
tmp = new NetEConst(vres);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
delete ip;
|
delete ip;
|
||||||
} else {
|
} 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);
|
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;
|
||||||
|
|
|
||||||
27
netmisc.cc
27
netmisc.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue