2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
26 struct DeminoutPass
: public Pass
{
27 DeminoutPass() : Pass("deminout", "demote inout ports to input or output") { }
28 void help() YS_OVERRIDE
31 log(" deminout [options] [selection]\n");
33 log("\"Demote\" inout ports to input or output ports, if possible.\n");
36 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
38 log_header(design
, "Executing DEMINOUT pass (demote inout ports to input or output).\n");
41 for (argidx
= 1; argidx
< args
.size(); argidx
++)
43 // if (args[argidx] == "-bits") {
49 extra_args(args
, argidx
, design
);
51 bool keep_running
= true;
57 for (auto module
: design
->selected_modules())
59 SigMap
sigmap(module
);
60 pool
<SigBit
> bits_written
, bits_used
, bits_inout
, bits_tribuf
;
61 dict
<SigBit
, int> bits_numports
;
63 for (auto wire
: module
->wires())
65 for (auto bit
: sigmap(wire
))
68 for (auto cell
: module
->cells())
69 for (auto &conn
: cell
->connections())
71 bool cellport_out
= cell
->output(conn
.first
) || !cell
->known();
72 bool cellport_in
= cell
->input(conn
.first
) || !cell
->known();
74 if (cellport_out
&& cellport_in
)
75 for (auto bit
: sigmap(conn
.second
))
76 bits_inout
.insert(bit
);
79 for (auto bit
: sigmap(conn
.second
))
80 bits_written
.insert(bit
);
83 for (auto bit
: sigmap(conn
.second
))
84 bits_used
.insert(bit
);
86 if (conn
.first
== "\\Y" && cell
->type
.in("$mux", "$pmux", "$_MUX_", "$_TBUF_", "$tribuf"))
88 bool tribuf
= cell
->type
.in("$_TBUF_", "$tribuf");
91 for (auto &c
: cell
->connections()) {
92 if (!c
.first
.in("\\A", "\\B"))
94 for (auto b
: sigmap(c
.second
))
101 for (auto bit
: sigmap(conn
.second
))
102 bits_tribuf
.insert(bit
);
106 for (auto wire
: module
->selected_wires())
107 if (wire
->port_input
&& wire
->port_output
)
109 bool new_input
= false;
110 bool new_output
= false;
112 for (auto bit
: sigmap(wire
))
114 if (bits_numports
[bit
] > 1 || bits_inout
.count(bit
))
115 new_input
= true, new_output
= true;
116 if (bit
== State::S0
|| bit
== State::S1
)
118 if (bits_written
.count(bit
)) {
120 if (bits_tribuf
.count(bit
))
124 if (bits_used
.count(bit
))
129 if (new_input
!= new_output
) {
130 log("Demoting inout port %s.%s to %s.\n", log_id(module
), log_id(wire
), new_input
? "input" : "output");
131 wire
->port_input
= new_input
;
132 wire
->port_output
= new_output
;
141 PRIVATE_NAMESPACE_END