diff --git a/Makefile.in b/Makefile.in index 8711dc937..ec7abb879 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.143 2003/01/26 21:15:58 steve Exp $" +#ident "$Id: Makefile.in,v 1.144 2003/02/08 19:49:21 steve Exp $" # # SHELL = /bin/sh @@ -123,7 +123,7 @@ FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \ -elab_sig.o emit.o eval.o eval_attrib.o eval_rconst.o \ +elab_sig.o emit.o eval.o eval_attrib.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ load_module.o netlist.o netmisc.o net_assign.o \ net_design.o net_event.o net_expr.o net_force.o net_func.o \ diff --git a/PDelays.cc b/PDelays.cc index 6fc7e0e99..42e550165 100644 --- a/PDelays.cc +++ b/PDelays.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PDelays.cc,v 1.9 2002/08/12 01:34:58 steve Exp $" +#ident "$Id: PDelays.cc,v 1.10 2003/02/08 19:49:21 steve Exp $" #endif # include "config.h" @@ -62,34 +62,51 @@ void PDelays::set_delays(const svector*del, bool df) delete_flag_ = df; } -static unsigned long calculate_val(Design*des, const NetScope*scope, +static unsigned long calculate_val(Design*des, NetScope*scope, const PExpr*expr) { - assert(expr); - unsigned long val; - int shift = scope->time_unit() - des->get_precision(); - - if (verireal*dr = expr->eval_rconst(des, scope)) { - val = dr->as_long(shift); - delete dr; - - } else { - verinum*dv = expr->eval_const(des, scope); - if (dv == 0) { - cerr << expr->get_line() << ": sorry: non-constant " - << "delays not supported here: " << *expr << endl; - des->errors += 1; - return 0; - } - - assert(dv); - val = dv->as_ulong(); - val = des->scale_to_precision(val, scope); - delete dv; + NetExpr*dex = expr->elaborate_expr(des, scope); + if (NetExpr*tmp = dex->eval_tree()) { + delete dex; + dex = tmp; } - return val; + /* If the delay expression is a real constant or vector + constant, then evaluate it, scale it to the local time + units, and return an adjusted value. */ + + if (NetECReal*tmp = dynamic_cast(dex)) { + verireal fn = tmp->value(); + + int shift = scope->time_unit() - des->get_precision(); + long delay = fn.as_long(shift); + if (delay < 0) + delay = 0; + + delete tmp; + return delay; + } + + + if (NetEConst*tmp = dynamic_cast(dex)) { + verinum fn = tmp->value(); + + unsigned long delay = + des->scale_to_precision(fn.as_ulong(), scope); + + delete tmp; + return delay; + } + + /* Oops, cannot evaluate down to a constant. Error message. */ + delete dex; + + cerr << expr->get_line() << ": sorry: non-constant " + << "delays not supported here: " << *expr << endl; + des->errors += 1; + return 0; + } void PDelays::eval_delays(Design*des, NetScope*scope, @@ -131,6 +148,13 @@ void PDelays::eval_delays(Design*des, NetScope*scope, /* * $Log: PDelays.cc,v $ + * Revision 1.10 2003/02/08 19:49:21 steve + * Calculate delay statement delays using elaborated + * expressions instead of pre-elaborated expression + * trees. + * + * Remove the eval_pexpr methods from PExpr. + * * Revision 1.9 2002/08/12 01:34:58 steve * conditional ident string using autoconfig. * diff --git a/PExpr.h b/PExpr.h index 36f4cf279..e32c4d32c 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,13 +19,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PExpr.h,v 1.64 2003/01/30 16:23:07 steve Exp $" +#ident "$Id: PExpr.h,v 1.65 2003/02/08 19:49:21 steve Exp $" #endif # include # include "netlist.h" # include "verinum.h" -# include "verireal.h" # include "LineInfo.h" class Design; @@ -92,11 +91,6 @@ class PExpr : public LineInfo { // evaluated, return 0. virtual verinum* eval_const(const Design*des, const NetScope*sc) const; - // This attempts to evaluate a constant expression as a - // decimal floating point. This is used when calculating delay - // constants. - virtual verireal* eval_rconst(const Design*, const NetScope*) const; - // This method returns true if that expression is the same as // this expression. This method is used for comparing // expressions that must be structurally "identical". @@ -190,9 +184,6 @@ class PEFNumber : public PExpr { any rounding that is needed to get the value. */ virtual verinum* eval_const(const Design*des, const NetScope*sc) const; - /* This method returns the full floating point value. */ - virtual verireal* eval_rconst(const Design*, const NetScope*) const; - /* A PEFNumber is a constant, so this returns true. */ virtual bool is_constant(Module*) const; @@ -243,7 +234,6 @@ class PEIdent : public PExpr { virtual bool is_constant(Module*) const; verinum* eval_const(const Design*des, const NetScope*sc) const; - verireal*eval_rconst(const Design*des, const NetScope*sc) const; const hname_t& path() const; @@ -301,7 +291,6 @@ class PENumber : public PExpr { virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const; virtual verinum* eval_const(const Design*des, const NetScope*sc) const; - virtual verireal*eval_rconst(const Design*, const NetScope*) const; virtual bool is_the_same(const PExpr*that) const; virtual bool is_constant(Module*) const; @@ -389,7 +378,6 @@ class PEBinary : public PExpr { bool sys_task_arg =false) const; virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; virtual verinum* eval_const(const Design*des, const NetScope*sc) const; - virtual verireal*eval_rconst(const Design*des, const NetScope*sc) const; private: char op_; @@ -504,6 +492,13 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.65 2003/02/08 19:49:21 steve + * Calculate delay statement delays using elaborated + * expressions instead of pre-elaborated expression + * trees. + * + * Remove the eval_pexpr methods from PExpr. + * * Revision 1.64 2003/01/30 16:23:07 steve * Spelling fixes. * diff --git a/elaborate.cc b/elaborate.cc index c41c96764..0a5cfd302 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2003 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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.272 2003/02/07 02:49:24 steve Exp $" +#ident "$Id: elaborate.cc,v 1.273 2003/02/08 19:49:21 steve Exp $" #endif # include "config.h" @@ -868,23 +868,43 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope) { - if (verireal*dr = expr->eval_rconst(des, scope)) { + NetExpr*dex = expr->elaborate_expr(des, scope); + if (NetExpr*tmp = dex->eval_tree()) { + delete dex; + dex = tmp; + } + + /* If the delay expression is a real constant or vector + constant, then evaluate it, scale it to the local time + units, and return an adjusted NetEConst. */ + + if (NetECReal*tmp = dynamic_cast(dex)) { + verireal fn = tmp->value(); + int shift = scope->time_unit() - des->get_precision(); - long val = dr->as_long(shift); - delete dr; - return new NetEConst(verinum(val)); + long delay = fn.as_long(shift); + if (delay < 0) + delay = 0; + delete tmp; + return new NetEConst(verinum(delay)); } - if (verinum*dv = expr->eval_const(des, scope)) { - unsigned long val = dv->as_ulong(); - val = des->scale_to_precision(val, scope); - return new NetEConst(verinum(val)); + if (NetEConst*tmp = dynamic_cast(dex)) { + verinum fn = tmp->value(); + + unsigned long delay = + des->scale_to_precision(fn.as_ulong(), scope); + + delete tmp; + return new NetEConst(verinum(delay)); } - NetExpr*delay = expr->elaborate_expr(des, scope); + /* The expression is not constant, so generate an expanded + expression that includes the necessary scale shifts, and + return that expression. */ int shift = scope->time_unit() - des->get_precision(); if (shift > 0) { unsigned long scale = 1; @@ -894,7 +914,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope) } NetExpr*scal_val = new NetEConst(verinum(scale)); - delay = new NetEBMult('*', delay, scal_val); + dex = new NetEBMult('*', dex, scal_val); } if (shift < 0) { @@ -905,10 +925,10 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope) } NetExpr*scal_val = new NetEConst(verinum(scale)); - delay = new NetEBDiv('/', delay, scal_val); + dex = new NetEBDiv('/', dex, scal_val); } - return delay; + return dex; } NetProc* PAssign::elaborate(Design*des, NetScope*scope) const @@ -1574,81 +1594,27 @@ NetProc* PDelayStatement::elaborate(Design*des, NetScope*scope) const { assert(scope); - NetExpr*dex = delay_->elaborate_expr(des, scope); - if (NetExpr*tmp = dex->eval_tree()) { - delete dex; - dex = tmp; - } + /* This call evaluates the delay expression to a NetEConst, if + possible. This includes transforming NetECReal values to + integers, and applying the proper scaling. */ + NetExpr*dex = elaborate_delay_expr(delay_, des, scope); - /* Catch the case that the expression is a constant real - value. Scale the delay to the units of the design, and make - the delay statement. */ - if (NetECReal*tmp = dynamic_cast(dex)) { - verireal fn = tmp->value(); - - int shift = scope->time_unit() - des->get_precision(); - long delay = fn.as_long(shift); - if (delay < 0) - delay = 0; - - delete tmp; - - if (statement_) - return new NetPDelay(delay, statement_->elaborate(des, scope)); - else - return new NetPDelay(delay, 0); - } - - /* OK, Maybe the expression is a constant integer. If so, - scale the delay to simulation units and make the delay - statement. */ if (NetEConst*tmp = dynamic_cast(dex)) { - verinum fn = tmp->value(); - - unsigned long delay = - des->scale_to_precision(fn.as_ulong(), scope); - - delete tmp; - if (statement_) - return new NetPDelay(delay, statement_->elaborate(des, scope)); + return new NetPDelay(tmp->value().as_ulong(), + statement_->elaborate(des, scope)); else - return new NetPDelay(delay, 0); + return new NetPDelay(tmp->value().as_ulong(), 0); + + delete dex; + + } else { + if (statement_) + return new NetPDelay(dex, statement_->elaborate(des, scope)); + else + return new NetPDelay(dex, 0); } - - /* Ah well, the delay is not constant. OK, elaborate the - expression and let the run-time handle it. */ - - - /* If the local scope units are different from the - simulation precision, then extend the expression to - convert the delay to simulation time. */ - if (scope->time_unit() != des->get_precision()) { - long scale = 1; - int unit = scope->time_unit(); - int prec = des->get_precision(); - while (unit > prec) { - scale *= 10; - unit -= 1; - } - - verinum scale_v (scale); - NetEConst*scale_e = new NetEConst(scale_v); - NetEBMult*scale_m = new NetEBMult('*', scale_e, dex); - if (NetExpr*tmp = scale_m->eval_tree()) { - dex = tmp; - delete scale_m; - } else { - dex = scale_m; - } - } - - if (statement_) - return new NetPDelay(dex, statement_->elaborate(des, scope)); - else - return new NetPDelay(dex, 0); - } /* @@ -2508,6 +2474,13 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.273 2003/02/08 19:49:21 steve + * Calculate delay statement delays using elaborated + * expressions instead of pre-elaborated expression + * trees. + * + * Remove the eval_pexpr methods from PExpr. + * * Revision 1.272 2003/02/07 02:49:24 steve * Rewrite delay statement elaboration of handle real expressions. * diff --git a/eval_rconst.cc b/eval_rconst.cc deleted file mode 100644 index 1ed5f5226..000000000 --- a/eval_rconst.cc +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2001 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 - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: eval_rconst.cc,v 1.6 2003/02/01 23:37:34 steve Exp $" -#endif - -# include "config.h" - -# include "PExpr.h" -# include "verireal.h" - -verireal* PExpr::eval_rconst(const Design*, const NetScope*) const -{ - return 0; -} - -verireal* PEFNumber::eval_rconst(const Design*, const NetScope*) const -{ - verireal*res = new verireal; - *res = *value_; - return res; -} - -verireal* PENumber::eval_rconst(const Design*, const NetScope*) const -{ - verireal*res = new verireal(value_->as_long()); - return res; -} - -verireal* PEBinary::eval_rconst(const Design*des, const NetScope*scope) const -{ - verireal*lef = left_->eval_rconst(des, scope); - verireal*rig = right_->eval_rconst(des, scope); - verireal*res = 0; - - switch (op_) { - case '*': - if (lef == 0) - break; - if (rig == 0) - break; - res = new verireal; - *res = (*lef) * (*rig); - break; - - default: - break; - } - - delete lef; - delete rig; - return res; -} - - -verireal* PEIdent::eval_rconst(const Design*des, const NetScope*scope) const -{ - assert(scope); - const NetExpr*expr = des->find_parameter(scope, path_); - if (expr == 0) - return 0; - - /* Is this a real valued parameter? If so, then evaluate it - as a real expression and return the resulting verireal. */ - if (expr->expr_type() == NetExpr::ET_REAL) { - const NetECReal*ereal = dynamic_cast(expr); - if (ereal == 0) { - cerr << get_line() << ": internal error: " - << "Unable to evaluate real constant expression " - << "(parameter=" << path_ << "): " << *expr << endl; - return 0; - } - - return new verireal(ereal->value()); - } - - verinum* val = eval_const(des, scope); - if (val == 0) - return 0; - - verireal*res = new verireal(val->as_long()); - delete val; - return res; -} - -/* - * $Log: eval_rconst.cc,v $ - * Revision 1.6 2003/02/01 23:37:34 steve - * Allow parameter expressions to be type real. - * - * Revision 1.5 2002/08/12 01:34:59 steve - * conditional ident string using autoconfig. - * - * Revision 1.4 2001/11/07 04:01:59 steve - * eval_const uses scope instead of a string path. - * - * Revision 1.3 2001/11/06 06:11:55 steve - * Support more real arithmetic in delay constants. - * - * Revision 1.2 2001/07/25 03:10:49 steve - * Create a config.h.in file to hold all the config - * junk, and support gcc 3.0. (Stephan Boettcher) - * - * Revision 1.1 2001/01/14 23:04:56 steve - * Generalize the evaluation of floating point delays, and - * get it working with delay assignment statements. - * - * Allow parameters to be referenced by hierarchical name. - * - */ -