/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf * * 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 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>::hash(bitdata); return cached_hash; } }; pool 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