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
);
74 for (int i
= 0; i
< SIZE(current_val
); i
++)
75 assert(current_val
[i
].wire
!= NULL
|| current_val
[i
] == value
.bits
[i
]);
77 values_map
.add(sig
, RTLIL::SigSpec(value
));
80 void stop(RTLIL::SigSpec sig
)
82 assign_map
.apply(sig
);
83 stop_signals
.add(sig
);
86 bool eval(RTLIL::Cell
*cell
, RTLIL::SigSpec
&undef
)
88 RTLIL::SigSpec sig_a
, sig_b
, sig_s
, sig_y
;
90 assert(cell
->has("\\Y"));
91 sig_y
= values_map(assign_map(cell
->get("\\Y")));
92 if (sig_y
.is_fully_const())
95 if (cell
->has("\\S")) {
96 sig_s
= cell
->get("\\S");
97 if (!eval(sig_s
, undef
, cell
))
101 if (cell
->has("\\A"))
102 sig_a
= cell
->get("\\A");
104 if (cell
->has("\\B"))
105 sig_b
= cell
->get("\\B");
107 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$safe_pmux" || cell
->type
== "$_MUX_")
109 std::vector
<RTLIL::SigSpec
> y_candidates
;
110 int count_maybe_set_s_bits
= 0;
111 int count_set_s_bits
= 0;
113 for (int i
= 0; i
< sig_s
.size(); i
++)
115 RTLIL::State s_bit
= sig_s
.extract(i
, 1).as_const().bits
.at(0);
116 RTLIL::SigSpec b_slice
= sig_b
.extract(sig_y
.size()*i
, sig_y
.size());
118 if (s_bit
== RTLIL::State::Sx
|| s_bit
== RTLIL::State::S1
)
119 y_candidates
.push_back(b_slice
);
121 if (s_bit
== RTLIL::State::S1
|| s_bit
== RTLIL::State::Sx
)
122 count_maybe_set_s_bits
++;
124 if (s_bit
== RTLIL::State::S1
)
128 if (cell
->type
== "$safe_pmux" && count_set_s_bits
> 1)
129 y_candidates
.clear();
131 if ((cell
->type
== "$safe_pmux" && count_maybe_set_s_bits
> 1) || count_set_s_bits
== 0)
132 y_candidates
.push_back(sig_a
);
134 std::vector
<RTLIL::Const
> y_values
;
136 assert(y_candidates
.size() > 0);
137 for (auto &yc
: y_candidates
) {
138 if (!eval(yc
, undef
, cell
))
140 y_values
.push_back(yc
.as_const());
143 if (y_values
.size() > 1)
145 std::vector
<RTLIL::State
> master_bits
= y_values
.at(0).bits
;
147 for (size_t i
= 1; i
< y_values
.size(); i
++) {
148 std::vector
<RTLIL::State
> &slave_bits
= y_values
.at(i
).bits
;
149 assert(master_bits
.size() == slave_bits
.size());
150 for (size_t j
= 0; j
< master_bits
.size(); j
++)
151 if (master_bits
[j
] != slave_bits
[j
])
152 master_bits
[j
] = RTLIL::State::Sx
;
155 set(sig_y
, RTLIL::Const(master_bits
));
158 set(sig_y
, y_values
.front());
162 if (sig_a
.size() > 0 && !eval(sig_a
, undef
, cell
))
164 if (sig_b
.size() > 0 && !eval(sig_b
, undef
, cell
))
166 set(sig_y
, CellTypes::eval(cell
, sig_a
.as_const(), sig_b
.as_const()));
172 bool eval(RTLIL::SigSpec
&sig
, RTLIL::SigSpec
&undef
, RTLIL::Cell
*busy_cell
= NULL
)
174 assign_map
.apply(sig
);
175 values_map
.apply(sig
);
177 if (sig
.is_fully_const())
180 if (stop_signals
.check_any(sig
)) {
181 undef
= stop_signals
.extract(sig
);
186 if (busy
.count(busy_cell
) > 0) {
190 busy
.insert(busy_cell
);
193 std::set
<RTLIL::Cell
*> driver_cells
;
194 sig2driver
.find(sig
, driver_cells
);
195 for (auto cell
: driver_cells
) {
196 if (!eval(cell
, undef
)) {
198 busy
.erase(busy_cell
);
204 busy
.erase(busy_cell
);
206 values_map
.apply(sig
);
207 if (sig
.is_fully_const())
210 for (auto &c
: sig
.chunks())
216 bool eval(RTLIL::SigSpec
&sig
)
218 RTLIL::SigSpec undef
;
219 return eval(sig
, undef
);