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:
parent
abc2aa17d2
commit
7dc473db8d
|
|
@ -424,10 +424,6 @@ void NetScope::evaluate_parameters(Design*des)
|
||||||
assert(nexpr);
|
assert(nexpr);
|
||||||
delete expr;
|
delete expr;
|
||||||
(*cur).second.expr = nexpr;
|
(*cur).second.expr = nexpr;
|
||||||
|
|
||||||
// Set the signedness flag.
|
|
||||||
(*cur).second.expr
|
|
||||||
->cast_signed( (*cur).second.signed_flag );
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -440,7 +436,9 @@ void NetScope::evaluate_parameters(Design*des)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the parameter has range information, then make
|
/* 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) {
|
if (range_flag) {
|
||||||
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
||||||
wid += 1;
|
wid += 1;
|
||||||
|
|
|
||||||
12
verinum.cc
12
verinum.cc
|
|
@ -734,14 +734,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
|
|
@ -106,6 +106,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 is minimal. That is, it has only the length
|
/* Return a verinum that is minimal. That is, it has only the length
|
||||||
needed to accurately represent the contained value, signed or not. */
|
needed to accurately represent the contained value, signed or not. */
|
||||||
extern verinum trim_vnum(const verinum&);
|
extern verinum trim_vnum(const verinum&);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue