Merge pull request #942 from YosysHQ/clifford/fix931

Improve proc full_case detection and handling
This commit is contained in:
Clifford Wolf 2019-04-20 10:05:35 +02:00 committed by GitHub
commit e3687f6f4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 5 deletions

View File

@ -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;

View File

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