mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +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)));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				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")) {
 | 
			
		||||
					IdString memid = c->getParam("\\MEMID").decode_string();
 | 
			
		||||
					RTLIL::Memory *mem = module->memories.at(memid);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ EXTRA_OBJS += passes/pmgen/peepopt_pm.h
 | 
			
		|||
.SECONDARY: passes/pmgen/peepopt_pm.h
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
	$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,6 +59,7 @@ struct PeepoptPass : public Pass {
 | 
			
		|||
				did_something = false;
 | 
			
		||||
				peepopt_pm pm(module, module->selected_cells());
 | 
			
		||||
				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)
 | 
			
		||||
        for index in range(len(blocks)):
 | 
			
		||||
            block = blocks[index]
 | 
			
		||||
            if block["pattern"] != current_pattern:
 | 
			
		||||
                continue
 | 
			
		||||
            if block["type"] == "match":
 | 
			
		||||
                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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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