Agentic FPGA Backend Optimization Competition @ FPL'26
This is a preliminary example agent for contestants getting started, see details below:
Contest website can be found here: https://xilinx.github.io/fpl26_optimization_contest/
An example LLM-powered autonomous agent that optimizes FPGA designs for timing using RapidWright and Vivado optimizations and tools via MCP (Model Context Protocol) servers.
- Overview
- Architecture
- Quick Start
- Running the Optimizer
- Validating Optimized Designs
- VivadoMCP Server
- RapidWrightMCP Server
- Optimization Strategies
- Optimization Workflow
- Example Session
- Troubleshooting
- Project Structure
- License
- Resources
This project provides an intelligent agent that:
- Analyzes FPGA design checkpoints (.dcp files) for timing issues
- Identifies high-fanout nets on critical timing paths
- Applies fanout optimization using RapidWright
- Routes the optimized design in Vivado
- Iteratively improves timing until the design meets targets or no further improvement is possible
The agent uses two MCP servers that enable AI assistants to interact with FPGA design tools:
- VivadoMCP: Provides access to Xilinx Vivado's design analysis and implementation tools
- RapidWrightMCP: Provides access to RapidWright's netlist manipulation and optimization capabilities
┌────────────────────────────────────────────────────────┐
│ dcp_optimizer.py │
│ (AI Optimization Agent) │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ RapidWrightMCP │ │ VivadoMCP │ │
│ │ (Python MCP) │ │ (Python MCP) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ RapidWright │ │ Vivado Tcl │ │
│ │ (Java/JPype) │ │ (stdin/stdout) │ │
│ └─────────────────┘ └─────────────────┘ │
└────────────────────────────────────────────────────────┘
The fastest way to get started is with the Makefile:
# 1. Run setup (installs dependencies, downloads benchmark DCPs)
make setup
# 2a. Run in test mode (no API key required)
make run_test DCP=fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp
# 2b. Or run the full LLM-guided optimizer (requires API key)
export OPENROUTER_API_KEY="<your_key_here>"
make run_optimizer DCP=fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcpSee the Running the Optimizer section for more details.
- Python 3.8+
- Java 11+ (for RapidWright - can be auto-detected from Vivado)
- AMD/Xilinx Vivado (2025.1)
- Vivado must be on your PATH, or you can set the
VIVADO_EXECenvironment variable
- Vivado must be on your PATH, or you can set the
- OpenRouter API key (for LLM access, optional for test mode)
The easiest way to set up the project is using the provided Makefile:
# Clone the repository (--recursive initializes the RapidWright submodule)
git clone --recursive https://github.com/Xilinx/fpl26_optimization_contest.git
cd fpl26_optimization_contest
# Run setup (installs deps, builds RapidWright, checks Vivado/Java, downloads benchmark DCPs)
make setup
# If Vivado is not on your PATH, specify it when running make:
make setup VIVADO_EXEC=/path/to/Vivado/2025.1/bin/vivado
# Or set VIVADO_EXEC as an environment variable:
export VIVADO_EXEC=/path/to/Vivado/2025.1/bin/vivado
make setupThe make setup command will:
- Install Python dependencies from
requirements.txt - Check if Vivado is available (and provide instructions if not)
- Check for Java, or locate Java from the Vivado installation
- Build RapidWright from the
RapidWright/git submodule source - Download and extract benchmark DCPs into
fpl26_contest_benchmarks/
If you prefer not to use the Makefile:
# Initialize the RapidWright git submodule
git submodule update --init RapidWright
# Install Python dependencies
pip install -r requirements.txt
# Build RapidWright from source
cd RapidWright && ./gradlew compileJava && cd ..
# Set environment variables to use local RapidWright source
export RAPIDWRIGHT_PATH=$(pwd)/RapidWright
export CLASSPATH=$RAPIDWRIGHT_PATH/bin:$RAPIDWRIGHT_PATH/jars/*
# Verify Java is available (required for RapidWright)
java -version
# Download and extract benchmark DCPs
wget https://github.com/Xilinx/fpl26_optimization_contest/releases/download/v1.0.0/fpl26_contest_benchmarks_v1.0.0.tar.gz
tar xzf fpl26_contest_benchmarks_v1.0.0.tar.gzImportant: Set JAVA_HOME
When running the optimizer scripts directly (without the Makefile), you may need to set JAVA_HOME. The Makefile automatically detects JAVA_HOME from either:
- The
javacommand on your PATH, or - The Java bundled with Vivado (at
<VIVADO_ROOT>/tps/lnx64/jre21*/bin/java)
For manual invocation, you need to set it explicitly:
# Option 1: If java is on your PATH
# Linux (with readlink -f support):
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
# macOS / Linux alternative:
export JAVA_HOME=$(/usr/libexec/java_home 2>/dev/null || dirname $(dirname $(which java)))
# Option 2: Use Java bundled with Vivado (if java is not on PATH)
# See: https://www.rapidwright.io/docs/Install.html#using-java-distributed-with-vivado
VIVADO_ROOT=$(dirname $(dirname $(which vivado)))
export JAVA_HOME=$(ls -d $VIVADO_ROOT/tps/lnx64/jre21* | head -n 1)
export PATH=$JAVA_HOME/bin:$PATH
# Verify it's set correctly
echo $JAVA_HOME
java -versionRapidWright (used for netlist manipulation) may need JAVA_HOME to locate the Java installation.
The Makefile provides convenient targets for running the optimizer:
# Test mode: no API key required, uses hardcoded optimization flow
make run_test DCP=fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp
make run_test DCP=fpl26_contest_benchmarks/vexriscv_re-place_2025.1.dcp
# Full agent mode: LLM-guided optimization (requires OPENROUTER_API_KEY)
export OPENROUTER_API_KEY="<your_key_here>"
make run_optimizer DCP=fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcpBoth targets will:
- Generate timestamped output:
<input>_optimized-YYYYMMDD_HHMMSS.dcp(in same directory as input) - Create a run directory:
dcp_optimizer_run-YYYYMMDD_HHMMSS/(contains all logs and intermediate files)
| Target | Description |
|---|---|
make help |
Show available targets and usage (default) |
make setup |
Install dependencies, build RapidWright, check tools, download benchmark DCPs |
make build-rapidwright |
Build RapidWright from source (git submodule); re-run after modifying RapidWright code |
make run_test DCP=<file> |
Run optimizer in test mode — no LLM required (supports MAX_NETS option) |
make run_optimizer DCP=<file> |
Run LLM-guided optimizer (requires OPENROUTER_API_KEY) |
make clean |
Remove run directories and .Xil directories (preserves optimized DCPs) |
make veryclean |
Deep clean including benchmark DCPs and Python cache |
Test mode runs a deterministic optimization flow without using an LLM, useful for debugging and verifying the MCP servers work correctly. The test mode detects which benchmark DCP is being used and applies the appropriate optimization:
| DCP File | Optimization Strategy |
|---|---|
fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp |
Pblock-based re-placement |
fpl26_contest_benchmarks/vexriscv_re-place_2025.1.dcp |
Critical path cell re-placement (same recipe as docs/optimization_example.md) |
# LogicNets: Pblock optimization flow
python3 dcp_optimizer.py fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp --test
# VexRiscv: Cell re-placement flow (mirrors docs/optimization_example.md)
python3 dcp_optimizer.py fpl26_contest_benchmarks/vexriscv_re-place_2025.1.dcp --test- Opens the DCP and reports initial Fmax
- Extracts critical path cells and analyzes their spread
- Unplaces the design and applies a pblock constraint
- Re-places and routes within the constrained region
- Reports Fmax improvement
Runs the same recipe as the optimization example:
- Opens the DCP in Vivado and reports baseline Fmax
- Extracts critical path pins and analyzes net detour ratios in RapidWright
- Moves poorly-placed cells to the centroid of their connections
- Routes the optimized design in Vivado and measures Fmax improvement
For other designs, use the full agent mode (LLM-guided) which can analyze the design and select the appropriate optimization strategy.
# Enable debug mode (verbose logging, preserve all files)
python3 dcp_optimizer.py fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp --test --debug
python3 dcp_optimizer.py fpl26_contest_benchmarks/vexriscv_re-place_2025.1.dcp --test --debugIn full agent mode, an LLM guides the optimization process:
# Using environment variable for API key (output name auto-generated)
export OPENROUTER_API_KEY="your-openrouter-api-key"
python3 dcp_optimizer.py input.dcp
# Or specify API key and custom output name
python3 dcp_optimizer.py input.dcp --output output.dcp --api-key "your-key"
# Use a different model (default: x-ai/grok-4.1-fast)
python3 dcp_optimizer.py input.dcp --model anthropic/claude-sonnet-4| Option | Description | Default |
|---|---|---|
input_dcp |
Input design checkpoint (.dcp) file | Required |
--output, -o |
Output optimized checkpoint (.dcp) file | <input>_optimized-<timestamp>.dcp |
--api-key |
OpenRouter API key | OPENROUTER_API_KEY env var |
--model |
LLM model to use | x-ai/grok-4.1-fast |
--debug |
Enable debug mode (verbose logging, preserve all files) | False |
--test |
Test mode: run without LLM. Pblock for LogicNets, cell re-placement for VexRiscv | False |
--max-nets |
Max high-fanout nets to optimize in test mode (high fanout flow only) | 5 |
After running dcp_optimizer.py, you should validate that the optimized design is functionally equivalent to the original. The validate_dcps.py script provides automated equivalence checking using a two-phase approach:
Phase 1: Structural Sanity Checks (via RapidWright)
- Verifies top-level module name matches
- Checks I/O ports (names, directions, widths) are identical
- Validates device compatibility
- Ensures cell count is reasonable (can increase but not decrease)
Phase 2: Functional Simulation (via Vivado + xsim)
- Exports both designs as Verilog simulation models
- Generates testbench with random stimulus (LFSR-based)
- Runs xsim simulation with configurable test vector count
- Compares outputs cycle-by-cycle for mismatches
# Basic validation with 200 test vectors (default)
python3 validate_dcps.py golden.dcp optimized.dcp
# More thorough validation with 10,000 vectors
python3 validate_dcps.py golden.dcp optimized.dcp --vectors 10000
# Enable debug logging
python3 validate_dcps.py golden.dcp optimized.dcp --debug# First, optimize a design
python3 dcp_optimizer.py fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp --output logicnets_jscl_optimized.dcp
# Then validate the optimized design
python3 validate_dcps.py fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp logicnets_jscl_optimized.dcp
# Output:
# ======================================================================
# DCP EQUIVALENCE VALIDATION
# ======================================================================
# Golden: logicnets_jscl.dcp
# Revised: logicnets_jscl_optimized.dcp
# Vectors: 200
# ======================================================================
#
# ======================================================================
# PHASE 1: STRUCTURAL SANITY CHECKS
# ======================================================================
#
# Comparing design structures...
#
# Structural Checks: 4/4 passed
# Result: PASS
#
# No issues found - designs are structurally compatible
#
# ----------------------------------------------------------------------
# Phase 1: PASSED ✓
# ----------------------------------------------------------------------
#
# ======================================================================
# PHASE 2: FUNCTIONAL SIMULATION
# ======================================================================
#
# Exporting simulation models...
# ✓ Golden model exported: golden_sim.v
# ✓ Revised model exported: revised_sim.v
#
# Parsing design information...
# Golden module: logicnets_jscl
# Revised module: logicnets_jscl
# Inputs: 24
# Outputs: 16
#
# Generating testbench (200 random vectors)...
# ✓ Testbench generated: testbench.v
#
# Running xsim simulation...
# (This may take a few minutes...)
# ✓ Compilation successful
# ✓ Elaboration successful
#
# Simulating 200 test vectors...
#
# ----------------------------------------------------------------------
# Simulation Results:
# Cycles: 200
# Mismatches: 0
# Log: /tmp/dcp_validation_xyz/simulation.log
#
# Phase 2: PASSED ✓
# ----------------------------------------------------------------------
#
# ======================================================================
# VALIDATION SUMMARY
# ======================================================================
# Golden DCP: logicnets_jscl.dcp
# Revised DCP: logicnets_jscl_optimized.dcp
# Runtime: 3.2 minutes
#
# Phase 1 (Structural): PASSED ✓
# Checks: 4/4
#
# Phase 2 (Simulation): PASSED ✓
# Cycles: 200
# Mismatches: 0
#
# Overall Result: PASSED ✓
# ======================================================================| Option | Description | Default |
|---|---|---|
golden_dcp |
Golden (reference) DCP file | Required |
revised_dcp |
Revised (optimized) DCP file to validate | Required |
--vectors, -n |
Number of random test vectors to simulate | 200 |
--debug |
Enable debug logging | False |
- Simulation time: Dominated by
xelab(must compile every cell in both designs) plus per-cyclexsimcost. For huge benchmarks likecorescore_500_mod(~6.7K user modules, ~100K primitives)xelabalone takes ~14 minutes, so run-to-run wall-clock is bounded by that even with very few vectors. - Vector count: 200 vectors is sufficient to catch functional regressions on most designs while keeping wall-clock reasonable on the largest benchmarks. For higher confidence on small/medium designs use
--vectors 10000(or more). xsim cost scales roughly linearly with vectors. - Working directory: Preserved after validation in
/tmp/dcp_validation_*with simulation logs and intermediate files. - No testbench required: The tool automatically generates stimulus based on design I/O structure.
- Clock/reset detection: Automatically identifies clock and reset signals by name pattern matching.
- Simulation-based validation is not exhaustive (depends on test vector coverage)
- For formal proof of equivalence, use commercial tools like Synopsys Formality or Cadence Conformal
- Designs with encrypted IP blocks are not supported
- Asynchronous designs may require custom testbenches
The Vivado MCP server enables AI assistants to interact with Xilinx Vivado through its Tcl interpreter interface.
┌─────────────────┐ stdin/stdout ┌─────────────────────┐
│ MCP Server │◄─────────────────►│ Vivado Process │
│ (Python) │ (pexpect) │ ( `-mode tcl` ) │
└─────────────────┘ └─────────────────────┘
The server:
- Starts Vivado automatically in Tcl mode when first needed
- Communicates via stdin/stdout using pexpect for direct process control
- Exposes Vivado commands as MCP tools
- Handles timeout recovery and graceful cleanup
| Tool | Description |
|---|---|
open_checkpoint |
Open a Vivado Design Checkpoint (.dcp) - starts Vivado automatically |
write_checkpoint |
Save current design to .dcp file |
report_timing_summary |
Get timing summary (WNS/TNS) |
get_critical_high_fanout_nets |
Find high-fanout nets on critical paths |
analyze_critical_path_spread |
Measure cell spread across fabric using Manhattan distance |
report_utilization_for_pblock |
Get resource utilization for pblock sizing (with 1.5x multiplier) |
create_and_apply_pblock |
Create area constraint and apply to design |
report_route_status |
Check routing completion status |
write_edif |
Export unencrypted EDIF netlist |
phys_opt_design |
Run physical optimization (post-place/route) |
route_design |
Route the design (with directive option) |
place_design |
Run placement (with directive option) |
run_tcl |
Execute arbitrary Tcl commands |
restart_vivado |
Restart Vivado if hung or stuck |
| Variable | Description | Default |
|---|---|---|
VIVADO_EXEC |
Path to vivado executable (used by Makefile, VivadoMCP, and Python scripts) |
vivado (auto-detect from PATH) |
JAVA_HOME |
Java installation directory (required for RapidWright) | Auto-detected from java on PATH, or from Vivado's bundled Java |
RAPIDWRIGHT_PATH |
Path to the RapidWright git submodule directory | Auto-set by Makefile to $(CURDIR)/RapidWright |
CLASSPATH |
Java classpath for RapidWright classes and dependencies | Auto-set by Makefile to $RAPIDWRIGHT_PATH/bin:$RAPIDWRIGHT_PATH/jars/* |
Setting VIVADO_EXEC: You can set this variable in multiple ways:
# Method 1: Export in your shell (persists for session)
export VIVADO_EXEC=/path/to/Vivado/2025.1/bin/vivado
python3 dcp_optimizer.py input.dcp --test
# Method 2: One-line with command
VIVADO_EXEC=/path/to/vivado python3 dcp_optimizer.py input.dcp --test
# Method 3: Through Makefile
make run_test DCP=input.dcp VIVADO_EXEC=/path/to/vivado
make run_optimizer DCP=input.dcp VIVADO_EXEC=/path/to/vivadoNote: The server automatically starts Vivado in Tcl mode when first needed. No manual setup required.
The RapidWright MCP server provides AI access to RapidWright, an open-source FPGA design tool framework from AMD/Xilinx.
┌─────────────────┐
│ MCP Client │
└────────┬────────┘
│ MCP Protocol (JSON-RPC over stdio)
┌────────▼────────┐
│ server.py │ ← Python MCP Server
└────────┬────────┘
│
┌────────▼────────────┐
│ rapidwright_tools.py│ ← Tool Wrappers
└────────┬────────────┘
│
┌────────▼────────┐
│ RapidWright │ ← pip package (JPype + Java libs)
└─────────────────┘
The server:
- Initializes RapidWright's JVM with configurable memory
- Uses Java classes from the local
RapidWright/git submodule (viaRAPIDWRIGHT_PATH/CLASSPATH) - Loads/saves Vivado design checkpoints
- Provides design analysis and manipulation
- Implements optimization algorithms (fanout splitting, LUT optimization)
| Tool | Description |
|---|---|
initialize_rapidwright |
Initialize RapidWright JVM (call first!) |
read_checkpoint |
Load a Vivado Design Checkpoint (.dcp) |
write_checkpoint |
Save design to .dcp file |
get_design_info |
Get design statistics (cells, nets, types) |
optimize_fanout |
Split high-fanout nets by replicating drivers |
optimize_lut_input_cone |
Combine chained LUTs to reduce logic depth |
analyze_fabric_for_pblock |
Find best contiguous fabric region for pblock (avoids delay-heavy columns) |
convert_fabric_region_to_pblock |
Convert fabric coordinates to Vivado pblock range strings |
get_supported_devices |
List supported FPGA devices |
get_device_info |
Get device specifications |
search_cells |
Search for cells by name/type |
get_tile_info |
Get FPGA tile information |
search_sites |
Search for sites by type |
The optimize_fanout tool splits high-fanout nets by replicating the source driver:
Before: Driver -> [1000 loads]
After: Driver_1 -> [250 loads]
Driver_2 -> [250 loads]
Driver_3 -> [250 loads]
Driver_4 -> [250 loads]
Recommended split factors:
- k=2: Fanout 500-1000 loads
- k=3-4: Fanout 1000-3000 loads
- k≥5: Fanout >3000 loads
The agent implements multiple optimization strategies to improve timing:
The optimize_fanout tool splits high-fanout nets by replicating the source driver:
Before: Driver -> [1000 loads]
After: Driver_1 -> [250 loads]
Driver_2 -> [250 loads]
Driver_3 -> [250 loads]
Driver_4 -> [250 loads]
When to use:
- Multiple critical paths share high-fanout signals (fanout > 100)
- Design is already placed and routed
- Routing delays dominate the critical path
Recommended split factors:
- k=2-3: Fanout 200-500 loads
- k=3-5: Fanout 500-1500 loads
- k=5-8: Fanout >1500 loads
Area constraints (pblocks) restrict placement to a specific contiguous region of the FPGA fabric. This reduces routing distances when cells are spread too far apart.
When to use:
- Cells on critical paths are spread >70 tiles apart (Manhattan distance)
- Multiple critical paths (5+) exhibit large cell spread
- Initial placement is poor with excessive routing delays
Workflow:
- Analyze spread:
analyze_critical_path_spreadmeasures Manhattan distance between cells on critical paths - Get utilization:
report_utilization_for_pblockprovides resource counts - Find region:
analyze_fabric_for_pblock(RapidWright) identifies best contiguous fabric region:- Avoids delay-heavy columns (URAM, IO)
- Has 1.5x required resources
- Maximizes contiguity
- Convert coordinates:
convert_fabric_region_to_pblockgenerates Vivado pblock range string - Apply pblock:
create_and_apply_pblockcreates and applies the constraint (IS_SOFT=0) - Re-implement: Run
place_designandroute_designwith the new constraint
Example:
# 1. Check if cells are spread out
result = vivado.analyze_critical_path_spread(num_paths=50, distance_threshold=70)
# => "STRONG RECOMMENDATION: Apply pblock-based re-placement"
# 2. Get resource utilization (1.5x multiplier included)
utilization = vivado.report_utilization_for_pblock()
# => LUTs: 45000, FFs: 90000, DSPs: 120, BRAMs: 60
# 3. Find best fabric region (RapidWright)
region = rapidwright.analyze_fabric_for_pblock(
target_lut_count=45000,
target_ff_count=90000,
target_dsp_count=120,
target_bram_count=60
)
# => Recommended region: cols 10-85, rows 20-150
# 4. Convert to pblock range
pblock_range = rapidwright.convert_fabric_region_to_pblock(
col_min=10, col_max=85, row_min=20, row_max=150,
use_clock_regions=True
)
# => "CLOCKREGION_X0Y0:CLOCKREGION_X1Y2"
# 5. Apply pblock and re-implement
vivado.create_and_apply_pblock(
pblock_name="pblock_tight",
ranges=pblock_range,
apply_to="current_design",
is_soft=False
)
vivado.place_design()
vivado.route_design()Important notes:
- Only use pblock if analyze_critical_path_spread strongly recommends it
- For 1-2 paths with spread, try phys_opt_design first
- Pblock must have IS_SOFT=0 (hard constraint) to be effective
- Must re-run place_design and route_design after applying pblock
The phys_opt_design tool performs timing-driven optimizations on the placed/routed design:
When to use:
- 1-2 isolated problematic paths
- After fanout optimization or pblock re-placement
- As a final polish step
Common directives:
RuntimeOptimized: Fast optimization (fanout, critical_cell, placement, BRAM enable)Explore: Multiple passes with replication for high fanout netsAggressiveExplore: More aggressive algorithms, may temporarily degrade WNS
Example:
vivado.phys_opt_design(directive="Explore")The agent automatically selects the best strategy based on design analysis:
- Initialize RapidWright MCP server (Vivado starts automatically when first used)
- Open the input design in Vivado - this starts Vivado in Tcl mode
- Analyze timing with
report_timing_summary - Analyze cell spread with
analyze_critical_path_spread - Decide strategy:
- If timing met (WNS ≥ 0): Save and exit
- If large cell spread (5+ paths >70 tiles): Use pblock strategy
- If high fanout nets on critical paths: Use fanout optimization
- If isolated problematic paths: Use phys_opt_design
- Apply optimization:
- Fanout: Load design in RapidWright → optimize_fanout → save → open in Vivado → route
- Pblock: Analyze fabric → calculate pblock → apply → place → route
- Phys_opt: Run phys_opt_design with appropriate directive
- Check timing - if improved, iterate; otherwise save final result
$ make run_test DCP=fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp
Running optimizer in TEST MODE on fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp...
FPGA Design Optimization - TEST MODE
=====================================
Input: /path/to/fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp
Output: /path/to/fpl26_contest_benchmarks/logicnets_jscl_2025.1_optimized-20260407_143022.dcp
Run dir: /path/to/dcp_optimizer_run-20260407_143022
...
$ python3 dcp_optimizer.py fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp --test
FPGA Design Optimization - TEST MODE
=====================================
Input: /path/to/fpl26_contest_benchmarks/logicnets_jscl_2025.1.dcp
Output: /path/to/fpl26_contest_benchmarks/logicnets_jscl_2025.1_optimized-<timestamp>.dcp
Run dir: /path/to/dcp_optimizer_run-<timestamp>
[TEST] Detected LogicNets design - using pblock optimization flow
[TEST] Starting RapidWright MCP server...
[TEST] Starting Vivado MCP server...
[TEST] Both MCP servers connected successfully
STEP 0: Initialize RapidWright
STEP 1: Open input DCP in Vivado
STEP 2: Report initial timing in Vivado
*** Initial Fmax (clock: clk_fpl26contest): 403.55 MHz (WNS: -0.978 ns) ***
STEP 3: Extract critical path cells
STEP 4: Analyze critical path spread in RapidWright
STEP 5: Apply pblock for LogicNets
STEP 6: Unplace the design in Vivado
STEP 7: Create and apply pblock to entire design
STEP 8: Place the design in Vivado
STEP 9: Route the design in Vivado
STEP 10: Report final timing
*** Final Fmax (clock: clk_fpl26contest): 521.10 MHz (WNS: -0.419 ns) ***
*** Fmax: 403.55 -> 521.10 MHz (+117.55 MHz, +29.1%) ***
======================================================================
TEST SUMMARY - LOGICNETS PBLOCK OPTIMIZATION
======================================================================
Total runtime: 664.86 seconds (11.08 minutes)
Fmax Results:
Target Fmax: 666.67 MHz (clock period: 1.500 ns)
Initial Fmax: 403.55 MHz (WNS: -0.978 ns)
Final Fmax: 521.10 MHz (WNS: -0.419 ns)
Fmax Improvement: +117.55 MHz (WNS: +0.559 ns)
Pblock applied: SLICE_X55Y60:SLICE_X111Y254
======================================================================
| Issue | Solution |
|---|---|
| "Could not find 'vivado' executable" | Set VIVADO_EXEC env var or use make setup VIVADO_EXEC=/path/to/vivado or source Vivado settings64.sh |
| "RapidWright not initialized" | Ensure Java 11+ is installed and RapidWright is built (make build-rapidwright) |
| RapidWright changes not taking effect | Rebuild after modifying source: make build-rapidwright |
| "Vivado command timed out" | Command may be still running; use restart_vivado to recover |
| Out of memory (RapidWright) | Increase jvm_max_memory (e.g., "16G") |
| Vivado hangs | Use restart_vivado tool to kill and restart Vivado |
Enable debug mode for verbose logging:
python3 dcp_optimizer.py input.dcp --debugThis will:
- Set logging level to DEBUG
- Show MCP server output in console (instead of redirecting to log files)
- Print detailed tool call information
Note: All intermediate files are always preserved in the run directory, regardless of debug mode.
The Makefile provides clean targets to remove generated files:
# Remove run directories and .Xil directories (preserves optimized DCPs)
make clean
# Deep clean: also remove benchmark DCPs and Python cache
make verycleanFiles/directories removed by make clean:
dcp_optimizer_run-*/directories (contain all logs, journals, intermediate DCPs).Xil/directories (Vivado-generated)VivadoMCP/.Xil/directory
Note: Optimized DCP files (e.g., design_optimized-<timestamp>.dcp) are preserved.
fpl26_optimization_contest/
├── Makefile # Build automation (setup, build-rapidwright, run, clean)
├── dcp_optimizer.py # Main optimization agent
├── requirements.txt # Python dependencies
├── README.md # This file
├── SYSTEM_PROMPT.TXT # The system prompt used in dcp_optimizer.py
├── RapidWright/ # Git submodule (github.com/Xilinx/RapidWright)
│ ├── src/ # Java source code (modifiable by contestants)
│ ├── bin/ # Compiled Java classes (after build)
│ ├── jars/ # Third-party Java dependencies
│ └── gradlew # Gradle wrapper for building
├── RapidWrightMCP/ # RapidWright MCP server
│ ├── server.py # MCP server
│ ├── rapidwright_tools.py # RapidWright tool wrappers
│ └── setup.sh # Setup script
└── VivadoMCP/ # Vivado MCP server
├── vivado_mcp_server.py # MCP server with pexpect control
├── requirements.txt # Python dependencies
└── test_vivado_mcp.py # Unit tests
Copyright (C) 2026, Advanced Micro Devices, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
See LICENSE-APACHE-2.0.txt for full license details.