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.
23 #include "kernel/yosys.h"
24 #include "kernel/sigtools.h"
25 #include "kernel/celltypes.h"
29 struct ModIndex
: public RTLIL::Monitor
36 PortInfo() : cell(), port(), offset() { }
37 PortInfo(RTLIL::Cell
* _c
, RTLIL::IdString _p
, int _o
) : cell(_c
), port(_p
), offset(_o
) { }
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
;
47 bool operator==(const PortInfo
&other
) const {
48 return cell
== other
.cell
&& port
== other
.port
&& offset
== other
.offset
;
51 unsigned int hash() const {
52 return mkhash_add(mkhash(cell
->name
.hash(), port
.hash()), offset
);
58 bool is_input
, is_output
;
61 SigBitInfo() : is_input(false), is_output(false) { }
63 bool operator==(const SigBitInfo
&other
) const {
64 return is_input
== other
.is_input
&& is_output
== other
.is_output
&& ports
== other
.ports
;
67 void merge(const SigBitInfo
&other
)
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());
76 RTLIL::Module
*module
;
77 std::map
<RTLIL::SigBit
, SigBitInfo
> database
;
78 int auto_reload_counter
;
79 bool auto_reload_module
;
81 void port_add(RTLIL::Cell
*cell
, RTLIL::IdString port
, const RTLIL::SigSpec
&sig
)
83 for (int i
= 0; i
< GetSize(sig
); i
++) {
84 RTLIL::SigBit bit
= sigmap(sig
[i
]);
86 database
[bit
].ports
.insert(PortInfo(cell
, port
, i
));
90 void port_del(RTLIL::Cell
*cell
, RTLIL::IdString port
, const RTLIL::SigSpec
&sig
)
92 for (int i
= 0; i
< GetSize(sig
); i
++) {
93 RTLIL::SigBit bit
= sigmap(sig
[i
]);
95 database
[bit
].ports
.erase(PortInfo(cell
, port
, i
));
99 const SigBitInfo
&info(RTLIL::SigBit bit
)
101 return database
[sigmap(bit
)];
104 void reload_module(bool reset_sigmap
= true)
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;
121 for (auto cell
: module
->cells())
122 for (auto &conn
: cell
->connections())
123 port_add(cell
, conn
.first
, conn
.second
);
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;
135 if (auto_reload_module
)
138 for (auto it
: database
)
139 log_assert(it
.first
== sigmap(it
.first
));
141 auto database_bak
= std::move(database
);
142 reload_module(false);
144 if (!(database
== database_bak
))
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
));
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
));
156 log_assert(database
== database_bak
);
161 void notify_connect(RTLIL::Cell
*cell
, const RTLIL::IdString
&port
, const RTLIL::SigSpec
&old_sig
, RTLIL::SigSpec
&sig
) YS_OVERRIDE
163 log_assert(module
== cell
->module
);
165 if (auto_reload_module
)
168 port_del(cell
, port
, old_sig
);
169 port_add(cell
, port
, sig
);
172 void notify_connect(RTLIL::Module
*mod
YS_ATTRIBUTE(unused
), const RTLIL::SigSig
&sigsig
) YS_OVERRIDE
174 log_assert(module
== mod
);
176 if (auto_reload_module
)
179 for (int i
= 0; i
< GetSize(sigsig
.first
); i
++)
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;
186 if (!has_lhs
&& !has_rhs
) {
187 sigmap
.add(lhs
, rhs
);
190 SigBitInfo new_info
= database
.at(lhs
);
192 sigmap
.add(lhs
, rhs
);
195 database
[lhs
] = new_info
;
198 SigBitInfo new_info
= database
.at(rhs
);
200 sigmap
.add(lhs
, rhs
);
203 database
[rhs
] = new_info
;
205 SigBitInfo new_info
= database
.at(lhs
);
206 new_info
.merge(database
.at(rhs
));
209 sigmap
.add(lhs
, rhs
);
212 database
[rhs
] = new_info
;
217 void notify_connect(RTLIL::Module
*mod
YS_ATTRIBUTE(unused
), const std::vector
<RTLIL::SigSig
>&) YS_OVERRIDE
219 log_assert(module
== mod
);
220 auto_reload_module
= true;
223 void notify_blackout(RTLIL::Module
*mod
YS_ATTRIBUTE(unused
)) YS_OVERRIDE
225 log_assert(module
== mod
);
226 auto_reload_module
= true;
229 ModIndex(RTLIL::Module
*_m
) : sigmap(_m
), module(_m
)
231 auto_reload_counter
= 0;
232 auto_reload_module
= true;
233 module
->monitors
.insert(this);
238 module
->monitors
.erase(this);
241 SigBitInfo
*query(RTLIL::SigBit bit
)
243 if (auto_reload_module
)
246 auto it
= database
.find(sigmap(bit
));
247 if (it
== database
.end())
253 bool query_is_input(RTLIL::SigBit bit
)
255 const SigBitInfo
*info
= query(bit
);
258 return info
->is_input
;
261 bool query_is_output(RTLIL::SigBit bit
)
263 const SigBitInfo
*info
= query(bit
);
266 return info
->is_output
;
269 pool
<PortInfo
> &query_ports(RTLIL::SigBit bit
)
271 static pool
<PortInfo
> empty_result_set
;
272 SigBitInfo
*info
= query(bit
);
274 return empty_result_set
;
280 log("--- ModIndex Dump ---\n");
282 if (auto_reload_module
) {
283 log("AUTO-RELOAD\n");
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
));
305 RTLIL::IdString port
;
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
;
316 bool operator==(const PortBit
&other
) const {
317 return cell
== other
.cell
&& port
== other
.port
&& offset
== other
.offset
;
320 unsigned int hash() const {
321 return mkhash_add(mkhash(cell
->name
.hash(), port
.hash()), offset
);
325 RTLIL::Design
*design
;
326 RTLIL::Module
*module
;
331 dict
<RTLIL::SigBit
, pool
<PortBit
>> signal_drivers
;
332 dict
<RTLIL::SigBit
, pool
<PortBit
>> signal_consumers
;
333 pool
<RTLIL::SigBit
> signal_inputs
, signal_outputs
;
335 dict
<RTLIL::Cell
*, pool
<RTLIL::SigBit
>> cell_outputs
, cell_inputs
;
337 void add_wire(RTLIL::Wire
*wire
)
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
);
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
);
354 void add_cell_port(RTLIL::Cell
*cell
, RTLIL::IdString port
, std::vector
<RTLIL::SigBit
> bits
, bool is_output
, bool is_input
)
356 for (int i
= 0; i
< int(bits
.size()); i
++)
357 if (bits
[i
].wire
!= NULL
) {
358 PortBit pbit
= { cell
, port
, i
};
360 signal_drivers
[bits
[i
]].insert(pbit
);
361 cell_outputs
[cell
].insert(bits
[i
]);
364 signal_consumers
[bits
[i
]].insert(pbit
);
365 cell_inputs
[cell
].insert(bits
[i
]);
370 void add_cell(RTLIL::Cell
*cell
)
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
));
378 for (auto &conn
: cell
->connections())
379 add_cell_port(cell
, conn
.first
, sigmap(conn
.second
), true, true);
383 ModWalker() : design(NULL
), module(NULL
)
387 ModWalker(RTLIL::Design
*design
, RTLIL::Module
*module
, CellTypes
*filter_ct
= NULL
)
389 setup(design
, module
, filter_ct
);
392 void setup(RTLIL::Design
*design
, RTLIL::Module
*module
, CellTypes
*filter_ct
= NULL
)
394 this->design
= design
;
395 this->module
= module
;
401 signal_drivers
.clear();
402 signal_consumers
.clear();
403 signal_inputs
.clear();
404 signal_outputs
.clear();
406 for (auto &it
: module
->wires_
)
408 for (auto &it
: module
->cells_
)
409 if (filter_ct
== NULL
|| filter_ct
->cell_known(it
.second
->type
))
413 // get_* methods -- single RTLIL::SigBit
416 inline bool get_drivers(pool
<PortBit
> &result
, RTLIL::SigBit bit
) const
419 if (signal_drivers
.count(bit
)) {
420 const pool
<PortBit
> &r
= signal_drivers
.at(bit
);
421 result
.insert(r
.begin(), r
.end());
428 inline bool get_consumers(pool
<PortBit
> &result
, RTLIL::SigBit bit
) const
431 if (signal_consumers
.count(bit
)) {
432 const pool
<PortBit
> &r
= signal_consumers
.at(bit
);
433 result
.insert(r
.begin(), r
.end());
440 inline bool get_inputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigBit bit
) const
443 if (signal_inputs
.count(bit
))
444 result
.insert(bit
), found
= true;
449 inline bool get_outputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigBit bit
) const
452 if (signal_outputs
.count(bit
))
453 result
.insert(bit
), found
= true;
457 // get_* methods -- container of RTLIL::SigBit's (always by reference)
460 inline bool get_drivers(pool
<PortBit
> &result
, const T
&bits
) const
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());
473 inline bool get_consumers(pool
<PortBit
> &result
, const T
&bits
) const
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());
486 inline bool get_inputs(pool
<RTLIL::SigBit
> &result
, const T
&bits
) const
489 for (RTLIL::SigBit bit
: bits
)
490 if (signal_inputs
.count(bit
))
491 result
.insert(bit
), found
= true;
496 inline bool get_outputs(pool
<RTLIL::SigBit
> &result
, const T
&bits
) const
499 for (RTLIL::SigBit bit
: bits
)
500 if (signal_outputs
.count(bit
))
501 result
.insert(bit
), found
= true;
505 // get_* methods -- call by RTLIL::SigSpec (always by value)
507 bool get_drivers(pool
<PortBit
> &result
, RTLIL::SigSpec signal
) const
509 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
510 return get_drivers(result
, bits
);
513 bool get_consumers(pool
<PortBit
> &result
, RTLIL::SigSpec signal
) const
515 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
516 return get_consumers(result
, bits
);
519 bool get_inputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigSpec signal
) const
521 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
522 return get_inputs(result
, bits
);
525 bool get_outputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigSpec signal
) const
527 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
528 return get_outputs(result
, bits
);
531 // has_* methods -- call by reference
534 inline bool has_drivers(const T
&sig
) const {
535 pool
<PortBit
> result
;
536 return get_drivers(result
, sig
);
540 inline bool has_consumers(const T
&sig
) const {
541 pool
<PortBit
> result
;
542 return get_consumers(result
, sig
);
546 inline bool has_inputs(const T
&sig
) const {
547 pool
<RTLIL::SigBit
> result
;
548 return get_inputs(result
, sig
);
552 inline bool has_outputs(const T
&sig
) const {
553 pool
<RTLIL::SigBit
> result
;
554 return get_outputs(result
, sig
);
557 // has_* methods -- call by value
559 inline bool has_drivers(RTLIL::SigSpec sig
) const {
560 pool
<PortBit
> result
;
561 return get_drivers(result
, sig
);
564 inline bool has_consumers(RTLIL::SigSpec sig
) const {
565 pool
<PortBit
> result
;
566 return get_consumers(result
, sig
);
569 inline bool has_inputs(RTLIL::SigSpec sig
) const {
570 pool
<RTLIL::SigBit
> result
;
571 return get_inputs(result
, sig
);
574 inline bool has_outputs(RTLIL::SigSpec sig
) const {
575 pool
<RTLIL::SigBit
> result
;
576 return get_outputs(result
, sig
);