为 netlist 的执行设置单独的线程

This commit is contained in:
锦恢 2025-01-08 00:11:46 +08:00
parent 0ce43f6628
commit 048fa9d2ea
5 changed files with 524 additions and 333 deletions

View File

@ -1,244 +1,34 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as fspath from 'path'; import * as fspath from 'path';
import * as fs from 'fs'; import { Worker } from 'worker_threads';
import * as os from 'os'; import { hdlFile, hdlPath } from '../../hdlFs';
import { t } from '../../i18n';
import { WASI } from 'wasi'; import { gotoDefinition, saveAsPdf, saveAsSvg } from './api';
import { getIconConfig } from '../../hdlFs/icons';
import { AbsPath, opeParam, ReportType, YosysOutput } from '../../global'; import { AbsPath, opeParam, ReportType, YosysOutput } from '../../global';
import { PathSet } from '../../global/util';
import { hdlParam } from '../../hdlParser'; import { hdlParam } from '../../hdlParser';
import { hdlDir, hdlFile, hdlPath } from '../../hdlFs';
import { defaultMacro, doFastApi } from '../../hdlParser/util'; import { defaultMacro, doFastApi } from '../../hdlParser/util';
import { HdlFile } from '../../hdlParser/core'; import { HdlFile } from '../../hdlParser/core';
import { t } from '../../i18n';
import { HdlLangID } from '../../global/enum';
import { getIconConfig } from '../../hdlFs/icons';
import { getDiskLetters, PathSet } from '../../global/util';
import { gotoDefinition, saveAsPdf, saveAsSvg } from './api';
import { Worker } from 'worker_threads';
type SynthMode = 'before' | 'after' | 'RTL'; type SynthMode = 'before' | 'after' | 'RTL';
interface SimpleOpe {
workspacePath: string,
libCommonPath: string,
prjPath: string,
extensionPath: string
}
class Netlist { const workerScriptPath = hdlPath.join(__dirname, 'worker.js');
context: vscode.ExtensionContext;
wsName: string; class NetlistRender {
libName: string;
panel?: vscode.WebviewPanel; panel?: vscode.WebviewPanel;
wasm?: WebAssembly.Module; constructor() {
constructor(context: vscode.ExtensionContext) {
this.context = context;
this.wsName = '{workspace}';
this.libName = '{library}';
} }
public async open(uri: vscode.Uri, moduleName: string, option = {}) { public create(moduleName: string) {
const pathset = new PathSet();
const path = hdlPath.toSlash(uri.fsPath);
let moduleFile = hdlParam.getHdlFile(path);
// 没有说明是单文件模式,直接打开解析
if (!moduleFile) {
const standardPath = hdlPath.toSlash(path);
const response = await doFastApi(standardPath, 'common');
const langID = hdlFile.getLanguageId(standardPath);
const projectType = hdlParam.getHdlFileProjectType(standardPath, 'common');
moduleFile = new HdlFile(
standardPath, langID,
response?.macro || defaultMacro,
response?.content || [],
projectType,
'common'
);
// 从 hdlParam 中去除,避免干扰全局
hdlParam.removeFromHdlFile(moduleFile);
// const message = t('error.common.not-valid-hdl-file');
// const errorMsg = path + ' ' + message + ' ' + opeParam.prjInfo.hardwareSrcPath + '\n' + opeParam.prjInfo.hardwareSimPath;
// vscode.window.showErrorMessage(errorMsg);
// return undefined;
}
for (const hdlModule of moduleFile.getAllHdlModules()) {
const hdlDependence = hdlParam.getAllDependences(path, hdlModule.name);
if (hdlDependence) {
// include 宏在后续会被正确处理,所以只需要处理 others 即可
hdlDependence.others.forEach(path => pathset.add(path));
}
}
pathset.add(path);
const prjFiles = [...pathset.files];
console.log(prjFiles);
console.log(opeParam.prjInfo.prjPath);
if (!this.wasm) {
const wasm = await this.loadWasm();
this.wasm = wasm;
}
const targetYs = this.makeYs(prjFiles, moduleName);
if (!targetYs || !this.wasm) {
return;
}
const wasm = this.wasm;
const wasiResult = await this.makeWasi(targetYs, moduleName);
if (wasiResult === undefined) {
return;
}
const { wasi, fd } = wasiResult;
const netlistPayloadFolder = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist');
const targetJson = hdlPath.join(netlistPayloadFolder, moduleName + '.json');
hdlFile.rmSync(targetJson);
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: t('info.netlist.generate-network'),
cancellable: true
}, async (_, token) => {
token.onCancellationRequested(() => {
console.log('cancel');
fs.closeSync(fd);
});
const instance = WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport
});
try {
const exitCode = wasi.start(instance);
} catch (error) {
console.error(error);
}
});
if (!fs.existsSync(targetJson)) {
fs.closeSync(fd);
const logFilePath = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist', moduleName + '.log');
const res = await vscode.window.showErrorMessage(
t('error.cannot-gen-netlist'),
{ title: t('error.look-up-log'), value: true }
)
if (res?.value) {
const document = await vscode.workspace.openTextDocument(vscode.Uri.file(logFilePath));
await vscode.window.showTextDocument(document);
}
return;
}
this.create(moduleName, fd);
}
private getSynthMode(): SynthMode {
const configuration = vscode.workspace.getConfiguration();
return configuration.get<SynthMode>('digital-ide.function.netlist.schema-mode') || 'before';
}
private makeYs(files: AbsPath[], topModule: string) {
const netlistPayloadFolder = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist');
hdlDir.mkdir(netlistPayloadFolder);
const target = hdlPath.join(netlistPayloadFolder, topModule + '.ys');
const targetJson = hdlPath.join(netlistPayloadFolder, topModule + '.json').replace(opeParam.workspacePath, this.wsName);
const scripts: string[] = [];
for (const file of files) {
const langID = hdlFile.getLanguageId(file);
if (langID === HdlLangID.Unknown || langID === HdlLangID.Vhdl) {
vscode.window.showErrorMessage(t('info.netlist.not-support-vhdl'));
return undefined;
}
if (file.startsWith(opeParam.workspacePath)) {
const constraintPath = file.replace(opeParam.workspacePath, this.wsName);
scripts.push(`read_verilog -sv -formal -overwrite ${constraintPath}`);
} else if (file.startsWith(opeParam.prjInfo.libCommonPath)) {
const constraintPath = file.replace(opeParam.prjInfo.libCommonPath, this.libName);
scripts.push(`read_verilog -sv -formal -overwrite ${constraintPath}`);
}
}
const mode = this.getSynthMode();
switch (mode) {
case 'before':
scripts.push('design -reset-vlog; proc;');
break;
case 'after':
scripts.push('design -reset-vlog; proc; opt_clean;');
break;
case 'RTL':
scripts.push('synth -run coarse;');
break;
}
scripts.push(`write_json ${targetJson}`);
const ysCode = scripts.join('\n');
hdlFile.writeFile(target, ysCode);
return target.replace(opeParam.workspacePath, this.wsName);
}
public async getPreopens() {
const basepreopens = {
'/share': hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'static', 'share'),
[this.wsName ]: opeParam.workspacePath,
[this.libName]: opeParam.prjInfo.libCommonPath
};
if (os.platform() === 'win32') {
const mounts = await getDiskLetters();
for (const mountName of mounts) {
const realMount = mountName + '/';
basepreopens[realMount.toLowerCase()] = realMount;
basepreopens[realMount.toUpperCase()] = realMount;
}
} else {
basepreopens['/'] = '/';
}
return basepreopens;
}
private async makeWasi(target: string, logName: string) {
// 创建日志文件路径
const logFilePath = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist', logName + '.log');
hdlFile.removeFile(logFilePath);
const logFd = fs.openSync(logFilePath, 'a');
try {
const wasiOption = {
version: 'preview1',
args: [
'yosys',
'-s',
target
],
preopens: await this.getPreopens(),
stdin: process.stdin.fd,
stdout: process.stdout.fd,
stderr: logFd,
env: process.env
};
const wasi = new WASI(wasiOption);
return { wasi, fd: logFd };
} catch (error) {
fs.closeSync(logFd);
return undefined;
}
}
private async loadWasm() {
const netlistWasmPath = hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'static', 'yosys.wasm');
if (!hdlPath.exist(netlistWasmPath)) {
vscode.window.showErrorMessage(t('info.netlist.not-found-payload'));
throw Error(t('info.netlist.not-found-payload'));
}
const binary = fs.readFileSync(netlistWasmPath);
const wasm = await WebAssembly.compile(binary);
return wasm;
}
private create(moduleName: string, fd: number) {
// Create panel // Create panel
this.panel = vscode.window.createWebviewPanel( this.panel = vscode.window.createWebviewPanel(
'Netlist', 'Netlist',
@ -252,7 +42,6 @@ class Netlist {
); );
this.panel.onDidDispose(() => { this.panel.onDidDispose(() => {
fs.closeSync(fd);
}); });
const previewHtml = this.getWebviewContent(); const previewHtml = this.getWebviewContent();
@ -281,10 +70,6 @@ class Netlist {
} }
} }
public send() {
}
public getWebviewContent() { public getWebviewContent() {
const netlistPath = hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'view'); const netlistPath = hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'view');
const htmlIndexPath = hdlPath.join(netlistPath, 'index.html'); const htmlIndexPath = hdlPath.join(netlistPath, 'index.html');
@ -297,80 +82,61 @@ class Netlist {
}); });
return html; return html;
} }
}
public getJsonPathFromYs(path: AbsPath): AbsPath | undefined { async function generateFilelist(path: AbsPath): Promise<AbsPath[]> {
for (const line of fs.readFileSync(path, { encoding: 'utf-8' }).split('\n')) { const pathset = new PathSet();
if (line.trim().startsWith('write_json')) { path = hdlPath.toSlash(path);
const path = line.split(/\s+/).at(1);
if (path) { let moduleFile = hdlParam.getHdlFile(path);
const realPath = path // 没有说明是单文件模式,直接打开解析
.replace(this.wsName, opeParam.workspacePath) if (!moduleFile) {
.replace(this.libName, opeParam.prjInfo.libCommonPath); const standardPath = hdlPath.toSlash(path);
return hdlPath.toSlash(realPath); const response = await doFastApi(standardPath, 'common');
} const langID = hdlFile.getLanguageId(standardPath);
} const projectType = hdlParam.getHdlFileProjectType(standardPath, 'common');
} moduleFile = new HdlFile(
return undefined; standardPath, langID,
response?.macro || defaultMacro,
response?.content || [],
projectType,
'common'
);
// 从 hdlParam 中去除,避免干扰全局
hdlParam.removeFromHdlFile(moduleFile);
// const message = t('error.common.not-valid-hdl-file');
// const errorMsg = path + ' ' + message + ' ' + opeParam.prjInfo.hardwareSrcPath + '\n' + opeParam.prjInfo.hardwareSimPath;
// vscode.window.showErrorMessage(errorMsg);
// return undefined;
} }
public async runYs(uri: vscode.Uri) { for (const hdlModule of moduleFile.getAllHdlModules()) {
const ysPath = hdlPath.toSlash(uri.fsPath); const hdlDependence = hdlParam.getAllDependences(path, hdlModule.name);
const targetJson = this.getJsonPathFromYs(ysPath); if (hdlDependence) {
const name = ysPath.split('/').at(-1) as string; // include 宏在后续会被正确处理,所以只需要处理 others 即可
const wasiResult = await this.makeWasi(ysPath, name); hdlDependence.others.forEach(path => pathset.add(path));
if (wasiResult === undefined) {
return;
}
const { wasi, fd } = wasiResult;
if (targetJson) {
hdlFile.rmSync(targetJson);
}
if (!this.wasm) {
const wasm = await this.loadWasm();
this.wasm = wasm;
}
const wasm = this.wasm;
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: t('info.netlist.generate-network'),
cancellable: true
}, async () => {
const instance = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport
});
const exitCode = wasi.start(instance);
});
if (targetJson && !fs.existsSync(targetJson)) {
fs.closeSync(fd);
const logFilePath = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist', name + '.log');
const res = await vscode.window.showErrorMessage(
t('error.cannot-gen-netlist'),
{ title: t('error.look-up-log'), value: true }
)
if (res?.value) {
const document = await vscode.workspace.openTextDocument(vscode.Uri.file(logFilePath));
await vscode.window.showTextDocument(document);
}
} }
} }
pathset.add(path);
const filelist = [...pathset.files];
console.log(filelist);
console.log(opeParam.prjInfo.prjPath);
return filelist;
} }
export async function openNetlistViewer(context: vscode.ExtensionContext, uri: vscode.Uri, moduleName: string) { function generateOpe(): SimpleOpe {
const viewer = new Netlist(context); return {
viewer.open(uri, moduleName); workspacePath: opeParam.workspacePath,
extensionPath: opeParam.extensionPath,
libCommonPath: opeParam.prjInfo.libCommonPath,
prjPath: opeParam.prjInfo.prjPath
};
} }
export async function runYsScript(context: vscode.ExtensionContext, uri: vscode.Uri) {
const viewer = new Netlist(context);
viewer.runYs(uri);
}
function registerMessageEvent(panel: vscode.WebviewPanel) { function registerMessageEvent(panel: vscode.WebviewPanel) {
panel.webview.onDidReceiveMessage(message => { panel.webview.onDidReceiveMessage(message => {
const { command, data } = message; const { command, data } = message;
@ -390,3 +156,125 @@ function registerMessageEvent(panel: vscode.WebviewPanel) {
} }
}); });
} }
function waitForFinish(worker: Worker): Promise<void> {
return new Promise<void>(resolve => {
worker.on('message', message => {
if (message.command === 'finish') {
resolve();
}
});
});
}
function checkResource() {
const netlistWasmPath = hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'static', 'yosys.wasm');
if (!hdlPath.exist(netlistWasmPath)) {
vscode.window.showErrorMessage(t('info.netlist.not-found-payload'));
throw Error(t('info.netlist.not-found-payload'));
}
}
export async function openNetlistViewer(context: vscode.ExtensionContext, uri: vscode.Uri, moduleName: string) {
checkResource();
const worker = new Worker(workerScriptPath);
worker.on('message', message => {
const command = message.command;
const data = message.data;
switch (command) {
case 'error-log-file':
showErrorLogFile(data);
break;
default:
break;
}
});
const configuration = vscode.workspace.getConfiguration();
const mode = configuration.get<SynthMode>('digital-ide.function.netlist.schema-mode') || 'before';
const filelist = await generateFilelist(uri.fsPath);
const ope = generateOpe();
worker.postMessage({
command: 'open',
data: {
path: uri.fsPath,
moduleName, mode,
filelist,
ope
}
});
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: t('info.netlist.generate-network'),
cancellable: true
}, async (_, token) => {
token.onCancellationRequested(() => {
worker.terminate();
});
await waitForFinish(worker);
});
worker.terminate();
const render = new NetlistRender();
render.create(moduleName);
}
async function showErrorLogFile(data: any) {
const { logFilePath } = data;
const res = await vscode.window.showErrorMessage(
t('error.cannot-gen-netlist'),
{ title: t('error.look-up-log'), value: true }
)
if (res?.value) {
const document = await vscode.workspace.openTextDocument(vscode.Uri.file(logFilePath));
await vscode.window.showTextDocument(document);
}
}
export async function runYsScript(context: vscode.ExtensionContext, uri: vscode.Uri) {
checkResource();
const worker = new Worker(workerScriptPath);
worker.on('message', message => {
const command = message.command;
const data = message.data;
switch (command) {
case 'error-log-file':
showErrorLogFile(data);
break;
default:
break;
}
});
const ope = generateOpe();
worker.postMessage({
command: 'run',
data: {
path: uri.fsPath,
ope
}
});
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: t('info.netlist.generate-network'),
cancellable: true
}, async (_, token) => {
token.onCancellationRequested(() => {
worker.terminate();
});
await waitForFinish(worker);
});
worker.terminate();
}

View File

@ -1,4 +1,25 @@
import { isMainThread, Worker, parentPort } from 'worker_threads'; import { parentPort } from 'worker_threads';
import * as childProcess from 'child_process';
import * as fs from 'fs';
import * as os from 'os';
import { WASI } from 'wasi';
type SynthMode = 'before' | 'after' | 'RTL';
type AbsPath = string;
enum HdlLangID {
Verilog = 'verilog',
SystemVerilog = 'systemverilog',
Vhdl = 'vhdl',
Unknown = 'Unknown'
};
interface SimpleOpe {
workspacePath: string,
libCommonPath: string,
prjPath: string,
extensionPath: string
}
if (parentPort) { if (parentPort) {
parentPort.on('message', message => { parentPort.on('message', message => {
@ -6,13 +27,323 @@ if (parentPort) {
const data = message.data; const data = message.data;
switch (command) { switch (command) {
case 'ys': case 'open':
open(data);
break;
case 'run':
run(data);
break; break;
default: default:
break; break;
} }
}); });
} }
async function open(data: any) {
const { path, moduleName, mode, filelist, ope } = data;
const viewer = new Netlist(ope);
viewer.open(path, moduleName, filelist, mode);
}
async function run(data: any) {
const { path, ope } = data;
const viewer = new Netlist(ope);
viewer.runYs(path);
}
function getDiskLetters(): Promise<string[]> {
return new Promise((resolve, reject) => {
// 调用 wmic 命令获取磁盘信息
childProcess.exec('wmic logicaldisk get name', (error, stdout, stderr) => {
if (error) {
reject(`Error: ${error.message}`);
return;
}
if (stderr) {
reject(`Stderr: ${stderr}`);
return;
}
// 解析命令输出
const disks = stdout
.split('\n') // 按行分割
.map(line => line.trim()) // 去除每行的空白字符
.filter(line => /^[A-Z]:$/.test(line)); // 过滤出盘符(如 C:, D:
resolve(disks);
});
});
}
function mkdir(path: AbsPath): boolean {
if (!path) {
return false;
}
// 如果存在则直接退出
if (fs.existsSync(path)) {
return true;
}
try {
fs.mkdirSync(path, {recursive:true});
return true;
}
catch (error) {
fs.mkdirSync(path, {recursive:true});
}
return false;
}
function join(...paths: string[]): AbsPath {
return paths.join('/');
}
function isVlog(file: AbsPath): boolean {
const exts = ['.v', '.vh', '.vl', '.sv'];
for (const ext of exts) {
if (file.toLowerCase().endsWith(ext)) {
return true;
}
}
return false;
}
class Netlist {
wsName: string;
libName: string;
ope: SimpleOpe;
wasm?: WebAssembly.Module;
constructor(ope: SimpleOpe) {
this.wsName = '{workspace}';
this.libName = '{library}';
this.ope = ope;
}
public async open(path: string, moduleName: string, filelist: AbsPath[], mode: SynthMode) {
if (!this.wasm) {
const wasm = await this.loadWasm();
this.wasm = wasm;
}
const targetYs = this.makeYs(filelist, moduleName, mode);
if (!targetYs || !this.wasm) {
return;
}
const wasm = this.wasm;
const wasiResult = await this.makeWasi(targetYs, moduleName);
if (wasiResult === undefined) {
return;
}
const { wasi, fd } = wasiResult;
const netlistPayloadFolder = join(this.ope.prjPath, 'netlist');
const targetJson = join(netlistPayloadFolder, moduleName + '.json');
if (fs.existsSync(targetJson)) {
fs.rmSync(targetJson);
}
const instance = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport
});
try {
const exitCode = wasi.start(instance);
} catch (error) {
if (parentPort) {
parentPort.postMessage({
command: 'finish',
data: { error }
});
}
}
if (!fs.existsSync(targetJson)) {
fs.closeSync(fd);
const logFilePath = join(this.ope.prjPath, 'netlist', moduleName + '.log');
if (parentPort) {
parentPort.postMessage({
command: 'error-log-file',
data: { logFilePath }
});
}
}
if (parentPort) {
parentPort.postMessage({
command: 'finish',
data: {}
});
}
}
private makeYs(files: AbsPath[], topModule: string, mode: SynthMode) {
const netlistPayloadFolder = join(this.ope.prjPath, 'netlist');
mkdir(netlistPayloadFolder);
const target = join(netlistPayloadFolder, topModule + '.ys');
const targetJson = join(netlistPayloadFolder, topModule + '.json').replace(this.ope.workspacePath, this.wsName);
const scripts: string[] = [];
for (const file of files) {
if (!isVlog(file)) {
return undefined;
}
if (file.startsWith(this.ope.workspacePath)) {
const constraintPath = file.replace(this.ope.workspacePath, this.wsName);
scripts.push(`read_verilog -sv -formal -overwrite ${constraintPath}`);
} else if (file.startsWith(this.ope.libCommonPath)) {
const constraintPath = file.replace(this.ope.libCommonPath, this.libName);
scripts.push(`read_verilog -sv -formal -overwrite ${constraintPath}`);
}
}
switch (mode) {
case 'before':
scripts.push('design -reset-vlog; proc;');
break;
case 'after':
scripts.push('design -reset-vlog; proc; opt_clean;');
break;
case 'RTL':
scripts.push('synth -run coarse;');
break;
}
scripts.push(`write_json ${targetJson}`);
const ysCode = scripts.join('\n');
fs.writeFileSync(target, ysCode, { encoding: 'utf-8' });
return target.replace(this.ope.workspacePath, this.wsName);
}
public async getPreopens() {
const basepreopens = {
'/share': join(this.ope.extensionPath, 'resources', 'dide-netlist', 'static', 'share'),
[this.wsName ]: this.ope.workspacePath,
[this.libName]: this.ope.libCommonPath
};
if (os.platform() === 'win32') {
const mounts = await getDiskLetters();
for (const mountName of mounts) {
const realMount = mountName + '/';
basepreopens[realMount.toLowerCase()] = realMount;
basepreopens[realMount.toUpperCase()] = realMount;
}
} else {
basepreopens['/'] = '/';
}
return basepreopens;
}
private async makeWasi(target: string, logName: string) {
// 创建日志文件路径
const logFilePath = join(this.ope.prjPath, 'netlist', logName + '.log');
if (fs.existsSync(logFilePath)) {
fs.rmSync(logFilePath)
}
const logFd = fs.openSync(logFilePath, 'a');
try {
const wasiOption = {
version: 'preview1',
args: [
'yosys',
'-s',
target
],
preopens: await this.getPreopens(),
stdin: process.stdin.fd,
stdout: process.stdout.fd,
stderr: logFd,
env: process.env
};
const wasi = new WASI(wasiOption);
return { wasi, fd: logFd };
} catch (error) {
fs.closeSync(logFd);
return undefined;
}
}
private async loadWasm() {
const netlistWasmPath = join(this.ope.extensionPath, 'resources', 'dide-netlist', 'static', 'yosys.wasm');
const binary = fs.readFileSync(netlistWasmPath);
const wasm = await WebAssembly.compile(binary);
return wasm;
}
public getJsonPathFromYs(path: AbsPath): AbsPath | undefined {
for (const line of fs.readFileSync(path, { encoding: 'utf-8' }).split('\n')) {
if (line.trim().startsWith('write_json')) {
const path = line.split(/\s+/).at(1);
if (path) {
const realPath = path
.replace(this.wsName, this.ope.workspacePath)
.replace(this.libName, this.ope.libCommonPath);
return realPath.replace(/\\/g,"\/");
}
}
}
return undefined;
}
public async runYs(path: string) {
const ysPath = path.replace(/\\/g,"\/");
const targetJson = this.getJsonPathFromYs(ysPath);
const name = ysPath.split('/').at(-1) as string;
const wasiResult = await this.makeWasi(ysPath, name);
if (wasiResult === undefined) {
return;
}
const { wasi, fd } = wasiResult;
if (targetJson) {
fs.rmSync(targetJson);
}
if (!this.wasm) {
const wasm = await this.loadWasm();
this.wasm = wasm;
}
const wasm = this.wasm;
const instance = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport
});
try {
const exitCode = wasi.start(instance);
} catch (error) {
if (parentPort) {
parentPort.postMessage({
command: 'finish',
data: { error }
});
}
}
if (targetJson && !fs.existsSync(targetJson)) {
fs.closeSync(fd);
const logFilePath = join(this.ope.prjPath, 'netlist', name + '.log');
if (parentPort) {
parentPort.postMessage({
command: 'error-log-file',
data: { logFilePath }
});
}
}
if (parentPort) {
parentPort.postMessage({
command: 'finish',
data: {}
});
}
}
}

View File

@ -263,28 +263,3 @@ export function getUserHomeDir(): AbsPath {
const path = process.env.HOME || process.env.USERPROFILE || os.homedir(); const path = process.env.HOME || process.env.USERPROFILE || os.homedir();
return hdlPath.toSlash(path); return hdlPath.toSlash(path);
} }
export function getDiskLetters(): Promise<string[]> {
return new Promise((resolve, reject) => {
// 调用 wmic 命令获取磁盘信息
childProcess.exec('wmic logicaldisk get name', (error, stdout, stderr) => {
if (error) {
reject(`Error: ${error.message}`);
return;
}
if (stderr) {
reject(`Stderr: ${stderr}`);
return;
}
// 解析命令输出
const disks = stdout
.split('\n') // 按行分割
.map(line => line.trim()) // 去除每行的空白字符
.filter(line => /^[A-Z]:$/.test(line)); // 过滤出盘符(如 C:, D:
resolve(disks);
});
});
}

View File

@ -5,8 +5,6 @@ import { AbsPath, RelPath } from '../global';
import { HdlLangID } from '../global/enum'; import { HdlLangID } from '../global/enum';
import { verilogExts, vhdlExts, systemVerilogExts, hdlExts } from '../global/lang'; import { verilogExts, vhdlExts, systemVerilogExts, hdlExts } from '../global/lang';
import * as hdlPath from './path'; import * as hdlPath from './path';
import { HdlFileProjectType } from '../hdlParser/common';
import { opeParam } from '../global';
import { hdlIgnore } from '../manager/ignore'; import { hdlIgnore } from '../manager/ignore';
import { hdlDir } from '.'; import { hdlDir } from '.';

View File

@ -1,6 +1,5 @@
import * as vscode from 'vscode';
import { AbsPath, opeParam } from '../global'; import { AbsPath, opeParam } from '../global';
import { hdlFile, hdlPath } from '../hdlFs'; import { hdlPath } from '../hdlFs';
import * as fs from 'fs'; import * as fs from 'fs';
import * as fspath from 'path'; import * as fspath from 'path';
import { minimatch } from 'minimatch'; import { minimatch } from 'minimatch';