mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	muldiv_c peepopt pass
This commit is contained in:
		
							parent
							
								
									8afa827b94
								
							
						
					
					
						commit
						98db6bd2d8
					
				
					 3 changed files with 75 additions and 0 deletions
				
			
		|  | @ -57,6 +57,7 @@ PEEPOPT_PATTERN  = passes/pmgen/peepopt_shiftmul_right.pmg | |||
| PEEPOPT_PATTERN += passes/pmgen/peepopt_shiftmul_left.pmg | ||||
| PEEPOPT_PATTERN += passes/pmgen/peepopt_shiftadd.pmg | ||||
| PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg | ||||
| PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv_c.pmg | ||||
| PEEPOPT_PATTERN += passes/pmgen/peepopt_muxadd.pmg | ||||
| 
 | ||||
| passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) | ||||
|  |  | |||
|  | @ -46,6 +46,8 @@ struct PeepoptPass : public Pass { | |||
| 		log("\n"); | ||||
| 		log("   * muldiv - Replace (A*B)/B with A\n"); | ||||
| 		log("\n"); | ||||
| 		log("   * muldiv_c - Replace (A*B)/C with A*(B/C) when C is a const divisible by B.\n"); | ||||
| 		log("\n"); | ||||
| 		log("   * shiftmul - Replace A>>(B*C) with A'>>(B<<K) where C and K are constants\n"); | ||||
| 		log("                and A' is derived from A by appropriately inserting padding\n"); | ||||
| 		log("                into the signal. (right variant)\n"); | ||||
|  | @ -92,6 +94,7 @@ struct PeepoptPass : public Pass { | |||
| 				pm.run_shiftmul_right(); | ||||
| 				pm.run_shiftmul_left(); | ||||
| 				pm.run_muldiv(); | ||||
| 				pm.run_muldiv_c(); | ||||
| 				pm.run_muxadd(); | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
							
								
								
									
										71
									
								
								passes/pmgen/peepopt_muldiv_c.pmg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								passes/pmgen/peepopt_muldiv_c.pmg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | |||
| pattern muldiv_c | ||||
| // | ||||
| // Transforms mul->div into div->mul when b and c are divisible constants: | ||||
| // y = (a * b_const) / c_const   ===>   a * (b_const / c_const) | ||||
| // | ||||
| 
 | ||||
| state <SigSpec> a b_const mul_y | ||||
| 
 | ||||
| match mul | ||||
| 	// Select multiplier | ||||
| 	select mul->type == $mul | ||||
| endmatch | ||||
| 
 | ||||
| code a b_const mul_y | ||||
| 	printf("CODING MUL!!!\n"); | ||||
| 
 | ||||
| 	// Get multiplier signals | ||||
| 	a = port(mul, \A); | ||||
| 	b_const = port(mul, \B); | ||||
| 	mul_y = port(mul, \Y); | ||||
| 
 | ||||
| 	// Fanout of each multiplier Y bit should be 1 (no bit-split) | ||||
| 	for (auto bit : mul_y) | ||||
| 		if (nusers(bit) != 2) | ||||
| 			reject; | ||||
| 
 | ||||
| 	// A and B can be interchanged | ||||
| 	branch; | ||||
| 	std::swap(a, b_const); | ||||
| endcode | ||||
| 
 | ||||
| match div | ||||
| 	// Select div of form (a * b_const) / c_const | ||||
| 	select div->type == $div | ||||
| 	index <SigSpec> port(div, \A) === port(mul, \Y) | ||||
| 
 | ||||
| 	// Check that b_const and c_const is constant | ||||
| 	filter port(mul, \B).is_fully_const() | ||||
| 	filter port(div, \B).is_fully_const() | ||||
| endmatch | ||||
| 
 | ||||
| code | ||||
| 	printf("CODING DIV!!!\n"); | ||||
| 
 | ||||
| 	// Get div signals | ||||
| 	SigSpec c_const = port(div, \B); | ||||
| 	SigSpec div_y = port(div, \Y); | ||||
| 
 | ||||
| 	// Get properties and values of b_const and c_const | ||||
| 	int b_const_width = mul->getParam(ID::B_WIDTH).as_int(); | ||||
| 	bool b_const_signed = mul->getParam(ID::B_SIGNED).as_bool(); | ||||
| 	bool c_const_signed = div->getParam(ID::B_SIGNED).as_bool(); | ||||
| 	int b_const_int = b_const.as_int(b_const_signed); | ||||
| 	int c_const_int = c_const.as_int(c_const_signed); | ||||
| 
 | ||||
| 	// Check that b is divisible by c | ||||
| 	if (b_const_int % c_const_int != 0) | ||||
| 		reject; | ||||
| 
 | ||||
| 	// Rewire to only keep multiplier | ||||
| 	mul->setPort(\B, Const(b_const_int / c_const_int, b_const_width)); | ||||
| 	mul->setPort(\Y, div_y); | ||||
| 
 | ||||
| 	// Remove divider | ||||
| 	autoremove(div); | ||||
| 
 | ||||
| 	// Log, fixup, accept | ||||
| 	log("muldiv_const pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); | ||||
| 	mul->fixup_parameters(); | ||||
| 	accept; | ||||
| endcode | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue