mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Added opt_expr support for div/mod by power-of-two
This commit is contained in:
		
							parent
							
								
									766032c5f8
								
							
						
					
					
						commit
						11f7b8a2a1
					
				
					 2 changed files with 96 additions and 0 deletions
				
			
		| 
						 | 
					@ -1098,6 +1098,75 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!keepdc && cell->type.in("$div", "$mod"))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bool b_signed = cell->parameters["\\B_SIGNED"].as_bool();
 | 
				
			||||||
 | 
								SigSpec sig_b = assign_map(cell->getPort("\\B"));
 | 
				
			||||||
 | 
								SigSpec sig_y = assign_map(cell->getPort("\\Y"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (sig_b.is_fully_def() && sig_b.size() <= 32)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									int b_val = sig_b.as_int();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (b_val == 0)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										cover("opt.opt_expr.divmod_zero");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										log("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
 | 
				
			||||||
 | 
												cell->name.c_str(), module->name.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size())));
 | 
				
			||||||
 | 
										module->remove(cell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										did_something = true;
 | 
				
			||||||
 | 
										goto next_cell;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++)
 | 
				
			||||||
 | 
										if (b_val == (1 << i))
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											if (cell->type == "$div")
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												cover("opt.opt_expr.div_shift");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												log("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
 | 
				
			||||||
 | 
														b_val, cell->name.c_str(), module->name.c_str(), i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
 | 
				
			||||||
 | 
													new_b.pop_back();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												cell->type = "$shr";
 | 
				
			||||||
 | 
												cell->parameters["\\B_WIDTH"] = GetSize(new_b);
 | 
				
			||||||
 | 
												cell->parameters["\\B_SIGNED"] = false;
 | 
				
			||||||
 | 
												cell->setPort("\\B", new_b);
 | 
				
			||||||
 | 
												cell->check();
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											else
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												cover("opt.opt_expr.mod_mask");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												log("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
 | 
				
			||||||
 | 
														b_val, cell->name.c_str(), module->name.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if (b_signed)
 | 
				
			||||||
 | 
													new_b.push_back(State::S0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												cell->type = "$and";
 | 
				
			||||||
 | 
												cell->parameters["\\B_WIDTH"] = GetSize(new_b);
 | 
				
			||||||
 | 
												cell->setPort("\\B", new_b);
 | 
				
			||||||
 | 
												cell->check();
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											did_something = true;
 | 
				
			||||||
 | 
											goto next_cell;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	next_cell:;
 | 
						next_cell:;
 | 
				
			||||||
#undef ACTION_DO
 | 
					#undef ACTION_DO
 | 
				
			||||||
#undef ACTION_DO_Y
 | 
					#undef ACTION_DO_Y
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								tests/simple/constmuldivmod.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tests/simple/constmuldivmod.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					module constmuldivmod(input [7:0] A, input [2:0] mode, output reg [7:0] Y);
 | 
				
			||||||
 | 
						always @* begin
 | 
				
			||||||
 | 
							case (mode)
 | 
				
			||||||
 | 
								0: Y = A / 8'd0;
 | 
				
			||||||
 | 
								1: Y = A % 8'd0;
 | 
				
			||||||
 | 
								2: Y = A * 8'd0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								3: Y = A / 8'd1;
 | 
				
			||||||
 | 
								4: Y = A % 8'd1;
 | 
				
			||||||
 | 
								5: Y = A * 8'd1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								6: Y = A / 8'd2;
 | 
				
			||||||
 | 
								7: Y = A % 8'd2;
 | 
				
			||||||
 | 
								8: Y = A * 8'd2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								9: Y = A / 8'd4;
 | 
				
			||||||
 | 
								10: Y = A % 8'd4;
 | 
				
			||||||
 | 
								11: Y = A * 8'd4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								12: Y = A / 8'd8;
 | 
				
			||||||
 | 
								13: Y = A % 8'd8;
 | 
				
			||||||
 | 
								14: Y = A * 8'd8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								default: Y = 8'd16 * A;
 | 
				
			||||||
 | 
							endcase
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue