Skip to content

Commit

Permalink
Calculate delay statement delays using elaborated
Browse files Browse the repository at this point in the history
 expressions instead of pre-elaborated expression
 trees.

 Remove the eval_pexpr methods from PExpr.
  • Loading branch information
steve committed Feb 8, 2003
1 parent 26b755d commit e571dd9
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 243 deletions.
4 changes: 2 additions & 2 deletions Makefile.in
Expand Up @@ -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
Expand Down Expand Up @@ -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 \
Expand Down
66 changes: 45 additions & 21 deletions PDelays.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
NetExpr*dex = expr->elaborate_expr(des, scope);
if (NetExpr*tmp = dex->eval_tree()) {
delete dex;
dex = tmp;
}

if (verireal*dr = expr->eval_rconst(des, scope)) {
val = dr->as_long(shift);
delete dr;
/* 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. */

} 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;
}
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;
}

assert(dv);
val = dv->as_ulong();
val = des->scale_to_precision(val, scope);
delete dv;

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;
}

return val;
/* 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,
Expand Down Expand Up @@ -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.
*
Expand Down
21 changes: 8 additions & 13 deletions PExpr.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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".
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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_;
Expand Down Expand Up @@ -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.
*
Expand Down
133 changes: 53 additions & 80 deletions 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
Expand All @@ -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"
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

/* 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;
/* 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);

if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
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);

/* 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;
delete dex;

} else {
if (statement_)
return new NetPDelay(delay, statement_->elaborate(des, scope));
return new NetPDelay(dex, statement_->elaborate(des, scope));
else
return new NetPDelay(delay, 0);
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);

}

/*
Expand Down Expand Up @@ -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.
*
Expand Down

0 comments on commit e571dd9

Please sign in to comment.