@@ -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
362388private:
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