Renamed $_INV_ cell type to $_NOT_
[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 <stdio.h>
25 #include <string.h>
26
27 extern void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
28
29 static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
30 {
31 RTLIL::SigSpec sig_a = cell->getPort("\\A");
32 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
33
34 sig_a.extend(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
35
36 for (int i = 0; i < SIZE(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]);
40 }
41 }
42
43 static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
44 {
45 RTLIL::SigSpec sig_a = cell->getPort("\\A");
46 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
47
48 sig_a.extend(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
49
50 module->connect(RTLIL::SigSig(sig_y, sig_a));
51 }
52
53 static void simplemap_bu0(RTLIL::Module *module, RTLIL::Cell *cell)
54 {
55 RTLIL::SigSpec sig_a = cell->getPort("\\A");
56 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
57
58 sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
59
60 module->connect(RTLIL::SigSig(sig_y, sig_a));
61 }
62
63 static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
64 {
65 RTLIL::SigSpec sig_a = cell->getPort("\\A");
66 RTLIL::SigSpec sig_b = cell->getPort("\\B");
67 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
68
69 sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
70 sig_b.extend_u0(SIZE(sig_y), cell->parameters.at("\\B_SIGNED").as_bool());
71
72 if (cell->type == "$xnor")
73 {
74 RTLIL::SigSpec sig_t = module->addWire(NEW_ID, SIZE(sig_y));
75
76 for (int i = 0; i < SIZE(sig_y); i++) {
77 RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
78 gate->setPort("\\A", sig_t[i]);
79 gate->setPort("\\Y", sig_y[i]);
80 }
81
82 sig_y = sig_t;
83 }
84
85 std::string gate_type;
86 if (cell->type == "$and") gate_type = "$_AND_";
87 if (cell->type == "$or") gate_type = "$_OR_";
88 if (cell->type == "$xor") gate_type = "$_XOR_";
89 if (cell->type == "$xnor") gate_type = "$_XOR_";
90 log_assert(!gate_type.empty());
91
92 for (int i = 0; i < SIZE(sig_y); i++) {
93 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
94 gate->setPort("\\A", sig_a[i]);
95 gate->setPort("\\B", sig_b[i]);
96 gate->setPort("\\Y", sig_y[i]);
97 }
98 }
99
100 static void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
101 {
102 RTLIL::SigSpec sig_a = cell->getPort("\\A");
103 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
104
105 if (sig_y.size() == 0)
106 return;
107
108 if (sig_a.size() == 0) {
109 if (cell->type == "$reduce_and") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
110 if (cell->type == "$reduce_or") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
111 if (cell->type == "$reduce_xor") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
112 if (cell->type == "$reduce_xnor") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
113 if (cell->type == "$reduce_bool") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
114 return;
115 }
116
117 if (sig_y.size() > 1) {
118 module->connect(RTLIL::SigSig(sig_y.extract(1, sig_y.size()-1), RTLIL::SigSpec(0, sig_y.size()-1)));
119 sig_y = sig_y.extract(0, 1);
120 }
121
122 std::string gate_type;
123 if (cell->type == "$reduce_and") gate_type = "$_AND_";
124 if (cell->type == "$reduce_or") gate_type = "$_OR_";
125 if (cell->type == "$reduce_xor") gate_type = "$_XOR_";
126 if (cell->type == "$reduce_xnor") gate_type = "$_XOR_";
127 if (cell->type == "$reduce_bool") gate_type = "$_OR_";
128 log_assert(!gate_type.empty());
129
130 RTLIL::Cell *last_output_cell = NULL;
131
132 while (sig_a.size() > 1)
133 {
134 RTLIL::SigSpec sig_t = module->addWire(NEW_ID, sig_a.size() / 2);
135
136 for (int i = 0; i < sig_a.size(); i += 2)
137 {
138 if (i+1 == sig_a.size()) {
139 sig_t.append(sig_a[i]);
140 continue;
141 }
142
143 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
144 gate->setPort("\\A", sig_a[i]);
145 gate->setPort("\\B", sig_a[i+1]);
146 gate->setPort("\\Y", sig_t[i/2]);
147 last_output_cell = gate;
148 }
149
150 sig_a = sig_t;
151 }
152
153 if (cell->type == "$reduce_xnor") {
154 RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
155 RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
156 gate->setPort("\\A", sig_a);
157 gate->setPort("\\Y", sig_t);
158 last_output_cell = gate;
159 sig_a = sig_t;
160 }
161
162 if (last_output_cell == NULL) {
163 module->connect(RTLIL::SigSig(sig_y, sig_a));
164 } else {
165 last_output_cell->setPort("\\Y", sig_y);
166 }
167 }
168
169 static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig)
170 {
171 while (sig.size() > 1)
172 {
173 RTLIL::SigSpec sig_t = module->addWire(NEW_ID, sig.size() / 2);
174
175 for (int i = 0; i < sig.size(); i += 2)
176 {
177 if (i+1 == sig.size()) {
178 sig_t.append(sig[i]);
179 continue;
180 }
181
182 RTLIL::Cell *gate = module->addCell(NEW_ID, "$_OR_");
183 gate->setPort("\\A", sig[i]);
184 gate->setPort("\\B", sig[i+1]);
185 gate->setPort("\\Y", sig_t[i/2]);
186 }
187
188 sig = sig_t;
189 }
190
191 if (sig.size() == 0)
192 sig = RTLIL::SigSpec(0, 1);
193 }
194
195 static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
196 {
197 RTLIL::SigSpec sig_a = cell->getPort("\\A");
198 logic_reduce(module, sig_a);
199
200 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
201
202 if (sig_y.size() == 0)
203 return;
204
205 if (sig_y.size() > 1) {
206 module->connect(RTLIL::SigSig(sig_y.extract(1, sig_y.size()-1), RTLIL::SigSpec(0, sig_y.size()-1)));
207 sig_y = sig_y.extract(0, 1);
208 }
209
210 RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
211 gate->setPort("\\A", sig_a);
212 gate->setPort("\\Y", sig_y);
213 }
214
215 static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
216 {
217 RTLIL::SigSpec sig_a = cell->getPort("\\A");
218 logic_reduce(module, sig_a);
219
220 RTLIL::SigSpec sig_b = cell->getPort("\\B");
221 logic_reduce(module, sig_b);
222
223 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
224
225 if (sig_y.size() == 0)
226 return;
227
228 if (sig_y.size() > 1) {
229 module->connect(RTLIL::SigSig(sig_y.extract(1, sig_y.size()-1), RTLIL::SigSpec(0, sig_y.size()-1)));
230 sig_y = sig_y.extract(0, 1);
231 }
232
233 std::string gate_type;
234 if (cell->type == "$logic_and") gate_type = "$_AND_";
235 if (cell->type == "$logic_or") gate_type = "$_OR_";
236 log_assert(!gate_type.empty());
237
238 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
239 gate->setPort("\\A", sig_a);
240 gate->setPort("\\B", sig_b);
241 gate->setPort("\\Y", sig_y);
242 }
243
244 static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
245 {
246 RTLIL::SigSpec sig_a = cell->getPort("\\A");
247 RTLIL::SigSpec sig_b = cell->getPort("\\B");
248 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
249
250 for (int i = 0; i < SIZE(sig_y); i++) {
251 RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_");
252 gate->setPort("\\A", sig_a[i]);
253 gate->setPort("\\B", sig_b[i]);
254 gate->setPort("\\S", cell->getPort("\\S"));
255 gate->setPort("\\Y", sig_y[i]);
256 }
257 }
258
259 static void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
260 {
261 int offset = cell->parameters.at("\\OFFSET").as_int();
262 RTLIL::SigSpec sig_a = cell->getPort("\\A");
263 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
264 module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size())));
265 }
266
267 static void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
268 {
269 RTLIL::SigSpec sig_ab = cell->getPort("\\A");
270 sig_ab.append(cell->getPort("\\B"));
271 RTLIL::SigSpec sig_y = cell->getPort("\\Y");
272 module->connect(RTLIL::SigSig(sig_y, sig_ab));
273 }
274
275 static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
276 {
277 int width = cell->parameters.at("\\WIDTH").as_int();
278 char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
279 char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
280
281 RTLIL::SigSpec sig_s = cell->getPort("\\SET");
282 RTLIL::SigSpec sig_r = cell->getPort("\\CLR");
283 RTLIL::SigSpec sig_q = cell->getPort("\\Q");
284
285 std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol);
286
287 for (int i = 0; i < width; i++) {
288 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
289 gate->setPort("\\S", sig_s[i]);
290 gate->setPort("\\R", sig_r[i]);
291 gate->setPort("\\Q", sig_q[i]);
292 }
293 }
294
295 static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
296 {
297 int width = cell->parameters.at("\\WIDTH").as_int();
298 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
299
300 RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
301 RTLIL::SigSpec sig_d = cell->getPort("\\D");
302 RTLIL::SigSpec sig_q = cell->getPort("\\Q");
303
304 std::string gate_type = stringf("$_DFF_%c_", clk_pol);
305
306 for (int i = 0; i < width; i++) {
307 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
308 gate->setPort("\\C", sig_clk);
309 gate->setPort("\\D", sig_d[i]);
310 gate->setPort("\\Q", sig_q[i]);
311 }
312 }
313
314 static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
315 {
316 int width = cell->parameters.at("\\WIDTH").as_int();
317 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
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_clk = cell->getPort("\\CLK");
322 RTLIL::SigSpec sig_s = cell->getPort("\\SET");
323 RTLIL::SigSpec sig_r = cell->getPort("\\CLR");
324 RTLIL::SigSpec sig_d = cell->getPort("\\D");
325 RTLIL::SigSpec sig_q = cell->getPort("\\Q");
326
327 std::string gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
328
329 for (int i = 0; i < width; i++) {
330 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
331 gate->setPort("\\C", sig_clk);
332 gate->setPort("\\S", sig_s[i]);
333 gate->setPort("\\R", sig_r[i]);
334 gate->setPort("\\D", sig_d[i]);
335 gate->setPort("\\Q", sig_q[i]);
336 }
337 }
338
339 static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
340 {
341 int width = cell->parameters.at("\\WIDTH").as_int();
342 char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
343 char rst_pol = cell->parameters.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
344
345 std::vector<RTLIL::State> rst_val = cell->parameters.at("\\ARST_VALUE").bits;
346 while (int(rst_val.size()) < width)
347 rst_val.push_back(RTLIL::State::S0);
348
349 RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
350 RTLIL::SigSpec sig_rst = cell->getPort("\\ARST");
351 RTLIL::SigSpec sig_d = cell->getPort("\\D");
352 RTLIL::SigSpec sig_q = cell->getPort("\\Q");
353
354 std::string gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol);
355 std::string gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol);
356
357 for (int i = 0; i < width; i++) {
358 RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
359 gate->setPort("\\C", sig_clk);
360 gate->setPort("\\R", sig_rst);
361 gate->setPort("\\D", sig_d[i]);
362 gate->setPort("\\Q", sig_q[i]);
363 }
364 }
365
366 static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
367 {
368 int width = cell->parameters.at("\\WIDTH").as_int();
369 char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
370
371 RTLIL::SigSpec sig_en = cell->getPort("\\EN");
372 RTLIL::SigSpec sig_d = cell->getPort("\\D");
373 RTLIL::SigSpec sig_q = cell->getPort("\\Q");
374
375 std::string gate_type = stringf("$_DLATCH_%c_", en_pol);
376
377 for (int i = 0; i < width; i++) {
378 RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
379 gate->setPort("\\E", sig_en);
380 gate->setPort("\\D", sig_d[i]);
381 gate->setPort("\\Q", sig_q[i]);
382 }
383 }
384
385 void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
386 {
387 mappers["$not"] = simplemap_not;
388 mappers["$pos"] = simplemap_pos;
389 mappers["$bu0"] = simplemap_bu0;
390 mappers["$and"] = simplemap_bitop;
391 mappers["$or"] = simplemap_bitop;
392 mappers["$xor"] = simplemap_bitop;
393 mappers["$xnor"] = simplemap_bitop;
394 mappers["$reduce_and"] = simplemap_reduce;
395 mappers["$reduce_or"] = simplemap_reduce;
396 mappers["$reduce_xor"] = simplemap_reduce;
397 mappers["$reduce_xnor"] = simplemap_reduce;
398 mappers["$reduce_bool"] = simplemap_reduce;
399 mappers["$logic_not"] = simplemap_lognot;
400 mappers["$logic_and"] = simplemap_logbin;
401 mappers["$logic_or"] = simplemap_logbin;
402 mappers["$mux"] = simplemap_mux;
403 mappers["$slice"] = simplemap_slice;
404 mappers["$concat"] = simplemap_concat;
405 mappers["$sr"] = simplemap_sr;
406 mappers["$dff"] = simplemap_dff;
407 mappers["$dffsr"] = simplemap_dffsr;
408 mappers["$adff"] = simplemap_adff;
409 mappers["$dlatch"] = simplemap_dlatch;
410 }
411
412 struct SimplemapPass : public Pass {
413 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
414 virtual void help()
415 {
416 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
417 log("\n");
418 log(" simplemap [selection]\n");
419 log("\n");
420 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
421 log("primitives. The following internal cell types are mapped by this pass:\n");
422 log("\n");
423 log(" $not, $pos, $bu0, $and, $or, $xor, $xnor\n");
424 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
425 log(" $logic_not, $logic_and, $logic_or, $mux\n");
426 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
427 log("\n");
428 }
429 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
430 {
431 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
432 extra_args(args, 1, design);
433
434 std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
435 simplemap_get_mappers(mappers);
436
437 for (auto mod : design->modules()) {
438 if (!design->selected(mod))
439 continue;
440 std::vector<RTLIL::Cell*> cells = mod->cells();
441 for (auto cell : cells) {
442 if (mappers.count(cell->type) == 0)
443 continue;
444 if (!design->selected(mod, cell))
445 continue;
446 log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
447 mappers.at(cell->type)(mod, cell);
448 mod->remove(cell);
449 }
450 }
451 }
452 } SimplemapPass;
453