Skip to content

Integration examples · End-to-end Agent scenarios

Three complete end-to-end examples showing how Agents invoke the iEDA toolchain—from timing repair and placement optimization to full-flow automation.

agent — end-to-end flow
# Agent drives the full RTL-to-GDS flow
>>> agent.execute(goal="close_timing")
[iSTA ] WNS=-0.15ns  TNS=-3.2ns     violations
[Agent ] proposing ECO...           3 candidates
[iTO   ] resize+buffer applied      WNS=-0.02ns
[iSTA ] verify pass                 clean
→ timing closed in 2 iterations
iMapsynthesisiFPfloorplaniPDNpoweriPLplacementiCTSclockiTOoptimizationiRTroutingiSTAtimingAiEDAdesign dataiPCLlayout modeliMapsynthesisiFPfloorplaniPDNpoweriPLplacementiCTSclockiTOoptimizationiRTroutingiSTAtimingAiEDAdesign dataiPCLlayout model

Example 1: Agent-driven timing repair

After detecting timing violations, the Agent calls iSTA for root-cause diagnosis, iTO for ECO proposals, and iSTA to verify fixes—a complete closed-loop optimization.

Scenario

Post-route WNS = -0.15ns on critical paths. iSTA diagnoses three violating paths: two oversized buffers (resize) and one long detour (local reroute).

Agent decision chain

Step 1: iSTA.diagnose(WNS, path) → root cause: buffer_oversized x2, route_detour x1
Step 2: iTO.propose(resize=2, reroute=1) → 3 candidates
Step 3: Evaluation.gate(candidates) → candidate_2 selected (best WNS+area trade-off)
Step 4: iSTA.verify(candidate_2) → WNS=-0.02ns, PASS

Python
MCP

Python implementation

from ieda import AgentClient
from ieda.evaluation import Gate

client = AgentClient()

# Step 1: Diagnose timing root causes
timing = client.call("iSTA.analyze", design_ref="post_route_snap")
if timing.wns < 0:
    # Step 2: Get diagnostic & generate ECO
    diagnosis = client.call("iSTA.diagnose", path=timing.critical_paths[0])
    eco = client.call("iTO.propose", diagnosis=diagnosis)

    # Step 3: Evaluate all candidates through gate
    for candidate in eco.candidates:
        result = client.call("iTO.apply", candidate=candidate)
        gate = Gate.judge(before="post_route_snap", after=result.design_ref)
        if gate.wns >= -0.05 and gate.drc_count == 0:
            best_candidate = candidate
            break

    # Step 4: Verify and commit
    verify = client.call("iSTA.verify", design_ref=best_candidate.design_ref)
    print(f"Timing closed: WNS={verify.wns}ns")
    client.call("iDB.commit", design_ref=best_candidate.design_ref)

Example 2: Agent-driven placement optimization

After placement, the Agent detects local congestion and timing violations, iterating iPL local optimization with iSTA incremental analysis in a feedback loop.

Scenario

After global iPL placement, iSTA finds a region with both congestion and setup violations. The Agent uses iPL local moves—fine-tuning cell positions to improve congestion and timing with minimal global HPWL impact.

Agent decision chain

Step 1: iPL.place(region) + iSTA.analyze(snap) → congestion hotspot + WNS violation
Step 2: iPL.propose_local_move(hotspot, max_displacement=50um) → 5 candidates
Step 3: iSTA.incremental(candidates, dirty_set) → candidate_3: WNS=-0.01ns, congestion improved 30%
Step 4: iDB.commit(candidate_3) → local optimization complete; global HPWL increased only 0.3%

Python

Python implementation

from ieda import AgentClient

client = AgentClient()

# Step 1: Global place + analyze
place = client.call("iPL.place", design_ref="snap_fp")
timing = client.call("iSTA.analyze", design_ref=place.design_ref)

# Step 2: Detect hotspot region
hotspot = (timing.wns < 0 and place.congestion_map["max_bin"] > 0.85)
if hotspot:
    # Step 3: Iterative local optimization with feedback loop
    best_hpwl = place.hpwl
    for iteration in range(5):
        move = client.call(
            "iPL.propose_local_move",
            design_ref=place.design_ref,
            region=hotspot.bbox,
            max_displacement_nm=50000,
        )
        incr = client.call(
            "iSTA.analyze",
            design_ref=move.design_ref,
            incremental=True,
            dirty_set=move.dirty_set,
        )
        if incr.wns >= 0 and move.hpwl <= best_hpwl * 1.05:
            best_hpwl = min(best_hpwl, move.hpwl)
            client.call("iDB.commit", design_ref=move.design_ref)
            print(f"Iteration {iteration}: WNS={incr.wns}, HPWL={move.hpwl}")
            break

Example 3: Agent full flow

From RTL, the Agent drives the full physical design flow—synthesis, floorplan, power, placement, clock tree, optimization, routing, timing, DRC—deciding at each stage under the Evaluation gate.

Full-flow toolchain

iMap (Synthesis) → iFP (Floorplan) → iPDN (Power) → iPL (Place) → iCTS (Clock) → iTO (Opt) → iRT (Route) → iSTA (Timing) → iDRC (Check)
Between stages the Agent uses the Evaluation gate to proceed or roll back.

Agent role in full flow

The Agent is not a passive script runner—it checks intermediate results, compares candidates, decides rollback or skip (e.g., skip repair if DRC is clean). Agent Planner orchestrates; Runtime manages branches and transactions.

Python

Python implementation (full-flow skeleton)

from ieda import AgentClient
from ieda.planner import FlowPlanner

client = AgentClient()
planner = FlowPlanner(client)

# Define the full flow with exit criteria at each stage
flow = [
    {"tool": "iMap",   "op": "synthesize",  "gate": {"area": "< 1.2e6"}},
    {"tool": "iFP",    "op": "floorplan",   "gate": {"util": "< 0.80"}},
    {"tool": "iPDN",   "op": "power_grid", "gate": {"ir_drop": "< 5%"}},
    {"tool": "iPL",    "op": "place",       "gate": {"density": "< 0.85"}},
    {"tool": "iCTS",   "op": "build_clock", "gate": {"skew": "< 50ps"}},
    {"tool": "iTO",    "op": "optimize",    "gate": {"wns": ">= -0.05"}},
    {"tool": "iRT",    "op": "route",       "gate": {"drc_count": "== 0"}},
    {"tool": "iSTA",   "op": "signoff",    "gate": {"wns": ">= 0"}},
    {"tool": "iDRC",   "op": "signoff",    "gate": {"drc_count": "== 0"}},
]

# Execute flow: Agent Planner handles retry, rollback, branch
result = planner.execute(
    flow=flow,
    design_ref="riscv_core",
    auto_recover=True,
    max_retries_per_stage=3,
)

if result.all_stages_passed:
    print("Full RTL-to-GDS flow completed successfully!")
    print(f"Final design_ref: {result.design_ref}")
else:
    print(f"Failed at stage: {result.failed_stage}")
    print(f"Gate failures: {result.gate_failures}")

Start building your Agent

Learn Agent patterns from these examples—start with Quickstart and run your first end-to-end flow in five minutes.