Support constant evaluation of / and % (PR#124)
This commit is contained in:
parent
57d1bfaf29
commit
94a1d59817
26
eval_tree.cc
26
eval_tree.cc
|
|
@ -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.
|
||||
|
|
|
|||
125
verinum.cc
125
verinum.cc
|
|
@ -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 ~.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue