背景
在数字后端设计中,我们经常需要从各种 EDA 工具输出中提取数据、生成报告。Python 是进行这项工作的理想选择。
基础:解析时序报告
提取 WNS/TNS
#!/usr/bin/env python3
import re
import argparse
from pathlib import Path
def parse_timing_report(report_file: str) -> dict:
"""解析时序报告"""
with open(report_file, 'r') as f:
content = f.read()
# 提取 WNS
wns_match = re.search(r'wns\s*=\s*([-\d.]+)', content, re.IGNORECASE)
wns = float(wns_match.group(1)) if wns_match else None
# 提取 TNS
tns_match = re.search(r'tns\s*=\s*([-\d.]+)', content, re.IGNORECASE)
tns = float(tns_match.group(1)) if tns_match else None
return {'wns': wns, 'tns': tns}
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('report', help='Timing report file')
args = parser.parse_args()
result = parse_timing_report(args.report)
print(f"WNS: {result['wns']}")
print(f"TNS: {result['tns']}")
中级:批量处理
批量解析目录中的报告
#!/usr/bin/env python3
import os
import json
from pathlib import Path
from parse_timing_report import parse_timing_report
def batch_process_reports(report_dir: str) -> list:
"""批量处理时序报告"""
results = []
for root, _, files in os.walk(report_dir):
for file in files:
if file.endswith('.rpt') or file.endswith('.timing'):
filepath = Path(root) / file
try:
result = parse_timing_report(str(filepath))
result['file'] = str(filepath)
result['status'] = 'pass' if result['wns'] >= 0 else 'fail'
results.append(result)
except Exception as e:
print(f"Error processing {filepath}: {e}")
return results
def generate_summary(results: list) -> dict:
"""生成汇总统计"""
passed = sum(1 for r in results if r['status'] == 'pass')
failed = sum(1 for r in results if r['status'] == 'fail')
wns_values = [r['wns'] for r in results if r['wns'] is not None]
return {
'total': len(results),
'passed': passed,
'failed': failed,
'worst_wns': min(wns_values) if wns_values else None,
'best_wns': max(wns_values) if wns_values else None,
}
if __name__ == '__main__':
results = batch_process_reports('./reports/timing')
summary = generate_summary(results)
print(json.dumps(summary, indent=2))
高级:生成 HTML 报告
创建可视化报告
#!/usr/bin/env python3
import json
from datetime import datetime
def generate_html_report(summary: dict, details: list) -> str:
"""生成 HTML 报告"""
status_color = {
'pass': '#00D9A6',
'fail': '#FF6B4A',
}
rows = ''
for item in details:
color = status_color[item['status']]
rows += f"""
<tr>
<td>{item['file']}</td>
<td style="color: {color}">{item['wns']}</td>
<td style="color: {color}">{item['tns']}</td>
<td style="color: {color}">{item['status'].upper()}</td>
</tr>
"""
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Timing Report - {datetime.now().strftime('%Y-%m-%d')}</title>
<style>
body {{
font-family: Inter, system-ui, sans-serif;
background: #0C0E14;
color: #E8ECF4;
padding: 2rem;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid #2A3142;
}}
th {{
background: #141820;
}}
</style>
</head>
<body>
<h1>时序报告汇总</h1>
<p>生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<h2>统计信息</h2>
<ul>
<li>总计: {summary['total']}</li>
<li>通过: {summary['passed']}</li>
<li>失败: {summary['failed']}</li>
<li>最差 WNS: {summary.get('worst_wns', 'N/A')}</li>
</ul>
<h2>详细结果</h2>
<table>
<thead>
<tr>
<th>文件</th>
<th>WNS (ns)</th>
<th>TNS (ns)</th>
<th>状态</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
</body>
</html>
"""
return html
if __name__ == '__main__':
with open('summary.json') as f:
summary = json.load(f)
with open('details.json') as f:
details = json.load(f)
html = generate_html_report(summary, details)
with open('timing_report.html', 'w') as f:
f.write(html)
print("Report generated: timing_report.html")
使用方法
# 1. 批量处理时序报告
python batch_process_reports.py ./reports/timing > summary.json
# 2. 生成详情 JSON
python batch_process_reports.py ./reports/timing --json > details.json
# 3. 生成 HTML 报告
python generate_html_report.py
扩展建议
- 添加图表(使用 Chart.js)
- 支持邮件发送
- 集成 CI/CD 流程
- 添加趋势分析
总结
Python 脚本可以大大提高后端设计的效率,特别是对于重复性的报告生成工作。