3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-17 04:35:44 +00:00

opt_prienc: guard ConstEval fingerprint inputs against constant/aliased bits

The round-robin detector fed sigmap(wire) signals straight into
ConstEval::set() while sweeping test vectors. On real designs a candidate
bus can have bits tied to constants, repeated bits, or a req/start pair
that alias to the same net after sigmap. ConstEval::set() asserts
(current_val[i].wire != NULL || current_val[i] == value[i]) when asked to
re-pin such a bit to a conflicting value, crashing the pass
(consteval.h:83) on designs like veer/picorv32/murax/raygentop under
formal synthesis.

Add clean_set_signals() and reject any fingerprint candidate whose
set-signals contain constant bits, repeated bits, or overlap each other,
in both the priority-encoder and round-robin paths. Skipping an unclean
candidate only forgoes a possible rewrite; it never produces an incorrect
one. Clean candidates (the intended patterns) are unaffected.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Akash Levy 2026-07-06 21:35:51 -07:00
parent 84f4054584
commit 676ac184ed

View file

@ -243,6 +243,23 @@ struct OptPriEncWorker {
return vs;
}
// ConstEval::set() requires every (sigmap-canonical) bit it pins to be a
// distinct free wire bit. Real designs can tie parts of a bus to constants
// or alias nets together, so guard the fingerprint inputs: reject signals
// containing constant or repeated bits, and (across the whole set) any
// overlap between them. This prevents a ConstEval assertion; skipping an
// unclean candidate only forgoes a possible rewrite, never yields a wrong
// one.
static bool clean_set_signals(std::initializer_list<const SigSpec*> sigs) {
pool<SigBit> seen;
for (const SigSpec* sp : sigs)
for (auto bit : *sp) {
if (bit.wire == nullptr) return false;
if (!seen.insert(bit).second) return false;
}
return true;
}
// Run all candidate test vectors through ConstEval and try to match each of
// the four PE variants against the recorded outputs. Returns the matched
// variant, or NONE.
@ -257,6 +274,9 @@ struct OptPriEncWorker {
if (!clz_full_ok && !ctz_full_ok && !clz_short_ok && !ctz_short_ok)
return PEVariant::NONE;
if (!clean_set_signals({&T_sig}))
return PEVariant::NONE;
auto vs = gen_test_vectors(N);
for (auto& v : vs) {
ce.push();
@ -440,6 +460,8 @@ struct OptPriEncWorker {
int fingerprint_rr(SigSpec req_sig, SigSpec start_sig, SigSpec S_sig,
int N, int W) {
ConstEval ce(module);
if (!clean_set_signals({&req_sig, &start_sig}))
return -1;
bool ok0 = true, ok1 = true;
auto deck = gen_test_vectors(N);
int checks = 0;