support evaluation of constant < in expressions.

This commit is contained in:
steve 2001-02-09 05:44:23 +00:00
parent 8376553349
commit 7ef3b44ab1
6 changed files with 158 additions and 16 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: elab_expr.cc,v 1.34 2001/01/14 23:04:55 steve Exp $"
#ident "$Id: elab_expr.cc,v 1.35 2001/02/09 05:44:23 steve Exp $"
#endif
@ -145,6 +145,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
return tmp;
}
/*
* Given a call to a system function, generate the proper expression
* nodes to represent the call in the netlist. Since we don't support
* size_tf functions, make assumptions about widths based on some
* known function names.
*/
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
{
unsigned wid = 32;
@ -152,11 +158,43 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
if (name_ == "$time")
wid = 64;
NetESFunc*fun = new NetESFunc(name_, wid, parms_.count());
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
/* How many parameters are there? The Verilog language allows
empty parameters in certain contexts, so the parser will
allow things like func(1,,3). It will also cause func() to
be interpreted as a single empty parameter.
Functions cannot really take empty parameters, but the
case ``func()'' is the same as no parmaters at all. So
catch that special case here. */
unsigned nparms = parms_.count();
if ((nparms == 1) && (parms_[0] == 0))
nparms = 0;
NetESFunc*fun = new NetESFunc(name_, wid, nparms);
/* Now run through the expected parameters. If we find that
there are missing parameters, print an error message. */
unsigned missing_parms = 0;
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
PExpr*expr = parms_[idx];
NetExpr*tmp = expr->elaborate_expr(des, scope);
fun->parm(idx, tmp);
if (expr) {
NetExpr*tmp = expr->elaborate_expr(des, scope);
fun->parm(idx, tmp);
} else {
missing_parms += 1;
fun->parm(idx, 0);
}
}
if (missing_parms > 0) {
cerr << get_line() << ": error: The function " << name_
<< " has been called with empty parameters." << endl;
cerr << get_line() << ": : Verilog doesn't allow "
<< "passing empty parameters to functions." << endl;
des->errors += 1;
}
return fun;
@ -195,10 +233,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const
of the function being called. The scope of the called
function is elaborated when the definition is elaborated. */
unsigned missing_parms = 0;
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
PExpr*tmp = parms_[idx];
assert(tmp);
parms[idx] = tmp->elaborate_expr(des, scope);
if (tmp) {
parms[idx] = tmp->elaborate_expr(des, scope);
} else {
missing_parms += 1;
parms[idx] = 0;
}
}
if (missing_parms > 0) {
cerr << get_line() << ": error: The function " << name_
<< " has been called with empty parameters." << endl;
cerr << get_line() << ": : Verilog doesn't allow "
<< "passing empty parameters to functions." << endl;
des->errors += 1;
}
@ -545,6 +597,9 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
/*
* $Log: elab_expr.cc,v $
* Revision 1.35 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.34 2001/01/14 23:04:55 steve
* Generalize the evaluation of floating point delays, and
* get it working with delay assignment statements.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: elaborate.cc,v 1.206 2001/02/07 21:47:13 steve Exp $"
#ident "$Id: elaborate.cc,v 1.207 2001/02/09 05:44:23 steve Exp $"
#endif
/*
@ -2031,10 +2031,10 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
}
if (NetExpr*tmp = ce->eval_tree()) {
if (dynamic_cast<NetEConst*>(tmp))
if (dynamic_cast<NetEConst*>(tmp)) {
cerr << get_line() << ": warning: condition expression "
"is constant." << endl;
"of for-loop is constant." << endl;
}
ce = tmp;
}
@ -2367,6 +2367,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.207 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.206 2001/02/07 21:47:13 steve
* Fix expression widths for rvalues and parameters (PR#131,132)
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: eval_tree.cc,v 1.22 2001/02/07 02:46:31 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.23 2001/02/09 05:44:23 steve Exp $"
#endif
# include "netlist.h"
@ -161,6 +161,50 @@ NetEConst* NetEBComp::eval_eqeq_()
}
NetEConst* NetEBComp::eval_less_()
{
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
verinum rv = r->value();
if (! rv.is_defined()) {
verinum result(verinum::Vx, 1);
return new NetEConst(result);
}
/* Detect the case where the right side is greater that or
equal to the largest value the left side can possibly
have. */
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width());
if (lv < rv) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
lv = l->value();
if (! lv.is_defined()) {
verinum result(verinum::Vx, 1);
return new NetEConst(result);
}
if (lv.has_sign() && rv.has_sign() && (lv.as_long() < rv.as_long())) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
if (lv.as_ulong() < rv.as_ulong()) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
verinum result(verinum::V0, 1);
return new NetEConst(result);
}
NetEConst* NetEBComp::eval_leeq_()
{
NetEConst*r = dynamic_cast<NetEConst*>(right_);
@ -358,6 +402,9 @@ NetEConst* NetEBComp::eval_tree()
case 'n': // not-equal (!=)
return eval_neeq_();
case '<': // Less than
return eval_less_();
default:
return 0;
}
@ -843,6 +890,9 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.23 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.22 2001/02/07 02:46:31 steve
* Support constant evaluation of / and % (PR#124)
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.h,v 1.195 2001/01/18 03:16:35 steve Exp $"
#ident "$Id: netlist.h,v 1.196 2001/02/09 05:44:23 steve Exp $"
#endif
/*
@ -2182,6 +2182,7 @@ class NetEBComp : public NetEBinary {
private:
NetEConst*eval_eqeq_();
NetEConst*eval_less_();
NetEConst*eval_leeq_();
NetEConst*eval_neeq_();
NetEConst*eval_eqeqeq_();
@ -2852,6 +2853,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.196 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.195 2001/01/18 03:16:35 steve
* NetMux needs a scope. (PR#115)
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: verinum.cc,v 1.25 2001/02/08 05:38:18 steve Exp $"
#ident "$Id: verinum.cc,v 1.26 2001/02/09 05:44:23 steve Exp $"
#endif
# include "verinum.h"
@ -420,7 +420,7 @@ verinum::V operator <= (const verinum&left, const verinum&right)
}
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
if (right[idx-1] != verinum::V0) return verinum::V0;
if (right[idx-1] != verinum::V0) return verinum::V1;
}
while (idx > 0) {
@ -435,6 +435,29 @@ verinum::V operator <= (const verinum&left, const verinum&right)
return verinum::V1;
}
verinum::V operator < (const verinum&left, const verinum&right)
{
unsigned idx;
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
if (left[idx-1] != verinum::V0) return verinum::V0;
}
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
if (right[idx-1] != verinum::V0) return verinum::V1;
}
while (idx > 0) {
if (left[idx-1] == verinum::Vx) return verinum::Vx;
if (left[idx-1] == verinum::Vz) return verinum::Vx;
if (right[idx-1] == verinum::Vx) return verinum::Vx;
if (right[idx-1] == verinum::Vz) return verinum::Vx;
if (left[idx-1] > right[idx-1]) return verinum::V0;
idx -= 1;
}
return verinum::V0;
}
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c)
{
unsigned sum = 0;
@ -743,6 +766,9 @@ verinum::V operator & (verinum::V l, verinum::V r)
/*
* $Log: verinum.cc,v $
* Revision 1.26 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.25 2001/02/08 05:38:18 steve
* trim the length of unsized numbers.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: verinum.h,v 1.16 2001/02/07 02:46:31 steve Exp $"
#ident "$Id: verinum.h,v 1.17 2001/02/09 05:44:23 steve Exp $"
#endif
# include <string>
@ -110,6 +110,7 @@ extern verinum::V operator & (verinum::V l, verinum::V r);
extern verinum::V operator == (const verinum&left, const verinum&right);
extern verinum::V operator <= (const verinum&left, const verinum&right);
extern verinum::V operator < (const verinum&left, const verinum&right);
extern verinum operator + (const verinum&left, const verinum&right);
extern verinum operator - (const verinum&left, const verinum&right);
extern verinum operator * (const verinum&left, const verinum&right);
@ -120,6 +121,9 @@ extern verinum v_not(const verinum&left);
/*
* $Log: verinum.h,v $
* Revision 1.17 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.16 2001/02/07 02:46:31 steve
* Support constant evaluation of / and % (PR#124)
*