From f4671a308287f9f74a759b67e449483f2ee5d411 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 16 Dec 2000 19:03:30 +0000 Subject: [PATCH] Evaluate <= and ?: in parameter expressions (PR#81) --- PExpr.cc | 11 +++-- PExpr.h | 6 ++- elab_pexpr.cc | 16 ++++++- eval_tree.cc | 119 ++++++++++++++++++++++++++++++++++++++++++++++++-- netlist.h | 8 +++- 5 files changed, 150 insertions(+), 10 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index ebc31567e..7efe40962 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.cc,v 1.20 2000/12/10 22:01:35 steve Exp $" +#ident "$Id: PExpr.cc,v 1.21 2000/12/16 19:03:30 steve Exp $" #endif # include "PExpr.h" @@ -222,9 +222,11 @@ PETernary::~PETernary() { } -bool PETernary::is_constant(Module*) const +bool PETernary::is_constant(Module*m) const { - return false; + return expr_->is_constant(m) + && tru_->is_constant(m) + && fal_->is_constant(m); } PEUnary::PEUnary(char op, PExpr*ex) @@ -243,6 +245,9 @@ bool PEUnary::is_constant(Module*m) const /* * $Log: PExpr.cc,v $ + * Revision 1.21 2000/12/16 19:03:30 steve + * Evaluate <= and ?: in parameter expressions (PR#81) + * * Revision 1.20 2000/12/10 22:01:35 steve * Support decimal constants in behavioral delays. * diff --git a/PExpr.h b/PExpr.h index 74047098b..92721af4f 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.h,v 1.46 2000/12/10 22:01:35 steve Exp $" +#ident "$Id: PExpr.h,v 1.47 2000/12/16 19:03:30 steve Exp $" #endif # include @@ -401,6 +401,7 @@ class PETernary : public PExpr { Link::strength_t drive0, Link::strength_t drive1) const; virtual NetETernary*elaborate_expr(Design*des, NetScope*) const; + virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const; virtual verinum* eval_const(const Design*des, const string&path) const; private: @@ -431,6 +432,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.47 2000/12/16 19:03:30 steve + * Evaluate <= and ?: in parameter expressions (PR#81) + * * Revision 1.46 2000/12/10 22:01:35 steve * Support decimal constants in behavioral delays. * diff --git a/elab_pexpr.cc b/elab_pexpr.cc index 9be94322a..36b96cd33 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_pexpr.cc,v 1.5 2000/06/13 05:22:16 steve Exp $" +#ident "$Id: elab_pexpr.cc,v 1.6 2000/12/16 19:03:30 steve Exp $" #endif # include "PExpr.h" @@ -138,6 +138,17 @@ NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const return elaborate_expr(des, scope); } +NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const +{ + NetExpr*c = expr_->elaborate_pexpr(des, scope); + NetExpr*t = tru_->elaborate_pexpr(des, scope); + NetExpr*f = fal_->elaborate_pexpr(des, scope); + if (c == 0) return 0; + if (t == 0) return 0; + if (f == 0) return 0; + return new NetETernary(c, t, f); +} + NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const { NetExpr*ip = expr_->elaborate_pexpr(des, scope); @@ -163,6 +174,9 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const /* * $Log: elab_pexpr.cc,v $ + * Revision 1.6 2000/12/16 19:03:30 steve + * Evaluate <= and ?: in parameter expressions (PR#81) + * * Revision 1.5 2000/06/13 05:22:16 steve * Support concatenation in parameter expressions. * diff --git a/eval_tree.cc b/eval_tree.cc index e2d2b0f15..4806bffec 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -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.13 2000/09/29 04:42:56 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.14 2000/12/16 19:03:30 steve Exp $" #endif # include "netlist.h" @@ -101,6 +101,10 @@ NetEConst* NetEBComp::eval_leeq_() 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 @@ -112,7 +116,26 @@ NetEConst* NetEBComp::eval_leeq_() return new NetEConst(result); } - return 0; + /* Now go on to the normal test of the values. */ + NetEConst*l = dynamic_cast(left_); + 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_neeq_() @@ -290,7 +313,7 @@ NetEConst* NetEBShift::eval_tree() return res; } -NetExpr* NetEConcat::eval_tree() +NetEConst* NetEConcat::eval_tree() { for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { @@ -369,6 +392,93 @@ NetExpr* NetEParam::eval_tree() return res->dup_expr(); } +/* + * A ternary expression evaluation is controlled by the condition + * expression. If the condition evaluates to true or false, then + * return the evaluated true or false expression. If the condition + * evaluates to x or z, then merge the constant bits of the true and + * false expressions. + */ +NetExpr* NetETernary::eval_tree() +{ + NetExpr*tmp; + + /* Evaluate the cond_ to a constant. If it already is a + constant, then there is nothing to do. */ + + NetEConst*c = dynamic_cast(cond_); + if (c == 0) { + tmp = cond_->eval_tree(); + c = dynamic_cast(tmp); + if (c == 0) + return 0; + + delete cond_; + cond_ = c; + } + + + /* If the condition is 1 or 0, return the true or false + expression. Try to evaluate the expression down as far as + we can. */ + + if (c->value().get(0) == verinum::V1) { + tmp = true_val_->eval_tree(); + return tmp? tmp : true_val_; + } + + if (c->value().get(0) == verinum::V0) { + tmp = false_val_->eval_tree(); + return tmp? tmp : false_val_; + } + + + /* Here we have a more complex case. We need to evaluate both + expressions down to constants then compare the values to + build up a constant result. */ + + NetEConst*t = dynamic_cast(true_val_); + if (t == 0) { + tmp = true_val_->eval_tree(); + t = dynamic_cast(tmp); + if (t == 0) + return 0; + + delete true_val_; + true_val_ = t; + } + + + NetEConst*f = dynamic_cast(false_val_); + if (f == 0) { + tmp = false_val_->eval_tree(); + f = dynamic_cast(tmp); + if (f == 0) + return 0; + + delete false_val_; + false_val_ = f; + } + + unsigned size = t->expr_width(); + assert(size == f->expr_width()); + + verinum val (verinum::V0, size); + for (unsigned idx = 0 ; idx < size ; idx += 1) { + verinum::V tv = t->value().get(idx); + verinum::V fv = f->value().get(idx); + + if (tv == fv) + val.set(idx, tv); + else + val.set(idx, verinum::Vx); + } + + NetEConst*rc = new NetEConst(val); + rc->set_line(*this); + return rc; +} + NetEConst* NetEUnary::eval_tree() { NetExpr*oper = expr_->eval_tree(); @@ -413,6 +523,9 @@ NetEConst* NetEUnary::eval_tree() /* * $Log: eval_tree.cc,v $ + * Revision 1.14 2000/12/16 19:03:30 steve + * Evaluate <= and ?: in parameter expressions (PR#81) + * * Revision 1.13 2000/09/29 04:42:56 steve * Cnstant evaluation of NE. * diff --git a/netlist.h b/netlist.h index 48322036a..8b052f748 100644 --- a/netlist.h +++ b/netlist.h @@ -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.187 2000/12/16 01:45:48 steve Exp $" +#ident "$Id: netlist.h,v 1.188 2000/12/16 19:03:30 steve Exp $" #endif /* @@ -2262,7 +2262,7 @@ class NetEConcat : public NetExpr { virtual bool set_width(unsigned w); virtual NetEConcat* dup_expr() const; - virtual NetExpr* eval_tree(); + virtual NetEConst* eval_tree(); virtual NetNet*synthesize(Design*); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -2375,6 +2375,7 @@ class NetETernary : public NetExpr { const NetExpr*false_expr() const; virtual NetETernary* dup_expr() const; + virtual NetExpr* eval_tree(); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -2837,6 +2838,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.188 2000/12/16 19:03:30 steve + * Evaluate <= and ?: in parameter expressions (PR#81) + * * Revision 1.187 2000/12/16 01:45:48 steve * Detect recursive instantiations (PR#2) *