diff options
author | Clifford Wolf <clifford@clifford.at> | 2017-10-31 12:40:25 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2017-10-31 12:40:25 +0100 |
commit | 4f31cb6daddedcee467d85797d81b79360ce1826 (patch) | |
tree | 53590a9c53c2a1363889107bc43ab0496dadfc40 /passes/cmds/ltp.cc | |
parent | 455c1c9d97330b9d20cafe62cd72c3c3f71d3573 (diff) | |
download | yosys-4f31cb6daddedcee467d85797d81b79360ce1826.tar.gz yosys-4f31cb6daddedcee467d85797d81b79360ce1826.tar.bz2 yosys-4f31cb6daddedcee467d85797d81b79360ce1826.zip |
Add "ltp" command
Diffstat (limited to 'passes/cmds/ltp.cc')
-rw-r--r-- | passes/cmds/ltp.cc | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc new file mode 100644 index 000000000..42dc794ec --- /dev/null +++ b/passes/cmds/ltp.cc @@ -0,0 +1,185 @@ +/* + * 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. + * + */ + +#include "kernel/yosys.h" +#include "kernel/celltypes.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct LtpWorker +{ + RTLIL::Design *design; + RTLIL::Module *module; + SigMap sigmap; + + dict<SigBit, tuple<int, SigBit, Cell*>> bits; + dict<SigBit, dict<SigBit, Cell*>> bit2bits; + dict<SigBit, tuple<SigBit, Cell*>> bit2ff; + + int maxlvl; + SigBit maxbit; + pool<SigBit> busy; + + LtpWorker(RTLIL::Module *module, bool noff) : design(module->design), module(module), sigmap(module) + { + CellTypes ff_celltypes; + + if (noff) { + ff_celltypes.setup_internals_mem(); + ff_celltypes.setup_stdcells_mem(); + } + + for (auto wire : module->selected_wires()) + for (auto bit : sigmap(wire)) + bits[bit] = tuple<int, SigBit, Cell*>(-1, State::Sx, nullptr); + + for (auto cell : module->selected_cells()) + { + pool<SigBit> src_bits, dst_bits; + + for (auto &conn : cell->connections()) + for (auto bit : sigmap(conn.second)) { + if (cell->input(conn.first)) + src_bits.insert(bit); + if (cell->output(conn.first)) + dst_bits.insert(bit); + } + + if (noff && ff_celltypes.cell_known(cell->type)) { + for (auto s : src_bits) + for (auto d : dst_bits) { + bit2ff[s] = tuple<SigBit, Cell*>(d, cell); + break; + } + continue; + } + + for (auto s : src_bits) + for (auto d : dst_bits) + bit2bits[s][d] = cell; + } + + maxlvl = -1; + maxbit = State::Sx; + } + + void runner(SigBit bit, int level, SigBit from, Cell *via) + { + auto &bitinfo = bits.at(bit); + + if (get<0>(bitinfo) >= level) + return; + + if (busy.count(bit) > 0) { + log_warning("Detected loop at %s in %s\n", log_signal(bit), log_id(module)); + return; + } + + busy.insert(bit); + get<0>(bitinfo) = level; + get<1>(bitinfo) = from; + get<2>(bitinfo) = via; + + if (level > maxlvl) { + maxlvl = level; + maxbit = bit; + } + + if (bit2bits.count(bit)) { + for (auto &it : bit2bits.at(bit)) + runner(it.first, level+1, bit, it.second); + } + + busy.erase(bit); + } + + void printpath(SigBit bit) + { + auto &bitinfo = bits.at(bit); + if (get<2>(bitinfo)) { + printpath(get<1>(bitinfo)); + log("%5d: %s (via %s)\n", get<0>(bitinfo), log_signal(bit), log_id(get<2>(bitinfo))); + } else { + log("%5d: %s\n", get<0>(bitinfo), log_signal(bit)); + } + } + + void run() + { + for (auto &it : bits) + if (get<0>(it.second) < 0) + runner(it.first, 0, State::Sx, nullptr); + + log("\n"); + log("Longest topological path in %s (length=%d):\n", log_id(module), maxlvl); + + if (maxlvl >= 0) + printpath(maxbit); + + if (bit2ff.count(maxbit)) + log("%5s: %s (via %s)\n", "ff", log_signal(get<0>(bit2ff.at(maxbit))), log_id(get<1>(bit2ff.at(maxbit)))); + } +}; + +struct LtpPass : public Pass { + LtpPass() : Pass("ltp", "print longest topological path") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" ltp [options] [selection]\n"); + log("\n"); + log("This command prints the longest topological path in the design. (Only considers\n"); + log("paths within a single module, so the design must be flattened.)\n"); + log("\n"); + log(" -noff\n"); + log(" automatically exclude FF cell types\n"); + log("\n"); + } + virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + { + bool noff = false; + + log_header(design, "Executing LTP pass (find longest path).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-noff") { + noff = true; + continue; + } + break; + } + + extra_args(args, argidx, design); + + for (Module *module : design->selected_modules()) + { + if (module->has_processes_warn()) + continue; + + LtpWorker worker(module, noff); + worker.run(); + } + } +} LtpPass; + +PRIVATE_NAMESPACE_END |