mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge pull request #942 from YosysHQ/clifford/fix931
Improve proc full_case detection and handling
This commit is contained in:
		
						commit
						e3687f6f4e
					
				
					 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