支持直接运行 ys
This commit is contained in:
parent
aa3b3b529a
commit
0321ab8a78
@ -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",
|
||||
|
@ -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"
|
||||
}
|
@ -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 スクリプトを実行"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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 脚本"
|
||||
}
|
@ -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 腳本"
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
})
|
||||
)
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user