# AST波形调试工具 - TypeScript重写规范 ## 一、项目背景 将Python实现的Verilog AST波形调试工具重写为TypeScript,用于VSCode插件。 **已完成部分**: - ✅ Verilog AST解析(生成JSON格式的信号依赖图) - ✅ 图结构定义 **待重写部分**: - ⚠️ BFS信号回溯 - ⚠️ VCD波形解析 - ⚠️ 仿真输出解析 - ⚠️ 工具整合封装 --- ## 二、数据结构定义 ### 2.1 AST图结构(已完成) ```typescript interface ASTNode { id: string; attributes: { lines: [number, number]; // [起始行, 结束行] type: string; // Input/Output/Reg/Wire/Always/Assign等 }; } interface ASTEdge { from: string; // 控制信号 to: string; // 被控制信号 attributes: { lines: [number, number]; type: string; // Always/Assign/IfStatement等 }; } interface ASTGraph { metadata: { moduleName: string; nodeCount: number; edgeCount: number; generatedAt: string; }; nodes: ASTNode[]; edges: ASTEdge[]; } ``` ### 2.2 追踪结果结构 ```typescript interface TraceResult { controlSignals: Map; // 信号名 -> 代码行号 signalLevelTracer: string[][]; // 每层的控制关系链 } ``` ### 2.3 波形数据结构 ```typescript interface WaveformData { time: number; // 时间点(ns) signals: { [signalName: string]: string; // 信号名 -> 值(十六进制) }; } interface MismatchInfo { signals: string[]; // 出错的信号列表 firstMismatchTime: number; // 第一次出错的时间 } ``` --- ## 三、需要重写的模块 ### 3.1 BFS信号回溯模块 **源文件**: `debug_graph_analyzer.py` **代码行数**: ~70行 **第三方依赖**: 无 #### 功能描述 从出错信号出发,BFS反向遍历图,找到所有控制该信号的上游信号。 #### 输入输出 ```typescript // 输入 graph: ASTGraph // AST图(JSON格式) targetSignals: string[] // 出错的信号列表,如 ['count', 'overflow'] k: number // 回溯层数 signalOnly: boolean // 是否只返回信号节点(过滤Always/Assign等) // 输出 TraceResult { controlSignals: Map, signalLevelTracer: string[][] } ``` #### 核心算法(伪代码) ``` 1. 构建前驱映射(反向边) for each edge in graph.edges: predecessorMap[edge.to].push(edge.from) 2. 初始化BFS队列 for each signal in targetSignals: queue.push([signal, signal]) controlSignals.set(signal, node.lines) 3. BFS遍历K层 for level = 0 to k: while queue not empty: [curSignal, controlledSignal] = queue.pop() 记录关系: curSignal -> controlledSignal for each predecessor of curSignal: if not visited and not filtered: queue.push([predecessor, curSignal]) 记录本层关系到 signalLevelTracer 4. 返回结果 ``` #### 过滤规则 ```typescript // 需要过滤的节点类型 const FILTERED_TYPES = ['Parameter', 'Localparam']; // signalOnly=true时,还需要过滤以下前缀 const FILTERED_PREFIXES = ['Always', 'Assign', 'Module', 'IntConst']; ``` --- ### 3.2 仿真输出解析模块 **源文件**: `vcd_waveform_analyzer.py` 中的 `parse_mismatch()` **代码行数**: ~20行 **第三方依赖**: 无 #### 功能描述 解析仿真工具的输出文本,提取出错信号名和出错时间。 #### 输入输出 ```typescript // 输入 testOutput: string // 仿真工具的输出文本 // 输出 MismatchInfo { signals: string[], // 出错信号列表 firstMismatchTime: number // 第一次出错时间(ns) } ``` #### 解析规则 ```typescript // 需要匹配的格式 // "First mismatch occurred at time 100. Output 'count' ..." const pattern = /First mismatch occurred at time (\d+).*Output '(\w+)'/g; // 提取所有匹配 // 返回信号列表和最小时间戳 ``` #### 示例 ``` 输入: "First mismatch occurred at time 100. Output 'count' expected 0001, got 0000 First mismatch occurred at time 150. Output 'overflow' expected 1, got 0" 输出: { signals: ['count', 'overflow'], firstMismatchTime: 100 } ``` --- ### 3.3 VCD波形解析模块 **源文件**: `vcd_waveform_analyzer.py` 中的 `get_tabular()` 和 `tabular_via_dataframe()` **代码行数**: ~150行 **第三方依赖**: Python版用了 `vcdvcd`, `pandas`, `numpy` #### 功能描述 读取VCD(Value Change Dump)波形文件,提取指定信号的波形值,生成表格。 #### VCD文件格式简介 ```vcd $timescale 1ns $end $scope module tb $end $var wire 1 ! clk $end $var wire 8 " count [7:0] $end $upscope $end $enddefinitions $end #0 b0 " 1! #5 0! #10 1! b00000001 " ... ``` #### 输入输出 ```typescript // 输入 vcdPath: string // VCD文件路径 signalsToTrace: string[] // 需要提取的信号列表 offset: number // 时间偏移(从哪个时间点开始) windowSize: number // 窗口大小(提取多少个时间点) // 输出 string // 格式化的波形表格字符串 ``` #### 输出格式示例 ``` ### First mismatched signals time(ns) Trace ### time(ns) clk reset count_ref count_dut 0 1 1 00 00 5 0 1 00 00 10 1 0 00 00 15 0 0 00 00 20 1 0 01 00 <- mismatch ### First mismatched signals time(ns) End ### ``` #### TS实现建议 1. **方案A**: 找现有的JS VCD解析库 - 搜索: `npm vcd parser`, `vcd-stream`, `wavedrom` 2. **方案B**: 自己实现简单的VCD解析器 - VCD格式相对简单,核心是解析变量定义和时间变化 - 约100-150行代码 #### VCD解析核心逻辑 ```typescript class VCDParser { signals: Map; // 信号定义 timeValues: Map>; // 时间 -> 信号值 parse(vcdContent: string): void { // 1. 解析头部($var定义) // 2. 解析数据部分(#时间 和 值变化) } getSignalValues(signalName: string, startTime: number, endTime: number): WaveformData[] { // 提取指定信号在时间范围内的值 } } ``` --- ### 3.4 工具整合封装模块 **源文件**: `waveform_trace_tool.py` **代码行数**: ~150行 **第三方依赖**: 依赖上面所有模块 #### 功能描述 整合所有模块,提供统一的调试接口。 #### 输入输出 ```typescript // 输入 verilogFilePath: string // Verilog文件路径 vcdFilePath: string // VCD波形文件路径 simulationOutput: string // 仿真输出文本 traceLevel: number // 回溯层数 // 输出 string // 完整的调试报告 ``` #### 调试报告格式 ``` [Signal Traces] Backtrace control signal relations. clk->count reset->count -count->state --state->out (*last output port level) [Signal Waveform]: _ref 是期望值(golden) _dut 是实际输出 [Traced Signals]: out, state, count, clk, reset [Table Waveform in hexadecimal format] time(ns) clk reset count_ref count_dut ... [Verilog of DUT]: ```verilog module counter(...); ... endmodule ``` [Hint] ... ``` --- ## 四、调用流程图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ waveform_trace_tool() │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. 检查文件是否存在 │ │ ├── verilogFilePath │ │ └── vcdFilePath │ │ │ │ 2. 加载AST图(已有JSON) │ │ └── graph = loadASTGraph(verilogFilePath) │ │ │ │ 3. 解析仿真输出,获取出错信号 │ │ └── mismatchInfo = parseMismatch(simulationOutput) │ │ ├── signals: ['count', 'overflow'] │ │ └── firstMismatchTime: 100 │ │ │ │ 4. BFS回溯,找到控制信号链 │ │ └── traceResult = getKControlSignals(graph, signals, k) │ │ ├── controlSignals: Map<信号名, 行号> │ │ └── signalLevelTracer: [['clk->count'], ...] │ │ │ │ 5. 读取VCD波形,提取相关信号的值 │ │ └── waveformTable = getTabular(vcdPath, signals, offset) │ │ │ │ 6. 读取Verilog源码 │ │ └── verilogCode = readFile(verilogFilePath) │ │ │ │ 7. 组装调试报告 │ │ └── return formatReport(traceResult, waveformTable, code) │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 五、参考实现 ### 5.1 Python源文件位置 ``` ast_debug_core/ ├── ast_node.py # AST节点定义(参考32-137行) ├── graph_builder.py # 图构建入口 ├── debug_graph_analyzer.py # BFS回溯(完整文件,约70行) ├── vcd_waveform_analyzer.py # VCD解析(参考89-285行) └── waveform_trace_tool.py # 工具封装(完整文件,约180行) ``` ### 5.2 关键函数对照表 | Python函数 | 位置 | TS函数名建议 | |------------|------|--------------| | `get_k_control_signals()` | debug_graph_analyzer.py:20 | `getKControlSignals()` | | `parse_mismatch()` | vcd_waveform_analyzer.py:244 | `parseMismatch()` | | `get_tabular()` | vcd_waveform_analyzer.py:264 | `getTabular()` | | `tabular_via_dataframe()` | vcd_waveform_analyzer.py:95 | `generateWaveformTable()` | | `waveform_trace_tool()` | waveform_trace_tool.py:63 | `waveformTraceTool()` | --- ## 六、测试用例 ### 6.1 BFS回溯测试 ```typescript // 输入 const graph: ASTGraph = /* 加载 counter_ast_graph.json */; const targetSignals = ['count']; const k = 2; // 期望输出 const expected = { controlSignals: new Map([ ['count', [6, 6]], ['next_count', [10, 10]], ['reset', [4, 4]], ['clk', [3, 3]], ['enable', [5, 5]] ]), signalLevelTracer: [ ['count->count'], ['next_count->count', 'reset->count', 'clk->count'], ['enable->next_count', 'count->next_count'] ] }; ``` ### 6.2 仿真输出解析测试 ```typescript // 输入 const testOutput = ` Mismatches: 2 First mismatch occurred at time 100. Output 'count' expected 0001, got 0000 First mismatch occurred at time 150. Output 'overflow' expected 1, got 0 `; // 期望输出 const expected = { signals: ['count', 'overflow'], firstMismatchTime: 100 }; ``` --- ## 七、注意事项 1. **无第三方依赖要求** - BFS回溯和仿真解析完全可以用原生TS实现 - VCD解析可以自己实现或找现有库 2. **性能考虑** - 图遍历使用Map而非Object,提高查找效率 - VCD文件可能很大,考虑流式解析 3. **错误处理** - 文件不存在时返回友好错误信息 - 信号不在图中时跳过而非报错 4. **兼容性** - 信号名可能包含方括号,如 `count[7:0]` - 时间单位统一为ns --- ## 八、交付物 1. `debugGraphAnalyzer.ts` - BFS回溯模块 2. `simulationParser.ts` - 仿真输出解析模块 3. `vcdParser.ts` - VCD波形解析模块 4. `waveformTraceTool.ts` - 工具整合封装 5. `types.ts` - 类型定义 6. 单元测试文件