mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-29 18:52:30 +00:00 
			
		
		
		
	Improve proc full_case detection and handling, fixes #931
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
		
							parent
							
								
									ea8ac0aaad
								
							
						
					
					
						commit
						88be1cbfa5
					
				
					 2 changed files with 63 additions and 5 deletions
				
			
		|  | @ -108,6 +108,7 @@ struct SigSnippets | |||
| 
 | ||||
| struct SnippetSwCache | ||||
| { | ||||
| 	dict<RTLIL::SwitchRule*, pool<RTLIL::SigBit>, hash_ptr_ops> full_case_bits_cache; | ||||
| 	dict<RTLIL::SwitchRule*, pool<int>, hash_ptr_ops> cache; | ||||
| 	const SigSnippets *snippets; | ||||
| 	int current_snippet; | ||||
|  | @ -268,6 +269,49 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve | |||
| 	last_mux_cell->parameters["\\S_WIDTH"] = last_mux_cell->getPort("\\S").size(); | ||||
| } | ||||
| 
 | ||||
| const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRule *sw) | ||||
| { | ||||
| 	if (!swcache.full_case_bits_cache.count(sw)) | ||||
| 	{ | ||||
| 		pool<SigBit> bits; | ||||
| 
 | ||||
| 		if (sw->get_bool_attribute("\\full_case")) | ||||
| 		{ | ||||
| 			bool first_case = true; | ||||
| 
 | ||||
| 			for (auto cs : sw->cases) | ||||
| 			{ | ||||
| 				pool<SigBit> case_bits; | ||||
| 
 | ||||
| 				for (auto it : cs->actions) { | ||||
| 					for (auto bit : it.first) | ||||
| 						case_bits.insert(bit); | ||||
| 				} | ||||
| 
 | ||||
| 				for (auto it : cs->switches) { | ||||
| 					for (auto bit : get_full_case_bits(swcache, it)) | ||||
| 						case_bits.insert(bit); | ||||
| 				} | ||||
| 
 | ||||
| 				if (first_case) { | ||||
| 					first_case = false; | ||||
| 					bits = case_bits; | ||||
| 				} else { | ||||
| 					pool<SigBit> new_bits; | ||||
| 					for (auto bit : bits) | ||||
| 						if (case_bits.count(bit)) | ||||
| 							new_bits.insert(bit); | ||||
| 					bits.swap(new_bits); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		bits.swap(swcache.full_case_bits_cache[sw]); | ||||
| 	} | ||||
| 
 | ||||
| 	return swcache.full_case_bits_cache.at(sw); | ||||
| } | ||||
| 
 | ||||
| RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool, hash_ptr_ops> &swpara, | ||||
| 		RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval, bool ifxmode) | ||||
| { | ||||
|  | @ -337,6 +381,12 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// mask default bits that are irrelevant because the output is driven by a full case
 | ||||
| 		const pool<SigBit> &full_case_bits = get_full_case_bits(swcache, sw); | ||||
| 		for (int i = 0; i < GetSize(sig); i++) | ||||
| 			if (full_case_bits.count(sig[i])) | ||||
| 				result[i] = State::Sx; | ||||
| 
 | ||||
| 		// evaluate in reverse order to give the first entry the top priority
 | ||||
| 		RTLIL::SigSpec initial_val = result; | ||||
| 		RTLIL::Cell *last_mux_cell = NULL; | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ | |||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| void proc_rmdead(RTLIL::SwitchRule *sw, int &counter) | ||||
| void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter) | ||||
| { | ||||
| 	BitPatternPool pool(sw->signal); | ||||
| 
 | ||||
|  | @ -56,11 +56,16 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter) | |||
| 		} | ||||
| 
 | ||||
| 		for (auto switch_it : sw->cases[i]->switches) | ||||
| 			proc_rmdead(switch_it, counter); | ||||
| 			proc_rmdead(switch_it, counter, full_case_counter); | ||||
| 
 | ||||
| 		if (is_default) | ||||
| 			pool.take_all(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (pool.empty() && !sw->get_bool_attribute("\\full_case")) { | ||||
| 		sw->set_bool_attribute("\\full_case"); | ||||
| 		full_case_counter++; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct ProcRmdeadPass : public Pass { | ||||
|  | @ -87,12 +92,15 @@ struct ProcRmdeadPass : public Pass { | |||
| 			for (auto &proc_it : mod->processes) { | ||||
| 				if (!design->selected(mod, proc_it.second)) | ||||
| 					continue; | ||||
| 				int counter = 0; | ||||
| 				int counter = 0, full_case_counter = 0; | ||||
| 				for (auto switch_it : proc_it.second->root_case.switches) | ||||
| 					proc_rmdead(switch_it, counter); | ||||
| 					proc_rmdead(switch_it, counter, full_case_counter); | ||||
| 				if (counter > 0) | ||||
| 					log("Removed %d dead cases from process %s in module %s.\n", counter, | ||||
| 							proc_it.first.c_str(), log_id(mod)); | ||||
| 							log_id(proc_it.first), log_id(mod)); | ||||
| 				if (full_case_counter > 0) | ||||
| 					log("Marked %d switch rules as full_case in process %s in module %s.\n", | ||||
| 							full_case_counter, log_id(proc_it.first), log_id(mod)); | ||||
| 				total_counter += counter; | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue