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; | ||||
| 		} | ||||
| 
 | ||||
| 		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 (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