Support constant evaluation of / and % (PR#124)

This commit is contained in:
steve 2001-02-07 02:46:31 +00:00
parent 57d1bfaf29
commit 94a1d59817
3 changed files with 151 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) && !defined(macintosh)
#ident "$Id: eval_tree.cc,v 1.21 2001/01/14 23:04:56 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.22 2001/02/07 02:46:31 steve Exp $"
#endif
# include "netlist.h"
@ -363,9 +363,30 @@ NetEConst* NetEBComp::eval_tree()
}
}
/*
* The NetEBDiv operator includes the / and % opeators. First evaluate
* the sub-expressions, then perform the required operation.
*/
NetEConst* NetEBDiv::eval_tree()
{
eval_sub_tree_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum lval = lc->value();
verinum rval = rc->value();
switch (op_) {
case '/':
return new NetEConst(lval / rval);
case '%':
return new NetEConst(lval % rval);
}
return 0;
}
@ -822,6 +843,9 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.22 2001/02/07 02:46:31 steve
* Support constant evaluation of / and % (PR#124)
*
* Revision 1.21 2001/01/14 23:04:56 steve
* Generalize the evaluation of floating point delays, and
* get it working with delay assignment statements.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: verinum.cc,v 1.22 2001/01/02 03:23:40 steve Exp $"
#ident "$Id: verinum.cc,v 1.23 2001/02/07 02:46:31 steve Exp $"
#endif
# include "verinum.h"
@ -60,8 +60,8 @@ verinum::verinum(const string&str)
}
}
verinum::verinum(verinum::V val, unsigned n)
: has_len_(true), has_sign_(false), string_flag_(false)
verinum::verinum(verinum::V val, unsigned n, bool h)
: has_len_(h), has_sign_(false), string_flag_(false)
{
nbits_ = n;
bits_ = new V[nbits_];
@ -523,13 +523,18 @@ verinum operator - (const verinum&left, const verinum&r)
*/
verinum operator * (const verinum&left, const verinum&right)
{
const bool has_len_flag = left.has_len() && right.has_len();
/* If either operand is not fully defined, then the entire
result is undefined. Create a result that is the right size
and is filled with 'bx bits. */
if (! (left.is_defined() && right.is_defined())) {
verinum result (verinum::Vx, left.len() + right.len());
verinum result (verinum::Vx, left.len()+right.len(), has_len_flag);
result.has_sign(left.has_sign() || right.has_sign());
return result;
}
verinum result(verinum::V0, left.len() + right.len());
verinum result(verinum::V0, left.len() + right.len(), has_len_flag);
for (unsigned rdx = 0 ; rdx < right.len() ; rdx += 1) {
@ -548,6 +553,113 @@ verinum operator * (const verinum&left, const verinum&right)
return result;
}
/*
* This operator divides the left number by the right number. If
* either value is signed, the result is signed. If both values have a
* defined length, then the result has a defined length.
*/
verinum operator / (const verinum&left, const verinum&right)
{
const bool has_len_flag = left.has_len() && right.has_len();
unsigned use_len = left.len();
/* If either operand is not fully defined, then the entire
result is undefined. Create a result that is the right size
and is filled with 'bx bits. */
if (! (left.is_defined() && right.is_defined())) {
verinum result (verinum::Vx, use_len, has_len_flag);
result.has_sign(left.has_sign() || right.has_sign());
return result;
}
verinum result(verinum::Vz, use_len, has_len_flag);
result.has_sign(left.has_sign() || right.has_sign());
/* do the operation differently, depending on whether the
result is signed or not. */
if (result.has_sign()) {
/* XXXX FIXME XXXX Use native unsigned division to do
the work. This does not work if the result is too
large for the native integer. */
assert(use_len <= 8*sizeof(long));
long l = left.as_long();
long r = right.as_long();
long v = l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
}
} else {
/* XXXX FIXME XXXX Use native unsigned division to do
the work. This does not work if the result is too
large for the native integer. */
assert(use_len <= 8*sizeof(unsigned long));
unsigned long l = left.as_ulong();
unsigned long r = right.as_ulong();
unsigned long v = l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
}
}
return result;
}
verinum operator % (const verinum&left, const verinum&right)
{
const bool has_len_flag = left.has_len() && right.has_len();
unsigned use_len = left.len();
/* If either operand is not fully defined, then the entire
result is undefined. Create a result that is the right size
and is filled with 'bx bits. */
if (! (left.is_defined() && right.is_defined())) {
verinum result (verinum::Vx, use_len, has_len_flag);
result.has_sign(left.has_sign() || right.has_sign());
return result;
}
verinum result(verinum::Vz, use_len, has_len_flag);
result.has_sign(left.has_sign() || right.has_sign());
if (result.has_sign()) {
/* XXXX FIXME XXXX Use native unsigned division to do
the work. This does not work if the result is too
large for the native integer. */
assert(use_len <= 8*sizeof(long));
long l = left.as_long();
long r = right.as_long();
long v = l % r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
}
} else {
/* XXXX FIXME XXXX Use native unsigned division to do
the work. This does not work if the result is too
large for the native integer. */
assert(use_len <= 8*sizeof(unsigned long));
unsigned long l = left.as_ulong();
unsigned long r = right.as_ulong();
unsigned long v = l % r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
}
}
return result;
}
verinum::V operator | (verinum::V l, verinum::V r)
{
if (l == verinum::V1)
@ -576,6 +688,9 @@ verinum::V operator & (verinum::V l, verinum::V r)
/*
* $Log: verinum.cc,v $
* Revision 1.23 2001/02/07 02:46:31 steve
* Support constant evaluation of / and % (PR#124)
*
* Revision 1.22 2001/01/02 03:23:40 steve
* Evaluate constant &, | and unary ~.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: verinum.h,v 1.15 2001/01/16 02:44:18 steve Exp $"
#ident "$Id: verinum.h,v 1.16 2001/02/07 02:46:31 steve Exp $"
#endif
# include <string>
@ -44,7 +44,7 @@ class verinum {
verinum();
verinum(const string&str);
verinum(const V*v, unsigned nbits, bool has_len =true);
verinum(V, unsigned nbits =1);
verinum(V, unsigned nbits =1, bool has_len =true);
verinum(unsigned long val, unsigned bits);
verinum(const verinum&);
@ -114,11 +114,15 @@ extern verinum 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);
extern verinum operator / (const verinum&left, const verinum&right);
extern verinum operator % (const verinum&left, const verinum&right);
extern verinum v_not(const verinum&left);
/*
* $Log: verinum.h,v $
* Revision 1.16 2001/02/07 02:46:31 steve
* Support constant evaluation of / and % (PR#124)
*
* Revision 1.15 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*