diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index b834cd120..16aa900f1 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -625,11 +625,11 @@ struct value : public expr_base> { value remainder; value dividend = sext(); value divisor = other.template sext(); - if (dividend.is_neg()) dividend = dividend.neg(); - if (divisor.is_neg()) divisor = divisor.neg(); + if (is_neg()) dividend = dividend.neg(); + if (other.is_neg()) divisor = divisor.neg(); std::tie(quotient, remainder) = dividend.udivmod(divisor); - if (dividend.is_neg() != divisor.is_neg()) quotient = quotient.neg(); - if (dividend.is_neg()) remainder = remainder.neg(); + if (is_neg() != other.is_neg()) quotient = quotient.neg(); + if (is_neg()) remainder = remainder.neg(); return {quotient.template trunc(), remainder.template trunc()}; } }; diff --git a/tests/cxxrtl/test_value_fuzz.cc b/tests/cxxrtl/test_value_fuzz.cc index 4428e9f6e..a7bbb293a 100644 --- a/tests/cxxrtl/test_value_fuzz.cc +++ b/tests/cxxrtl/test_value_fuzz.cc @@ -25,6 +25,11 @@ T rand_int(T min = std::numeric_limits::min(), T max = std::numeric_limits return dist(generator); } +int64_t sext(size_t bits, uint64_t value) +{ + return (int64_t)(value << (64 - bits)) >> (64 - bits); +} + struct BinaryOperationBase { void tweak_input(uint64_t &a, uint64_t &b) {} @@ -246,6 +251,106 @@ struct CtlzTest } } ctlz; +struct UdivTest : BinaryOperationBase +{ + UdivTest() + { + std::printf("Randomized tests for value::udivmod (div):\n"); + test_binary_operation(*this); + } + + uint64_t reference_impl(size_t bits, uint64_t a, uint64_t b) + { + return a / b; + } + + template + cxxrtl::value testing_impl(cxxrtl::value a, cxxrtl::value b) + { + return std::get<0>(a.udivmod(b)); + } + + void tweak_input(uint64_t &, uint64_t &b) + { + if (b == 0) b = 1; // Avoid divide by zero + } +} udiv; + +struct UmodTest : BinaryOperationBase +{ + UmodTest() + { + std::printf("Randomized tests for value::udivmod (mod):\n"); + test_binary_operation(*this); + } + + uint64_t reference_impl(size_t bits, uint64_t a, uint64_t b) + { + return a % b; + } + + template + cxxrtl::value testing_impl(cxxrtl::value a, cxxrtl::value b) + { + return std::get<1>(a.udivmod(b)); + } + + void tweak_input(uint64_t &, uint64_t &b) + { + if (b == 0) b = 1; // Avoid divide by zero + } +} umod; + +struct SdivTest : BinaryOperationBase +{ + SdivTest() + { + std::printf("Randomized tests for value::sdivmod (div):\n"); + test_binary_operation(*this); + } + + uint64_t reference_impl(size_t bits, uint64_t a, uint64_t b) + { + return (uint64_t)(sext(bits, a) / sext(bits, b)); + } + + template + cxxrtl::value testing_impl(cxxrtl::value a, cxxrtl::value b) + { + return std::get<0>(a.sdivmod(b)); + } + + void tweak_input(uint64_t &, uint64_t &b) + { + if (b == 0) b = 1; // Avoid divide by zero + } +} sdiv; + +struct SmodTest : BinaryOperationBase +{ + SmodTest() + { + std::printf("Randomized tests for value::sdivmod (mod):\n"); + test_binary_operation(*this); + } + + uint64_t reference_impl(size_t bits, uint64_t a, uint64_t b) + { + return (uint64_t)(sext(bits, a) % sext(bits, b)); + } + + template + cxxrtl::value testing_impl(cxxrtl::value a, cxxrtl::value b) + { + return std::get<1>(a.sdivmod(b)); + } + + void tweak_input(uint64_t &, uint64_t &b) + { + if (b == 0) b = 1; // Avoid divide by zero + } +} smod; + int main() { }