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 int width
= cell
->parameters
.at("\\Y_WIDTH").as_int();
34 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
35 sig_a
.extend(width
, cell
->parameters
.at("\\A_SIGNED").as_bool());
38 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
41 for (int i
= 0; i
< width
; i
++) {
42 RTLIL::Cell
*gate
= new RTLIL::Cell
;
44 gate
->type
= "$_INV_";
45 gate
->connections
["\\A"] = sig_a
.__chunks
.at(i
);
46 gate
->connections
["\\Y"] = sig_y
.__chunks
.at(i
);
51 static void simplemap_pos(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
53 int width
= cell
->parameters
.at("\\Y_WIDTH").as_int();
55 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
56 sig_a
.extend(width
, cell
->parameters
.at("\\A_SIGNED").as_bool());
58 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
60 module
->connections
.push_back(RTLIL::SigSig(sig_y
, sig_a
));
63 static void simplemap_bu0(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
65 int width
= cell
->parameters
.at("\\Y_WIDTH").as_int();
67 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
68 sig_a
.extend_u0(width
, cell
->parameters
.at("\\A_SIGNED").as_bool());
70 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
72 module
->connections
.push_back(RTLIL::SigSig(sig_y
, sig_a
));
75 static void simplemap_bitop(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
77 int width
= cell
->parameters
.at("\\Y_WIDTH").as_int();
79 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
80 sig_a
.extend_u0(width
, cell
->parameters
.at("\\A_SIGNED").as_bool());
83 RTLIL::SigSpec sig_b
= cell
->connections
.at("\\B");
84 sig_b
.extend_u0(width
, cell
->parameters
.at("\\B_SIGNED").as_bool());
87 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
90 if (cell
->type
== "$xnor")
92 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, width
);
95 for (int i
= 0; i
< width
; i
++) {
96 RTLIL::Cell
*gate
= new RTLIL::Cell
;
98 gate
->type
= "$_INV_";
99 gate
->connections
["\\A"] = sig_t
.__chunks
.at(i
);
100 gate
->connections
["\\Y"] = sig_y
.__chunks
.at(i
);
107 std::string gate_type
;
108 if (cell
->type
== "$and") gate_type
= "$_AND_";
109 if (cell
->type
== "$or") gate_type
= "$_OR_";
110 if (cell
->type
== "$xor") gate_type
= "$_XOR_";
111 if (cell
->type
== "$xnor") gate_type
= "$_XOR_";
112 log_assert(!gate_type
.empty());
114 for (int i
= 0; i
< width
; i
++) {
115 RTLIL::Cell
*gate
= new RTLIL::Cell
;
117 gate
->type
= gate_type
;
118 gate
->connections
["\\A"] = sig_a
.__chunks
.at(i
);
119 gate
->connections
["\\B"] = sig_b
.__chunks
.at(i
);
120 gate
->connections
["\\Y"] = sig_y
.__chunks
.at(i
);
125 static void simplemap_reduce(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
127 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
130 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
132 if (sig_y
.__width
== 0)
135 if (sig_a
.__width
== 0) {
136 if (cell
->type
== "$reduce_and") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.__width
)));
137 if (cell
->type
== "$reduce_or") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.__width
)));
138 if (cell
->type
== "$reduce_xor") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.__width
)));
139 if (cell
->type
== "$reduce_xnor") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.__width
)));
140 if (cell
->type
== "$reduce_bool") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.__width
)));
144 if (sig_y
.__width
> 1) {
145 module
->connections
.push_back(RTLIL::SigSig(sig_y
.extract(1, sig_y
.__width
-1), RTLIL::SigSpec(0, sig_y
.__width
-1)));
146 sig_y
= sig_y
.extract(0, 1);
149 std::string gate_type
;
150 if (cell
->type
== "$reduce_and") gate_type
= "$_AND_";
151 if (cell
->type
== "$reduce_or") gate_type
= "$_OR_";
152 if (cell
->type
== "$reduce_xor") gate_type
= "$_XOR_";
153 if (cell
->type
== "$reduce_xnor") gate_type
= "$_XOR_";
154 if (cell
->type
== "$reduce_bool") gate_type
= "$_OR_";
155 log_assert(!gate_type
.empty());
157 RTLIL::SigSpec
*last_output
= NULL
;
159 while (sig_a
.__width
> 1)
161 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig_a
.__width
/ 2);
164 for (int i
= 0; i
< sig_a
.__width
; i
+= 2)
166 if (i
+1 == sig_a
.__width
) {
167 sig_t
.append(sig_a
.__chunks
.at(i
));
171 RTLIL::Cell
*gate
= new RTLIL::Cell
;
173 gate
->type
= gate_type
;
174 gate
->connections
["\\A"] = sig_a
.__chunks
.at(i
);
175 gate
->connections
["\\B"] = sig_a
.__chunks
.at(i
+1);
176 gate
->connections
["\\Y"] = sig_t
.__chunks
.at(i
/2);
177 last_output
= &gate
->connections
["\\Y"];
184 if (cell
->type
== "$reduce_xnor") {
185 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
);
186 RTLIL::Cell
*gate
= new RTLIL::Cell
;
188 gate
->type
= "$_INV_";
189 gate
->connections
["\\A"] = sig_a
;
190 gate
->connections
["\\Y"] = sig_t
;
191 last_output
= &gate
->connections
["\\Y"];
196 if (last_output
== NULL
) {
197 module
->connections
.push_back(RTLIL::SigSig(sig_y
, sig_a
));
199 *last_output
= sig_y
;
203 static void logic_reduce(RTLIL::Module
*module
, RTLIL::SigSpec
&sig
)
207 while (sig
.__width
> 1)
209 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig
.__width
/ 2);
212 for (int i
= 0; i
< sig
.__width
; i
+= 2)
214 if (i
+1 == sig
.__width
) {
215 sig_t
.append(sig
.__chunks
.at(i
));
219 RTLIL::Cell
*gate
= new RTLIL::Cell
;
221 gate
->type
= "$_OR_";
222 gate
->connections
["\\A"] = sig
.__chunks
.at(i
);
223 gate
->connections
["\\B"] = sig
.__chunks
.at(i
+1);
224 gate
->connections
["\\Y"] = sig_t
.__chunks
.at(i
/2);
231 if (sig
.__width
== 0)
232 sig
= RTLIL::SigSpec(0, 1);
235 static void simplemap_lognot(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
237 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
238 logic_reduce(module
, sig_a
);
240 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
242 if (sig_y
.__width
== 0)
245 if (sig_y
.__width
> 1) {
246 module
->connections
.push_back(RTLIL::SigSig(sig_y
.extract(1, sig_y
.__width
-1), RTLIL::SigSpec(0, sig_y
.__width
-1)));
247 sig_y
= sig_y
.extract(0, 1);
250 RTLIL::Cell
*gate
= new RTLIL::Cell
;
252 gate
->type
= "$_INV_";
253 gate
->connections
["\\A"] = sig_a
;
254 gate
->connections
["\\Y"] = sig_y
;
258 static void simplemap_logbin(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
260 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
261 logic_reduce(module
, sig_a
);
263 RTLIL::SigSpec sig_b
= cell
->connections
.at("\\B");
264 logic_reduce(module
, sig_b
);
266 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
268 if (sig_y
.__width
== 0)
271 if (sig_y
.__width
> 1) {
272 module
->connections
.push_back(RTLIL::SigSig(sig_y
.extract(1, sig_y
.__width
-1), RTLIL::SigSpec(0, sig_y
.__width
-1)));
273 sig_y
= sig_y
.extract(0, 1);
276 std::string gate_type
;
277 if (cell
->type
== "$logic_and") gate_type
= "$_AND_";
278 if (cell
->type
== "$logic_or") gate_type
= "$_OR_";
279 log_assert(!gate_type
.empty());
281 RTLIL::Cell
*gate
= new RTLIL::Cell
;
283 gate
->type
= gate_type
;
284 gate
->connections
["\\A"] = sig_a
;
285 gate
->connections
["\\B"] = sig_b
;
286 gate
->connections
["\\Y"] = sig_y
;
290 static void simplemap_mux(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
292 int width
= cell
->parameters
.at("\\WIDTH").as_int();
294 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
297 RTLIL::SigSpec sig_b
= cell
->connections
.at("\\B");
300 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
303 for (int i
= 0; i
< width
; i
++) {
304 RTLIL::Cell
*gate
= new RTLIL::Cell
;
306 gate
->type
= "$_MUX_";
307 gate
->connections
["\\A"] = sig_a
.__chunks
.at(i
);
308 gate
->connections
["\\B"] = sig_b
.__chunks
.at(i
);
309 gate
->connections
["\\S"] = cell
->connections
.at("\\S");
310 gate
->connections
["\\Y"] = sig_y
.__chunks
.at(i
);
315 static void simplemap_slice(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
317 int offset
= cell
->parameters
.at("\\OFFSET").as_int();
318 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
319 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
320 module
->connections
.push_back(RTLIL::SigSig(sig_y
, sig_a
.extract(offset
, sig_y
.__width
)));
323 static void simplemap_concat(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
325 RTLIL::SigSpec sig_ab
= cell
->connections
.at("\\A");
326 sig_ab
.append(cell
->connections
.at("\\B"));
327 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
328 module
->connections
.push_back(RTLIL::SigSig(sig_y
, sig_ab
));
331 static void simplemap_sr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
333 int width
= cell
->parameters
.at("\\WIDTH").as_int();
334 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
335 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
337 RTLIL::SigSpec sig_s
= cell
->connections
.at("\\SET");
340 RTLIL::SigSpec sig_r
= cell
->connections
.at("\\CLR");
343 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
346 std::string gate_type
= stringf("$_SR_%c%c_", set_pol
, clr_pol
);
348 for (int i
= 0; i
< width
; i
++) {
349 RTLIL::Cell
*gate
= new RTLIL::Cell
;
351 gate
->type
= gate_type
;
352 gate
->connections
["\\S"] = sig_s
.__chunks
.at(i
);
353 gate
->connections
["\\R"] = sig_r
.__chunks
.at(i
);
354 gate
->connections
["\\Q"] = sig_q
.__chunks
.at(i
);
359 static void simplemap_dff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
361 int width
= cell
->parameters
.at("\\WIDTH").as_int();
362 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
364 RTLIL::SigSpec sig_clk
= cell
->connections
.at("\\CLK");
366 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
369 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
372 std::string gate_type
= stringf("$_DFF_%c_", clk_pol
);
374 for (int i
= 0; i
< width
; i
++) {
375 RTLIL::Cell
*gate
= new RTLIL::Cell
;
377 gate
->type
= gate_type
;
378 gate
->connections
["\\C"] = sig_clk
;
379 gate
->connections
["\\D"] = sig_d
.__chunks
.at(i
);
380 gate
->connections
["\\Q"] = sig_q
.__chunks
.at(i
);
385 static void simplemap_dffsr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
387 int width
= cell
->parameters
.at("\\WIDTH").as_int();
388 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
389 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
390 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
392 RTLIL::SigSpec sig_clk
= cell
->connections
.at("\\CLK");
394 RTLIL::SigSpec sig_s
= cell
->connections
.at("\\SET");
397 RTLIL::SigSpec sig_r
= cell
->connections
.at("\\CLR");
400 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
403 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
406 std::string gate_type
= stringf("$_DFFSR_%c%c%c_", clk_pol
, set_pol
, clr_pol
);
408 for (int i
= 0; i
< width
; i
++) {
409 RTLIL::Cell
*gate
= new RTLIL::Cell
;
411 gate
->type
= gate_type
;
412 gate
->connections
["\\C"] = sig_clk
;
413 gate
->connections
["\\S"] = sig_s
.__chunks
.at(i
);
414 gate
->connections
["\\R"] = sig_r
.__chunks
.at(i
);
415 gate
->connections
["\\D"] = sig_d
.__chunks
.at(i
);
416 gate
->connections
["\\Q"] = sig_q
.__chunks
.at(i
);
421 static void simplemap_adff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
423 int width
= cell
->parameters
.at("\\WIDTH").as_int();
424 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
425 char rst_pol
= cell
->parameters
.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
427 std::vector
<RTLIL::State
> rst_val
= cell
->parameters
.at("\\ARST_VALUE").bits
;
428 while (int(rst_val
.size()) < width
)
429 rst_val
.push_back(RTLIL::State::S0
);
431 RTLIL::SigSpec sig_clk
= cell
->connections
.at("\\CLK");
432 RTLIL::SigSpec sig_rst
= cell
->connections
.at("\\ARST");
434 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
437 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
440 std::string gate_type_0
= stringf("$_DFF_%c%c0_", clk_pol
, rst_pol
);
441 std::string gate_type_1
= stringf("$_DFF_%c%c1_", clk_pol
, rst_pol
);
443 for (int i
= 0; i
< width
; i
++) {
444 RTLIL::Cell
*gate
= new RTLIL::Cell
;
446 gate
->type
= rst_val
.at(i
) == RTLIL::State::S1
? gate_type_1
: gate_type_0
;
447 gate
->connections
["\\C"] = sig_clk
;
448 gate
->connections
["\\R"] = sig_rst
;
449 gate
->connections
["\\D"] = sig_d
.__chunks
.at(i
);
450 gate
->connections
["\\Q"] = sig_q
.__chunks
.at(i
);
455 static void simplemap_dlatch(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
457 int width
= cell
->parameters
.at("\\WIDTH").as_int();
458 char en_pol
= cell
->parameters
.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
460 RTLIL::SigSpec sig_en
= cell
->connections
.at("\\EN");
462 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
465 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
468 std::string gate_type
= stringf("$_DLATCH_%c_", en_pol
);
470 for (int i
= 0; i
< width
; i
++) {
471 RTLIL::Cell
*gate
= new RTLIL::Cell
;
473 gate
->type
= gate_type
;
474 gate
->connections
["\\E"] = sig_en
;
475 gate
->connections
["\\D"] = sig_d
.__chunks
.at(i
);
476 gate
->connections
["\\Q"] = sig_q
.__chunks
.at(i
);
481 void simplemap_get_mappers(std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
)
483 mappers
["$not"] = simplemap_not
;
484 mappers
["$pos"] = simplemap_pos
;
485 mappers
["$bu0"] = simplemap_bu0
;
486 mappers
["$and"] = simplemap_bitop
;
487 mappers
["$or"] = simplemap_bitop
;
488 mappers
["$xor"] = simplemap_bitop
;
489 mappers
["$xnor"] = simplemap_bitop
;
490 mappers
["$reduce_and"] = simplemap_reduce
;
491 mappers
["$reduce_or"] = simplemap_reduce
;
492 mappers
["$reduce_xor"] = simplemap_reduce
;
493 mappers
["$reduce_xnor"] = simplemap_reduce
;
494 mappers
["$reduce_bool"] = simplemap_reduce
;
495 mappers
["$logic_not"] = simplemap_lognot
;
496 mappers
["$logic_and"] = simplemap_logbin
;
497 mappers
["$logic_or"] = simplemap_logbin
;
498 mappers
["$mux"] = simplemap_mux
;
499 mappers
["$slice"] = simplemap_slice
;
500 mappers
["$concat"] = simplemap_concat
;
501 mappers
["$sr"] = simplemap_sr
;
502 mappers
["$dff"] = simplemap_dff
;
503 mappers
["$dffsr"] = simplemap_dffsr
;
504 mappers
["$adff"] = simplemap_adff
;
505 mappers
["$dlatch"] = simplemap_dlatch
;
508 struct SimplemapPass
: public Pass
{
509 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
512 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
514 log(" simplemap [selection]\n");
516 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
517 log("primitives. The following internal cell types are mapped by this pass:\n");
519 log(" $not, $pos, $bu0, $and, $or, $xor, $xnor\n");
520 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
521 log(" $logic_not, $logic_and, $logic_or, $mux\n");
522 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
525 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
527 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
528 extra_args(args
, 1, design
);
530 std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> mappers
;
531 simplemap_get_mappers(mappers
);
533 for (auto &mod_it
: design
->modules
) {
534 if (!design
->selected(mod_it
.second
))
536 std::vector
<RTLIL::Cell
*> delete_cells
;
537 for (auto &cell_it
: mod_it
.second
->cells
) {
538 if (mappers
.count(cell_it
.second
->type
) == 0)
540 if (!design
->selected(mod_it
.second
, cell_it
.second
))
542 log("Mapping %s.%s (%s).\n", RTLIL::id2cstr(mod_it
.first
), RTLIL::id2cstr(cell_it
.first
), RTLIL::id2cstr(cell_it
.second
->type
));
543 mappers
.at(cell_it
.second
->type
)(mod_it
.second
, cell_it
.second
);
544 delete_cells
.push_back(cell_it
.second
);
546 for (auto &it
: delete_cells
) {
547 mod_it
.second
->cells
.erase(it
->name
);