mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	opt_expr: Optimize bitwise logic ops with one fully const input
This commit is contained in:
		
							parent
							
								
									661fa5ff92
								
							
						
					
					
						commit
						c08242ba41
					
				
					 1 changed files with 81 additions and 0 deletions
				
			
		|  | @ -643,6 +643,87 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons | ||||||
| 			goto next_cell; | 			goto next_cell; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) | ||||||
|  | 		{ | ||||||
|  | 			RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); | ||||||
|  | 			RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); | ||||||
|  | 
 | ||||||
|  | 			bool a_fully_const = (sig_a.is_fully_const() && (!keepdc || !sig_a.is_fully_undef())); | ||||||
|  | 			bool b_fully_const = (sig_b.is_fully_const() && (!keepdc || !sig_b.is_fully_undef())); | ||||||
|  | 
 | ||||||
|  | 			if (a_fully_const != b_fully_const) | ||||||
|  | 			{ | ||||||
|  | 				cover("opt.opt_expr.bitwise_logic_one_const"); | ||||||
|  | 				log_debug("Replacing %s cell `%s' in module `%s' having one fully constant input\n", | ||||||
|  | 						log_id(cell->type), log_id(cell->name), log_id(module)); | ||||||
|  | 				RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); | ||||||
|  | 
 | ||||||
|  | 				int width = GetSize(cell->getPort(ID::Y)); | ||||||
|  | 
 | ||||||
|  | 				sig_a.extend_u0(width, cell->getParam(ID::A_SIGNED).as_bool()); | ||||||
|  | 				sig_b.extend_u0(width, cell->getParam(ID::B_SIGNED).as_bool()); | ||||||
|  | 
 | ||||||
|  | 				if (!a_fully_const) | ||||||
|  | 					std::swap(sig_a, sig_b); | ||||||
|  | 
 | ||||||
|  | 				RTLIL::SigSpec b_group_0, b_group_1, b_group_x; | ||||||
|  | 				RTLIL::SigSpec y_group_0, y_group_1, y_group_x; | ||||||
|  | 
 | ||||||
|  | 				for (int i = 0; i < width; i++) { | ||||||
|  | 					auto bit_a = sig_a[i].data; | ||||||
|  | 					if (bit_a == State::S0) b_group_0.append(sig_b[i]), y_group_0.append(sig_y[i]); | ||||||
|  | 					if (bit_a == State::S1) b_group_1.append(sig_b[i]), y_group_1.append(sig_y[i]); | ||||||
|  | 					if (bit_a == State::Sx) b_group_x.append(sig_b[i]), y_group_x.append(sig_y[i]); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (cell->type == ID($xnor)) { | ||||||
|  | 					std::swap(b_group_0, b_group_1); | ||||||
|  | 					std::swap(y_group_0, y_group_1); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				RTLIL::SigSpec y_new_0, y_new_1, y_new_x; | ||||||
|  | 
 | ||||||
|  | 				if (cell->type == ID($and)) { | ||||||
|  | 					if (!y_group_0.empty()) y_new_0 = Const(State::S0, GetSize(y_group_0)); | ||||||
|  | 					if (!y_group_1.empty()) y_new_1 = b_group_1; | ||||||
|  | 					if (!y_group_x.empty()) { | ||||||
|  | 						if (keepdc) | ||||||
|  | 							y_new_x = module->And(NEW_ID, Const(State::Sx, GetSize(y_group_x)), b_group_x); | ||||||
|  | 						else | ||||||
|  | 							y_new_x = Const(State::S0, GetSize(y_group_x)); | ||||||
|  | 					} | ||||||
|  | 				} else if (cell->type == ID($or)) { | ||||||
|  | 					if (!y_group_0.empty()) y_new_0 = b_group_0; | ||||||
|  | 					if (!y_group_1.empty()) y_new_1 = Const(State::S1, GetSize(y_group_1)); | ||||||
|  | 					if (!y_group_x.empty()) { | ||||||
|  | 						if (keepdc) | ||||||
|  | 							y_new_x = module->Or(NEW_ID, Const(State::Sx, GetSize(y_group_x)), b_group_x); | ||||||
|  | 						else | ||||||
|  | 							y_new_x = Const(State::S1, GetSize(y_group_x)); | ||||||
|  | 					} | ||||||
|  | 				} else if (cell->type.in(ID($xor), ID($xnor))) { | ||||||
|  | 					if (!y_group_0.empty()) y_new_0 = b_group_0; | ||||||
|  | 					if (!y_group_1.empty()) y_new_1 = module->Not(NEW_ID, b_group_1); | ||||||
|  | 					if (!y_group_x.empty()) { | ||||||
|  | 						if (keepdc) | ||||||
|  | 							y_new_x = module->Xor(NEW_ID, Const(State::Sx, GetSize(y_group_x)), b_group_x); | ||||||
|  | 						else // This should be fine even with keepdc, but opt_expr_xor.ys wants to keep the xor
 | ||||||
|  | 							y_new_x = Const(State::Sx, GetSize(y_group_x)); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					log_abort(); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				assign_map.add(y_group_0, y_new_0); module->connect(y_group_0, y_new_0); | ||||||
|  | 				assign_map.add(y_group_1, y_new_1); module->connect(y_group_1, y_new_1); | ||||||
|  | 				assign_map.add(y_group_x, y_new_x); module->connect(y_group_x, y_new_x); | ||||||
|  | 
 | ||||||
|  | 				module->remove(cell); | ||||||
|  | 				did_something = true; | ||||||
|  | 				goto next_cell; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if (do_fine) | 		if (do_fine) | ||||||
| 		{ | 		{ | ||||||
| 			if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor))) | 			if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor))) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue