2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
29 bool assert_mode
= false;
34 const NlutmapConfig
&config
;
35 pool
<Cell
*> mapped_cells
;
38 NlutmapWorker(const NlutmapConfig
&config
, Module
*module
) :
39 config(config
), module(module
)
43 RTLIL::Selection
get_selection()
45 RTLIL::Selection
sel(false);
46 for (auto cell
: module
->cells())
47 if (!mapped_cells
.count(cell
))
48 sel
.select(module
, cell
);
52 void run_abc(int lut_size
)
54 Pass::call_on_selection(module
->design
, get_selection(), "lut2mux");
57 Pass::call_on_selection(module
->design
, get_selection(), stringf("abc -lut 1:%d", lut_size
));
59 Pass::call_on_selection(module
->design
, get_selection(), "abc");
61 Pass::call_on_module(module
->design
, module
, "opt_clean");
66 vector
<int> available_luts
= config
.luts
;
68 while (GetSize(available_luts
) > 1)
70 int n_luts
= available_luts
.back();
71 int lut_size
= GetSize(available_luts
);
72 available_luts
.pop_back();
79 SigMap
sigmap(module
);
80 dict
<Cell
*, int> candidate_ratings
;
81 dict
<SigBit
, int> bit_lut_count
;
83 for (auto cell
: module
->cells())
85 if (cell
->type
!= ID($lut
) || mapped_cells
.count(cell
))
88 if (GetSize(cell
->getPort(ID::A
)) == lut_size
|| lut_size
== 2)
89 candidate_ratings
[cell
] = 0;
91 for (auto &conn
: cell
->connections())
92 for (auto bit
: sigmap(conn
.second
))
96 for (auto &cand
: candidate_ratings
)
98 for (auto &conn
: cand
.first
->connections())
99 for (auto bit
: sigmap(conn
.second
))
100 cand
.second
-= bit_lut_count
[bit
];
103 vector
<pair
<int, IdString
>> rated_candidates
;
105 for (auto &cand
: candidate_ratings
)
106 rated_candidates
.push_back(pair
<int, IdString
>(cand
.second
, cand
.first
->name
));
108 std::sort(rated_candidates
.begin(), rated_candidates
.end());
110 while (n_luts
> 0 && !rated_candidates
.empty()) {
111 mapped_cells
.insert(module
->cell(rated_candidates
.back().second
));
112 rated_candidates
.pop_back();
116 if (!available_luts
.empty())
117 available_luts
.back() += n_luts
;
120 if (config
.assert_mode
) {
121 for (auto cell
: module
->cells())
122 if (cell
->type
== ID($lut
) && !mapped_cells
.count(cell
))
123 log_error("Insufficient number of LUTs to map all logic cells!\n");
130 struct NlutmapPass
: public Pass
{
131 NlutmapPass() : Pass("nlutmap", "map to LUTs of different sizes") { }
132 void help() YS_OVERRIDE
134 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
136 log(" nlutmap [options] [selection]\n");
138 log("This pass uses successive calls to 'abc' to map to an architecture. That\n");
139 log("provides a small number of differently sized LUTs.\n");
141 log(" -luts N_1,N_2,N_3,...\n");
142 log(" The number of LUTs with 1, 2, 3, ... inputs that are\n");
143 log(" available in the target architecture.\n");
146 log(" Create an error if not all logic can be mapped\n");
148 log("Excess logic that does not fit into the specified LUTs is mapped back\n");
149 log("to generic logic gates ($_AND_, etc.).\n");
152 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
154 NlutmapConfig config
;
156 log_header(design
, "Executing NLUTMAP pass (mapping to constant drivers).\n");
160 for (argidx
= 1; argidx
< args
.size(); argidx
++)
162 if (args
[argidx
] == "-luts" && argidx
+1 < args
.size()) {
163 vector
<string
> tokens
= split_tokens(args
[++argidx
], ",");
165 for (auto &token
: tokens
)
166 config
.luts
.push_back(atoi(token
.c_str()));
169 if (args
[argidx
] == "-assert") {
170 config
.assert_mode
= true;
175 extra_args(args
, argidx
, design
);
177 for (auto module
: design
->selected_whole_modules_warn())
179 NlutmapWorker
worker(config
, module
);
187 PRIVATE_NAMESPACE_END