From 19b861536333a5d400607aaf1c4985ac00a23bc7 Mon Sep 17 00:00:00 2001 From: steve Date: Sun, 10 Oct 1999 23:29:37 +0000 Subject: [PATCH] Support evaluating + operator at compile time. --- eval_tree.cc | 42 ++++++++++++++--- netlist.cc | 40 +++++++++++++++- netlist.h | 62 +++++++++++++++---------- verinum.cc | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++- verinum.h | 7 ++- 5 files changed, 244 insertions(+), 34 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index a16dbc71f..bcb5a6d03 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: eval_tree.cc,v 1.4 1999/09/23 03:56:57 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.5 1999/10/10 23:29:37 steve Exp $" #endif # include "netlist.h" @@ -26,8 +26,8 @@ NetExpr* NetExpr::eval_tree() { return 0; } -/* +/* * Some of the derived classes can be evaluated by the compiler, this * method provides the common aid of evaluating the parameter * expressions. @@ -46,8 +46,33 @@ void NetEBinary::eval_sub_tree_() } } +NetEConst* NetEBAdd::eval_tree() +{ + eval_sub_tree_(); + NetEConst*lc = dynamic_cast(left_); + if (lc == 0) return 0; + NetEConst*rc = dynamic_cast(right_); + if (rc == 0) return 0; -NetExpr* NetEBComp::eval_eqeq_() + verinum lval = lc->value(); + verinum rval = rc->value(); + + verinum val; + switch (op_) { + case '+': + val = lval + rval; + break; + case '-': + val = lval - rval; + break; + default: + return 0; + } + + return new NetEConst(val); +} + +NetEConst* NetEBComp::eval_eqeq_() { NetEConst*l = dynamic_cast(left_); if (l == 0) return 0; @@ -70,7 +95,7 @@ NetExpr* NetEBComp::eval_eqeq_() } -NetExpr* NetEBComp::eval_leeq_() +NetEConst* NetEBComp::eval_leeq_() { NetEConst*r = dynamic_cast(right_); if (r == 0) return 0; @@ -90,7 +115,7 @@ NetExpr* NetEBComp::eval_leeq_() } -NetExpr* NetEBComp::eval_tree() +NetEConst* NetEBComp::eval_tree() { eval_sub_tree_(); @@ -106,7 +131,7 @@ NetExpr* NetEBComp::eval_tree() } } -NetExpr* NetEBLogic::eval_tree() +NetEConst* NetEBLogic::eval_tree() { eval_sub_tree_(); return 0; @@ -116,7 +141,7 @@ NetExpr* NetEBLogic::eval_tree() * Evaluate the shift operator if possible. For this to work, both * operands must be constant. */ -NetExpr* NetEBShift::eval_tree() +NetEConst* NetEBShift::eval_tree() { eval_sub_tree_(); NetEConst*re = dynamic_cast(right_); @@ -236,6 +261,9 @@ NetExpr* NetEParam::eval_tree() /* * $Log: eval_tree.cc,v $ + * Revision 1.5 1999/10/10 23:29:37 steve + * Support evaluating + operator at compile time. + * * Revision 1.4 1999/09/23 03:56:57 steve * Support shift operators. * diff --git a/netlist.cc b/netlist.cc index a29e4f6ca..e3c5bf06e 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.76 1999/10/10 01:59:55 steve Exp $" +#ident "$Id: netlist.cc,v 1.77 1999/10/10 23:29:37 steve Exp $" #endif # include @@ -833,6 +833,13 @@ NetEBAdd::~NetEBAdd() { } +NetEBAdd* NetEBAdd::dup_expr() const +{ + NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { @@ -865,6 +872,13 @@ NetEBBits::~NetEBBits() { } +NetEBBits* NetEBBits::dup_expr() const +{ + NetEBBits*result = new NetEBBits(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { @@ -875,6 +889,13 @@ NetEBComp::~NetEBComp() { } +NetEBComp* NetEBComp::dup_expr() const +{ + NetEBComp*result = new NetEBComp(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r) : op_(op), left_(l), right_(r) { @@ -901,6 +922,13 @@ NetEBLogic::~NetEBLogic() { } +NetEBLogic* NetEBLogic::dup_expr() const +{ + NetEBLogic*result = new NetEBLogic(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { @@ -911,6 +939,13 @@ NetEBShift::~NetEBShift() { } +NetEBShift* NetEBShift::dup_expr() const +{ + NetEBShift*result = new NetEBShift(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + NetEConcat::NetEConcat(unsigned cnt, unsigned r) : parms_(cnt), repeat_(r) { @@ -1754,6 +1789,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.77 1999/10/10 23:29:37 steve + * Support evaluating + operator at compile time. + * * Revision 1.76 1999/10/10 01:59:55 steve * Structural case equals device. * diff --git a/netlist.h b/netlist.h index f98cec311..bcd9901a4 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.79 1999/10/10 01:59:55 steve Exp $" +#ident "$Id: netlist.h,v 1.80 1999/10/10 23:29:37 steve Exp $" #endif /* @@ -398,6 +398,29 @@ class NetExpr : public LineInfo { NetExpr& operator=(const NetExpr&); }; +/* + * The expression constant is slightly special, and is sometimes + * retured from other classes that can be evaluated at compile + * time. This class represents constant values in expressions. + */ +class NetEConst : public NetExpr { + + public: + explicit NetEConst(const verinum&val); + ~NetEConst(); + + const verinum&value() const { return value_; } + + virtual bool set_width(unsigned w); + virtual void expr_scan(struct expr_scan_t*) const; + virtual void dump(ostream&) const; + + virtual NetEConst* dup_expr() const; + + private: + verinum value_; +}; + /* * The NetTmp object is a network that is only used momentarily by * elaboration to carry links around. A completed netlist cannot have @@ -1219,6 +1242,8 @@ class NetEBAdd : public NetEBinary { ~NetEBAdd(); virtual bool set_width(unsigned w); + virtual NetEBAdd* dup_expr() const; + virtual NetEConst* eval_tree(); }; /* @@ -1242,6 +1267,7 @@ class NetEBBits : public NetEBinary { ~NetEBBits(); virtual bool set_width(unsigned w); + virtual NetEBBits* dup_expr() const; }; /* @@ -1265,11 +1291,12 @@ class NetEBComp : public NetEBinary { ~NetEBComp(); virtual bool set_width(unsigned w); - virtual NetExpr* eval_tree(); + virtual NetEBComp* dup_expr() const; + virtual NetEConst* eval_tree(); private: - NetExpr*eval_eqeq_(); - NetExpr*eval_leeq_(); + NetEConst*eval_eqeq_(); + NetEConst*eval_leeq_(); }; @@ -1286,7 +1313,8 @@ class NetEBLogic : public NetEBinary { ~NetEBLogic(); virtual bool set_width(unsigned w); - virtual NetExpr* eval_tree(); + virtual NetEBLogic* dup_expr() const; + virtual NetEConst* eval_tree(); private: }; @@ -1306,7 +1334,8 @@ class NetEBShift : public NetEBinary { ~NetEBShift(); virtual bool set_width(unsigned w); - virtual NetExpr* eval_tree(); + virtual NetEBShift* dup_expr() const; + virtual NetEConst* eval_tree(); private: }; @@ -1345,24 +1374,6 @@ class NetEConcat : public NetExpr { unsigned repeat_; }; -class NetEConst : public NetExpr { - - public: - explicit NetEConst(const verinum&val); - ~NetEConst(); - - const verinum&value() const { return value_; } - - virtual bool set_width(unsigned w); - virtual void expr_scan(struct expr_scan_t*) const; - virtual void dump(ostream&) const; - - virtual NetEConst* dup_expr() const; - - private: - verinum value_; -}; - /* * This clas is a placeholder for a parameter expression. When * parameters are first created, an instance of this object is used to @@ -1733,6 +1744,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.80 1999/10/10 23:29:37 steve + * Support evaluating + operator at compile time. + * * Revision 1.79 1999/10/10 01:59:55 steve * Structural case equals device. * diff --git a/verinum.cc b/verinum.cc index 8b262a1b8..678ba333a 100644 --- a/verinum.cc +++ b/verinum.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: verinum.cc,v 1.9 1999/07/20 05:12:22 steve Exp $" +#ident "$Id: verinum.cc,v 1.10 1999/10/10 23:29:37 steve Exp $" #endif # include "verinum.h" @@ -308,8 +308,133 @@ bool operator == (const verinum&left, const verinum&right) return true; } +static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c) +{ + unsigned sum = 0; + switch (c) { + case verinum::Vx: + case verinum::Vz: + c = verinum::Vx; + return verinum::Vx; + case verinum::V0: + break; + case verinum::V1: + sum += 1; + } + + switch (l) { + case verinum::Vx: + case verinum::Vz: + c = verinum::Vx; + return verinum::Vx; + case verinum::V0: + break; + case verinum::V1: + sum += 1; + break; + } + + switch (r) { + case verinum::Vx: + case verinum::Vz: + c = verinum::Vx; + return verinum::Vx; + case verinum::V0: + break; + case verinum::V1: + sum += 1; + break; + } + + if (sum & 2) + c = verinum::V1; + else + c = verinum::V0; + if (sum & 1) + return verinum::V1; + else + return verinum::V0; +} + +verinum not(const verinum&left) +{ + verinum val = left; + for (unsigned idx = 0 ; idx < val.len() ; idx += 1) + switch (val[idx]) { + case verinum::V0: + val.set(idx, verinum::V1); + break; + case verinum::V1: + val.set(idx, verinum::V0); + break; + default: + val.set(idx, verinum::Vx); + break; + } + + return val; +} + +/* + * Addition works a bit at a time, from the least significant up to + * the most significant. + */ +verinum operator + (const verinum&left, const verinum&right) +{ + unsigned min = left.len(); + if (right.len() < min) min = right.len(); + + unsigned max = left.len(); + if (right.len() > max) max = right.len(); + + verinum val (verinum::V0, max); + + verinum::V carry = verinum::V0; + for (unsigned idx = 0 ; idx < min ; idx += 1) + val.set(idx, add_with_carry(left[idx], right[idx], carry)); + + if (left.len() > right.len()) { + for (unsigned idx = min ; idx < max ; idx += 1) + val.set(idx,add_with_carry(left[idx], verinum::V0, carry)); + } else { + for (unsigned idx = min ; idx < max ; idx += 1) + val.set(idx, add_with_carry(verinum::V0, right[idx], carry)); + } + + return val; +} + +verinum operator - (const verinum&left, const verinum&r) +{ + verinum right = not(r); + unsigned min = left.len(); + if (right.len() < min) min = right.len(); + + unsigned max = left.len(); + if (right.len() > max) max = right.len(); + + verinum val (verinum::V0, max); + + verinum::V carry = verinum::V1; + for (unsigned idx = 0 ; idx < min ; idx += 1) + val.set(idx, add_with_carry(left[idx], right[idx], carry)); + + if (left.len() > right.len()) { + for (unsigned idx = min ; idx < max ; idx += 1) + val.set(idx,add_with_carry(left[idx], verinum::V0, carry)); + } else { + for (unsigned idx = min ; idx < max ; idx += 1) + val.set(idx, add_with_carry(verinum::V0, right[idx], carry)); + } + + return val; +} + /* * $Log: verinum.cc,v $ + * Revision 1.10 1999/10/10 23:29:37 steve + * Support evaluating + operator at compile time. + * * Revision 1.9 1999/07/20 05:12:22 steve * Implement the set method. * diff --git a/verinum.h b/verinum.h index 7b3642263..3785414a3 100644 --- a/verinum.h +++ b/verinum.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: verinum.h,v 1.5 1999/05/13 04:02:09 steve Exp $" +#ident "$Id: verinum.h,v 1.6 1999/10/10 23:29:37 steve Exp $" #endif # include @@ -91,9 +91,14 @@ extern ostream& operator<< (ostream&, const verinum&); extern ostream& operator<< (ostream&, verinum::V); extern bool operator == (const verinum&left, const verinum&right); +extern verinum operator + (const verinum&left, const verinum&right); +extern verinum operator - (const verinum&left, const verinum&right); /* * $Log: verinum.h,v $ + * Revision 1.6 1999/10/10 23:29:37 steve + * Support evaluating + operator at compile time. + * * Revision 1.5 1999/05/13 04:02:09 steve * More precise handling of verinum bit lengths. *