Files
IC-Coder-Plugin/src/panels/helpers/vcdHelper.ts
Roe-xin 2a280aaa93 refactor: 优化 ICHelperPanel 组件结构
- 将 1346 行的单文件拆分为 7 个职责单一的模块
   - authHelper: 认证和登录检查
   - userInfoHelper: 用户信息管理
   - conversationHelper: 会话历史加载
   - vcdHelper: VCD 文件处理
   - contextHelper: 上下文管理
   - fileHelper: 文件操作
   - messageRouter: 消息路由分发
   - 主组件精简至 157 行,提升可维护性
2026-03-12 11:58:43 +08:00

159 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* VCD 文件处理模块
* 功能VCD 文件信息获取和信号解析
* 依赖vscode, fs
* 使用场景:波形查看器相关功能
*/
import * as vscode from "vscode";
export async function getVCDFileInfo(
panel: vscode.WebviewPanel,
vcdFilePath: string,
containerId: string,
) {
try {
const fs = require("fs");
if (!fs.existsSync(vcdFilePath)) {
panel.webview.postMessage({
command: "vcdInfo",
containerId: containerId,
vcdInfo: {
signalCount: "N/A",
timeRange: "N/A",
fileSize: "N/A",
error: "文件不存在",
},
});
return;
}
const stats = fs.statSync(vcdFilePath);
const fileSizeKB = stats.size / 1024;
const fileSize =
fileSizeKB < 1024
? `${fileSizeKB.toFixed(2)} KB`
: `${(fileSizeKB / 1024).toFixed(2)} MB`;
const content = fs.readFileSync(vcdFilePath, "utf-8");
const varMatches = content.match(/\$var/g);
const signalCount = varMatches ? varMatches.length : 0;
let timeRange = "N/A";
const timeMatch = content.match(/#(\d+)/g);
if (timeMatch && timeMatch.length > 0) {
const times = timeMatch.map((t: string) => parseInt(t.substring(1)));
const minTime = Math.min(...times);
const maxTime = Math.max(...times);
timeRange = `${minTime} - ${maxTime}`;
}
const signals = parseVCDSignals(content, 3);
panel.webview.postMessage({
command: "vcdInfo",
containerId: containerId,
vcdInfo: {
signalCount: signalCount.toString(),
timeRange: timeRange,
fileSize: fileSize,
signals: signals,
},
});
} catch (error) {
console.error("获取 VCD 文件信息失败:", error);
panel.webview.postMessage({
command: "vcdInfo",
containerId: containerId,
vcdInfo: {
signalCount: "N/A",
timeRange: "N/A",
fileSize: "N/A",
error: error instanceof Error ? error.message : "未知错误",
},
});
}
}
function parseVCDSignals(content: string, maxSignals: number = 3) {
const signals: Array<{
name: string;
identifier: string;
width: number;
values: Array<{ time: number; value: string }>;
}> = [];
try {
const varRegex = /\$var\s+(\w+)\s+(\d+)\s+(\S+)\s+([^\$]+?)\s+\$end/g;
let match;
const signalDefs: Array<{
name: string;
identifier: string;
width: number;
}> = [];
while (
(match = varRegex.exec(content)) !== null &&
signalDefs.length < maxSignals
) {
const width = parseInt(match[2]);
const identifier = match[3];
const name = match[4].trim();
signalDefs.push({ name, identifier, width });
}
const dumpvarsIndex = content.indexOf("$dumpvars");
if (dumpvarsIndex === -1) {
return signals;
}
const dataSection = content.substring(dumpvarsIndex);
for (const signalDef of signalDefs) {
const values: Array<{ time: number; value: string }> = [];
let currentTime = 0;
const lines = dataSection.split("\n");
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.startsWith("#")) {
currentTime = parseInt(trimmedLine.substring(1));
continue;
}
if (signalDef.width === 1) {
const singleBitMatch = trimmedLine.match(
new RegExp(`^([01xz])${signalDef.identifier}$`),
);
if (singleBitMatch) {
values.push({ time: currentTime, value: singleBitMatch[1] });
}
} else {
const multiBitMatch = trimmedLine.match(
new RegExp(`^b([01xz]+)\\s+${signalDef.identifier}$`),
);
if (multiBitMatch) {
values.push({ time: currentTime, value: multiBitMatch[1] });
}
}
if (values.length >= 50) {
break;
}
}
signals.push({
name: signalDef.name,
identifier: signalDef.identifier,
width: signalDef.width,
values: values,
});
}
} catch (error) {
console.error("解析 VCD 信号数据失败:", error);
}
return signals;
}