From bcf5e923896eb84d9d342246a5c2dfd5c3b61c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 11 Dec 2023 22:10:51 +0100 Subject: [PATCH 1/4] cxxrtl: Fix `ctlz` implementation --- backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index bd4affc30..0be7ab2b2 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -508,12 +508,13 @@ struct value : public expr_base> { size_t count = 0; for (size_t n = 0; n < chunks; n++) { chunk::type x = data[chunks - 1 - n]; - if (x == 0) { - count += (n == 0 ? Bits % chunk::bits : chunk::bits); - } else { - // This loop implements the find first set idiom as recognized by LLVM. - for (; x != 0; count++) + // First add to `count` as if the chunk is zero + count += (n == 0 ? Bits % chunk::bits : chunk::bits); + // If the chunk isn't zero, correct the `count` value and return + if (x != 0) { + for (; x != 0; count--) x >>= 1; + break; } } return count; From c848d98d9196a9c86acc1a27c9f07b6b52872861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 11 Dec 2023 22:11:35 +0100 Subject: [PATCH 2/4] cxxrtl: Fix `udivmod` logic --- backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index 0be7ab2b2..a1d32fa60 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -583,7 +583,7 @@ struct value : public expr_base> { value dividend = *this; if (dividend.ucmp(divisor)) return {/*quotient=*/value{0u}, /*remainder=*/dividend}; - uint32_t divisor_shift = dividend.ctlz() - divisor.ctlz(); + uint32_t divisor_shift = divisor.ctlz() - dividend.ctlz(); divisor = divisor.shl(value{divisor_shift}); for (size_t step = 0; step <= divisor_shift; step++) { quotient = quotient.shl(value{1u}); From 6206a3af304d25db1f8e057b9c88e0ad2d15dac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 12 Dec 2023 09:51:17 +0100 Subject: [PATCH 3/4] cxxrtl: Handle case of `Bits < 4` in formatting of values --- backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index a1d32fa60..04ed48eb3 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -796,7 +796,10 @@ std::ostream &operator<<(std::ostream &os, const value_formatted &vf) buf += '0'; while (!val.is_zero()) { value quotient, remainder; - std::tie(quotient, remainder) = val.udivmod(value{10u}); + if (Bits >= 4) + std::tie(quotient, remainder) = val.udivmod(value{10u}); + else + std::tie(quotient, remainder) = std::make_pair(value{0u}, val); buf += '0' + remainder.template trunc<(Bits > 4 ? 4 : Bits)>().val().template get(); val = quotient; } From 18d1907fa85eebb2c1d1ac9457b2f3d5928970be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 12 Dec 2023 09:52:35 +0100 Subject: [PATCH 4/4] cxxrtl: Assert well-formedness of input to `udivmod` --- backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index 04ed48eb3..2d5451287 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -583,8 +583,9 @@ struct value : public expr_base> { value dividend = *this; if (dividend.ucmp(divisor)) return {/*quotient=*/value{0u}, /*remainder=*/dividend}; - uint32_t divisor_shift = divisor.ctlz() - dividend.ctlz(); - divisor = divisor.shl(value{divisor_shift}); + int64_t divisor_shift = divisor.ctlz() - dividend.ctlz(); + assert(divisor_shift >= 0); + divisor = divisor.shl(value{(chunk::type) divisor_shift}); for (size_t step = 0; step <= divisor_shift; step++) { quotient = quotient.shl(value{1u}); if (!dividend.ucmp(divisor)) {