mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-29 01:18:46 +00:00
Cleanup
This commit is contained in:
parent
f76fd9280b
commit
fd811ddaee
23 changed files with 39 additions and 126 deletions
257
passes/silimate/longloop_select.cc
Normal file
257
passes/silimate/longloop_select.cc
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* 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 LongLoopSelect : public ScriptPass {
|
||||
LongLoopSelect()
|
||||
: ScriptPass("longloop_select", "Selects long for-loops (Creating logic above a certain logic depth) for further optimizations")
|
||||
{
|
||||
}
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" longloop_select [-depth <for-loop threshold depth>] [-abc_opt <ABC options>] [-abc_script <ABC script>]\n");
|
||||
log(" If no ABC script/option is provided, this pass simply selects cells in for-loops\n");
|
||||
log(" If an ABC script/option is provided, this pass selects cells in a per for-loop basis and runs ABC with the given script\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, bool debug)
|
||||
{
|
||||
if (debug) {
|
||||
log(" Collecting design data\n");
|
||||
log_flush();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
log(" Creating sorting data structure\n");
|
||||
log_flush();
|
||||
}
|
||||
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;
|
||||
if (debug) {
|
||||
log(" Sorting\n");
|
||||
log_flush();
|
||||
}
|
||||
toposort.sort();
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
if (design == nullptr) {
|
||||
log_error("No design object");
|
||||
return;
|
||||
}
|
||||
uint32_t threshold_depth = 100;
|
||||
bool debug = false;
|
||||
size_t argidx;
|
||||
std::string abc_script;
|
||||
std::string abc_options;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-depth") {
|
||||
argidx++;
|
||||
threshold_depth = std::stoul(args[argidx], nullptr, 10);
|
||||
} else if (args[argidx] == "-debug") {
|
||||
debug = true;
|
||||
} else if (args[argidx] == "-abc_script") {
|
||||
argidx++;
|
||||
abc_script = args[argidx];
|
||||
} else if (args[argidx] == "-abc_opt") {
|
||||
argidx++;
|
||||
abc_options = args[argidx];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (std::getenv("DEBUG_LONGLOOPS")) {
|
||||
debug = true;
|
||||
}
|
||||
log("Running longloop_select pass\n");
|
||||
log_flush();
|
||||
|
||||
// Memorize the existing selection, so the loop over modules still works after "select -none"
|
||||
const std::vector<Yosys::RTLIL::Module *> &modules = design->selected_modules();
|
||||
|
||||
// Start with an empty selection, the code below is going to add selection based on loop depth
|
||||
Pass::call(design, "select -none");
|
||||
|
||||
for (auto module : modules) {
|
||||
if (debug) {
|
||||
log("Module %s\n", log_id(module));
|
||||
log_flush();
|
||||
}
|
||||
if (debug) {
|
||||
log(" Creating sigmap\n");
|
||||
log_flush();
|
||||
}
|
||||
SigMap sigmap(module);
|
||||
std::map<std::string, std::vector<Cell *>> loopIndexCellMap;
|
||||
if (debug) {
|
||||
log(" Creating sorting datastructures\n");
|
||||
log_flush();
|
||||
}
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
std::string loopIndex = cell->get_string_attribute("\\in_for_loop");
|
||||
if (!loopIndex.empty()) {
|
||||
std::map<std::string, std::vector<Cell *>>::iterator itr = loopIndexCellMap.find(loopIndex);
|
||||
if (itr == loopIndexCellMap.end()) {
|
||||
std::vector<Cell *> cellSet;
|
||||
cellSet.push_back(cell);
|
||||
loopIndexCellMap.emplace(loopIndex, cellSet);
|
||||
} else {
|
||||
itr->second.push_back(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!loopIndexCellMap.empty()) {
|
||||
log(" Found %ld for-loop clusters in module %s\n", loopIndexCellMap.size(), module->name.c_str());
|
||||
log_flush();
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::vector<Cell *>>::iterator itrCluster = loopIndexCellMap.begin();
|
||||
itrCluster != loopIndexCellMap.end(); itrCluster++) {
|
||||
std::string loopInd = itrCluster->first;
|
||||
if (itrCluster->second.size() < threshold_depth) {
|
||||
if (debug) {
|
||||
log(" Skipping loop location %s as it contains only %ld cells\n", loopInd.c_str(),
|
||||
itrCluster->second.size());
|
||||
log_flush();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (debug) {
|
||||
log(" Analyzing loop location %s containing %ld cells\n", loopInd.c_str(), itrCluster->second.size());
|
||||
log_flush();
|
||||
}
|
||||
// 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 = 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();
|
||||
}
|
||||
if (logicdepth > (int)threshold_depth) {
|
||||
log(" Selecting %ld cells in for-loop location %s of depth %d ending with cell %s\n",
|
||||
itrCluster->second.size(), loopInd.c_str(), logicdepth, log_id((*itrLastCell)));
|
||||
log_flush();
|
||||
std::string src_info = (*itrLastCell)->get_src_attribute();
|
||||
if (!(*itrLastCell)->get_string_attribute("\\in_for_loop").empty()) {
|
||||
src_info = (*itrLastCell)->get_string_attribute("\\in_for_loop");
|
||||
}
|
||||
// Select all cells in the loop cluster
|
||||
if (!abc_script.empty()) {
|
||||
// If an ABC script is provided, select on a per-loop basis
|
||||
Pass::call(design, "select -none");
|
||||
}
|
||||
for (auto cell : itrCluster->second) {
|
||||
if (debug) {
|
||||
log(" Selecting: %s\n", cell->name.c_str());
|
||||
log_flush();
|
||||
}
|
||||
design->select(module, cell);
|
||||
if (cell->get_string_attribute("\\in_for_loop").empty()) {
|
||||
cell->set_string_attribute("\\in_for_loop", src_info);
|
||||
} else {
|
||||
src_info = cell->get_string_attribute("\\in_for_loop");
|
||||
}
|
||||
}
|
||||
if (!abc_script.empty()) {
|
||||
std::string command = "abc -map_src " + src_info + " -script " + abc_script;
|
||||
log(" Executing: %s\n", command.c_str());
|
||||
log_flush();
|
||||
Pass::call(design, command);
|
||||
} else if (!abc_options.empty()) {
|
||||
abc_options.erase(std::remove(abc_options.begin(), abc_options.end(), '"'), abc_options.end());
|
||||
std::string command = "abc -map_src " + src_info + " " + abc_options;
|
||||
log(" Executing: %s\n", command.c_str());
|
||||
log_flush();
|
||||
Pass::call(design, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log("End longloop_select pass\n");
|
||||
log_flush();
|
||||
}
|
||||
} LongLoopSelect;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
Loading…
Add table
Add a link
Reference in a new issue