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/Makefile.inc | 1 + passes/techmap/nlutmap.cc | 173 ++++++++++++++++++++++++++++++++++ techlibs/greenpak4/synth_greenpak4.cc | 4 +- 3 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 passes/techmap/nlutmap.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 373203ed..674cb77c 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -21,6 +21,7 @@ OBJS += passes/techmap/muxcover.o OBJS += passes/techmap/aigmap.o OBJS += passes/techmap/tribuf.o OBJS += passes/techmap/lut2mux.o +OBJS += passes/techmap/nlutmap.o endif GENFILES += passes/techmap/techmap.inc 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 diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index 8b88667c..15b53d62 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -91,7 +91,7 @@ struct SynthGreenPAK4Pass : public Pass { log(" abc -dff (only if -retime)\n"); log("\n"); log(" map_luts:\n"); - log(" abc -lut 4\n"); + log(" nlutmap -luts 0,8,16,2\n"); log(" clean\n"); log("\n"); log(" map_cells:\n"); @@ -197,7 +197,7 @@ struct SynthGreenPAK4Pass : public Pass { if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "abc -lut 4"); + Pass::call(design, "nlutmap -luts 0,8,16,2"); Pass::call(design, "clean"); } -- cgit v1.2.3