diff --git a/Makefile b/Makefile index 2592e3d4a..636a2e51e 100644 --- a/Makefile +++ b/Makefile @@ -717,7 +717,7 @@ OBJS += passes/cmds/stat.o OBJS += passes/cmds/cover.o OBJS += passes/cmds/design.o OBJS += passes/cmds/plugin.o - +OBJS += passes/cmds/annotate_logic_depth.o OBJS += passes/cmds/blackbox.o OBJS += passes/cmds/check.o OBJS += passes/cmds/clean_zerowidth.o diff --git a/passes/cmds/annotate_logic_depth.cc b/passes/cmds/annotate_logic_depth.cc new file mode 100644 index 000000000..de0533587 --- /dev/null +++ b/passes/cmds/annotate_logic_depth.cc @@ -0,0 +1,130 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia 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. + * + */ + +#include "kernel/celltypes.h" +#include "kernel/sigtools.h" +#include "kernel/utils.h" +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +typedef RTLIL::IdString::compare_ptr_by_name cell_ptr_cmp; + +struct AnnotateLogicDepth : public ScriptPass { + AnnotateLogicDepth() : ScriptPass("annotate_logic_depth", "Annotate logic depth per cells and modules") {} + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" annotate_logic_depth [-module] [-cell]\n"); + log("\n"); + } + void script() override {} + + // Adapted from the torder pass + void toposorting(std::vector &cells, SigMap &sigmap, + TopoSort> &toposort) + { + dict> bit_drivers, bit_users; + for (Cell *cell : cells) { + for (auto conn : cell->connections()) { + bool noautostop = false; + if (!noautostop && yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in(ID::Q, ID::CTRL_OUT, ID::RD_DATA)) + continue; + if (cell->type.in(ID($memrd), ID($memrd_v2)) && conn.first == ID::DATA) + continue; + } + + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell); + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell); + + toposort.node(cell); + } + } + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + + toposort.analyze_loops = false; + toposort.sort(); + } + + void execute(std::vector args, RTLIL::Design *design) override + { + if (design == nullptr) { + log_error("No design object"); + return; + } + size_t argidx; + bool annotate_modules = false; + bool annotate_cells = false; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-module") { + annotate_modules = true; + } else if (args[argidx] == "-cell") { + annotate_cells = true; + } else { + break; + } + } + extra_args(args, argidx, design); + int design_max_depth = 0; + for (auto module : design->selected_modules()) { + int module_max_depth = 0; + SigMap sigmap(module); + std::vector cells; + std::map celllevel; + for (auto cell : module->selected_cells()) { + cells.push_back(cell); + celllevel.emplace(cell, 0); + } + TopoSort> toposort; + toposorting(cells, sigmap, toposort); + std::map, cell_ptr_cmp> topo_cell_drivers = toposort.get_database(); + for (auto cell : toposort.sorted) { + int level = 0; + auto itrAdj = topo_cell_drivers.find(cell); + for (auto c : (*itrAdj).second) { + level = std::max(level, celllevel[c]); + } + level++; + celllevel[cell] = level; + module_max_depth = std::max(module_max_depth, level); + if (annotate_cells) + cell->set_string_attribute("$DEPTH", std::to_string(level)); + } + design_max_depth = std::max(design_max_depth, module_max_depth); + if (annotate_modules) + module->set_string_attribute("$MAX_DEPTH", std::to_string(module_max_depth)); + } + design->top_module()->set_string_attribute("$DESIGN_MAX_DEPTH", std::to_string(design_max_depth)); + log("Max logic depth: %d\n", design_max_depth); + } +} AnnotateLogicDepth; + +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/longloop_select.cc b/passes/cmds/longloop_select.cc index b5284be1d..b7336787a 100644 --- a/passes/cmds/longloop_select.cc +++ b/passes/cmds/longloop_select.cc @@ -25,6 +25,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +typedef RTLIL::IdString::compare_ptr_by_name cell_ptr_cmp; + struct LongLoopSelect : public ScriptPass { LongLoopSelect() : ScriptPass("longloop_select", "Selects long for-loops (Creating logic above a certain logic depth) for further optimizations") @@ -178,10 +180,26 @@ struct LongLoopSelect : public ScriptPass { } // For a given for-loop cell group, perform topological sorting to get the logic depth of the ending cell in // the group + std::map celllevel; + for (auto cell : itrCluster->second) { + celllevel.emplace(cell, 0); + } TopoSort> toposort; toposorting(itrCluster->second, sigmap, toposort, debug); std::vector::reverse_iterator itrLastCell = toposort.sorted.rbegin(); - int logicdepth = toposort.node_to_index.find((*itrLastCell))->second; + int logicdepth = 0; + std::map, cell_ptr_cmp> topo_cell_drivers = + toposort.get_database(); + for (auto cell : toposort.sorted) { + int level = 0; + auto itrAdj = topo_cell_drivers.find(cell); + for (auto c : (*itrAdj).second) { + level = std::max(level, celllevel[c]); + } + level++; + celllevel[cell] = level; + logicdepth = std::max(logicdepth, level); + } if (debug) { log(" Logic depth: %d\n", logicdepth); log_flush();