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_bitop(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(width
, cell
->parameters
.at("\\A_SIGNED").as_bool());
71 RTLIL::SigSpec sig_b
= cell
->connections
.at("\\B");
72 sig_b
.extend(width
, cell
->parameters
.at("\\B_SIGNED").as_bool());
75 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
78 if (cell
->type
== "$xnor")
80 RTLIL::SigSpec sig_t
= module
->new_wire(width
, NEW_ID
);
83 for (int i
= 0; i
< width
; i
++) {
84 RTLIL::Cell
*gate
= new RTLIL::Cell
;
86 gate
->type
= "$_INV_";
87 gate
->connections
["\\A"] = sig_t
.chunks
.at(i
);
88 gate
->connections
["\\Y"] = sig_y
.chunks
.at(i
);
95 std::string gate_type
;
96 if (cell
->type
== "$and") gate_type
= "$_AND_";
97 if (cell
->type
== "$or") gate_type
= "$_OR_";
98 if (cell
->type
== "$xor") gate_type
= "$_XOR_";
99 if (cell
->type
== "$xnor") gate_type
= "$_XOR_";
100 log_assert(!gate_type
.empty());
102 for (int i
= 0; i
< width
; i
++) {
103 RTLIL::Cell
*gate
= new RTLIL::Cell
;
105 gate
->type
= gate_type
;
106 gate
->connections
["\\A"] = sig_a
.chunks
.at(i
);
107 gate
->connections
["\\B"] = sig_b
.chunks
.at(i
);
108 gate
->connections
["\\Y"] = sig_y
.chunks
.at(i
);
113 static void simplemap_reduce(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
115 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
118 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
120 if (sig_y
.width
== 0)
123 if (sig_a
.width
== 0) {
124 if (cell
->type
== "$reduce_and") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.width
)));
125 if (cell
->type
== "$reduce_or") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.width
)));
126 if (cell
->type
== "$reduce_xor") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.width
)));
127 if (cell
->type
== "$reduce_xnor") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.width
)));
128 if (cell
->type
== "$reduce_bool") module
->connections
.push_back(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.width
)));
132 if (sig_y
.width
> 1) {
133 module
->connections
.push_back(RTLIL::SigSig(sig_y
.extract(1, sig_y
.width
-1), RTLIL::SigSpec(0, sig_y
.width
-1)));
134 sig_y
= sig_y
.extract(0, 1);
137 std::string gate_type
;
138 if (cell
->type
== "$reduce_and") gate_type
= "$_AND_";
139 if (cell
->type
== "$reduce_or") gate_type
= "$_OR_";
140 if (cell
->type
== "$reduce_xor") gate_type
= "$_XOR_";
141 if (cell
->type
== "$reduce_xnor") gate_type
= "$_XOR_";
142 if (cell
->type
== "$reduce_bool") gate_type
= "$_OR_";
143 log_assert(!gate_type
.empty());
145 RTLIL::SigSpec
*last_output
= NULL
;
147 while (sig_a
.width
> 1)
149 RTLIL::SigSpec sig_t
= module
->new_wire(sig_a
.width
/ 2, NEW_ID
);
152 for (int i
= 0; i
< sig_a
.width
; i
+= 2)
154 if (i
+1 == sig_a
.width
) {
155 sig_t
.append(sig_a
.chunks
.at(i
));
159 RTLIL::Cell
*gate
= new RTLIL::Cell
;
161 gate
->type
= gate_type
;
162 gate
->connections
["\\A"] = sig_a
.chunks
.at(i
);
163 gate
->connections
["\\B"] = sig_a
.chunks
.at(i
+1);
164 gate
->connections
["\\Y"] = sig_t
.chunks
.at(i
/2);
165 last_output
= &gate
->connections
["\\Y"];
172 if (cell
->type
== "$reduce_xnor") {
173 RTLIL::SigSpec sig_t
= module
->new_wire(1, NEW_ID
);
174 RTLIL::Cell
*gate
= new RTLIL::Cell
;
176 gate
->type
= "$_INV_";
177 gate
->connections
["\\A"] = sig_a
;
178 gate
->connections
["\\Y"] = sig_t
;
179 last_output
= &gate
->connections
["\\Y"];
184 if (last_output
== NULL
) {
185 module
->connections
.push_back(RTLIL::SigSig(sig_y
, sig_a
));
187 *last_output
= sig_y
;
191 static void logic_reduce(RTLIL::Module
*module
, RTLIL::SigSpec
&sig
)
195 while (sig
.width
> 1)
197 RTLIL::SigSpec sig_t
= module
->new_wire(sig
.width
/ 2, NEW_ID
);
200 for (int i
= 0; i
< sig
.width
; i
+= 2)
202 if (i
+1 == sig
.width
) {
203 sig_t
.append(sig
.chunks
.at(i
));
207 RTLIL::Cell
*gate
= new RTLIL::Cell
;
209 gate
->type
= "$_OR_";
210 gate
->connections
["\\A"] = sig
.chunks
.at(i
);
211 gate
->connections
["\\B"] = sig
.chunks
.at(i
+1);
212 gate
->connections
["\\Y"] = sig_t
.chunks
.at(i
/2);
220 sig
= RTLIL::SigSpec(0, 1);
223 static void simplemap_lognot(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
225 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
226 logic_reduce(module
, sig_a
);
228 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
230 if (sig_y
.width
== 0)
233 if (sig_y
.width
> 1) {
234 module
->connections
.push_back(RTLIL::SigSig(sig_y
.extract(1, sig_y
.width
-1), RTLIL::SigSpec(0, sig_y
.width
-1)));
235 sig_y
= sig_y
.extract(0, 1);
238 RTLIL::Cell
*gate
= new RTLIL::Cell
;
240 gate
->type
= "$_INV_";
241 gate
->connections
["\\A"] = sig_a
;
242 gate
->connections
["\\Y"] = sig_y
;
246 static void simplemap_logbin(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
248 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
249 logic_reduce(module
, sig_a
);
251 RTLIL::SigSpec sig_b
= cell
->connections
.at("\\B");
252 logic_reduce(module
, sig_b
);
254 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
256 if (sig_y
.width
== 0)
259 if (sig_y
.width
> 1) {
260 module
->connections
.push_back(RTLIL::SigSig(sig_y
.extract(1, sig_y
.width
-1), RTLIL::SigSpec(0, sig_y
.width
-1)));
261 sig_y
= sig_y
.extract(0, 1);
264 std::string gate_type
;
265 if (cell
->type
== "$logic_and") gate_type
= "$_AND_";
266 if (cell
->type
== "$logic_or") gate_type
= "$_OR_";
267 log_assert(!gate_type
.empty());
269 RTLIL::Cell
*gate
= new RTLIL::Cell
;
271 gate
->type
= gate_type
;
272 gate
->connections
["\\A"] = sig_a
;
273 gate
->connections
["\\B"] = sig_b
;
274 gate
->connections
["\\Y"] = sig_y
;
278 static void simplemap_mux(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
280 int width
= cell
->parameters
.at("\\WIDTH").as_int();
282 RTLIL::SigSpec sig_a
= cell
->connections
.at("\\A");
285 RTLIL::SigSpec sig_b
= cell
->connections
.at("\\B");
288 RTLIL::SigSpec sig_y
= cell
->connections
.at("\\Y");
291 for (int i
= 0; i
< width
; i
++) {
292 RTLIL::Cell
*gate
= new RTLIL::Cell
;
294 gate
->type
= "$_MUX_";
295 gate
->connections
["\\A"] = sig_a
.chunks
.at(i
);
296 gate
->connections
["\\B"] = sig_b
.chunks
.at(i
);
297 gate
->connections
["\\S"] = cell
->connections
.at("\\S");
298 gate
->connections
["\\Y"] = sig_y
.chunks
.at(i
);
303 static void simplemap_sr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
305 int width
= cell
->parameters
.at("\\WIDTH").as_int();
306 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
307 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
309 RTLIL::SigSpec sig_s
= cell
->connections
.at("\\SET");
312 RTLIL::SigSpec sig_r
= cell
->connections
.at("\\CLR");
315 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
318 std::string gate_type
= stringf("$_SR_%c%c_", set_pol
, clr_pol
);
320 for (int i
= 0; i
< width
; i
++) {
321 RTLIL::Cell
*gate
= new RTLIL::Cell
;
323 gate
->type
= gate_type
;
324 gate
->connections
["\\S"] = sig_s
.chunks
.at(i
);
325 gate
->connections
["\\R"] = sig_r
.chunks
.at(i
);
326 gate
->connections
["\\Q"] = sig_q
.chunks
.at(i
);
331 static void simplemap_dff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
333 int width
= cell
->parameters
.at("\\WIDTH").as_int();
334 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
336 RTLIL::SigSpec sig_clk
= cell
->connections
.at("\\CLK");
338 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
341 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
344 std::string gate_type
= stringf("$_DFF_%c_", clk_pol
);
346 for (int i
= 0; i
< width
; i
++) {
347 RTLIL::Cell
*gate
= new RTLIL::Cell
;
349 gate
->type
= gate_type
;
350 gate
->connections
["\\C"] = sig_clk
;
351 gate
->connections
["\\D"] = sig_d
.chunks
.at(i
);
352 gate
->connections
["\\Q"] = sig_q
.chunks
.at(i
);
357 static void simplemap_dffsr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
359 int width
= cell
->parameters
.at("\\WIDTH").as_int();
360 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
361 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
362 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
364 RTLIL::SigSpec sig_clk
= cell
->connections
.at("\\CLK");
366 RTLIL::SigSpec sig_s
= cell
->connections
.at("\\SET");
369 RTLIL::SigSpec sig_r
= cell
->connections
.at("\\CLR");
372 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
375 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
378 std::string gate_type
= stringf("$_DFFSR_%c%c%c_", clk_pol
, set_pol
, clr_pol
);
380 for (int i
= 0; i
< width
; i
++) {
381 RTLIL::Cell
*gate
= new RTLIL::Cell
;
383 gate
->type
= gate_type
;
384 gate
->connections
["\\C"] = sig_clk
;
385 gate
->connections
["\\S"] = sig_s
.chunks
.at(i
);
386 gate
->connections
["\\R"] = sig_r
.chunks
.at(i
);
387 gate
->connections
["\\D"] = sig_d
.chunks
.at(i
);
388 gate
->connections
["\\Q"] = sig_q
.chunks
.at(i
);
393 static void simplemap_adff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
395 int width
= cell
->parameters
.at("\\WIDTH").as_int();
396 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
397 char rst_pol
= cell
->parameters
.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
399 std::vector
<RTLIL::State
> rst_val
= cell
->parameters
.at("\\ARST_VALUE").bits
;
400 while (int(rst_val
.size()) < width
)
401 rst_val
.push_back(RTLIL::State::S0
);
403 RTLIL::SigSpec sig_clk
= cell
->connections
.at("\\CLK");
404 RTLIL::SigSpec sig_rst
= cell
->connections
.at("\\ARST");
406 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
409 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
412 std::string gate_type_0
= stringf("$_DFF_%c%c0_", clk_pol
, rst_pol
);
413 std::string gate_type_1
= stringf("$_DFF_%c%c1_", clk_pol
, rst_pol
);
415 for (int i
= 0; i
< width
; i
++) {
416 RTLIL::Cell
*gate
= new RTLIL::Cell
;
418 gate
->type
= rst_val
.at(i
) == RTLIL::State::S1
? gate_type_1
: gate_type_0
;
419 gate
->connections
["\\C"] = sig_clk
;
420 gate
->connections
["\\R"] = sig_rst
;
421 gate
->connections
["\\D"] = sig_d
.chunks
.at(i
);
422 gate
->connections
["\\Q"] = sig_q
.chunks
.at(i
);
427 static void simplemap_dlatch(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
429 int width
= cell
->parameters
.at("\\WIDTH").as_int();
430 char en_pol
= cell
->parameters
.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
432 RTLIL::SigSpec sig_en
= cell
->connections
.at("\\EN");
434 RTLIL::SigSpec sig_d
= cell
->connections
.at("\\D");
437 RTLIL::SigSpec sig_q
= cell
->connections
.at("\\Q");
440 std::string gate_type
= stringf("$_DLATCH_%c_", en_pol
);
442 for (int i
= 0; i
< width
; i
++) {
443 RTLIL::Cell
*gate
= new RTLIL::Cell
;
445 gate
->type
= gate_type
;
446 gate
->connections
["\\E"] = sig_en
;
447 gate
->connections
["\\D"] = sig_d
.chunks
.at(i
);
448 gate
->connections
["\\Q"] = sig_q
.chunks
.at(i
);
453 void simplemap_get_mappers(std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
)
455 mappers
["$not"] = simplemap_not
;
456 mappers
["$pos"] = simplemap_pos
;
457 mappers
["$and"] = simplemap_bitop
;
458 mappers
["$or"] = simplemap_bitop
;
459 mappers
["$xor"] = simplemap_bitop
;
460 mappers
["$xnor"] = simplemap_bitop
;
461 mappers
["$reduce_and"] = simplemap_reduce
;
462 mappers
["$reduce_or"] = simplemap_reduce
;
463 mappers
["$reduce_xor"] = simplemap_reduce
;
464 mappers
["$reduce_xnor"] = simplemap_reduce
;
465 mappers
["$reduce_bool"] = simplemap_reduce
;
466 mappers
["$logic_not"] = simplemap_lognot
;
467 mappers
["$logic_and"] = simplemap_logbin
;
468 mappers
["$logic_or"] = simplemap_logbin
;
469 mappers
["$mux"] = simplemap_mux
;
470 mappers
["$sr"] = simplemap_sr
;
471 mappers
["$dff"] = simplemap_dff
;
472 mappers
["$dffsr"] = simplemap_dffsr
;
473 mappers
["$adff"] = simplemap_adff
;
474 mappers
["$dlatch"] = simplemap_dlatch
;
477 struct SimplemapPass
: public Pass
{
478 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
481 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
483 log(" simplemap [selection]\n");
485 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
486 log("primitives. The following internal cell types are mapped by this pass:\n");
488 log(" $not, $pos, $and, $or, $xor, $xnor\n");
489 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
490 log(" $logic_not, $logic_and, $logic_or, $mux\n");
491 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
494 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
496 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
497 extra_args(args
, 1, design
);
499 std::map
<std::string
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> mappers
;
500 simplemap_get_mappers(mappers
);
502 for (auto &mod_it
: design
->modules
) {
503 if (!design
->selected(mod_it
.second
))
505 std::vector
<RTLIL::Cell
*> delete_cells
;
506 for (auto &cell_it
: mod_it
.second
->cells
) {
507 if (mappers
.count(cell_it
.second
->type
) == 0)
509 if (!design
->selected(mod_it
.second
, cell_it
.second
))
511 log("Mapping %s.%s (%s).\n", RTLIL::id2cstr(mod_it
.first
), RTLIL::id2cstr(cell_it
.first
), RTLIL::id2cstr(cell_it
.second
->type
));
512 mappers
.at(cell_it
.second
->type
)(mod_it
.second
, cell_it
.second
);
513 delete_cells
.push_back(cell_it
.second
);
515 for (auto &it
: delete_cells
) {
516 mod_it
.second
->cells
.erase(it
->name
);