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 "simplemap.h"
21 #include "kernel/sigtools.h"
29 void simplemap_not(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
31 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
32 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
34 sig_a
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
36 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
37 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
38 gate
->setPort("\\A", sig_a
[i
]);
39 gate
->setPort("\\Y", sig_y
[i
]);
43 void simplemap_pos(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
45 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
46 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
48 sig_a
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
50 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
53 void simplemap_bitop(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
55 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
56 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
57 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
59 sig_a
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
60 sig_b
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\B_SIGNED").as_bool());
62 if (cell
->type
== "$xnor")
64 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, GetSize(sig_y
));
66 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
67 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
68 gate
->setPort("\\A", sig_t
[i
]);
69 gate
->setPort("\\Y", sig_y
[i
]);
75 std::string gate_type
;
76 if (cell
->type
== "$and") gate_type
= "$_AND_";
77 if (cell
->type
== "$or") gate_type
= "$_OR_";
78 if (cell
->type
== "$xor") gate_type
= "$_XOR_";
79 if (cell
->type
== "$xnor") gate_type
= "$_XOR_";
80 log_assert(!gate_type
.empty());
82 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
83 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
84 gate
->setPort("\\A", sig_a
[i
]);
85 gate
->setPort("\\B", sig_b
[i
]);
86 gate
->setPort("\\Y", sig_y
[i
]);
90 void simplemap_reduce(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
92 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
93 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
95 if (sig_y
.size() == 0)
98 if (sig_a
.size() == 0) {
99 if (cell
->type
== "$reduce_and") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.size())));
100 if (cell
->type
== "$reduce_or") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
101 if (cell
->type
== "$reduce_xor") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
102 if (cell
->type
== "$reduce_xnor") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.size())));
103 if (cell
->type
== "$reduce_bool") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
107 if (sig_y
.size() > 1) {
108 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
109 sig_y
= sig_y
.extract(0, 1);
112 std::string gate_type
;
113 if (cell
->type
== "$reduce_and") gate_type
= "$_AND_";
114 if (cell
->type
== "$reduce_or") gate_type
= "$_OR_";
115 if (cell
->type
== "$reduce_xor") gate_type
= "$_XOR_";
116 if (cell
->type
== "$reduce_xnor") gate_type
= "$_XOR_";
117 if (cell
->type
== "$reduce_bool") gate_type
= "$_OR_";
118 log_assert(!gate_type
.empty());
120 RTLIL::Cell
*last_output_cell
= NULL
;
122 while (sig_a
.size() > 1)
124 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig_a
.size() / 2);
126 for (int i
= 0; i
< sig_a
.size(); i
+= 2)
128 if (i
+1 == sig_a
.size()) {
129 sig_t
.append(sig_a
[i
]);
133 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
134 gate
->setPort("\\A", sig_a
[i
]);
135 gate
->setPort("\\B", sig_a
[i
+1]);
136 gate
->setPort("\\Y", sig_t
[i
/2]);
137 last_output_cell
= gate
;
143 if (cell
->type
== "$reduce_xnor") {
144 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
);
145 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
146 gate
->setPort("\\A", sig_a
);
147 gate
->setPort("\\Y", sig_t
);
148 last_output_cell
= gate
;
152 if (last_output_cell
== NULL
) {
153 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
155 last_output_cell
->setPort("\\Y", sig_y
);
159 static void logic_reduce(RTLIL::Module
*module
, RTLIL::SigSpec
&sig
)
161 while (sig
.size() > 1)
163 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig
.size() / 2);
165 for (int i
= 0; i
< sig
.size(); i
+= 2)
167 if (i
+1 == sig
.size()) {
168 sig_t
.append(sig
[i
]);
172 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_OR_");
173 gate
->setPort("\\A", sig
[i
]);
174 gate
->setPort("\\B", sig
[i
+1]);
175 gate
->setPort("\\Y", sig_t
[i
/2]);
182 sig
= RTLIL::SigSpec(0, 1);
185 void simplemap_lognot(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
187 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
188 logic_reduce(module
, sig_a
);
190 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
192 if (sig_y
.size() == 0)
195 if (sig_y
.size() > 1) {
196 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
197 sig_y
= sig_y
.extract(0, 1);
200 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
201 gate
->setPort("\\A", sig_a
);
202 gate
->setPort("\\Y", sig_y
);
205 void simplemap_logbin(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
207 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
208 logic_reduce(module
, sig_a
);
210 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
211 logic_reduce(module
, sig_b
);
213 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
215 if (sig_y
.size() == 0)
218 if (sig_y
.size() > 1) {
219 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
220 sig_y
= sig_y
.extract(0, 1);
223 std::string gate_type
;
224 if (cell
->type
== "$logic_and") gate_type
= "$_AND_";
225 if (cell
->type
== "$logic_or") gate_type
= "$_OR_";
226 log_assert(!gate_type
.empty());
228 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
229 gate
->setPort("\\A", sig_a
);
230 gate
->setPort("\\B", sig_b
);
231 gate
->setPort("\\Y", sig_y
);
234 void simplemap_eqne(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
236 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
237 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
238 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
239 bool is_signed
= cell
->parameters
.at("\\A_SIGNED").as_bool();
240 bool is_ne
= cell
->type
== "$ne" || cell
->type
== "$nex";
242 RTLIL::SigSpec xor_out
= module
->addWire(NEW_ID
, std::max(GetSize(sig_a
), GetSize(sig_b
)));
243 RTLIL::Cell
*xor_cell
= module
->addXor(NEW_ID
, sig_a
, sig_b
, xor_out
, is_signed
);
244 simplemap_bitop(module
, xor_cell
);
245 module
->remove(xor_cell
);
247 RTLIL::SigSpec reduce_out
= is_ne
? sig_y
: module
->addWire(NEW_ID
);
248 RTLIL::Cell
*reduce_cell
= module
->addReduceOr(NEW_ID
, xor_out
, reduce_out
);
249 simplemap_reduce(module
, reduce_cell
);
250 module
->remove(reduce_cell
);
253 RTLIL::Cell
*not_cell
= module
->addLogicNot(NEW_ID
, reduce_out
, sig_y
);
254 simplemap_lognot(module
, not_cell
);
255 module
->remove(not_cell
);
259 void simplemap_mux(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
261 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
262 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
263 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
265 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
266 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_MUX_");
267 gate
->setPort("\\A", sig_a
[i
]);
268 gate
->setPort("\\B", sig_b
[i
]);
269 gate
->setPort("\\S", cell
->getPort("\\S"));
270 gate
->setPort("\\Y", sig_y
[i
]);
274 void simplemap_slice(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
276 int offset
= cell
->parameters
.at("\\OFFSET").as_int();
277 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
278 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
279 module
->connect(RTLIL::SigSig(sig_y
, sig_a
.extract(offset
, sig_y
.size())));
282 void simplemap_concat(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
284 RTLIL::SigSpec sig_ab
= cell
->getPort("\\A");
285 sig_ab
.append(cell
->getPort("\\B"));
286 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
287 module
->connect(RTLIL::SigSig(sig_y
, sig_ab
));
290 void simplemap_sr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
292 int width
= cell
->parameters
.at("\\WIDTH").as_int();
293 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
294 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
296 RTLIL::SigSpec sig_s
= cell
->getPort("\\SET");
297 RTLIL::SigSpec sig_r
= cell
->getPort("\\CLR");
298 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
300 std::string gate_type
= stringf("$_SR_%c%c_", set_pol
, clr_pol
);
302 for (int i
= 0; i
< width
; i
++) {
303 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
304 gate
->setPort("\\S", sig_s
[i
]);
305 gate
->setPort("\\R", sig_r
[i
]);
306 gate
->setPort("\\Q", sig_q
[i
]);
310 void simplemap_dff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
312 int width
= cell
->parameters
.at("\\WIDTH").as_int();
313 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
315 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
316 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
317 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
319 std::string gate_type
= stringf("$_DFF_%c_", clk_pol
);
321 for (int i
= 0; i
< width
; i
++) {
322 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
323 gate
->setPort("\\C", sig_clk
);
324 gate
->setPort("\\D", sig_d
[i
]);
325 gate
->setPort("\\Q", sig_q
[i
]);
329 void simplemap_dffe(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
331 int width
= cell
->parameters
.at("\\WIDTH").as_int();
332 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
333 char en_pol
= cell
->parameters
.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
335 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
336 RTLIL::SigSpec sig_en
= cell
->getPort("\\EN");
337 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
338 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
340 std::string gate_type
= stringf("$_DFFE_%c%c_", clk_pol
, en_pol
);
342 for (int i
= 0; i
< width
; i
++) {
343 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
344 gate
->setPort("\\C", sig_clk
);
345 gate
->setPort("\\E", sig_en
);
346 gate
->setPort("\\D", sig_d
[i
]);
347 gate
->setPort("\\Q", sig_q
[i
]);
351 void simplemap_dffsr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
353 int width
= cell
->parameters
.at("\\WIDTH").as_int();
354 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
355 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
356 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
358 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
359 RTLIL::SigSpec sig_s
= cell
->getPort("\\SET");
360 RTLIL::SigSpec sig_r
= cell
->getPort("\\CLR");
361 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
362 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
364 std::string gate_type
= stringf("$_DFFSR_%c%c%c_", clk_pol
, set_pol
, clr_pol
);
366 for (int i
= 0; i
< width
; i
++) {
367 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
368 gate
->setPort("\\C", sig_clk
);
369 gate
->setPort("\\S", sig_s
[i
]);
370 gate
->setPort("\\R", sig_r
[i
]);
371 gate
->setPort("\\D", sig_d
[i
]);
372 gate
->setPort("\\Q", sig_q
[i
]);
376 void simplemap_adff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
378 int width
= cell
->parameters
.at("\\WIDTH").as_int();
379 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
380 char rst_pol
= cell
->parameters
.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
382 std::vector
<RTLIL::State
> rst_val
= cell
->parameters
.at("\\ARST_VALUE").bits
;
383 while (int(rst_val
.size()) < width
)
384 rst_val
.push_back(RTLIL::State::S0
);
386 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
387 RTLIL::SigSpec sig_rst
= cell
->getPort("\\ARST");
388 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
389 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
391 std::string gate_type_0
= stringf("$_DFF_%c%c0_", clk_pol
, rst_pol
);
392 std::string gate_type_1
= stringf("$_DFF_%c%c1_", clk_pol
, rst_pol
);
394 for (int i
= 0; i
< width
; i
++) {
395 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, rst_val
.at(i
) == RTLIL::State::S1
? gate_type_1
: gate_type_0
);
396 gate
->setPort("\\C", sig_clk
);
397 gate
->setPort("\\R", sig_rst
);
398 gate
->setPort("\\D", sig_d
[i
]);
399 gate
->setPort("\\Q", sig_q
[i
]);
403 void simplemap_dlatch(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
405 int width
= cell
->parameters
.at("\\WIDTH").as_int();
406 char en_pol
= cell
->parameters
.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
408 RTLIL::SigSpec sig_en
= cell
->getPort("\\EN");
409 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
410 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
412 std::string gate_type
= stringf("$_DLATCH_%c_", en_pol
);
414 for (int i
= 0; i
< width
; i
++) {
415 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
416 gate
->setPort("\\E", sig_en
);
417 gate
->setPort("\\D", sig_d
[i
]);
418 gate
->setPort("\\Q", sig_q
[i
]);
422 void simplemap_get_mappers(std::map
<RTLIL::IdString
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
)
424 mappers
["$not"] = simplemap_not
;
425 mappers
["$pos"] = simplemap_pos
;
426 mappers
["$and"] = simplemap_bitop
;
427 mappers
["$or"] = simplemap_bitop
;
428 mappers
["$xor"] = simplemap_bitop
;
429 mappers
["$xnor"] = simplemap_bitop
;
430 mappers
["$reduce_and"] = simplemap_reduce
;
431 mappers
["$reduce_or"] = simplemap_reduce
;
432 mappers
["$reduce_xor"] = simplemap_reduce
;
433 mappers
["$reduce_xnor"] = simplemap_reduce
;
434 mappers
["$reduce_bool"] = simplemap_reduce
;
435 mappers
["$logic_not"] = simplemap_lognot
;
436 mappers
["$logic_and"] = simplemap_logbin
;
437 mappers
["$logic_or"] = simplemap_logbin
;
438 mappers
["$eq"] = simplemap_eqne
;
439 mappers
["$eqx"] = simplemap_eqne
;
440 mappers
["$ne"] = simplemap_eqne
;
441 mappers
["$nex"] = simplemap_eqne
;
442 mappers
["$mux"] = simplemap_mux
;
443 mappers
["$slice"] = simplemap_slice
;
444 mappers
["$concat"] = simplemap_concat
;
445 mappers
["$sr"] = simplemap_sr
;
446 mappers
["$dff"] = simplemap_dff
;
447 mappers
["$dffe"] = simplemap_dffe
;
448 mappers
["$dffsr"] = simplemap_dffsr
;
449 mappers
["$adff"] = simplemap_adff
;
450 mappers
["$dlatch"] = simplemap_dlatch
;
453 void simplemap(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
455 static std::map
<RTLIL::IdString
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> mappers
;
456 static bool initialized_mappers
= false;
458 if (!initialized_mappers
) {
459 simplemap_get_mappers(mappers
);
460 initialized_mappers
= true;
463 mappers
.at(cell
->type
)(module
, cell
);
467 PRIVATE_NAMESPACE_BEGIN
469 struct SimplemapPass
: public Pass
{
470 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
473 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
475 log(" simplemap [selection]\n");
477 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
478 log("primitives. The following internal cell types are mapped by this pass:\n");
480 log(" $not, $pos, $and, $or, $xor, $xnor\n");
481 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
482 log(" $logic_not, $logic_and, $logic_or, $mux\n");
483 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
486 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
488 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
489 extra_args(args
, 1, design
);
491 std::map
<RTLIL::IdString
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> mappers
;
492 simplemap_get_mappers(mappers
);
494 for (auto mod
: design
->modules()) {
495 if (!design
->selected(mod
))
497 std::vector
<RTLIL::Cell
*> cells
= mod
->cells();
498 for (auto cell
: cells
) {
499 if (mappers
.count(cell
->type
) == 0)
501 if (!design
->selected(mod
, cell
))
503 log("Mapping %s.%s (%s).\n", log_id(mod
), log_id(cell
), log_id(cell
->type
));
504 mappers
.at(cell
->type
)(mod
, cell
);
511 PRIVATE_NAMESPACE_END