respect hide_internal flag
[yosys.git] / passes / sat / expose.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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->module(cell->type) == nullptr))
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 cell : module->cells()) {
89 if (ct.cell_known(cell->type) && cell->hasPort(ID::Q))
90 dffsignals.add(sigmap(cell->getPort(ID::Q)));
91 }
92
93 for (auto w : module->wires()) {
94 if (dffsignals.check_any(w))
95 dff_wires.insert(w->name);
96 }
97 }
98
99 void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::Module *module)
100 {
101 std::map<RTLIL::SigBit, dff_map_bit_info_t> bit_info;
102 SigMap sigmap(module);
103
104 for (auto cell : module->selected_cells())
105 {
106 dff_map_bit_info_t info;
107 info.bit_d = RTLIL::State::Sm;
108 info.bit_clk = RTLIL::State::Sm;
109 info.bit_arst = RTLIL::State::Sm;
110 info.clk_polarity = false;
111 info.arst_polarity = false;
112 info.arst_value = RTLIL::State::Sm;
113 info.cell = cell;
114
115 if (info.cell->type == ID($dff)) {
116 info.bit_clk = sigmap(info.cell->getPort(ID::CLK)).as_bit();
117 info.clk_polarity = info.cell->parameters.at(ID::CLK_POLARITY).as_bool();
118 std::vector<RTLIL::SigBit> sig_d = sigmap(info.cell->getPort(ID::D)).to_sigbit_vector();
119 std::vector<RTLIL::SigBit> sig_q = sigmap(info.cell->getPort(ID::Q)).to_sigbit_vector();
120 for (size_t i = 0; i < sig_d.size(); i++) {
121 info.bit_d = sig_d.at(i);
122 bit_info[sig_q.at(i)] = info;
123 }
124 continue;
125 }
126
127 if (info.cell->type == ID($adff)) {
128 info.bit_clk = sigmap(info.cell->getPort(ID::CLK)).as_bit();
129 info.bit_arst = sigmap(info.cell->getPort(ID::ARST)).as_bit();
130 info.clk_polarity = info.cell->parameters.at(ID::CLK_POLARITY).as_bool();
131 info.arst_polarity = info.cell->parameters.at(ID::ARST_POLARITY).as_bool();
132 std::vector<RTLIL::SigBit> sig_d = sigmap(info.cell->getPort(ID::D)).to_sigbit_vector();
133 std::vector<RTLIL::SigBit> sig_q = sigmap(info.cell->getPort(ID::Q)).to_sigbit_vector();
134 std::vector<RTLIL::State> arst_value = info.cell->parameters.at(ID::ARST_VALUE).bits;
135 for (size_t i = 0; i < sig_d.size(); i++) {
136 info.bit_d = sig_d.at(i);
137 info.arst_value = arst_value.at(i);
138 bit_info[sig_q.at(i)] = info;
139 }
140 continue;
141 }
142
143 if (info.cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) {
144 info.bit_clk = sigmap(info.cell->getPort(ID::C)).as_bit();
145 info.clk_polarity = info.cell->type == ID($_DFF_P_);
146 info.bit_d = sigmap(info.cell->getPort(ID::D)).as_bit();
147 bit_info[sigmap(info.cell->getPort(ID::Q)).as_bit()] = info;
148 continue;
149 }
150
151 if (info.cell->type.size() == 10 && info.cell->type.begins_with("$_DFF_")) {
152 info.bit_clk = sigmap(info.cell->getPort(ID::C)).as_bit();
153 info.bit_arst = sigmap(info.cell->getPort(ID::R)).as_bit();
154 info.clk_polarity = info.cell->type[6] == 'P';
155 info.arst_polarity = info.cell->type[7] == 'P';
156 info.arst_value = info.cell->type[0] == '1' ? RTLIL::State::S1 : RTLIL::State::S0;
157 info.bit_d = sigmap(info.cell->getPort(ID::D)).as_bit();
158 bit_info[sigmap(info.cell->getPort(ID::Q)).as_bit()] = info;
159 continue;
160 }
161 }
162
163 std::map<RTLIL::IdString, dff_map_info_t> empty_dq_map;
164 for (auto w : module->wires())
165 {
166 if (!consider_wire(w, empty_dq_map))
167 continue;
168
169 std::vector<RTLIL::SigBit> bits_q = sigmap(w).to_sigbit_vector();
170 std::vector<RTLIL::SigBit> bits_d;
171 std::vector<RTLIL::State> arst_value;
172 std::set<RTLIL::Cell*> cells;
173
174 if (bits_q.empty() || !bit_info.count(bits_q.front()))
175 continue;
176
177 dff_map_bit_info_t ref_info = bit_info.at(bits_q.front());
178 for (auto &bit : bits_q) {
179 if (!bit_info.count(bit))
180 break;
181 dff_map_bit_info_t info = bit_info.at(bit);
182 if (info.bit_clk != ref_info.bit_clk)
183 break;
184 if (info.bit_arst != ref_info.bit_arst)
185 break;
186 if (info.clk_polarity != ref_info.clk_polarity)
187 break;
188 if (info.arst_polarity != ref_info.arst_polarity)
189 break;
190 bits_d.push_back(info.bit_d);
191 arst_value.push_back(info.arst_value);
192 cells.insert(info.cell);
193 }
194
195 if (bits_d.size() != bits_q.size())
196 continue;
197
198 dff_map_info_t info;
199 info.sig_d = bits_d;
200 info.sig_clk = ref_info.bit_clk;
201 info.sig_arst = ref_info.bit_arst;
202 info.clk_polarity = ref_info.clk_polarity;
203 info.arst_polarity = ref_info.arst_polarity;
204 info.arst_value = arst_value;
205 for (auto it : cells)
206 info.cells.push_back(it->name);
207 map[w->name] = info;
208 }
209 }
210
211 RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width = 1)
212 {
213 if (module->count_id(name))
214 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));
215 return module->addWire(name, width);
216 }
217
218 struct ExposePass : public Pass {
219 ExposePass() : Pass("expose", "convert internal signals to module ports") { }
220 void help() override
221 {
222 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
223 log("\n");
224 log(" expose [options] [selection]\n");
225 log("\n");
226 log("This command exposes all selected internal signals of a module as additional\n");
227 log("outputs.\n");
228 log("\n");
229 log(" -dff\n");
230 log(" only consider wires that are directly driven by register cell.\n");
231 log("\n");
232 log(" -cut\n");
233 log(" when exposing a wire, create an input/output pair and cut the internal\n");
234 log(" signal path at that wire.\n");
235 log("\n");
236 log(" -input\n");
237 log(" when exposing a wire, create an input port and disconnect the internal\n");
238 log(" driver.\n");
239 log("\n");
240 log(" -shared\n");
241 log(" only expose those signals that are shared among the selected modules.\n");
242 log(" this is useful for preparing modules for equivalence checking.\n");
243 log("\n");
244 log(" -evert\n");
245 log(" also turn connections to instances of other modules to additional\n");
246 log(" inputs and outputs and remove the module instances.\n");
247 log("\n");
248 log(" -evert-dff\n");
249 log(" turn flip-flops to sets of inputs and outputs.\n");
250 log("\n");
251 log(" -sep <separator>\n");
252 log(" when creating new wire/port names, the original object name is suffixed\n");
253 log(" with this separator (default: '.') and the port name or a type\n");
254 log(" designator for the exposed signal.\n");
255 log("\n");
256 }
257 void execute(std::vector<std::string> args, RTLIL::Design *design) override
258 {
259 bool flag_shared = false;
260 bool flag_evert = false;
261 bool flag_dff = false;
262 bool flag_cut = false;
263 bool flag_input = false;
264 bool flag_evert_dff = false;
265 std::string sep = ".";
266
267 log_header(design, "Executing EXPOSE pass (exposing internal signals as outputs).\n");
268
269 size_t argidx;
270 for (argidx = 1; argidx < args.size(); argidx++)
271 {
272 if (args[argidx] == "-shared") {
273 flag_shared = true;
274 continue;
275 }
276 if (args[argidx] == "-evert") {
277 flag_evert = true;
278 continue;
279 }
280 if (args[argidx] == "-dff") {
281 flag_dff = true;
282 continue;
283 }
284 if (args[argidx] == "-cut") {
285 if (flag_input)
286 log_cmd_error("Options -cut and -input are mutually exclusive.\n");
287 flag_cut = true;
288 continue;
289 }
290 if (args[argidx] == "-input") {
291 if (flag_cut)
292 log_cmd_error("Options -cut and -input are mutually exclusive.\n");
293 flag_input = true;
294 continue;
295 }
296 if (args[argidx] == "-evert-dff") {
297 flag_evert_dff = true;
298 continue;
299 }
300 if (args[argidx] == "-sep" && argidx+1 < args.size()) {
301 sep = args[++argidx];
302 continue;
303 }
304 break;
305 }
306 extra_args(args, argidx, design);
307
308 CellTypes ct(design);
309
310 std::map<RTLIL::Module*, std::map<RTLIL::IdString, dff_map_info_t>> dff_dq_maps;
311 std::map<RTLIL::Module*, std::set<RTLIL::IdString>> dff_cells;
312
313 if (flag_evert_dff)
314 {
315 RTLIL::Module *first_module = NULL;
316 std::set<RTLIL::IdString> shared_dff_wires;
317
318 for (auto mod : design->selected_modules())
319 {
320 create_dff_dq_map(dff_dq_maps[mod], mod);
321
322 if (!flag_shared)
323 continue;
324
325 if (first_module == NULL) {
326 for (auto &it : dff_dq_maps[mod])
327 shared_dff_wires.insert(it.first);
328 first_module = mod;
329 } else {
330 std::set<RTLIL::IdString> new_shared_dff_wires;
331 for (auto &it : shared_dff_wires) {
332 if (!dff_dq_maps[mod].count(it))
333 continue;
334 if (!compare_wires(first_module->wire(it), mod->wire(it)))
335 continue;
336 new_shared_dff_wires.insert(it);
337 }
338 shared_dff_wires.swap(new_shared_dff_wires);
339 }
340 }
341
342 if (flag_shared)
343 for (auto &map_it : dff_dq_maps)
344 {
345 std::map<RTLIL::IdString, dff_map_info_t> new_map;
346 for (auto &it : map_it.second)
347 if (shared_dff_wires.count(it.first))
348 new_map[it.first] = it.second;
349 map_it.second.swap(new_map);
350 }
351
352 for (auto &it1 : dff_dq_maps)
353 for (auto &it2 : it1.second)
354 for (auto &it3 : it2.second.cells)
355 dff_cells[it1.first].insert(it3);
356 }
357
358 std::set<RTLIL::IdString> shared_wires, shared_cells;
359 std::set<RTLIL::IdString> used_names;
360
361 if (flag_shared)
362 {
363 RTLIL::Module *first_module = NULL;
364
365 for (auto module : design->selected_modules())
366 {
367 std::set<RTLIL::IdString> dff_wires;
368 if (flag_dff)
369 find_dff_wires(dff_wires, module);
370
371 if (first_module == NULL)
372 {
373 for (auto w : module->wires())
374 if (design->selected(module, w) && consider_wire(w, dff_dq_maps[module]))
375 if (!flag_dff || dff_wires.count(w->name))
376 shared_wires.insert(w->name);
377
378 if (flag_evert)
379 for (auto cell : module->cells())
380 if (design->selected(module, cell) && consider_cell(design, dff_cells[module], cell))
381 shared_cells.insert(cell->name);
382
383 first_module = module;
384 }
385 else
386 {
387 std::vector<RTLIL::IdString> delete_shared_wires, delete_shared_cells;
388
389 for (auto &it : shared_wires)
390 {
391 RTLIL::Wire *wire;
392
393 if (module->wire(it) == nullptr)
394 goto delete_shared_wire;
395
396 wire = module->wire(it);
397
398 if (!design->selected(module, wire))
399 goto delete_shared_wire;
400 if (!consider_wire(wire, dff_dq_maps[module]))
401 goto delete_shared_wire;
402 if (!compare_wires(first_module->wire(it), wire))
403 goto delete_shared_wire;
404 if (flag_dff && !dff_wires.count(it))
405 goto delete_shared_wire;
406
407 if (0)
408 delete_shared_wire:
409 delete_shared_wires.push_back(it);
410 }
411
412 if (flag_evert)
413 for (auto &it : shared_cells)
414 {
415 RTLIL::Cell *cell;
416
417 if (module->cell(it) == nullptr)
418 goto delete_shared_cell;
419
420 cell = module->cell(it);
421
422 if (!design->selected(module, cell))
423 goto delete_shared_cell;
424 if (!consider_cell(design, dff_cells[module], cell))
425 goto delete_shared_cell;
426 if (!compare_cells(first_module->cell(it), cell))
427 goto delete_shared_cell;
428
429 if (0)
430 delete_shared_cell:
431 delete_shared_cells.push_back(it);
432 }
433
434 for (auto &it : delete_shared_wires)
435 shared_wires.erase(it);
436 for (auto &it : delete_shared_cells)
437 shared_cells.erase(it);
438 }
439 }
440 }
441
442 for (auto module : design->selected_modules())
443 {
444 std::set<RTLIL::IdString> dff_wires;
445 if (flag_dff && !flag_shared)
446 find_dff_wires(dff_wires, module);
447
448 SigMap sigmap(module);
449
450 SigMap out_to_in_map;
451
452 std::map<RTLIL::Wire*, RTLIL::IdString> wire_map;
453
454 for (auto w : module->wires())
455 {
456 if (flag_shared) {
457 if (shared_wires.count(w->name) == 0)
458 continue;
459 } else {
460 if (!design->selected(module, w) || !consider_wire(w, dff_dq_maps[module]))
461 continue;
462 if (flag_dff && !dff_wires.count(w->name))
463 continue;
464 }
465
466 if (flag_input)
467 {
468 if (!w->port_input) {
469 w->port_input = true;
470 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name));
471 wire_map[w] = NEW_ID;
472 }
473 }
474 else
475 {
476 if (!w->port_output) {
477 w->port_output = true;
478 log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name));
479 }
480
481 if (flag_cut) {
482 wire_map[w] = w->name.str() + sep + "i";
483 }
484 }
485 }
486
487 if (flag_input)
488 {
489 for (auto &wm : wire_map)
490 {
491 RTLIL::Wire *in_wire = module->addWire(wm.second, GetSize(wm.first));
492 out_to_in_map.add(wm.first, in_wire);
493 }
494
495 for (auto cell : module->cells()) {
496 if (!ct.cell_known(cell->type))
497 continue;
498 for (auto &conn : cell->connections_)
499 if (ct.cell_output(cell->type, conn.first))
500 conn.second = out_to_in_map(sigmap(conn.second));
501 }
502
503 for (auto &conn : module->connections_)
504 conn.first = out_to_in_map(conn.first);
505 }
506
507 if (flag_cut)
508 {
509 for (auto &wm : wire_map)
510 {
511 RTLIL::Wire *in_wire = add_new_wire(module, wm.second, wm.first->width);
512 in_wire->port_input = true;
513 out_to_in_map.add(sigmap(wm.first), in_wire);
514 }
515
516 for (auto cell : module->cells()) {
517 if (!ct.cell_known(cell->type))
518 continue;
519 for (auto &conn : cell->connections_)
520 if (ct.cell_input(cell->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->wire(dq.first) == nullptr)
533 continue;
534
535 RTLIL::Wire *wire = module->wire(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->cell(cell_name);
545 std::vector<RTLIL::SigBit> cell_q_bits = sigmap(cell->getPort(ID::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(ID::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, ID($not));
578 c->parameters[ID::A_SIGNED] = 0;
579 c->parameters[ID::A_WIDTH] = 1;
580 c->parameters[ID::Y_WIDTH] = 1;
581 c->setPort(ID::A, info.sig_clk);
582 c->setPort(ID::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, ID($not));
594 c->parameters[ID::A_SIGNED] = 0;
595 c->parameters[ID::A_WIDTH] = 1;
596 c->parameters[ID::Y_WIDTH] = 1;
597 c->setPort(ID::A, info.sig_arst);
598 c->setPort(ID::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 cell : module->cells())
613 {
614 if (flag_shared) {
615 if (shared_cells.count(cell->name) == 0)
616 continue;
617 } else {
618 if (!design->selected(module, cell) || !consider_cell(design, dff_cells[module], cell))
619 continue;
620 }
621
622 if (design->module(cell->type) != nullptr)
623 {
624 RTLIL::Module *mod = design->module(cell->type);
625
626 for (auto p : mod->wires())
627 {
628 if (!p->port_input && !p->port_output)
629 continue;
630
631 RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + RTLIL::unescape_id(p->name), p->width);
632 if (p->port_input)
633 w->port_output = true;
634 if (p->port_output)
635 w->port_input = true;
636
637 log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name), RTLIL::id2cstr(cell->type));
638
639 RTLIL::SigSpec sig;
640 if (cell->hasPort(p->name))
641 sig = cell->getPort(p->name);
642 sig.extend_u0(w->width);
643 if (w->port_input)
644 module->connect(RTLIL::SigSig(sig, w));
645 else
646 module->connect(RTLIL::SigSig(w, sig));
647 }
648 }
649 else
650 {
651 for (auto &it : cell->connections())
652 {
653 RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + RTLIL::unescape_id(it.first), it.second.size());
654 if (ct.cell_input(cell->type, it.first))
655 w->port_output = true;
656 if (ct.cell_output(cell->type, it.first))
657 w->port_input = true;
658
659 log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name), RTLIL::id2cstr(cell->type));
660
661 if (w->port_input)
662 module->connect(RTLIL::SigSig(it.second, w));
663 else
664 module->connect(RTLIL::SigSig(w, it.second));
665 }
666 }
667
668 delete_cells.push_back(cell);
669 }
670
671 for (auto cell : delete_cells) {
672 log("Removing cell: %s/%s (%s)\n", log_id(module), log_id(cell), log_id(cell->type));
673 module->remove(cell);
674 }
675 }
676
677 module->fixup_ports();
678 }
679 }
680 } ExposePass;
681
682 PRIVATE_NAMESPACE_END