abc9: generate $abc9_holes design instead of <name>$holes
[yosys.git] / passes / cmds / splice.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/celltypes.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/rtlil.h"
24 #include "kernel/log.h"
25 #include <tuple>
26
27 USING_YOSYS_NAMESPACE
28 PRIVATE_NAMESPACE_BEGIN
29
30 struct SpliceWorker
31 {
32 RTLIL::Design *design;
33 RTLIL::Module *module;
34
35 bool sel_by_cell;
36 bool sel_by_wire;
37 bool sel_any_bit;
38 bool no_outputs;
39 bool do_wires;
40
41 std::set<RTLIL::IdString> ports;
42 std::set<RTLIL::IdString> no_ports;
43
44 CellTypes ct;
45 SigMap sigmap;
46
47 std::vector<RTLIL::SigBit> driven_bits;
48 std::map<RTLIL::SigBit, int> driven_bits_map;
49
50 std::set<RTLIL::SigSpec> driven_chunks;
51 std::map<RTLIL::SigSpec, RTLIL::SigSpec> spliced_signals_cache;
52 std::map<RTLIL::SigSpec, RTLIL::SigSpec> sliced_signals_cache;
53
54 SpliceWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), ct(design), sigmap(module)
55 {
56 }
57
58 RTLIL::SigSpec get_sliced_signal(RTLIL::SigSpec sig)
59 {
60 if (sig.size() == 0 || sig.is_fully_const())
61 return sig;
62
63 if (sliced_signals_cache.count(sig))
64 return sliced_signals_cache.at(sig);
65
66 int offset = 0;
67 int p = driven_bits_map.at(sig.extract(0, 1).as_bit()) - 1;
68 while (driven_bits.at(p) != RTLIL::State::Sm)
69 p--, offset++;
70
71 RTLIL::SigSpec sig_a;
72 for (p++; driven_bits.at(p) != RTLIL::State::Sm; p++)
73 sig_a.append(driven_bits.at(p));
74
75 RTLIL::SigSpec new_sig = sig;
76
77 if (sig_a.size() != sig.size()) {
78 RTLIL::Cell *cell = module->addCell(NEW_ID, ID($slice));
79 cell->parameters[ID::OFFSET] = offset;
80 cell->parameters[ID::A_WIDTH] = sig_a.size();
81 cell->parameters[ID::Y_WIDTH] = sig.size();
82 cell->setPort(ID::A, sig_a);
83 cell->setPort(ID::Y, module->addWire(NEW_ID, sig.size()));
84 new_sig = cell->getPort(ID::Y);
85 }
86
87 sliced_signals_cache[sig] = new_sig;
88
89 return new_sig;
90 }
91
92 RTLIL::SigSpec get_spliced_signal(RTLIL::SigSpec sig)
93 {
94 if (sig.size() == 0 || sig.is_fully_const())
95 return sig;
96
97 if (spliced_signals_cache.count(sig))
98 return spliced_signals_cache.at(sig);
99
100 int last_bit = -1;
101 std::vector<RTLIL::SigSpec> chunks;
102
103 for (auto &bit : sig.to_sigbit_vector())
104 {
105 if (bit.wire == nullptr)
106 {
107 if (last_bit == 0)
108 chunks.back().append(bit);
109 else
110 chunks.push_back(bit);
111 last_bit = 0;
112 continue;
113 }
114
115 if (driven_bits_map.count(bit))
116 {
117 int this_bit = driven_bits_map.at(bit);
118 if (last_bit+1 == this_bit)
119 chunks.back().append(bit);
120 else
121 chunks.push_back(bit);
122 last_bit = this_bit;
123 continue;
124 }
125
126 log(" Failed to generate spliced signal %s.\n", log_signal(sig));
127 spliced_signals_cache[sig] = sig;
128 return sig;
129 }
130
131
132 RTLIL::SigSpec new_sig = get_sliced_signal(chunks.front());
133 for (size_t i = 1; i < chunks.size(); i++) {
134 RTLIL::SigSpec sig2 = get_sliced_signal(chunks[i]);
135 RTLIL::Cell *cell = module->addCell(NEW_ID, ID($concat));
136 cell->parameters[ID::A_WIDTH] = new_sig.size();
137 cell->parameters[ID::B_WIDTH] = sig2.size();
138 cell->setPort(ID::A, new_sig);
139 cell->setPort(ID::B, sig2);
140 cell->setPort(ID::Y, module->addWire(NEW_ID, new_sig.size() + sig2.size()));
141 new_sig = cell->getPort(ID::Y);
142 }
143
144 spliced_signals_cache[sig] = new_sig;
145
146 log(" Created spliced signal: %s -> %s\n", log_signal(sig), log_signal(new_sig));
147 return new_sig;
148 }
149
150 void run()
151 {
152 log("Splicing signals in module %s:\n", log_id(module->name));
153
154 driven_bits.push_back(RTLIL::State::Sm);
155 driven_bits.push_back(RTLIL::State::Sm);
156
157 for (auto wire : module->wires())
158 if (wire->port_input) {
159 RTLIL::SigSpec sig = sigmap(wire);
160 driven_chunks.insert(sig);
161 for (auto &bit : sig.to_sigbit_vector())
162 driven_bits.push_back(bit);
163 driven_bits.push_back(RTLIL::State::Sm);
164 }
165
166 for (auto cell : module->cells())
167 for (auto &conn : cell->connections())
168 if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) {
169 RTLIL::SigSpec sig = sigmap(conn.second);
170 driven_chunks.insert(sig);
171 for (auto &bit : sig.to_sigbit_vector())
172 driven_bits.push_back(bit);
173 driven_bits.push_back(RTLIL::State::Sm);
174 }
175
176 driven_bits.push_back(RTLIL::State::Sm);
177
178 for (size_t i = 0; i < driven_bits.size(); i++)
179 driven_bits_map[driven_bits[i]] = i;
180
181 SigPool selected_bits;
182 if (!sel_by_cell)
183 for (auto wire : module->selected_wires())
184 selected_bits.add(sigmap(wire));
185
186 std::vector<Cell*> mod_cells = module->cells();
187
188 for (auto cell : mod_cells) {
189 if (!sel_by_wire && !design->selected(module, cell))
190 continue;
191 for (auto &conn : cell->connections_)
192 if (ct.cell_input(cell->type, conn.first)) {
193 if (ports.size() > 0 && !ports.count(conn.first))
194 continue;
195 if (no_ports.size() > 0 && no_ports.count(conn.first))
196 continue;
197 RTLIL::SigSpec sig = sigmap(conn.second);
198 if (!sel_by_cell) {
199 if (!sel_any_bit && !selected_bits.check_all(sig))
200 continue;
201 if (sel_any_bit && !selected_bits.check_any(sig))
202 continue;
203 }
204 if (driven_chunks.count(sig) > 0)
205 continue;
206 conn.second = get_spliced_signal(sig);
207 }
208 }
209
210 std::vector<std::pair<RTLIL::Wire*, RTLIL::SigSpec>> rework_wires;
211 std::vector<Wire*> mod_wires = module->wires();
212
213 for (auto wire : mod_wires)
214 if ((!no_outputs && wire->port_output) || (do_wires && wire->name[0] == '\\')) {
215 if (!design->selected(module, wire))
216 continue;
217 RTLIL::SigSpec sig = sigmap(wire);
218 if (driven_chunks.count(sig) > 0)
219 continue;
220 RTLIL::SigSpec new_sig = get_spliced_signal(sig);
221 if (new_sig != sig)
222 rework_wires.push_back(std::pair<RTLIL::Wire*, RTLIL::SigSpec>(wire, new_sig));
223 } else
224 if (!wire->port_input) {
225 RTLIL::SigSpec sig = sigmap(wire);
226 if (spliced_signals_cache.count(sig) && spliced_signals_cache.at(sig) != sig)
227 rework_wires.push_back(std::pair<RTLIL::Wire*, RTLIL::SigSpec>(wire, spliced_signals_cache.at(sig)));
228 else if (sliced_signals_cache.count(sig) && sliced_signals_cache.at(sig) != sig)
229 rework_wires.push_back(std::pair<RTLIL::Wire*, RTLIL::SigSpec>(wire, sliced_signals_cache.at(sig)));
230 }
231
232 for (auto &it : rework_wires)
233 {
234 RTLIL::IdString orig_name = it.first->name;
235 module->rename(it.first, NEW_ID);
236
237 RTLIL::Wire *new_port = module->addWire(orig_name, it.first);
238 it.first->port_id = 0;
239 it.first->port_input = false;
240 it.first->port_output = false;
241
242 module->connect(RTLIL::SigSig(new_port, it.second));
243 }
244 }
245 };
246
247 struct SplicePass : public Pass {
248 SplicePass() : Pass("splice", "create explicit splicing cells") { }
249 void help() YS_OVERRIDE
250 {
251 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
252 log("\n");
253 log(" splice [options] [selection]\n");
254 log("\n");
255 log("This command adds $slice and $concat cells to the design to make the splicing\n");
256 log("of multi-bit signals explicit. This for example is useful for coarse grain\n");
257 log("synthesis, where dedicated hardware is needed to splice signals.\n");
258 log("\n");
259 log(" -sel_by_cell\n");
260 log(" only select the cell ports to rewire by the cell. if the selection\n");
261 log(" contains a cell, than all cell inputs are rewired, if necessary.\n");
262 log("\n");
263 log(" -sel_by_wire\n");
264 log(" only select the cell ports to rewire by the wire. if the selection\n");
265 log(" contains a wire, than all cell ports driven by this wire are wired,\n");
266 log(" if necessary.\n");
267 log("\n");
268 log(" -sel_any_bit\n");
269 log(" it is sufficient if the driver of any bit of a cell port is selected.\n");
270 log(" by default all bits must be selected.\n");
271 log("\n");
272 log(" -wires\n");
273 log(" also add $slice and $concat cells to drive otherwise unused wires.\n");
274 log("\n");
275 log(" -no_outputs\n");
276 log(" do not rewire selected module outputs.\n");
277 log("\n");
278 log(" -port <name>\n");
279 log(" only rewire cell ports with the specified name. can be used multiple\n");
280 log(" times. implies -no_output.\n");
281 log("\n");
282 log(" -no_port <name>\n");
283 log(" do not rewire cell ports with the specified name. can be used multiple\n");
284 log(" times. can not be combined with -port <name>.\n");
285 log("\n");
286 log("By default selected output wires and all cell ports of selected cells driven\n");
287 log("by selected wires are rewired.\n");
288 log("\n");
289 }
290 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
291 {
292 bool sel_by_cell = false;
293 bool sel_by_wire = false;
294 bool sel_any_bit = false;
295 bool no_outputs = false;
296 bool do_wires = false;
297 std::set<RTLIL::IdString> ports, no_ports;
298
299 size_t argidx;
300 for (argidx = 1; argidx < args.size(); argidx++) {
301 if (args[argidx] == "-sel_by_cell") {
302 sel_by_cell = true;
303 continue;
304 }
305 if (args[argidx] == "-sel_by_wire") {
306 sel_by_wire = true;
307 continue;
308 }
309 if (args[argidx] == "-sel_any_bit") {
310 sel_any_bit = true;
311 continue;
312 }
313 if (args[argidx] == "-wires") {
314 do_wires = true;
315 continue;
316 }
317 if (args[argidx] == "-no_outputs") {
318 no_outputs = true;
319 continue;
320 }
321 if (args[argidx] == "-port" && argidx+1 < args.size()) {
322 ports.insert(RTLIL::escape_id(args[++argidx]));
323 no_outputs = true;
324 continue;
325 }
326 if (args[argidx] == "-no_port" && argidx+1 < args.size()) {
327 no_ports.insert(RTLIL::escape_id(args[++argidx]));
328 continue;
329 }
330 break;
331 }
332 extra_args(args, argidx, design);
333
334 if (sel_by_cell && sel_by_wire)
335 log_cmd_error("The options -sel_by_cell and -sel_by_wire are exclusive!\n");
336
337 if (sel_by_cell && sel_any_bit)
338 log_cmd_error("The options -sel_by_cell and -sel_any_bit are exclusive!\n");
339
340 if (!ports.empty() && !no_ports.empty())
341 log_cmd_error("The options -port and -no_port are exclusive!\n");
342
343 log_header(design, "Executing SPLICE pass (creating cells for signal splicing).\n");
344
345 for (auto module : design->selected_modules())
346 {
347 if (module->processes.size()) {
348 log("Skipping module %s as it contains processes.\n", module->name.c_str());
349 continue;
350 }
351
352 SpliceWorker worker(design, module);
353 worker.sel_by_cell = sel_by_cell;
354 worker.sel_by_wire = sel_by_wire;
355 worker.sel_any_bit = sel_any_bit;
356 worker.no_outputs = no_outputs;
357 worker.do_wires = do_wires;
358 worker.ports = ports;
359 worker.no_ports = no_ports;
360 worker.run();
361 }
362 }
363 } SplicePass;
364
365 PRIVATE_NAMESPACE_END