feat: 集成 waveform_trace 波形调试工具
新增功能: - 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: 打包脚本
This commit is contained in:
455
tools/waveform_trace/src/TS_REWRITE_SPEC.md
Normal file
455
tools/waveform_trace/src/TS_REWRITE_SPEC.md
Normal file
@ -0,0 +1,455 @@
|
||||
# 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<string, [number, number]>; // 信号名 -> 代码行号
|
||||
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<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. 返回结果
|
||||
```
|
||||
|
||||
#### 过滤规则
|
||||
```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<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行
|
||||
**第三方依赖**: 依赖上面所有模块
|
||||
|
||||
#### 功能描述
|
||||
整合所有模块,提供统一的调试接口。
|
||||
|
||||
#### 输入输出
|
||||
```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]:
|
||||
<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 仿真输出解析测试
|
||||
|
||||
```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. 单元测试文件
|
||||
Reference in New Issue
Block a user