From 93ad8ff95fd9ef32892c1eb7d79b61f58ac6b347 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 13 Feb 2009 18:25:54 -0800 Subject: [PATCH] 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). --- elab_expr.cc | 75 +++++++++++++++++++++++++++++++++++++++++++++++----- netmisc.cc | 27 ++++++++++++++++--- netmisc.h | 4 +-- 3 files changed, 94 insertions(+), 12 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index a8ab1d0d9..1e3f06c67 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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(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(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; diff --git a/netmisc.cc b/netmisc.cc index 05579dfa8..ae5a21652 100644 --- a/netmisc.cc +++ b/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 * 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(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 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 diff --git a/netmisc.h b/netmisc.h index d8e8be9e1..b5ef3bc97 100644 --- a/netmisc.h +++ b/netmisc.h @@ -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