Calculate delay statement delays using elaborated

expressions instead of pre-elaborated expression
 trees.

 Remove the eval_pexpr methods from PExpr.
This commit is contained in:
steve 2003-02-08 19:49:21 +00:00
parent 26b755d544
commit e571dd90d8
5 changed files with 114 additions and 249 deletions

View File

@ -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 \

View File

@ -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<PExpr*>*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<NetECReal*>(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<NetEConst*>(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.
*

21
PExpr.h
View File

@ -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 <string>
# 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.
*

View File

@ -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<NetECReal*>(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<NetEConst*>(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<NetECReal*>(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<NetEConst*>(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(list<const char*>roots)
/*
* $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.
*

View File

@ -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<const NetECReal*>(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.
*
*/