Fixed undef extend for bitwise binary ops (bugs in simplemap and satgen)
[yosys.git] / passes / techmap / simplemap.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 */
19
20 #include "kernel/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/log.h"
23 #include <stdlib.h>
24 #include <assert.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 extern void simplemap_get_mappers(std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
29
30 static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
31 {
32 int width = cell->parameters.at("\\Y_WIDTH").as_int();
33
34 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
35 sig_a.extend(width, cell->parameters.at("\\A_SIGNED").as_bool());
36 sig_a.expand();
37
38 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
39 sig_y.expand();
40
41 for (int i = 0; i < width; i++) {
42 RTLIL::Cell *gate = new RTLIL::Cell;
43 gate->name = NEW_ID;
44 gate->type = "$_INV_";
45 gate->connections["\\A"] = sig_a.chunks.at(i);
46 gate->connections["\\Y"] = sig_y.chunks.at(i);
47 module->add(gate);
48 }
49 }
50
51 static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
52 {
53 int width = cell->parameters.at("\\Y_WIDTH").as_int();
54
55 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
56 sig_a.extend(width, cell->parameters.at("\\A_SIGNED").as_bool());
57
58 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
59
60 module->connections.push_back(RTLIL::SigSig(sig_y, sig_a));
61 }
62
63 static void simplemap_bu0(RTLIL::Module *module, RTLIL::Cell *cell)
64 {
65 int width = cell->parameters.at("\\Y_WIDTH").as_int();
66
67 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
68 sig_a.extend_u0(width, cell->parameters.at("\\A_SIGNED").as_bool());
69
70 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
71
72 module->connections.push_back(RTLIL::SigSig(sig_y, sig_a));
73 }
74
75 static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
76 {
77 int width = cell->parameters.at("\\Y_WIDTH").as_int();
78
79 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
80 sig_a.extend_u0(width, cell->parameters.at("\\A_SIGNED").as_bool());
81 sig_a.expand();
82
83 RTLIL::SigSpec sig_b = cell->connections.at("\\B");
84 sig_b.extend_u0(width, cell->parameters.at("\\B_SIGNED").as_bool());
85 sig_b.expand();
86
87 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
88 sig_y.expand();
89
90 if (cell->type == "$xnor")
91 {
92 RTLIL::SigSpec sig_t = module->new_wire(width, NEW_ID);
93 sig_t.expand();
94
95 for (int i = 0; i < width; i++) {
96 RTLIL::Cell *gate = new RTLIL::Cell;
97 gate->name = NEW_ID;
98 gate->type = "$_INV_";
99 gate->connections["\\A"] = sig_t.chunks.at(i);
100 gate->connections["\\Y"] = sig_y.chunks.at(i);
101 module->add(gate);
102 }
103
104 sig_y = sig_t;
105 }
106
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());
113
114 for (int i = 0; i < width; i++) {
115 RTLIL::Cell *gate = new RTLIL::Cell;
116 gate->name = NEW_ID;
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);
121 module->add(gate);
122 }
123 }
124
125 static void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
126 {
127 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
128 sig_a.expand();
129
130 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
131
132 if (sig_y.width == 0)
133 return;
134
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)));
141 return;
142 }
143
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);
147 }
148
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());
156
157 RTLIL::SigSpec *last_output = NULL;
158
159 while (sig_a.width > 1)
160 {
161 RTLIL::SigSpec sig_t = module->new_wire(sig_a.width / 2, NEW_ID);
162 sig_t.expand();
163
164 for (int i = 0; i < sig_a.width; i += 2)
165 {
166 if (i+1 == sig_a.width) {
167 sig_t.append(sig_a.chunks.at(i));
168 continue;
169 }
170
171 RTLIL::Cell *gate = new RTLIL::Cell;
172 gate->name = NEW_ID;
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"];
178 module->add(gate);
179 }
180
181 sig_a = sig_t;
182 }
183
184 if (cell->type == "$reduce_xnor") {
185 RTLIL::SigSpec sig_t = module->new_wire(1, NEW_ID);
186 RTLIL::Cell *gate = new RTLIL::Cell;
187 gate->name = NEW_ID;
188 gate->type = "$_INV_";
189 gate->connections["\\A"] = sig_a;
190 gate->connections["\\Y"] = sig_t;
191 last_output = &gate->connections["\\Y"];
192 module->add(gate);
193 sig_a = sig_t;
194 }
195
196 if (last_output == NULL) {
197 module->connections.push_back(RTLIL::SigSig(sig_y, sig_a));
198 } else {
199 *last_output = sig_y;
200 }
201 }
202
203 static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig)
204 {
205 sig.expand();
206
207 while (sig.width > 1)
208 {
209 RTLIL::SigSpec sig_t = module->new_wire(sig.width / 2, NEW_ID);
210 sig_t.expand();
211
212 for (int i = 0; i < sig.width; i += 2)
213 {
214 if (i+1 == sig.width) {
215 sig_t.append(sig.chunks.at(i));
216 continue;
217 }
218
219 RTLIL::Cell *gate = new RTLIL::Cell;
220 gate->name = NEW_ID;
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);
225 module->add(gate);
226 }
227
228 sig = sig_t;
229 }
230
231 if (sig.width == 0)
232 sig = RTLIL::SigSpec(0, 1);
233 }
234
235 static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
236 {
237 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
238 logic_reduce(module, sig_a);
239
240 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
241
242 if (sig_y.width == 0)
243 return;
244
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);
248 }
249
250 RTLIL::Cell *gate = new RTLIL::Cell;
251 gate->name = NEW_ID;
252 gate->type = "$_INV_";
253 gate->connections["\\A"] = sig_a;
254 gate->connections["\\Y"] = sig_y;
255 module->add(gate);
256 }
257
258 static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
259 {
260 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
261 logic_reduce(module, sig_a);
262
263 RTLIL::SigSpec sig_b = cell->connections.at("\\B");
264 logic_reduce(module, sig_b);
265
266 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
267
268 if (sig_y.width == 0)
269 return;
270
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);
274 }
275
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());
280
281 RTLIL::Cell *gate = new RTLIL::Cell;
282 gate->name = NEW_ID;
283 gate->type = gate_type;
284 gate->connections["\\A"] = sig_a;
285 gate->connections["\\B"] = sig_b;
286 gate->connections["\\Y"] = sig_y;
287 module->add(gate);
288 }
289
290 static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
291 {
292 int width = cell->parameters.at("\\WIDTH").as_int();
293
294 RTLIL::SigSpec sig_a = cell->connections.at("\\A");
295 sig_a.expand();
296
297 RTLIL::SigSpec sig_b = cell->connections.at("\\B");
298 sig_b.expand();
299
300 RTLIL::SigSpec sig_y = cell->connections.at("\\Y");
301 sig_y.expand();
302
303 for (int i = 0; i < width; i++) {
304 RTLIL::Cell *gate = new RTLIL::Cell;
305 gate->name = NEW_ID;
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);
311 module->add(gate);
312 }
313 }
314
315 static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
316 {
317 int width = cell->parameters.at("\\WIDTH").as_int();
318 char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
319 char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
320
321 RTLIL::SigSpec sig_s = cell->connections.at("\\SET");
322 sig_s.expand();
323
324 RTLIL::SigSpec sig_r = cell->connections.at("\\CLR");
325 sig_r.expand();
326
327 RTLIL::SigSpec sig_q = cell->connections.at("\\Q");
328 sig_q.expand();
329
330 std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol);
331
332 for (int i = 0; i < width; i++) {
333 RTLIL::Cell *gate = new RTLIL::Cell;
334 gate->name = NEW_ID;
335 gate->type = gate_type;
336 gate->connections["\\S"] = sig_s.chunks.at(i);
337 gate->connections["\\R"] = sig_r.chunks.at(i);
338 gate->connections["\\Q"] = sig_q.chunks.at(i);
339 module->add(gate);
340 }
341 }
342
343 static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
344 {
345 int width = cell->parameters.at("\\WIDTH").as_int();
346 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
347
348 RTLIL::SigSpec sig_clk = cell->connections.at("\\CLK");
349
350 RTLIL::SigSpec sig_d = cell->connections.at("\\D");
351 sig_d.expand();
352
353 RTLIL::SigSpec sig_q = cell->connections.at("\\Q");
354 sig_q.expand();
355
356 std::string gate_type = stringf("$_DFF_%c_", clk_pol);
357
358 for (int i = 0; i < width; i++) {
359 RTLIL::Cell *gate = new RTLIL::Cell;
360 gate->name = NEW_ID;
361 gate->type = gate_type;
362 gate->connections["\\C"] = sig_clk;
363 gate->connections["\\D"] = sig_d.chunks.at(i);
364 gate->connections["\\Q"] = sig_q.chunks.at(i);
365 module->add(gate);
366 }
367 }
368
369 static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
370 {
371 int width = cell->parameters.at("\\WIDTH").as_int();
372 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
373 char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
374 char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
375
376 RTLIL::SigSpec sig_clk = cell->connections.at("\\CLK");
377
378 RTLIL::SigSpec sig_s = cell->connections.at("\\SET");
379 sig_s.expand();
380
381 RTLIL::SigSpec sig_r = cell->connections.at("\\CLR");
382 sig_r.expand();
383
384 RTLIL::SigSpec sig_d = cell->connections.at("\\D");
385 sig_d.expand();
386
387 RTLIL::SigSpec sig_q = cell->connections.at("\\Q");
388 sig_q.expand();
389
390 std::string gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
391
392 for (int i = 0; i < width; i++) {
393 RTLIL::Cell *gate = new RTLIL::Cell;
394 gate->name = NEW_ID;
395 gate->type = gate_type;
396 gate->connections["\\C"] = sig_clk;
397 gate->connections["\\S"] = sig_s.chunks.at(i);
398 gate->connections["\\R"] = sig_r.chunks.at(i);
399 gate->connections["\\D"] = sig_d.chunks.at(i);
400 gate->connections["\\Q"] = sig_q.chunks.at(i);
401 module->add(gate);
402 }
403 }
404
405 static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
406 {
407 int width = cell->parameters.at("\\WIDTH").as_int();
408 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
409 char rst_pol = cell->parameters.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
410
411 std::vector<RTLIL::State> rst_val = cell->parameters.at("\\ARST_VALUE").bits;
412 while (int(rst_val.size()) < width)
413 rst_val.push_back(RTLIL::State::S0);
414
415 RTLIL::SigSpec sig_clk = cell->connections.at("\\CLK");
416 RTLIL::SigSpec sig_rst = cell->connections.at("\\ARST");
417
418 RTLIL::SigSpec sig_d = cell->connections.at("\\D");
419 sig_d.expand();
420
421 RTLIL::SigSpec sig_q = cell->connections.at("\\Q");
422 sig_q.expand();
423
424 std::string gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol);
425 std::string gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol);
426
427 for (int i = 0; i < width; i++) {
428 RTLIL::Cell *gate = new RTLIL::Cell;
429 gate->name = NEW_ID;
430 gate->type = rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0;
431 gate->connections["\\C"] = sig_clk;
432 gate->connections["\\R"] = sig_rst;
433 gate->connections["\\D"] = sig_d.chunks.at(i);
434 gate->connections["\\Q"] = sig_q.chunks.at(i);
435 module->add(gate);
436 }
437 }
438
439 static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
440 {
441 int width = cell->parameters.at("\\WIDTH").as_int();
442 char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
443
444 RTLIL::SigSpec sig_en = cell->connections.at("\\EN");
445
446 RTLIL::SigSpec sig_d = cell->connections.at("\\D");
447 sig_d.expand();
448
449 RTLIL::SigSpec sig_q = cell->connections.at("\\Q");
450 sig_q.expand();
451
452 std::string gate_type = stringf("$_DLATCH_%c_", en_pol);
453
454 for (int i = 0; i < width; i++) {
455 RTLIL::Cell *gate = new RTLIL::Cell;
456 gate->name = NEW_ID;
457 gate->type = gate_type;
458 gate->connections["\\E"] = sig_en;
459 gate->connections["\\D"] = sig_d.chunks.at(i);
460 gate->connections["\\Q"] = sig_q.chunks.at(i);
461 module->add(gate);
462 }
463 }
464
465 void simplemap_get_mappers(std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
466 {
467 mappers["$not"] = simplemap_not;
468 mappers["$pos"] = simplemap_pos;
469 mappers["$bu0"] = simplemap_bu0;
470 mappers["$and"] = simplemap_bitop;
471 mappers["$or"] = simplemap_bitop;
472 mappers["$xor"] = simplemap_bitop;
473 mappers["$xnor"] = simplemap_bitop;
474 mappers["$reduce_and"] = simplemap_reduce;
475 mappers["$reduce_or"] = simplemap_reduce;
476 mappers["$reduce_xor"] = simplemap_reduce;
477 mappers["$reduce_xnor"] = simplemap_reduce;
478 mappers["$reduce_bool"] = simplemap_reduce;
479 mappers["$logic_not"] = simplemap_lognot;
480 mappers["$logic_and"] = simplemap_logbin;
481 mappers["$logic_or"] = simplemap_logbin;
482 mappers["$mux"] = simplemap_mux;
483 mappers["$sr"] = simplemap_sr;
484 mappers["$dff"] = simplemap_dff;
485 mappers["$dffsr"] = simplemap_dffsr;
486 mappers["$adff"] = simplemap_adff;
487 mappers["$dlatch"] = simplemap_dlatch;
488 }
489
490 struct SimplemapPass : public Pass {
491 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
492 virtual void help()
493 {
494 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
495 log("\n");
496 log(" simplemap [selection]\n");
497 log("\n");
498 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
499 log("primitives. The following internal cell types are mapped by this pass:\n");
500 log("\n");
501 log(" $not, $pos, $bu0, $and, $or, $xor, $xnor\n");
502 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
503 log(" $logic_not, $logic_and, $logic_or, $mux\n");
504 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
505 log("\n");
506 }
507 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
508 {
509 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
510 extra_args(args, 1, design);
511
512 std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
513 simplemap_get_mappers(mappers);
514
515 for (auto &mod_it : design->modules) {
516 if (!design->selected(mod_it.second))
517 continue;
518 std::vector<RTLIL::Cell*> delete_cells;
519 for (auto &cell_it : mod_it.second->cells) {
520 if (mappers.count(cell_it.second->type) == 0)
521 continue;
522 if (!design->selected(mod_it.second, cell_it.second))
523 continue;
524 log("Mapping %s.%s (%s).\n", RTLIL::id2cstr(mod_it.first), RTLIL::id2cstr(cell_it.first), RTLIL::id2cstr(cell_it.second->type));
525 mappers.at(cell_it.second->type)(mod_it.second, cell_it.second);
526 delete_cells.push_back(cell_it.second);
527 }
528 for (auto &it : delete_cells) {
529 mod_it.second->cells.erase(it->name);
530 delete it;
531 }
532 }
533 }
534 } SimplemapPass;
535