Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cxxrtl: Fix sdivmod #4305

Merged
merged 1 commit into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions backends/cxxrtl/runtime/cxxrtl/cxxrtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -625,11 +625,11 @@ struct value : public expr_base<value<Bits>> {
value<Bits + 1> remainder;
value<Bits + 1> dividend = sext<Bits + 1>();
value<Bits + 1> divisor = other.template sext<Bits + 1>();
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<Bits>(), remainder.template trunc<Bits>()};
}
};
Expand Down
105 changes: 105 additions & 0 deletions tests/cxxrtl/test_value_fuzz.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ T rand_int(T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>
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) {}
Expand Down Expand Up @@ -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<size_t Bits>
cxxrtl::value<Bits> testing_impl(cxxrtl::value<Bits> a, cxxrtl::value<Bits> 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<size_t Bits>
cxxrtl::value<Bits> testing_impl(cxxrtl::value<Bits> a, cxxrtl::value<Bits> 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<size_t Bits>
cxxrtl::value<Bits> testing_impl(cxxrtl::value<Bits> a, cxxrtl::value<Bits> 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<size_t Bits>
cxxrtl::value<Bits> testing_impl(cxxrtl::value<Bits> a, cxxrtl::value<Bits> 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()
{
}
Loading