|
25 | 25 | #include <stdlib.h> |
26 | 26 | #include <stdio.h> |
27 | 27 | #include <algorithm> |
| 28 | +#include <type_traits> |
28 | 29 |
|
29 | 30 | USING_YOSYS_NAMESPACE |
30 | 31 | PRIVATE_NAMESPACE_BEGIN |
@@ -159,17 +160,9 @@ class Dff { |
159 | 160 | // higher bits cannot be optimized in the same way. |
160 | 161 | void optimize_same_value(ConstEval& ce) { |
161 | 162 | for (size_t i = 0; i + 1 < async_rules.size();) { |
162 | | - const auto bit_optimizable = [&](const size_t bit) { |
| 163 | + const bool lsb_optimizable = shrink_while_matching_values([&](const size_t bit) { |
163 | 164 | return async_rules[i].value[bit] == async_rules[i + 1].value[bit]; |
164 | | - }; |
165 | | - |
166 | | - const bool lsb_optimizable = bit_optimizable(0); |
167 | | - |
168 | | - size_t new_size; |
169 | | - for (new_size = 1; new_size < size(); new_size++) |
170 | | - if (bit_optimizable(new_size) != lsb_optimizable) |
171 | | - break; |
172 | | - resize(new_size); |
| 165 | + }); |
173 | 166 |
|
174 | 167 | if (!lsb_optimizable) { |
175 | 168 | i++; |
@@ -202,26 +195,15 @@ class Dff { |
202 | 195 |
|
203 | 196 | // Calculate the number of low priority rules that can be folded into |
204 | 197 | // the input signal for a given bit position |
205 | | - const auto foldable_rules = [&](const size_t i) { |
| 198 | + const size_t lsb_foldable_rules = shrink_while_matching_values([&](const size_t i) { |
206 | 199 | size_t foldable = 0; |
207 | 200 | for (auto it = async_rules.crbegin(); it != async_rules.crend(); it++, foldable++) { |
208 | 201 | const auto& [value, trigger] = *it; |
209 | 202 | if (value[i] != sig_out_mapped[i]) |
210 | 203 | break; |
211 | 204 | } |
212 | 205 | return foldable; |
213 | | - }; |
214 | | - |
215 | | - // Work out how many bits from the lsb can be folded into the same |
216 | | - // number of rules |
217 | | - const size_t lsb_foldable_rules = foldable_rules(0); |
218 | | - |
219 | | - size_t new_size; |
220 | | - for (new_size = 1; new_size < size(); new_size++) |
221 | | - if (foldable_rules(new_size) != lsb_foldable_rules) |
222 | | - break; |
223 | | - |
224 | | - resize(new_size); |
| 206 | + }); |
225 | 207 |
|
226 | 208 | if (lsb_foldable_rules == 0) |
227 | 209 | return; |
@@ -250,17 +232,9 @@ class Dff { |
250 | 232 | if (async_rules.size() != 1) |
251 | 233 | return; |
252 | 234 |
|
253 | | - const auto& [val, trigger] = async_rules.front(); |
254 | | - log_assert(GetSize(val) > 0); |
255 | | - |
256 | | - const bool lsb_wire = val[0].is_wire(); |
257 | | - |
258 | | - size_t new_size; |
259 | | - for (new_size = 1; new_size < size(); new_size++) |
260 | | - if (val[new_size].is_wire() != lsb_wire) |
261 | | - break; |
262 | | - |
263 | | - resize(new_size); |
| 235 | + shrink_while_matching_values([&](const size_t i) { |
| 236 | + return async_rules.front().value[i].is_wire(); |
| 237 | + }); |
264 | 238 | } |
265 | 239 |
|
266 | 240 | void generate() { |
@@ -432,6 +406,23 @@ class Dff { |
432 | 406 | value = value.extract(0, new_size); |
433 | 407 | } |
434 | 408 |
|
| 409 | + // Given some function that maps from an index to a value, this resizes |
| 410 | + // the dff to a range starting at the LSB that all return the same value |
| 411 | + // from the function as the LSB. This function also returns the value |
| 412 | + // calculated for the LSB. |
| 413 | + template <typename F> |
| 414 | + typename std::result_of<F(size_t)>::type shrink_while_matching_values(F f) { |
| 415 | + const auto base_val = f(0); |
| 416 | + |
| 417 | + size_t new_size; |
| 418 | + for (new_size = 1; new_size < size(); new_size++) |
| 419 | + if (f(new_size) != base_val) |
| 420 | + break; |
| 421 | + |
| 422 | + resize(new_size); |
| 423 | + return base_val; |
| 424 | + } |
| 425 | + |
435 | 426 | RTLIL::Process& proc; |
436 | 427 | RTLIL::Module& mod; |
437 | 428 |
|
|
0 commit comments