mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +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> 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>()}; | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
|  | @ -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) {} | ||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue