summaryrefslogtreecommitdiff
path: root/kernel/bitpattern.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bitpattern.h')
-rw-r--r--kernel/bitpattern.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h
new file mode 100644
index 00000000..aaefa50f
--- /dev/null
+++ b/kernel/bitpattern.h
@@ -0,0 +1,143 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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"
+
+struct BitPatternPool
+{
+ int width;
+ typedef std::vector<RTLIL::State> bits_t;
+ std::set<bits_t> pool;
+
+ BitPatternPool(RTLIL::SigSpec sig)
+ {
+ width = sig.width;
+ if (width > 0) {
+ std::vector<RTLIL::State> pattern(width);
+ sig.optimize();
+ for (int i = 0; i < width; i++) {
+ RTLIL::SigSpec s = sig.extract(i, 1);
+ s.optimize();
+ assert(s.chunks.size() == 1);
+ if (s.chunks[0].wire == NULL && s.chunks[0].data.bits[0] <= RTLIL::State::S1)
+ pattern[i] = s.chunks[0].data.bits[0];
+ else
+ pattern[i] = RTLIL::State::Sa;
+ }
+ pool.insert(pattern);
+ }
+ }
+
+ BitPatternPool(int width)
+ {
+ this->width = width;
+ if (width > 0) {
+ std::vector<RTLIL::State> pattern(width);
+ for (int i = 0; i < width; i++)
+ pattern[i] = RTLIL::State::Sa;
+ pool.insert(pattern);
+ }
+ }
+
+ bits_t sig2bits(RTLIL::SigSpec sig)
+ {
+ sig.optimize();
+ assert(sig.is_fully_const());
+ assert(sig.chunks.size() == 1);
+ bits_t bits = sig.chunks[0].data.bits;
+ for (auto &b : bits)
+ if (b > RTLIL::State::S1)
+ b = RTLIL::State::Sa;
+ return bits;
+ }
+
+ bool match(bits_t a, bits_t b)
+ {
+ assert(int(a.size()) == width);
+ assert(int(b.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 : pool)
+ if (match(it, bits))
+ return true;
+ return false;
+ }
+
+ bool has_all(RTLIL::SigSpec sig)
+ {
+ bits_t bits = sig2bits(sig);
+ for (auto &it : pool)
+ if (match(it, bits)) {
+ for (int i = 0; i < width; i++)
+ if (bits[i] > RTLIL::State::S1 && it[i] <= RTLIL::State::S1)
+ goto next_pool_entry;
+ return true;
+ next_pool_entry:;
+ }
+ return false;
+ }
+
+ bool take(RTLIL::SigSpec sig)
+ {
+ bool status = false;
+ bits_t bits = sig2bits(sig);
+ std::vector<bits_t> pattern_list;
+ for (auto &it : pool)
+ if (match(it, bits))
+ pattern_list.push_back(it);
+ for (auto pattern : pattern_list) {
+ pool.erase(pattern);
+ for (int i = 0; i < width; i++) {
+ if (pattern[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa)
+ continue;
+ bits_t new_pattern = pattern;
+ new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1;
+ pool.insert(new_pattern);
+ }
+ status = true;
+ }
+ return status;
+ }
+
+ bool take_all()
+ {
+ if (pool.empty())
+ return false;
+ pool.clear();
+ return true;
+ }
+
+ bool empty()
+ {
+ return pool.empty();
+ }
+};
+
+#endif