From 598a475724b51954cb40c991dc3ed26cc11f81ec Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 18 Sep 2015 21:57:34 +0200 Subject: Added nlutmap --- passes/techmap/nlutmap.cc | 173 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 passes/techmap/nlutmap.cc (limited to 'passes/techmap/nlutmap.cc') diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc new file mode 100644 index 00000000..7ece4005 --- /dev/null +++ b/passes/techmap/nlutmap.cc @@ -0,0 +1,173 @@ +/* + * 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. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct NlutmapConfig +{ + vector luts; +}; + +struct NlutmapWorker +{ + const NlutmapConfig &config; + pool mapped_cells; + Module *module; + + NlutmapWorker(const NlutmapConfig &config, Module *module) : + config(config), module(module) + { + } + + RTLIL::Selection get_selection() + { + RTLIL::Selection sel(false); + for (auto cell : module->cells()) + if (!mapped_cells.count(cell)) + sel.select(module, cell); + return sel; + } + + void run_abc(int lut_size) + { + Pass::call_on_selection(module->design, get_selection(), "lut2mux"); + + if (lut_size > 0) + Pass::call_on_selection(module->design, get_selection(), stringf("abc -lut 1:%d", lut_size)); + else + Pass::call_on_selection(module->design, get_selection(), "abc"); + + Pass::call_on_module(module->design, module, "opt_clean"); + } + + void run() + { + vector available_luts = config.luts; + + while (!available_luts.empty()) + { + int n_luts = available_luts.back(); + int lut_size = GetSize(available_luts); + available_luts.pop_back(); + + if (n_luts == 0) + continue; + + run_abc(lut_size); + + SigMap sigmap(module); + dict candidate_ratings; + dict bit_lut_count; + + for (auto cell : module->cells()) + { + if (cell->type != "$lut" || mapped_cells.count(cell)) + continue; + + if (GetSize(cell->getPort("\\A")) == lut_size) + candidate_ratings[cell] = 0; + + for (auto &conn : cell->connections()) + for (auto bit : sigmap(conn.second)) + bit_lut_count[bit]++; + } + + for (auto &cand : candidate_ratings) + { + for (auto &conn : cand.first->connections()) + for (auto bit : sigmap(conn.second)) + cand.second -= bit_lut_count[bit]; + } + + vector> rated_candidates; + + for (auto &cand : candidate_ratings) + rated_candidates.push_back(pair(cand.second, cand.first->name)); + + std::sort(rated_candidates.begin(), rated_candidates.end()); + + while (n_luts > 0 && !rated_candidates.empty()) { + mapped_cells.insert(module->cell(rated_candidates.back().second)); + rated_candidates.pop_back(); + n_luts--; + } + + if (!available_luts.empty()) + available_luts.back() += n_luts; + } + + run_abc(0); + } +}; + +struct NlutmapPass : public Pass { + NlutmapPass() : Pass("nlutmap", "map to LUTs of different sizes") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" nlutmap [options] [selection]\n"); + log("\n"); + log("This pass uses successive calls to 'abc' to map to an architecture. That\n"); + log("provides a small number of differently sized LUTs.\n"); + log("\n"); + log(" -luts N_1,N_2,N_3,...\n"); + log(" The number of LUTs with 1, 2, 3, ... inputs that are\n"); + log(" available in the target architecture.\n"); + log("\n"); + log("Excess logic that does not fit into the specified LUTs is mapped back\n"); + log("to generic logic gates ($_AND_, etc.).\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + NlutmapConfig config; + + log_header("Executing NLUTMAP pass (mapping to constant drivers).\n"); + log_push(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-luts" && argidx+1 < args.size()) { + vector tokens = split_tokens(args[++argidx], ","); + config.luts.clear(); + for (auto &token : tokens) + config.luts.push_back(atoi(token.c_str())); + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_whole_modules_warn()) + { + NlutmapWorker worker(config, module); + worker.run(); + } + + log_pop(); + } +} NlutmapPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3