3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-15 19:55:41 +00:00

Speed up opt_* using cut_region with shared_ce

This commit is contained in:
Akash Levy 2026-07-06 07:42:47 -07:00
parent 9d39a82587
commit bab0ee6bf8
3 changed files with 54 additions and 23 deletions

View file

@ -826,6 +826,20 @@ struct CutRegionWorker
return sig;
}
// Shared ConstEval for the whole matching phase. The netlist is not
// modified until rewrites are applied, so one instance (built once, at
// O(module) cost) serves every fingerprint eval instead of rebuilding
// one per candidate. Callers keep push/pop balanced, so the base state
// stays clean between uses (asserted on each hand-out).
std::unique_ptr<ConstEval> shared_ce_ptr;
ConstEval &shared_ce()
{
if (!shared_ce_ptr)
shared_ce_ptr = std::make_unique<ConstEval>(module);
log_assert(shared_ce_ptr->stack.empty());
return *shared_ce_ptr;
}
// Evaluate `out_sig` under the given input assignments; returns false if
// the cut does not fully determine the output. Charges the eval budget
// by `cone_cells_estimate`.

View file

@ -256,7 +256,7 @@ struct OptPriorityOnehotWorker : CutRegionWorker {
bool fingerprint(const Candidate &cand, bool msb_first)
{
ConstEval ce(module);
ConstEval &ce = shared_ce();
SigSpec out_sig = sigmap(cand.out_sig);
SigSpec valid_sig = sigmap(cand.valid_sig);
SigSpec field_sig = sigmap(cand.field_sig);

View file

@ -236,7 +236,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
for (auto bit : en_cands)
cand_bits.push_back(bit);
ConstEval ce(module);
ConstEval &ce = shared_ce();
SigSpec out_s = sigmap(root_sig);
SigSpec data_s = sigmap(data_sig);
SigSpec cand_s;
@ -415,7 +415,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
{
if (width < 4)
return false;
ConstEval ce(module);
ConstEval &ce = shared_ce();
SigSpec in_s = sigmap(in_sig);
SigSpec out_s = sigmap(out_sig);
@ -511,7 +511,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
int wd = GetSize(dis_s);
int wt = GetSize(data_s);
bool self = sigmap(dis_s) == sigmap(data_s);
ConstEval ce(module);
ConstEval &ce = shared_ce();
for (int pol = 0; pol < 2; pol++) {
// A self-pair (data == disable bus) can only be probed with all
// lanes enabled AND data all-ones, i.e. enable-high polarity.
@ -546,7 +546,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
return false;
if (lw > wd || lw > wt || wd > 62 || wt > 62)
return false;
ConstEval ce(module);
ConstEval &ce = shared_ce();
SigSpec dis_s = sigmap(dis_sig);
SigSpec data_s = sigmap(data_sig);
SigSpec out_s = sigmap(out_sig);
@ -615,8 +615,14 @@ struct OptCompactPrefixWorker : CutRegionWorker
return mask;
}
// Evaluate the modulo vector set once and test all four
// (msb_first, offset) variants against the recorded outputs, in the
// original priority order with first-match tie-break. This replaces up
// to four full ConstEval sweeps (one per variant) with a single sweep;
// sets out_msb_first/out_offset on the first surviving variant.
bool fingerprint_modulo(const SigSpec &en_sig, const SigSpec &n_sig,
const SigSpec &mask_sig, int width, bool msb_first, int offset)
const SigSpec &mask_sig, int width,
bool &out_msb_first, int &out_offset)
{
if (width <= 0 || width > 62)
return false;
@ -624,7 +630,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
// also matches plain gating muxes; require a real counter range.
if (GetSize(n_sig) < 2)
return false;
ConstEval ce(module);
ConstEval &ce = shared_ce();
SigSpec en_s = sigmap(en_sig);
SigSpec n_s = sigmap(n_sig);
SigSpec mask_s = sigmap(mask_sig);
@ -653,6 +659,12 @@ struct OptCompactPrefixWorker : CutRegionWorker
envals.push_back(lfsr & full);
}
// Variants in the original check order (msb/lsb x offset 0/1).
static const struct { bool msb; int off; } variants[] = {
{true, 0}, {false, 0}, {false, 1}, {true, 1}
};
bool alive[4] = {true, true, true, true};
for (uint64_t nv : nvals)
for (uint64_t ev : envals) {
uint64_t actual;
@ -660,10 +672,27 @@ struct OptCompactPrefixWorker : CutRegionWorker
{n_s, const_u64(nv, nw)}},
mask_s, actual))
return false;
if (actual != expected_modulo_mask(ev, nv, width, msb_first, offset))
bool any = false;
for (int v = 0; v < 4; v++) {
if (!alive[v])
continue;
if (actual != expected_modulo_mask(ev, nv, width,
variants[v].msb, variants[v].off))
alive[v] = false;
else
any = true;
}
if (!any)
return false;
}
return true;
for (int v = 0; v < 4; v++)
if (alive[v]) {
out_msb_first = variants[v].msb;
out_offset = variants[v].off;
return true;
}
return false;
}
// --- Forward gather/compress: out[k] = data[i_k] where i_k is the
@ -693,7 +722,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
{
if (width < 4 || width > 62)
return false;
ConstEval ce(module);
ConstEval &ce = shared_ce();
SigSpec en_s = sigmap(en_sig);
SigSpec data_s = sigmap(data_sig);
SigSpec out_s = sigmap(out_sig);
@ -1397,19 +1426,7 @@ struct OptCompactPrefixWorker : CutRegionWorker
fp_attempts++;
bool msb_first = false;
int offset = -1;
if (fingerprint_modulo(en.sig, n.sig, root.sig, width, true, 0)) {
msb_first = true;
offset = 0;
} else if (fingerprint_modulo(en.sig, n.sig, root.sig, width, false, 0)) {
msb_first = false;
offset = 0;
} else if (fingerprint_modulo(en.sig, n.sig, root.sig, width, false, 1)) {
msb_first = false;
offset = 1;
} else if (fingerprint_modulo(en.sig, n.sig, root.sig, width, true, 1)) {
msb_first = true;
offset = 1;
} else {
if (!fingerprint_modulo(en.sig, n.sig, root.sig, width, msb_first, offset)) {
log_debug(" mod %s/%s: fingerprint mismatch\n", en.name.c_str(), n.name.c_str());
continue;
}