3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-24 01:25:33 +00:00

Annotate logic depth

This commit is contained in:
Alain Dargelas 2025-02-05 16:45:08 -08:00
parent 47aac95f64
commit bf96f94267
3 changed files with 150 additions and 2 deletions

View file

@ -0,0 +1,130 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* 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<RTLIL::Cell> 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<Cell *> &cells, SigMap &sigmap,
TopoSort<RTLIL::Cell *, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> &toposort)
{
dict<SigBit, pool<Cell *>> 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<std::string> 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<Cell *> cells;
std::map<RTLIL::Cell *, int> celllevel;
for (auto cell : module->selected_cells()) {
cells.push_back(cell);
celllevel.emplace(cell, 0);
}
TopoSort<RTLIL::Cell *, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> toposort;
toposorting(cells, sigmap, toposort);
std::map<RTLIL::Cell *, std::set<RTLIL::Cell *, cell_ptr_cmp>, 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

View file

@ -25,6 +25,8 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
typedef RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell> 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<RTLIL::Cell *, int> celllevel;
for (auto cell : itrCluster->second) {
celllevel.emplace(cell, 0);
}
TopoSort<RTLIL::Cell *, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> toposort;
toposorting(itrCluster->second, sigmap, toposort, debug);
std::vector<Cell *>::reverse_iterator itrLastCell = toposort.sorted.rbegin();
int logicdepth = toposort.node_to_index.find((*itrLastCell))->second;
int logicdepth = 0;
std::map<RTLIL::Cell *, std::set<RTLIL::Cell *, cell_ptr_cmp>, 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();