diff options
author | Clifford Wolf <clifford@clifford.at> | 2013-01-05 11:13:26 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2013-01-05 11:13:26 +0100 |
commit | 7764d0ba1dcf064ae487ee985c43083a0909e7f4 (patch) | |
tree | 18c05b8729df381af71b707748ce1d605e0df764 /kernel/sigtools.h |
initial import
Diffstat (limited to 'kernel/sigtools.h')
-rw-r--r-- | kernel/sigtools.h | 415 |
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 */ |