mirror of https://github.com/YosysHQ/yosys.git
162 lines
3.8 KiB
C++
162 lines
3.8 KiB
C++
/*
|
|
* yosys -- Yosys Open SYnthesis Suite
|
|
*
|
|
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#ifndef BITPATTERN_H
|
|
#define BITPATTERN_H
|
|
|
|
#include "kernel/log.h"
|
|
#include "kernel/rtlil.h"
|
|
|
|
YOSYS_NAMESPACE_BEGIN
|
|
|
|
struct BitPatternPool
|
|
{
|
|
int width;
|
|
struct bits_t {
|
|
std::vector<RTLIL::State> bitdata;
|
|
mutable 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)
|
|
cached_hash = hash_ops<std::vector<RTLIL::State>>::hash(bitdata);
|
|
return cached_hash;
|
|
}
|
|
};
|
|
pool<bits_t> database;
|
|
|
|
BitPatternPool(RTLIL::SigSpec sig)
|
|
{
|
|
width = sig.size();
|
|
if (width > 0) {
|
|
bits_t pattern(width);
|
|
for (int i = 0; i < width; i++) {
|
|
if (sig[i].wire == NULL && sig[i].data <= RTLIL::State::S1)
|
|
pattern[i] = sig[i].data;
|
|
else
|
|
pattern[i] = RTLIL::State::Sa;
|
|
}
|
|
database.insert(pattern);
|
|
}
|
|
}
|
|
|
|
BitPatternPool(int width)
|
|
{
|
|
this->width = width;
|
|
if (width > 0) {
|
|
bits_t pattern(width);
|
|
for (int i = 0; i < width; i++)
|
|
pattern[i] = RTLIL::State::Sa;
|
|
database.insert(pattern);
|
|
}
|
|
}
|
|
|
|
bits_t sig2bits(RTLIL::SigSpec sig)
|
|
{
|
|
bits_t bits;
|
|
bits.bitdata = sig.as_const().bits();
|
|
for (auto &b : bits.bitdata)
|
|
if (b > RTLIL::State::S1)
|
|
b = RTLIL::State::Sa;
|
|
return bits;
|
|
}
|
|
|
|
bool match(bits_t a, bits_t b)
|
|
{
|
|
log_assert(int(a.bitdata.size()) == width);
|
|
log_assert(int(b.bitdata.size()) == width);
|
|
for (int i = 0; i < width; i++)
|
|
if (a[i] <= RTLIL::State::S1 && b[i] <= RTLIL::State::S1 && a[i] != b[i])
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool has_any(RTLIL::SigSpec sig)
|
|
{
|
|
bits_t bits = sig2bits(sig);
|
|
for (auto &it : database)
|
|
if (match(it, bits))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool has_all(RTLIL::SigSpec sig)
|
|
{
|
|
bits_t bits = sig2bits(sig);
|
|
for (auto &it : database)
|
|
if (match(it, bits)) {
|
|
for (int i = 0; i < width; i++)
|
|
if (bits[i] > RTLIL::State::S1 && it[i] <= RTLIL::State::S1)
|
|
goto next_database_entry;
|
|
return true;
|
|
next_database_entry:;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool take(RTLIL::SigSpec sig)
|
|
{
|
|
bool status = false;
|
|
bits_t bits = sig2bits(sig);
|
|
for (auto it = database.begin(); it != database.end();)
|
|
if (match(*it, bits)) {
|
|
for (int i = 0; i < width; i++) {
|
|
if ((*it)[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa)
|
|
continue;
|
|
bits_t new_pattern;
|
|
new_pattern.bitdata = it->bitdata;
|
|
new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1;
|
|
database.insert(new_pattern);
|
|
}
|
|
it = database.erase(it);
|
|
status = true;
|
|
continue;
|
|
} else
|
|
++it;
|
|
return status;
|
|
}
|
|
|
|
bool take_all()
|
|
{
|
|
if (database.empty())
|
|
return false;
|
|
database.clear();
|
|
return true;
|
|
}
|
|
|
|
bool empty()
|
|
{
|
|
return database.empty();
|
|
}
|
|
};
|
|
|
|
YOSYS_NAMESPACE_END
|
|
|
|
#endif
|