diff options
| author | Clifford Wolf <clifford@clifford.at> | 2019-04-18 15:07:43 +0200 | 
|---|---|---|
| committer | Clifford Wolf <clifford@clifford.at> | 2019-04-18 15:13:47 +0200 | 
| commit | 88be1cbfa50238d77d9489218a8cca7275731da9 (patch) | |
| tree | 59bd0b1eb7dedc0880ec67bc6ff109dd27e7a171 /passes | |
| parent | ea8ac0aaad3a1f89ead8eb44b2fef5927f29a099 (diff) | |
| download | yosys-88be1cbfa50238d77d9489218a8cca7275731da9.tar.gz yosys-88be1cbfa50238d77d9489218a8cca7275731da9.tar.bz2 yosys-88be1cbfa50238d77d9489218a8cca7275731da9.zip | |
Improve proc full_case detection and handling, fixes #931
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'passes')
| -rw-r--r-- | passes/proc/proc_mux.cc | 50 | ||||
| -rw-r--r-- | passes/proc/proc_rmdead.cc | 18 | 
2 files changed, 63 insertions, 5 deletions
| diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index 1329c1fef..aac0b121c 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -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; diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index 7c334e661..4f40be446 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -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;  			}  		} | 
