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/register.h"
21 #include "kernel/rtlil.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/celltypes.h"
24 #include "kernel/log.h"
27 PRIVATE_NAMESPACE_BEGIN
29 static void unset_drivers(RTLIL::Design
*design
, RTLIL::Module
*module
, SigMap
&sigmap
, RTLIL::SigSpec
&sig
)
33 RTLIL::Wire
*dummy_wire
= module
->addWire(NEW_ID
, sig
.size());
35 for (auto cell
: module
->cells())
36 for (auto &port
: cell
->connections_
)
37 if (ct
.cell_output(cell
->type
, port
.first
))
38 sigmap(port
.second
).replace(sig
, dummy_wire
, &port
.second
);
40 for (auto &conn
: module
->connections_
)
41 sigmap(conn
.first
).replace(sig
, dummy_wire
, &conn
.first
);
44 struct ConnectPass
: public Pass
{
45 ConnectPass() : Pass("connect", "create or remove connections") { }
46 void help() YS_OVERRIDE
48 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
50 log(" connect [-nomap] [-nounset] -set <lhs-expr> <rhs-expr>\n");
52 log("Create a connection. This is equivalent to adding the statement 'assign\n");
53 log("<lhs-expr> = <rhs-expr>;' to the Verilog input. Per default, all existing\n");
54 log("drivers for <lhs-expr> are unconnected. This can be overwritten by using\n");
55 log("the -nounset option.\n");
58 log(" connect [-nomap] -unset <expr>\n");
60 log("Unconnect all existing drivers for the specified expression.\n");
63 log(" connect [-nomap] -port <cell> <port> <expr>\n");
65 log("Connect the specified cell port to the specified cell port.\n");
68 log("Per default signal alias names are resolved and all signal names are mapped\n");
69 log("the the signal name of the primary driver. Using the -nomap option deactivates\n");
70 log("this behavior.\n");
72 log("The connect command operates in one module only. Either only one module must\n");
73 log("be selected or an active module must be set using the 'cd' command.\n");
75 log("This command does not operate on module with processes.\n");
78 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
80 RTLIL::Module
*module
= nullptr;
81 for (auto mod
: design
->selected_modules()) {
82 if (module
!= nullptr)
83 log_cmd_error("Multiple modules selected: %s, %s\n", log_id(module
->name
), log_id(mod
->name
));
86 if (module
== nullptr)
87 log_cmd_error("No modules selected.\n");
88 if (!module
->processes
.empty())
89 log_cmd_error("Found processes in selected module.\n");
91 bool flag_nounset
= false, flag_nomap
= false;
92 std::string set_lhs
, set_rhs
, unset_expr
;
93 std::string port_cell
, port_port
, port_expr
;
96 for (argidx
= 1; argidx
< args
.size(); argidx
++)
98 std::string arg
= args
[argidx
];
99 if (arg
== "-nounset") {
103 if (arg
== "-nomap") {
107 if (arg
== "-set" && argidx
+2 < args
.size()) {
108 set_lhs
= args
[++argidx
];
109 set_rhs
= args
[++argidx
];
112 if (arg
== "-unset" && argidx
+1 < args
.size()) {
113 unset_expr
= args
[++argidx
];
116 if (arg
== "-port" && argidx
+3 < args
.size()) {
117 port_cell
= args
[++argidx
];
118 port_port
= args
[++argidx
];
119 port_expr
= args
[++argidx
];
127 for (auto &it
: module
->connections()) {
128 std::vector
<RTLIL::SigBit
> lhs
= it
.first
.to_sigbit_vector();
129 std::vector
<RTLIL::SigBit
> rhs
= it
.first
.to_sigbit_vector();
130 for (size_t i
= 0; i
< lhs
.size(); i
++)
131 if (rhs
[i
].wire
!= nullptr)
132 sigmap
.add(lhs
[i
], rhs
[i
]);
135 if (!set_lhs
.empty())
137 if (!unset_expr
.empty() || !port_cell
.empty())
138 log_cmd_error("Can't use -set together with -unset and/or -port.\n");
140 RTLIL::SigSpec sig_lhs
, sig_rhs
;
141 if (!RTLIL::SigSpec::parse_sel(sig_lhs
, design
, module
, set_lhs
))
142 log_cmd_error("Failed to parse set lhs expression `%s'.\n", set_lhs
.c_str());
143 if (!RTLIL::SigSpec::parse_rhs(sig_lhs
, sig_rhs
, module
, set_rhs
))
144 log_cmd_error("Failed to parse set rhs expression `%s'.\n", set_rhs
.c_str());
146 sigmap
.apply(sig_lhs
);
147 sigmap
.apply(sig_rhs
);
150 unset_drivers(design
, module
, sigmap
, sig_lhs
);
152 module
->connect(RTLIL::SigSig(sig_lhs
, sig_rhs
));
155 if (!unset_expr
.empty())
157 if (!port_cell
.empty() || flag_nounset
)
158 log_cmd_error("Can't use -unset together with -port and/or -nounset.\n");
161 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, unset_expr
))
162 log_cmd_error("Failed to parse unset expression `%s'.\n", unset_expr
.c_str());
165 unset_drivers(design
, module
, sigmap
, sig
);
168 if (!port_cell
.empty())
171 log_cmd_error("Can't use -port together with -nounset.\n");
173 if (module
->cell(RTLIL::escape_id(port_cell
)) == nullptr)
174 log_cmd_error("Can't find cell %s.\n", port_cell
.c_str());
177 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, port_expr
))
178 log_cmd_error("Failed to parse port expression `%s'.\n", port_expr
.c_str());
180 module
->cell(RTLIL::escape_id(port_cell
))->setPort(RTLIL::escape_id(port_port
), sigmap(sig
));
183 log_cmd_error("Expected -set, -unset, or -port.\n");
187 PRIVATE_NAMESPACE_END