mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	cxxrtl: Fix sdivmod
x = x.neg(); results in the subsequent x.is_neg() always being false. Ditto for the dividend.is_neg() != divisor.is_neg() test.
This commit is contained in:
		
							parent
							
								
									0a854cf4ce
								
							
						
					
					
						commit
						d07a55a852
					
				
					 2 changed files with 109 additions and 4 deletions
				
			
		|  | @ -625,11 +625,11 @@ struct value : public expr_base<value<Bits>> { | ||||||
| 		value<Bits + 1> remainder; | 		value<Bits + 1> remainder; | ||||||
| 		value<Bits + 1> dividend = sext<Bits + 1>(); | 		value<Bits + 1> dividend = sext<Bits + 1>(); | ||||||
| 		value<Bits + 1> divisor = other.template sext<Bits + 1>(); | 		value<Bits + 1> divisor = other.template sext<Bits + 1>(); | ||||||
| 		if (dividend.is_neg()) dividend = dividend.neg(); | 		if (is_neg()) dividend = dividend.neg(); | ||||||
| 		if (divisor.is_neg()) divisor = divisor.neg(); | 		if (other.is_neg()) divisor = divisor.neg(); | ||||||
| 		std::tie(quotient, remainder) = dividend.udivmod(divisor); | 		std::tie(quotient, remainder) = dividend.udivmod(divisor); | ||||||
| 		if (dividend.is_neg() != divisor.is_neg()) quotient = quotient.neg(); | 		if (is_neg() != other.is_neg()) quotient = quotient.neg(); | ||||||
| 		if (dividend.is_neg()) remainder = remainder.neg(); | 		if (is_neg()) remainder = remainder.neg(); | ||||||
| 		return {quotient.template trunc<Bits>(), remainder.template trunc<Bits>()}; | 		return {quotient.template trunc<Bits>(), remainder.template trunc<Bits>()}; | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -25,6 +25,11 @@ T rand_int(T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T> | ||||||
| 	return dist(generator); | 	return dist(generator); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int64_t sext(size_t bits, uint64_t value) | ||||||
|  | { | ||||||
|  | 	return (int64_t)(value << (64 - bits)) >> (64 - bits); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct BinaryOperationBase | struct BinaryOperationBase | ||||||
| { | { | ||||||
| 	void tweak_input(uint64_t &a, uint64_t &b) {} | 	void tweak_input(uint64_t &a, uint64_t &b) {} | ||||||
|  | @ -246,6 +251,106 @@ struct CtlzTest | ||||||
| 	} | 	} | ||||||
| } ctlz; | } 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() | int main() | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue