Skip to content

Commit 94a6c09

Browse files
committed
proc_dff: split constant and non-constant resets into different flops
1 parent 2b50afb commit 94a6c09

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

passes/proc/proc_dff.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class Dff {
130130
optimize_const_eval(ce);
131131
optimize_same_value(ce);
132132
optimize_self_assign(ce);
133+
optimize_single_rule_consts();
133134
}
134135

135136
// Const evaluate async rule values and triggers, and remove those that
@@ -201,6 +202,31 @@ class Dff {
201202
async_rules.resize(new_size);
202203
}
203204

205+
// If we have only a single rule, this means we will generate either an $aldff
206+
// or an $adff if the reset value is constant or non-constant respectively.
207+
// If there are any non-constant bits in the rule value, an $aldff will be
208+
// used for all bits, but we would like to use an $adff for as many
209+
// bits as possible. This optimization therefore calculates the longest run
210+
// of bits starting at the LSB of the value with the same constness and
211+
// removes the rest from consideration in this pass. This means that const
212+
// and non-const sections can be separately mapped to $adff and $aldff.
213+
void optimize_single_rule_consts() {
214+
if (async_rules.size() != 1)
215+
return;
216+
217+
const auto& [val, trigger] = async_rules.front();
218+
log_assert(GetSize(val) > 0);
219+
220+
const bool lsb_wire = val[0].is_wire();
221+
222+
size_t new_size;
223+
for (new_size = 1; new_size < size(); new_size++)
224+
if (val[new_size].is_wire() != lsb_wire)
225+
break;
226+
227+
resize(new_size);
228+
}
229+
204230
void generate() {
205231
// Progressively attempt more complex formulations, preferring the
206232
// simpler ones. These rules should be able to cover all representable
@@ -360,6 +386,16 @@ class Dff {
360386
bool explicitly_clocked() const { return !always && !clk.empty(); }
361387

362388
private:
389+
void resize(const size_t new_size) {
390+
if (new_size >= size())
391+
return;
392+
393+
sig_in = sig_in.extract(0, new_size);
394+
sig_out = sig_out.extract(0, new_size);
395+
for (auto& [value, _] : async_rules)
396+
value = value.extract(0, new_size);
397+
}
398+
363399
RTLIL::Process& proc;
364400
RTLIL::Module& mod;
365401

0 commit comments

Comments
 (0)