新增功能: - 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: 打包脚本
12 KiB
AST波形调试工具 - TypeScript重写规范
一、项目背景
将Python实现的Verilog AST波形调试工具重写为TypeScript,用于VSCode插件。
已完成部分:
- ✅ Verilog AST解析(生成JSON格式的信号依赖图)
- ✅ 图结构定义
待重写部分:
- ⚠️ BFS信号回溯
- ⚠️ VCD波形解析
- ⚠️ 仿真输出解析
- ⚠️ 工具整合封装
二、数据结构定义
2.1 AST图结构(已完成)
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 追踪结果结构
interface TraceResult {
controlSignals: Map<string, [number, number]>; // 信号名 -> 代码行号
signalLevelTracer: string[][]; // 每层的控制关系链
}
2.3 波形数据结构
interface WaveformData {
time: number; // 时间点(ns)
signals: {
[signalName: string]: string; // 信号名 -> 值(十六进制)
};
}
interface MismatchInfo {
signals: string[]; // 出错的信号列表
firstMismatchTime: number; // 第一次出错的时间
}
三、需要重写的模块
3.1 BFS信号回溯模块
源文件: debug_graph_analyzer.py
代码行数: ~70行
第三方依赖: 无
功能描述
从出错信号出发,BFS反向遍历图,找到所有控制该信号的上游信号。
输入输出
// 输入
graph: ASTGraph // AST图(JSON格式)
targetSignals: string[] // 出错的信号列表,如 ['count', 'overflow']
k: number // 回溯层数
signalOnly: boolean // 是否只返回信号节点(过滤Always/Assign等)
// 输出
TraceResult {
controlSignals: Map<string, [number, number]>,
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. 返回结果
过滤规则
// 需要过滤的节点类型
const FILTERED_TYPES = ['Parameter', 'Localparam'];
// signalOnly=true时,还需要过滤以下前缀
const FILTERED_PREFIXES = ['Always', 'Assign', 'Module', 'IntConst'];
3.2 仿真输出解析模块
源文件: vcd_waveform_analyzer.py 中的 parse_mismatch()
代码行数: ~20行
第三方依赖: 无
功能描述
解析仿真工具的输出文本,提取出错信号名和出错时间。
输入输出
// 输入
testOutput: string // 仿真工具的输出文本
// 输出
MismatchInfo {
signals: string[], // 出错信号列表
firstMismatchTime: number // 第一次出错时间(ns)
}
解析规则
// 需要匹配的格式
// "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文件格式简介
$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 "
...
输入输出
// 输入
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实现建议
-
方案A: 找现有的JS VCD解析库
- 搜索:
npm vcd parser,vcd-stream,wavedrom
- 搜索:
-
方案B: 自己实现简单的VCD解析器
- VCD格式相对简单,核心是解析变量定义和时间变化
- 约100-150行代码
VCD解析核心逻辑
class VCDParser {
signals: Map<string, Signal>; // 信号定义
timeValues: Map<number, Map<string, string>>; // 时间 -> 信号值
parse(vcdContent: string): void {
// 1. 解析头部($var定义)
// 2. 解析数据部分(#时间 和 值变化)
}
getSignalValues(signalName: string, startTime: number, endTime: number): WaveformData[] {
// 提取指定信号在时间范围内的值
}
}
3.4 工具整合封装模块
源文件: waveform_trace_tool.py
代码行数: ~150行
第三方依赖: 依赖上面所有模块
功能描述
整合所有模块,提供统一的调试接口。
输入输出
// 输入
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]:
<signal>_ref 是期望值(golden)
<signal>_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 仿真输出解析测试
// 输入
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
};
七、注意事项
-
无第三方依赖要求
- BFS回溯和仿真解析完全可以用原生TS实现
- VCD解析可以自己实现或找现有库
-
性能考虑
- 图遍历使用Map而非Object,提高查找效率
- VCD文件可能很大,考虑流式解析
-
错误处理
- 文件不存在时返回友好错误信息
- 信号不在图中时跳过而非报错
-
兼容性
- 信号名可能包含方括号,如
count[7:0] - 时间单位统一为ns
- 信号名可能包含方括号,如
八、交付物
debugGraphAnalyzer.ts- BFS回溯模块simulationParser.ts- 仿真输出解析模块vcdParser.ts- VCD波形解析模块waveformTraceTool.ts- 工具整合封装types.ts- 类型定义- 单元测试文件