Fix a couple problems with signed multiply
Problems with signed expressions that are set to parameters and that include multipliciation exposed a few bugs in the calculation of signed multiply. Fix this and add some improved diagnostics.
This commit is contained in:
parent
32b115d8fe
commit
ea74eb771e
19
eval_tree.cc
19
eval_tree.cc
|
|
@ -808,13 +808,18 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||||
verinum lval = lc->value();
|
verinum lval = lc->value();
|
||||||
verinum rval = rc->value();
|
verinum rval = rc->value();
|
||||||
|
|
||||||
|
NetExpr*tmp = 0;
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case '/':
|
case '/':
|
||||||
return new NetEConst(lval / rval);
|
tmp = new NetEConst(lval / rval);
|
||||||
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
return new NetEConst(lval % rval);
|
tmp = new NetEConst(lval % rval);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
ivl_assert(*this, tmp);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -919,7 +924,13 @@ NetExpr* NetEBMult::eval_tree(int prune_to_width)
|
||||||
verinum lval = lc->value();
|
verinum lval = lc->value();
|
||||||
verinum rval = rc->value();
|
verinum rval = rc->value();
|
||||||
|
|
||||||
return new NetEConst(lval * rval);
|
NetEConst*tmp = new NetEConst(lval * rval);
|
||||||
|
|
||||||
|
if (debug_eval_tree)
|
||||||
|
cerr << get_fileline() << ": debug: Evaluate "
|
||||||
|
<< lval << " * " << rval << " --> " << *tmp << endl;
|
||||||
|
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* NetEBPow::eval_tree_real_()
|
NetExpr* NetEBPow::eval_tree_real_()
|
||||||
|
|
|
||||||
12
verinum.cc
12
verinum.cc
|
|
@ -881,14 +881,18 @@ verinum operator * (const verinum&left, const verinum&right)
|
||||||
verinum result(verinum::V0, left.len() + right.len(), has_len_flag);
|
verinum result(verinum::V0, left.len() + right.len(), has_len_flag);
|
||||||
result.has_sign(left.has_sign() || right.has_sign());
|
result.has_sign(left.has_sign() || right.has_sign());
|
||||||
|
|
||||||
for (unsigned rdx = 0 ; rdx < right.len() ; rdx += 1) {
|
verinum::V r_sign = sign_bit(right);
|
||||||
|
for (unsigned rdx = 0 ; rdx < result.len() ; rdx += 1) {
|
||||||
|
|
||||||
if (right.get(rdx) == verinum::V0)
|
verinum::V r_bit = rdx < right.len()? right.get(rdx) : r_sign;
|
||||||
|
if (r_bit == verinum::V0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
verinum::V l_sign = sign_bit(left);
|
||||||
verinum::V carry = verinum::V0;
|
verinum::V carry = verinum::V0;
|
||||||
for (unsigned ldx = 0 ; ldx < left.len() ; ldx += 1) {
|
for (unsigned ldx = 0 ; ldx < result.len()-rdx ; ldx += 1) {
|
||||||
result.set(ldx+rdx, add_with_carry(left[ldx],
|
verinum::V l_bit = ldx < left.len()? left[ldx] : l_sign;
|
||||||
|
result.set(ldx+rdx, add_with_carry(l_bit,
|
||||||
result[rdx+ldx],
|
result[rdx+ldx],
|
||||||
carry));
|
carry));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
verinum.h
13
verinum.h
|
|
@ -104,6 +104,19 @@ class verinum {
|
||||||
bool string_flag_;
|
bool string_flag_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This returns the sign bit of the verinum value. If the value is
|
||||||
|
* unsigned, then return an implicit sign bit of 0. Otherwise, return
|
||||||
|
* the high bit.
|
||||||
|
*/
|
||||||
|
inline verinum::V sign_bit(const verinum&val)
|
||||||
|
{
|
||||||
|
if (val.has_sign())
|
||||||
|
return val.get(val.len()-1);
|
||||||
|
else
|
||||||
|
return verinum::V0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a verinum that has the same value as the input, but is at
|
/* Return a verinum that has the same value as the input, but is at
|
||||||
least as wide as the requested width. This may involve sign
|
least as wide as the requested width. This may involve sign
|
||||||
extension, if the value is signed. */
|
extension, if the value is signed. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue