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/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/log.h"
28 extern void simplemap_get_mappers(std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
);
30 static void simplemap_not(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
32 RTLIL::SigSpec sig_a
= cell
->get("\\A");
33 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
35 sig_a
.extend(SIZE(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
37 for (int i
= 0; i
< SIZE(sig_y
); i
++) {
38 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_INV_");
39 gate
->set("\\A", sig_a
[i
]);
40 gate
->set("\\Y", sig_y
[i
]);
44 static void simplemap_pos(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
46 RTLIL::SigSpec sig_a
= cell
->get("\\A");
47 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
49 sig_a
.extend(SIZE(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
51 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
54 static void simplemap_bu0(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
56 RTLIL::SigSpec sig_a
= cell
->get("\\A");
57 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
59 sig_a
.extend_u0(SIZE(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
61 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
64 static void simplemap_bitop(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
66 RTLIL::SigSpec sig_a
= cell
->get("\\A");
67 RTLIL::SigSpec sig_b
= cell
->get("\\B");
68 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
70 sig_a
.extend_u0(SIZE(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
71 sig_b
.extend_u0(SIZE(sig_y
), cell
->parameters
.at("\\B_SIGNED").as_bool());
73 if (cell
->type
== "$xnor")
75 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, SIZE(sig_y
));
77 for (int i
= 0; i
< SIZE(sig_y
); i
++) {
78 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_INV_");
79 gate
->set("\\A", sig_t
[i
]);
80 gate
->set("\\Y", sig_y
[i
]);
86 std::string gate_type
;
87 if (cell
->type
== "$and") gate_type
= "$_AND_";
88 if (cell
->type
== "$or") gate_type
= "$_OR_";
89 if (cell
->type
== "$xor") gate_type
= "$_XOR_";
90 if (cell
->type
== "$xnor") gate_type
= "$_XOR_";
91 log_assert(!gate_type
.empty());
93 for (int i
= 0; i
< SIZE(sig_y
); i
++) {
94 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
95 gate
->set("\\A", sig_a
[i
]);
96 gate
->set("\\B", sig_b
[i
]);
97 gate
->set("\\Y", sig_y
[i
]);
101 static void simplemap_reduce(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
103 RTLIL::SigSpec sig_a
= cell
->get("\\A");
104 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
106 if (sig_y
.size() == 0)
109 if (sig_a
.size() == 0) {
110 if (cell
->type
== "$reduce_and") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.size())));
111 if (cell
->type
== "$reduce_or") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
112 if (cell
->type
== "$reduce_xor") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
113 if (cell
->type
== "$reduce_xnor") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.size())));
114 if (cell
->type
== "$reduce_bool") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
118 if (sig_y
.size() > 1) {
119 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
120 sig_y
= sig_y
.extract(0, 1);
123 std::string gate_type
;
124 if (cell
->type
== "$reduce_and") gate_type
= "$_AND_";
125 if (cell
->type
== "$reduce_or") gate_type
= "$_OR_";
126 if (cell
->type
== "$reduce_xor") gate_type
= "$_XOR_";
127 if (cell
->type
== "$reduce_xnor") gate_type
= "$_XOR_";
128 if (cell
->type
== "$reduce_bool") gate_type
= "$_OR_";
129 log_assert(!gate_type
.empty());
131 RTLIL::Cell
*last_output_cell
= NULL
;
133 while (sig_a
.size() > 1)
135 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig_a
.size() / 2);
137 for (int i
= 0; i
< sig_a
.size(); i
+= 2)
139 if (i
+1 == sig_a
.size()) {
140 sig_t
.append(sig_a
[i
]);
144 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
145 gate
->set("\\A", sig_a
[i
]);
146 gate
->set("\\B", sig_a
[i
+1]);
147 gate
->set("\\Y", sig_t
[i
/2]);
148 last_output_cell
= gate
;
154 if (cell
->type
== "$reduce_xnor") {
155 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
);
156 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_INV_");
157 gate
->set("\\A", sig_a
);
158 gate
->set("\\Y", sig_t
);
159 last_output_cell
= gate
;
163 if (last_output_cell
== NULL
) {
164 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
166 last_output_cell
->set("\\Y", sig_y
);
170 static void logic_reduce(RTLIL::Module
*module
, RTLIL::SigSpec
&sig
)
172 while (sig
.size() > 1)
174 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig
.size() / 2);
176 for (int i
= 0; i
< sig
.size(); i
+= 2)
178 if (i
+1 == sig
.size()) {
179 sig_t
.append(sig
[i
]);
183 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_OR_");
184 gate
->set("\\A", sig
[i
]);
185 gate
->set("\\B", sig
[i
+1]);
186 gate
->set("\\Y", sig_t
[i
/2]);
193 sig
= RTLIL::SigSpec(0, 1);
196 static void simplemap_lognot(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
198 RTLIL::SigSpec sig_a
= cell
->get("\\A");
199 logic_reduce(module
, sig_a
);
201 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
203 if (sig_y
.size() == 0)
206 if (sig_y
.size() > 1) {
207 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
208 sig_y
= sig_y
.extract(0, 1);
211 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_INV_");
212 gate
->set("\\A", sig_a
);
213 gate
->set("\\Y", sig_y
);
216 static void simplemap_logbin(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
218 RTLIL::SigSpec sig_a
= cell
->get("\\A");
219 logic_reduce(module
, sig_a
);
221 RTLIL::SigSpec sig_b
= cell
->get("\\B");
222 logic_reduce(module
, sig_b
);
224 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
226 if (sig_y
.size() == 0)
229 if (sig_y
.size() > 1) {
230 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
231 sig_y
= sig_y
.extract(0, 1);
234 std::string gate_type
;
235 if (cell
->type
== "$logic_and") gate_type
= "$_AND_";
236 if (cell
->type
== "$logic_or") gate_type
= "$_OR_";
237 log_assert(!gate_type
.empty());
239 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
240 gate
->set("\\A", sig_a
);
241 gate
->set("\\B", sig_b
);
242 gate
->set("\\Y", sig_y
);
245 static void simplemap_mux(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
247 RTLIL::SigSpec sig_a
= cell
->get("\\A");
248 RTLIL::SigSpec sig_b
= cell
->get("\\B");
249 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
251 for (int i
= 0; i
< SIZE(sig_y
); i
++) {
252 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_MUX_");
253 gate
->set("\\A", sig_a
[i
]);
254 gate
->set("\\B", sig_b
[i
]);
255 gate
->set("\\S", cell
->get("\\S"));
256 gate
->set("\\Y", sig_y
[i
]);
260 static void simplemap_slice(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
262 int offset
= cell
->parameters
.at("\\OFFSET").as_int();
263 RTLIL::SigSpec sig_a
= cell
->get("\\A");
264 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
265 module
->connect(RTLIL::SigSig(sig_y
, sig_a
.extract(offset
, sig_y
.size())));
268 static void simplemap_concat(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
270 RTLIL::SigSpec sig_ab
= cell
->get("\\A");
271 sig_ab
.append(cell
->get("\\B"));
272 RTLIL::SigSpec sig_y
= cell
->get("\\Y");
273 module
->connect(RTLIL::SigSig(sig_y
, sig_ab
));
276 static void simplemap_sr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
278 int width
= cell
->parameters
.at("\\WIDTH").as_int();
279 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
280 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
282 RTLIL::SigSpec sig_s
= cell
->get("\\SET");
283 RTLIL::SigSpec sig_r
= cell
->get("\\CLR");
284 RTLIL::SigSpec sig_q
= cell
->get("\\Q");
286 std::string gate_type
= stringf("$_SR_%c%c_", set_pol
, clr_pol
);
288 for (int i
= 0; i
< width
; i
++) {
289 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
290 gate
->set("\\S", sig_s
[i
]);
291 gate
->set("\\R", sig_r
[i
]);
292 gate
->set("\\Q", sig_q
[i
]);
296 static void simplemap_dff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
298 int width
= cell
->parameters
.at("\\WIDTH").as_int();
299 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
301 RTLIL::SigSpec sig_clk
= cell
->get("\\CLK");
302 RTLIL::SigSpec sig_d
= cell
->get("\\D");
303 RTLIL::SigSpec sig_q
= cell
->get("\\Q");
305 std::string gate_type
= stringf("$_DFF_%c_", clk_pol
);
307 for (int i
= 0; i
< width
; i
++) {
308 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
309 gate
->set("\\C", sig_clk
);
310 gate
->set("\\D", sig_d
[i
]);
311 gate
->set("\\Q", sig_q
[i
]);
315 static void simplemap_dffsr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
317 int width
= cell
->parameters
.at("\\WIDTH").as_int();
318 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
319 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
320 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
322 RTLIL::SigSpec sig_clk
= cell
->get("\\CLK");
323 RTLIL::SigSpec sig_s
= cell
->get("\\SET");
324 RTLIL::SigSpec sig_r
= cell
->get("\\CLR");
325 RTLIL::SigSpec sig_d
= cell
->get("\\D");
326 RTLIL::SigSpec sig_q
= cell
->get("\\Q");
328 std::string gate_type
= stringf("$_DFFSR_%c%c%c_", clk_pol
, set_pol
, clr_pol
);
330 for (int i
= 0; i
< width
; i
++) {
331 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
332 gate
->set("\\C", sig_clk
);
333 gate
->set("\\S", sig_s
[i
]);
334 gate
->set("\\R", sig_r
[i
]);
335 gate
->set("\\D", sig_d
[i
]);
336 gate
->set("\\Q", sig_q
[i
]);
340 static void simplemap_adff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
342 int width
= cell
->parameters
.at("\\WIDTH").as_int();
343 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
344 char rst_pol
= cell
->parameters
.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
346 std::vector
<RTLIL::State
> rst_val
= cell
->parameters
.at("\\ARST_VALUE").bits
;
347 while (int(rst_val
.size()) < width
)
348 rst_val
.push_back(RTLIL::State::S0
);
350 RTLIL::SigSpec sig_clk
= cell
->get("\\CLK");
351 RTLIL::SigSpec sig_rst
= cell
->get("\\ARST");
352 RTLIL::SigSpec sig_d
= cell
->get("\\D");
353 RTLIL::SigSpec sig_q
= cell
->get("\\Q");
355 std::string gate_type_0
= stringf("$_DFF_%c%c0_", clk_pol
, rst_pol
);
356 std::string gate_type_1
= stringf("$_DFF_%c%c1_", clk_pol
, rst_pol
);
358 for (int i
= 0; i
< width
; i
++) {
359 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, rst_val
.at(i
) == RTLIL::State::S1
? gate_type_1
: gate_type_0
);
360 gate
->set("\\C", sig_clk
);
361 gate
->set("\\R", sig_rst
);
362 gate
->set("\\D", sig_d
[i
]);
363 gate
->set("\\Q", sig_q
[i
]);
367 static void simplemap_dlatch(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
369 int width
= cell
->parameters
.at("\\WIDTH").as_int();
370 char en_pol
= cell
->parameters
.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
372 RTLIL::SigSpec sig_en
= cell
->get("\\EN");
373 RTLIL::SigSpec sig_d
= cell
->get("\\D");
374 RTLIL::SigSpec sig_q
= cell
->get("\\Q");
376 std::string gate_type
= stringf("$_DLATCH_%c_", en_pol
);
378 for (int i
= 0; i
< width
; i
++) {
379 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
380 gate
->set("\\E", sig_en
);
381 gate
->set("\\D", sig_d
[i
]);
382 gate
->set("\\Q", sig_q
[i
]);
386 void simplemap_get_mappers(std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
)
388 mappers
["$not"] = simplemap_not
;
389 mappers
["$pos"] = simplemap_pos
;
390 mappers
["$bu0"] = simplemap_bu0
;
391 mappers
["$and"] = simplemap_bitop
;
392 mappers
["$or"] = simplemap_bitop
;
393 mappers
["$xor"] = simplemap_bitop
;
394 mappers
["$xnor"] = simplemap_bitop
;
395 mappers
["$reduce_and"] = simplemap_reduce
;
396 mappers
["$reduce_or"] = simplemap_reduce
;
397 mappers
["$reduce_xor"] = simplemap_reduce
;
398 mappers
["$reduce_xnor"] = simplemap_reduce
;
399 mappers
["$reduce_bool"] = simplemap_reduce
;
400 mappers
["$logic_not"] = simplemap_lognot
;
401 mappers
["$logic_and"] = simplemap_logbin
;
402 mappers
["$logic_or"] = simplemap_logbin
;
403 mappers
["$mux"] = simplemap_mux
;
404 mappers
["$slice"] = simplemap_slice
;
405 mappers
["$concat"] = simplemap_concat
;
406 mappers
["$sr"] = simplemap_sr
;
407 mappers
["$dff"] = simplemap_dff
;
408 mappers
["$dffsr"] = simplemap_dffsr
;
409 mappers
["$adff"] = simplemap_adff
;
410 mappers
["$dlatch"] = simplemap_dlatch
;
413 struct SimplemapPass
: public Pass
{
414 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
417 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
419 log(" simplemap [selection]\n");
421 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
422 log("primitives. The following internal cell types are mapped by this pass:\n");
424 log(" $not, $pos, $bu0, $and, $or, $xor, $xnor\n");
425 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
426 log(" $logic_not, $logic_and, $logic_or, $mux\n");
427 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
430 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
432 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
433 extra_args(args
, 1, design
);
435 std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> mappers
;
436 simplemap_get_mappers(mappers
);
438 for (auto &mod_it
: design
->modules_
) {
439 if (!design
->selected(mod_it
.second
))
441 std::vector
<RTLIL::Cell
*> delete_cells
;
442 for (auto &cell_it
: mod_it
.second
->cells_
) {
443 if (mappers
.count(cell_it
.second
->type
) == 0)
445 if (!design
->selected(mod_it
.second
, cell_it
.second
))
447 log("Mapping %s.%s (%s).\n", RTLIL::id2cstr(mod_it
.first
), RTLIL::id2cstr(cell_it
.first
), RTLIL::id2cstr(cell_it
.second
->type
));
448 mappers
.at(cell_it
.second
->type
)(mod_it
.second
, cell_it
.second
);
449 delete_cells
.push_back(cell_it
.second
);
451 for (auto c
: delete_cells
)
452 mod_it
.second
->remove(c
);