mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 19:52:31 +00:00 
			
		
		
		
	Add peepopt_muldiv, fixes #930
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
		
							parent
							
								
									4306bebe58
								
							
						
					
					
						commit
						b515fd2d25
					
				
					 6 changed files with 86 additions and 1 deletions
				
			
		|  | @ -529,6 +529,42 @@ struct WreducePass : public Pass { | ||||||
| 						module->connect(sig, Const(0, GetSize(sig))); | 						module->connect(sig, Const(0, GetSize(sig))); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				if (c->type.in("$div", "$mod", "$pow")) | ||||||
|  | 				{ | ||||||
|  | 					SigSpec A = c->getPort("\\A"); | ||||||
|  | 					int original_a_width = GetSize(A); | ||||||
|  | 					if (c->getParam("\\A_SIGNED").as_bool()) { | ||||||
|  | 						while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0) | ||||||
|  | 							A.remove(GetSize(A)-1, 1); | ||||||
|  | 					} else { | ||||||
|  | 						while (GetSize(A) > 0 && A[GetSize(A)-1] == State::S0) | ||||||
|  | 							A.remove(GetSize(A)-1, 1); | ||||||
|  | 					} | ||||||
|  | 					if (original_a_width != GetSize(A)) { | ||||||
|  | 						log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n", | ||||||
|  | 								original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type)); | ||||||
|  | 						c->setPort("\\A", A); | ||||||
|  | 						c->setParam("\\A_WIDTH", GetSize(A)); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					SigSpec B = c->getPort("\\B"); | ||||||
|  | 					int original_b_width = GetSize(B); | ||||||
|  | 					if (c->getParam("\\B_SIGNED").as_bool()) { | ||||||
|  | 						while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0) | ||||||
|  | 							B.remove(GetSize(B)-1, 1); | ||||||
|  | 					} else { | ||||||
|  | 						while (GetSize(B) > 0 && B[GetSize(B)-1] == State::S0) | ||||||
|  | 							B.remove(GetSize(B)-1, 1); | ||||||
|  | 					} | ||||||
|  | 					if (original_b_width != GetSize(B)) { | ||||||
|  | 						log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n", | ||||||
|  | 								original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type)); | ||||||
|  | 						c->setPort("\\B", B); | ||||||
|  | 						c->setParam("\\B_WIDTH", GetSize(B)); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
| 				if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) { | 				if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) { | ||||||
| 					IdString memid = c->getParam("\\MEMID").decode_string(); | 					IdString memid = c->getParam("\\MEMID").decode_string(); | ||||||
| 					RTLIL::Memory *mem = module->memories.at(memid); | 					RTLIL::Memory *mem = module->memories.at(memid); | ||||||
|  |  | ||||||
|  | @ -16,7 +16,8 @@ passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h | ||||||
| EXTRA_OBJS += passes/pmgen/peepopt_pm.h | EXTRA_OBJS += passes/pmgen/peepopt_pm.h | ||||||
| .SECONDARY: passes/pmgen/peepopt_pm.h | .SECONDARY: passes/pmgen/peepopt_pm.h | ||||||
| 
 | 
 | ||||||
| PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg | PEEPOPT_PATTERN  = passes/pmgen/peepopt_shiftmul.pmg | ||||||
|  | PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg | ||||||
| 
 | 
 | ||||||
| passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) | passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) | ||||||
| 	$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^) | 	$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^) | ||||||
|  |  | ||||||
|  | @ -59,6 +59,7 @@ struct PeepoptPass : public Pass { | ||||||
| 				did_something = false; | 				did_something = false; | ||||||
| 				peepopt_pm pm(module, module->selected_cells()); | 				peepopt_pm pm(module, module->selected_cells()); | ||||||
| 				pm.run_shiftmul(); | 				pm.run_shiftmul(); | ||||||
|  | 				pm.run_muldiv(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								passes/pmgen/peepopt_muldiv.pmg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								passes/pmgen/peepopt_muldiv.pmg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | pattern muldiv | ||||||
|  | 
 | ||||||
|  | state <SigSpec> t x y | ||||||
|  | 
 | ||||||
|  | match mul | ||||||
|  | 	select mul->type == $mul | ||||||
|  | 	select GetSize(port(mul, \A)) + GetSize(port(mul, \B)) <= GetSize(port(mul, \Y)) | ||||||
|  | endmatch | ||||||
|  | 
 | ||||||
|  | code t x y | ||||||
|  | 	t = port(mul, \Y); | ||||||
|  | 	x = port(mul, \A); | ||||||
|  | 	y = port(mul, \B); | ||||||
|  | 	branch; | ||||||
|  | 	std::swap(x, y); | ||||||
|  | endcode | ||||||
|  | 
 | ||||||
|  | match div | ||||||
|  | 	select div->type.in($div) | ||||||
|  | 	index <SigSpec> port(div, \A) === t | ||||||
|  | 	index <SigSpec> port(div, \B) === x | ||||||
|  | endmatch | ||||||
|  | 
 | ||||||
|  | code | ||||||
|  | 	SigSpec div_y = port(div, \Y); | ||||||
|  | 	SigSpec val_y = y; | ||||||
|  | 
 | ||||||
|  | 	if (GetSize(div_y) != GetSize(val_y)) | ||||||
|  | 		val_y.extend_u0(GetSize(div_y), param(div, \A_SIGNED).as_bool()); | ||||||
|  | 
 | ||||||
|  | 	did_something = true; | ||||||
|  | 	log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); | ||||||
|  | 	module->connect(div_y, val_y); | ||||||
|  | 	autoremove(div); | ||||||
|  | 	reject; | ||||||
|  | endcode | ||||||
|  | @ -335,6 +335,8 @@ with open(outfile, "w") as f: | ||||||
|         print("    blacklist_dirty = false;", file=f) |         print("    blacklist_dirty = false;", file=f) | ||||||
|         for index in range(len(blocks)): |         for index in range(len(blocks)): | ||||||
|             block = blocks[index] |             block = blocks[index] | ||||||
|  |             if block["pattern"] != current_pattern: | ||||||
|  |                 continue | ||||||
|             if block["type"] == "match": |             if block["type"] == "match": | ||||||
|                 print("    if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f) |                 print("    if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f) | ||||||
|                 print("      rollback = {};".format(index+1), file=f) |                 print("      rollback = {};".format(index+1), file=f) | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								tests/simple/peepopt.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/simple/peepopt.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | module peepopt_shiftmul_0 #(parameter N=3, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output [W-1:0] o); | ||||||
|  | assign o = i[s*W+:W]; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module peepopt_muldiv_0(input [1:0] i, output [1:0] o); | ||||||
|  | wire [3:0] t; | ||||||
|  | assign t = i * 3; | ||||||
|  | assign o = t / 3; | ||||||
|  | endmodule | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue