V0.8: fix signed parameter multiply

This patch mirrors what was done in development to fix the
multiplication of signed values.
This commit is contained in:
Cary R 2008-11-21 18:08:36 -08:00 committed by Stephen Williams
parent abc2aa17d2
commit 7dc473db8d
3 changed files with 24 additions and 9 deletions

View File

@ -424,10 +424,6 @@ void NetScope::evaluate_parameters(Design*des)
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
// Set the signedness flag.
(*cur).second.expr
->cast_signed( (*cur).second.signed_flag );
}
break;
@ -440,7 +436,9 @@ void NetScope::evaluate_parameters(Design*des)
}
/* If the parameter has range information, then make
sure the value is set right. */
sure the value is set right. Note that if the
parameter doesn't have an explicit range, then it
will get the signedness from the expression itself. */
if (range_flag) {
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;

View File

@ -734,14 +734,18 @@ verinum operator * (const verinum&left, const verinum&right)
verinum result(verinum::V0, left.len() + right.len(), has_len_flag);
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;
verinum::V l_sign = sign_bit(left);
verinum::V carry = verinum::V0;
for (unsigned ldx = 0 ; ldx < left.len() ; ldx += 1) {
result.set(ldx+rdx, add_with_carry(left[ldx],
for (unsigned ldx = 0 ; ldx < result.len()-rdx ; ldx += 1) {
verinum::V l_bit = ldx < left.len()? left[ldx] : l_sign;
result.set(ldx+rdx, add_with_carry(l_bit,
result[rdx+ldx],
carry));
}

View File

@ -106,6 +106,19 @@ class verinum {
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 is minimal. That is, it has only the length
needed to accurately represent the contained value, signed or not. */
extern verinum trim_vnum(const verinum&);