Merge pull request #1085 from YosysHQ/eddie/shregmap_improve
[yosys.git] / passes / sat / expose.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/celltypes.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/rtlil.h"
24 #include "kernel/log.h"
25
26 USING_YOSYS_NAMESPACE
27 PRIVATE_NAMESPACE_BEGIN
28
29 struct dff_map_info_t {
30 RTLIL::SigSpec sig_d, sig_clk, sig_arst;
31 bool clk_polarity, arst_polarity;
32 RTLIL::Const arst_value;
33 std::vector<RTLIL::IdString> cells;
34 };
35
36 struct dff_map_bit_info_t {
37 RTLIL::SigBit bit_d, bit_clk, bit_arst;
38 bool clk_polarity, arst_polarity;
39 RTLIL::State arst_value;
40 RTLIL::Cell *cell;
41 };
42
43 bool consider_wire(RTLIL::Wire *wire, std::map<RTLIL::IdString, dff_map_info_t> &dff_dq_map)
44 {
45 if (wire->name[0] == '$' || dff_dq_map.count(wire->name))
46 return false;
47 if (wire->port_input)
48 return false;
49 return true;
50 }
51
52 bool consider_cell(RTLIL::Design *design, std::set<RTLIL::IdString> &dff_cells, RTLIL::Cell *cell)
53 {
54 if (cell->name[0] == '$' || dff_cells.count(cell->name))
55 return false;
56 if (cell->type[0] == '\\' && !design->modules_.count(cell->type))
57 return false;
58 return true;
59 }
60
61 bool compare_wires(RTLIL::Wire *wire1, RTLIL::Wire *wire2)
62 {
63 log_assert(wire1->name == wire2->name);
64 if (wire1->width != wire2->width)
65 return false;
66 return true;
67 }
68
69 bool compare_cells(RTLIL::Cell *cell1, RTLIL::Cell *cell2)
70 {
71 log_assert(cell1->name == cell2->name);
72 if (cell1->type != cell2->type)
73 return false;
74 if (cell1->parameters != cell2->parameters)
75 return false;
76 return true;
77 }
78
79 void find_dff_wires(std::set<RTLIL::IdString> &dff_wires, RTLIL::Module *module)
80 {
81 CellTypes ct;
82 ct.setup_internals_mem();
83 ct.setup_stdcells_mem();
84
85 SigMap sigmap(module);
86 SigPool dffsignals;
87
88 for (auto &it : module->cells_) {
89 if (ct.cell_known(it.second->type) && it.second->hasPort("\\Q"))
90 dffsignals.add(sigmap(it.second->getPort("\\Q")));
91 }
92
93 for (auto &it : module->wires_) {
94 if (dffsignals.check_any(it.second))
95 dff_wires.insert(it.first);
96 }
97 }
98
99 void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::Design *design, RTLIL::Module *module)
100 {
101 std::map<RTLIL::SigBit, dff_map_bit_info_t> bit_info;
102 SigMap sigmap(module);
103
104 for (auto &it : module->cells_)
105 {
106 if (!design->selected(module, it.second))
107 continue;
108
109 dff_map_bit_info_t info;
110 info.bit_d = RTLIL::State::Sm;
111 info.bit_clk = RTLIL::State::Sm;
112 info.bit_arst = RTLIL::State::Sm;
113 info.clk_polarity = false;
114 info.arst_polarity = false;
115 info.arst_value = RTLIL::State::Sm;
116 info.cell = it.second;
117
118 if (info.cell->type == "$dff") {
119 info.bit_clk = sigmap(info.cell->getPort("\\CLK")).as_bit();
120 info.clk_polarity = info.cell->parameters.at("\\CLK_POLARITY").as_bool();
121 std::vector<RTLIL::SigBit> sig_d = sigmap(info.cell->getPort("\\D")).to_sigbit_vector();
122 std::vector<RTLIL::SigBit> sig_q = sigmap(info.cell->getPort("\\Q")).to_sigbit_vector();
123 for (size_t i = 0; i < sig_d.size(); i++) {
124 info.bit_d = sig_d.at(i);
125 bit_info[sig_q.at(i)] = info;
126 }
127 continue;
128 }
129
130 if (info.cell->type == "$adff") {
131 info.bit_clk = sigmap(info.cell->getPort("\\CLK")).as_bit();
132 info.bit_arst = sigmap(info.cell->getPort("\\ARST")).as_bit();
133 info.clk_polarity = info.cell->parameters.at("\\CLK_POLARITY").as_bool();
134 info.arst_polarity = info.cell->parameters.at("\\ARST_POLARITY").as_bool();
135 std::vector<RTLIL::SigBit> sig_d = sigmap(info.cell->getPort("\\D")).to_sigbit_vector();
136 std::vector<RTLIL::SigBit> sig_q = sigmap(info.cell->getPort("\\Q")).to_sigbit_vector();
137 std::vector<RTLIL::State> arst_value = info.cell->parameters.at("\\ARST_VALUE").bits;
138 for (size_t i = 0; i < sig_d.size(); i++) {
139 info.bit_d = sig_d.at(i);
140 info.arst_value = arst_value.at(i);
141 bit_info[sig_q.at(i)] = info;
142 }
143 continue;
144 }
145
146 if (info.cell->type == "$_DFF_N_" || info.cell->type == "$_DFF_P_") {
147 info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
148 info.clk_polarity = info.cell->type == "$_DFF_P_";
149 info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit();
150 bit_info[sigmap(info.cell->getPort("\\Q")).as_bit()] = info;
151 continue;
152 }
153
154 if (info.cell->type.size() == 10 && info.cell->type.substr(0, 6) == "$_DFF_") {
155 info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
156 info.bit_arst = sigmap(info.cell->getPort("\\R")).as_bit();
157 info.clk_polarity = info.cell->type[6] == 'P';
158 info.arst_polarity = info.cell->type[7] == 'P';
159 info.arst_value = info.cell->type[0] == '1' ? RTLIL::State::S1 : RTLIL::State::S0;
160 info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit();
161 bit_info[sigmap(info.cell->getPort("\\Q")).as_bit()] = info;
162 continue;
163 }
164 }
165
166 std::map<RTLIL::IdString, dff_map_info_t> empty_dq_map;
167 for (auto &it : module->wires_)
168 {
169 if (!consider_wire(it.second, empty_dq_map))
170 continue;
171
172 std::vector<RTLIL::SigBit> bits_q = sigmap(it.second).to_sigbit_vector();
173 std::vector<RTLIL::SigBit> bits_d;
174 std::vector<RTLIL::State> arst_value;
175 std::set<RTLIL::Cell*> cells;
176
177 if (bits_q.empty() || !bit_info.count(bits_q.front()))
178 continue;
179
180 dff_map_bit_info_t ref_info = bit_info.at(bits_q.front());
181 for (auto &bit : bits_q) {
182 if (!bit_info.count(bit))
183 break;
184 dff_map_bit_info_t info = bit_info.at(bit);
185 if (info.bit_clk != ref_info.bit_clk)
186 break;
187 if (info.bit_arst != ref_info.bit_arst)
188 break;
189 if (info.clk_polarity != ref_info.clk_polarity)
190 break;
191 if (info.arst_polarity != ref_info.arst_polarity)
192 break;
193 bits_d.push_back(info.bit_d);
194 arst_value.push_back(info.arst_value);
195 cells.insert(info.cell);
196 }
197
198 if (bits_d.size() != bits_q.size())
199 continue;
200
201 dff_map_info_t info;
202 info.sig_d = bits_d;
203 info.sig_clk = ref_info.bit_clk;
204 info.sig_arst = ref_info.bit_arst;
205 info.clk_polarity = ref_info.clk_polarity;
206 info.arst_polarity = ref_info.arst_polarity;
207 info.arst_value = arst_value;
208 for (auto it : cells)
209 info.cells.push_back(it->name);
210 map[it.first] = info;
211 }
212 }
213
214 RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width = 1)
215 {
216 if (module->count_id(name))
217 log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", log_id(name));
218 return module->addWire(name, width);
219 }
220
221 struct ExposePass : public Pass {
222 ExposePass() : Pass("expose", "convert internal signals to module ports") { }
223 void help() YS_OVERRIDE
224 {
225 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
226 log("\n");
227 log(" expose [options] [selection]\n");
228 log("\n");
229 log("This command exposes all selected internal signals of a module as additional\n");
230 log("outputs.\n");
231 log("\n");
232 log(" -dff\n");
233 log(" only consider wires that are directly driven by register cell.\n");
234 log("\n");
235 log(" -cut\n");
236 log(" when exposing a wire, create an input/output pair and cut the internal\n");
237 log(" signal path at that wire.\n");
238 log("\n");
239 log(" -input\n");
240 log(" when exposing a wire, create an input port and disconnect the internal\n");
241 log(" driver.\n");
242 log("\n");
243 log(" -shared\n");
244 log(" only expose those signals that are shared among the selected modules.\n");
245 log(" this is useful for preparing modules for equivalence checking.\n");
246 log("\n");
247 log(" -evert\n");
248 log(" also turn connections to instances of other modules to additional\n");
249 log(" inputs and outputs and remove the module instances.\n");
250 log("\n");
251 log(" -evert-dff\n");
252 log(" turn flip-flops to sets of inputs and outputs.\n");
253 log("\n");
254 log(" -sep <separator>\n");
255 log(" when creating new wire/port names, the original object name is suffixed\n");
256 log(" with this separator (default: '.') and the port name or a type\n");
257 log(" designator for the exposed signal.\n");
258 log("\n");
259 }
260 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
261 {
262 bool flag_shared = false;
263 bool flag_evert = false;
264 bool flag_dff = false;
265 bool flag_cut = false;
266 bool flag_input = false;
267 bool flag_evert_dff = false;
268 std::string sep = ".";
269
270 log_header(design, "Executing EXPOSE pass (exposing internal signals as outputs).\n");
271
272 size_t argidx;
273 for (argidx = 1; argidx < args.size(); argidx++)
274 {
275 if (args[argidx] == "-shared") {
276 flag_shared = true;
277 continue;
278 }
279 if (args[argidx] == "-evert") {
280 flag_evert = true;
281 continue;
282 }
283 if (args[argidx] == "-dff") {
284 flag_dff = true;
285 continue;
286 }
287 if (args[argidx] == "-cut" && !flag_input) {
288 flag_cut = true;
289 continue;
290 }
291 if (args[argidx] == "-input" && !flag_cut) {
292 flag_input = true;
293 continue;
294 }
295 if (args[argidx] == "-evert-dff") {
296 flag_evert_dff = true;
297 continue;
298 }
299 if (args[argidx] == "-sep" && argidx+1 < args.size()) {
300 sep = args[++argidx];
301 continue;
302 }
303 break;
304 }
305 extra_args(args, argidx, design);
306
307 CellTypes ct(design);
308
309 std::map<RTLIL::Module*, std::map<RTLIL::IdString, dff_map_info_t>> dff_dq_maps;
310 std::map<RTLIL::Module*, std::set<RTLIL::IdString>> dff_cells;
311
312 if (flag_evert_dff)
313 {
314 RTLIL::Module *first_module = NULL;
315 std::set<RTLIL::IdString> shared_dff_wires;
316
317 for (auto &mod_it : design->modules_)
318 {
319 if (!design->selected(mod_it.second))
320 continue;
321
322 create_dff_dq_map(dff_dq_maps[mod_it.second], design, mod_it.second);
323
324 if (!flag_shared)
325 continue;
326
327 if (first_module == NULL) {
328 for (auto &it : dff_dq_maps[mod_it.second])
329 shared_dff_wires.insert(it.first);
330 first_module = mod_it.second;
331 } else {
332 std::set<RTLIL::IdString> new_shared_dff_wires;
333 for (auto &it : shared_dff_wires) {
334 if (!dff_dq_maps[mod_it.second].count(it))
335 continue;
336 if (!compare_wires(first_module->wires_.at(it), mod_it.second->wires_.at(it)))
337 continue;
338 new_shared_dff_wires.insert(it);
339 }
340 shared_dff_wires.swap(new_shared_dff_wires);
341 }
342 }
343
344 if (flag_shared)
345 for (auto &map_it : dff_dq_maps)
346 {
347 std::map<RTLIL::IdString, dff_map_info_t> new_map;
348 for (auto &it : map_it.second)
349 if (shared_dff_wires.count(it.first))
350 new_map[it.first] = it.second;
351 map_it.second.swap(new_map);
352 }
353
354 for (auto &it1 : dff_dq_maps)
355 for (auto &it2 : it1.second)
356 for (auto &it3 : it2.second.cells)
357 dff_cells[it1.first].insert(it3);
358 }
359
360 std::set<RTLIL::IdString> shared_wires, shared_cells;
361 std::set<RTLIL::IdString> used_names;
362
363 if (flag_shared)
364 {
365 RTLIL::Module *first_module = NULL;
366
367 for (auto &mod_it : design->modules_)
368 {
369 RTLIL::Module *module = mod_it.second;
370
371 if (!design->selected(module))
372 continue;
373
374 std::set<RTLIL::IdString> dff_wires;
375 if (flag_dff)
376 find_dff_wires(dff_wires, module);
377
378 if (first_module == NULL)
379 {
380 for (auto &it : module->wires_)
381 if (design->selected(module, it.second) && consider_wire(it.second, dff_dq_maps[module]))
382 if (!flag_dff || dff_wires.count(it.first))
383 shared_wires.insert(it.first);
384
385 if (flag_evert)
386 for (auto &it : module->cells_)
387 if (design->selected(module, it.second) && consider_cell(design, dff_cells[module], it.second))
388 shared_cells.insert(it.first);
389
390 first_module = module;
391 }
392 else
393 {
394 std::vector<RTLIL::IdString> delete_shared_wires, delete_shared_cells;
395
396 for (auto &it : shared_wires)
397 {
398 RTLIL::Wire *wire;
399
400 if (module->wires_.count(it) == 0)
401 goto delete_shared_wire;
402
403 wire = module->wires_.at(it);
404
405 if (!design->selected(module, wire))
406 goto delete_shared_wire;
407 if (!consider_wire(wire, dff_dq_maps[module]))
408 goto delete_shared_wire;
409 if (!compare_wires(first_module->wires_.at(it), wire))
410 goto delete_shared_wire;
411 if (flag_dff && !dff_wires.count(it))
412 goto delete_shared_wire;
413
414 if (0)
415 delete_shared_wire:
416 delete_shared_wires.push_back(it);
417 }
418
419 if (flag_evert)
420 for (auto &it : shared_cells)
421 {
422 RTLIL::Cell *cell;
423
424 if (module->cells_.count(it) == 0)
425 goto delete_shared_cell;
426
427 cell = module->cells_.at(it);
428
429 if (!design->selected(module, cell))
430 goto delete_shared_cell;
431 if (!consider_cell(design, dff_cells[module], cell))
432 goto delete_shared_cell;
433 if (!compare_cells(first_module->cells_.at(it), cell))
434 goto delete_shared_cell;
435
436 if (0)
437 delete_shared_cell:
438 delete_shared_cells.push_back(it);
439 }
440
441 for (auto &it : delete_shared_wires)
442 shared_wires.erase(it);
443 for (auto &it : delete_shared_cells)
444 shared_cells.erase(it);
445 }
446 }
447 }
448
449 for (auto &mod_it : design->modules_)
450 {
451 RTLIL::Module *module = mod_it.second;
452
453 if (!design->selected(module))
454 continue;
455
456 std::set<RTLIL::IdString> dff_wires;
457 if (flag_dff && !flag_shared)
458 find_dff_wires(dff_wires, module);
459
460 SigMap sigmap(module);
461
462 SigMap out_to_in_map;
463
464 for (auto &it : module->wires_)
465 {
466 if (flag_shared) {
467 if (shared_wires.count(it.first) == 0)
468 continue;
469 } else {
470 if (!design->selected(module, it.second) || !consider_wire(it.second, dff_dq_maps[module]))
471 continue;
472 if (flag_dff && !dff_wires.count(it.first))
473 continue;
474 }
475
476 if (flag_input)
477 {
478 if (!it.second->port_input) {
479 it.second->port_input = true;
480 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.second->name));
481 RTLIL::Wire *w = module->addWire(NEW_ID, GetSize(it.second));
482 out_to_in_map.add(it.second, w);
483 }
484 }
485 else
486 {
487 if (!it.second->port_output) {
488 it.second->port_output = true;
489 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.second->name));
490 }
491
492 if (flag_cut) {
493 RTLIL::Wire *in_wire = add_new_wire(module, it.second->name.str() + sep + "i", it.second->width);
494 in_wire->port_input = true;
495 out_to_in_map.add(sigmap(it.second), in_wire);
496 }
497 }
498 }
499
500 if (flag_input)
501 {
502 for (auto &it : module->cells_) {
503 if (!ct.cell_known(it.second->type))
504 continue;
505 for (auto &conn : it.second->connections_)
506 if (ct.cell_output(it.second->type, conn.first))
507 conn.second = out_to_in_map(sigmap(conn.second));
508 }
509
510 for (auto &conn : module->connections_)
511 conn.first = out_to_in_map(conn.first);
512 }
513
514 if (flag_cut)
515 {
516 for (auto &it : module->cells_) {
517 if (!ct.cell_known(it.second->type))
518 continue;
519 for (auto &conn : it.second->connections_)
520 if (ct.cell_input(it.second->type, conn.first))
521 conn.second = out_to_in_map(sigmap(conn.second));
522 }
523
524 for (auto &conn : module->connections_)
525 conn.second = out_to_in_map(sigmap(conn.second));
526 }
527
528 std::set<RTLIL::SigBit> set_q_bits;
529
530 for (auto &dq : dff_dq_maps[module])
531 {
532 if (!module->wires_.count(dq.first))
533 continue;
534
535 RTLIL::Wire *wire = module->wires_.at(dq.first);
536 std::set<RTLIL::SigBit> wire_bits_set = sigmap(wire).to_sigbit_set();
537 std::vector<RTLIL::SigBit> wire_bits_vec = sigmap(wire).to_sigbit_vector();
538
539 dff_map_info_t &info = dq.second;
540
541 RTLIL::Wire *wire_dummy_q = add_new_wire(module, NEW_ID, 0);
542
543 for (auto &cell_name : info.cells) {
544 RTLIL::Cell *cell = module->cells_.at(cell_name);
545 std::vector<RTLIL::SigBit> cell_q_bits = sigmap(cell->getPort("\\Q")).to_sigbit_vector();
546 for (auto &bit : cell_q_bits)
547 if (wire_bits_set.count(bit))
548 bit = RTLIL::SigBit(wire_dummy_q, wire_dummy_q->width++);
549 cell->setPort("\\Q", cell_q_bits);
550 }
551
552 RTLIL::Wire *wire_q = add_new_wire(module, wire->name.str() + sep + "q", wire->width);
553 wire_q->port_input = true;
554 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_q->name));
555
556 RTLIL::SigSig connect_q;
557 for (size_t i = 0; i < wire_bits_vec.size(); i++) {
558 if (set_q_bits.count(wire_bits_vec[i]))
559 continue;
560 connect_q.first.append(wire_bits_vec[i]);
561 connect_q.second.append(RTLIL::SigBit(wire_q, i));
562 set_q_bits.insert(wire_bits_vec[i]);
563 }
564 module->connect(connect_q);
565
566 RTLIL::Wire *wire_d = add_new_wire(module, wire->name.str() + sep + "d", wire->width);
567 wire_d->port_output = true;
568 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_d->name));
569 module->connect(RTLIL::SigSig(wire_d, info.sig_d));
570
571 RTLIL::Wire *wire_c = add_new_wire(module, wire->name.str() + sep + "c");
572 wire_c->port_output = true;
573 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_c->name));
574 if (info.clk_polarity) {
575 module->connect(RTLIL::SigSig(wire_c, info.sig_clk));
576 } else {
577 RTLIL::Cell *c = module->addCell(NEW_ID, "$not");
578 c->parameters["\\A_SIGNED"] = 0;
579 c->parameters["\\A_WIDTH"] = 1;
580 c->parameters["\\Y_WIDTH"] = 1;
581 c->setPort("\\A", info.sig_clk);
582 c->setPort("\\Y", wire_c);
583 }
584
585 if (info.sig_arst != RTLIL::State::Sm)
586 {
587 RTLIL::Wire *wire_r = add_new_wire(module, wire->name.str() + sep + "r");
588 wire_r->port_output = true;
589 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_r->name));
590 if (info.arst_polarity) {
591 module->connect(RTLIL::SigSig(wire_r, info.sig_arst));
592 } else {
593 RTLIL::Cell *c = module->addCell(NEW_ID, "$not");
594 c->parameters["\\A_SIGNED"] = 0;
595 c->parameters["\\A_WIDTH"] = 1;
596 c->parameters["\\Y_WIDTH"] = 1;
597 c->setPort("\\A", info.sig_arst);
598 c->setPort("\\Y", wire_r);
599 }
600
601 RTLIL::Wire *wire_v = add_new_wire(module, wire->name.str() + sep + "v", wire->width);
602 wire_v->port_output = true;
603 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_v->name));
604 module->connect(RTLIL::SigSig(wire_v, info.arst_value));
605 }
606 }
607
608 if (flag_evert)
609 {
610 std::vector<RTLIL::Cell*> delete_cells;
611
612 for (auto &it : module->cells_)
613 {
614 if (flag_shared) {
615 if (shared_cells.count(it.first) == 0)
616 continue;
617 } else {
618 if (!design->selected(module, it.second) || !consider_cell(design, dff_cells[module], it.second))
619 continue;
620 }
621
622 RTLIL::Cell *cell = it.second;
623
624 if (design->modules_.count(cell->type))
625 {
626 RTLIL::Module *mod = design->modules_.at(cell->type);
627
628 for (auto &it : mod->wires_)
629 {
630 RTLIL::Wire *p = it.second;
631 if (!p->port_input && !p->port_output)
632 continue;
633
634 RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + RTLIL::unescape_id(p->name), p->width);
635 if (p->port_input)
636 w->port_output = true;
637 if (p->port_output)
638 w->port_input = true;
639
640 log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name), RTLIL::id2cstr(cell->type));
641
642 RTLIL::SigSpec sig;
643 if (cell->hasPort(p->name))
644 sig = cell->getPort(p->name);
645 sig.extend_u0(w->width);
646 if (w->port_input)
647 module->connect(RTLIL::SigSig(sig, w));
648 else
649 module->connect(RTLIL::SigSig(w, sig));
650 }
651 }
652 else
653 {
654 for (auto &it : cell->connections())
655 {
656 RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + RTLIL::unescape_id(it.first), it.second.size());
657 if (ct.cell_input(cell->type, it.first))
658 w->port_output = true;
659 if (ct.cell_output(cell->type, it.first))
660 w->port_input = true;
661
662 log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name), RTLIL::id2cstr(cell->type));
663
664 if (w->port_input)
665 module->connect(RTLIL::SigSig(it.second, w));
666 else
667 module->connect(RTLIL::SigSig(w, it.second));
668 }
669 }
670
671 delete_cells.push_back(cell);
672 }
673
674 for (auto cell : delete_cells) {
675 log("Removing cell: %s/%s (%s)\n", log_id(module), log_id(cell), log_id(cell->type));
676 module->remove(cell);
677 }
678 }
679
680 module->fixup_ports();
681 }
682 }
683 } ExposePass;
684
685 PRIVATE_NAMESPACE_END