新增功能: - waveformTracer.ts: 调用 waveform_trace.exe 的工具实现 - toolExecutor.ts: 添加 waveform_trace 工具分发 - types/api.ts: 添加 WaveformTraceArgs 类型定义 工具源码 (tools/waveform_trace/src/): - AST 解析 + BFS 信号追踪 - VCD 波形解析 - 修复通用 testbench 支持 配置文件: - .gitignore: 排除 exe 和打包产物 - .vscodeignore: 发布时排除源码 - build.bat/build.sh: 打包脚本
150 lines
4.5 KiB
Python
150 lines
4.5 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
waveform_trace CLI 入口
|
||
用于 PyInstaller 打包成独立可执行文件
|
||
|
||
使用方式:
|
||
waveform_trace --verilog <path> --vcd <path> --sim-output <text> [--trace-level <int>] [--output-format text|json]
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
import builtins
|
||
|
||
# Monkey-patch open 函数,强制使用 UTF-8 编码(解决 pyverilog 读取中文注释的问题)
|
||
_original_open = builtins.open
|
||
def _utf8_open(file, mode='r', *args, **kwargs):
|
||
if 'b' not in mode and 'encoding' not in kwargs:
|
||
kwargs['encoding'] = 'utf-8'
|
||
kwargs.setdefault('errors', 'replace')
|
||
return _original_open(file, mode, *args, **kwargs)
|
||
builtins.open = _utf8_open
|
||
|
||
if sys.platform == 'win32':
|
||
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
||
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
|
||
|
||
import argparse
|
||
import json
|
||
|
||
# 添加当前目录到路径(打包后需要)
|
||
if getattr(sys, 'frozen', False):
|
||
# 如果是打包后的可执行文件
|
||
application_path = os.path.dirname(sys.executable)
|
||
else:
|
||
# 如果是直接运行的脚本
|
||
application_path = os.path.dirname(os.path.abspath(__file__))
|
||
|
||
sys.path.insert(0, application_path)
|
||
|
||
from waveform_trace_tool import WaveformTracer
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(
|
||
description='Verilog 波形追踪工具 - 通过 AST + BFS 追踪信号依赖,定位代码问题',
|
||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||
epilog='''
|
||
示例:
|
||
waveform_trace --verilog src/counter.v --vcd output/wave.vcd --sim-output "Mismatches: 3"
|
||
waveform_trace --verilog src/counter.v --vcd output/wave.vcd --sim-output "Mismatches: 3" --trace-level 3
|
||
waveform_trace --verilog src/counter.v --vcd output/wave.vcd --sim-output "Mismatches: 3" --output-format json
|
||
'''
|
||
)
|
||
|
||
parser.add_argument(
|
||
'--verilog',
|
||
required=True,
|
||
help='Verilog 源文件路径'
|
||
)
|
||
parser.add_argument(
|
||
'--vcd',
|
||
required=True,
|
||
help='VCD 波形文件路径'
|
||
)
|
||
parser.add_argument(
|
||
'--sim-output',
|
||
required=True,
|
||
help='仿真工具的输出字符串(必须包含 mismatch 信息)'
|
||
)
|
||
parser.add_argument(
|
||
'--trace-level',
|
||
type=int,
|
||
default=2,
|
||
help='BFS 回溯层数,默认 2,建议 2-5'
|
||
)
|
||
parser.add_argument(
|
||
'--output-format',
|
||
choices=['text', 'json'],
|
||
default='text',
|
||
help='输出格式:text(默认)或 json'
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
try:
|
||
# 验证文件存在
|
||
if not os.path.exists(args.verilog):
|
||
raise FileNotFoundError(f"Verilog 文件不存在: {args.verilog}")
|
||
if not os.path.exists(args.vcd):
|
||
raise FileNotFoundError(f"VCD 文件不存在: {args.vcd}")
|
||
|
||
# 验证 trace_level
|
||
if args.trace_level < 1:
|
||
raise ValueError("trace-level 必须大于等于 1")
|
||
|
||
# 创建追踪器并执行
|
||
tracer = WaveformTracer(args.verilog, args.vcd)
|
||
result = tracer.waveform_trace_tool(args.sim_output, args.trace_level)
|
||
|
||
# 输出结果
|
||
if args.output_format == 'json':
|
||
output = {
|
||
'success': True,
|
||
'result': result,
|
||
'verilog_path': args.verilog,
|
||
'vcd_path': args.vcd,
|
||
'trace_level': args.trace_level
|
||
}
|
||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||
else:
|
||
print(result)
|
||
|
||
except FileNotFoundError as e:
|
||
if args.output_format == 'json':
|
||
print(json.dumps({
|
||
'success': False,
|
||
'error': str(e),
|
||
'error_type': 'FileNotFoundError'
|
||
}, ensure_ascii=False))
|
||
else:
|
||
print(f'[Error] {e}', file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
except ValueError as e:
|
||
if args.output_format == 'json':
|
||
print(json.dumps({
|
||
'success': False,
|
||
'error': str(e),
|
||
'error_type': 'ValueError'
|
||
}, ensure_ascii=False))
|
||
else:
|
||
print(f'[Error] {e}', file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
except Exception as e:
|
||
if args.output_format == 'json':
|
||
print(json.dumps({
|
||
'success': False,
|
||
'error': str(e),
|
||
'error_type': type(e).__name__
|
||
}, ensure_ascii=False))
|
||
else:
|
||
print(f'[Error] {e}', file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|