mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #942 from YosysHQ/clifford/fix931
Improve proc full_case detection and handling
This commit is contained in:
commit
e3687f6f4e
|
@ -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…
Reference in New Issue