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 virtual 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 virtual 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
);
184 bool has_rhs
= database
.count(rhs
);
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 virtual 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 virtual 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
) : 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
;
284 RTLIL::IdString port
;
287 bool operator<(const PortBit
&other
) const {
288 if (cell
!= other
.cell
)
289 return cell
< other
.cell
;
290 if (port
!= other
.port
)
291 return port
< other
.port
;
292 return offset
< other
.offset
;
295 bool operator==(const PortBit
&other
) const {
296 return cell
== other
.cell
&& port
== other
.port
&& offset
== other
.offset
;
299 unsigned int hash() const {
300 return mkhash_add(mkhash(cell
->name
.hash(), port
.hash()), offset
);
304 RTLIL::Design
*design
;
305 RTLIL::Module
*module
;
310 dict
<RTLIL::SigBit
, pool
<PortBit
>> signal_drivers
;
311 dict
<RTLIL::SigBit
, pool
<PortBit
>> signal_consumers
;
312 pool
<RTLIL::SigBit
> signal_inputs
, signal_outputs
;
314 dict
<RTLIL::Cell
*, pool
<RTLIL::SigBit
>> cell_outputs
, cell_inputs
;
316 void add_wire(RTLIL::Wire
*wire
)
318 if (wire
->port_input
) {
319 std::vector
<RTLIL::SigBit
> bits
= sigmap(wire
);
320 for (auto bit
: bits
)
321 if (bit
.wire
!= NULL
)
322 signal_inputs
.insert(bit
);
325 if (wire
->port_output
) {
326 std::vector
<RTLIL::SigBit
> bits
= sigmap(wire
);
327 for (auto bit
: bits
)
328 if (bit
.wire
!= NULL
)
329 signal_outputs
.insert(bit
);
333 void add_cell_port(RTLIL::Cell
*cell
, RTLIL::IdString port
, std::vector
<RTLIL::SigBit
> bits
, bool is_output
, bool is_input
)
335 for (int i
= 0; i
< int(bits
.size()); i
++)
336 if (bits
[i
].wire
!= NULL
) {
337 PortBit pbit
= { cell
, port
, i
};
339 signal_drivers
[bits
[i
]].insert(pbit
);
340 cell_outputs
[cell
].insert(bits
[i
]);
343 signal_consumers
[bits
[i
]].insert(pbit
);
344 cell_inputs
[cell
].insert(bits
[i
]);
349 void add_cell(RTLIL::Cell
*cell
)
351 if (ct
.cell_known(cell
->type
)) {
352 for (auto &conn
: cell
->connections())
353 add_cell_port(cell
, conn
.first
, sigmap(conn
.second
),
354 ct
.cell_output(cell
->type
, conn
.first
),
355 ct
.cell_input(cell
->type
, conn
.first
));
357 for (auto &conn
: cell
->connections())
358 add_cell_port(cell
, conn
.first
, sigmap(conn
.second
), true, true);
362 ModWalker() : design(NULL
), module(NULL
)
366 ModWalker(RTLIL::Design
*design
, RTLIL::Module
*module
, CellTypes
*filter_ct
= NULL
)
368 setup(design
, module
, filter_ct
);
371 void setup(RTLIL::Design
*design
, RTLIL::Module
*module
, CellTypes
*filter_ct
= NULL
)
373 this->design
= design
;
374 this->module
= module
;
380 signal_drivers
.clear();
381 signal_consumers
.clear();
382 signal_inputs
.clear();
383 signal_outputs
.clear();
385 for (auto &it
: module
->wires_
)
387 for (auto &it
: module
->cells_
)
388 if (filter_ct
== NULL
|| filter_ct
->cell_known(it
.second
->type
))
392 // get_* methods -- single RTLIL::SigBit
395 inline bool get_drivers(pool
<PortBit
> &result
, RTLIL::SigBit bit
) const
398 if (signal_drivers
.count(bit
)) {
399 const pool
<PortBit
> &r
= signal_drivers
.at(bit
);
400 result
.insert(r
.begin(), r
.end());
407 inline bool get_consumers(pool
<PortBit
> &result
, RTLIL::SigBit bit
) const
410 if (signal_consumers
.count(bit
)) {
411 const pool
<PortBit
> &r
= signal_consumers
.at(bit
);
412 result
.insert(r
.begin(), r
.end());
419 inline bool get_inputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigBit bit
) const
422 if (signal_inputs
.count(bit
))
423 result
.insert(bit
), found
= true;
428 inline bool get_outputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigBit bit
) const
431 if (signal_outputs
.count(bit
))
432 result
.insert(bit
), found
= true;
436 // get_* methods -- container of RTLIL::SigBit's (always by reference)
439 inline bool get_drivers(pool
<PortBit
> &result
, const T
&bits
) const
442 for (RTLIL::SigBit bit
: bits
)
443 if (signal_drivers
.count(bit
)) {
444 const pool
<PortBit
> &r
= signal_drivers
.at(bit
);
445 result
.insert(r
.begin(), r
.end());
452 inline bool get_consumers(pool
<PortBit
> &result
, const T
&bits
) const
455 for (RTLIL::SigBit bit
: bits
)
456 if (signal_consumers
.count(bit
)) {
457 const pool
<PortBit
> &r
= signal_consumers
.at(bit
);
458 result
.insert(r
.begin(), r
.end());
465 inline bool get_inputs(pool
<RTLIL::SigBit
> &result
, const T
&bits
) const
468 for (RTLIL::SigBit bit
: bits
)
469 if (signal_inputs
.count(bit
))
470 result
.insert(bit
), found
= true;
475 inline bool get_outputs(pool
<RTLIL::SigBit
> &result
, const T
&bits
) const
478 for (RTLIL::SigBit bit
: bits
)
479 if (signal_outputs
.count(bit
))
480 result
.insert(bit
), found
= true;
484 // get_* methods -- call by RTLIL::SigSpec (always by value)
486 bool get_drivers(pool
<PortBit
> &result
, RTLIL::SigSpec signal
) const
488 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
489 return get_drivers(result
, bits
);
492 bool get_consumers(pool
<PortBit
> &result
, RTLIL::SigSpec signal
) const
494 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
495 return get_consumers(result
, bits
);
498 bool get_inputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigSpec signal
) const
500 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
501 return get_inputs(result
, bits
);
504 bool get_outputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigSpec signal
) const
506 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
507 return get_outputs(result
, bits
);
510 // has_* methods -- call by reference
513 inline bool has_drivers(const T
&sig
) const {
514 pool
<PortBit
> result
;
515 return get_drivers(result
, sig
);
519 inline bool has_consumers(const T
&sig
) const {
520 pool
<PortBit
> result
;
521 return get_consumers(result
, sig
);
525 inline bool has_inputs(const T
&sig
) const {
526 pool
<RTLIL::SigBit
> result
;
527 return get_inputs(result
, sig
);
531 inline bool has_outputs(const T
&sig
) const {
532 pool
<RTLIL::SigBit
> result
;
533 return get_outputs(result
, sig
);
536 // has_* methods -- call by value
538 inline bool has_drivers(RTLIL::SigSpec sig
) const {
539 pool
<PortBit
> result
;
540 return get_drivers(result
, sig
);
543 inline bool has_consumers(RTLIL::SigSpec sig
) const {
544 pool
<PortBit
> result
;
545 return get_consumers(result
, sig
);
548 inline bool has_inputs(RTLIL::SigSpec sig
) const {
549 pool
<RTLIL::SigBit
> result
;
550 return get_inputs(result
, sig
);
553 inline bool has_outputs(RTLIL::SigSpec sig
) const {
554 pool
<RTLIL::SigBit
> result
;
555 return get_outputs(result
, sig
);