fix: Remove unused vars to fix Vercel strict TS build
Browse files- .gitignore +16 -0
- docs/AZURE_STUDENT_GUIDE.md +0 -88
- server/api.py +5 -3
- src/agentic/cli.py +428 -428
- src/agentic/orchestrator.py +70 -21
- src/agentic/tools/vlsi_tools.py +71 -18
- training/agentic_sft_data.jsonl +3 -0
- web/src/App.tsx +3 -2
- web/src/components/BuildMonitor.tsx +1 -1
- web/src/components/Chip3D.tsx +5 -5
- web/src/pages/Dashboard.tsx +5 -4
- web/src/pages/DesignStudio.tsx +2 -2
.gitignore
CHANGED
|
@@ -46,3 +46,19 @@ Thumbs.db
|
|
| 46 |
temp_*.svg
|
| 47 |
designs/*/src/sim
|
| 48 |
.venv-agentic/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
temp_*.svg
|
| 47 |
designs/*/src/sim
|
| 48 |
.venv-agentic/
|
| 49 |
+
|
| 50 |
+
# Node / Frontend
|
| 51 |
+
node_modules/
|
| 52 |
+
web/node_modules/
|
| 53 |
+
web/dist/
|
| 54 |
+
web/.vite/
|
| 55 |
+
dist/
|
| 56 |
+
|
| 57 |
+
# Temporary / test scripts
|
| 58 |
+
*.tmp
|
| 59 |
+
global_reqs.tmp
|
| 60 |
+
venv_reqs.tmp
|
| 61 |
+
nodesource_setup.sh
|
| 62 |
+
test_import.py
|
| 63 |
+
test_signoff.py
|
| 64 |
+
test_signoff2.py
|
docs/AZURE_STUDENT_GUIDE.md
DELETED
|
@@ -1,88 +0,0 @@
|
|
| 1 |
-
# ☁️ Azure Student Developer Pack Guide for AgentIC
|
| 2 |
-
|
| 3 |
-
Since your local PC is overheating, moving to Azure is the perfect solution. With the **Microsoft Azure Student Pack**, you get **$100 credit** and free access to specific services.
|
| 4 |
-
|
| 5 |
-
This guide will help you create a **Virtual Machine (VM)** to run OpenLane and AgentIC without burning your laptop.
|
| 6 |
-
|
| 7 |
-
## 1. Create the Virtual Machine (VM)
|
| 8 |
-
The "hectic" part is the OpenLane build process (compiling 30,000 transistors!).
|
| 9 |
-
|
| 10 |
-
1. Log in to the [Azure Portal](https://portal.azure.com).
|
| 11 |
-
2. Click **"Create a resource"** > **"Virtual Machine"**.
|
| 12 |
-
3. **Basics Tab**:
|
| 13 |
-
* **Subscription**: Azure for Students.
|
| 14 |
-
* **Resource Group**: Create new (e.g., `rg-agentic`).
|
| 15 |
-
* **Virtual Machine Name**: `vm-agentic`.
|
| 16 |
-
* **Region**: Pick one close to you (e.g., East US).
|
| 17 |
-
* **Image**: **Ubuntu Server 22.04 LTS - x64 Gen2**.
|
| 18 |
-
* **Size**: **Standard D4s v3** (4 vCPUs, 16 GiB memory).
|
| 19 |
-
* *Note:* This costs about ~$0.18/hour. Since you have $100 credits, you can run this for ~500 hours.
|
| 20 |
-
* *Important:* Remember to **STOP** the VM when you aren't using it to save credits!
|
| 21 |
-
4. **Administrator Account**:
|
| 22 |
-
* **Authentication type**: SSH public key.
|
| 23 |
-
* **Username**: `azureuser`.
|
| 24 |
-
* **Key source**: Generate new key pair.
|
| 25 |
-
5. **Review + create** > **Create**.
|
| 26 |
-
* Download the private key (`.pem` file) when prompted. Keep it safe!
|
| 27 |
-
|
| 28 |
-
## 2. Connect to the Cloud
|
| 29 |
-
1. Open your local terminal (Git Bash or WSL).
|
| 30 |
-
2. Move the key to a safe place and secure it:
|
| 31 |
-
```bash
|
| 32 |
-
mv ~/Downloads/vm-agentic_key.pem ~/.ssh/
|
| 33 |
-
chmod 400 ~/.ssh/vm-agentic_key.pem
|
| 34 |
-
```
|
| 35 |
-
3. Connect (replace `YOUR_VM_IP` with the Public IP from Azure Portal):
|
| 36 |
-
```bash
|
| 37 |
-
ssh -i ~/.ssh/vm-agentic_key.pem azureuser@YOUR_VM_IP
|
| 38 |
-
```
|
| 39 |
-
|
| 40 |
-
## 3. Install the Environment (One-Time Setup)
|
| 41 |
-
Copy and paste this block into your Azure SSH terminal to install everything:
|
| 42 |
-
|
| 43 |
-
```bash
|
| 44 |
-
# Update and Install Docker
|
| 45 |
-
sudo apt-get update
|
| 46 |
-
sudo apt-get install -y docker.io python3-pip python3-venv git make
|
| 47 |
-
sudo usermod -aG docker $USER
|
| 48 |
-
newgrp docker
|
| 49 |
-
|
| 50 |
-
# Setup OpenLane
|
| 51 |
-
git clone https://github.com/The-OpenROAD-Project/OpenLane.git ~/OpenLane
|
| 52 |
-
cd ~/OpenLane
|
| 53 |
-
# This download is heavy (~2GB), but it runs on Azure's fast internet!
|
| 54 |
-
make pull-openlane
|
| 55 |
-
|
| 56 |
-
# Get your AgentIC code
|
| 57 |
-
# (You can clone your repo, or we create a fresh one)
|
| 58 |
-
mkdir -p ~/AgentIC
|
| 59 |
-
```
|
| 60 |
-
|
| 61 |
-
## 4. Solving the "Thinking" Heat (The LLM)
|
| 62 |
-
Running Ollama (DeepSeek) locally is what heats up your GPU. On an Azure CPU VM, it will be slow.
|
| 63 |
-
**Recommendation:** Use the **DeepSeek API** instead. It costs pennies and offloads the "brain" work to DeepSeek's servers.
|
| 64 |
-
|
| 65 |
-
1. Get an API Key from [platform.deepseek.com](https://platform.deepseek.com).
|
| 66 |
-
2. On the Azure VM, export it:
|
| 67 |
-
```bash
|
| 68 |
-
export OPENAI_API_KEY="sk-..." # Your DeepSeek Key
|
| 69 |
-
export OPENAI_API_BASE="https://api.deepseek.com"
|
| 70 |
-
export LLM_MODEL="deepseek-chat"
|
| 71 |
-
```
|
| 72 |
-
|
| 73 |
-
## 5. Running the Flow
|
| 74 |
-
Now, your laptop stays cool while Azure does the work.
|
| 75 |
-
|
| 76 |
-
```bash
|
| 77 |
-
# On Azure VM
|
| 78 |
-
cd ~/AgentIC
|
| 79 |
-
python3 main.py build --name cloud_chip --desc "An 8-bit counter"
|
| 80 |
-
```
|
| 81 |
-
|
| 82 |
-
## 6. Retrieving the Result
|
| 83 |
-
When finished, download the GDS file to your laptop to view it:
|
| 84 |
-
|
| 85 |
-
```bash
|
| 86 |
-
# On Local Laptop
|
| 87 |
-
scp -i ~/.ssh/vm-agentic_key.pem azureuser@YOUR_VM_IP:~/AgentIC/cloud_chip.gds ./
|
| 88 |
-
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
server/api.py
CHANGED
|
@@ -81,6 +81,8 @@ def _get_llm():
|
|
| 81 |
temperature=1.0,
|
| 82 |
top_p=1.0,
|
| 83 |
max_completion_tokens=16384,
|
|
|
|
|
|
|
| 84 |
extra_body=extra,
|
| 85 |
)
|
| 86 |
return llm, name
|
|
@@ -476,8 +478,8 @@ def get_metrics(design_name: str):
|
|
| 476 |
@app.get("/signoff/{design_name}")
|
| 477 |
def get_signoff_report(design_name: str):
|
| 478 |
try:
|
| 479 |
-
from agentic.tools.vlsi_tools import
|
| 480 |
-
|
| 481 |
-
return {"success":
|
| 482 |
except Exception as e:
|
| 483 |
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
| 81 |
temperature=1.0,
|
| 82 |
top_p=1.0,
|
| 83 |
max_completion_tokens=16384,
|
| 84 |
+
max_tokens=16384,
|
| 85 |
+
timeout=300,
|
| 86 |
extra_body=extra,
|
| 87 |
)
|
| 88 |
return llm, name
|
|
|
|
| 478 |
@app.get("/signoff/{design_name}")
|
| 479 |
def get_signoff_report(design_name: str):
|
| 480 |
try:
|
| 481 |
+
from agentic.tools.vlsi_tools import check_physical_metrics
|
| 482 |
+
metrics, report = check_physical_metrics(design_name)
|
| 483 |
+
return {"success": metrics is not None, "report": report}
|
| 484 |
except Exception as e:
|
| 485 |
raise HTTPException(status_code=500, detail=str(e))
|
src/agentic/cli.py
CHANGED
|
@@ -1,23 +1,23 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""
|
| 3 |
-
AgentIC - Natural Language to GDSII Pipeline
|
| 4 |
-
=============================================
|
| 5 |
-
Uses CrewAI + LLM (DeepSeek/Llama/Groq) to generate chips from natural language.
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
Usage:
|
| 9 |
-
python main.py build --name counter --desc "8-bit counter with enable and reset"
|
| 10 |
-
"""
|
| 11 |
-
|
| 12 |
-
import os
|
| 13 |
-
import re
|
| 14 |
-
import sys
|
| 15 |
-
import typer
|
| 16 |
-
from rich.console import Console
|
| 17 |
-
from rich.panel import Panel
|
| 18 |
-
from rich.progress import Progress, SpinnerColumn, TextColumn
|
| 19 |
-
from crewai import Agent, Task, Crew, LLM
|
| 20 |
-
|
| 21 |
# Local imports
|
| 22 |
from .config import (
|
| 23 |
OPENLANE_ROOT,
|
|
@@ -33,83 +33,85 @@ from .config import (
|
|
| 33 |
COVERAGE_FALLBACK_POLICY_DEFAULT,
|
| 34 |
COVERAGE_PROFILE_DEFAULT,
|
| 35 |
)
|
| 36 |
-
from .agents.designer import get_designer_agent
|
| 37 |
-
from .agents.testbench_designer import get_testbench_agent
|
| 38 |
-
from .agents.verifier import get_verification_agent, get_error_analyst_agent
|
| 39 |
-
from .tools.vlsi_tools import (
|
| 40 |
-
write_verilog,
|
| 41 |
-
write_config,
|
| 42 |
-
run_syntax_check,
|
| 43 |
-
syntax_check_tool,
|
| 44 |
-
read_file_content,
|
| 45 |
-
read_file_tool,
|
| 46 |
-
run_simulation,
|
| 47 |
-
run_openlane,
|
| 48 |
-
run_verification,
|
| 49 |
-
SecurityCheck,
|
| 50 |
-
write_sby_config,
|
| 51 |
-
run_formal_verification,
|
| 52 |
-
check_physical_metrics,
|
| 53 |
run_lint_check,
|
| 54 |
run_gls_simulation,
|
| 55 |
signoff_check_tool,
|
| 56 |
startup_self_check,
|
| 57 |
)
|
| 58 |
-
|
| 59 |
-
# --- INITIALIZE ---
|
| 60 |
-
app = typer.Typer()
|
| 61 |
-
console = Console()
|
| 62 |
-
|
| 63 |
-
# Setup Brain
|
| 64 |
def get_llm():
|
| 65 |
-
"""Returns the LLM instance. Strict 3-Model Policy:
|
| 66 |
-
1. NVIDIA Nemotron Cloud (Primary)
|
| 67 |
-
2. NVIDIA Qwen Cloud (High Perf)
|
| 68 |
-
3. VeriReason Local (Fallback)
|
| 69 |
-
"""
|
| 70 |
-
|
| 71 |
configs = [
|
| 72 |
("NVIDIA Nemotron Cloud", NEMOTRON_CONFIG),
|
| 73 |
("Backup GLM5 Cloud", GLM5_CONFIG),
|
| 74 |
("VeriReason Local", LOCAL_CONFIG),
|
| 75 |
]
|
| 76 |
-
|
| 77 |
-
for name, cfg in configs:
|
| 78 |
-
key = cfg.get("api_key", "")
|
| 79 |
-
# For Cloud, skip if no key.
|
| 80 |
-
if "Cloud" in name and (not key or key.strip() == "" or key == "mock-key"):
|
| 81 |
-
console.print(f"[dim]⏭ {name}: No valid API key set, skipping.[/dim]")
|
| 82 |
-
continue
|
| 83 |
-
|
| 84 |
-
try:
|
| 85 |
-
console.print(f"[dim]Testing {name}...[/dim]")
|
| 86 |
-
# Add extra parameters for reasoning models
|
| 87 |
-
extra_t = {}
|
| 88 |
-
if "nemotron" in cfg["model"].lower():
|
| 89 |
-
extra_t = {
|
| 90 |
-
"reasoning_budget": 16384,
|
| 91 |
-
"chat_template_kwargs": {"enable_thinking": True}
|
| 92 |
-
}
|
| 93 |
-
elif "glm5" in cfg["model"].lower():
|
| 94 |
-
extra_t = {
|
| 95 |
-
"chat_template_kwargs": {"enable_thinking": True, "clear_thinking": False}
|
| 96 |
-
}
|
| 97 |
-
|
| 98 |
-
llm = LLM(
|
| 99 |
-
model=cfg["model"],
|
| 100 |
-
base_url=cfg["base_url"],
|
| 101 |
-
api_key=key if key and key != "NA" else "mock-key", # Local LLMs might use mock-key
|
| 102 |
-
temperature=1.0,
|
| 103 |
-
top_p=1.0,
|
| 104 |
-
max_completion_tokens=16384,
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
|
|
|
|
|
|
| 113 |
console.print(f"[bold red]CRITICAL: No valid LLM backend found.[/bold red]")
|
| 114 |
console.print(f"Please set [bold]NVIDIA_API_KEY[/bold] for Cloud or configure [bold]LLM_BASE_URL[/bold] for Local.")
|
| 115 |
raise typer.Exit(1)
|
|
@@ -126,321 +128,319 @@ def run_startup_diagnostics(strict: bool = True):
|
|
| 126 |
console.print(f" [red]✗ {check.get('tool')}[/red] -> {check.get('resolved')}")
|
| 127 |
if strict:
|
| 128 |
raise typer.Exit(1)
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
@app.command()
|
| 132 |
-
def simulate(
|
| 133 |
-
name: str = typer.Option(..., "--name", "-n", help="Design name (e.g., counter)"),
|
| 134 |
-
max_retries: int = typer.Option(5, "--max-retries", "-r", min=0, help="Max auto-fix retries for failures"),
|
| 135 |
-
show_thinking: bool = typer.Option(True, "--show-thinking", help="Print DeepSeek <think> reasoning")
|
| 136 |
-
):
|
| 137 |
-
"""Run simulation on an existing design with AUTO-FIX loop."""
|
| 138 |
-
console.print(Panel(
|
| 139 |
-
f"[bold cyan]AgentIC: Manual Simulation + Auto-Fix Mode[/bold cyan]\n"
|
| 140 |
-
f"Design: [yellow]{name}[/yellow]",
|
| 141 |
-
title="🚀 Starting Simulation"
|
| 142 |
-
))
|
| 143 |
-
|
| 144 |
-
llm = get_llm()
|
| 145 |
-
|
| 146 |
-
def log_thinking(raw_text: str, step: str):
|
| 147 |
-
"""Emit DeepSeek <think> content."""
|
| 148 |
-
if not show_thinking: return
|
| 149 |
-
# Simple logging for sim tool
|
| 150 |
-
pass
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
sim_tries
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
```
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
```
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
```
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
```
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
-
|
| 281 |
-
- Keep
|
| 282 |
-
-
|
| 283 |
-
-
|
| 284 |
-
-
|
| 285 |
-
- If the
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
```
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
```
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
line_count =
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
set ::env(
|
| 352 |
-
set ::env(
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
set ::env(
|
| 358 |
-
set ::env(
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
console.print(" [dim]
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
console.print(
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
console.print(
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
# --- THE BUILD COMMAND ---
|
| 438 |
-
@app.command()
|
| 439 |
def build(
|
| 440 |
name: str = typer.Option(..., "--name", "-n", help="Design name (e.g., counter)"),
|
| 441 |
desc: str = typer.Option(..., "--desc", "-d", help="Natural language description"),
|
| 442 |
max_retries: int = typer.Option(5, "--max-retries", "-r", min=0, help="Max auto-fix retries for RTL/TB/sim failures"),
|
| 443 |
-
skip_openlane: bool = typer.Option(False, "--skip-openlane", help="Stop after simulation (no RTL→GDSII hardening)"),
|
| 444 |
show_thinking: bool = typer.Option(False, "--show-thinking", help="Print DeepSeek <think> reasoning for each generation/fix step"),
|
| 445 |
full_signoff: bool = typer.Option(False, "--full-signoff", help="Run full industry signoff (formal + coverage + regression + DRC/LVS)"),
|
| 446 |
min_coverage: float = typer.Option(80.0, "--min-coverage", help="Minimum line coverage percentage to pass verification"),
|
|
@@ -456,18 +456,18 @@ def build(
|
|
| 456 |
coverage_fallback_policy: str = typer.Option(COVERAGE_FALLBACK_POLICY_DEFAULT, "--coverage-fallback-policy", help="Coverage fallback policy: fail_closed, fallback_oss, skip"),
|
| 457 |
coverage_profile: str = typer.Option(COVERAGE_PROFILE_DEFAULT, "--coverage-profile", help="Coverage profile: balanced, aggressive, relaxed"),
|
| 458 |
):
|
| 459 |
-
"""Build a chip from natural language description (Autonomous Orchestrator 2.0)."""
|
| 460 |
-
|
| 461 |
-
from .orchestrator import BuildOrchestrator
|
| 462 |
-
|
| 463 |
-
console.print(Panel(
|
| 464 |
-
f"[bold cyan]AgentIC: Natural Language → GDSII[/bold cyan]\n"
|
| 465 |
-
f"Design: [yellow]{name}[/yellow]\n"
|
| 466 |
-
f"Description: {desc}\n"
|
| 467 |
-
f"{'[bold green]Full Industry Signoff Enabled[/bold green]' if full_signoff else ''}",
|
| 468 |
-
title="🚀 Starting Autonomous Orchestrator"
|
| 469 |
-
))
|
| 470 |
-
|
| 471 |
tb_gate_mode = tb_gate_mode.lower().strip()
|
| 472 |
if tb_gate_mode not in {"strict", "relaxed"}:
|
| 473 |
raise typer.BadParameter("--tb-gate-mode must be one of: strict, relaxed")
|
|
@@ -490,12 +490,12 @@ def build(
|
|
| 490 |
|
| 491 |
run_startup_diagnostics(strict=strict_gates)
|
| 492 |
llm = get_llm()
|
| 493 |
-
|
| 494 |
-
orchestrator = BuildOrchestrator(
|
| 495 |
-
name=name,
|
| 496 |
-
desc=desc,
|
| 497 |
-
llm=llm,
|
| 498 |
-
max_retries=max_retries,
|
| 499 |
verbose=show_thinking,
|
| 500 |
skip_openlane=skip_openlane,
|
| 501 |
full_signoff=full_signoff,
|
|
@@ -512,17 +512,17 @@ def build(
|
|
| 512 |
coverage_fallback_policy=coverage_fallback_policy,
|
| 513 |
coverage_profile=coverage_profile,
|
| 514 |
)
|
| 515 |
-
|
| 516 |
-
orchestrator.run()
|
| 517 |
-
|
| 518 |
-
@app.command()
|
| 519 |
-
def verify(name: str = typer.Argument(..., help="Design name to verify")):
|
| 520 |
-
"""Run verification on an existing design."""
|
| 521 |
-
console.print(f"[yellow]Running verification for {name}...[/yellow]")
|
| 522 |
-
output = run_verification(name)
|
| 523 |
-
console.print(output)
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
if __name__ == "__main__":
|
| 528 |
app()
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
AgentIC - Natural Language to GDSII Pipeline
|
| 4 |
+
=============================================
|
| 5 |
+
Uses CrewAI + LLM (DeepSeek/Llama/Groq) to generate chips from natural language.
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
Usage:
|
| 9 |
+
python main.py build --name counter --desc "8-bit counter with enable and reset"
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import os
|
| 13 |
+
import re
|
| 14 |
+
import sys
|
| 15 |
+
import typer
|
| 16 |
+
from rich.console import Console
|
| 17 |
+
from rich.panel import Panel
|
| 18 |
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
| 19 |
+
from crewai import Agent, Task, Crew, LLM
|
| 20 |
+
|
| 21 |
# Local imports
|
| 22 |
from .config import (
|
| 23 |
OPENLANE_ROOT,
|
|
|
|
| 33 |
COVERAGE_FALLBACK_POLICY_DEFAULT,
|
| 34 |
COVERAGE_PROFILE_DEFAULT,
|
| 35 |
)
|
| 36 |
+
from .agents.designer import get_designer_agent
|
| 37 |
+
from .agents.testbench_designer import get_testbench_agent
|
| 38 |
+
from .agents.verifier import get_verification_agent, get_error_analyst_agent
|
| 39 |
+
from .tools.vlsi_tools import (
|
| 40 |
+
write_verilog,
|
| 41 |
+
write_config,
|
| 42 |
+
run_syntax_check,
|
| 43 |
+
syntax_check_tool,
|
| 44 |
+
read_file_content,
|
| 45 |
+
read_file_tool,
|
| 46 |
+
run_simulation,
|
| 47 |
+
run_openlane,
|
| 48 |
+
run_verification,
|
| 49 |
+
SecurityCheck,
|
| 50 |
+
write_sby_config,
|
| 51 |
+
run_formal_verification,
|
| 52 |
+
check_physical_metrics,
|
| 53 |
run_lint_check,
|
| 54 |
run_gls_simulation,
|
| 55 |
signoff_check_tool,
|
| 56 |
startup_self_check,
|
| 57 |
)
|
| 58 |
+
|
| 59 |
+
# --- INITIALIZE ---
|
| 60 |
+
app = typer.Typer()
|
| 61 |
+
console = Console()
|
| 62 |
+
|
| 63 |
+
# Setup Brain
|
| 64 |
def get_llm():
|
| 65 |
+
"""Returns the LLM instance. Strict 3-Model Policy:
|
| 66 |
+
1. NVIDIA Nemotron Cloud (Primary)
|
| 67 |
+
2. NVIDIA Qwen Cloud (High Perf)
|
| 68 |
+
3. VeriReason Local (Fallback)
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
configs = [
|
| 72 |
("NVIDIA Nemotron Cloud", NEMOTRON_CONFIG),
|
| 73 |
("Backup GLM5 Cloud", GLM5_CONFIG),
|
| 74 |
("VeriReason Local", LOCAL_CONFIG),
|
| 75 |
]
|
| 76 |
+
|
| 77 |
+
for name, cfg in configs:
|
| 78 |
+
key = cfg.get("api_key", "")
|
| 79 |
+
# For Cloud, skip if no key.
|
| 80 |
+
if "Cloud" in name and (not key or key.strip() == "" or key == "mock-key"):
|
| 81 |
+
console.print(f"[dim]⏭ {name}: No valid API key set, skipping.[/dim]")
|
| 82 |
+
continue
|
| 83 |
+
|
| 84 |
+
try:
|
| 85 |
+
console.print(f"[dim]Testing {name}...[/dim]")
|
| 86 |
+
# Add extra parameters for reasoning models
|
| 87 |
+
extra_t = {}
|
| 88 |
+
if "nemotron" in cfg["model"].lower():
|
| 89 |
+
extra_t = {
|
| 90 |
+
"reasoning_budget": 16384,
|
| 91 |
+
"chat_template_kwargs": {"enable_thinking": True}
|
| 92 |
+
}
|
| 93 |
+
elif "glm5" in cfg["model"].lower():
|
| 94 |
+
extra_t = {
|
| 95 |
+
"chat_template_kwargs": {"enable_thinking": True, "clear_thinking": False}
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
llm = LLM(
|
| 99 |
+
model=cfg["model"],
|
| 100 |
+
base_url=cfg["base_url"],
|
| 101 |
+
api_key=key if key and key != "NA" else "mock-key", # Local LLMs might use mock-key
|
| 102 |
+
temperature=1.0,
|
| 103 |
+
top_p=1.0,
|
| 104 |
+
max_completion_tokens=16384,
|
| 105 |
+
max_tokens=16384,
|
| 106 |
+
timeout=300,
|
| 107 |
+
extra_body=extra_t
|
| 108 |
+
)
|
| 109 |
+
console.print(f"[green]✓ Using {name} ({cfg['model']})[/green]")
|
| 110 |
+
return llm
|
| 111 |
+
except Exception as e:
|
| 112 |
+
console.print(f"[yellow]⚠ {name} init failed: {e}[/yellow]")
|
| 113 |
+
|
| 114 |
+
# Critical Failure if both fail
|
| 115 |
console.print(f"[bold red]CRITICAL: No valid LLM backend found.[/bold red]")
|
| 116 |
console.print(f"Please set [bold]NVIDIA_API_KEY[/bold] for Cloud or configure [bold]LLM_BASE_URL[/bold] for Local.")
|
| 117 |
raise typer.Exit(1)
|
|
|
|
| 128 |
console.print(f" [red]✗ {check.get('tool')}[/red] -> {check.get('resolved')}")
|
| 129 |
if strict:
|
| 130 |
raise typer.Exit(1)
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
@app.command()
|
| 134 |
+
def simulate(
|
| 135 |
+
name: str = typer.Option(..., "--name", "-n", help="Design name (e.g., counter)"),
|
| 136 |
+
max_retries: int = typer.Option(5, "--max-retries", "-r", min=0, help="Max auto-fix retries for failures"),
|
| 137 |
+
show_thinking: bool = typer.Option(True, "--show-thinking", help="Print DeepSeek <think> reasoning")
|
| 138 |
+
):
|
| 139 |
+
"""Run simulation on an existing design with AUTO-FIX loop."""
|
| 140 |
+
console.print(Panel(
|
| 141 |
+
f"[bold cyan]AgentIC: Manual Simulation + Auto-Fix Mode[/bold cyan]\n"
|
| 142 |
+
f"Design: [yellow]{name}[/yellow]",
|
| 143 |
+
title="🚀 Starting Simulation"
|
| 144 |
+
))
|
| 145 |
+
|
| 146 |
+
llm = get_llm()
|
| 147 |
+
|
| 148 |
+
def log_thinking(raw_text: str, step: str):
|
| 149 |
+
"""Emit DeepSeek <think> content."""
|
| 150 |
+
if not show_thinking: return
|
| 151 |
+
# Simple logging for sim tool
|
| 152 |
+
pass
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
rtl_path = f"{OPENLANE_ROOT}/designs/{name}/src/{name}.v"
|
| 156 |
+
tb_path = f"{OPENLANE_ROOT}/designs/{name}/src/{name}_tb.v"
|
| 157 |
+
|
| 158 |
+
def _fix_with_llm(agent_role: str, goal: str, prompt: str) -> str:
|
| 159 |
+
# Give the agent TOOLS to self-correct
|
| 160 |
+
fix_agent = Agent(
|
| 161 |
+
role=agent_role,
|
| 162 |
+
goal=goal,
|
| 163 |
+
backstory='Expert in SystemVerilog and verification.',
|
| 164 |
+
llm=llm,
|
| 165 |
+
verbose=show_thinking,
|
| 166 |
+
tools=[syntax_check_tool, read_file_tool]
|
| 167 |
+
)
|
| 168 |
+
fix_task = Task(
|
| 169 |
+
description=prompt,
|
| 170 |
+
expected_output='Corrected SystemVerilog code in a ```verilog fence',
|
| 171 |
+
agent=fix_agent
|
| 172 |
+
)
|
| 173 |
+
with console.status(f"[cyan]AI is fixing ({agent_role})...[/cyan]"):
|
| 174 |
+
result = str(Crew(agents=[fix_agent], tasks=[fix_task]).kickoff())
|
| 175 |
+
return result
|
| 176 |
+
|
| 177 |
+
sim_success, sim_output = run_simulation(name)
|
| 178 |
+
sim_tries = 0
|
| 179 |
+
|
| 180 |
+
while not sim_success and sim_tries < max_retries:
|
| 181 |
+
sim_tries += 1
|
| 182 |
+
console.print(f"[bold red]✗ SIMULATION FAILED (attempt {sim_tries}/{max_retries})[/bold red]")
|
| 183 |
+
sim_output_text = sim_output or ""
|
| 184 |
+
|
| 185 |
+
# 1) If compilation failed, fix TB first.
|
| 186 |
+
if "Compilation failed:" in sim_output_text or "syntax error" in sim_output_text:
|
| 187 |
+
fix_tb_prompt = f'''Fix this SystemVerilog testbench so it compiles and avoids directionality errors.
|
| 188 |
+
|
| 189 |
+
CRITICAL FIXING RULES:
|
| 190 |
+
1. **Unresolved Wires**: If you see "Unable to assign to unresolved wires", it means you are driving a DUT OUTPUT. Stop driving it!
|
| 191 |
+
2. **Signal Directions**:
|
| 192 |
+
- Check the DUT definition.
|
| 193 |
+
- If a port is `output` in DUT, it is a `wire` in TB (Read-Only).
|
| 194 |
+
- If a port is `input` in DUT, it is a `reg/logic` in TB (Write-Only).
|
| 195 |
+
3. **Format**: Return ONLY corrected testbench code inside ```verilog fences.
|
| 196 |
+
|
| 197 |
+
Simulation output / errors:
|
| 198 |
+
{sim_output_text}
|
| 199 |
+
|
| 200 |
+
Current RTL (do not modify unless absolutely necessary):
|
| 201 |
+
```verilog
|
| 202 |
+
{read_file_content(rtl_path)}
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
Current testbench:
|
| 206 |
+
```verilog
|
| 207 |
+
{read_file_content(tb_path)}
|
| 208 |
+
```
|
| 209 |
+
'''
|
| 210 |
+
fixed_tb = _fix_with_llm('Verification Engineer', f'Fix testbench for {name}', fix_tb_prompt)
|
| 211 |
+
result_path = write_verilog(name, fixed_tb, is_testbench=True)
|
| 212 |
+
if isinstance(result_path, str) and result_path.startswith("Error:"):
|
| 213 |
+
sim_output = f"Failed to write fixed TB: {result_path}"
|
| 214 |
+
continue
|
| 215 |
+
tb_path = result_path
|
| 216 |
+
sim_success, sim_output = run_simulation(name)
|
| 217 |
+
continue
|
| 218 |
+
|
| 219 |
+
# 2) Logic or Runtime Errors
|
| 220 |
+
if "TEST FAILED" in sim_output_text or "TEST PASSED" not in sim_output_text:
|
| 221 |
+
|
| 222 |
+
# AI-Based Error Classification
|
| 223 |
+
analyst = get_error_analyst_agent(llm, verbose=False)
|
| 224 |
+
analysis_task = Task(
|
| 225 |
+
description=f'''Analyze this Verification Failure.
|
| 226 |
+
Error Log:
|
| 227 |
+
{sim_output_text}
|
| 228 |
+
Is this a:
|
| 229 |
+
A) TESTBENCH_ERROR (Syntax, $monitor usage, race condition, compilation fail)
|
| 230 |
+
B) RTL_LOGIC_ERROR (Mismatch, Wrong State, Functional Failure)
|
| 231 |
+
Reply with ONLY "A" or "B".''',
|
| 232 |
+
expected_output='Single letter A or B',
|
| 233 |
+
agent=analyst
|
| 234 |
+
)
|
| 235 |
+
analysis = str(Crew(agents=[analyst], tasks=[analysis_task]).kickoff()).strip()
|
| 236 |
+
|
| 237 |
+
is_tb_issue = "A" in analysis
|
| 238 |
+
|
| 239 |
+
if is_tb_issue:
|
| 240 |
+
console.print("[yellow] -> [Analyst] Root Cause: Testbench Error. Fixing TB...[/yellow]")
|
| 241 |
+
fix_tb_logic_prompt = f'''Fix the Testbench logic/syntax. The simulation failed or generated runtime errors.
|
| 242 |
+
|
| 243 |
+
CRITICAL FIXING RULES:
|
| 244 |
+
1. **Timing is USUALLY THE PROBLEM**: If "TEST FAILED" appears, the testbench is checking outputs TOO EARLY.
|
| 245 |
+
- Count the FSM states in the RTL. Wait at least (num_states + 10) clock cycles.
|
| 246 |
+
- Use `repeat(25) @(posedge clk);` minimum before checking ANY output.
|
| 247 |
+
- If there's a `done` or `valid` signal, use `while(!done) @(posedge clk);`
|
| 248 |
+
2. **Race Conditions**: Add `#1` delays after clock edges before sampling.
|
| 249 |
+
3. **Reset**: Ensure reset is held for at least 4 clock cycles.
|
| 250 |
+
4. **Between Tests**: Wait for FSM to return to IDLE with `repeat(10) @(posedge clk);`
|
| 251 |
+
5. **Format**: Return ONLY corrected testbench code inside ```verilog fences.
|
| 252 |
+
|
| 253 |
+
Simulation Error/Output:
|
| 254 |
+
{sim_output_text}
|
| 255 |
+
|
| 256 |
+
Current RTL (Reference - count the FSM states):
|
| 257 |
+
```verilog
|
| 258 |
+
{read_file_content(rtl_path)}
|
| 259 |
+
```
|
| 260 |
+
|
| 261 |
+
Current Testbench (To Fix - increase wait cycles):
|
| 262 |
+
```verilog
|
| 263 |
+
{read_file_content(tb_path)}
|
| 264 |
+
```
|
| 265 |
+
'''
|
| 266 |
+
fixed_tb = _fix_with_llm('Verification Engineer', f'Fix testbench logic for {name}', fix_tb_logic_prompt)
|
| 267 |
+
result_path = write_verilog(name, fixed_tb, is_testbench=True)
|
| 268 |
+
if isinstance(result_path, str) and result_path.startswith("Error:"):
|
| 269 |
+
sim_output = f"Failed to write fixed TB: {result_path}"
|
| 270 |
+
continue
|
| 271 |
+
tb_path = result_path
|
| 272 |
+
sim_success, sim_output = run_simulation(name)
|
| 273 |
+
continue
|
| 274 |
+
|
| 275 |
+
else:
|
| 276 |
+
console.print("[yellow] -> Detecting Design Logic mismatch. Fixing RTL...[/yellow]")
|
| 277 |
+
fix_rtl_prompt = f'''The simulation did not pass. Fix the RTL (module "{name}") so that the testbench passes.
|
| 278 |
+
|
| 279 |
+
CRITICAL REQUIREMENTS:
|
| 280 |
+
- **NO CONVERSATION**: Return ONLY the code inside ```verilog fences. Do NOT write "Thought:", "Here is the code", or any explanation.
|
| 281 |
+
- Keep module name exactly "{name}"
|
| 282 |
+
- SystemVerilog only
|
| 283 |
+
- Keep ports: clk, rst_n (active-low) present
|
| 284 |
+
- **MAINTAIN DESIGN INTENT**: Do NOT simplify the logic to pass the test case.
|
| 285 |
+
- If the design is an NPU or Processor, do NOT replace complex logic with simple static assignments.
|
| 286 |
+
- You must fix the BUGS in the implementation, not delete the implementation.
|
| 287 |
+
- If the testbench expects a result after N cycles, ensure your pipeline matches that latency.
|
| 288 |
+
- Return ONLY corrected RTL code inside ```verilog fences
|
| 289 |
+
|
| 290 |
+
Simulation output:
|
| 291 |
+
{sim_output_text}
|
| 292 |
+
|
| 293 |
+
Current testbench (do not change in this step):
|
| 294 |
+
```verilog
|
| 295 |
+
{read_file_content(tb_path)}
|
| 296 |
+
```
|
| 297 |
+
|
| 298 |
+
Current RTL:
|
| 299 |
+
```verilog
|
| 300 |
+
{read_file_content(rtl_path)}
|
| 301 |
+
```
|
| 302 |
+
'''
|
| 303 |
+
fixed_rtl = _fix_with_llm('VLSI Design Engineer', f'Fix RTL behavior for {name}', fix_rtl_prompt)
|
| 304 |
+
rtl_path = write_verilog(name, fixed_rtl)
|
| 305 |
+
|
| 306 |
+
# Check syntax of fix
|
| 307 |
+
success, errors = run_syntax_check(rtl_path)
|
| 308 |
+
if not success:
|
| 309 |
+
sim_output = f"RTL fix introduced syntax error:\n{errors}"
|
| 310 |
+
continue
|
| 311 |
+
|
| 312 |
+
sim_success, sim_output = run_simulation(name)
|
| 313 |
+
continue
|
| 314 |
+
|
| 315 |
+
if not sim_success:
|
| 316 |
+
console.print(f"[bold red]✗ SIMULATION FAILED:[/bold red]\n{sim_output}")
|
| 317 |
+
raise typer.Exit(1)
|
| 318 |
+
|
| 319 |
+
sim_lines = sim_output.strip().split('\n')
|
| 320 |
+
for line in sim_lines[-20:]: # Print last 20 lines of log
|
| 321 |
+
console.print(f" [dim]{line}[/dim]")
|
| 322 |
+
console.print(" ✓ Simulation [green]passed[/green]")
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
def _generate_config_tcl(design_name: str, rtl_file: str) -> str:
|
| 326 |
+
"""Auto-generate OpenLane config.tcl based on design complexity.
|
| 327 |
+
|
| 328 |
+
Reads the RTL file to estimate size and generates appropriate
|
| 329 |
+
die area, clock period, and synthesis settings.
|
| 330 |
+
"""
|
| 331 |
+
# Estimate design complexity from file size
|
| 332 |
+
try:
|
| 333 |
+
with open(rtl_file, 'r') as f:
|
| 334 |
+
rtl_content = f.read()
|
| 335 |
+
line_count = len(rtl_content.strip().split('\n'))
|
| 336 |
+
except IOError:
|
| 337 |
+
line_count = 100 # Fallback
|
| 338 |
+
|
| 339 |
+
# Scale parameters based on complexity
|
| 340 |
+
if line_count < 100:
|
| 341 |
+
# Small: counter, shift register, PWM
|
| 342 |
+
die_size, util, clock_period = 300, 50, "10"
|
| 343 |
+
elif line_count < 300:
|
| 344 |
+
# Medium: FIFO, UART, SPI, FSM
|
| 345 |
+
die_size, util, clock_period = 500, 40, "15"
|
| 346 |
+
else:
|
| 347 |
+
# Large: TMR, AES, processors
|
| 348 |
+
die_size, util, clock_period = 800, 35, "20"
|
| 349 |
+
|
| 350 |
+
return f'''# Auto-generated by AgentIC for {design_name}
|
| 351 |
+
set ::env(DESIGN_NAME) "{design_name}"
|
| 352 |
+
set ::env(VERILOG_FILES) "$::env(DESIGN_DIR)/src/{design_name}.v"
|
| 353 |
+
set ::env(CLOCK_PORT) "clk"
|
| 354 |
+
set ::env(CLOCK_PERIOD) "{clock_period}"
|
| 355 |
+
|
| 356 |
+
# Floorplanning (scaled for ~{line_count} lines of RTL)
|
| 357 |
+
set ::env(FP_SIZING) "absolute"
|
| 358 |
+
set ::env(DIE_AREA) "0 0 {die_size} {die_size}"
|
| 359 |
+
set ::env(FP_CORE_UTIL) {util}
|
| 360 |
+
set ::env(PL_TARGET_DENSITY) {util / 100 + 0.05:.2f}
|
| 361 |
+
|
| 362 |
+
# Synthesis
|
| 363 |
+
set ::env(SYNTH_STRATEGY) "AREA 0"
|
| 364 |
+
set ::env(MAX_FANOUT_CONSTRAINT) 8
|
| 365 |
+
|
| 366 |
+
# Routing
|
| 367 |
+
set ::env(GRT_OVERFLOW_ITERS) 64
|
| 368 |
+
|
| 369 |
+
# PDK
|
| 370 |
+
set ::env(PDK) "{PDK}"
|
| 371 |
+
'''
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
@app.command()
|
| 375 |
+
def harden(
|
| 376 |
+
name: str = typer.Option(..., "--name", "-n", help="Design name (e.g., counter)"),
|
| 377 |
+
):
|
| 378 |
+
"""Run OpenLane hardening (RTL -> GDSII) on an existing design."""
|
| 379 |
+
console.print(Panel(
|
| 380 |
+
f"[bold cyan]AgentIC: Manual Hardening Mode[/bold cyan]\n"
|
| 381 |
+
f"Design: [yellow]{name}[/yellow]",
|
| 382 |
+
title="🚀 Starting OpenLane"
|
| 383 |
+
))
|
| 384 |
+
|
| 385 |
+
new_config = f"{OPENLANE_ROOT}/designs/{name}/config.tcl"
|
| 386 |
+
rtl_file = f"{OPENLANE_ROOT}/designs/{name}/src/{name}.v"
|
| 387 |
+
|
| 388 |
+
if not os.path.exists(new_config):
|
| 389 |
+
if not os.path.exists(rtl_file):
|
| 390 |
+
console.print(f"[bold red]✗ RTL file not found: {rtl_file}[/bold red]")
|
| 391 |
+
raise typer.Exit(1)
|
| 392 |
+
|
| 393 |
+
# Auto-generate config.tcl based on design size
|
| 394 |
+
config_content = _generate_config_tcl(name, rtl_file)
|
| 395 |
+
os.makedirs(os.path.dirname(new_config), exist_ok=True)
|
| 396 |
+
with open(new_config, 'w') as f:
|
| 397 |
+
f.write(config_content)
|
| 398 |
+
console.print(f" ✓ Config auto-generated: [green]{new_config}[/green]")
|
| 399 |
+
|
| 400 |
+
# Ask for background execution
|
| 401 |
+
run_bg = typer.confirm("OpenLane hardening can take 10-30+ minutes. Run in background?", default=True)
|
| 402 |
+
|
| 403 |
+
if run_bg:
|
| 404 |
+
console.print(" [dim]Launching background process...[/dim]")
|
| 405 |
+
else:
|
| 406 |
+
console.print(" [dim]Running OpenLane (this may take 10-30 minutes)...[/dim]")
|
| 407 |
+
|
| 408 |
+
ol_success, ol_result = run_openlane(name, background=run_bg)
|
| 409 |
+
|
| 410 |
+
if ol_success:
|
| 411 |
+
if run_bg:
|
| 412 |
+
console.print(f" ✓ [green]{ol_result}[/green]")
|
| 413 |
+
console.print(f" [dim]Monitor logs: tail -f {OPENLANE_ROOT}/designs/{name}/harden.log[/dim]")
|
| 414 |
+
console.print(" [yellow]Note: Run manual signoff check after background job completes.[/yellow]")
|
| 415 |
+
return
|
| 416 |
+
console.print(f" ✓ GDSII generated: [green]{ol_result}[/green]")
|
| 417 |
+
|
| 418 |
+
# --- Strict Signoff Check ---
|
| 419 |
+
console.print(Panel(
|
| 420 |
+
f"[bold cyan]Running Signoff Checks (STA/Power)...[/bold cyan]",
|
| 421 |
+
title="🔍 Fabrication Readiness"
|
| 422 |
+
))
|
| 423 |
+
success, report = signoff_check_tool(name)
|
| 424 |
+
if success:
|
| 425 |
+
console.print(f"[bold green]✅ SIGNOFF PASSED[/bold green]")
|
| 426 |
+
console.print(report)
|
| 427 |
+
else:
|
| 428 |
+
console.print(f"[bold red]❌ SIGNOFF FAILED[/bold red]")
|
| 429 |
+
console.print(report)
|
| 430 |
+
raise typer.Exit(1)
|
| 431 |
+
|
| 432 |
+
else:
|
| 433 |
+
console.print(f"[bold red]✗ OpenLane failed[/bold red]")
|
| 434 |
+
console.print(f" Error: {ol_result[:500]}...")
|
| 435 |
+
raise typer.Exit(1)
|
| 436 |
+
|
| 437 |
+
# --- THE BUILD COMMAND ---
|
| 438 |
+
@app.command()
|
|
|
|
|
|
|
| 439 |
def build(
|
| 440 |
name: str = typer.Option(..., "--name", "-n", help="Design name (e.g., counter)"),
|
| 441 |
desc: str = typer.Option(..., "--desc", "-d", help="Natural language description"),
|
| 442 |
max_retries: int = typer.Option(5, "--max-retries", "-r", min=0, help="Max auto-fix retries for RTL/TB/sim failures"),
|
| 443 |
+
skip_openlane: bool = typer.Option(False, "--skip-openlane", help="Stop after simulation (no RTL→GDSII hardening)"),
|
| 444 |
show_thinking: bool = typer.Option(False, "--show-thinking", help="Print DeepSeek <think> reasoning for each generation/fix step"),
|
| 445 |
full_signoff: bool = typer.Option(False, "--full-signoff", help="Run full industry signoff (formal + coverage + regression + DRC/LVS)"),
|
| 446 |
min_coverage: float = typer.Option(80.0, "--min-coverage", help="Minimum line coverage percentage to pass verification"),
|
|
|
|
| 456 |
coverage_fallback_policy: str = typer.Option(COVERAGE_FALLBACK_POLICY_DEFAULT, "--coverage-fallback-policy", help="Coverage fallback policy: fail_closed, fallback_oss, skip"),
|
| 457 |
coverage_profile: str = typer.Option(COVERAGE_PROFILE_DEFAULT, "--coverage-profile", help="Coverage profile: balanced, aggressive, relaxed"),
|
| 458 |
):
|
| 459 |
+
"""Build a chip from natural language description (Autonomous Orchestrator 2.0)."""
|
| 460 |
+
|
| 461 |
+
from .orchestrator import BuildOrchestrator
|
| 462 |
+
|
| 463 |
+
console.print(Panel(
|
| 464 |
+
f"[bold cyan]AgentIC: Natural Language → GDSII[/bold cyan]\n"
|
| 465 |
+
f"Design: [yellow]{name}[/yellow]\n"
|
| 466 |
+
f"Description: {desc}\n"
|
| 467 |
+
f"{'[bold green]Full Industry Signoff Enabled[/bold green]' if full_signoff else ''}",
|
| 468 |
+
title="🚀 Starting Autonomous Orchestrator"
|
| 469 |
+
))
|
| 470 |
+
|
| 471 |
tb_gate_mode = tb_gate_mode.lower().strip()
|
| 472 |
if tb_gate_mode not in {"strict", "relaxed"}:
|
| 473 |
raise typer.BadParameter("--tb-gate-mode must be one of: strict, relaxed")
|
|
|
|
| 490 |
|
| 491 |
run_startup_diagnostics(strict=strict_gates)
|
| 492 |
llm = get_llm()
|
| 493 |
+
|
| 494 |
+
orchestrator = BuildOrchestrator(
|
| 495 |
+
name=name,
|
| 496 |
+
desc=desc,
|
| 497 |
+
llm=llm,
|
| 498 |
+
max_retries=max_retries,
|
| 499 |
verbose=show_thinking,
|
| 500 |
skip_openlane=skip_openlane,
|
| 501 |
full_signoff=full_signoff,
|
|
|
|
| 512 |
coverage_fallback_policy=coverage_fallback_policy,
|
| 513 |
coverage_profile=coverage_profile,
|
| 514 |
)
|
| 515 |
+
|
| 516 |
+
orchestrator.run()
|
| 517 |
+
|
| 518 |
+
@app.command()
|
| 519 |
+
def verify(name: str = typer.Argument(..., help="Design name to verify")):
|
| 520 |
+
"""Run verification on an existing design."""
|
| 521 |
+
console.print(f"[yellow]Running verification for {name}...[/yellow]")
|
| 522 |
+
output = run_verification(name)
|
| 523 |
+
console.print(output)
|
| 524 |
+
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
if __name__ == "__main__":
|
| 528 |
app()
|
src/agentic/orchestrator.py
CHANGED
|
@@ -29,6 +29,7 @@ from .agents.designer import get_designer_agent
|
|
| 29 |
from .agents.testbench_designer import get_testbench_agent
|
| 30 |
from .agents.verifier import get_verification_agent, get_error_analyst_agent, get_regression_agent
|
| 31 |
from .agents.doc_agent import get_doc_agent
|
|
|
|
| 32 |
from .tools.vlsi_tools import (
|
| 33 |
write_verilog,
|
| 34 |
run_syntax_check,
|
|
@@ -46,7 +47,6 @@ from .tools.vlsi_tools import (
|
|
| 46 |
parse_drc_lvs_reports,
|
| 47 |
parse_sta_signoff,
|
| 48 |
parse_power_signoff,
|
| 49 |
-
check_physical_metrics,
|
| 50 |
run_cdc_check,
|
| 51 |
generate_design_doc,
|
| 52 |
convert_sva_to_yosys,
|
|
@@ -78,6 +78,7 @@ class BuildState(enum.Enum):
|
|
| 78 |
FORMAL_VERIFY = "Formal Property Verification"
|
| 79 |
COVERAGE_CHECK = "Coverage Analysis"
|
| 80 |
REGRESSION = "Regression Testing"
|
|
|
|
| 81 |
FLOORPLAN = "Floorplanning"
|
| 82 |
HARDENING = "GDSII Hardening"
|
| 83 |
CONVERGENCE_REVIEW = "Convergence Review"
|
|
@@ -179,9 +180,9 @@ class BuildOrchestrator:
|
|
| 179 |
self.tb_repair_fail_count = 0
|
| 180 |
self.tb_failure_fingerprint_history: Dict[str, int] = {}
|
| 181 |
self.tb_recovery_counts: Dict[str, int] = {}
|
| 182 |
-
self.artifacts = {} # Store paths to gathered files
|
| 183 |
-
self.history = [] # Log of state transitions and errors
|
| 184 |
-
self.errors = [] # List of error messages
|
| 185 |
|
| 186 |
def setup_logger(self):
|
| 187 |
"""Sets up a file logger for the build process."""
|
|
@@ -405,6 +406,8 @@ class BuildOrchestrator:
|
|
| 405 |
self.do_coverage_check()
|
| 406 |
elif self.state == BuildState.REGRESSION:
|
| 407 |
self.do_regression()
|
|
|
|
|
|
|
| 408 |
elif self.state == BuildState.FLOORPLAN:
|
| 409 |
self.do_floorplan()
|
| 410 |
elif self.state == BuildState.HARDENING:
|
|
@@ -1133,7 +1136,7 @@ endclass
|
|
| 1133 |
def _kickoff_with_timeout(self, agents: List[Agent], tasks: List[Task], timeout_s: int) -> str:
|
| 1134 |
timeout_s = max(1, int(timeout_s))
|
| 1135 |
if not hasattr(signal, "SIGALRM"):
|
| 1136 |
-
return str(Crew(agents=agents, tasks=tasks).kickoff())
|
| 1137 |
|
| 1138 |
def _timeout_handler(signum, frame):
|
| 1139 |
raise TimeoutError(f"Crew kickoff exceeded {timeout_s}s timeout")
|
|
@@ -1142,7 +1145,7 @@ endclass
|
|
| 1142 |
signal.signal(signal.SIGALRM, _timeout_handler)
|
| 1143 |
signal.alarm(timeout_s)
|
| 1144 |
try:
|
| 1145 |
-
return str(Crew(agents=agents, tasks=tasks).kickoff())
|
| 1146 |
finally:
|
| 1147 |
signal.alarm(0)
|
| 1148 |
signal.signal(signal.SIGALRM, prev_handler)
|
|
@@ -1405,12 +1408,12 @@ LOGIC DECOUPLING HINT:
|
|
| 1405 |
{self.artifacts.get('logic_decoupling_hint', 'N/A')}
|
| 1406 |
|
| 1407 |
CRITICAL RULES:
|
| 1408 |
-
1.
|
| 1409 |
2. Async active-low reset `rst_n`
|
| 1410 |
-
3. Flatten ports (no multi-dim arrays on ports)
|
| 1411 |
4. **IMPLEMENT EVERYTHING**: Do not leave any logic as "to be implemented" or "simplified".
|
| 1412 |
-
5. **
|
| 1413 |
-
6. Return code in ```verilog fence
|
| 1414 |
""",
|
| 1415 |
expected_output='Verilog Code',
|
| 1416 |
agent=rtl_agent
|
|
@@ -2235,7 +2238,7 @@ CRITICAL:
|
|
| 2235 |
elif self.skip_openlane:
|
| 2236 |
self.transition(BuildState.SUCCESS)
|
| 2237 |
else:
|
| 2238 |
-
self.transition(BuildState.
|
| 2239 |
return
|
| 2240 |
if self.strict_gates:
|
| 2241 |
self.log("Coverage infra failure is blocking under strict mode.", refined=True)
|
|
@@ -2247,7 +2250,7 @@ CRITICAL:
|
|
| 2247 |
elif self.skip_openlane:
|
| 2248 |
self.transition(BuildState.SUCCESS)
|
| 2249 |
else:
|
| 2250 |
-
self.transition(BuildState.
|
| 2251 |
return
|
| 2252 |
|
| 2253 |
if not coverage_data.get("ok", False):
|
|
@@ -2258,7 +2261,7 @@ CRITICAL:
|
|
| 2258 |
|
| 2259 |
coverage_checks = {
|
| 2260 |
"line": line_pct >= float(thresholds["line"]),
|
| 2261 |
-
"branch": branch_pct >=
|
| 2262 |
"toggle": toggle_pct >= float(thresholds["toggle"]),
|
| 2263 |
"functional": functional_pct >= float(thresholds["functional"]),
|
| 2264 |
}
|
|
@@ -2282,7 +2285,7 @@ CRITICAL:
|
|
| 2282 |
self.log(
|
| 2283 |
(
|
| 2284 |
"Coverage PASSED "
|
| 2285 |
-
f"(line>={thresholds['line']:.1f}, branch>=
|
| 2286 |
f"toggle>={thresholds['toggle']:.1f}, functional>={thresholds['functional']:.1f})"
|
| 2287 |
),
|
| 2288 |
refined=True,
|
|
@@ -2292,11 +2295,11 @@ CRITICAL:
|
|
| 2292 |
elif self.skip_openlane:
|
| 2293 |
self.transition(BuildState.SUCCESS)
|
| 2294 |
else:
|
| 2295 |
-
self.transition(BuildState.
|
| 2296 |
return
|
| 2297 |
|
| 2298 |
self.retry_count += 1
|
| 2299 |
-
coverage_max_retries = min(self.max_retries,
|
| 2300 |
if self.retry_count > coverage_max_retries:
|
| 2301 |
if getattr(self, "best_tb_backup", None) and os.path.exists(self.best_tb_backup):
|
| 2302 |
self.log(f"Restoring Best Testbench ({self.best_coverage:.1f}%) before proceeding.", refined=True)
|
|
@@ -2312,7 +2315,7 @@ CRITICAL:
|
|
| 2312 |
elif self.skip_openlane:
|
| 2313 |
self.transition(BuildState.SUCCESS)
|
| 2314 |
else:
|
| 2315 |
-
self.transition(BuildState.
|
| 2316 |
return
|
| 2317 |
|
| 2318 |
self.log(
|
|
@@ -2327,7 +2330,7 @@ CRITICAL:
|
|
| 2327 |
tb_agent = get_testbench_agent(self.llm, f"Improve coverage for {self.name}", verbose=self.verbose, strategy=self.strategy.name)
|
| 2328 |
|
| 2329 |
improve_prompt = f"""The current testbench for "{self.name}" does not meet coverage thresholds.
|
| 2330 |
-
|
| 2331 |
Current Coverage Data: {coverage_data}
|
| 2332 |
|
| 2333 |
Current RTL:
|
|
@@ -2341,8 +2344,9 @@ CRITICAL:
|
|
| 2341 |
```
|
| 2342 |
|
| 2343 |
Create an IMPROVED self-checking testbench that:
|
| 2344 |
-
1.
|
| 2345 |
-
2.
|
|
|
|
| 2346 |
3. Tests reset behavior mid-operation
|
| 2347 |
4. Tests boundary values (max/min inputs)
|
| 2348 |
5. Includes back-to-back operations
|
|
@@ -2512,7 +2516,49 @@ CRITICAL:
|
|
| 2512 |
if self.skip_openlane:
|
| 2513 |
self.transition(BuildState.SUCCESS)
|
| 2514 |
else:
|
| 2515 |
-
self.transition(BuildState.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2516 |
|
| 2517 |
def do_floorplan(self):
|
| 2518 |
"""Generate floorplan artifacts and feed hardening with spatial intent."""
|
|
@@ -2625,12 +2671,15 @@ REASONING: <1-line explanation>""",
|
|
| 2625 |
)
|
| 2626 |
|
| 2627 |
floorplan_tcl = os.path.join(src_dir, f"{self.name}_floorplan.tcl")
|
|
|
|
|
|
|
| 2628 |
with open(floorplan_tcl, "w") as f:
|
| 2629 |
f.write(
|
| 2630 |
f"set ::env(DESIGN_NAME) \"{self.name}\"\n"
|
| 2631 |
f"set ::env(PDK) \"{self.pdk_profile.get('pdk', PDK)}\"\n"
|
| 2632 |
f"set ::env(STD_CELL_LIBRARY) \"{self.pdk_profile.get('std_cell_library', 'sky130_fd_sc_hd')}\"\n"
|
| 2633 |
f"set ::env(VERILOG_FILES) [glob $::env(DESIGN_DIR)/src/{self.name}.v]\n"
|
|
|
|
| 2634 |
"set ::env(FP_SIZING) \"absolute\"\n"
|
| 2635 |
f"set ::env(DIE_AREA) \"0 0 {die} {die}\"\n"
|
| 2636 |
f"set ::env(FP_CORE_UTIL) {util}\n"
|
|
|
|
| 29 |
from .agents.testbench_designer import get_testbench_agent
|
| 30 |
from .agents.verifier import get_verification_agent, get_error_analyst_agent, get_regression_agent
|
| 31 |
from .agents.doc_agent import get_doc_agent
|
| 32 |
+
from .agents.sdc_agent import get_sdc_agent
|
| 33 |
from .tools.vlsi_tools import (
|
| 34 |
write_verilog,
|
| 35 |
run_syntax_check,
|
|
|
|
| 47 |
parse_drc_lvs_reports,
|
| 48 |
parse_sta_signoff,
|
| 49 |
parse_power_signoff,
|
|
|
|
| 50 |
run_cdc_check,
|
| 51 |
generate_design_doc,
|
| 52 |
convert_sva_to_yosys,
|
|
|
|
| 78 |
FORMAL_VERIFY = "Formal Property Verification"
|
| 79 |
COVERAGE_CHECK = "Coverage Analysis"
|
| 80 |
REGRESSION = "Regression Testing"
|
| 81 |
+
SDC_GEN = "Timing Constraints Generation"
|
| 82 |
FLOORPLAN = "Floorplanning"
|
| 83 |
HARDENING = "GDSII Hardening"
|
| 84 |
CONVERGENCE_REVIEW = "Convergence Review"
|
|
|
|
| 180 |
self.tb_repair_fail_count = 0
|
| 181 |
self.tb_failure_fingerprint_history: Dict[str, int] = {}
|
| 182 |
self.tb_recovery_counts: Dict[str, int] = {}
|
| 183 |
+
self.artifacts: Dict[str, Any] = {} # Store paths to gathered files
|
| 184 |
+
self.history: List[Dict[str, Any]] = [] # Log of state transitions and errors
|
| 185 |
+
self.errors: List[str] = [] # List of error messages
|
| 186 |
|
| 187 |
def setup_logger(self):
|
| 188 |
"""Sets up a file logger for the build process."""
|
|
|
|
| 406 |
self.do_coverage_check()
|
| 407 |
elif self.state == BuildState.REGRESSION:
|
| 408 |
self.do_regression()
|
| 409 |
+
elif self.state == BuildState.SDC_GEN:
|
| 410 |
+
self.do_sdc_gen()
|
| 411 |
elif self.state == BuildState.FLOORPLAN:
|
| 412 |
self.do_floorplan()
|
| 413 |
elif self.state == BuildState.HARDENING:
|
|
|
|
| 1136 |
def _kickoff_with_timeout(self, agents: List[Agent], tasks: List[Task], timeout_s: int) -> str:
|
| 1137 |
timeout_s = max(1, int(timeout_s))
|
| 1138 |
if not hasattr(signal, "SIGALRM"):
|
| 1139 |
+
return str(Crew(agents=agents, tasks=tasks).kickoff()) # type: ignore
|
| 1140 |
|
| 1141 |
def _timeout_handler(signum, frame):
|
| 1142 |
raise TimeoutError(f"Crew kickoff exceeded {timeout_s}s timeout")
|
|
|
|
| 1145 |
signal.signal(signal.SIGALRM, _timeout_handler)
|
| 1146 |
signal.alarm(timeout_s)
|
| 1147 |
try:
|
| 1148 |
+
return str(Crew(agents=agents, tasks=tasks).kickoff()) # type: ignore
|
| 1149 |
finally:
|
| 1150 |
signal.alarm(0)
|
| 1151 |
signal.signal(signal.SIGALRM, prev_handler)
|
|
|
|
| 1408 |
{self.artifacts.get('logic_decoupling_hint', 'N/A')}
|
| 1409 |
|
| 1410 |
CRITICAL RULES:
|
| 1411 |
+
1. Top-level module name MUST be "{self.name}"
|
| 1412 |
2. Async active-low reset `rst_n`
|
| 1413 |
+
3. Flatten ports on the TOP module (no multi-dim arrays on top-level ports). Internal modules can use them.
|
| 1414 |
4. **IMPLEMENT EVERYTHING**: Do not leave any logic as "to be implemented" or "simplified".
|
| 1415 |
+
5. **MODULAR HIERARCHY**: For complex designs, break them into smaller sub-modules. Output ALL modules in your response.
|
| 1416 |
+
6. Return code in ```verilog fence.
|
| 1417 |
""",
|
| 1418 |
expected_output='Verilog Code',
|
| 1419 |
agent=rtl_agent
|
|
|
|
| 2238 |
elif self.skip_openlane:
|
| 2239 |
self.transition(BuildState.SUCCESS)
|
| 2240 |
else:
|
| 2241 |
+
self.transition(BuildState.SDC_GEN)
|
| 2242 |
return
|
| 2243 |
if self.strict_gates:
|
| 2244 |
self.log("Coverage infra failure is blocking under strict mode.", refined=True)
|
|
|
|
| 2250 |
elif self.skip_openlane:
|
| 2251 |
self.transition(BuildState.SUCCESS)
|
| 2252 |
else:
|
| 2253 |
+
self.transition(BuildState.SDC_GEN)
|
| 2254 |
return
|
| 2255 |
|
| 2256 |
if not coverage_data.get("ok", False):
|
|
|
|
| 2261 |
|
| 2262 |
coverage_checks = {
|
| 2263 |
"line": line_pct >= float(thresholds["line"]),
|
| 2264 |
+
"branch": branch_pct >= 95.0, # Industry Standard Coverage Closure
|
| 2265 |
"toggle": toggle_pct >= float(thresholds["toggle"]),
|
| 2266 |
"functional": functional_pct >= float(thresholds["functional"]),
|
| 2267 |
}
|
|
|
|
| 2285 |
self.log(
|
| 2286 |
(
|
| 2287 |
"Coverage PASSED "
|
| 2288 |
+
f"(line>={thresholds['line']:.1f}, branch>=95.0, "
|
| 2289 |
f"toggle>={thresholds['toggle']:.1f}, functional>={thresholds['functional']:.1f})"
|
| 2290 |
),
|
| 2291 |
refined=True,
|
|
|
|
| 2295 |
elif self.skip_openlane:
|
| 2296 |
self.transition(BuildState.SUCCESS)
|
| 2297 |
else:
|
| 2298 |
+
self.transition(BuildState.SDC_GEN)
|
| 2299 |
return
|
| 2300 |
|
| 2301 |
self.retry_count += 1
|
| 2302 |
+
coverage_max_retries = min(self.max_retries, 5) # Increased for closure loop
|
| 2303 |
if self.retry_count > coverage_max_retries:
|
| 2304 |
if getattr(self, "best_tb_backup", None) and os.path.exists(self.best_tb_backup):
|
| 2305 |
self.log(f"Restoring Best Testbench ({self.best_coverage:.1f}%) before proceeding.", refined=True)
|
|
|
|
| 2315 |
elif self.skip_openlane:
|
| 2316 |
self.transition(BuildState.SUCCESS)
|
| 2317 |
else:
|
| 2318 |
+
self.transition(BuildState.SDC_GEN)
|
| 2319 |
return
|
| 2320 |
|
| 2321 |
self.log(
|
|
|
|
| 2330 |
tb_agent = get_testbench_agent(self.llm, f"Improve coverage for {self.name}", verbose=self.verbose, strategy=self.strategy.name)
|
| 2331 |
|
| 2332 |
improve_prompt = f"""The current testbench for "{self.name}" does not meet coverage thresholds.
|
| 2333 |
+
TARGET: Industry Standard >95.0% Branch Coverage.
|
| 2334 |
Current Coverage Data: {coverage_data}
|
| 2335 |
|
| 2336 |
Current RTL:
|
|
|
|
| 2344 |
```
|
| 2345 |
|
| 2346 |
Create an IMPROVED self-checking testbench that:
|
| 2347 |
+
1. Achieves >95% branch coverage by hitting all missing branches.
|
| 2348 |
+
2. Tests all FSM states (not just happy path)
|
| 2349 |
+
3. Exercises all conditional branches (if/else, case)
|
| 2350 |
3. Tests reset behavior mid-operation
|
| 2351 |
4. Tests boundary values (max/min inputs)
|
| 2352 |
5. Includes back-to-back operations
|
|
|
|
| 2516 |
if self.skip_openlane:
|
| 2517 |
self.transition(BuildState.SUCCESS)
|
| 2518 |
else:
|
| 2519 |
+
self.transition(BuildState.SDC_GEN)
|
| 2520 |
+
|
| 2521 |
+
def do_sdc_gen(self):
|
| 2522 |
+
"""Generate Synthesis Design Constraints (.sdc) for OpenLane."""
|
| 2523 |
+
src_dir = f"{OPENLANE_ROOT}/designs/{self.name}/src"
|
| 2524 |
+
os.makedirs(src_dir, exist_ok=True)
|
| 2525 |
+
sdc_path = os.path.join(src_dir, f"{self.name}.sdc")
|
| 2526 |
+
|
| 2527 |
+
self.log("Generating SDC Timing Constraints...", refined=True)
|
| 2528 |
+
sdc_agent = get_sdc_agent(self.llm, "Generate Synthesis Design Constraints", self.verbose)
|
| 2529 |
+
|
| 2530 |
+
arch_spec = self.artifacts.get('spec', 'No spec generated.')
|
| 2531 |
+
sdc_task = Task(
|
| 2532 |
+
description=f"""Generate an SDC file for module '{self.name}'.
|
| 2533 |
+
|
| 2534 |
+
Architecture Specification:
|
| 2535 |
+
{arch_spec}
|
| 2536 |
+
|
| 2537 |
+
REQUIREMENTS:
|
| 2538 |
+
1. Identify the clock port and requested frequency/period.
|
| 2539 |
+
2. If unspecified, assume 100MHz (10.0ns period).
|
| 2540 |
+
3. Output ONLY the raw SDC constraints. DO NOT output code blocks or markdown wrappers (no ```sdc).
|
| 2541 |
+
""",
|
| 2542 |
+
expected_output="Raw SDC constraints text cleanly formatted.",
|
| 2543 |
+
agent=sdc_agent
|
| 2544 |
+
)
|
| 2545 |
+
|
| 2546 |
+
with console.status("[bold cyan]Generating Timing Constraints (SDC)...[/bold cyan]"):
|
| 2547 |
+
sdc_content = str(Crew(agents=[sdc_agent], tasks=[sdc_task]).kickoff()).strip()
|
| 2548 |
+
|
| 2549 |
+
# Clean up potential markdown wrappers created by LLM anyway
|
| 2550 |
+
if sdc_content.startswith("```"):
|
| 2551 |
+
lines = sdc_content.split("\n")
|
| 2552 |
+
if len(lines) > 2:
|
| 2553 |
+
sdc_content = "\n".join(lines[1:-1])
|
| 2554 |
+
|
| 2555 |
+
with open(sdc_path, "w") as f:
|
| 2556 |
+
f.write(sdc_content)
|
| 2557 |
+
|
| 2558 |
+
self.artifacts["sdc_path"] = sdc_path
|
| 2559 |
+
self.log(f"SDC Constraints generated: {sdc_path}", refined=True)
|
| 2560 |
+
|
| 2561 |
+
self.transition(BuildState.FLOORPLAN)
|
| 2562 |
|
| 2563 |
def do_floorplan(self):
|
| 2564 |
"""Generate floorplan artifacts and feed hardening with spatial intent."""
|
|
|
|
| 2671 |
)
|
| 2672 |
|
| 2673 |
floorplan_tcl = os.path.join(src_dir, f"{self.name}_floorplan.tcl")
|
| 2674 |
+
sdc_injection = f"set ::env(BASE_SDC_FILE) \"$::env(DESIGN_DIR)/src/{self.name}.sdc\"\n" if "sdc_path" in self.artifacts else ""
|
| 2675 |
+
|
| 2676 |
with open(floorplan_tcl, "w") as f:
|
| 2677 |
f.write(
|
| 2678 |
f"set ::env(DESIGN_NAME) \"{self.name}\"\n"
|
| 2679 |
f"set ::env(PDK) \"{self.pdk_profile.get('pdk', PDK)}\"\n"
|
| 2680 |
f"set ::env(STD_CELL_LIBRARY) \"{self.pdk_profile.get('std_cell_library', 'sky130_fd_sc_hd')}\"\n"
|
| 2681 |
f"set ::env(VERILOG_FILES) [glob $::env(DESIGN_DIR)/src/{self.name}.v]\n"
|
| 2682 |
+
f"{sdc_injection}"
|
| 2683 |
"set ::env(FP_SIZING) \"absolute\"\n"
|
| 2684 |
f"set ::env(DIE_AREA) \"0 0 {die} {die}\"\n"
|
| 2685 |
f"set ::env(FP_CORE_UTIL) {util}\n"
|
src/agentic/tools/vlsi_tools.py
CHANGED
|
@@ -8,6 +8,7 @@ from collections import Counter, defaultdict, deque
|
|
| 8 |
from typing import Dict, Any, List, Tuple
|
| 9 |
import shutil
|
| 10 |
from crewai.tools import tool
|
|
|
|
| 11 |
from ..config import (
|
| 12 |
OPENLANE_ROOT,
|
| 13 |
SCRIPTS_DIR,
|
|
@@ -249,7 +250,7 @@ def write_verilog(design_name: str, code: str, is_testbench: bool = False, suffi
|
|
| 249 |
stripped = line.strip()
|
| 250 |
if not stripped or stripped.startswith('`') or stripped.startswith('//'):
|
| 251 |
filtered_lines.append(line)
|
| 252 |
-
clean_code = '\n'.join(filtered_lines) + clean_code[module_pos:]
|
| 253 |
|
| 254 |
# --- VALIDATION ---
|
| 255 |
if "module" not in clean_code:
|
|
@@ -280,8 +281,38 @@ def write_verilog(design_name: str, code: str, is_testbench: bool = False, suffi
|
|
| 280 |
if not clean_code.endswith("\n"):
|
| 281 |
clean_code += "\n"
|
| 282 |
|
| 283 |
-
|
| 284 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 285 |
return path
|
| 286 |
except IOError as e:
|
| 287 |
return f"Error: Failed to write Verilog file {path}: {str(e)}"
|
|
@@ -295,11 +326,18 @@ def run_syntax_check(file_path: str) -> tuple:
|
|
| 295 |
return False, f"File not found: {file_path}"
|
| 296 |
|
| 297 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
# --lint-only: check syntax and basic semantics
|
| 299 |
# --sv: force SystemVerilog parsing
|
| 300 |
# --timing: support delays
|
| 301 |
# -Wno-fatal: don't crash on warnings (unless they are errors)
|
| 302 |
-
cmd = ["verilator", "--lint-only", "--sv", "--timing", "-Wno-fatal"
|
| 303 |
|
| 304 |
result = subprocess.run(
|
| 305 |
cmd,
|
|
@@ -323,8 +361,14 @@ def run_lint_check(file_path: str) -> tuple:
|
|
| 323 |
if not os.path.exists(file_path):
|
| 324 |
return False, f"File not found: {file_path}"
|
| 325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
# Use --lint-only with sensible warnings (not -Wall, which flags unused signals as errors)
|
| 327 |
-
cmd = ["verilator", "--lint-only", "-Wno-UNUSED", "-Wno-PINMISSING", "-Wno-CASEINCOMPLETE", "--timing"
|
| 328 |
|
| 329 |
try:
|
| 330 |
result = subprocess.run(
|
|
@@ -629,7 +673,7 @@ def convert_sva_to_yosys(sva_content: str, module_name: str) -> str:
|
|
| 629 |
"""
|
| 630 |
port_match = re.search(r'module\s+\w+_sva\s*\((.*?)\);', sva_content, re.DOTALL)
|
| 631 |
if not port_match:
|
| 632 |
-
return
|
| 633 |
|
| 634 |
ports_section = port_match.group(1)
|
| 635 |
port_lines = []
|
|
@@ -1239,6 +1283,9 @@ def run_simulation(design_name: str) -> tuple:
|
|
| 1239 |
if not os.path.exists(tb_file):
|
| 1240 |
return False, f"Testbench file not found: {tb_file}"
|
| 1241 |
|
|
|
|
|
|
|
|
|
|
| 1242 |
# Compile & Build using Verilator --binary
|
| 1243 |
# --binary: Build a binary executable
|
| 1244 |
# -j 0: Use all cores
|
|
@@ -1252,7 +1299,7 @@ def run_simulation(design_name: str) -> tuple:
|
|
| 1252 |
"--timing",
|
| 1253 |
"--assert",
|
| 1254 |
"-Wno-fatal", # Don't error out on warnings
|
| 1255 |
-
|
| 1256 |
"--top-module", f"{design_name}_tb",
|
| 1257 |
"--Mdir", obj_dir,
|
| 1258 |
"-o", "sim_exec"
|
|
@@ -1645,7 +1692,7 @@ def parse_congestion_metrics(design_name: str, run_tag: str = "agentrun") -> Dic
|
|
| 1645 |
continue
|
| 1646 |
overflow_triplet = m.group("overflow").split("/")
|
| 1647 |
total_over = int(overflow_triplet[-1].strip())
|
| 1648 |
-
result["layers"].append(
|
| 1649 |
{
|
| 1650 |
"layer": m.group("layer"),
|
| 1651 |
"usage_pct": float(m.group("usage")),
|
|
@@ -1874,6 +1921,9 @@ def run_verilator_coverage(design_name: str, rtl_file: str, tb_file: str, covera
|
|
| 1874 |
except OSError:
|
| 1875 |
pass
|
| 1876 |
|
|
|
|
|
|
|
|
|
|
| 1877 |
compile_cmd = [
|
| 1878 |
"verilator",
|
| 1879 |
"--binary",
|
|
@@ -1881,7 +1931,7 @@ def run_verilator_coverage(design_name: str, rtl_file: str, tb_file: str, covera
|
|
| 1881 |
"--sv",
|
| 1882 |
"--timing",
|
| 1883 |
"-Wno-fatal",
|
| 1884 |
-
|
| 1885 |
tb_file,
|
| 1886 |
"--top-module",
|
| 1887 |
f"{design_name}_tb",
|
|
@@ -1991,7 +2041,10 @@ def run_iverilog_coverage(design_name: str, rtl_file: str, tb_file: str, coverag
|
|
| 1991 |
result["total_signals"] = len(signals)
|
| 1992 |
signal_set = set(signals)
|
| 1993 |
|
| 1994 |
-
|
|
|
|
|
|
|
|
|
|
| 1995 |
try:
|
| 1996 |
comp = subprocess.run(compile_cmd, capture_output=True, text=True, timeout=120, cwd=src_dir)
|
| 1997 |
except FileNotFoundError:
|
|
@@ -2281,8 +2334,8 @@ def parse_drc_lvs_reports(design_name: str) -> tuple:
|
|
| 2281 |
if drc_files:
|
| 2282 |
drc_path = _best_report_path(drc_files, "drc")
|
| 2283 |
try:
|
| 2284 |
-
with open(drc_path, 'r') as
|
| 2285 |
-
drc_content =
|
| 2286 |
details['drc_report'] = drc_content[:2000] # Truncate for readability
|
| 2287 |
|
| 2288 |
# Count violations
|
|
@@ -2311,8 +2364,8 @@ def parse_drc_lvs_reports(design_name: str) -> tuple:
|
|
| 2311 |
if lvs_files:
|
| 2312 |
lvs_path = _best_report_path(lvs_files, ".lvs")
|
| 2313 |
try:
|
| 2314 |
-
with open(lvs_path, 'r') as
|
| 2315 |
-
lvs_content =
|
| 2316 |
details['lvs_report'] = lvs_content[:2000]
|
| 2317 |
|
| 2318 |
# Prefer explicit numeric result when available.
|
|
@@ -2664,7 +2717,7 @@ def parse_sta_signoff(design_name: str) -> dict:
|
|
| 2664 |
if worst_hold == float("inf"):
|
| 2665 |
worst_hold = 0.0
|
| 2666 |
|
| 2667 |
-
timing_met = all((c["setup_slack"] >= 0.0 and c["hold_slack"] >= 0.0) for c in corners)
|
| 2668 |
top_paths = sorted(top_paths, key=lambda x: x.get("slack", 0.0))[:10]
|
| 2669 |
|
| 2670 |
return {
|
|
@@ -2722,8 +2775,8 @@ def parse_power_signoff(design_name: str) -> dict:
|
|
| 2722 |
|
| 2723 |
if power_report and os.path.exists(power_report):
|
| 2724 |
result["power_report"] = power_report
|
| 2725 |
-
with open(power_report, "r", errors="ignore") as
|
| 2726 |
-
content =
|
| 2727 |
total_match = re.search(r"Total\\s+([\\d.eE+\\-]+)\\s+([\\d.eE+\\-]+)\\s+([\\d.eE+\\-]+)\\s+([\\d.eE+\\-]+)", content)
|
| 2728 |
if total_match:
|
| 2729 |
result["internal_power_w"] = float(total_match.group(1))
|
|
@@ -2771,7 +2824,7 @@ def parse_power_signoff(design_name: str) -> dict:
|
|
| 2771 |
result["irdrop_max_vgnd"] = _parse_irdrop(vgnd_path)
|
| 2772 |
|
| 2773 |
# 5% of 1.8V ~= 90mV
|
| 2774 |
-
result["power_ok"] = result["irdrop_max_vpwr"] <= 0.09 and result["irdrop_max_vgnd"] <= 0.09
|
| 2775 |
return result
|
| 2776 |
except Exception:
|
| 2777 |
return result
|
|
|
|
| 8 |
from typing import Dict, Any, List, Tuple
|
| 9 |
import shutil
|
| 10 |
from crewai.tools import tool
|
| 11 |
+
from typing import cast
|
| 12 |
from ..config import (
|
| 13 |
OPENLANE_ROOT,
|
| 14 |
SCRIPTS_DIR,
|
|
|
|
| 250 |
stripped = line.strip()
|
| 251 |
if not stripped or stripped.startswith('`') or stripped.startswith('//'):
|
| 252 |
filtered_lines.append(line)
|
| 253 |
+
clean_code = '\n'.join(filtered_lines) + '\n' + clean_code[module_pos:]
|
| 254 |
|
| 255 |
# --- VALIDATION ---
|
| 256 |
if "module" not in clean_code:
|
|
|
|
| 281 |
if not clean_code.endswith("\n"):
|
| 282 |
clean_code += "\n"
|
| 283 |
|
| 284 |
+
# --- MULTI-FILE RTL HIERARCHY SPLITTING ---
|
| 285 |
+
if not is_testbench and "module" in clean_code:
|
| 286 |
+
import glob
|
| 287 |
+
# Remove old RTL files to prevent stale modules from breaking build
|
| 288 |
+
src_dir = os.path.dirname(path)
|
| 289 |
+
for old_rt in glob.glob(os.path.join(src_dir, "*.v")):
|
| 290 |
+
if not old_rt.endswith("_tb.v") and "regression" not in old_rt:
|
| 291 |
+
try:
|
| 292 |
+
os.remove(old_rt)
|
| 293 |
+
except OSError:
|
| 294 |
+
pass
|
| 295 |
+
|
| 296 |
+
# Find all modules
|
| 297 |
+
modules = re.findall(r'(module\s+([a-zA-Z0-9_]+).*?endmodule)', clean_code, re.DOTALL)
|
| 298 |
+
if len(modules) > 1:
|
| 299 |
+
# If multiple modules exist, write them to separate files
|
| 300 |
+
for mod_code, mod_name in modules:
|
| 301 |
+
mod_path = os.path.join(src_dir, f"{mod_name}.v")
|
| 302 |
+
with open(mod_path, "w") as f:
|
| 303 |
+
f.write(mod_code + "\n")
|
| 304 |
+
|
| 305 |
+
# Make sure the requested path exists so syntax check doesn't fail
|
| 306 |
+
if not os.path.exists(path):
|
| 307 |
+
with open(path, "w") as f:
|
| 308 |
+
f.write(f"// Main module {design_name} likely defined in other files\n")
|
| 309 |
+
else:
|
| 310 |
+
with open(path, "w") as f:
|
| 311 |
+
f.write(clean_code)
|
| 312 |
+
else:
|
| 313 |
+
with open(path, "w") as f:
|
| 314 |
+
f.write(clean_code)
|
| 315 |
+
|
| 316 |
return path
|
| 317 |
except IOError as e:
|
| 318 |
return f"Error: Failed to write Verilog file {path}: {str(e)}"
|
|
|
|
| 326 |
return False, f"File not found: {file_path}"
|
| 327 |
|
| 328 |
try:
|
| 329 |
+
# Gather all RTL files to support multi-file compilation
|
| 330 |
+
import glob
|
| 331 |
+
src_dir = os.path.dirname(file_path)
|
| 332 |
+
rtl_files = [f for f in glob.glob(os.path.join(src_dir, "*.v")) if not f.endswith("_tb.v") and "regression" not in f]
|
| 333 |
+
if file_path not in rtl_files and os.path.exists(file_path):
|
| 334 |
+
rtl_files.append(file_path)
|
| 335 |
+
|
| 336 |
# --lint-only: check syntax and basic semantics
|
| 337 |
# --sv: force SystemVerilog parsing
|
| 338 |
# --timing: support delays
|
| 339 |
# -Wno-fatal: don't crash on warnings (unless they are errors)
|
| 340 |
+
cmd = ["verilator", "--lint-only", "--sv", "--timing", "-Wno-fatal"] + rtl_files
|
| 341 |
|
| 342 |
result = subprocess.run(
|
| 343 |
cmd,
|
|
|
|
| 361 |
if not os.path.exists(file_path):
|
| 362 |
return False, f"File not found: {file_path}"
|
| 363 |
|
| 364 |
+
import glob
|
| 365 |
+
src_dir = os.path.dirname(file_path)
|
| 366 |
+
rtl_files = [f for f in glob.glob(os.path.join(src_dir, "*.v")) if not f.endswith("_tb.v") and "regression" not in f]
|
| 367 |
+
if file_path not in rtl_files and os.path.exists(file_path):
|
| 368 |
+
rtl_files.append(file_path)
|
| 369 |
+
|
| 370 |
# Use --lint-only with sensible warnings (not -Wall, which flags unused signals as errors)
|
| 371 |
+
cmd = ["verilator", "--lint-only", "-Wno-UNUSED", "-Wno-PINMISSING", "-Wno-CASEINCOMPLETE", "--timing"] + rtl_files
|
| 372 |
|
| 373 |
try:
|
| 374 |
result = subprocess.run(
|
|
|
|
| 673 |
"""
|
| 674 |
port_match = re.search(r'module\s+\w+_sva\s*\((.*?)\);', sva_content, re.DOTALL)
|
| 675 |
if not port_match:
|
| 676 |
+
return ""
|
| 677 |
|
| 678 |
ports_section = port_match.group(1)
|
| 679 |
port_lines = []
|
|
|
|
| 1283 |
if not os.path.exists(tb_file):
|
| 1284 |
return False, f"Testbench file not found: {tb_file}"
|
| 1285 |
|
| 1286 |
+
import glob
|
| 1287 |
+
rtl_files = [f for f in glob.glob(os.path.join(src_dir, "*.v")) if not f.endswith("_tb.v") and "regression" not in f]
|
| 1288 |
+
|
| 1289 |
# Compile & Build using Verilator --binary
|
| 1290 |
# --binary: Build a binary executable
|
| 1291 |
# -j 0: Use all cores
|
|
|
|
| 1299 |
"--timing",
|
| 1300 |
"--assert",
|
| 1301 |
"-Wno-fatal", # Don't error out on warnings
|
| 1302 |
+
*rtl_files, tb_file,
|
| 1303 |
"--top-module", f"{design_name}_tb",
|
| 1304 |
"--Mdir", obj_dir,
|
| 1305 |
"-o", "sim_exec"
|
|
|
|
| 1692 |
continue
|
| 1693 |
overflow_triplet = m.group("overflow").split("/")
|
| 1694 |
total_over = int(overflow_triplet[-1].strip())
|
| 1695 |
+
cast(list, result["layers"]).append(
|
| 1696 |
{
|
| 1697 |
"layer": m.group("layer"),
|
| 1698 |
"usage_pct": float(m.group("usage")),
|
|
|
|
| 1921 |
except OSError:
|
| 1922 |
pass
|
| 1923 |
|
| 1924 |
+
import glob
|
| 1925 |
+
rtl_files = [f for f in glob.glob(os.path.join(src_dir, "*.v")) if not f.endswith("_tb.v") and "regression" not in f]
|
| 1926 |
+
|
| 1927 |
compile_cmd = [
|
| 1928 |
"verilator",
|
| 1929 |
"--binary",
|
|
|
|
| 1931 |
"--sv",
|
| 1932 |
"--timing",
|
| 1933 |
"-Wno-fatal",
|
| 1934 |
+
*rtl_files,
|
| 1935 |
tb_file,
|
| 1936 |
"--top-module",
|
| 1937 |
f"{design_name}_tb",
|
|
|
|
| 2041 |
result["total_signals"] = len(signals)
|
| 2042 |
signal_set = set(signals)
|
| 2043 |
|
| 2044 |
+
import glob
|
| 2045 |
+
rtl_files = [f for f in glob.glob(os.path.join(src_dir, "*.v")) if not f.endswith("_tb.v") and "regression" not in f]
|
| 2046 |
+
|
| 2047 |
+
compile_cmd = ["iverilog", "-g2012", "-o", sim_out, *rtl_files, tb_file]
|
| 2048 |
try:
|
| 2049 |
comp = subprocess.run(compile_cmd, capture_output=True, text=True, timeout=120, cwd=src_dir)
|
| 2050 |
except FileNotFoundError:
|
|
|
|
| 2334 |
if drc_files:
|
| 2335 |
drc_path = _best_report_path(drc_files, "drc")
|
| 2336 |
try:
|
| 2337 |
+
with open(drc_path, 'r') as f_rpt:
|
| 2338 |
+
drc_content = f_rpt.read()
|
| 2339 |
details['drc_report'] = drc_content[:2000] # Truncate for readability
|
| 2340 |
|
| 2341 |
# Count violations
|
|
|
|
| 2364 |
if lvs_files:
|
| 2365 |
lvs_path = _best_report_path(lvs_files, ".lvs")
|
| 2366 |
try:
|
| 2367 |
+
with open(lvs_path, 'r') as f_rpt:
|
| 2368 |
+
lvs_content = f_rpt.read()
|
| 2369 |
details['lvs_report'] = lvs_content[:2000]
|
| 2370 |
|
| 2371 |
# Prefer explicit numeric result when available.
|
|
|
|
| 2717 |
if worst_hold == float("inf"):
|
| 2718 |
worst_hold = 0.0
|
| 2719 |
|
| 2720 |
+
timing_met = all((float(c["setup_slack"]) >= 0.0 and float(c["hold_slack"]) >= 0.0) for c in corners) # type: ignore
|
| 2721 |
top_paths = sorted(top_paths, key=lambda x: x.get("slack", 0.0))[:10]
|
| 2722 |
|
| 2723 |
return {
|
|
|
|
| 2775 |
|
| 2776 |
if power_report and os.path.exists(power_report):
|
| 2777 |
result["power_report"] = power_report
|
| 2778 |
+
with open(power_report, "r", errors="ignore") as f_rpt:
|
| 2779 |
+
content = f_rpt.read()
|
| 2780 |
total_match = re.search(r"Total\\s+([\\d.eE+\\-]+)\\s+([\\d.eE+\\-]+)\\s+([\\d.eE+\\-]+)\\s+([\\d.eE+\\-]+)", content)
|
| 2781 |
if total_match:
|
| 2782 |
result["internal_power_w"] = float(total_match.group(1))
|
|
|
|
| 2824 |
result["irdrop_max_vgnd"] = _parse_irdrop(vgnd_path)
|
| 2825 |
|
| 2826 |
# 5% of 1.8V ~= 90mV
|
| 2827 |
+
result["power_ok"] = float(result["irdrop_max_vpwr"]) <= 0.09 and float(result["irdrop_max_vgnd"]) <= 0.09 # type: ignore
|
| 2828 |
return result
|
| 2829 |
except Exception:
|
| 2830 |
return result
|
training/agentic_sft_data.jsonl
CHANGED
|
@@ -75,3 +75,6 @@
|
|
| 75 |
{"job_id": "36e08ecb-87b9-41a6-8599-c8ba38188712", "timestamp": 1772030529, "design_name": "8bit_risc_cpu_with", "instruction": "Design a digital chip: 8-bit RISC CPU with Harvard architecture", "input": "\n# 8‑bit RISC CPU – Micro‑Architecture Specification (MAS)\n\n> **Doc.** : 8‑bit_risc_cpu_with – Harvard‑architecture, single‑issue, 2‑stage pipeline \n> **Author** : Chief System Architect – *Your Name* \n> **Date** : 2025‑11‑02 \n> **Version** : 1.0 \n\n--- \n\n## 1. I/O Interface \n\n| Port | Width | Direction | Description | Timing / Control | Reset State |\n|------|-------|-----------|-------------|------------------|--------------|\n| `clk` | 1 | Input | System clock – positive‑edge triggered. | – | Idle (no action) |\n| `rst_n` | 1 | Input | Active‑low asynchronous reset. | – | All registers forced to `0`; PC = `0x00` |\n| `enable` | 1 | Input | Chip‑enable; when `0` the core is put in *sleep* (no state change). | – | Same as reset when disabled |\n| `addr` | 16 | Output | Address bus to **Instruction Memory** (Harvard separate I‑space). | – | Output the current PC value |\n| `data_in` | 8 | Input | Data bus from **Data Memory** (load/store operand). | – | – |\n| `data_out` | 8 | Output | Data bus to **Data Memory** (write operand). | – | – |\n| `we_mem` | 1 | Output | Memory‑Write Enable – asserted when a store instruction is in the MEM stage. | – | `0` (idle) |\n| `re_mem` | 1 | Output | Memory‑Read Enable – asserted when a load instruction is in the MEM stage. | – | `0` (idle) |\n| `irq` | 1 | Input | External interrupt request (level‑triggered). | – | De‑asserted |\n| `irq_ack` | 1 | Output | Interrupt‑acknowledge pulse (generated in the WRITE‑BACK stage). | – | `0` |\n| `ready` | 1 | Output | Indicates the core is ready for a new instruction fetch (pipeline flush not in progress). | – | `1` after reset release |\n\n### Timing Assumptions \n\n* All control signals are **registered** (registered on the rising edge of `clk`). \n* Memory accesses complete **within the same clock cycle** (single‑cycle read/write). \n* Interrupt latency = 1 cycle (acknowledge asserted one cycle after `irq` is seen and pipeline is not stalled). \n\n--- \n\n## 2. Internal Registers & FSM States \n\n#", "output": "module eightbit_risc_cpu_with #(\n parameter ADDR_WIDTH = 16,\n parameter DATA_WIDTH = 8,\n parameter INSTR_DEPTH = 16\n) (\n input logic clk,\n input logic rst_n, // asynchronous active‑low reset\n input logic enable, // chip enable (0 = sleep)\n\n // Instruction address output (to Instruction Memory)\n output logic [ADDR_WIDTH-1:0] addr,\n\n // Data interface to Data Memory\n input logic [DATA_WIDTH-1:0] data_in, // data from Data Memory\n output logic [DATA_WIDTH-1:0] data_out, // data to Data Memory\n output logic we_mem, // memory write enable\n output logic re_mem, // memory read enable\n\n // Interrupt interface\n input logic irq, // external interrupt request (level)\n output logic irq_ack, // interrupt acknowledge pulse\n output logic ready // core ready for new fetch\n);\n\n // -----------------------------------------------------------\n // I/O Policy – No shadowing of ports\n // -----------------------------------------------------------\n // Internal signals – all declared with `logic` (SystemVerilog)\n // -----------------------------------------------------------\n\n // Index width for ROM access\n localparam IDX_W = $clog2(INSTR_DEPTH);\n\n // FSM definition (3‑bit encoding – matches state count)\n typedef enum logic [2:0] {\n S_IDLE = 3'd0,", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for '8bit_risc_cpu_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/8bit_risc_cpu_with/8bit_risc_cpu_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] Hierarchical synthesis planner: disabled.\n[RTL_GEN] Transitioning: RTL_GEN -> RTL_FIX\n[RTL_FIX] Fixing Code (Attempt 1/5)\n[RTL_FIX] Fixing Code (Attempt 2/5)\n[RTL_FIX] Syntax Check Passed (Verilator)\n[RTL_FIX] Lint Check Passed (Verilator)\n[RTL_FIX] Pre-synthesis auto-fix applied.\n[RTL_FIX] Syntax Check Passed (Verilator)\n[RTL_FIX] Lint Check Passed (Verilator)\n[RTL_FIX] Semantic rigor gate failed. Routing back to RTL fix.\n[RTL_FIX] Fixing Code (Attempt 3/5)\n[RTL_FIX] Syntax Check Passed (Verilator)\n[RTL_FIX] Lint Check Passed (Verilator)\n[RTL_FIX] Transitioning: RTL_FIX -> VERIFICATION\n[VERIFICATION] Generating Testbench...\n[VERIFICATION] TB generation stalled/failed (signal only works in main thread of the main interpreter). Using deterministic fallback TB.\n[VERIFICATION] TB static gate: PASS (diag: 8bit_risc_cpu_with_tb_static_gate_attempt1.json)\n[VERIFICATION] TB compile gate: FAIL (diag: 8bit_risc_cpu_with_tb_compile_gate_attempt1.json)\n[VERIFICATION] Verifying with existing Testbench (Attempt 0).\n[VERIFICATION] TB static gate: FAIL (diag: 8bit_risc_cpu_with_tb_static_gate_attempt2.json)\n[VERIFICATION] TB gate failed; applied deterministic auto-repair.\n[VERIFICATION] Verifying with existing Testbench (Attempt 0).\n[VERIFICATION] TB static gate: FAIL (diag: 8bit_risc_cpu_with_tb_static_gate_attempt3.json)\n[VERIFICATION] TB gate failed; forcing LLM TB regeneration with structured diagnostics.\n[VERIFICATION] Generating Testbench...\n[VERIFICATION] TB generation stalled/failed (signal only works in main thread of the main interpreter). Using deterministic fallback TB.\n[VERIFICATION] TB static gate: PASS (diag: 8bit_risc_cpu_with_tb_static_gate_attempt4.json)\n[VERIFICATION] TB compile gate: FAIL (diag: 8bit_risc_cpu_with_tb_compile_gate_attempt2.json)\n[VERIFICATION] Repeated TB compile fingerprint detected. Failing closed.", "source": "agentic_web_build"}
|
| 76 |
{"job_id": "05223be4-69db-4e20-85c3-07c4038f0b42", "timestamp": 1772031476, "design_name": "axi4_dma_engine_with", "instruction": "Design a digital chip: AXI4 DMA engine with 4 channels", "input": "\n# **## Module: axi4_dma_engine_with**\n\nThe RTL entity that implements a **four‑channel AXI‑4 master‑side DMA engine**. The top‑level module name **must** be `axi4_dma_engine_with`. All ports, parameters, and internal blocks are defined to support a production‑ready AXI‑4 compliant DMA engine suitable for integration into an SoC.\n\n---\n\n# **## Chip Family** \n**AXI** – The device belongs to the AXI‑4 interconnect family (AXI4‑Stream/AXI4‑Lite/AXI4‑Full). It provides a high‑performance memory transfer subsystem by bridging the AXI master interface to internal descriptor‑based channels.\n\n---\n\n# **## Port List**\n\n| Port | Direction | Bits | Name | Purpose |\n|------|-----------|------|------|---------|\n| `clk` | Input | 1 | Clock | System clock for all logic (positive‑edge triggered). |\n| `rst_n` | Input | 1 | Asynchronous active‑low reset | Global reset; clears all state machines, registers, and FIFO pointers. |\n| **AXI‑Master Interface** |\n| `awaddr` | Output | `ADDR_WIDTH` | Address Write Channel address |\n| `awvalid` | Output | 1 | Write address valid |\n| `awready` | Input | 1 | Write address ready |\n| `wdata` | Output | `DATA_WIDTH` | Write data payload |\n| `wstrb` | Output | `DATA_WIDTH/8` | Byte lane strobes |\n| `wvalid` | Output | 1 | Write data valid |\n| `wready` | Input | 1 | Write data ready |\n| `bresp` | Output | 2 | Write response (OKAY, SLVERR, etc.) |\n| `bvalid` | Output | 1 | Write response valid |\n| `bready` | Input | 1 | Write response ready |\n| `araddr` | Output | `ADDR_WIDTH` | Read address channel address |\n| `arvalid` | Output | 1 | Read address valid |\n| `arready` | Input | 1 | Read address ready |\n| `rdata` | Input | `DATA_WIDTH` | Read data returned |\n| `rresp` | Input | 2 | Read response |\n| `rvalid` | Input | 1 | Read data valid |\n| `rready` | Output | 1 | Read data ready |\n| **DMA Control & Status** |\n| `ch0_cfg` | Input | `CH_CFG_BITS` | Channel‑0 configuration (enable, direction, burst, etc.) |\n| `ch1_cfg` | Input | `CH_CFG_BITS` | Channel‑1", "output": "module axi4_dma_engine_with #(\n // -----------------------------------------------------------------\n // Parameters (all have default values as specified in the spec)\n // -----------------------------------------------------------------\n parameter int DATA_WIDTH = 32; // AXI data bus width\n parameter int ADDR_WIDTH = 32; // AXI address bus width\n parameter int NUM_CH = 4; // Number of DMA channels\n parameter int CH_CFG_BITS = 8; // Config register width per channel\n parameter int DESC_BITS = 16; // Width of descriptor address pointer\n parameter int DESC_COUNT_MAX = 1024; // Max descriptors per channel\n parameter int FIFO_DEPTH = 8; // Depth of per‑channel descriptor FIFO\n parameter string RESET_STYLE = \"SYNC\"; // \"SYNC\" or \"ASYNC\"\n parameter string INTERFACE_STYLE = \"AXI4_FULL\"; // Enforces full handshake\n parameter logic SUPPORTS_BURST = 1'b1; // Enable burst transfers\n parameter int MAX_BURST_LEN = 16; // Max beats per burst\n parameter string ERROR_POLICY = \"HALT_AND_REPORT\" // Error handling policy\n)(\n // -----------------------------------------------------------------\n // Clock and asynchronous active‑low reset\n // -----------------------------------------------------------------\n input logic clk,\n input logic ", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'axi4_dma_engine_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/axi4_dma_engine_with/axi4_dma_engine_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] Hierarchical synthesis planner: disabled.\n[RTL_GEN] Transitioning: RTL_GEN -> RTL_FIX\n[RTL_FIX] Fixing Code (Attempt 1/5)\n[RTL_FIX] File Write Error in FIX stage: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.\n[RTL_FIX] Retrying fix (LLM output was unparsable).\n[RTL_FIX] Detected repeated syntax/lint failure fingerprint. Failing closed.", "source": "agentic_web_build"}
|
| 77 |
{"job_id": "aefbc11b-69f4-4d60-842d-6691200babda", "timestamp": 1772031756, "design_name": "uart_controller_at_115200", "instruction": "Design a digital chip: UART controller at 115200 baud", "input": "\n## Module: uart_controller_at_115200 \n\n## Chip Family \n**UART** – a classic serial‑communication peripheral that implements a full‑featured asynchronous transmitter and receiver operating at a fixed 115 200 baud rate. \n\n--- \n\n## Port List \n\n| Direction | Bit‑Width | Signal Name | Purpose |\n|-----------|----------|-------------|------------------------------------------------|\n| Input | 1 | `clk` | System clock (positive‑edge triggered). |\n| Input | 1 | `rst_n` | Asynchronous active‑low reset. |\n| Input | 1 | `tx_load` | Pulse to load new data onto the transmitter. |\n| Input | 8 | `tx_data` | Data byte to be transmitted. |\n| Input | 1 | `rx_valid` | (unused on the input side – kept as a reserved input for future extensions.) |\n| Output | 1 | `txd` | UART transmit line (idles high). |\n| Output | 1 | `rxd` | UART receive line (sampled on positive edges). |\n| Output | 1 | `tx_done` | Pulses high for one clock cycle when the transmitter finishes a frame. |\n| Output | 1 | `rx_error` | Flags overrun/parity/framing error on receive. |\n| Output | 8 | `rx_data` | Received data byte (valid when `rx_valid` is high). |\n\nAll ports are one‑bit wide except where noted; each signal name follows the exact spelling shown above. \n\n--- \n\n## Parameters \n\n| Parameter | Type | Default Value | Meaning / Usage |\n|-----------|------|---------------|-----------------|\n| `DATA_WIDTH` | `int` | `8` | Width of the data bus used for TX and RX payloads. |\n| `SYSTEM_CLK_FREQ` | `int` | `30_000_000` | Frequency of `clk` in Hz. Chosen to enable an exact integer divider for 115 200 baud when `OVERSAMPLE = 16`. |\n| `BAUD_RATE` | `int` | `115200` | Target baud rate (fixed for this instance). |\n| `OVERSAMPLE` | `int` | `16` | Number of samples per bit; standard for UART‑v2. |\n| `DIVIDER_WIDTH` | `int` | `8` | Width of the baud‑rate divider counter. |\n| `FIFO_DEP", "output": "", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'uart_controller_at_115200' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/uart_controller_at_115200/uart_controller_at_115200.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] File Write Error: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.", "source": "agentic_web_build"}
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
{"job_id": "36e08ecb-87b9-41a6-8599-c8ba38188712", "timestamp": 1772030529, "design_name": "8bit_risc_cpu_with", "instruction": "Design a digital chip: 8-bit RISC CPU with Harvard architecture", "input": "\n# 8‑bit RISC CPU – Micro‑Architecture Specification (MAS)\n\n> **Doc.** : 8‑bit_risc_cpu_with – Harvard‑architecture, single‑issue, 2‑stage pipeline \n> **Author** : Chief System Architect – *Your Name* \n> **Date** : 2025‑11‑02 \n> **Version** : 1.0 \n\n--- \n\n## 1. I/O Interface \n\n| Port | Width | Direction | Description | Timing / Control | Reset State |\n|------|-------|-----------|-------------|------------------|--------------|\n| `clk` | 1 | Input | System clock – positive‑edge triggered. | – | Idle (no action) |\n| `rst_n` | 1 | Input | Active‑low asynchronous reset. | – | All registers forced to `0`; PC = `0x00` |\n| `enable` | 1 | Input | Chip‑enable; when `0` the core is put in *sleep* (no state change). | – | Same as reset when disabled |\n| `addr` | 16 | Output | Address bus to **Instruction Memory** (Harvard separate I‑space). | – | Output the current PC value |\n| `data_in` | 8 | Input | Data bus from **Data Memory** (load/store operand). | – | – |\n| `data_out` | 8 | Output | Data bus to **Data Memory** (write operand). | – | – |\n| `we_mem` | 1 | Output | Memory‑Write Enable – asserted when a store instruction is in the MEM stage. | – | `0` (idle) |\n| `re_mem` | 1 | Output | Memory‑Read Enable – asserted when a load instruction is in the MEM stage. | – | `0` (idle) |\n| `irq` | 1 | Input | External interrupt request (level‑triggered). | – | De‑asserted |\n| `irq_ack` | 1 | Output | Interrupt‑acknowledge pulse (generated in the WRITE‑BACK stage). | – | `0` |\n| `ready` | 1 | Output | Indicates the core is ready for a new instruction fetch (pipeline flush not in progress). | – | `1` after reset release |\n\n### Timing Assumptions \n\n* All control signals are **registered** (registered on the rising edge of `clk`). \n* Memory accesses complete **within the same clock cycle** (single‑cycle read/write). \n* Interrupt latency = 1 cycle (acknowledge asserted one cycle after `irq` is seen and pipeline is not stalled). \n\n--- \n\n## 2. Internal Registers & FSM States \n\n#", "output": "module eightbit_risc_cpu_with #(\n parameter ADDR_WIDTH = 16,\n parameter DATA_WIDTH = 8,\n parameter INSTR_DEPTH = 16\n) (\n input logic clk,\n input logic rst_n, // asynchronous active‑low reset\n input logic enable, // chip enable (0 = sleep)\n\n // Instruction address output (to Instruction Memory)\n output logic [ADDR_WIDTH-1:0] addr,\n\n // Data interface to Data Memory\n input logic [DATA_WIDTH-1:0] data_in, // data from Data Memory\n output logic [DATA_WIDTH-1:0] data_out, // data to Data Memory\n output logic we_mem, // memory write enable\n output logic re_mem, // memory read enable\n\n // Interrupt interface\n input logic irq, // external interrupt request (level)\n output logic irq_ack, // interrupt acknowledge pulse\n output logic ready // core ready for new fetch\n);\n\n // -----------------------------------------------------------\n // I/O Policy – No shadowing of ports\n // -----------------------------------------------------------\n // Internal signals – all declared with `logic` (SystemVerilog)\n // -----------------------------------------------------------\n\n // Index width for ROM access\n localparam IDX_W = $clog2(INSTR_DEPTH);\n\n // FSM definition (3‑bit encoding – matches state count)\n typedef enum logic [2:0] {\n S_IDLE = 3'd0,", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for '8bit_risc_cpu_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/8bit_risc_cpu_with/8bit_risc_cpu_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] Hierarchical synthesis planner: disabled.\n[RTL_GEN] Transitioning: RTL_GEN -> RTL_FIX\n[RTL_FIX] Fixing Code (Attempt 1/5)\n[RTL_FIX] Fixing Code (Attempt 2/5)\n[RTL_FIX] Syntax Check Passed (Verilator)\n[RTL_FIX] Lint Check Passed (Verilator)\n[RTL_FIX] Pre-synthesis auto-fix applied.\n[RTL_FIX] Syntax Check Passed (Verilator)\n[RTL_FIX] Lint Check Passed (Verilator)\n[RTL_FIX] Semantic rigor gate failed. Routing back to RTL fix.\n[RTL_FIX] Fixing Code (Attempt 3/5)\n[RTL_FIX] Syntax Check Passed (Verilator)\n[RTL_FIX] Lint Check Passed (Verilator)\n[RTL_FIX] Transitioning: RTL_FIX -> VERIFICATION\n[VERIFICATION] Generating Testbench...\n[VERIFICATION] TB generation stalled/failed (signal only works in main thread of the main interpreter). Using deterministic fallback TB.\n[VERIFICATION] TB static gate: PASS (diag: 8bit_risc_cpu_with_tb_static_gate_attempt1.json)\n[VERIFICATION] TB compile gate: FAIL (diag: 8bit_risc_cpu_with_tb_compile_gate_attempt1.json)\n[VERIFICATION] Verifying with existing Testbench (Attempt 0).\n[VERIFICATION] TB static gate: FAIL (diag: 8bit_risc_cpu_with_tb_static_gate_attempt2.json)\n[VERIFICATION] TB gate failed; applied deterministic auto-repair.\n[VERIFICATION] Verifying with existing Testbench (Attempt 0).\n[VERIFICATION] TB static gate: FAIL (diag: 8bit_risc_cpu_with_tb_static_gate_attempt3.json)\n[VERIFICATION] TB gate failed; forcing LLM TB regeneration with structured diagnostics.\n[VERIFICATION] Generating Testbench...\n[VERIFICATION] TB generation stalled/failed (signal only works in main thread of the main interpreter). Using deterministic fallback TB.\n[VERIFICATION] TB static gate: PASS (diag: 8bit_risc_cpu_with_tb_static_gate_attempt4.json)\n[VERIFICATION] TB compile gate: FAIL (diag: 8bit_risc_cpu_with_tb_compile_gate_attempt2.json)\n[VERIFICATION] Repeated TB compile fingerprint detected. Failing closed.", "source": "agentic_web_build"}
|
| 76 |
{"job_id": "05223be4-69db-4e20-85c3-07c4038f0b42", "timestamp": 1772031476, "design_name": "axi4_dma_engine_with", "instruction": "Design a digital chip: AXI4 DMA engine with 4 channels", "input": "\n# **## Module: axi4_dma_engine_with**\n\nThe RTL entity that implements a **four‑channel AXI‑4 master‑side DMA engine**. The top‑level module name **must** be `axi4_dma_engine_with`. All ports, parameters, and internal blocks are defined to support a production‑ready AXI‑4 compliant DMA engine suitable for integration into an SoC.\n\n---\n\n# **## Chip Family** \n**AXI** – The device belongs to the AXI‑4 interconnect family (AXI4‑Stream/AXI4‑Lite/AXI4‑Full). It provides a high‑performance memory transfer subsystem by bridging the AXI master interface to internal descriptor‑based channels.\n\n---\n\n# **## Port List**\n\n| Port | Direction | Bits | Name | Purpose |\n|------|-----------|------|------|---------|\n| `clk` | Input | 1 | Clock | System clock for all logic (positive‑edge triggered). |\n| `rst_n` | Input | 1 | Asynchronous active‑low reset | Global reset; clears all state machines, registers, and FIFO pointers. |\n| **AXI‑Master Interface** |\n| `awaddr` | Output | `ADDR_WIDTH` | Address Write Channel address |\n| `awvalid` | Output | 1 | Write address valid |\n| `awready` | Input | 1 | Write address ready |\n| `wdata` | Output | `DATA_WIDTH` | Write data payload |\n| `wstrb` | Output | `DATA_WIDTH/8` | Byte lane strobes |\n| `wvalid` | Output | 1 | Write data valid |\n| `wready` | Input | 1 | Write data ready |\n| `bresp` | Output | 2 | Write response (OKAY, SLVERR, etc.) |\n| `bvalid` | Output | 1 | Write response valid |\n| `bready` | Input | 1 | Write response ready |\n| `araddr` | Output | `ADDR_WIDTH` | Read address channel address |\n| `arvalid` | Output | 1 | Read address valid |\n| `arready` | Input | 1 | Read address ready |\n| `rdata` | Input | `DATA_WIDTH` | Read data returned |\n| `rresp` | Input | 2 | Read response |\n| `rvalid` | Input | 1 | Read data valid |\n| `rready` | Output | 1 | Read data ready |\n| **DMA Control & Status** |\n| `ch0_cfg` | Input | `CH_CFG_BITS` | Channel‑0 configuration (enable, direction, burst, etc.) |\n| `ch1_cfg` | Input | `CH_CFG_BITS` | Channel‑1", "output": "module axi4_dma_engine_with #(\n // -----------------------------------------------------------------\n // Parameters (all have default values as specified in the spec)\n // -----------------------------------------------------------------\n parameter int DATA_WIDTH = 32; // AXI data bus width\n parameter int ADDR_WIDTH = 32; // AXI address bus width\n parameter int NUM_CH = 4; // Number of DMA channels\n parameter int CH_CFG_BITS = 8; // Config register width per channel\n parameter int DESC_BITS = 16; // Width of descriptor address pointer\n parameter int DESC_COUNT_MAX = 1024; // Max descriptors per channel\n parameter int FIFO_DEPTH = 8; // Depth of per‑channel descriptor FIFO\n parameter string RESET_STYLE = \"SYNC\"; // \"SYNC\" or \"ASYNC\"\n parameter string INTERFACE_STYLE = \"AXI4_FULL\"; // Enforces full handshake\n parameter logic SUPPORTS_BURST = 1'b1; // Enable burst transfers\n parameter int MAX_BURST_LEN = 16; // Max beats per burst\n parameter string ERROR_POLICY = \"HALT_AND_REPORT\" // Error handling policy\n)(\n // -----------------------------------------------------------------\n // Clock and asynchronous active‑low reset\n // -----------------------------------------------------------------\n input logic clk,\n input logic ", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'axi4_dma_engine_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/axi4_dma_engine_with/axi4_dma_engine_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] Hierarchical synthesis planner: disabled.\n[RTL_GEN] Transitioning: RTL_GEN -> RTL_FIX\n[RTL_FIX] Fixing Code (Attempt 1/5)\n[RTL_FIX] File Write Error in FIX stage: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.\n[RTL_FIX] Retrying fix (LLM output was unparsable).\n[RTL_FIX] Detected repeated syntax/lint failure fingerprint. Failing closed.", "source": "agentic_web_build"}
|
| 77 |
{"job_id": "aefbc11b-69f4-4d60-842d-6691200babda", "timestamp": 1772031756, "design_name": "uart_controller_at_115200", "instruction": "Design a digital chip: UART controller at 115200 baud", "input": "\n## Module: uart_controller_at_115200 \n\n## Chip Family \n**UART** – a classic serial‑communication peripheral that implements a full‑featured asynchronous transmitter and receiver operating at a fixed 115 200 baud rate. \n\n--- \n\n## Port List \n\n| Direction | Bit‑Width | Signal Name | Purpose |\n|-----------|----------|-------------|------------------------------------------------|\n| Input | 1 | `clk` | System clock (positive‑edge triggered). |\n| Input | 1 | `rst_n` | Asynchronous active‑low reset. |\n| Input | 1 | `tx_load` | Pulse to load new data onto the transmitter. |\n| Input | 8 | `tx_data` | Data byte to be transmitted. |\n| Input | 1 | `rx_valid` | (unused on the input side – kept as a reserved input for future extensions.) |\n| Output | 1 | `txd` | UART transmit line (idles high). |\n| Output | 1 | `rxd` | UART receive line (sampled on positive edges). |\n| Output | 1 | `tx_done` | Pulses high for one clock cycle when the transmitter finishes a frame. |\n| Output | 1 | `rx_error` | Flags overrun/parity/framing error on receive. |\n| Output | 8 | `rx_data` | Received data byte (valid when `rx_valid` is high). |\n\nAll ports are one‑bit wide except where noted; each signal name follows the exact spelling shown above. \n\n--- \n\n## Parameters \n\n| Parameter | Type | Default Value | Meaning / Usage |\n|-----------|------|---------------|-----------------|\n| `DATA_WIDTH` | `int` | `8` | Width of the data bus used for TX and RX payloads. |\n| `SYSTEM_CLK_FREQ` | `int` | `30_000_000` | Frequency of `clk` in Hz. Chosen to enable an exact integer divider for 115 200 baud when `OVERSAMPLE = 16`. |\n| `BAUD_RATE` | `int` | `115200` | Target baud rate (fixed for this instance). |\n| `OVERSAMPLE` | `int` | `16` | Number of samples per bit; standard for UART‑v2. |\n| `DIVIDER_WIDTH` | `int` | `8` | Width of the baud‑rate divider counter. |\n| `FIFO_DEP", "output": "", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'uart_controller_at_115200' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/uart_controller_at_115200/uart_controller_at_115200.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] File Write Error: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.", "source": "agentic_web_build"}
|
| 78 |
+
{"job_id": "7b3059c5-022e-42a4-a082-c0c0f0f0bf23", "timestamp": 1772035035, "design_name": "axi4_dma_engine_with", "instruction": "Design a digital chip: AXI4 DMA engine with 4 channels", "input": "\n## Module: axi4_dma_engine_with \n\n--- \n\n## Chip Family \n**AXI4 DMA Engine** – a multi‑channel, AXI‑4 compliant Direct Memory Access engine. The core is an AXI master that can initiate independent read and write transactions on each of four channels. \n\n--- \n\n## Port List \n\n| Port | Direction | Bit‑Width | Purpose |\n|------|-----------|-----------|---------|\n| `clk` | Input | 1 | System clock. |\n| `rst_n` | Input | 1 | Asynchronous active‑low reset. |\n| `start_i` | Input | 4 | Start transaction for each of the 4 channels. |\n| `stop_i` | Input | 4 | Abort transaction for each of the 4 channels. |\n| `done_o` | Output | 4 | Transaction‑complete flag per channel. |\n| `err_o` | Output | 4 | Error flag per channel (decode or timeout). |\n| **AXI‑4 Master Interface** (shared by all channels) | | | |\n| `axi_awaddr` | Input | 32 | Address for Write (AW) channel. |\n| `axi_awvalid` | Input | 1 | Valid signal for write address. |\n| `axi_awready` | Output | 1 | Ready to accept write address. |\n| `axi_wdata` | Input | 32 | Write data bus. |\n| `axi_wstrb` | Input | 4 | Byte‑lane strobe (1‑bit per 8‑bit). |\n| `axi_wlast` | Input | 1 | Last beat of a burst. |\n| `axi_wvalid` | Output | 1 | Valid signal for write data. |\n| `axi_wready` | Input | 1 | Ready to accept write data. |\n| `axi_bresp` | Output | 2 | Write response (OKAY, SLVERR, DECERR). |\n| `axi_bvalid` | Output | 1 | Valid response on write channel. |\n| `axi_bready` | Input | 1 | Ready to accept write response. |\n| `axi_araddr` | Input | 32 | Address for Read (AR) channel. |\n| `axi_arvalid` | Input | 1 | Valid signal for read address. |\n| `axi_arready` | Output | 1 | Ready to accept read address. |\n| `axi_rdata` | Output | 32 | Read data bus. |\n| `axi_rresp` | Output | 2 | Read response. |\n| `axi_rvalid` | Output | 1 | Valid signal for read data. |\n| `axi_rready` | Input | 1 | Ready to accept read data. |\n| `irq_o` | Output | 1 | Interrupt request to host (active‑high). |\n\n*All AXI‑4 signals are **shared** among the f", "output": "`timescale 1ns / 1psmodule name matches spec: axi4_dma_engine_with\n * -------------------------------------------------------\n * Features:\n * – 4 independent AXI‑4 master channels\n * – Start/Stop control per channel\n * – Simple descriptor fetch (addr, length, flags)\n * – Write‑burst up to MAX_BURST_LEN beats\n * – Write‑response checking (b.resp == OKAY)\n * – Completion interrupt (irq_o)\n * – Asynchronous active‑low reset (rst_n)\n * – All parameters are configurable via parameters below\n * – Production‑ready coding style (always_ff, logic, enum, no placeholders)\n ******************************************************************************************/\n\nmodule axi4_dma_engine_with #(\n parameter int DATA_WIDTH = 32,\n parameter int ADDR_WIDTH = 32,\n parameter int NUM_CHANNELS = 4,\n parameter int MAX_BURST_LEN = 16,\n parameter int DESCRIPTOR_DEPTH = 1024,\n parameter int RESET_SYNC = 0, // 0 = async reset, 1 = sync reset\n parameter string INITIAL_FSM_STATE = \"IDLE\"\n) (\n // System & Reset\n input logic clk,\n input logic rst_n, // async active‑low\n\n // Channel Control Interface\n input logic [NUM_CHANNELS-1:0] start_i,\n input logic [NUM_CHANNELS-1:0] stop_i,\n output logic [NUM_CHANNELS-1:0] done_o,\n output logic [NUM_CHANNELS-1:0] err_o,\n\n // Shared AXI‑4 Master Interface\n output logic [ADDR_WIDTH-1:0] axi_aw", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'axi4_dma_engine_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/axi4_dma_engine_with/axi4_dma_engine_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] Hierarchical synthesis planner: disabled.\n[RTL_GEN] Transitioning: RTL_GEN -> RTL_FIX\n[RTL_FIX] Fixing Code (Attempt 1/5)\n[RTL_FIX] File Write Error in FIX stage: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.\n[RTL_FIX] Retrying fix (LLM output was unparsable).\n[RTL_FIX] Detected repeated syntax/lint failure fingerprint. Failing closed.", "source": "agentic_web_build"}
|
| 79 |
+
{"job_id": "f6dc0268-20c7-4291-97b9-187e908e324c", "timestamp": 1772036669, "design_name": "axi4_dma_engine_with", "instruction": "Design a digital chip: AXI4 DMA engine with 4 channels", "input": "\n## Module: axi4_dma_engine_with \n\n## Chip Family \n**AXI4‑DMA Engine** – A high‑performance, AXI‑4‑stream‑compatible Direct‑Memory Access controller. \nThe core belongs to the **AXI peripheral** family; it implements a multi‑channel, AXI‑4 master/target datapath surrounding a compact state‑machine that services four independent DMA channels.\n\n--- \n\n## Port List \n\n| Port Name | Direction | Bit‑Width | Purpose |\n|-----------|-----------|-----------|---------|\n| `clk` | Input | 1 | System clock. All synchronous logic samples on the rising edge. |\n| `rst_n` | Input | 1 | Asynchronous active‑low reset. When asserted the entire engine goes to the **IDLE** reset state. |\n| `axi_araddr` | Input | `ADDR_WIDTH` | Address channel (read) address bus. |\n| `axi_arvalid` | Input | 1 | Valid signal for a read address transaction. |\n| `axi_arready` | Output | 1 | Ready signal for a read address transaction. |\n| `axi_rdata` | Output | `DATA_WIDTH` | Read data returned by the AXI slave. |\n| `axi_rresp` | Output | 2 | Response code for the read transaction (OKAY, SLVERR, etc.). |\n| `axi_rvalid` | Output | 1 | Valid signal indicating that `axi_rdata`/`axi_rresp` are meaningful. |\n| `axi_rready` | Input | 1 | Ready signal for the read data channel. |\n| `axi_awaddr` | Input | `ADDR_WIDTH` | Address channel (write) address bus. |\n| `axi_awvalid` | Input | 1 | Valid signal for a write address transaction. |\n| `axi_awready` | Output | 1 | Ready signal for a write address transaction. |\n| `axi_wdata` | Input | `DATA_WIDTH` | Write data bus supplied by the master. |\n| `axi_wstrb` | Input | `DATA_BYTES` (`DATA_WIDTH/8`) | Byte‑lane strobe signals. |\n| `axi_wvalid` | Input | 1 | Valid signal indicating that `axi_wdata`/`axi_wstrb` are driven. |\n| `axi_wready` | Output | 1 | Ready signal for the write data channel. |\n| `axi_bresp` | Output | 2 | Response code for a write‐back transaction. |\n| `axi_bvalid` | Output | 1 | Valid signal indicating that `axi_bresp` is available. |\n| `axi_bready` |", "output": "", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'axi4_dma_engine_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/axi4_dma_engine_with/axi4_dma_engine_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] File Write Error: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.", "source": "agentic_web_build"}
|
| 80 |
+
{"job_id": "3772ce69-1eb1-4fd7-9786-7bd93c1a0e28", "timestamp": 1772037059, "design_name": "axi4_dma_engine_with", "instruction": "Design a digital chip: AXI4 DMA engine with 4 channels", "input": "\n## Module: axi4_dma_engine_with \n\n## Chip Family \n**AXI** – This block is a dedicated AXI‑4 peripheral that implements a multi‑channel Direct Memory Access (DMA) engine. It is classified under the AXI family because its primary purpose is to act as an AXI‑4 slave that coordinates memory transfers on behalf of other system masters, while exposing a fully‑featured AXI‑4 interface for configuration and status.\n\n---\n\n## Port List \n\n| Direction | Name | Width | Purpose |\n|-----------|---------------------|-------|------------------------------------------------------------|\n| Input | `aclk` | 1 | System clock for the DMA engine (single‑cycle synchronous logic). |\n| Input | `aresetn` | 1 | Active‑low asynchronous reset for all logic. |\n| Input | `s_axi_awaddr` | 32 | Address for AXI write‑address channel. |\n| Input | `s_axi_awvalid` | 1 | Valid signal for write‑address channel. |\n| Output | `s_axi_awready` | 1 | Ready signal for write‑address channel. |\n| Input | `s_axi_wdata` | 32 | Write data bus. |\n| Input | `s_axi_wstrb` | 4 | Byte‑lane strobe for write data (byte‑enable). |\n| Input | `s_axi_wvalid` | 1 | Valid signal for write‑data channel. |\n| Output | `s_axi_wready` | 1 | Ready signal for write‑data channel. |\n| Output | `s_axi_bresp` | 2 | Response for write‑address/write data completion. |\n| Output | `s_axi_bvalid` | 1 | Valid signal for write‑response channel. |\n| Input | `s_axi_bready` | 1 | Ready signal for write‑response channel. |\n| Input | `s_axi_araddr` | 32 | Address for AXI read‑address channel. |\n| Input | `s_axi_arvalid` | 1 | Valid signal for read‑address channel. |\n| Output | `s_axi_arready` | 1 | Ready signal for read‑address channel. |\n| Output | `s_axi_rdata` | 32 | Read data returned to the AXI master. |\n", "output": "", "success": false, "strategy": "SystemVerilog Modular (Modern)", "metrics": {}, "coverage": {}, "build_log_excerpt": "[INIT] Starting Build Process for 'axi4_dma_engine_with' using SystemVerilog Modular (Modern)\n[INIT] Logging initialized to /home/vickynishad/OpenLane/designs/axi4_dma_engine_with/axi4_dma_engine_with.log\n[INIT] PDK profile: sky130 (PDK=sky130A, LIB=sky130_fd_sc_hd)\n[INIT] Transitioning: INIT -> SPEC\n[SPEC] Architecture Plan Generated\n[SPEC] Transitioning: SPEC -> RTL_GEN\n[RTL_GEN] No golden template match. Generating from scratch.\n[RTL_GEN] File Write Error: Error: No Verilog 'module' definition found in the provided code. Please ensure you output the full Verilog code inside ```verilog``` fences.", "source": "agentic_web_build"}
|
web/src/App.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import
|
| 2 |
import axios from 'axios';
|
| 3 |
import { Canvas } from '@react-three/fiber';
|
| 4 |
import { Chip3D } from './components/Chip3D';
|
|
@@ -14,7 +14,8 @@ const App = () => {
|
|
| 14 |
const [selectedDesign, setSelectedDesign] = useState<string>('');
|
| 15 |
|
| 16 |
useEffect(() => {
|
| 17 |
-
|
|
|
|
| 18 |
.then(res => {
|
| 19 |
const data = res.data.designs;
|
| 20 |
setDesigns(data);
|
|
|
|
| 1 |
+
import { useState, useEffect, Suspense } from 'react';
|
| 2 |
import axios from 'axios';
|
| 3 |
import { Canvas } from '@react-three/fiber';
|
| 4 |
import { Chip3D } from './components/Chip3D';
|
|
|
|
| 14 |
const [selectedDesign, setSelectedDesign] = useState<string>('');
|
| 15 |
|
| 16 |
useEffect(() => {
|
| 17 |
+
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000';
|
| 18 |
+
axios.get(`${API_BASE_URL}/designs`)
|
| 19 |
.then(res => {
|
| 20 |
const data = res.data.designs;
|
| 21 |
setDesigns(data);
|
web/src/components/BuildMonitor.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
|
|
| 2 |
import { motion } from 'framer-motion';
|
| 3 |
import axios from 'axios';
|
| 4 |
|
| 5 |
-
const API = 'http://localhost:8000';
|
| 6 |
|
| 7 |
const STATES_DISPLAY: Record<string, { label: string; icon: string }> = {
|
| 8 |
INIT: { label: 'Initializing Workspace', icon: '🔧' },
|
|
|
|
| 2 |
import { motion } from 'framer-motion';
|
| 3 |
import axios from 'axios';
|
| 4 |
|
| 5 |
+
const API = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000';
|
| 6 |
|
| 7 |
const STATES_DISPLAY: Record<string, { label: string; icon: string }> = {
|
| 8 |
INIT: { label: 'Initializing Workspace', icon: '🔧' },
|
web/src/components/Chip3D.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import
|
| 2 |
import { useFrame } from '@react-three/fiber';
|
| 3 |
import { Float, Box, Edges } from '@react-three/drei';
|
| 4 |
import * as THREE from 'three';
|
|
@@ -29,12 +29,12 @@ export const Chip3D = () => {
|
|
| 29 |
|
| 30 |
{/* Top Active Matrix - Glowing */}
|
| 31 |
<Box args={[2.5, 0.2, 2.5]} position={[0, 0, 0]}>
|
| 32 |
-
<meshStandardMaterial
|
| 33 |
-
color="#00FF88"
|
| 34 |
emissive="#00FF88"
|
| 35 |
emissiveIntensity={0.5}
|
| 36 |
-
roughness={0.2}
|
| 37 |
-
metalness={0.8}
|
| 38 |
/>
|
| 39 |
<Edges color="#fff" />
|
| 40 |
</Box>
|
|
|
|
| 1 |
+
import { useRef } from 'react';
|
| 2 |
import { useFrame } from '@react-three/fiber';
|
| 3 |
import { Float, Box, Edges } from '@react-three/drei';
|
| 4 |
import * as THREE from 'three';
|
|
|
|
| 29 |
|
| 30 |
{/* Top Active Matrix - Glowing */}
|
| 31 |
<Box args={[2.5, 0.2, 2.5]} position={[0, 0, 0]}>
|
| 32 |
+
<meshStandardMaterial
|
| 33 |
+
color="#00FF88"
|
| 34 |
emissive="#00FF88"
|
| 35 |
emissiveIntensity={0.5}
|
| 36 |
+
roughness={0.2}
|
| 37 |
+
metalness={0.8}
|
| 38 |
/>
|
| 39 |
<Edges color="#fff" />
|
| 40 |
</Box>
|
web/src/pages/Dashboard.tsx
CHANGED
|
@@ -17,20 +17,21 @@ export const Dashboard: React.FC<DashboardProps> = ({ selectedDesign }) => {
|
|
| 17 |
setLoading(true);
|
| 18 |
|
| 19 |
// Fetch Quick Metrics
|
| 20 |
-
|
|
|
|
| 21 |
.then(res => {
|
| 22 |
if (res.data.metrics) setMetrics(res.data.metrics);
|
| 23 |
})
|
| 24 |
-
.catch(
|
| 25 |
setMetrics({ wns: 'N/A', power: 'N/A', area: 'N/A', gate_count: 'N/A' });
|
| 26 |
});
|
| 27 |
|
| 28 |
// Fetch Full LLM Signoff Report
|
| 29 |
-
axios.get(`
|
| 30 |
.then(res => {
|
| 31 |
setSignoffData({ report: res.data.report, pass: res.data.success });
|
| 32 |
})
|
| 33 |
-
.catch(
|
| 34 |
setSignoffData({ report: 'Failed to retrieve Signoff Report. Has the device been fully hardened via OpenLane yet?', pass: false });
|
| 35 |
})
|
| 36 |
.finally(() => setLoading(false));
|
|
|
|
| 17 |
setLoading(true);
|
| 18 |
|
| 19 |
// Fetch Quick Metrics
|
| 20 |
+
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000';
|
| 21 |
+
axios.get(`${API_BASE_URL}/metrics/${selectedDesign}`)
|
| 22 |
.then(res => {
|
| 23 |
if (res.data.metrics) setMetrics(res.data.metrics);
|
| 24 |
})
|
| 25 |
+
.catch(() => {
|
| 26 |
setMetrics({ wns: 'N/A', power: 'N/A', area: 'N/A', gate_count: 'N/A' });
|
| 27 |
});
|
| 28 |
|
| 29 |
// Fetch Full LLM Signoff Report
|
| 30 |
+
axios.get(`${API_BASE_URL}/signoff/${selectedDesign}`)
|
| 31 |
.then(res => {
|
| 32 |
setSignoffData({ report: res.data.report, pass: res.data.success });
|
| 33 |
})
|
| 34 |
+
.catch(() => {
|
| 35 |
setSignoffData({ report: 'Failed to retrieve Signoff Report. Has the device been fully hardened via OpenLane yet?', pass: false });
|
| 36 |
})
|
| 37 |
.finally(() => setLoading(false));
|
web/src/pages/DesignStudio.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
-
import
|
| 2 |
import { motion, AnimatePresence } from 'framer-motion';
|
| 3 |
import axios from 'axios';
|
| 4 |
import { BuildMonitor } from '../components/BuildMonitor';
|
| 5 |
import { ChipSummary } from '../components/ChipSummary';
|
| 6 |
|
| 7 |
-
const API = 'http://localhost:8000';
|
| 8 |
|
| 9 |
type Phase = 'prompt' | 'building' | 'done';
|
| 10 |
|
|
|
|
| 1 |
+
import { useState, useEffect, useRef } from 'react';
|
| 2 |
import { motion, AnimatePresence } from 'framer-motion';
|
| 3 |
import axios from 'axios';
|
| 4 |
import { BuildMonitor } from '../components/BuildMonitor';
|
| 5 |
import { ChipSummary } from '../components/ChipSummary';
|
| 6 |
|
| 7 |
+
const API = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000';
|
| 8 |
|
| 9 |
type Phase = 'prompt' | 'building' | 'done';
|
| 10 |
|