Revert "Merge pull request #1917 from YosysHQ/eddie/abc9_delay_check"
[yosys.git] / passes / cmds / connect.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/rtlil.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/celltypes.h"
24 #include "kernel/log.h"
25
26 USING_YOSYS_NAMESPACE
27 PRIVATE_NAMESPACE_BEGIN
28
29 static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap &sigmap, RTLIL::SigSpec &sig)
30 {
31 CellTypes ct(design);
32
33 RTLIL::Wire *dummy_wire = module->addWire(NEW_ID, sig.size());
34
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);
39
40 for (auto &conn : module->connections_)
41 sigmap(conn.first).replace(sig, dummy_wire, &conn.first);
42 }
43
44 struct ConnectPass : public Pass {
45 ConnectPass() : Pass("connect", "create or remove connections") { }
46 void help() YS_OVERRIDE
47 {
48 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
49 log("\n");
50 log(" connect [-nomap] [-nounset] -set <lhs-expr> <rhs-expr>\n");
51 log("\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");
56 log("\n");
57 log("\n");
58 log(" connect [-nomap] -unset <expr>\n");
59 log("\n");
60 log("Unconnect all existing drivers for the specified expression.\n");
61 log("\n");
62 log("\n");
63 log(" connect [-nomap] -port <cell> <port> <expr>\n");
64 log("\n");
65 log("Connect the specified cell port to the specified cell port.\n");
66 log("\n");
67 log("\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");
71 log("\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");
74 log("\n");
75 log("This command does not operate on module with processes.\n");
76 log("\n");
77 }
78 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
79 {
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));
84 module = mod;
85 }
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");
90
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;
94
95 size_t argidx;
96 for (argidx = 1; argidx < args.size(); argidx++)
97 {
98 std::string arg = args[argidx];
99 if (arg == "-nounset") {
100 flag_nounset = true;
101 continue;
102 }
103 if (arg == "-nomap") {
104 flag_nomap = true;
105 continue;
106 }
107 if (arg == "-set" && argidx+2 < args.size()) {
108 set_lhs = args[++argidx];
109 set_rhs = args[++argidx];
110 continue;
111 }
112 if (arg == "-unset" && argidx+1 < args.size()) {
113 unset_expr = args[++argidx];
114 continue;
115 }
116 if (arg == "-port" && argidx+3 < args.size()) {
117 port_cell = args[++argidx];
118 port_port = args[++argidx];
119 port_expr = args[++argidx];
120 continue;
121 }
122 break;
123 }
124
125 SigMap sigmap;
126 if (!flag_nomap)
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]);
133 }
134
135 if (!set_lhs.empty())
136 {
137 if (!unset_expr.empty() || !port_cell.empty())
138 log_cmd_error("Can't use -set together with -unset and/or -port.\n");
139
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());
145
146 sigmap.apply(sig_lhs);
147 sigmap.apply(sig_rhs);
148
149 if (!flag_nounset)
150 unset_drivers(design, module, sigmap, sig_lhs);
151
152 module->connect(RTLIL::SigSig(sig_lhs, sig_rhs));
153 }
154 else
155 if (!unset_expr.empty())
156 {
157 if (!port_cell.empty() || flag_nounset)
158 log_cmd_error("Can't use -unset together with -port and/or -nounset.\n");
159
160 RTLIL::SigSpec sig;
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());
163
164 sigmap.apply(sig);
165 unset_drivers(design, module, sigmap, sig);
166 }
167 else
168 if (!port_cell.empty())
169 {
170 if (flag_nounset)
171 log_cmd_error("Can't use -port together with -nounset.\n");
172
173 if (module->cell(RTLIL::escape_id(port_cell)) == nullptr)
174 log_cmd_error("Can't find cell %s.\n", port_cell.c_str());
175
176 RTLIL::SigSpec sig;
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());
179
180 module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
181 }
182 else
183 log_cmd_error("Expected -set, -unset, or -port.\n");
184 }
185 } ConnectPass;
186
187 PRIVATE_NAMESPACE_END