Note: This repository is provided for the purpose of double-blind review for ICCAD 2026. Please do not distribute or deanonymize.
HELIX is a framework for LLM-driven algorithmic evolution of production placement engines. It operates directly on the C++ source of both the global placement (GPL) and detailed placement (DPL) modules in OpenROAD, discovering interpretable algorithmic improvements that a human engineer can read, understand, and adopt.
Rather than writing placement algorithms from scratch, HELIX evolves the existing codebase through a (mu+lambda) evolutionary strategy: tuning numerical parameters, restructuring algorithmic hot-loops, implementing techniques from placement literature, and proposing novel optimizations -- all validated by building, running, and measuring real HPWL and runtime impact on benchmark designs.
Integration with DREAMPlace confirms that the framework generalizes across codebases and languages without modification.
Across twelve design--node pairs (NanGate45 and ASAP7), the evolved placers:
- Reduce post-detailed placement HPWL by up to 9% (4.5% geometric mean)
- Reduce routed wirelength by up to 23% (5.6% geometric mean)
- Preserve timing and power
- Generalize to unseen designs (3 of 6 designs were not part of evolution)
Against a comparable-budget LLM single-shot baseline, HELIX achieves 7x larger fitness gains.
+----------------+
| spec.yaml | configuration
+-------+--------+
|
+-------v--------+
| evo.cli | CLI entry-point
+-------+--------+
|
+------------v------------+
| EvolutionaryLoop | orchestrator
| (evo/loop.py) |
+------------+------------+
|
+--------------------+--------------------+
| | |
+------v-------+ +------v-------+ +-------v-------+
| Bottleneck | | Code | | Generation |
| Analyzer | | Evolver | | Reflection |
+--------------+ +------+-------+ +---------------+
|
+-------------+-------------+
| | |
+------v---+ +----v-----+ +----v-----+
| Build | | Bench | | Fitness |
| (make) | | (openrd) | | Score |
+----------+ +----------+ +----------+
- Bottleneck analysis (generation 0 only) -- an LLM ranks functions by optimization potential given the user's query.
- Pipeline detection (generation 0 only) -- LLM-driven detection of orchestrator patterns (functions that sequence multiple optimization sub-algorithms).
- Parent selection -- Tournament selection picks
muparents from the population. - Offspring generation -- For each of
lambdaoffspring, the loop selects a parent, samples an operator from the adaptive distribution, assigns a focus target (parameter cluster or algorithm), and dispatches a coding agent to edit C++ source in an isolated git worktree. - Build --
build_worktree.shoverlays modified sources onto the main repo, runsmakeinside a Singularity container, then restores originals. - Benchmark --
openroad_dpl_bench.sh(oropenroad_gpl_bench.sh) runs each design and extracts HPWL / runtime. - Fitness -- Per-design scores are computed via Equation 1 (with adaptive gamma) and aggregated via Equation 2.
- Refinement retry -- Near-miss offspring (beat baseline but not parent)
receive up to
max_refinement_attemptsiterative refinement rounds with benchmark feedback and placement diagnostics. - Placement analysis -- DEF files are parsed to compute spatial displacement deltas; heatmaps are generated for visualization.
- Reflection -- If runtime regressed or results are mixed across designs, a reflection agent attempts a targeted fix.
- Survivor selection -- The top
muindividuals survive, scored by fitness (60%), focus-target diversity (25%), and a lineage crowding penalty. - Stagnation injection -- If best fitness has not improved for
stagnation_thresholdgenerations, a fresh individual is evolved from the unmodified baseline usingmutate_liton a novel focus target and injected into the population. - Generation reflection -- An LLM analyzes the generation, recommends operator weight adjustments, and identifies tabu regions.
- Telemetry -- All calls, outcomes, token consumption, costs, diff sizes,
and failure modes are logged to
telemetry.jsonl.
helix/
├── spec.yaml # OpenROAD evolution configuration
├── spec_dreamplace.yaml # DREAMPlace evolution configuration
├── pyproject.toml # Package metadata (placement-evo 0.1.0)
├── evo/ # Main Python package
│ ├── __main__.py # python -m evo entry
│ ├── cli.py # Click CLI (run, results, ls, show, promote)
│ ├── loop.py # EvolutionaryLoop orchestrator
│ ├── config.py # Typed dataclasses from spec.yaml
│ ├── models.py # Individual, EvolutionHistory, TabuEntry
│ ├── context_builder.py # Builds per-operator prompt context
│ ├── operator_scheduler.py # Adaptive operator selection
│ ├── focus_selector.py # Focus target assignment
│ ├── telemetry.py # Per-call telemetry with aggregation
│ ├── constants.py # Shared constants and paths
│ ├── refine.py # Refinement retry logic
│ ├── preserve.py # Best-individual promotion
│ ├── distill.py # Literature distillation pipeline
│ ├── single_shot.py # LLM single-shot baseline
│ ├── adapters/
│ │ ├── base.py # AgentAdapter / LLMAdapter ABCs
│ │ ├── agent_cli.py # Cursor Agent adapter for code editing
│ │ ├── claude_cli.py # Claude Code adapter for analysis
│ │ └── codex_cli.py # OpenAI Codex adapter
│ ├── agents/
│ │ ├── bottleneck_analyzer.py # Query-driven function ranking via LLM
│ │ ├── code_evolver.py # Full individual lifecycle
│ │ └── build_repair.py # Automated compilation error fixing
│ ├── operators/
│ │ ├── base.py # EvolutionaryOperator ABC
│ │ ├── mutation.py # Lit, Creative, Struct, Param mutations
│ │ ├── crossover.py # CrossoverOperator
│ │ ├── reflection.py # Population + Generation reflection
│ │ └── templates/ # Jinja2 prompt templates
│ │ ├── _base.j2 # Shared prompt skeleton
│ │ ├── mutation_lit.j2 # Literature-guided mutation
│ │ ├── mutation_creative.j2 # Creative/novel mutation
│ │ ├── mutation_struct.j2 # Structural refactoring
│ │ ├── mutation_param.j2 # Parameter tuning
│ │ ├── crossover.j2 # Two-parent crossover
│ │ ├── reflect_population.j2
│ │ ├── reflect_generation.j2
│ │ ├── refine_post.j2 # Refinement retry prompt
│ │ ├── build_repair.j2 # Build error repair
│ │ └── single_shot.j2 # Single-shot baseline
│ ├── fitness/
│ │ └── score.py # Fitness equations and baseline loading
│ ├── analysis/
│ │ ├── def_diff.py # DEF parsing, delta computation, heatmaps
│ │ ├── pipeline_detector.py # Orchestrator/pipeline pattern detection
│ │ └── render_heatmap.py # Matplotlib heatmap renderer
│ ├── common/
│ │ ├── io.py # Run directory I/O, checkpointing
│ │ ├── json_utils.py # Robust JSON extraction from LLM output
│ │ └── schemas.py # Pydantic schemas for structured output
│ └── sandbox/
│ └── workspace.py # Git worktree create / cleanup
├── scripts/
│ ├── build_worktree.sh # Source-overlay incremental build
│ ├── openroad_gpl_bench.sh # Run OpenROAD GPL benchmarks
│ ├── openroad_dpl_bench.sh # Run OpenROAD DPL benchmarks
│ ├── dreamplace_bench.sh # Run DREAMPlace benchmarks
│ ├── build_dreamplace_worktree.sh # DREAMPlace worktree setup
│ ├── run_gpl_baseline.sh # Baseline GPL benchmark runner
│ ├── profile_dpl.sh # CPU profiling on benchmark designs
│ ├── parse_openroad_metrics.py # Extract HPWL/runtime from OpenROAD logs
│ ├── parse_dreamplace_metrics.py # Extract metrics from DREAMPlace logs
│ ├── validate_pipeline.py # End-to-end pipeline validation
│ ├── extract_parameters.py # Extract tunable constants from source
│ ├── extract_design_stats.py # Extract design statistics
│ ├── build_call_graphs.py # Generate call graph JSON from source
│ ├── generate_pseudocode.py # LLM-generated pseudocode for functions
│ ├── distill_literature.py # Distill papers into literature cards
│ ├── sweep_target_density.py # DREAMPlace target density sweep
│ ├── eval_helix_dreamplace.py # Evaluate HELIX on DREAMPlace
│ ├── eval_evoplace_configs.py # Evaluate EvoPlace configurations
│ ├── plot_llm_ss_comparison.py # Plot LLM single-shot comparison
│ ├── plot_operator_ablation.py # Plot operator analysis
│ └── plot_evolution_trajectory.py # Plot evolution fitness trajectory
├── corpus/ # OpenROAD Corpus (ORC)
│ ├── baseline/ # Reference HPWL and runtime per design
│ ├── call_graphs/ # Static call graphs (GPL, DPL, DREAMPlace)
│ ├── pseudocode/ # LLM-generated pseudocode abstractions
│ ├── literature/ # Distilled paper summaries (97 JSON cards)
│ ├── parameters/ # Curated tunable constants with ranges
│ ├── profiling/ # Per-design CPU hotspot data
│ ├── design_stats/ # Design statistics
│ ├── lessons/ # Consolidated evolution lessons
│ └── docs/ # Architecture guides and domain references
├── saved_best/ # Best evolved individuals
│ ├── merged_gpl_dpl/ # Combined GPL+DPL patches and source
│ ├── llm_ss_best/ # LLM single-shot baseline best
│ └── evo-*/ # Per-run best individuals with patches
├── evoplace_eval/ # DREAMPlace evaluation harness
│ ├── dreamplace/ # Modified DREAMPlace Python modules
│ └── results/ # ISPD 2005 benchmark results
├── results/ # Evaluation result summaries
└── example_prompts/ # Candidate prompts from evolution runs
└── evo-<timestamp>-<id>/ # Per-run prompt archives
└── gen<N>-<operator>-<hex>/ # Per-candidate prompt
└── prompt.txt # Full LLM prompt used for mutation
- Python 3.9+ with pip
- OpenROAD repository cloned and pre-built (for OpenROAD evolution)
- DREAMPlace repository cloned and installed (for DREAMPlace evolution)
- Singularity/Apptainer container image with the build toolchain
- LLM CLI tools (at least one of the following):
- Cursor Agent CLI for code editing tasks
- Claude Code CLI for analysis tasks
- (Optional)
matplotlibandnumpyfor placement heatmap generation
# Clone the repository
git clone <repository-url> helix
cd helix
# Install the Python package in editable mode
pip install -e .
# Verify installation
evo --helpHELIX is configured through YAML specification files. Two are provided:
spec.yaml-- Configuration for evolving OpenROAD's GPL and DPL modulesspec_dreamplace.yaml-- Configuration for evolving DREAMPlace
Before running, update the following paths in the spec file to match your environment:
| Key | Description |
|---|---|
targets.<module>.source_dir |
Path to the target module's source directory |
build.repo_root |
Path to the OpenROAD or DREAMPlace repository root |
build.build_dir |
Path to the build output directory |
build.bench_command |
Path to the benchmark script |
build.singularity_image |
Path to the Singularity/Apptainer container image |
analysis.bo_env_python |
Path to Python environment for Bayesian optimization |
| Section | Key Fields | Description |
|---|---|---|
target_module |
"dpl", "gpl", or "dreamplace_gp" |
Which module to evolve |
targets.<module> |
source_dir, call_graph, pseudocode_dir, entry_functions |
Per-module paths and metadata |
designs.evolution |
List of design names | Designs used for fitness during evolution |
designs.evaluation |
List of design names | Full evaluation suite (post-run) |
fitness |
w1, w2, gamma, gamma_end, zeta |
Fitness equation weights |
evolution |
mu, lambda, G_max, k_tournament |
Evolutionary algorithm parameters |
operator_weights |
a_param, a_struct, a_lit, a_creative, a_xover |
Operator probability weights |
build |
repo_root, build_dir, threads, timeout_s |
Build environment settings |
agent |
model, timeout_s |
Coding agent settings |
llm |
model, timeout_s |
Analysis LLM settings |
# Minimal dry-run (1 generation, 1 parent, 2 offspring)
python -m evo -v run \
--spec spec.yaml \
--query "Optimize HPWL in detailed placement" \
--gens 1 --mu 1 --lam 2
# Full production run (mu=5, lambda=8, 15 generations)
python -m evo -v run \
--spec spec.yaml \
--query "Optimize HPWL in detailed placement" \
--gens 15 --mu 5 --lam 8
# Resume a previous run
python -m evo run --spec spec.yaml --query "..." --resume .evo/runs/<run-id># List all runs
python -m evo ls
# Show top candidates from latest run
python -m evo results --top 20
# Inspect a specific candidate (with diff and prompt)
python -m evo show <run-id> <candidate-id> --diff --prompt
# Promote a candidate's commit to a named git branch
python -m evo promote <run-id> <candidate-id> my-improvementpython -m evo -v single-shot \
--spec spec.yaml \
--query "Optimize HPWL in detailed placement" \
--shots 120The ORC is a multi-layered knowledge base that grounds every LLM mutation in structured domain knowledge. It is assembled once per target module and reused across all generations.
| Component | Location | Description |
|---|---|---|
| Literature technique cards | corpus/literature/cards/ |
97 research papers distilled into structured JSON cards |
| Pseudocode abstractions | corpus/pseudocode/ |
Algorithm-level pseudocode for performance-critical functions |
| Call graphs | corpus/call_graphs/ |
Static call graphs extracted via Clang-based analysis |
| Parameter catalog | corpus/parameters/ |
Tunable constants with source locations and mutation ranges |
| CPU profiling data | corpus/profiling/ |
Per-design hotspot rankings |
| Architecture guides | corpus/docs/ |
Narrative architecture overviews for GPL and DPL modules |
| Baseline metrics | corpus/baseline/ |
Reference HPWL and runtime per design |
# Generate call graphs from source
python scripts/build_call_graphs.py --source-dir <path-to-module>
# Generate pseudocode abstractions
bash scripts/run_generate_pseudocode.sh
# Distill literature papers into technique cards
python scripts/distill_literature.py --papers-dir <path-to-pdfs>
# Extract tunable parameters from source
python scripts/extract_parameters.py --source-dir <path-to-module>Per-design fitness (Equation 1):
f_N(theta) = w1 * (HPWL_baseline / HPWL_candidate)
- w2 * max(0, runtime_candidate / runtime_baseline - gamma_eff)
- zeta (if build crashed or produced illegal placement)
Aggregate fitness (Equation 2):
f_bar = (1 / |designs|) * SUM( f_N )
A candidate matching baseline performance exactly scores w1 (default 1.0).
HPWL improvements push fitness above w1. A runtime penalty applies only when
the candidate exceeds gamma_eff times the baseline runtime. Build failures
receive a penalty of -zeta (default -100).
The runtime tolerance gamma_eff decays linearly over generations:
gamma_eff = gamma_start - (gamma_start - gamma_end) * (generation / G_max)
Early generations allow runtime overhead for algorithmic exploration; late generations enforce runtime neutrality.
| Operator | Purpose | Line Budget | Focus Target |
|---|---|---|---|
mutate_param |
Perturb 1--3 numerical constants within annotated ranges | 25 | Parameter cluster |
mutate_struct |
Restructure control flow or data access patterns | 100 | Algorithm |
mutate_lit |
Implement a technique from a retrieved literature card | 200 | Algorithm |
mutate_creative |
Novel heuristic guided by profiling and placement data | 200 | Algorithm |
crossover |
Merge complementary diffs from two parents | 500 | None |
Line budgets are advisory; the fitness function is the sole arbiter of solution quality. Operator selection probabilities are adapted across generations via three multiplicative factors: progress-based scheduling, stagnation boosting, and Laplace-smoothed empirical success rates.
The saved_best/ directory contains the best evolved individuals from each
evolution run:
BEST_INDIVIDUAL.md-- Summary of fitness, per-design metrics, and the evolutionary path (operator, generation, focus target)patches/-- Git-format patches that can be applied to the baseline OpenROAD repositorysource/-- Snapshot of the modified source files
The merged_gpl_dpl/ subdirectory contains the combined GPL+DPL patches used
for the end-to-end evaluation reported in the paper.
To apply a patch:
cd <openroad-repo>
git apply <path-to-patch>/cumulative_gpl.patch
git apply <path-to-patch>/cumulative_dpl.patchThe example_prompts/ directory contains the full LLM prompts used during
evolution runs. Each prompt demonstrates how the Context Builder assembles
domain knowledge, evolutionary context, and operator-specific instructions into
a single coherent prompt for the coding agent.
This project is released under the BSD 3-Clause License. See LICENSE for details.