diff --git a/net_design.cc b/net_design.cc index d1bebfff8..b3a45582a 100644 --- a/net_design.cc +++ b/net_design.cc @@ -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; diff --git a/verinum.cc b/verinum.cc index a463cdb63..50759bdaf 100644 --- a/verinum.cc +++ b/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); 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)); } diff --git a/verinum.h b/verinum.h index 39caae4e8..3119b8101 100644 --- a/verinum.h +++ b/verinum.h @@ -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&);