Merge branch 'sv_packages' of https://github.com/rubund/yosys
[yosys.git] / passes / techmap / deminout.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/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 struct DeminoutPass : public Pass {
27 DeminoutPass() : Pass("deminout", "demote inout ports to input or output") { }
28 virtual void help()
29 {
30 log("\n");
31 log(" deminout [options] [selection]\n");
32 log("\n");
33 log("\"Demote\" inout ports to input or output ports, if possible.\n");
34 log("\n");
35 }
36 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
37 {
38 log_header(design, "Executing DEMINOUT pass (demote inout ports to input or output).\n");
39
40 size_t argidx;
41 for (argidx = 1; argidx < args.size(); argidx++)
42 {
43 // if (args[argidx] == "-bits") {
44 // flag_bits = true;
45 // continue;
46 // }
47 break;
48 }
49 extra_args(args, argidx, design);
50
51 bool keep_running = true;
52
53 while (keep_running)
54 {
55 keep_running = false;
56
57 for (auto module : design->selected_modules())
58 {
59 SigMap sigmap(module);
60 pool<SigBit> bits_written, bits_used, bits_inout;
61 dict<SigBit, int> bits_numports;
62
63 for (auto wire : module->wires())
64 if (wire->port_id)
65 for (auto bit : sigmap(wire))
66 bits_numports[bit]++;
67
68 for (auto cell : module->cells())
69 for (auto &conn : cell->connections())
70 {
71 bool cellport_out = cell->output(conn.first) || !cell->known();
72 bool cellport_in = cell->input(conn.first) || !cell->known();
73
74 if (cellport_out && cellport_in)
75 for (auto bit : sigmap(conn.second))
76 bits_inout.insert(bit);
77
78 if (cellport_out)
79 for (auto bit : sigmap(conn.second))
80 bits_written.insert(bit);
81
82 if (cellport_in)
83 for (auto bit : sigmap(conn.second))
84 bits_used.insert(bit);
85 }
86
87 for (auto wire : module->selected_wires())
88 if (wire->port_input && wire->port_output)
89 {
90 bool new_input = false;
91 bool new_output = false;
92
93 for (auto bit : sigmap(wire))
94 {
95 if (bits_numports[bit] > 1 || bits_inout.count(bit))
96 new_input = true, new_output = true;
97
98 if (bits_written.count(bit))
99 new_output = true;
100 else if (bits_used.count(bit))
101 new_input = true;
102 }
103
104 if (new_input != new_output) {
105 log("Demoting inout port %s.%s to %s.\n", log_id(module), log_id(wire), new_input ? "input" : "output");
106 wire->port_input = new_input;
107 wire->port_output = new_output;
108 keep_running = true;
109 }
110 }
111 }
112 }
113 }
114 } DeminoutPass;
115
116 PRIVATE_NAMESPACE_END