/* * 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 MODTOOLS_H #define MODTOOLS_H #include "kernel/sigtools.h" #include "kernel/celltypes.h" struct ModWalker { struct PortBit { RTLIL::Cell *cell; RTLIL::IdString port; int offset; bool operator<(const PortBit &other) const { if (cell != other.cell) return cell < other.cell; if (port != other.port) return port < other.port; return offset < other.offset; } }; RTLIL::Design *design; RTLIL::Module *module; CellTypes ct; SigMap sigmap; std::map> signal_drivers; std::map> signal_consumers; std::set signal_inputs, signal_outputs; std::map> cell_outputs, cell_inputs; void add_wire(RTLIL::Wire *wire) { if (wire->port_input) { std::vector bits = sigmap(wire); for (auto bit : bits) if (bit.wire != NULL) signal_inputs.insert(bit); } if (wire->port_output) { std::vector bits = sigmap(wire); for (auto bit : bits) if (bit.wire != NULL) signal_outputs.insert(bit); } } void add_cell_port(RTLIL::Cell *cell, RTLIL::IdString port, std::vector bits, bool is_output, bool is_input) { for (int i = 0; i < int(bits.size()); i++) if (bits[i].wire != NULL) { PortBit pbit = { cell, port, i }; if (is_output) { signal_drivers[bits[i]].insert(pbit); cell_outputs[cell].insert(bits[i]); } if (is_input) { signal_consumers[bits[i]].insert(pbit); cell_inputs[cell].insert(bits[i]); } } } void add_cell(RTLIL::Cell *cell) { if (ct.cell_known(cell->type)) { for (auto &conn : cell->connections()) add_cell_port(cell, conn.first, sigmap(conn.second), ct.cell_output(cell->type, conn.first), ct.cell_input(cell->type, conn.first)); } else { for (auto &conn : cell->connections()) add_cell_port(cell, conn.first, sigmap(conn.second), true, true); } } ModWalker() : design(NULL), module(NULL) { } ModWalker(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL) { setup(design, module, filter_ct); } void setup(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL) { this->design = design; this->module = module; ct.clear(); ct.setup(design); sigmap.set(module); signal_drivers.clear(); signal_consumers.clear(); signal_inputs.clear(); signal_outputs.clear(); for (auto &it : module->wires_) add_wire(it.second); for (auto &it : module->cells_) if (filter_ct == NULL || filter_ct->cell_known(it.second->type)) add_cell(it.second); } // get_* methods -- single RTLIL::SigBit template inline bool get_drivers(std::set &result, RTLIL::SigBit bit) const { bool found = false; if (signal_drivers.count(bit)) { const std::set &r = signal_drivers.at(bit); result.insert(r.begin(), r.end()); found = true; } return found; } template inline bool get_consumers(std::set &result, RTLIL::SigBit bit) const { bool found = false; if (signal_consumers.count(bit)) { const std::set &r = signal_consumers.at(bit); result.insert(r.begin(), r.end()); found = true; } return found; } template inline bool get_inputs(std::set &result, RTLIL::SigBit bit) const { bool found = false; if (signal_inputs.count(bit)) result.insert(bit), found = true; return found; } template inline bool get_outputs(std::set &result, RTLIL::SigBit bit) const { bool found = false; if (signal_outputs.count(bit)) result.insert(bit), found = true; return found; } // get_* methods -- container of RTLIL::SigBit's (always by reference) template inline bool get_drivers(std::set &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_drivers.count(bit)) { const std::set &r = signal_drivers.at(bit); result.insert(r.begin(), r.end()); found = true; } return found; } template inline bool get_consumers(std::set &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_consumers.count(bit)) { const std::set &r = signal_consumers.at(bit); result.insert(r.begin(), r.end()); found = true; } return found; } template inline bool get_inputs(std::set &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_inputs.count(bit)) result.insert(bit), found = true; return found; } template inline bool get_outputs(std::set &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_outputs.count(bit)) result.insert(bit), found = true; return found; } // get_* methods -- call by RTLIL::SigSpec (always by value) bool get_drivers(std::set &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_drivers(result, bits); } bool get_consumers(std::set &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_consumers(result, bits); } bool get_inputs(std::set &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_inputs(result, bits); } bool get_outputs(std::set &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_outputs(result, bits); } // has_* methods -- call by reference template inline bool has_drivers(const T &sig) const { std::set result; return get_drivers(result, sig); } template inline bool has_consumers(const T &sig) const { std::set result; return get_consumers(result, sig); } template inline bool has_inputs(const T &sig) const { std::set result; return get_inputs(result, sig); } template inline bool has_outputs(const T &sig) const { std::set result; return get_outputs(result, sig); } // has_* methods -- call by value inline bool has_drivers(RTLIL::SigSpec sig) const { std::set result; return get_drivers(result, sig); } inline bool has_consumers(RTLIL::SigSpec sig) const { std::set result; return get_consumers(result, sig); } inline bool has_inputs(RTLIL::SigSpec sig) const { std::set result; return get_inputs(result, sig); } inline bool has_outputs(RTLIL::SigSpec sig) const { std::set result; return get_outputs(result, sig); } }; #endif