#!/usr/bin/env python # -*- coding: utf-8 -*- """ waveform_trace CLI 入口 用于 PyInstaller 打包成独立可执行文件 使用方式: waveform_trace --verilog --vcd --sim-output [--trace-level ] [--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()