3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-24 01:25:33 +00:00

proc_dff: split constant and non-constant resets into different flops

This commit is contained in:
George Rennie 2024-11-28 17:10:11 +01:00
parent bd2cdd31af
commit b7c830b55a

View file

@ -130,6 +130,7 @@ public:
optimize_const_eval(ce);
optimize_same_value(ce);
optimize_self_assign(ce);
optimize_single_rule_consts();
}
// Const evaluate async rule values and triggers, and remove those that
@ -201,6 +202,31 @@ public:
async_rules.resize(new_size);
}
// If we have only a single rule, this means we will generate either an $aldff
// or an $adff if the reset value is constant or non-constant respectively.
// If there are any non-constant bits in the rule value, an $aldff will be
// used for all bits, but we would like to use an $adff for as many
// bits as possible. This optimization therefore calculates the longest run
// of bits starting at the LSB of the value with the same constness and
// removes the rest from consideration in this pass. This means that const
// and non-const sections can be separately mapped to $adff and $aldff.
void optimize_single_rule_consts() {
if (async_rules.size() != 1)
return;
const auto& [val, trigger] = async_rules.front();
log_assert(GetSize(val) > 0);
const bool lsb_wire = val[0].is_wire();
size_t new_size;
for (new_size = 1; new_size < size(); new_size++)
if (val[new_size].is_wire() != lsb_wire)
break;
resize(new_size);
}
void generate() {
// Progressively attempt more complex formulations, preferring the
// simpler ones. These rules should be able to cover all representable
@ -360,6 +386,16 @@ public:
bool explicitly_clocked() const { return !always && !clk.empty(); }
private:
void resize(const size_t new_size) {
if (new_size >= size())
return;
sig_in = sig_in.extract(0, new_size);
sig_out = sig_out.extract(0, new_size);
for (auto& [value, _] : async_rules)
value = value.extract(0, new_size);
}
RTLIL::Process& proc;
RTLIL::Module& mod;