diff --git a/elaborate.cc b/elaborate.cc index 1cd61523f..bf8690ee6 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -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(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&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. * diff --git a/netlist.cc b/netlist.cc index 604e0b1a5..a73016451 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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 @@ -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(left_); + if (l == 0) return 0; + NetEConst*r = dynamic_cast(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. * diff --git a/netlist.h b/netlist.h index ffa7225e3..d2ff0d41e 100644 --- a/netlist.h +++ b/netlist.h @@ -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. *