mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42: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 | struct SnippetSwCache | ||||||
| { | { | ||||||
|  | 	dict<RTLIL::SwitchRule*, pool<RTLIL::SigBit>, hash_ptr_ops> full_case_bits_cache; | ||||||
| 	dict<RTLIL::SwitchRule*, pool<int>, hash_ptr_ops> cache; | 	dict<RTLIL::SwitchRule*, pool<int>, hash_ptr_ops> cache; | ||||||
| 	const SigSnippets *snippets; | 	const SigSnippets *snippets; | ||||||
| 	int current_snippet; | 	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(); | 	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::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) | 		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
 | 		// evaluate in reverse order to give the first entry the top priority
 | ||||||
| 		RTLIL::SigSpec initial_val = result; | 		RTLIL::SigSpec initial_val = result; | ||||||
| 		RTLIL::Cell *last_mux_cell = NULL; | 		RTLIL::Cell *last_mux_cell = NULL; | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | 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); | 	BitPatternPool pool(sw->signal); | ||||||
| 
 | 
 | ||||||
|  | @ -56,11 +56,16 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto switch_it : sw->cases[i]->switches) | 		for (auto switch_it : sw->cases[i]->switches) | ||||||
| 			proc_rmdead(switch_it, counter); | 			proc_rmdead(switch_it, counter, full_case_counter); | ||||||
| 
 | 
 | ||||||
| 		if (is_default) | 		if (is_default) | ||||||
| 			pool.take_all(); | 			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 { | struct ProcRmdeadPass : public Pass { | ||||||
|  | @ -87,12 +92,15 @@ struct ProcRmdeadPass : public Pass { | ||||||
| 			for (auto &proc_it : mod->processes) { | 			for (auto &proc_it : mod->processes) { | ||||||
| 				if (!design->selected(mod, proc_it.second)) | 				if (!design->selected(mod, proc_it.second)) | ||||||
| 					continue; | 					continue; | ||||||
| 				int counter = 0; | 				int counter = 0, full_case_counter = 0; | ||||||
| 				for (auto switch_it : proc_it.second->root_case.switches) | 				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) | 				if (counter > 0) | ||||||
| 					log("Removed %d dead cases from process %s in module %s.\n", counter, | 					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; | 				total_counter += counter; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue