Compile time evalutation of constant expressions.

This commit is contained in:
steve 1999-06-03 05:16:25 +00:00
parent f3a91a10b3
commit caae00f1fd
3 changed files with 103 additions and 8 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: elaborate.cc,v 1.32 1999/06/02 15:38:46 steve Exp $"
#ident "$Id: elaborate.cc,v 1.33 1999/06/03 05:16:25 steve Exp $"
#endif
/*
@ -1015,7 +1015,31 @@ NetProc* PCase::elaborate(Design*des, const string&path) const
NetProc* PCondit::elaborate(Design*des, const string&path) const
{
// Elaborate and try to evaluate the conditional expression.
NetExpr*expr = expr_->elaborate_expr(des, path);
NetExpr*tmp = expr->eval_tree();
if (tmp) {
delete expr;
expr = tmp;
}
// If the condition of the conditional statement is constant,
// then look at the value and elaborate either the if statement
// or the else statement. I don't need both. If there is no
// else_ statement, the use an empty block as a noop.
if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) {
verinum val = ce->value();
delete expr;
if (val[0] == verinum::V1)
return if_->elaborate(des, path);
else if (else_)
return else_->elaborate(des, path);
else
return new NetBlock(NetBlock::SEQU);
}
// Well, I actually need to generate code to handle the
// conditional, so elaborate.
NetProc*i = if_->elaborate(des, path);
NetProc*e = else_? else_->elaborate(des, path) : 0;
@ -1248,6 +1272,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.33 1999/06/03 05:16:25 steve
* Compile time evalutation of constant expressions.
*
* Revision 1.32 1999/06/02 15:38:46 steve
* Line information with nets.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.30 1999/06/02 15:38:46 steve Exp $"
#ident "$Id: netlist.cc,v 1.31 1999/06/03 05:16:25 steve Exp $"
#endif
# include <cassert>
@ -404,6 +404,11 @@ bool NetExpr::set_width(unsigned w)
return false;
}
NetExpr* NetExpr::eval_tree()
{
return 0;
}
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
: op_(op), left_(l), right_(r)
{
@ -426,7 +431,9 @@ bool NetEBinary::set_width(unsigned w)
case 'n': /* != */
assert(w == 1);
expr_width(w);
flag = right_->set_width(left_->expr_width());
flag = left_->set_width(right_->expr_width());
if (!flag)
flag = right_->set_width(left_->expr_width());
break;
case 'l': // left shift (<<)
@ -468,6 +475,50 @@ NetEBinary* NetEBinary::dup_expr() const
assert(0);
}
NetExpr* NetEBinary::eval_eqeq()
{
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
const verinum&lv = l->value();
const verinum&rv = r->value();
if (lv.len() < rv.len())
return 0;
verinum result(verinum::V1, 1);
for (unsigned idx = 0 ; idx < lv.len(); idx += 1) {
if (lv[idx] != rv[idx])
result = verinum::V0;
}
return new NetEConst(result);
}
NetExpr* NetEBinary::eval_tree()
{
NetExpr*tmp = left_->eval_tree();
if (tmp) {
delete left_;
left_ = tmp;
}
tmp = right_->eval_tree();
if (tmp){
delete right_;
right_ = tmp;
}
switch (op_) {
case 'e':
return eval_eqeq();
default:
return 0;
}
}
NetEConst::~NetEConst()
{
}
@ -539,11 +590,9 @@ NetESignal::~NetESignal()
bool NetESignal::set_width(unsigned w)
{
if (w != pin_count()) {
cerr << get_line() << ": " << *this << " cannot be made "
<< w << " bits wide." << endl;
if (w != pin_count())
return false;
}
assert(w == pin_count());
expr_width(w);
return true;
@ -1069,6 +1118,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.31 1999/06/03 05:16:25 steve
* Compile time evalutation of constant expressions.
*
* Revision 1.30 1999/06/02 15:38:46 steve
* Line information with nets.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.h,v 1.34 1999/06/02 15:38:46 steve Exp $"
#ident "$Id: netlist.h,v 1.35 1999/06/03 05:16:25 steve Exp $"
#endif
/*
@ -338,6 +338,12 @@ class NetExpr : public LineInfo {
// coersion works, then return true. Otherwise, return false.
virtual bool set_width(unsigned);
// This method evaluates the expression and returns an
// equivilent expression that is reduced as far as compile
// time knows how. Essentially, this is designed to fold
// constants.
virtual NetExpr*eval_tree();
// Make a duplicate of myself, and subexpressions if I have
// any. This is a deep copy operation.
virtual NetExpr*dup_expr() const =0;
@ -876,11 +882,18 @@ class NetEBinary : public NetExpr {
virtual bool set_width(unsigned w);
// If both of my subexpressions are constants, then I can
// probably evaluate this part of the expression at compile
// time.
virtual NetExpr* eval_tree();
virtual NetEBinary* dup_expr() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
NetExpr*eval_eqeq();
private:
char op_;
NetExpr* left_;
@ -1165,6 +1178,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.35 1999/06/03 05:16:25 steve
* Compile time evalutation of constant expressions.
*
* Revision 1.34 1999/06/02 15:38:46 steve
* Line information with nets.
*