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:
parent
26b755d544
commit
e571dd90d8
|
|
@ -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 \
|
||||
|
|
|
|||
72
PDelays.cc
72
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<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
21
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 <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.
|
||||
*
|
||||
|
|
|
|||
139
elaborate.cc
139
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<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.
|
||||
*
|
||||
|
|
|
|||
127
eval_rconst.cc
127
eval_rconst.cc
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue