支持直接运行 ys

This commit is contained in:
锦恢 2025-01-06 17:54:05 +08:00
parent aa3b3b529a
commit 0321ab8a78
9 changed files with 142 additions and 44 deletions

View File

@ -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",

View File

@ -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"
}

View File

@ -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 スクリプトを実行"
}

View File

@ -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"
}

View File

@ -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 脚本"
}

View File

@ -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 腳本"
}

View File

@ -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);
}

View File

@ -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);
})
)

View File

@ -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<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);
});
});
}