|
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 |
@@ -163,13 +164,7 @@ class Dff { |
163 | 164 | return async_rules[i].value[bit] == async_rules[i + 1].value[bit]; |
164 | 165 | }; |
165 | 166 |
|
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); |
| 167 | + const bool lsb_optimizable = shrink_while_matching_values(bit_optimizable); |
173 | 168 |
|
174 | 169 | if (!lsb_optimizable) { |
175 | 170 | i++; |
@@ -212,16 +207,7 @@ class Dff { |
212 | 207 | return foldable; |
213 | 208 | }; |
214 | 209 |
|
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); |
| 210 | + const size_t lsb_foldable_rules = shrink_while_matching_values(foldable_rules); |
225 | 211 |
|
226 | 212 | if (lsb_foldable_rules == 0) |
227 | 213 | return; |
@@ -250,17 +236,10 @@ class Dff { |
250 | 236 | if (async_rules.size() != 1) |
251 | 237 | return; |
252 | 238 |
|
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); |
| 239 | + const auto bit_is_wire = [&](const size_t i) { |
| 240 | + return async_rules.front().value[i].is_wire(); |
| 241 | + }; |
| 242 | + shrink_while_matching_values(bit_is_wire); |
264 | 243 | } |
265 | 244 |
|
266 | 245 | void generate() { |
@@ -432,6 +411,23 @@ class Dff { |
432 | 411 | value = value.extract(0, new_size); |
433 | 412 | } |
434 | 413 |
|
| 414 | + // Given some function that maps from an index to a value, this resizes |
| 415 | + // the dff to a range starting at the LSB that all return the same value |
| 416 | + // from the function as the LSB. This function also returns the value |
| 417 | + // calculated for the LSB. |
| 418 | + template <typename F> |
| 419 | + typename std::result_of<F(size_t)>::type shrink_while_matching_values(F f) { |
| 420 | + const auto base_val = f(0); |
| 421 | + |
| 422 | + size_t new_size; |
| 423 | + for (new_size = 1; new_size < size(); new_size++) |
| 424 | + if (f(new_size) != base_val) |
| 425 | + break; |
| 426 | + |
| 427 | + resize(new_size); |
| 428 | + return base_val; |
| 429 | + } |
| 430 | + |
435 | 431 | RTLIL::Process& proc; |
436 | 432 | RTLIL::Module& mod; |
437 | 433 |
|
|
0 commit comments