diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index 166b4896f82..85f45ac7fbc 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -66,6 +66,7 @@ namespace cxxrtl { // Therefore, using relatively wide chunks and clearing the high bits explicitly and only when we know they may be // clobbered results in simpler generated code. typedef uint32_t chunk_t; +typedef uint64_t wide_chunk_t; template struct chunk_traits { @@ -454,6 +455,24 @@ struct value : public expr_base> { bool overflow = (is_neg() == !other.is_neg()) && (is_neg() != result.is_neg()); return result.is_neg() ^ overflow; // a.scmp(b) ≡ a s< b } + + template + value mul(const value &other) const { + value result; + wide_chunk_t wide_result[result.chunks + 1] = {}; + for (size_t n = 0; n < chunks; n++) { + for (size_t m = 0; m < chunks && n + m < result.chunks; m++) { + wide_result[n + m] += wide_chunk_t(data[n]) * wide_chunk_t(other.data[m]); + wide_result[n + m + 1] += wide_result[n + m] >> chunk::bits; + wide_result[n + m] &= chunk::mask; + } + } + for (size_t n = 0; n < result.chunks; n++) { + result.data[n] = wide_result[n]; + } + result.data[result.chunks - 1] &= result.msb_mask; + return result; + } }; // Expression template for a slice, usable as lvalue or rvalue, and composable with other expression templates here. @@ -1306,28 +1325,14 @@ value sub_ss(const value &a, const value &b) { template CXXRTL_ALWAYS_INLINE value mul_uu(const value &a, const value &b) { - value product; - value multiplicand = a.template zcast(); - const value &multiplier = b; - uint32_t multiplicand_shift = 0; - for (size_t step = 0; step < BitsB; step++) { - if (multiplier.bit(step)) { - multiplicand = multiplicand.shl(value<32> { multiplicand_shift }); - product = product.add(multiplicand); - multiplicand_shift = 0; - } - multiplicand_shift++; - } - return product; + constexpr size_t BitsM = BitsA >= BitsB ? BitsA : BitsB; + return a.template zcast().template mul(b.template zcast()); } template CXXRTL_ALWAYS_INLINE value mul_ss(const value &a, const value &b) { - value ub = b.template sext(); - if (ub.is_neg()) ub = ub.neg(); - value y = mul_uu(a.template scast(), ub); - return b.is_neg() ? y.neg() : y; + return a.template scast().template mul(b.template scast()); } template