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/rtlil.h"
24 #include "kernel/sigtools.h"
25 #include "kernel/celltypes.h"
29 RTLIL::Module
*module
;
33 SigSet
<RTLIL::Cell
*> sig2driver
;
34 std::set
<RTLIL::Cell
*> busy
;
35 std::vector
<SigMap
> stack
;
37 ConstEval(RTLIL::Module
*module
) : module(module
), assign_map(module
)
43 for (auto &it
: module
->cells
) {
44 if (!ct
.cell_known(it
.second
->type
))
46 for (auto &it2
: it
.second
->connections
)
47 if (ct
.cell_output(it
.second
->type
, it2
.first
))
48 sig2driver
.insert(assign_map(it2
.second
), it
.second
);
60 stack
.push_back(values_map
);
65 values_map
.swap(stack
.back());
69 void set(RTLIL::SigSpec sig
, RTLIL::Const value
)
71 assign_map
.apply(sig
);
73 RTLIL::SigSpec current_val
= values_map(sig
);
75 for (size_t i
= 0; i
< current_val
.chunks
.size(); i
++) {
76 RTLIL::SigChunk
&chunk
= current_val
.chunks
[i
];
77 assert(chunk
.wire
!= NULL
|| chunk
.data
.bits
[0] == value
.bits
[i
]);
80 values_map
.add(sig
, RTLIL::SigSpec(value
));
83 void stop(RTLIL::SigSpec sig
)
85 assign_map
.apply(sig
);
86 stop_signals
.add(sig
);
89 bool eval(RTLIL::Cell
*cell
, RTLIL::SigSpec
&undef
)
91 RTLIL::SigSpec sig_a
, sig_b
, sig_s
, sig_y
;
92 bool ignore_sig_a
= false, ignore_sig_b
= false;
95 assert(cell
->connections
.count("\\Y") > 0);
96 sig_y
= values_map(assign_map(cell
->connections
["\\Y"]));
97 if (sig_y
.is_fully_const())
100 if (cell
->connections
.count("\\S") > 0) {
101 sig_s
= cell
->connections
["\\S"];
102 if (!eval(sig_s
, undef
, cell
))
106 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$safe_pmux" || cell
->type
== "$_MUX_") {
107 bool found_collision
= false;
108 for (int i
= 0; i
< sig_s
.width
; i
++)
109 if (sig_s
.extract(i
, 1).as_bool()) {
110 if (sig_b_shift
>= 0)
111 found_collision
= true;
114 if (cell
->type
!= "$safe_pmux")
117 if (found_collision
) {
119 ignore_sig_a
= false;
125 if (!ignore_sig_a
&& cell
->connections
.count("\\A") > 0) {
126 sig_a
= cell
->connections
["\\A"];
127 if (!eval(sig_a
, undef
, cell
))
131 if (!ignore_sig_b
&& cell
->connections
.count("\\B") > 0) {
132 sig_b
= cell
->connections
["\\B"];
133 if (sig_b_shift
>= 0)
134 sig_b
= sig_b
.extract(sig_y
.width
*sig_b_shift
, sig_y
.width
);
135 if (!eval(sig_b
, undef
, cell
))
139 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$safe_pmux" || cell
->type
== "$_MUX_")
140 set(sig_y
, sig_s
.as_bool() ? sig_b
.as_const() : sig_a
.as_const());
142 set(sig_y
, CellTypes::eval(cell
, sig_a
.as_const(), sig_b
.as_const()));
147 bool eval(RTLIL::SigSpec
&sig
, RTLIL::SigSpec
&undef
, RTLIL::Cell
*busy_cell
= NULL
)
149 assign_map
.apply(sig
);
150 values_map
.apply(sig
);
152 if (sig
.is_fully_const())
155 if (stop_signals
.check_any(sig
)) {
156 undef
= stop_signals
.extract(sig
);
161 if (busy
.count(busy_cell
) > 0) {
165 busy
.insert(busy_cell
);
168 std::set
<RTLIL::Cell
*> driver_cells
;
169 sig2driver
.find(sig
, driver_cells
);
170 for (auto cell
: driver_cells
) {
171 if (!eval(cell
, undef
)) {
173 busy
.erase(busy_cell
);
179 busy
.erase(busy_cell
);
181 values_map
.apply(sig
);
182 if (sig
.is_fully_const())
185 for (size_t i
= 0; i
< sig
.chunks
.size(); i
++)
186 if (sig
.chunks
[i
].wire
!= NULL
)
187 undef
.append(sig
.chunks
[i
]);
191 bool eval(RTLIL::SigSpec
&sig
)
193 RTLIL::SigSpec undef
;
194 return eval(sig
, undef
);