Merge branch 'yosys-0.5-vtr' of https://github.com/eddiehung/yosys into eddiehung-vtr
[yosys.git] / kernel / modtools.h
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 #ifndef MODTOOLS_H
21 #define MODTOOLS_H
22
23 #include "kernel/yosys.h"
24 #include "kernel/sigtools.h"
25 #include "kernel/celltypes.h"
26
27 YOSYS_NAMESPACE_BEGIN
28
29 struct ModIndex : public RTLIL::Monitor
30 {
31 struct PortInfo {
32 RTLIL::Cell* cell;
33 RTLIL::IdString port;
34 int offset;
35
36 PortInfo() : cell(), port(), offset() { }
37 PortInfo(RTLIL::Cell* _c, RTLIL::IdString _p, int _o) : cell(_c), port(_p), offset(_o) { }
38
39 bool operator<(const PortInfo &other) const {
40 if (cell != other.cell)
41 return cell < other.cell;
42 if (offset != other.offset)
43 return offset < other.offset;
44 return port < other.port;
45 }
46
47 bool operator==(const PortInfo &other) const {
48 return cell == other.cell && port == other.port && offset == other.offset;
49 }
50
51 unsigned int hash() const {
52 return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
53 }
54 };
55
56 struct SigBitInfo
57 {
58 bool is_input, is_output;
59 pool<PortInfo> ports;
60
61 SigBitInfo() : is_input(false), is_output(false) { }
62
63 bool operator==(const SigBitInfo &other) const {
64 return is_input == other.is_input && is_output == other.is_output && ports == other.ports;
65 }
66
67 void merge(const SigBitInfo &other)
68 {
69 is_input = is_input || other.is_input;
70 is_output = is_output || other.is_output;
71 ports.insert(other.ports.begin(), other.ports.end());
72 }
73 };
74
75 SigMap sigmap;
76 RTLIL::Module *module;
77 std::map<RTLIL::SigBit, SigBitInfo> database;
78 int auto_reload_counter;
79 bool auto_reload_module;
80
81 void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig)
82 {
83 for (int i = 0; i < GetSize(sig); i++) {
84 RTLIL::SigBit bit = sigmap(sig[i]);
85 if (bit.wire)
86 database[bit].ports.insert(PortInfo(cell, port, i));
87 }
88 }
89
90 void port_del(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig)
91 {
92 for (int i = 0; i < GetSize(sig); i++) {
93 RTLIL::SigBit bit = sigmap(sig[i]);
94 if (bit.wire)
95 database[bit].ports.erase(PortInfo(cell, port, i));
96 }
97 }
98
99 const SigBitInfo &info(RTLIL::SigBit bit)
100 {
101 return database[sigmap(bit)];
102 }
103
104 void reload_module(bool reset_sigmap = true)
105 {
106 if (reset_sigmap) {
107 sigmap.clear();
108 sigmap.set(module);
109 }
110
111 database.clear();
112 for (auto wire : module->wires())
113 if (wire->port_input || wire->port_output)
114 for (int i = 0; i < GetSize(wire); i++) {
115 RTLIL::SigBit bit = sigmap(RTLIL::SigBit(wire, i));
116 if (bit.wire && wire->port_input)
117 database[bit].is_input = true;
118 if (bit.wire && wire->port_output)
119 database[bit].is_output = true;
120 }
121 for (auto cell : module->cells())
122 for (auto &conn : cell->connections())
123 port_add(cell, conn.first, conn.second);
124
125 if (auto_reload_module) {
126 if (++auto_reload_counter > 2)
127 log_warning("Auto-reload in ModIndex -- possible performance bug!\n");
128 auto_reload_module = false;
129 }
130 }
131
132 void check()
133 {
134 #ifndef NDEBUG
135 if (auto_reload_module)
136 return;
137
138 for (auto it : database)
139 log_assert(it.first == sigmap(it.first));
140
141 auto database_bak = std::move(database);
142 reload_module(false);
143
144 if (!(database == database_bak))
145 {
146 for (auto &it : database_bak)
147 if (!database.count(it.first))
148 log("ModuleIndex::check(): Only in database_bak, not database: %s\n", log_signal(it.first));
149
150 for (auto &it : database)
151 if (!database_bak.count(it.first))
152 log("ModuleIndex::check(): Only in database, not database_bak: %s\n", log_signal(it.first));
153 else if (!(it.second == database_bak.at(it.first)))
154 log("ModuleIndex::check(): Different content for database[%s].\n", log_signal(it.first));
155
156 log_assert(database == database_bak);
157 }
158 #endif
159 }
160
161 virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE
162 {
163 log_assert(module == cell->module);
164
165 if (auto_reload_module)
166 return;
167
168 port_del(cell, port, old_sig);
169 port_add(cell, port, sig);
170 }
171
172 virtual void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const RTLIL::SigSig &sigsig) YS_OVERRIDE
173 {
174 log_assert(module == mod);
175
176 if (auto_reload_module)
177 return;
178
179 for (int i = 0; i < GetSize(sigsig.first); i++)
180 {
181 RTLIL::SigBit lhs = sigmap(sigsig.first[i]);
182 RTLIL::SigBit rhs = sigmap(sigsig.second[i]);
183 bool has_lhs = database.count(lhs) != 0;
184 bool has_rhs = database.count(rhs) != 0;
185
186 if (!has_lhs && !has_rhs) {
187 sigmap.add(lhs, rhs);
188 } else
189 if (!has_rhs) {
190 SigBitInfo new_info = database.at(lhs);
191 database.erase(lhs);
192 sigmap.add(lhs, rhs);
193 lhs = sigmap(lhs);
194 if (lhs.wire)
195 database[lhs] = new_info;
196 } else
197 if (!has_lhs) {
198 SigBitInfo new_info = database.at(rhs);
199 database.erase(rhs);
200 sigmap.add(lhs, rhs);
201 rhs = sigmap(rhs);
202 if (rhs.wire)
203 database[rhs] = new_info;
204 } else {
205 SigBitInfo new_info = database.at(lhs);
206 new_info.merge(database.at(rhs));
207 database.erase(lhs);
208 database.erase(rhs);
209 sigmap.add(lhs, rhs);
210 rhs = sigmap(rhs);
211 if (rhs.wire)
212 database[rhs] = new_info;
213 }
214 }
215 }
216
217 virtual void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const std::vector<RTLIL::SigSig>&) YS_OVERRIDE
218 {
219 log_assert(module == mod);
220 auto_reload_module = true;
221 }
222
223 virtual void notify_blackout(RTLIL::Module *mod YS_ATTRIBUTE(unused)) YS_OVERRIDE
224 {
225 log_assert(module == mod);
226 auto_reload_module = true;
227 }
228
229 ModIndex(RTLIL::Module *_m) : sigmap(_m), module(_m)
230 {
231 auto_reload_counter = 0;
232 auto_reload_module = true;
233 module->monitors.insert(this);
234 }
235
236 ~ModIndex()
237 {
238 module->monitors.erase(this);
239 }
240
241 SigBitInfo *query(RTLIL::SigBit bit)
242 {
243 if (auto_reload_module)
244 reload_module();
245
246 auto it = database.find(sigmap(bit));
247 if (it == database.end())
248 return nullptr;
249 else
250 return &it->second;
251 }
252
253 bool query_is_input(RTLIL::SigBit bit)
254 {
255 const SigBitInfo *info = query(bit);
256 if (info == nullptr)
257 return false;
258 return info->is_input;
259 }
260
261 bool query_is_output(RTLIL::SigBit bit)
262 {
263 const SigBitInfo *info = query(bit);
264 if (info == nullptr)
265 return false;
266 return info->is_output;
267 }
268
269 pool<PortInfo> &query_ports(RTLIL::SigBit bit)
270 {
271 static pool<PortInfo> empty_result_set;
272 SigBitInfo *info = query(bit);
273 if (info == nullptr)
274 return empty_result_set;
275 return info->ports;
276 }
277
278 void dump_db()
279 {
280 log("--- ModIndex Dump ---\n");
281
282 if (auto_reload_module) {
283 log("AUTO-RELOAD\n");
284 reload_module();
285 }
286
287 for (auto &it : database) {
288 log("BIT %s:\n", log_signal(it.first));
289 if (it.second.is_input)
290 log(" PRIMARY INPUT\n");
291 if (it.second.is_output)
292 log(" PRIMARY OUTPUT\n");
293 for (auto &port : it.second.ports)
294 log(" PORT: %s.%s[%d] (%s)\n", log_id(port.cell),
295 log_id(port.port), port.offset, log_id(port.cell->type));
296 }
297 }
298 };
299
300 struct ModWalker
301 {
302 struct PortBit
303 {
304 RTLIL::Cell *cell;
305 RTLIL::IdString port;
306 int offset;
307
308 bool operator<(const PortBit &other) const {
309 if (cell != other.cell)
310 return cell < other.cell;
311 if (port != other.port)
312 return port < other.port;
313 return offset < other.offset;
314 }
315
316 bool operator==(const PortBit &other) const {
317 return cell == other.cell && port == other.port && offset == other.offset;
318 }
319
320 unsigned int hash() const {
321 return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
322 }
323 };
324
325 RTLIL::Design *design;
326 RTLIL::Module *module;
327
328 CellTypes ct;
329 SigMap sigmap;
330
331 dict<RTLIL::SigBit, pool<PortBit>> signal_drivers;
332 dict<RTLIL::SigBit, pool<PortBit>> signal_consumers;
333 pool<RTLIL::SigBit> signal_inputs, signal_outputs;
334
335 dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_outputs, cell_inputs;
336
337 void add_wire(RTLIL::Wire *wire)
338 {
339 if (wire->port_input) {
340 std::vector<RTLIL::SigBit> bits = sigmap(wire);
341 for (auto bit : bits)
342 if (bit.wire != NULL)
343 signal_inputs.insert(bit);
344 }
345
346 if (wire->port_output) {
347 std::vector<RTLIL::SigBit> bits = sigmap(wire);
348 for (auto bit : bits)
349 if (bit.wire != NULL)
350 signal_outputs.insert(bit);
351 }
352 }
353
354 void add_cell_port(RTLIL::Cell *cell, RTLIL::IdString port, std::vector<RTLIL::SigBit> bits, bool is_output, bool is_input)
355 {
356 for (int i = 0; i < int(bits.size()); i++)
357 if (bits[i].wire != NULL) {
358 PortBit pbit = { cell, port, i };
359 if (is_output) {
360 signal_drivers[bits[i]].insert(pbit);
361 cell_outputs[cell].insert(bits[i]);
362 }
363 if (is_input) {
364 signal_consumers[bits[i]].insert(pbit);
365 cell_inputs[cell].insert(bits[i]);
366 }
367 }
368 }
369
370 void add_cell(RTLIL::Cell *cell)
371 {
372 if (ct.cell_known(cell->type)) {
373 for (auto &conn : cell->connections())
374 add_cell_port(cell, conn.first, sigmap(conn.second),
375 ct.cell_output(cell->type, conn.first),
376 ct.cell_input(cell->type, conn.first));
377 } else {
378 for (auto &conn : cell->connections())
379 add_cell_port(cell, conn.first, sigmap(conn.second), true, true);
380 }
381 }
382
383 ModWalker() : design(NULL), module(NULL)
384 {
385 }
386
387 ModWalker(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL)
388 {
389 setup(design, module, filter_ct);
390 }
391
392 void setup(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL)
393 {
394 this->design = design;
395 this->module = module;
396
397 ct.clear();
398 ct.setup(design);
399 sigmap.set(module);
400
401 signal_drivers.clear();
402 signal_consumers.clear();
403 signal_inputs.clear();
404 signal_outputs.clear();
405
406 for (auto &it : module->wires_)
407 add_wire(it.second);
408 for (auto &it : module->cells_)
409 if (filter_ct == NULL || filter_ct->cell_known(it.second->type))
410 add_cell(it.second);
411 }
412
413 // get_* methods -- single RTLIL::SigBit
414
415 template<typename T>
416 inline bool get_drivers(pool<PortBit> &result, RTLIL::SigBit bit) const
417 {
418 bool found = false;
419 if (signal_drivers.count(bit)) {
420 const pool<PortBit> &r = signal_drivers.at(bit);
421 result.insert(r.begin(), r.end());
422 found = true;
423 }
424 return found;
425 }
426
427 template<typename T>
428 inline bool get_consumers(pool<PortBit> &result, RTLIL::SigBit bit) const
429 {
430 bool found = false;
431 if (signal_consumers.count(bit)) {
432 const pool<PortBit> &r = signal_consumers.at(bit);
433 result.insert(r.begin(), r.end());
434 found = true;
435 }
436 return found;
437 }
438
439 template<typename T>
440 inline bool get_inputs(pool<RTLIL::SigBit> &result, RTLIL::SigBit bit) const
441 {
442 bool found = false;
443 if (signal_inputs.count(bit))
444 result.insert(bit), found = true;
445 return found;
446 }
447
448 template<typename T>
449 inline bool get_outputs(pool<RTLIL::SigBit> &result, RTLIL::SigBit bit) const
450 {
451 bool found = false;
452 if (signal_outputs.count(bit))
453 result.insert(bit), found = true;
454 return found;
455 }
456
457 // get_* methods -- container of RTLIL::SigBit's (always by reference)
458
459 template<typename T>
460 inline bool get_drivers(pool<PortBit> &result, const T &bits) const
461 {
462 bool found = false;
463 for (RTLIL::SigBit bit : bits)
464 if (signal_drivers.count(bit)) {
465 const pool<PortBit> &r = signal_drivers.at(bit);
466 result.insert(r.begin(), r.end());
467 found = true;
468 }
469 return found;
470 }
471
472 template<typename T>
473 inline bool get_consumers(pool<PortBit> &result, const T &bits) const
474 {
475 bool found = false;
476 for (RTLIL::SigBit bit : bits)
477 if (signal_consumers.count(bit)) {
478 const pool<PortBit> &r = signal_consumers.at(bit);
479 result.insert(r.begin(), r.end());
480 found = true;
481 }
482 return found;
483 }
484
485 template<typename T>
486 inline bool get_inputs(pool<RTLIL::SigBit> &result, const T &bits) const
487 {
488 bool found = false;
489 for (RTLIL::SigBit bit : bits)
490 if (signal_inputs.count(bit))
491 result.insert(bit), found = true;
492 return found;
493 }
494
495 template<typename T>
496 inline bool get_outputs(pool<RTLIL::SigBit> &result, const T &bits) const
497 {
498 bool found = false;
499 for (RTLIL::SigBit bit : bits)
500 if (signal_outputs.count(bit))
501 result.insert(bit), found = true;
502 return found;
503 }
504
505 // get_* methods -- call by RTLIL::SigSpec (always by value)
506
507 bool get_drivers(pool<PortBit> &result, RTLIL::SigSpec signal) const
508 {
509 std::vector<RTLIL::SigBit> bits = sigmap(signal);
510 return get_drivers(result, bits);
511 }
512
513 bool get_consumers(pool<PortBit> &result, RTLIL::SigSpec signal) const
514 {
515 std::vector<RTLIL::SigBit> bits = sigmap(signal);
516 return get_consumers(result, bits);
517 }
518
519 bool get_inputs(pool<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const
520 {
521 std::vector<RTLIL::SigBit> bits = sigmap(signal);
522 return get_inputs(result, bits);
523 }
524
525 bool get_outputs(pool<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const
526 {
527 std::vector<RTLIL::SigBit> bits = sigmap(signal);
528 return get_outputs(result, bits);
529 }
530
531 // has_* methods -- call by reference
532
533 template<typename T>
534 inline bool has_drivers(const T &sig) const {
535 pool<PortBit> result;
536 return get_drivers(result, sig);
537 }
538
539 template<typename T>
540 inline bool has_consumers(const T &sig) const {
541 pool<PortBit> result;
542 return get_consumers(result, sig);
543 }
544
545 template<typename T>
546 inline bool has_inputs(const T &sig) const {
547 pool<RTLIL::SigBit> result;
548 return get_inputs(result, sig);
549 }
550
551 template<typename T>
552 inline bool has_outputs(const T &sig) const {
553 pool<RTLIL::SigBit> result;
554 return get_outputs(result, sig);
555 }
556
557 // has_* methods -- call by value
558
559 inline bool has_drivers(RTLIL::SigSpec sig) const {
560 pool<PortBit> result;
561 return get_drivers(result, sig);
562 }
563
564 inline bool has_consumers(RTLIL::SigSpec sig) const {
565 pool<PortBit> result;
566 return get_consumers(result, sig);
567 }
568
569 inline bool has_inputs(RTLIL::SigSpec sig) const {
570 pool<RTLIL::SigBit> result;
571 return get_inputs(result, sig);
572 }
573
574 inline bool has_outputs(RTLIL::SigSpec sig) const {
575 pool<RTLIL::SigBit> result;
576 return get_outputs(result, sig);
577 }
578 };
579
580 YOSYS_NAMESPACE_END
581
582 #endif