read_openlane_reports
Extract and analyze OpenLane report files to examine PPA metrics, timing, routing quality, and design results for LLM-based assessment.
Instructions
Read OpenLane report files for LLM analysis. Returns all reports or specific category for detailed analysis of PPA metrics, timing, routing quality, and other design results.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | Project ID from OpenLane run | |
| report_type | No | Specific report category to read (synthesis, placement, routing, final, etc.). Leave empty to read all reports. |
Implementation Reference
- src/index.ts:584-709 (handler)The core handler function in EDAServer class that implements the read_openlane_reports tool. It locates the latest OpenLane run for the project, reads key report files (synthesis stats, timing reports, final summary), parses PPA metrics like cell count and timing slack, assesses design status, and returns structured JSON with excerpts and analysis.async readOpenlaneReports(projectId: string, reportType?: string): Promise<string> { try { const project = this.projects.get(projectId); if (!project) { return JSON.stringify({ success: false, error: `Project ${projectId} not found.`, }, null, 2); } const runsDir = join(project.dir, "runs"); let latestRun = ""; try { const runs = await fs.readdir(runsDir); if (runs.length === 0) { return JSON.stringify({ success: false, error: "No OpenLane runs found. Run OpenLane flow first.", }, null, 2); } latestRun = runs.sort().reverse()[0]; } catch { return JSON.stringify({ success: false, error: "No runs directory found. Run OpenLane flow first.", }, null, 2); } const reportsDir = join(project.dir, "runs", latestRun, "reports"); const finalDir = join(project.dir, "runs", latestRun, "final"); // Simple results object const results: any = { project_id: projectId, run_id: latestRun, success: true, ppa_metrics: { power_mw: null, max_frequency_mhz: null, total_cells: null, logic_area_um2: null, timing_slack_ns: null }, design_status: { synthesis_complete: false, timing_clean: false, routing_complete: false }, reports: {} }; // Helper to safely read file const readFile = async (path: string) => { try { return await fs.readFile(path, 'utf8'); } catch { return null; } }; // Read synthesis report const synthReport = await readFile(join(reportsDir, "synthesis", "1-synthesis.stat.rpt")); if (synthReport) { results.design_status.synthesis_complete = true; results.reports.synthesis = synthReport.substring(0, 2000); const cellMatch = synthReport.match(/Number of cells:\s*(\d+)/); if (cellMatch) { results.ppa_metrics.total_cells = parseInt(cellMatch[1]); } } // Read timing report try { const routingDir = join(reportsDir, "routing"); const files = await fs.readdir(routingDir); for (const file of files) { if (file.includes('sta') || file.includes('timing')) { const timingReport = await readFile(join(routingDir, file)); if (timingReport) { results.reports.timing = timingReport.substring(0, 2000); const wnsMatch = timingReport.match(/WNS.*?(-?\d+\.?\d*)/i); if (wnsMatch) { const wns = parseFloat(wnsMatch[1]); results.ppa_metrics.timing_slack_ns = wns; results.design_status.timing_clean = wns >= 0; } break; } } } } catch { // Timing reports not available } // Read final summary if available const finalSummary = await readFile(join(finalDir, "final.summary.rpt")); if (finalSummary) { results.reports.final_summary = finalSummary.substring(0, 3000); results.design_status.routing_complete = true; } // Add analysis summary const issues = []; if (!results.design_status.synthesis_complete) issues.push("Synthesis incomplete"); if (!results.design_status.timing_clean) issues.push("Timing violations detected"); if (!results.design_status.routing_complete) issues.push("Routing incomplete"); results.summary = { status: issues.length === 0 ? "SUCCESS" : "ISSUES_FOUND", issues: issues, note: "PPA metrics and design status extracted from OpenLane reports" }; return JSON.stringify(results, null, 2); } catch (error: any) { return JSON.stringify({ success: false, error: error.message || String(error), }, null, 2); } }
- src/index.ts:843-856 (schema)Input schema for the read_openlane_reports tool, defining required 'project_id' and optional 'report_type' parameters.type: "object", properties: { project_id: { type: "string", description: "Project ID from OpenLane run" }, report_type: { type: "string", description: "Specific report category to read (synthesis, placement, routing, final, etc.). Leave empty to read all reports.", default: "" }, }, required: ["project_id"], },
- src/index.ts:840-857 (registration)Tool registration in the ListTools response, defining name, description, and input schema.name: "read_openlane_reports", description: "Read OpenLane report files for LLM analysis. Returns all reports or specific category for detailed analysis of PPA metrics, timing, routing quality, and other design results.", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID from OpenLane run" }, report_type: { type: "string", description: "Specific report category to read (synthesis, placement, routing, final, etc.). Leave empty to read all reports.", default: "" }, }, required: ["project_id"], }, },
- src/index.ts:929-939 (registration)Dispatcher case in CallToolRequestHandler that validates parameters and invokes the readOpenlaneReports handler.case "read_openlane_reports": { const projectId = validateRequiredString(args, "project_id", name); const reportType = getStringProperty(args, "report_type", ""); return { content: [{ type: "text", text: await edaServer.readOpenlaneReports(projectId, reportType || undefined), }], }; }