improved bitpattern (proc_mux) performance

This commit is contained in:
Clifford Wolf 2014-12-31 13:15:35 +01:00
parent b9e412423a
commit ba48b6b1e6
1 changed files with 43 additions and 22 deletions

View File

@ -28,14 +28,34 @@ YOSYS_NAMESPACE_BEGIN
struct BitPatternPool struct BitPatternPool
{ {
int width; int width;
typedef std::vector<RTLIL::State> bits_t; struct bits_t {
std::vector<RTLIL::State> bitdata;
unsigned int cached_hash;
bits_t(int width = 0) : bitdata(width), cached_hash(0) { }
RTLIL::State &operator[](int index) {
return bitdata[index];
}
const RTLIL::State &operator[](int index) const {
return bitdata[index];
}
bool operator==(const bits_t &other) const {
if (hash() != other.hash())
return false;
return bitdata == other.bitdata;
}
unsigned int hash() const {
if (!cached_hash)
((bits_t*)this)->cached_hash = hash_ops<std::vector<RTLIL::State>>::hash(bitdata);
return cached_hash;
}
};
pool<bits_t> database; pool<bits_t> database;
BitPatternPool(RTLIL::SigSpec sig) BitPatternPool(RTLIL::SigSpec sig)
{ {
width = sig.size(); width = sig.size();
if (width > 0) { if (width > 0) {
std::vector<RTLIL::State> pattern(width); bits_t pattern(width);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
if (sig[i].wire == NULL && sig[i].data <= RTLIL::State::S1) if (sig[i].wire == NULL && sig[i].data <= RTLIL::State::S1)
pattern[i] = sig[i].data; pattern[i] = sig[i].data;
@ -50,7 +70,7 @@ struct BitPatternPool
{ {
this->width = width; this->width = width;
if (width > 0) { if (width > 0) {
std::vector<RTLIL::State> pattern(width); bits_t pattern(width);
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
pattern[i] = RTLIL::State::Sa; pattern[i] = RTLIL::State::Sa;
database.insert(pattern); database.insert(pattern);
@ -59,8 +79,9 @@ struct BitPatternPool
bits_t sig2bits(RTLIL::SigSpec sig) bits_t sig2bits(RTLIL::SigSpec sig)
{ {
bits_t bits = sig.as_const().bits; bits_t bits;
for (auto &b : bits) bits.bitdata = sig.as_const().bits;
for (auto &b : bits.bitdata)
if (b > RTLIL::State::S1) if (b > RTLIL::State::S1)
b = RTLIL::State::Sa; b = RTLIL::State::Sa;
return bits; return bits;
@ -68,8 +89,8 @@ struct BitPatternPool
bool match(bits_t a, bits_t b) bool match(bits_t a, bits_t b)
{ {
log_assert(int(a.size()) == width); log_assert(int(a.bitdata.size()) == width);
log_assert(int(b.size()) == width); log_assert(int(b.bitdata.size()) == width);
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
if (a[i] <= RTLIL::State::S1 && b[i] <= RTLIL::State::S1 && a[i] != b[i]) if (a[i] <= RTLIL::State::S1 && b[i] <= RTLIL::State::S1 && a[i] != b[i])
return false; return false;
@ -103,21 +124,21 @@ struct BitPatternPool
{ {
bool status = false; bool status = false;
bits_t bits = sig2bits(sig); bits_t bits = sig2bits(sig);
std::vector<bits_t> pattern_list; for (auto it = database.begin(); it != database.end();)
for (auto &it : database) if (match(*it, bits)) {
if (match(it, bits))
pattern_list.push_back(it);
for (auto pattern : pattern_list) {
database.erase(pattern);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
if (pattern[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa) if ((*it)[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa)
continue; continue;
bits_t new_pattern = pattern; bits_t new_pattern;
new_pattern.bitdata = it->bitdata;
new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1; new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1;
database.insert(new_pattern); database.insert(new_pattern);
} }
it = database.erase(it);
status = true; status = true;
} continue;
} else
++it;
return status; return status;
} }