3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-12 20:18:20 +00:00

fmt: fuzz, remove some unnecessary busywork

Removing some signed checks and logic where we've already guaranteed the
values to be positive.  Indeed, in these cases, if a negative value got
through (per my realisation in the signed fuzz harness), it would cause
an infinite loop due to flooring division.
This commit is contained in:
Charlotte 2023-06-28 11:51:24 +10:00 committed by Marcelina Kościelnicka
parent 2ae551c0af
commit 3571bf2c2d
4 changed files with 55 additions and 20 deletions

View file

@ -905,10 +905,7 @@ std::ostream &operator<<(std::ostream &os, const value_formatted<Bits> &vf)
buf += '0'; buf += '0';
while (!val.is_zero()) { while (!val.is_zero()) {
value<Bits> quotient; value<Bits> quotient;
if (negative) val.divideWithRemainder(value<Bits>{10u}, quotient);
val.signedDivideWithRemainder(value<Bits>{10u}, quotient);
else
val.divideWithRemainder(value<Bits>{10u}, quotient);
buf += '0' + val.template slice<3, 0>().val().template get<uint8_t>(); buf += '0' + val.template slice<3, 0>().val().template get<uint8_t>();
val = quotient; val = quotient;
} }

View file

@ -680,8 +680,8 @@ std::string Fmt::render() const
if (absvalue.is_fully_zero()) if (absvalue.is_fully_zero())
buf += '0'; buf += '0';
while (!absvalue.is_fully_zero()) { while (!absvalue.is_fully_zero()) {
buf += '0' + RTLIL::const_mod(absvalue, 10, part.signed_, false, 4).as_int(); buf += '0' + RTLIL::const_mod(absvalue, 10, false, false, 4).as_int();
absvalue = RTLIL::const_div(absvalue, 10, part.signed_, false, absvalue.size()); absvalue = RTLIL::const_div(absvalue, 10, false, false, absvalue.size());
} }
if (negative || part.plus) if (negative || part.plus)
buf += negative ? '-' : '+'; buf += negative ? '-' : '+';

View file

@ -17,6 +17,7 @@ add_executable(
x_test x_test
x_test.cc x_test.cc
../../../libs/bigint/BigUnsigned.cc ../../../libs/bigint/BigUnsigned.cc
../../../libs/bigint/BigInteger.cc
) )
link_fuzztest(x_test) link_fuzztest(x_test)

View file

@ -4,34 +4,33 @@
#include <sstream> #include <sstream>
#include "backends/cxxrtl/cxxrtl.h" #include "backends/cxxrtl/cxxrtl.h"
#include "libs/bigint/BigUnsigned.hh" #include "libs/bigint/BigUnsigned.hh"
#include "libs/bigint/BigInteger.hh"
using namespace cxxrtl_yosys; using namespace cxxrtl_yosys;
void Formats128BitUnsignedIntegers(uint64_t x, uint64_t y) { void Formats128BitUnsignedIntegers(chunk_t x0, chunk_t x1, chunk_t x2, chunk_t x3)
// Compare output to actual BigUnsigned. {
value<64> vs; // Compare output to BigUnsigned.
value<128> v; value<128> v;
vs.set(x); v = v.blit<127, 64>(value<64>{x1, x0});
v = v.blit<127, 64>(vs); v = v.blit<63, 0>(value<64>{x3, x2});
vs.set(y);
v = v.blit<63, 0>(vs);
std::ostringstream oss; std::ostringstream oss;
oss << value_formatted<128>(v, false, false, ' ', 0, 10, false, false, false); oss << value_formatted<128>(v, false, false, ' ', 0, 10, false, false, false);
auto actual = oss.str(); auto actual = oss.str();
BigUnsigned b(x); BigUnsigned u;
b.bitShiftLeft(b, 64); u.bitShiftLeft(v.slice<127, 64>().val().get<uint64_t>(), 64);
b.bitOr(b, y); u.bitOr(u, v.slice<63, 0>().val().get<uint64_t>());
std::string expected; std::string expected;
if (b.isZero()) { if (u.isZero()) {
expected = "0"; expected = "0";
} else { } else {
while (!b.isZero()) { while (!u.isZero()) {
expected += '0' + (b % 10).toInt(); expected += '0' + (u % 10).toInt();
b /= 10; u /= 10;
} }
std::reverse(expected.begin(), expected.end()); std::reverse(expected.begin(), expected.end());
} }
@ -40,3 +39,41 @@ void Formats128BitUnsignedIntegers(uint64_t x, uint64_t y) {
} }
FUZZ_TEST(CxxrtlDivisionFuzz, Formats128BitUnsignedIntegers); FUZZ_TEST(CxxrtlDivisionFuzz, Formats128BitUnsignedIntegers);
void Formats128BitSignedIntegers(chunk_t x0, chunk_t x1, chunk_t x2, chunk_t x3) {
// Compare output to BigInteger.
value<128> v;
v = v.blit<127, 64>(value<64>{x1, x0});
v = v.blit<63, 0>(value<64>{x3, x2});
std::ostringstream oss;
oss << value_formatted<128>(v, false, false, ' ', 0, 10, true, false, false);
auto actual = oss.str();
BigUnsigned u;
bool negative = v.is_neg();
if (negative)
v = v.neg();
u.bitShiftLeft(v.slice<127, 64>().val().get<uint64_t>(), 64);
u.bitOr(u, v.slice<63, 0>().val().get<uint64_t>());
std::string expected;
if (u.isZero()) {
expected = "0";
} else {
// Note that we never actually do division of negative numbers: our division
// routines are flooring, not truncating, so dividing by 10 repeatedly won't
// necessarily ever get to zero.
while (!u.isZero()) {
expected += '0' + (u % 10).toInt();
u /= 10;
}
if (negative) {
expected += '-';
}
std::reverse(expected.begin(), expected.end());
}
EXPECT_EQ(actual, expected);
}
FUZZ_TEST(CxxrtlDivisionFuzz, Formats128BitSignedIntegers);