支持直接运行 ys
This commit is contained in:
parent
aa3b3b529a
commit
0321ab8a78
@ -558,11 +558,11 @@
|
|||||||
{
|
{
|
||||||
"command": "digital-ide.netlist.run-ys",
|
"command": "digital-ide.netlist.run-ys",
|
||||||
"icon": {
|
"icon": {
|
||||||
"light": "images/svg/light/netlist.svg",
|
"light": "images/svg/light/ys.svg",
|
||||||
"dark": "images/svg/dark/netlist.svg"
|
"dark": "images/svg/dark/ys.svg"
|
||||||
},
|
},
|
||||||
"category": "Digital-IDE",
|
"category": "Digital-IDE",
|
||||||
"title": "%digital-ide.netlist.title%"
|
"title": "%digital-ide.run-ys.title%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "digital-ide.fsm",
|
"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.title": "Diagnoselevel-Einstellungen des Linters",
|
||||||
"digital-ide.function.lsp.linter.linter-level.error.title": "Nur Fehler anzeigen",
|
"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.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.title": "Netlist-Synthesemodus auswählen",
|
||||||
"%digital-ide.function.netlist.schema-mode.0.title%": "Prä-Verhaltenssynthese",
|
"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.1.title": "Post-Verhaltenssynthese",
|
||||||
"%digital-ide.function.netlist.schema-mode.2.title%": "Post-RTL-Synthese"
|
"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.title": "診断器の診断レベル設定",
|
||||||
"digital-ide.function.lsp.linter.linter-level.error.title": "エラーのみ表示",
|
"digital-ide.function.lsp.linter.linter-level.error.title": "エラーのみ表示",
|
||||||
"digital-ide.function.lsp.linter.linter-level.warning.title": "エラーと警告を表示",
|
"digital-ide.function.lsp.linter.linter-level.warning.title": "エラーと警告を表示",
|
||||||
"%digital-ide.function.netlist.schema-mode.title%": "Netlist 合成モードを選択",
|
"digital-ide.function.netlist.schema-mode.title": "Netlist 合成モードを選択",
|
||||||
"%digital-ide.function.netlist.schema-mode.0.title%": "ビヘイビア前合成",
|
"digital-ide.function.netlist.schema-mode.0.title": "ビヘイビア前合成",
|
||||||
"%digital-ide.function.netlist.schema-mode.1.title%": "ビヘイビア後合成",
|
"digital-ide.function.netlist.schema-mode.1.title": "ビヘイビア後合成",
|
||||||
"%digital-ide.function.netlist.schema-mode.2.title%": "RTL後合成"
|
"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.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.error.title": "Show Only Errors",
|
||||||
"digital-ide.function.lsp.linter.linter-level.warning.title": "Show Errors and Warnings",
|
"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.title": "Select Netlist Synthesis Mode",
|
||||||
"%digital-ide.function.netlist.schema-mode.0.title%": "Pre-Behavioral Synthesis",
|
"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.1.title": "Post-Behavioral Synthesis",
|
||||||
"%digital-ide.function.netlist.schema-mode.2.title%": "Post-RTL 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.title": "诊断器诊断等级设置",
|
||||||
"digital-ide.function.lsp.linter.linter-level.error.title": "只显示错误",
|
"digital-ide.function.lsp.linter.linter-level.error.title": "只显示错误",
|
||||||
"digital-ide.function.lsp.linter.linter-level.warning.title": "显示错误和警告",
|
"digital-ide.function.lsp.linter.linter-level.warning.title": "显示错误和警告",
|
||||||
"%digital-ide.function.netlist.schema-mode.title%": "选择 Netlist 综合模式",
|
"digital-ide.function.netlist.schema-mode.title": "选择 Netlist 综合模式",
|
||||||
"%digital-ide.function.netlist.schema-mode.0.title%": "行为前综合",
|
"digital-ide.function.netlist.schema-mode.0.title": "行为前综合",
|
||||||
"%digital-ide.function.netlist.schema-mode.1.title%": "行为后综合",
|
"digital-ide.function.netlist.schema-mode.1.title": "行为后综合",
|
||||||
"%digital-ide.function.netlist.schema-mode.2.title%": "RTL后综合"
|
"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.title": "診斷器診斷等級設置",
|
||||||
"digital-ide.function.lsp.linter.linter-level.error.title": "只顯示錯誤",
|
"digital-ide.function.lsp.linter.linter-level.error.title": "只顯示錯誤",
|
||||||
"digital-ide.function.lsp.linter.linter-level.warning.title": "顯示錯誤和警告",
|
"digital-ide.function.lsp.linter.linter-level.warning.title": "顯示錯誤和警告",
|
||||||
"%digital-ide.function.netlist.schema-mode.title%": "選擇 Netlist 綜合模式",
|
"digital-ide.function.netlist.schema-mode.title": "選擇 Netlist 綜合模式",
|
||||||
"%digital-ide.function.netlist.schema-mode.0.title%": "行為前綜合",
|
"digital-ide.function.netlist.schema-mode.0.title": "行為前綜合",
|
||||||
"%digital-ide.function.netlist.schema-mode.1.title%": "行為後綜合",
|
"digital-ide.function.netlist.schema-mode.1.title": "行為後綜合",
|
||||||
"%digital-ide.function.netlist.schema-mode.2.title%": "RTL後綜合"
|
"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 vscode from 'vscode';
|
||||||
import * as fspath from 'path';
|
import * as fspath from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import * as os from 'os';
|
||||||
|
|
||||||
import { WASI } from 'wasi';
|
import { WASI } from 'wasi';
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ import { HdlFile } from '../../hdlParser/core';
|
|||||||
import { t } from '../../i18n';
|
import { t } from '../../i18n';
|
||||||
import { HdlLangID } from '../../global/enum';
|
import { HdlLangID } from '../../global/enum';
|
||||||
import { getIconConfig } from '../../hdlFs/icons';
|
import { getIconConfig } from '../../hdlFs/icons';
|
||||||
import { PathSet } from '../../global/util';
|
import { getDiskLetters, PathSet } from '../../global/util';
|
||||||
import { gotoDefinition, saveAsPdf, saveAsSvg } from './api';
|
import { gotoDefinition, saveAsPdf, saveAsSvg } from './api';
|
||||||
|
|
||||||
type SynthMode = 'before' | 'after' | 'RTL';
|
type SynthMode = 'before' | 'after' | 'RTL';
|
||||||
@ -31,7 +32,7 @@ class Netlist {
|
|||||||
this.libName = '{library}';
|
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 pathset = new PathSet();
|
||||||
const path = hdlPath.toSlash(uri.fsPath);
|
const path = hdlPath.toSlash(uri.fsPath);
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ class Netlist {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wasm = this.wasm;
|
const wasm = this.wasm;
|
||||||
const wasiResult = this.makeWasi(targetYs, moduleName);
|
const wasiResult = await this.makeWasi(targetYs, moduleName);
|
||||||
|
|
||||||
if (wasiResult === undefined) {
|
if (wasiResult === undefined) {
|
||||||
return;
|
return;
|
||||||
@ -106,7 +107,8 @@ class Netlist {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!fs.existsSync(targetJson)) {
|
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(
|
const res = await vscode.window.showErrorMessage(
|
||||||
t('error.cannot-gen-netlist'),
|
t('error.cannot-gen-netlist'),
|
||||||
{ title: t('error.look-up-log'), value: true }
|
{ title: t('error.look-up-log'), value: true }
|
||||||
@ -167,12 +169,31 @@ class Netlist {
|
|||||||
return target.replace(opeParam.workspacePath, this.wsName);
|
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);
|
hdlFile.removeFile(logFilePath);
|
||||||
const logFd = fs.openSync(logFilePath, 'a');
|
const logFd = fs.openSync(logFilePath, 'a');
|
||||||
|
|
||||||
|
console.log(target);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const wasiOption = {
|
const wasiOption = {
|
||||||
version: 'preview1',
|
version: 'preview1',
|
||||||
@ -181,11 +202,7 @@ class Netlist {
|
|||||||
'-s',
|
'-s',
|
||||||
target
|
target
|
||||||
],
|
],
|
||||||
preopens: {
|
preopens: await this.getPreopens(),
|
||||||
'/share': hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'static', 'share'),
|
|
||||||
[this.wsName ]: opeParam.workspacePath,
|
|
||||||
[this.libName]: opeParam.prjInfo.libCommonPath
|
|
||||||
},
|
|
||||||
stdin: process.stdin.fd,
|
stdin: process.stdin.fd,
|
||||||
stdout: process.stdout.fd,
|
stdout: process.stdout.fd,
|
||||||
stderr: logFd,
|
stderr: logFd,
|
||||||
@ -228,12 +245,6 @@ class Netlist {
|
|||||||
fs.closeSync(fd);
|
fs.closeSync(fd);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.panel.webview.onDidReceiveMessage(message => {
|
|
||||||
switch (message.command) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}, undefined, this.context.subscriptions);
|
|
||||||
|
|
||||||
const previewHtml = this.getWebviewContent();
|
const previewHtml = this.getWebviewContent();
|
||||||
if (this.panel && previewHtml) {
|
if (this.panel && previewHtml) {
|
||||||
const netlistPath = hdlPath.join(opeParam.extensionPath, 'resources', 'dide-netlist', 'view');
|
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) {
|
export async function runYsScript(context: vscode.ExtensionContext, uri: vscode.Uri) {
|
||||||
const viewer = new Netlist(context);
|
const viewer = new Netlist(context);
|
||||||
|
viewer.runYs(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,8 +141,8 @@ function registerNetlist(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
context.subscriptions.push(
|
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();
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user