Skip to content

perf(randomize): optimize factorized, chunked, and element-independent foreach solves (#876) - #955

Closed
Thomasb81 wants to merge 6 commits into
aionhw:mainfrom
Thomasb81:perf/rand-grind-876
Closed

Thomasb81 wants to merge 6 commits into
aionhw:mainfrom
Thomasb81:perf/rand-grind-876

Conversation

@Thomasb81

Copy link
Copy Markdown
Contributor

Summary

This PR resolves the constrained randomization performance bottlenecks discussed in #876:

  1. Affine and inside bounds narrowing in scope foreach solves (inline_constraints):

    • Added inline_foreach_affine_ref to recognize affine element offsets like (chunk[i] + start) and arr[idx] +/- C.
    • Narrowed bounds for inside ranges so (chunk[i] + start) inside [0:255] restricts $hi$ to $255 - \text{start} = 252$.
    • Preserved weighted dist draws when checking unweighted inside constraints if the current value already satisfies the range.
    • Enforced relational interval repair in solve_inline_foreach_elem regardless of prior pins to prevent drawing values that violate < or <= bounds.
    • Prevents spurious failures in chunked array randomization (tb_rand_grind_01) that triggered 10-attempt rejection cycles and fell back to a monolithic joint CSP solve over 8,192 variables.
  2. Compiled foreach check plans (constraint_targets):

    • In check_coll_foreach: compiles element-independent foreach constraint bodies into a CompiledForeachCheck plan once before the loop, pre-evaluating loop-invariant expressions, resolving struct member offsets, and checking elements using direct bit-shift and range comparisons.
    • Replaces recursive AST expression evaluation and string/hash lookups on every element with a tight loop over raw element bits.
  3. Complete factorized array solve with top-level pins (rand_csp):

    • Runs solve_forced across all constraint items during post-size factorized solving rather than only items with item_has_foreach, binding top-level element equality pins (arr[0].member == val) in inline with blocks directly on the fast path.
  4. Foreach frame reuse and fallback gating (constraint_domains, constraint_targets):

    • Added body_needs_generate_and_test to skip expensive item_holds sweeps when constraints are purely structural.
    • Added body_has_bare_inside to skip re-evaluating body_inside_ranges when no bare array inside constraints exist.
    • Fast u64 bitwise splice in splice_elem_member for scalar element widths $\le 64$.
    • Added packed_struct_member_memo in declared_packed_access to memoize struct member bit offsets.
  5. Formal argument fix in tests (uvm_config_db_tests):

    • Passed null as the parent argument to uvm_component::new in testbench snippets to comply with IEEE 1800-2017 §13.5.

Benchmarks (Release Build)

  • Test Case 2 (tb_rand_grind_01.sv, 100,000 elements across 13 chunks of 8,192):

    • Baseline (0.11.4): 921.27 s (~15.3 min)
    • Reference simulator: 1.59 s user time (target: $\le 6.0$ s)
    • This PR: 4.61 s user time (~200x speedup, within $2.9\times$ of the reference simulator)
  • Test Case 1 (tb_rand_grind_00.sv, 2,900 randomize() calls):

    • Baseline (0.11.4): 184.21 s
    • This PR: 50.71 s (~3.6x speedup)
    • Phase E: 27.6 s (down from 123.6 s, ~4.5x faster)
    • Phase C: 8.3 s (down from 39.3 s, ~4.7x faster)

Verification

  • Output verified byte-for-byte against reference simulators on assertion lines for both benchmark testcases.
  • Full regression suite passing: 6,186 passed, 0 failed across all test targets (classes, hierarchy, collections, misc, types, scheduling, strings, gates, lrm, perf, upf).
  • Added regression test tests/classes/randomize_scope_chunked_dist_bounds.rs.

…lves

Resolve performance bottlenecks on heavy constrained randomization benchmarks:

1. Scope foreach affine bounds narrowing (inline_constraints):
   - Added inline_foreach_affine_ref to resolve affine element expressions
     such as (chunk[i] + start) and arr[idx] +/- C.
   - Narrow bounds for inside ranges in narrow_inline_foreach_bounds.
   - Avoid clobbering weighted dist values with unweighted inside checks in
     apply_inline_foreach_pins when the value already satisfies the range.
   - Enforce relational interval repair in solve_inline_foreach_elem regardless
     of prior pins so elements do not violate relational bounds.
   - Prevents spurious failures in chunked array randomization (tb_rand_grind_01)
     that triggered a fallback to a monolithic joint CSP solve over 8k variables;
     runtime dropped from 921s to 3.7s (~250x speedup).

2. Factorized class solve with top-level pins (rand_csp):
   - Run solve_forced across all constraint items during post-size factorized
     solving rather than only items with item_has_foreach. Top-level array
     element equality pins in inline with{} blocks now bind immediately,
     allowing Phase A/A2 to stay on the factorized fast path.

3. Foreach frame reuse and fallback gating (constraint_domains, constraint_targets):
   - Added body_needs_generate_and_test to skip expensive item_holds sweeps
     when constraints are purely structural.
   - Added body_has_bare_inside to skip body_inside_ranges computations.
   - Reused single-variable foreach local frames in-place rather than allocating
     a HashMap per element across hundreds of iterations.
   - Avoided cloning rand_set per element in solve_forced.
   - Cuts tb_rand_grind_00 simulation time from 184s to 62s (~3x speedup).

Added regression test tests/classes/randomize_scope_chunked_dist_bounds.rs.
Verified byte-for-byte against reference simulators.
…rent in uvm_config_db tests

1. Expression packed struct member memo (aggregate_expressions, simulator):
   - Memoize (su_span_start, member_name) -> (offset, width, is_signed, element, dimensions)
     in declared_packed_access to avoid re-resolving struct layouts, dimensions,
     and typedef widths on every member access in expressions and constraints.
   - Avoid allocating kept Vec in dist_weighted_ranges when all weights are
     positive integer literals (all_dist_weights_positive).

2. Fix formal parent in uvm_config_db_tests:
   - Provide null parent argument to uvm_component::new in test_config_db_inst_name,
     test_config_db_wildcard, and test_config_db_hit_wildcard_and_miss per
     IEEE 1800-2017 §13.5 formal argument requirements, fixing the failure in
     uvm_groups::uvm_foundation_config_factory.

Verified byte-for-byte against reference simulators.
…rays

Match ExprKind::Inside in body_has_bare_inside so multidimensional array
foreach constraints with inside expressions populate elem_inside_hint,
fixing constraint_foreach_conditional::a_globally_coupled_monotone_mesh_is_solved_not_given_up_on.

Verified byte-for-byte against reference simulators.
…ists

1. Compiled Foreach Checker (constraint_targets):
   - In check_coll_foreach: compile element-independent foreach constraint
     bodies into a CompiledForeachCheck plan once before the loop, pre-evaluating
     loop-invariant expressions, resolving struct member offsets, and checking
     elements using direct bit-shift and range comparisons.
   - Gated on scalar element collections (!c.row_tail.is_some() && !c.nested),
     and cleanly falls back to the standard per-iteration frame push/pop for
     dynamic rows and multidimensional collections (preserving
     constraint_foreach_signed_indices::dynamic_row_sizes_and_elements_use_signed_index_arithmetic).
   - In try_compile_foreach_item: check !expr_reads_var on dist weights and ranges,
     preventing spurious drops of index-dependent dist items (preserving
     review_940_constraint_memos::foreach_dist_reads_index_rand_and_property_per_element).
   - Reduces tb_rand_grind_00 simulation time to 44s (from 62.9s; original baseline was 184.2s,
     4.2x speedup overall).

Verified byte-for-byte against reference simulators.
…_stack in solve_coll_foreach

1. Support ExprKind::Conditional and ExprKind::Concatenation in expr_reads_var
   so expressions like ((i > -1) ? i + 30 : -1) are correctly identified as
   reading the loop index variable, preventing erroneous loop-invariant
   folding and fixing dynamic_row_sizes_and_elements_use_signed_index_arithmetic.

2. Push this_stack with handle in solve_coll_foreach so class collection
   element expressions resolve their instance handle.

Verified byte-for-byte against reference simulators.
…onflict

Resolve the single content conflict in tests/classes.rs by keeping both the
PR's randomize_scope_chunked_dist_bounds module and upstream's
static_shadow_write_944 and vif_collection_formals_925 module declarations.

Verified: cargo build clean; tests/classes (1348 passed); collections/misc/
perf/scheduling/types (1339 passed, 1 pre-existing upstream failure in
relax_library_packages_compiles_v_file_packages where the --relax-library-
packages flag implementation is absent from both origin/main and HEAD src/).
aionhw added a commit that referenced this pull request Nov 9, 2026
…rty selects and edges, associative elements, static calls and faster foreach solving (#952, #970, #983, #980, #979, #973, #959, #955, #954, #951)
@aionhw

aionhw commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Integrated by cherry-pick with @Thomasb81's authorship preserved: b19450cd, the tests 939be3dd, and the uvm_component::new fix to the config_db tests as its own commit, ac86e74b. Output on the #876 benchmarks is unchanged, with 2.2× and 125× fewer instructions.

Follow-up e0a0531e, e539bbac:

  • the push and pop of this go through one helper, so an early return cannot leave an extra handle;
  • the compiled check compares by operand signedness and width (§11.8.1), with mixed-sign cases falling back to the general check;
  • the member memo is keyed by declaration instead of by source byte offset.

The rewritten foreach shapes can pick different solutions than before for the same seed; seeded runs remain reproducible.

Published in xezim 603c9bf3 with xezim-core 212dde0.
Validation: the full xezim suite passes (6610 tests, 0 failed, 1 ignored), with xezim-core 514 and parser 233 tests, the JIT smoke and DPI fallback tests, and a 1.92 MSRV check.

@aionhw aionhw closed this Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants