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"
26 #include "kernel/macc.h"
30 RTLIL::Module
*module
;
34 SigSet
<RTLIL::Cell
*> sig2driver
;
35 std::set
<RTLIL::Cell
*> busy
;
36 std::vector
<SigMap
> stack
;
38 ConstEval(RTLIL::Module
*module
) : module(module
), assign_map(module
)
44 for (auto &it
: module
->cells_
) {
45 if (!ct
.cell_known(it
.second
->type
))
47 for (auto &it2
: it
.second
->connections())
48 if (ct
.cell_output(it
.second
->type
, it2
.first
))
49 sig2driver
.insert(assign_map(it2
.second
), it
.second
);
61 stack
.push_back(values_map
);
66 values_map
.swap(stack
.back());
70 void set(RTLIL::SigSpec sig
, RTLIL::Const value
)
72 assign_map
.apply(sig
);
74 RTLIL::SigSpec current_val
= values_map(sig
);
75 for (int i
= 0; i
< SIZE(current_val
); i
++)
76 log_assert(current_val
[i
].wire
!= NULL
|| current_val
[i
] == value
.bits
[i
]);
78 values_map
.add(sig
, RTLIL::SigSpec(value
));
81 void stop(RTLIL::SigSpec sig
)
83 assign_map
.apply(sig
);
84 stop_signals
.add(sig
);
87 bool eval(RTLIL::Cell
*cell
, RTLIL::SigSpec
&undef
)
89 if (cell
->type
== "$lcu")
91 RTLIL::SigSpec sig_p
= cell
->getPort("\\P");
92 RTLIL::SigSpec sig_g
= cell
->getPort("\\G");
93 RTLIL::SigSpec sig_ci
= cell
->getPort("\\CI");
94 RTLIL::SigSpec sig_co
= values_map(assign_map(cell
->getPort("\\CO")));
96 if (sig_co
.is_fully_const())
99 if (!eval(sig_p
, undef
, cell
))
102 if (!eval(sig_g
, undef
, cell
))
105 if (!eval(sig_ci
, undef
, cell
))
108 if (sig_p
.is_fully_def() && sig_g
.is_fully_def() && sig_ci
.is_fully_def())
110 RTLIL::Const
coval(RTLIL::Sx
, SIZE(sig_co
));
111 bool carry
= sig_ci
.as_bool();
113 for (int i
= 0; i
< SIZE(coval
); i
++) {
114 carry
= (sig_g
[i
] == RTLIL::S1
) || (sig_p
[i
] == RTLIL::S1
&& carry
);
115 coval
.bits
[i
] = carry
? RTLIL::S1
: RTLIL::S0
;
121 set(sig_co
, RTLIL::Const(RTLIL::Sx
, SIZE(sig_co
)));
126 RTLIL::SigSpec sig_a
, sig_b
, sig_s
, sig_y
;
128 log_assert(cell
->hasPort("\\Y"));
129 sig_y
= values_map(assign_map(cell
->getPort("\\Y")));
130 if (sig_y
.is_fully_const())
133 if (cell
->hasPort("\\S")) {
134 sig_s
= cell
->getPort("\\S");
135 if (!eval(sig_s
, undef
, cell
))
139 if (cell
->hasPort("\\A"))
140 sig_a
= cell
->getPort("\\A");
142 if (cell
->hasPort("\\B"))
143 sig_b
= cell
->getPort("\\B");
145 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$_MUX_")
147 std::vector
<RTLIL::SigSpec
> y_candidates
;
148 int count_maybe_set_s_bits
= 0;
149 int count_set_s_bits
= 0;
151 for (int i
= 0; i
< sig_s
.size(); i
++)
153 RTLIL::State s_bit
= sig_s
.extract(i
, 1).as_const().bits
.at(0);
154 RTLIL::SigSpec b_slice
= sig_b
.extract(sig_y
.size()*i
, sig_y
.size());
156 if (s_bit
== RTLIL::State::Sx
|| s_bit
== RTLIL::State::S1
)
157 y_candidates
.push_back(b_slice
);
159 if (s_bit
== RTLIL::State::S1
|| s_bit
== RTLIL::State::Sx
)
160 count_maybe_set_s_bits
++;
162 if (s_bit
== RTLIL::State::S1
)
166 if (count_set_s_bits
== 0)
167 y_candidates
.push_back(sig_a
);
169 std::vector
<RTLIL::Const
> y_values
;
171 log_assert(y_candidates
.size() > 0);
172 for (auto &yc
: y_candidates
) {
173 if (!eval(yc
, undef
, cell
))
175 y_values
.push_back(yc
.as_const());
178 if (y_values
.size() > 1)
180 std::vector
<RTLIL::State
> master_bits
= y_values
.at(0).bits
;
182 for (size_t i
= 1; i
< y_values
.size(); i
++) {
183 std::vector
<RTLIL::State
> &slave_bits
= y_values
.at(i
).bits
;
184 log_assert(master_bits
.size() == slave_bits
.size());
185 for (size_t j
= 0; j
< master_bits
.size(); j
++)
186 if (master_bits
[j
] != slave_bits
[j
])
187 master_bits
[j
] = RTLIL::State::Sx
;
190 set(sig_y
, RTLIL::Const(master_bits
));
193 set(sig_y
, y_values
.front());
195 else if (cell
->type
== "$fa")
197 RTLIL::SigSpec sig_c
= cell
->getPort("\\C");
198 RTLIL::SigSpec sig_x
= cell
->getPort("\\X");
199 int width
= SIZE(sig_c
);
201 if (!eval(sig_a
, undef
, cell
))
204 if (!eval(sig_b
, undef
, cell
))
207 if (!eval(sig_c
, undef
, cell
))
210 RTLIL::Const t1
= const_xor(sig_a
.as_const(), sig_b
.as_const(), false, false, width
);
211 RTLIL::Const val_y
= const_xor(t1
, sig_c
.as_const(), false, false, width
);
213 RTLIL::Const t2
= const_and(sig_a
.as_const(), sig_b
.as_const(), false, false, width
);
214 RTLIL::Const t3
= const_and(sig_c
.as_const(), t1
, false, false, width
);
215 RTLIL::Const val_x
= const_or(t2
, t3
, false, false, width
);
220 else if (cell
->type
== "$alu")
222 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
223 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
225 RTLIL::SigSpec sig_ci
= cell
->getPort("\\CI");
226 RTLIL::SigSpec sig_bi
= cell
->getPort("\\BI");
228 if (!eval(sig_a
, undef
, cell
))
231 if (!eval(sig_b
, undef
, cell
))
234 if (!eval(sig_ci
, undef
, cell
))
237 if (!eval(sig_bi
, undef
, cell
))
240 RTLIL::SigSpec sig_x
= cell
->getPort("\\X");
241 RTLIL::SigSpec sig_co
= cell
->getPort("\\CO");
243 bool any_input_undef
= !(sig_a
.is_fully_def() && sig_b
.is_fully_def() && sig_ci
.is_fully_def() && sig_bi
.is_fully_def());
244 sig_a
.extend_u0(SIZE(sig_y
), signed_a
);
245 sig_b
.extend_u0(SIZE(sig_y
), signed_b
);
247 bool carry
= sig_ci
[0] == RTLIL::S1
;
248 bool b_inv
= sig_bi
[0] == RTLIL::S1
;
250 for (int i
= 0; i
< SIZE(sig_y
); i
++)
252 RTLIL::SigSpec x_inputs
= { sig_a
[i
], sig_b
[i
], sig_bi
[0] };
254 if (!x_inputs
.is_fully_def()) {
255 set(sig_x
[i
], RTLIL::Sx
);
257 bool bit_a
= sig_a
[i
] == RTLIL::S1
;
258 bool bit_b
= (sig_b
[i
] == RTLIL::S1
) != b_inv
;
259 bool bit_x
= bit_a
!= bit_b
;
260 set(sig_x
[i
], bit_x
? RTLIL::S1
: RTLIL::S0
);
263 if (any_input_undef
) {
264 set(sig_y
[i
], RTLIL::Sx
);
265 set(sig_co
[i
], RTLIL::Sx
);
267 bool bit_a
= sig_a
[i
] == RTLIL::S1
;
268 bool bit_b
= (sig_b
[i
] == RTLIL::S1
) != b_inv
;
269 bool bit_y
= (bit_a
!= bit_b
) != carry
;
270 carry
= (bit_a
&& bit_b
) || (bit_a
&& carry
) || (bit_b
&& carry
);
271 set(sig_y
[i
], bit_y
? RTLIL::S1
: RTLIL::S0
);
272 set(sig_co
[i
], carry
? RTLIL::S1
: RTLIL::S0
);
276 else if (cell
->type
== "$macc")
279 macc
.from_cell(cell
);
281 if (!eval(macc
.bit_ports
, undef
, cell
))
284 for (auto &port
: macc
.ports
) {
285 if (!eval(port
.in_a
, undef
, cell
))
287 if (!eval(port
.in_b
, undef
, cell
))
291 RTLIL::Const
result(0, SIZE(cell
->getPort("\\Y")));
292 if (!macc
.eval(result
))
295 set(cell
->getPort("\\Y"), result
);
299 RTLIL::SigSpec sig_c
, sig_d
;
301 if (cell
->type
.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) {
302 if (cell
->hasPort("\\C"))
303 sig_c
= cell
->getPort("\\C");
304 if (cell
->hasPort("\\D"))
305 sig_d
= cell
->getPort("\\D");
308 if (sig_a
.size() > 0 && !eval(sig_a
, undef
, cell
))
310 if (sig_b
.size() > 0 && !eval(sig_b
, undef
, cell
))
312 if (sig_c
.size() > 0 && !eval(sig_c
, undef
, cell
))
314 if (sig_d
.size() > 0 && !eval(sig_d
, undef
, cell
))
317 set(sig_y
, CellTypes::eval(cell
, sig_a
.as_const(), sig_b
.as_const(),
318 sig_c
.as_const(), sig_d
.as_const()));
324 bool eval(RTLIL::SigSpec
&sig
, RTLIL::SigSpec
&undef
, RTLIL::Cell
*busy_cell
= NULL
)
326 assign_map
.apply(sig
);
327 values_map
.apply(sig
);
329 if (sig
.is_fully_const())
332 if (stop_signals
.check_any(sig
)) {
333 undef
= stop_signals
.extract(sig
);
338 if (busy
.count(busy_cell
) > 0) {
342 busy
.insert(busy_cell
);
345 std::set
<RTLIL::Cell
*> driver_cells
;
346 sig2driver
.find(sig
, driver_cells
);
347 for (auto cell
: driver_cells
) {
348 if (!eval(cell
, undef
)) {
350 busy
.erase(busy_cell
);
356 busy
.erase(busy_cell
);
358 values_map
.apply(sig
);
359 if (sig
.is_fully_const())
362 for (auto &c
: sig
.chunks())
368 bool eval(RTLIL::SigSpec
&sig
)
370 RTLIL::SigSpec undef
;
371 return eval(sig
, undef
);