Skip to content

Commit

Permalink
proc_dff: optimize self-assignment at bit granularity
Browse files Browse the repository at this point in the history
  • Loading branch information
georgerennie committed Nov 28, 2024
1 parent 94a6c09 commit ed989f8
Showing 1 changed file with 32 additions and 13 deletions.
45 changes: 32 additions & 13 deletions passes/proc/proc_dff.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,28 +178,47 @@ class Dff {
}

// If the lowest priority async rule assigns the output value to itself,
// remove the rule and fold this into the input signal.
// remove the rule and fold this into the input signal. If the LSB assigns
// the output to itself but higher bits don't, we resize down to just the
// LSBs that assign to themselves, allowing more optimized representations
// for those bits.
void optimize_self_assign(ConstEval& ce) {
SigSpec sig_out_mapped = sig_out;
ce.assign_map.apply(sig_out_mapped);

size_t new_size = async_rules.size();
for (auto it = async_rules.crbegin(); it != async_rules.crend(); it++) {
const auto& [value, trigger] = *it;
// Calculate the number of low priority rules that can be folded into
// the input signal for a given bit position
const auto foldable_rules = [&](const size_t i) {
size_t foldable = 0;
for (auto it = async_rules.crbegin(); it != async_rules.crend(); it++, foldable++) {
const auto& [value, trigger] = *it;
if (value[i] != sig_out_mapped[i])
break;
}
return foldable;
};

// Work out how many bits from the lsb can be folded into the same
// number of rules
const size_t lsb_foldable_rules = foldable_rules(0);

if (value != sig_out_mapped)
size_t new_size;
for (new_size = 1; new_size < size(); new_size++)
if (foldable_rules(new_size) != lsb_foldable_rules)
break;

if (!trigger.inverted)
sig_in = mod.Mux(NEW_ID, sig_in, value, trigger.sig);
else
sig_in = mod.Mux(NEW_ID, value, sig_in, trigger.sig);
resize(new_size);

ce.eval(sig_in);
new_size--;
}
// Calculate the disjunction of triggers
SigSpec triggers;
for (size_t i = 0; i < lsb_foldable_rules; i++)
triggers.append(async_rules.crbegin()[i].trigger.positive_trigger(mod));

const auto trigger = mod.ReduceOr(NEW_ID, triggers);
sig_in = mod.Mux(NEW_ID, sig_in, sig_out, trigger);
ce.eval(sig_in);

async_rules.resize(new_size);
async_rules.resize(async_rules.size() - lsb_foldable_rules);
}

// If we have only a single rule, this means we will generate either an $aldff
Expand Down

0 comments on commit ed989f8

Please sign in to comment.