summaryrefslogtreecommitdiff
path: root/kernel/sigtools.h
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-01-05 11:13:26 +0100
committerClifford Wolf <clifford@clifford.at>2013-01-05 11:13:26 +0100
commit7764d0ba1dcf064ae487ee985c43083a0909e7f4 (patch)
tree18c05b8729df381af71b707748ce1d605e0df764 /kernel/sigtools.h
initial import
Diffstat (limited to 'kernel/sigtools.h')
-rw-r--r--kernel/sigtools.h415
1 files changed, 415 insertions, 0 deletions
diff --git a/kernel/sigtools.h b/kernel/sigtools.h
new file mode 100644
index 00000000..e76fd602
--- /dev/null
+++ b/kernel/sigtools.h
@@ -0,0 +1,415 @@
+/*
+ * 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 SIGTOOLS_H
+#define SIGTOOLS_H
+
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+#include <assert.h>
+#include <set>
+
+struct SigPool
+{
+ typedef std::pair<RTLIL::Wire*,int> bitDef_t;
+ std::set<bitDef_t> bits;
+
+ void clear()
+ {
+ bits.clear();
+ }
+
+ void add(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ bits.insert(bit);
+ }
+ }
+
+ void add(const SigPool &other)
+ {
+ for (auto &bit : other.bits)
+ bits.insert(bit);
+ }
+
+ void del(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ bits.erase(bit);
+ }
+ }
+
+ void del(const SigPool &other)
+ {
+ for (auto &bit : other.bits)
+ bits.insert(bit);
+ }
+
+ void expand(RTLIL::SigSpec from, RTLIL::SigSpec to)
+ {
+ from.expand();
+ to.expand();
+ assert(from.chunks.size() == to.chunks.size());
+ for (size_t i = 0; i < from.chunks.size(); i++) {
+ bitDef_t bit_from(from.chunks[i].wire, from.chunks[i].offset);
+ bitDef_t bit_to(to.chunks[i].wire, to.chunks[i].offset);
+ if (bit_from.first == NULL || bit_to.first == NULL)
+ continue;
+ if (bits.count(bit_from) > 0)
+ bits.insert(bit_to);
+ }
+ }
+
+ RTLIL::SigSpec extract(RTLIL::SigSpec sig)
+ {
+ RTLIL::SigSpec result;
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ bitDef_t bit(c.wire, c.offset);
+ if (bits.count(bit) > 0)
+ result.append(c);
+ }
+ return result;
+ }
+
+ RTLIL::SigSpec remove(RTLIL::SigSpec sig)
+ {
+ RTLIL::SigSpec result;
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ bitDef_t bit(c.wire, c.offset);
+ if (bits.count(bit) == 0)
+ result.append(c);
+ }
+ return result;
+ }
+
+ bool check_any(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ bitDef_t bit(c.wire, c.offset);
+ if (bits.count(bit) != 0)
+ return true;
+ }
+ return false;
+ }
+
+ bool check_all(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ bitDef_t bit(c.wire, c.offset);
+ if (bits.count(bit) == 0)
+ return false;
+ }
+ return true;
+ }
+};
+
+template <typename T>
+struct SigSet
+{
+ typedef std::pair<RTLIL::Wire*,int> bitDef_t;
+ std::map<bitDef_t, std::set<T>> bits;
+
+ void clear()
+ {
+ bits.clear();
+ }
+
+ void insert(RTLIL::SigSpec sig, T data)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ bits[bit].insert(data);
+ }
+ }
+
+ void erase(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ bits[bit].clear();
+ }
+ }
+
+ void erase(RTLIL::SigSpec sig, T data)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ bits[bit].erase(data);
+ }
+ }
+
+ void find(RTLIL::SigSpec sig, std::set<T> &result)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks) {
+ if (c.wire == NULL)
+ continue;
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ for (auto &data : bits[bit])
+ result.insert(data);
+ }
+ }
+
+ std::set<T> find(RTLIL::SigSpec sig)
+ {
+ std::set<T> result;
+ find(sig, result);
+ return result;
+ }
+};
+
+struct SigMap
+{
+ typedef std::pair<RTLIL::Wire*,int> bitDef_t;
+
+ struct shared_bit_data_t {
+ RTLIL::SigChunk chunk;
+ std::set<bitDef_t> bits;
+ };
+
+ std::map<bitDef_t, shared_bit_data_t*> bits;
+
+ SigMap(RTLIL::Module *module = NULL)
+ {
+ if (module != NULL)
+ set(module);
+ }
+
+ SigMap(const SigMap &other)
+ {
+ copy(other);
+ }
+
+ const SigMap &operator=(const SigMap &other)
+ {
+ copy(other);
+ return *this;
+ }
+
+ void copy(const SigMap &other)
+ {
+ clear();
+ for (auto &bit : other.bits) {
+ bits[bit.first] = new shared_bit_data_t;
+ bits[bit.first]->chunk = bit.second->chunk;
+ bits[bit.first]->bits = bit.second->bits;
+ }
+ }
+
+ void swap(SigMap &other)
+ {
+ bits.swap(other.bits);
+ }
+
+ ~SigMap()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ std::set<shared_bit_data_t*> all_bd_ptr;
+ for (auto &it : bits)
+ all_bd_ptr.insert(it.second);
+ for (auto bd_ptr : all_bd_ptr)
+ delete bd_ptr;
+ bits.clear();
+ }
+
+ void set(RTLIL::Module *module)
+ {
+ clear();
+ for (auto &it : module->connections)
+ add(it.first, it.second);
+ }
+
+ // internal helper function
+ void register_bit(const RTLIL::SigChunk &c)
+ {
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ if (c.wire && bits.count(bit) == 0) {
+ shared_bit_data_t *bd = new shared_bit_data_t;
+ bd->chunk = c;
+ bd->bits.insert(bit);
+ bits[bit] = bd;
+ }
+ }
+
+ // internal helper function
+ void unregister_bit(const RTLIL::SigChunk &c)
+ {
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ if (c.wire && bits.count(bit) > 0) {
+ shared_bit_data_t *bd = bits[bit];
+ bd->bits.erase(bit);
+ if (bd->bits.size() == 0)
+ delete bd;
+ bits.erase(bit);
+ }
+ }
+
+ // internal helper function
+ void merge_bit(const RTLIL::SigChunk &c1, const RTLIL::SigChunk &c2)
+ {
+ assert(c1.wire != NULL && c2.wire != NULL);
+ assert(c1.width == 1 && c2.width == 1);
+
+ bitDef_t b1(c1.wire, c1.offset);
+ bitDef_t b2(c2.wire, c2.offset);
+
+ shared_bit_data_t *bd1 = bits[b1];
+ shared_bit_data_t *bd2 = bits[b2];
+ assert(bd1 != NULL && bd2 != NULL);
+
+ if (bd1 == bd2)
+ return;
+
+ if (bd1->bits.size() < bd2->bits.size())
+ {
+ for (auto &bit : bd1->bits)
+ bits[bit] = bd2;
+ bd2->bits.insert(bd1->bits.begin(), bd1->bits.end());
+ delete bd1;
+ }
+ else
+ {
+ bd1->chunk = bd2->chunk;
+ for (auto &bit : bd2->bits)
+ bits[bit] = bd1;
+ bd1->bits.insert(bd2->bits.begin(), bd2->bits.end());
+ delete bd2;
+ }
+ }
+
+ // internal helper function
+ void set_bit(const RTLIL::SigChunk &c1, const RTLIL::SigChunk &c2)
+ {
+ assert(c1.wire != NULL);
+ assert(c1.width == 1 && c2.width == 1);
+ bitDef_t bit(c1.wire, c1.offset);
+ assert(bits.count(bit) > 0);
+ bits[bit]->chunk = c2;
+ }
+
+ // internal helper function
+ void map_bit(RTLIL::SigChunk &c)
+ {
+ assert(c.width == 1);
+ bitDef_t bit(c.wire, c.offset);
+ if (c.wire && bits.count(bit) > 0)
+ c = bits[bit]->chunk;
+ }
+
+ void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
+ {
+ from.expand();
+ to.expand();
+
+ assert(from.chunks.size() == to.chunks.size());
+ for (size_t i = 0; i < from.chunks.size(); i++)
+ {
+ RTLIL::SigChunk &cf = from.chunks[i];
+ RTLIL::SigChunk &ct = to.chunks[i];
+
+ if (cf.wire == NULL)
+ continue;
+
+ register_bit(cf);
+ register_bit(ct);
+
+ if (ct.wire != NULL)
+ merge_bit(cf, ct);
+ else
+ set_bit(cf, ct);
+ }
+ }
+
+ void add(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (size_t i = 0; i < sig.chunks.size(); i++)
+ {
+ RTLIL::SigChunk &c = sig.chunks[i];
+ if (c.wire != NULL) {
+ register_bit(c);
+ set_bit(c, c);
+ }
+ }
+ }
+
+ void del(RTLIL::SigSpec sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks)
+ unregister_bit(c);
+ }
+
+ void apply(RTLIL::SigSpec &sig)
+ {
+ sig.expand();
+ for (auto &c : sig.chunks)
+ map_bit(c);
+ sig.optimize();
+ }
+
+ RTLIL::SigSpec operator()(RTLIL::SigSpec sig)
+ {
+ apply(sig);
+ return sig;
+ }
+};
+
+#endif /* SIGTOOLS_H */