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 void merge(const SigBitInfo
&other
)
65 is_input
= is_input
|| other
.is_input
;
66 is_output
= is_output
|| other
.is_output
;
67 ports
.insert(other
.ports
.begin(), other
.ports
.end());
72 RTLIL::Module
*module
;
73 dict
<RTLIL::SigBit
, SigBitInfo
> database
;
74 bool auto_reload_module
;
76 void port_add(RTLIL::Cell
*cell
, RTLIL::IdString port
, const RTLIL::SigSpec
&sig
)
78 for (int i
= 0; i
< GetSize(sig
); i
++) {
79 RTLIL::SigBit bit
= sigmap(sig
[i
]);
81 database
[bit
].ports
.insert(PortInfo(cell
, port
, i
));
85 void port_del(RTLIL::Cell
*cell
, RTLIL::IdString port
, const RTLIL::SigSpec
&sig
)
87 for (int i
= 0; i
< GetSize(sig
); i
++) {
88 RTLIL::SigBit bit
= sigmap(sig
[i
]);
90 database
[bit
].ports
.erase(PortInfo(cell
, port
, i
));
94 const SigBitInfo
&info(RTLIL::SigBit bit
)
96 return database
[sigmap(bit
)];
105 for (auto wire
: module
->wires())
106 if (wire
->port_input
|| wire
->port_output
)
107 for (int i
= 0; i
< GetSize(wire
); i
++) {
108 RTLIL::SigBit bit
= sigmap(RTLIL::SigBit(wire
, i
));
109 if (bit
.wire
&& wire
->port_input
)
110 database
[bit
].is_input
= true;
111 if (bit
.wire
&& wire
->port_output
)
112 database
[bit
].is_output
= true;
114 for (auto cell
: module
->cells())
115 for (auto &conn
: cell
->connections())
116 port_add(cell
, conn
.first
, conn
.second
);
118 auto_reload_module
= false;
119 // log("Auto-reload in ModIndex -- possible performance bug!\n");
122 virtual void notify_connect(RTLIL::Cell
*cell
, const RTLIL::IdString
&port
, const RTLIL::SigSpec
&old_sig
, RTLIL::SigSpec
&sig
) YS_OVERRIDE
124 log_assert(module
== cell
->module
);
126 if (auto_reload_module
)
129 port_del(cell
, port
, old_sig
);
130 port_add(cell
, port
, sig
);
133 virtual void notify_connect(RTLIL::Module
*mod
, const RTLIL::SigSig
&sigsig
) YS_OVERRIDE
135 log_assert(module
== mod
);
137 if (auto_reload_module
)
140 for (int i
= 0; i
< GetSize(sigsig
.first
); i
++)
142 RTLIL::SigBit lhs
= sigmap(sigsig
.first
[i
]);
143 RTLIL::SigBit rhs
= sigmap(sigsig
.second
[i
]);
144 bool has_lhs
= database
.count(lhs
);
145 bool has_rhs
= database
.count(rhs
);
147 if (!has_lhs
&& !has_rhs
) {
148 sigmap
.add(lhs
, rhs
);
151 SigBitInfo new_info
= database
.at(lhs
);
153 sigmap
.add(lhs
, rhs
);
154 database
[sigmap(lhs
)] = new_info
;
157 SigBitInfo new_info
= database
.at(rhs
);
159 sigmap
.add(lhs
, rhs
);
160 database
[sigmap(rhs
)] = new_info
;
163 auto_reload_module
= true;
166 SigBitInfo new_info
= database
.at(lhs
);
167 new_info
.merge(database
.at(rhs
));
170 sigmap
.add(lhs
, rhs
);
171 database
[sigmap(rhs
)] = new_info
;
177 virtual void notify_connect(RTLIL::Module
*mod
, const std::vector
<RTLIL::SigSig
>&) YS_OVERRIDE
179 log_assert(module
== mod
);
180 auto_reload_module
= true;
183 virtual void notify_blackout(RTLIL::Module
*mod
) YS_OVERRIDE
185 log_assert(module
== mod
);
186 auto_reload_module
= true;
189 ModIndex(RTLIL::Module
*_m
) : module(_m
)
191 auto_reload_module
= true;
192 module
->monitors
.insert(this);
197 module
->monitors
.erase(this);
200 SigBitInfo
*query(RTLIL::SigBit bit
)
202 if (auto_reload_module
)
205 auto it
= database
.find(sigmap(bit
));
206 if (it
== database
.end())
212 bool query_is_input(RTLIL::SigBit bit
)
214 const SigBitInfo
*info
= query(bit
);
217 return info
->is_input
;
220 bool query_is_output(RTLIL::SigBit bit
)
222 const SigBitInfo
*info
= query(bit
);
225 return info
->is_output
;
228 pool
<PortInfo
> &query_ports(RTLIL::SigBit bit
)
230 static pool
<PortInfo
> empty_result_set
;
231 SigBitInfo
*info
= query(bit
);
233 return empty_result_set
;
243 RTLIL::IdString port
;
246 bool operator<(const PortBit
&other
) const {
247 if (cell
!= other
.cell
)
248 return cell
< other
.cell
;
249 if (port
!= other
.port
)
250 return port
< other
.port
;
251 return offset
< other
.offset
;
254 bool operator==(const PortBit
&other
) const {
255 return cell
== other
.cell
&& port
== other
.port
&& offset
== other
.offset
;
258 unsigned int hash() const {
259 return mkhash_add(mkhash(cell
->name
.hash(), port
.hash()), offset
);
263 RTLIL::Design
*design
;
264 RTLIL::Module
*module
;
269 dict
<RTLIL::SigBit
, pool
<PortBit
>> signal_drivers
;
270 dict
<RTLIL::SigBit
, pool
<PortBit
>> signal_consumers
;
271 pool
<RTLIL::SigBit
> signal_inputs
, signal_outputs
;
273 dict
<RTLIL::Cell
*, pool
<RTLIL::SigBit
>, hash_obj_ops
> cell_outputs
, cell_inputs
;
275 void add_wire(RTLIL::Wire
*wire
)
277 if (wire
->port_input
) {
278 std::vector
<RTLIL::SigBit
> bits
= sigmap(wire
);
279 for (auto bit
: bits
)
280 if (bit
.wire
!= NULL
)
281 signal_inputs
.insert(bit
);
284 if (wire
->port_output
) {
285 std::vector
<RTLIL::SigBit
> bits
= sigmap(wire
);
286 for (auto bit
: bits
)
287 if (bit
.wire
!= NULL
)
288 signal_outputs
.insert(bit
);
292 void add_cell_port(RTLIL::Cell
*cell
, RTLIL::IdString port
, std::vector
<RTLIL::SigBit
> bits
, bool is_output
, bool is_input
)
294 for (int i
= 0; i
< int(bits
.size()); i
++)
295 if (bits
[i
].wire
!= NULL
) {
296 PortBit pbit
= { cell
, port
, i
};
298 signal_drivers
[bits
[i
]].insert(pbit
);
299 cell_outputs
[cell
].insert(bits
[i
]);
302 signal_consumers
[bits
[i
]].insert(pbit
);
303 cell_inputs
[cell
].insert(bits
[i
]);
308 void add_cell(RTLIL::Cell
*cell
)
310 if (ct
.cell_known(cell
->type
)) {
311 for (auto &conn
: cell
->connections())
312 add_cell_port(cell
, conn
.first
, sigmap(conn
.second
),
313 ct
.cell_output(cell
->type
, conn
.first
),
314 ct
.cell_input(cell
->type
, conn
.first
));
316 for (auto &conn
: cell
->connections())
317 add_cell_port(cell
, conn
.first
, sigmap(conn
.second
), true, true);
321 ModWalker() : design(NULL
), module(NULL
)
325 ModWalker(RTLIL::Design
*design
, RTLIL::Module
*module
, CellTypes
*filter_ct
= NULL
)
327 setup(design
, module
, filter_ct
);
330 void setup(RTLIL::Design
*design
, RTLIL::Module
*module
, CellTypes
*filter_ct
= NULL
)
332 this->design
= design
;
333 this->module
= module
;
339 signal_drivers
.clear();
340 signal_consumers
.clear();
341 signal_inputs
.clear();
342 signal_outputs
.clear();
344 for (auto &it
: module
->wires_
)
346 for (auto &it
: module
->cells_
)
347 if (filter_ct
== NULL
|| filter_ct
->cell_known(it
.second
->type
))
351 // get_* methods -- single RTLIL::SigBit
354 inline bool get_drivers(pool
<PortBit
> &result
, RTLIL::SigBit bit
) const
357 if (signal_drivers
.count(bit
)) {
358 const pool
<PortBit
> &r
= signal_drivers
.at(bit
);
359 result
.insert(r
.begin(), r
.end());
366 inline bool get_consumers(pool
<PortBit
> &result
, RTLIL::SigBit bit
) const
369 if (signal_consumers
.count(bit
)) {
370 const pool
<PortBit
> &r
= signal_consumers
.at(bit
);
371 result
.insert(r
.begin(), r
.end());
378 inline bool get_inputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigBit bit
) const
381 if (signal_inputs
.count(bit
))
382 result
.insert(bit
), found
= true;
387 inline bool get_outputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigBit bit
) const
390 if (signal_outputs
.count(bit
))
391 result
.insert(bit
), found
= true;
395 // get_* methods -- container of RTLIL::SigBit's (always by reference)
398 inline bool get_drivers(pool
<PortBit
> &result
, const T
&bits
) const
401 for (RTLIL::SigBit bit
: bits
)
402 if (signal_drivers
.count(bit
)) {
403 const pool
<PortBit
> &r
= signal_drivers
.at(bit
);
404 result
.insert(r
.begin(), r
.end());
411 inline bool get_consumers(pool
<PortBit
> &result
, const T
&bits
) const
414 for (RTLIL::SigBit bit
: bits
)
415 if (signal_consumers
.count(bit
)) {
416 const pool
<PortBit
> &r
= signal_consumers
.at(bit
);
417 result
.insert(r
.begin(), r
.end());
424 inline bool get_inputs(pool
<RTLIL::SigBit
> &result
, const T
&bits
) const
427 for (RTLIL::SigBit bit
: bits
)
428 if (signal_inputs
.count(bit
))
429 result
.insert(bit
), found
= true;
434 inline bool get_outputs(pool
<RTLIL::SigBit
> &result
, const T
&bits
) const
437 for (RTLIL::SigBit bit
: bits
)
438 if (signal_outputs
.count(bit
))
439 result
.insert(bit
), found
= true;
443 // get_* methods -- call by RTLIL::SigSpec (always by value)
445 bool get_drivers(pool
<PortBit
> &result
, RTLIL::SigSpec signal
) const
447 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
448 return get_drivers(result
, bits
);
451 bool get_consumers(pool
<PortBit
> &result
, RTLIL::SigSpec signal
) const
453 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
454 return get_consumers(result
, bits
);
457 bool get_inputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigSpec signal
) const
459 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
460 return get_inputs(result
, bits
);
463 bool get_outputs(pool
<RTLIL::SigBit
> &result
, RTLIL::SigSpec signal
) const
465 std::vector
<RTLIL::SigBit
> bits
= sigmap(signal
);
466 return get_outputs(result
, bits
);
469 // has_* methods -- call by reference
472 inline bool has_drivers(const T
&sig
) const {
473 pool
<PortBit
> result
;
474 return get_drivers(result
, sig
);
478 inline bool has_consumers(const T
&sig
) const {
479 pool
<PortBit
> result
;
480 return get_consumers(result
, sig
);
484 inline bool has_inputs(const T
&sig
) const {
485 pool
<RTLIL::SigBit
> result
;
486 return get_inputs(result
, sig
);
490 inline bool has_outputs(const T
&sig
) const {
491 pool
<RTLIL::SigBit
> result
;
492 return get_outputs(result
, sig
);
495 // has_* methods -- call by value
497 inline bool has_drivers(RTLIL::SigSpec sig
) const {
498 pool
<PortBit
> result
;
499 return get_drivers(result
, sig
);
502 inline bool has_consumers(RTLIL::SigSpec sig
) const {
503 pool
<PortBit
> result
;
504 return get_consumers(result
, sig
);
507 inline bool has_inputs(RTLIL::SigSpec sig
) const {
508 pool
<RTLIL::SigBit
> result
;
509 return get_inputs(result
, sig
);
512 inline bool has_outputs(RTLIL::SigSpec sig
) const {
513 pool
<RTLIL::SigBit
> result
;
514 return get_outputs(result
, sig
);