Manual fixes for new cell connections API
[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 RTLIL::SigSpec sig_a = cell->get("\\A");
33 RTLIL::SigSpec sig_y = cell->get("\\Y");
34
35 sig_a.extend(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
36
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]);
41 }
42 }
43
44 static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
45 {
46 RTLIL::SigSpec sig_a = cell->get("\\A");
47 RTLIL::SigSpec sig_y = cell->get("\\Y");
48
49 sig_a.extend(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
50
51 module->connect(RTLIL::SigSig(sig_y, sig_a));
52 }
53
54 static void simplemap_bu0(RTLIL::Module *module, RTLIL::Cell *cell)
55 {
56 RTLIL::SigSpec sig_a = cell->get("\\A");
57 RTLIL::SigSpec sig_y = cell->get("\\Y");
58
59 sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
60
61 module->connect(RTLIL::SigSig(sig_y, sig_a));
62 }
63
64 static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
65 {
66 RTLIL::SigSpec sig_a = cell->get("\\A");
67 RTLIL::SigSpec sig_b = cell->get("\\B");
68 RTLIL::SigSpec sig_y = cell->get("\\Y");
69
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());
72
73 if (cell->type == "$xnor")
74 {
75 RTLIL::SigSpec sig_t = module->addWire(NEW_ID, SIZE(sig_y));
76
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]);
81 }
82
83 sig_y = sig_t;
84 }
85
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());
92
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]);
98 }
99 }
100
101 static void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
102 {
103 RTLIL::SigSpec sig_a = cell->get("\\A");
104 RTLIL::SigSpec sig_y = cell->get("\\Y");
105
106 if (sig_y.size() == 0)
107 return;
108
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())));
115 return;
116 }
117
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);
121 }
122
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());
130
131 RTLIL::Cell *last_output_cell = NULL;
132
133 while (sig_a.size() > 1)
134 {
135 RTLIL::SigSpec sig_t = module->addWire(NEW_ID, sig_a.size() / 2);
136
137 for (int i = 0; i < sig_a.size(); i += 2)
138 {
139 if (i+1 == sig_a.size()) {
140 sig_t.append(sig_a[i]);
141 continue;
142 }
143
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;
149 }
150
151 sig_a = sig_t;
152 }
153
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;
160 sig_a = sig_t;
161 }
162
163 if (last_output_cell == NULL) {
164 module->connect(RTLIL::SigSig(sig_y, sig_a));
165 } else {
166 last_output_cell->set("\\Y", sig_y);
167 }
168 }
169
170 static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig)
171 {
172 while (sig.size() > 1)
173 {
174 RTLIL::SigSpec sig_t = module->addWire(NEW_ID, sig.size() / 2);
175
176 for (int i = 0; i < sig.size(); i += 2)
177 {
178 if (i+1 == sig.size()) {
179 sig_t.append(sig[i]);
180 continue;
181 }
182
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]);
187 }
188
189 sig = sig_t;
190 }
191
192 if (sig.size() == 0)
193 sig = RTLIL::SigSpec(0, 1);
194 }
195
196 static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
197 {
198 RTLIL::SigSpec sig_a = cell->get("\\A");
199 logic_reduce(module, sig_a);
200
201 RTLIL::SigSpec sig_y = cell->get("\\Y");
202
203 if (sig_y.size() == 0)
204 return;
205
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);
209 }
210
211 RTLIL::Cell *gate = module->addCell(NEW_ID, "$_INV_");
212 gate->set("\\A", sig_a);
213 gate->set("\\Y", sig_y);
214 }
215
216 static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
217 {
218 RTLIL::SigSpec sig_a = cell->get("\\A");
219 logic_reduce(module, sig_a);
220
221 RTLIL::SigSpec sig_b = cell->get("\\B");
222 logic_reduce(module, sig_b);
223
224 RTLIL::SigSpec sig_y = cell->get("\\Y");
225
226 if (sig_y.size() == 0)
227 return;
228
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);
232 }
233
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());
238
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);
243 }
244
245 static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
246 {
247 RTLIL::SigSpec sig_a = cell->get("\\A");
248 RTLIL::SigSpec sig_b = cell->get("\\B");
249 RTLIL::SigSpec sig_y = cell->get("\\Y");
250
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]);
257 }
258 }
259
260 static void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
261 {
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())));
266 }
267
268 static void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
269 {
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));
274 }
275
276 static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
277 {
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';
281
282 RTLIL::SigSpec sig_s = cell->get("\\SET");
283 RTLIL::SigSpec sig_r = cell->get("\\CLR");
284 RTLIL::SigSpec sig_q = cell->get("\\Q");
285
286 std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol);
287
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]);
293 }
294 }
295
296 static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
297 {
298 int width = cell->parameters.at("\\WIDTH").as_int();
299 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
300
301 RTLIL::SigSpec sig_clk = cell->get("\\CLK");
302 RTLIL::SigSpec sig_d = cell->get("\\D");
303 RTLIL::SigSpec sig_q = cell->get("\\Q");
304
305 std::string gate_type = stringf("$_DFF_%c_", clk_pol);
306
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]);
312 }
313 }
314
315 static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
316 {
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';
321
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");
327
328 std::string gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
329
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]);
337 }
338 }
339
340 static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
341 {
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';
345
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);
349
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");
354
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);
357
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]);
364 }
365 }
366
367 static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
368 {
369 int width = cell->parameters.at("\\WIDTH").as_int();
370 char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
371
372 RTLIL::SigSpec sig_en = cell->get("\\EN");
373 RTLIL::SigSpec sig_d = cell->get("\\D");
374 RTLIL::SigSpec sig_q = cell->get("\\Q");
375
376 std::string gate_type = stringf("$_DLATCH_%c_", en_pol);
377
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]);
383 }
384 }
385
386 void simplemap_get_mappers(std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
387 {
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;
411 }
412
413 struct SimplemapPass : public Pass {
414 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
415 virtual void help()
416 {
417 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
418 log("\n");
419 log(" simplemap [selection]\n");
420 log("\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");
423 log("\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");
428 log("\n");
429 }
430 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
431 {
432 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
433 extra_args(args, 1, design);
434
435 std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
436 simplemap_get_mappers(mappers);
437
438 for (auto &mod_it : design->modules) {
439 if (!design->selected(mod_it.second))
440 continue;
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)
444 continue;
445 if (!design->selected(mod_it.second, cell_it.second))
446 continue;
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);
450 }
451 for (auto c : delete_cells)
452 mod_it.second->remove(c);
453 }
454 }
455 } SimplemapPass;
456