diff --git a/package.json b/package.json index f7f7d34..36e3ad3 100644 --- a/package.json +++ b/package.json @@ -558,11 +558,11 @@ { "command": "digital-ide.netlist.run-ys", "icon": { - "light": "images/svg/light/netlist.svg", - "dark": "images/svg/dark/netlist.svg" + "light": "images/svg/light/ys.svg", + "dark": "images/svg/dark/ys.svg" }, "category": "Digital-IDE", - "title": "%digital-ide.netlist.title%" + "title": "%digital-ide.run-ys.title%" }, { "command": "digital-ide.fsm", diff --git a/package.nls.de.json b/package.nls.de.json index 306dba2..f3e4836 100644 --- a/package.nls.de.json +++ b/package.nls.de.json @@ -101,8 +101,9 @@ "digital-ide.function.lsp.linter.linter-level.title": "Diagnoselevel-Einstellungen des Linters", "digital-ide.function.lsp.linter.linter-level.error.title": "Nur Fehler anzeigen", "digital-ide.function.lsp.linter.linter-level.warning.title": "Fehler und Warnungen anzeigen", - "%digital-ide.function.netlist.schema-mode.title%": "Netlist-Synthesemodus auswählen", - "%digital-ide.function.netlist.schema-mode.0.title%": "Prä-Verhaltenssynthese", - "%digital-ide.function.netlist.schema-mode.1.title%": "Post-Verhaltenssynthese", - "%digital-ide.function.netlist.schema-mode.2.title%": "Post-RTL-Synthese" + "digital-ide.function.netlist.schema-mode.title": "Netlist-Synthesemodus auswählen", + "digital-ide.function.netlist.schema-mode.0.title": "Prä-Verhaltenssynthese", + "digital-ide.function.netlist.schema-mode.1.title": "Post-Verhaltenssynthese", + "digital-ide.function.netlist.schema-mode.2.title": "Post-RTL-Synthese", + "digital-ide.run-ys.title": "yosys-Skript ausführen" } \ No newline at end of file diff --git a/package.nls.ja.json b/package.nls.ja.json index 6422cad..af24420 100644 --- a/package.nls.ja.json +++ b/package.nls.ja.json @@ -101,8 +101,9 @@ "digital-ide.function.lsp.linter.linter-level.title": "診断器の診断レベル設定", "digital-ide.function.lsp.linter.linter-level.error.title": "エラーのみ表示", "digital-ide.function.lsp.linter.linter-level.warning.title": "エラーと警告を表示", - "%digital-ide.function.netlist.schema-mode.title%": "Netlist 合成モードを選択", - "%digital-ide.function.netlist.schema-mode.0.title%": "ビヘイビア前合成", - "%digital-ide.function.netlist.schema-mode.1.title%": "ビヘイビア後合成", - "%digital-ide.function.netlist.schema-mode.2.title%": "RTL後合成" + "digital-ide.function.netlist.schema-mode.title": "Netlist 合成モードを選択", + "digital-ide.function.netlist.schema-mode.0.title": "ビヘイビア前合成", + "digital-ide.function.netlist.schema-mode.1.title": "ビヘイビア後合成", + "digital-ide.function.netlist.schema-mode.2.title": "RTL後合成", + "digital-ide.run-ys.title": "yosys スクリプトを実行" } \ No newline at end of file diff --git a/package.nls.json b/package.nls.json index 9dd6a3b..ea49a91 100644 --- a/package.nls.json +++ b/package.nls.json @@ -101,8 +101,9 @@ "digital-ide.function.lsp.linter.linter-level.title": "Diagnostic Level Settings for the Linter", "digital-ide.function.lsp.linter.linter-level.error.title": "Show Only Errors", "digital-ide.function.lsp.linter.linter-level.warning.title": "Show Errors and Warnings", - "%digital-ide.function.netlist.schema-mode.title%": "Select Netlist Synthesis Mode", - "%digital-ide.function.netlist.schema-mode.0.title%": "Pre-Behavioral Synthesis", - "%digital-ide.function.netlist.schema-mode.1.title%": "Post-Behavioral Synthesis", - "%digital-ide.function.netlist.schema-mode.2.title%": "Post-RTL Synthesis" + "digital-ide.function.netlist.schema-mode.title": "Select Netlist Synthesis Mode", + "digital-ide.function.netlist.schema-mode.0.title": "Pre-Behavioral Synthesis", + "digital-ide.function.netlist.schema-mode.1.title": "Post-Behavioral Synthesis", + "digital-ide.function.netlist.schema-mode.2.title": "Post-RTL Synthesis", + "digital-ide.run-ys.title": "Run yosys script" } \ No newline at end of file diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index fa5948d..260745e 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -101,8 +101,9 @@ "digital-ide.function.lsp.linter.linter-level.title": "诊断器诊断等级设置", "digital-ide.function.lsp.linter.linter-level.error.title": "只显示错误", "digital-ide.function.lsp.linter.linter-level.warning.title": "显示错误和警告", - "%digital-ide.function.netlist.schema-mode.title%": "选择 Netlist 综合模式", - "%digital-ide.function.netlist.schema-mode.0.title%": "行为前综合", - "%digital-ide.function.netlist.schema-mode.1.title%": "行为后综合", - "%digital-ide.function.netlist.schema-mode.2.title%": "RTL后综合" + "digital-ide.function.netlist.schema-mode.title": "选择 Netlist 综合模式", + "digital-ide.function.netlist.schema-mode.0.title": "行为前综合", + "digital-ide.function.netlist.schema-mode.1.title": "行为后综合", + "digital-ide.function.netlist.schema-mode.2.title": "RTL后综合", + "digital-ide.run-ys.title": "运行 yosys 脚本" } \ No newline at end of file diff --git a/package.nls.zh-tw.json b/package.nls.zh-tw.json index 410a920..341b940 100644 --- a/package.nls.zh-tw.json +++ b/package.nls.zh-tw.json @@ -101,8 +101,9 @@ "digital-ide.function.lsp.linter.linter-level.title": "診斷器診斷等級設置", "digital-ide.function.lsp.linter.linter-level.error.title": "只顯示錯誤", "digital-ide.function.lsp.linter.linter-level.warning.title": "顯示錯誤和警告", - "%digital-ide.function.netlist.schema-mode.title%": "選擇 Netlist 綜合模式", - "%digital-ide.function.netlist.schema-mode.0.title%": "行為前綜合", - "%digital-ide.function.netlist.schema-mode.1.title%": "行為後綜合", - "%digital-ide.function.netlist.schema-mode.2.title%": "RTL後綜合" + "digital-ide.function.netlist.schema-mode.title": "選擇 Netlist 綜合模式", + "digital-ide.function.netlist.schema-mode.0.title": "行為前綜合", + "digital-ide.function.netlist.schema-mode.1.title": "行為後綜合", + "digital-ide.function.netlist.schema-mode.2.title": "RTL後綜合", + "digital-ide.run-ys.title": "運行 yosys 腳本" } \ No newline at end of file diff --git a/src/function/dide-netlist/index.ts b/src/function/dide-netlist/index.ts index 58fb104..5e89233 100644 --- a/src/function/dide-netlist/index.ts +++ b/src/function/dide-netlist/index.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import * as fspath from 'path'; import * as fs from 'fs'; +import * as os from 'os'; import { WASI } from 'wasi'; @@ -12,7 +13,7 @@ import { HdlFile } from '../../hdlParser/core'; import { t } from '../../i18n'; import { HdlLangID } from '../../global/enum'; import { getIconConfig } from '../../hdlFs/icons'; -import { PathSet } from '../../global/util'; +import { getDiskLetters, PathSet } from '../../global/util'; import { gotoDefinition, saveAsPdf, saveAsSvg } from './api'; type SynthMode = 'before' | 'after' | 'RTL'; @@ -31,7 +32,7 @@ class Netlist { this.libName = '{library}'; } - public async open(uri: vscode.Uri, moduleName: string) { + public async open(uri: vscode.Uri, moduleName: string, option = {}) { const pathset = new PathSet(); const path = hdlPath.toSlash(uri.fsPath); @@ -83,7 +84,7 @@ class Netlist { } const wasm = this.wasm; - const wasiResult = this.makeWasi(targetYs, moduleName); + const wasiResult = await this.makeWasi(targetYs, moduleName); if (wasiResult === undefined) { return; @@ -106,7 +107,8 @@ class Netlist { }); if (!fs.existsSync(targetJson)) { - const logFilePath = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist', 'netlist.log'); + 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 } @@ -167,12 +169,31 @@ class Netlist { return target.replace(opeParam.workspacePath, this.wsName); } - private makeWasi(target: string, moduleName: string) { + 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; + } + } + return basepreopens + } + + private async makeWasi(target: string, logName: string) { // 创建日志文件路径 - const logFilePath = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist', moduleName + '.log'); + const logFilePath = hdlPath.join(opeParam.prjInfo.prjPath, 'netlist', logName + '.log'); hdlFile.removeFile(logFilePath); const logFd = fs.openSync(logFilePath, 'a'); + console.log(target); + try { const wasiOption = { version: 'preview1', @@ -181,11 +202,7 @@ class Netlist { '-s', target ], - preopens: { - '/share': hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'static', 'share'), - [this.wsName ]: opeParam.workspacePath, - [this.libName]: opeParam.prjInfo.libCommonPath - }, + preopens: await this.getPreopens(), stdin: process.stdin.fd, stdout: process.stdout.fd, stderr: logFd, @@ -228,12 +245,6 @@ class Netlist { fs.closeSync(fd); }); - this.panel.webview.onDidReceiveMessage(message => { - switch (message.command) { - - } - }, undefined, this.context.subscriptions); - const previewHtml = this.getWebviewContent(); if (this.panel && previewHtml) { const netlistPath = hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'view'); @@ -305,8 +316,65 @@ class Netlist { } } - public async runYs(uri: vscode.Uri) { + 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, opeParam.workspacePath) + .replace(this.libName, opeParam.prjInfo.libCommonPath); + return hdlPath.toSlash(realPath); + } + } + } + return undefined; + } + public async runYs(uri: vscode.Uri) { + const ysPath = hdlPath.toSlash(uri.fsPath); + 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) { + 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); + } + } } } @@ -317,7 +385,7 @@ export async function openNetlistViewer(context: vscode.ExtensionContext, uri: v export async function runYsScript(context: vscode.ExtensionContext, uri: vscode.Uri) { const viewer = new Netlist(context); - + viewer.runYs(uri); } diff --git a/src/function/index.ts b/src/function/index.ts index e68d408..264d852 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -141,8 +141,8 @@ function registerNetlist(context: vscode.ExtensionContext) { ); context.subscriptions.push( - vscode.commands.registerCommand('digital-ide.netlist.run-ys', (uri) => { - + vscode.commands.registerCommand('digital-ide.netlist.run-ys', (uri: vscode.Uri) => { + Netlist.runYsScript(context, uri); }) ) diff --git a/src/global/util.ts b/src/global/util.ts index 619d964..2e036e7 100644 --- a/src/global/util.ts +++ b/src/global/util.ts @@ -263,3 +263,28 @@ export function getUserHomeDir(): AbsPath { const path = process.env.HOME || process.env.USERPROFILE || os.homedir(); return hdlPath.toSlash(path); } + +export function getDiskLetters(): Promise { + 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); + }); + }); +} \ No newline at end of file