mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +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:
		
							parent
							
								
									2ae551c0af
								
							
						
					
					
						commit
						3571bf2c2d
					
				
					 4 changed files with 55 additions and 20 deletions
				
			
		|  | @ -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; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -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 ? '-' : '+'; | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue