mirror of https://github.com/YosysHQ/yosys.git
bitpattern: add analysis effort limit, use in proc_rmdead
This commit is contained in:
parent
a966d06524
commit
a3740057e3
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
enum TakeResult {
|
||||
FALSE,
|
||||
TRUE,
|
||||
TOO_BIG
|
||||
};
|
||||
|
||||
/**
|
||||
* This file implements BitPatternPool for efficiently storing and querying
|
||||
* sets of fixed-width 2-valued logic constants compressed as "bit patterns".
|
||||
|
|
@ -39,6 +45,7 @@ YOSYS_NAMESPACE_BEGIN
|
|||
*/
|
||||
struct BitPatternPool
|
||||
{
|
||||
size_t limit = SIZE_MAX;
|
||||
int width;
|
||||
struct bits_t {
|
||||
std::vector<RTLIL::State> bitdata;
|
||||
|
|
@ -167,9 +174,10 @@ struct BitPatternPool
|
|||
* Taking 011 out of pool({01a}) -> pool({010}), returns true.
|
||||
* Taking 011 out of pool({010}) does nothing, returns false.
|
||||
*/
|
||||
bool take(RTLIL::SigSpec sig)
|
||||
[[nodiscard]]
|
||||
TakeResult take(RTLIL::SigSpec sig)
|
||||
{
|
||||
bool status = false;
|
||||
TakeResult status = FALSE;
|
||||
bits_t bits = sig2bits(sig);
|
||||
for (auto it = database.begin(); it != database.end();)
|
||||
if (match(*it, bits)) {
|
||||
|
|
@ -180,12 +188,15 @@ struct BitPatternPool
|
|||
new_pattern.bitdata = it->bitdata;
|
||||
new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
database.insert(new_pattern);
|
||||
if (database.size() > limit)
|
||||
return TOO_BIG;
|
||||
}
|
||||
it = database.erase(it);
|
||||
status = true;
|
||||
status = TRUE;
|
||||
continue;
|
||||
} else
|
||||
++it;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
|
|||
if (!pat.is_fully_const())
|
||||
extra_group_for_next_case = true;
|
||||
else if (!ifxmode)
|
||||
pool.take(pat);
|
||||
log_assert(pool.take(pat) != TakeResult::TOO_BIG);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,12 +54,14 @@ struct FullyDefinedPool
|
|||
: max_patterns{signal.size() >= 32 ? 0ul : 1ul << signal.size()}
|
||||
{}
|
||||
|
||||
bool take(RTLIL::SigSpec sig)
|
||||
// Yes, we never return TOO_BIG, since FullyDefinedPool::max_patterns
|
||||
// and BitPatternPool::limits are different concepts
|
||||
TakeResult take(RTLIL::SigSpec sig)
|
||||
{
|
||||
if (default_reached || patterns.count(sig))
|
||||
return false;
|
||||
return FALSE;
|
||||
patterns.insert(sig);
|
||||
return true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void take_all()
|
||||
|
|
@ -81,20 +83,24 @@ struct FullyDefinedPool
|
|||
void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter);
|
||||
|
||||
template <class Pool>
|
||||
static void proc_rmdead_impl(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
|
||||
static void proc_rmdead_impl(Pool& pool, RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
|
||||
{
|
||||
Pool pool(sw->signal);
|
||||
|
||||
bool is_too_big = false;
|
||||
for (size_t i = 0; i < sw->cases.size(); i++)
|
||||
{
|
||||
bool is_default = GetSize(sw->cases[i]->compare) == 0 && (!pool.empty() || GetSize(sw->signal) == 0);
|
||||
|
||||
for (size_t j = 0; j < sw->cases[i]->compare.size(); j++) {
|
||||
RTLIL::SigSpec sig = sw->cases[i]->compare[j];
|
||||
if (!sig.is_fully_const())
|
||||
continue;
|
||||
if (!pool.take(sig))
|
||||
sw->cases[i]->compare.erase(sw->cases[i]->compare.begin() + (j--));
|
||||
if (!is_too_big) {
|
||||
for (size_t j = 0; j < sw->cases[i]->compare.size(); j++) {
|
||||
RTLIL::SigSpec sig = sw->cases[i]->compare[j];
|
||||
if (!sig.is_fully_const())
|
||||
continue;
|
||||
auto res = pool.take(sig);
|
||||
if (res == TakeResult::TOO_BIG) {
|
||||
is_too_big = true; // Skip the rest of the analysis
|
||||
}
|
||||
if (res == TakeResult::FALSE)
|
||||
sw->cases[i]->compare.erase(sw->cases[i]->compare.begin() + (j--));
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_default) {
|
||||
|
|
@ -104,8 +110,6 @@ static void proc_rmdead_impl(RTLIL::SwitchRule *sw, int &counter, int &full_case
|
|||
counter++;
|
||||
continue;
|
||||
}
|
||||
// if (pool.empty())
|
||||
// sw->cases[i]->compare.clear();
|
||||
}
|
||||
|
||||
for (auto switch_it : sw->cases[i]->switches)
|
||||
|
|
@ -123,10 +127,14 @@ static void proc_rmdead_impl(RTLIL::SwitchRule *sw, int &counter, int &full_case
|
|||
|
||||
void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
|
||||
{
|
||||
if (can_use_fully_defined_pool(sw))
|
||||
proc_rmdead_impl<FullyDefinedPool>(sw, counter, full_case_counter);
|
||||
else
|
||||
proc_rmdead_impl<BitPatternPool>(sw, counter, full_case_counter);
|
||||
if (can_use_fully_defined_pool(sw)) {
|
||||
auto pool = FullyDefinedPool(sw->signal);
|
||||
proc_rmdead_impl<FullyDefinedPool>(pool, sw, counter, full_case_counter);
|
||||
} else {
|
||||
auto pool = BitPatternPool(sw->signal);
|
||||
pool.limit = 100000;
|
||||
proc_rmdead_impl<BitPatternPool>(pool, sw, counter, full_case_counter);
|
||||
}
|
||||
}
|
||||
|
||||
struct ProcRmdeadPass : public Pass {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ TEST(BitpatternTest, has)
|
|||
// 01a is not covered by 011
|
||||
EXPECT_FALSE(BitPatternPool(_011).has_all(_01a));
|
||||
EXPECT_FALSE(BitPatternPool(_111).has_all(_01a));
|
||||
// test mutating and analysis effort limits
|
||||
auto pool = BitPatternPool(3);
|
||||
pool.limit = 4;
|
||||
EXPECT_EQ(pool.take(_111), TakeResult::TRUE);
|
||||
EXPECT_EQ(pool.take(_111), TakeResult::FALSE);
|
||||
EXPECT_EQ(pool.take(_01a), TakeResult::TOO_BIG);
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
|||
Loading…
Reference in New Issue