Clean up $clog2() measurement of unsized numbers.

If the argument to $clog2() is unsized constant, then trim it to the
smallest representation that doesn't lose the sign, then do the $clog2
on that.

Also, use integer_width instead of 32 for the minimum $clog2() result
for a negative value.
This commit is contained in:
Stephen Williams 2008-08-28 21:15:43 -07:00
parent ed929a37bb
commit e322cce650
1 changed files with 13 additions and 4 deletions

View File

@ -1614,7 +1614,6 @@ NetExpr* evaluate_clog2(NetExpr*arg)
{ {
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg); NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg); NetECReal*tmpr = dynamic_cast<NetECReal *>(arg);
bool is_neg = false;
if (tmpi || tmpr) { if (tmpi || tmpr) {
verinum arg; verinum arg;
if (tmpi) { if (tmpi) {
@ -1631,9 +1630,17 @@ NetExpr* evaluate_clog2(NetExpr*arg)
return rtn; return rtn;
} }
bool is_neg = false;
uint64_t res = 0; uint64_t res = 0;
if (arg.is_negative()) is_neg = true; if (arg.is_negative()) {
is_neg = true;
// If the length is not defined, then work with
// the trimmed version of the number.
if (! arg.has_len())
arg = trim_vnum(arg);
}
arg.has_sign(false); // $unsigned() arg.has_sign(false); // $unsigned()
if (!arg.is_zero()) { if (!arg.is_zero()) {
arg = arg - verinum((uint64_t)1, 1); arg = arg - verinum((uint64_t)1, 1);
while (!arg.is_zero()) { while (!arg.is_zero()) {
@ -1641,9 +1648,11 @@ NetExpr* evaluate_clog2(NetExpr*arg)
arg = arg >> 1; arg = arg >> 1;
} }
} }
if (is_neg && res < 32) res = 32;
if (is_neg && res < integer_width)
res = integer_width;
verinum tmp (res, 32); verinum tmp (res, 32);
tmp.has_sign(true);
NetEConst*rtn = new NetEConst(tmp); NetEConst*rtn = new NetEConst(tmp);
return rtn; return rtn;
} }