Compare commits
10 Commits
d98dd69d8f
...
282c5b00da
Author | SHA1 | Date | |
---|---|---|---|
282c5b00da | |||
79c5c523ef | |||
![]() |
9fe382446b | ||
![]() |
f372aa4db0 | ||
![]() |
b949289ece | ||
![]() |
c6cc9fcdb4 | ||
![]() |
63fcb7a163 | ||
![]() |
99b1860f40 | ||
![]() |
e62428c38e | ||
![]() |
1a76d5ee81 |
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -8,6 +8,13 @@
|
||||
"typescript.tsc.autoDetect": "off",
|
||||
"i18n-haru.root": "l10n",
|
||||
"i18n-haru.main": "zh-cn",
|
||||
<<<<<<< HEAD
|
||||
"i18n-haru.line-hint-max-length": 20,
|
||||
"i18n-haru.custom-language-mapping": {
|
||||
"en": "l10n/bundle.l10n.json"
|
||||
}
|
||||
=======
|
||||
"i18n-haru.display": "zh-cn",
|
||||
"i18n-haru.line-hint-max-length": 20
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
## <code>Digital IDE</code> | All in one <code>vscode</code> plugin for Verilog/VHDL development
|
||||
|
||||
|
||||
[Document (New)](https://nc-ai.cn/) | [中文文档 (New)](https://nc-ai.cn/zh/) | [Bilibili Video](https://www.bilibili.com/video/BV1L19HYcEz6/?spm_id_from=333.1387.list.card_archive.click) | [Github](https://github.com/Digital-EDA/Digital-IDE)
|
||||
[Document (New)](https://nc-ai.cn/en/) | [中文文档 (New)](https://nc-ai.cn/) | [Bilibili Video](https://www.bilibili.com/video/BV1L19HYcEz6/?spm_id_from=333.1387.list.card_archive.click) | [Github](https://github.com/Digital-EDA/Digital-IDE)
|
||||
|
||||

|
||||

|
||||
|
@ -61,6 +61,9 @@
|
||||
"info.dide-doc.source.cannot-find": "Nicht gefunden",
|
||||
"info.command.instantiation.pick-title": "Select a Module",
|
||||
"warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!",
|
||||
<<<<<<< HEAD
|
||||
"info.launch.launch-digital-lsp": "启动 Digital LSP 语言服务器"
|
||||
=======
|
||||
"info.monitor.ppy.impl-change-to-project": "Änderungen werden auf das {0}-Projekt angewendet",
|
||||
"info.initialise.report.title": "Analyse von {0} HDL-Dateien abgeschlossen, {1} ungelöste Instanzmodule gefunden",
|
||||
"info.launch.following-folder-tracked": "Die Dateien im folgenden Ordner werden kontinuierlich analysiert und vollständige LSP-Dienste bereitgestellt.",
|
||||
@ -132,4 +135,5 @@
|
||||
"toolbar.save-as-html": "Als HTML speichern",
|
||||
"html-file": "HTML-Datei",
|
||||
"dide-doc.error.loading-html": "Digital CodeDoc-Ressourcen konnten nicht geladen werden, das Installationsverzeichnis ist beschädigt. Bitte installieren Sie das Programm neu!"
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52
|
||||
}
|
@ -61,6 +61,9 @@
|
||||
"info.dide-doc.source.cannot-find": "見つかりません",
|
||||
"info.command.instantiation.pick-title": "Select a Module",
|
||||
"warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!",
|
||||
<<<<<<< HEAD
|
||||
"info.launch.launch-digital-lsp": "启动 Digital LSP 语言服务器"
|
||||
=======
|
||||
"info.monitor.ppy.impl-change-to-project": "{0} プロジェクトに変更を適用しています",
|
||||
"info.initialise.report.title": "{0} 個のHDLファイルの解析が完了し、{1} 個の未解決のインスタンスモジュールが見つかりました",
|
||||
"info.launch.following-folder-tracked": "以下のフォルダ内のファイルは継続的に解析され、完全なLSPサービスが提供されます。",
|
||||
@ -132,4 +135,5 @@
|
||||
"toolbar.save-as-html": "HTMLとして保存",
|
||||
"html-file": "HTMLファイル",
|
||||
"dide-doc.error.loading-html": "Digital CodeDoc リソースの読み込みに失敗しました。インストールディレクトリが破損しています。再インストールしてください!"
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52
|
||||
}
|
@ -61,6 +61,9 @@
|
||||
"info.dide-doc.source.cannot-find": "Cannot find",
|
||||
"info.command.instantiation.pick-title": "Select a Module",
|
||||
"warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!",
|
||||
<<<<<<< HEAD:l10n/bundle.l10n.json
|
||||
"info.launch.launch-digital-lsp": "启动 Digital LSP 语言服务器"
|
||||
=======
|
||||
"info.monitor.ppy.impl-change-to-project": "Applying changes to the {0} project",
|
||||
"info.initialise.report.title": "Completed parsing {0} HDL files, found {1} unresolved instantiation modules",
|
||||
"info.launch.following-folder-tracked": "The files in the folder below will be continuously parsed and full LSP services will be provided.",
|
||||
@ -132,4 +135,5 @@
|
||||
"toolbar.save-as-html": "Save as HTML",
|
||||
"html-file": "HTML file",
|
||||
"dide-doc.error.loading-html": "Digital CodeDoc resource loading failed, the installation directory is corrupted, please reinstall!"
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52:l10n/bundle.l10n.en.json
|
||||
}
|
@ -61,6 +61,9 @@
|
||||
"info.dide-doc.source.cannot-find": "无法找到",
|
||||
"info.command.instantiation.pick-title": "选择一个模块",
|
||||
"warn.command.clean.prjPath-is-workspace": "arch.prjPath 和当前的工作区目录相同, clean 功能可能会删除整个项目,请检查你的 arch.prjPath !",
|
||||
<<<<<<< HEAD
|
||||
"info.launch.launch-digital-lsp": "启动 Digital LSP 语言服务器"
|
||||
=======
|
||||
"info.monitor.ppy.impl-change-to-project": "正在将修改应用于 {0} 项目中",
|
||||
"info.initialise.report.title": "完成 {0} 个 HDL 文件的解析,发现 {1} 个未解决的例化模块",
|
||||
"info.launch.following-folder-tracked": "下方文件夹中的文件将被持续解析并提供完整的 LSP 服务",
|
||||
@ -132,4 +135,5 @@
|
||||
"toolbar.save-as-html": "保存为 HTML",
|
||||
"html-file": "HTML 文件",
|
||||
"dide-doc.error.loading-html": "Digital CodeDoc 资源加载失败,安装目录已经损坏,请重新安装!"
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52
|
||||
}
|
@ -61,6 +61,9 @@
|
||||
"info.dide-doc.source.cannot-find": "無法找到",
|
||||
"info.command.instantiation.pick-title": "Select a Module",
|
||||
"warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!",
|
||||
<<<<<<< HEAD
|
||||
"info.launch.launch-digital-lsp": "启动 Digital LSP 语言服务器"
|
||||
=======
|
||||
"info.monitor.ppy.impl-change-to-project": "正在將修改應用於 {0} 專案中",
|
||||
"info.initialise.report.title": "完成 {0} 個 HDL 檔案的解析,發現 {1} 個未解決的例化模組",
|
||||
"info.launch.following-folder-tracked": "下方資料夾中的檔案將被持續解析並提供完整的LSP服務。",
|
||||
@ -132,4 +135,5 @@
|
||||
"toolbar.save-as-html": "保存為HTML",
|
||||
"html-file": "HTML檔案",
|
||||
"dide-doc.error.loading-html": "Digital CodeDoc 資源加載失敗,安裝目錄已經損壞,請重新安裝!"
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
"description": "all in one vscode plugin for Verilog/VHDL development",
|
||||
"publisher": "sterben",
|
||||
"homepage": "https://digital-eda.github.io/DIDE-doc-Cn",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.3",
|
||||
"main": "./out/extension",
|
||||
"l10n": "./l10n",
|
||||
"icon": "images/icon.png",
|
||||
|
@ -1,7 +0,0 @@
|
||||
set_param general.maxThreads 8
|
||||
create_project template d:/Project/FPGA/Design/TCL_project/Test/Efinity/prj/xilinx -part none -force
|
||||
set_property SOURCE_SET sources_1 [get_filesets sim_1]
|
||||
set_property top_lib xil_defaultlib [get_filesets sim_1]
|
||||
update_compile_order -fileset sim_1 -quiet
|
||||
source d:/Project/Code/.prj/Digital-IDE/resources/script/xilinx/refresh.tcl -quiet
|
||||
file delete d:/Project/Code/.prj/Digital-IDE/resources/script/xilinx/launch.tcl -force
|
@ -1,17 +0,0 @@
|
||||
remove_files -quiet [get_files]
|
||||
set xip_repo_paths {}
|
||||
set_property ip_repo_paths $xip_repo_paths [current_project] -quiet
|
||||
update_ip_catalog -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/async_fifo.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/DPRAM.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/ecc_decode.sv -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/ecc_encode.sv -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/ecc_pkg.sv -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/hbram/hbram_controller.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/hbram/hbram_ctrl.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/hbram/hyper_bus.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/hbram_test.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/spi_slave.v -quiet
|
||||
add_file d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/src/test.v -quiet
|
||||
add_files -fileset constrs_1 d:/Project/FPGA/Design/TCL_project/Test/Efinity/user/data -quiet
|
||||
file delete d:/Project/Code/.prj/Digital-IDE/resources/script/xilinx/refresh.tcl -force
|
@ -87,7 +87,11 @@ async function launch(context: vscode.ExtensionContext) {
|
||||
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Window,
|
||||
<<<<<<< HEAD
|
||||
title: t('info.launch.launch-digital-lsp')
|
||||
=======
|
||||
title: t('info.progress.launch-lsp')
|
||||
>>>>>>> 9fe382446ba6ff3efd72dae6924a0c493b950c52
|
||||
}, async () => {
|
||||
await lspClient.activate(context, packageJson);
|
||||
});
|
||||
|
@ -245,14 +245,27 @@ export async function clean() {
|
||||
const plName = opeParam.prjInfo.prjName.PL;
|
||||
const targetPath = fspath.dirname(opeParam.prjInfo.arch.hardware.src);
|
||||
|
||||
const sourceIpPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/ip`;
|
||||
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/bd`;
|
||||
if (hdlDir.isDir(`${workspacePath}/prj/xilinx/${plName}.gen`)) {
|
||||
const sourceIpPath = `${workspacePath}/prj/xilinx/${plName}.gen/sources_1/ip`;
|
||||
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.gen/sources_1/bd`;
|
||||
|
||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||
MainOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
|
||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||
MainOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
|
||||
|
||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||
MainOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
|
||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||
MainOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
|
||||
}
|
||||
|
||||
if (hdlDir.isDir(`${workspacePath}/prj/xilinx/${plName}.srcs`)) {
|
||||
const sourceIpPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/ip`;
|
||||
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/bd`;
|
||||
|
||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||
MainOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
|
||||
|
||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||
MainOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
|
||||
}
|
||||
|
||||
if (prjPath !== opeParam.workspacePath) {
|
||||
hdlDir.rmdir(prjPath);
|
||||
|
@ -2,6 +2,7 @@ import * as vscode from 'vscode';
|
||||
import { ChildProcessWithoutNullStreams, exec, spawn } from 'child_process';
|
||||
import * as fspath from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
|
||||
import { AbsPath, opeParam, PrjInfo } from '../../global';
|
||||
import { hdlParam } from '../../hdlParser/core';
|
||||
@ -13,9 +14,153 @@ import { HardwareOutput, MainOutput, ReportType } from '../../global/outputChann
|
||||
import { debounce, getPIDsWithName, killProcess } from '../../global/util';
|
||||
import { t } from '../../i18n';
|
||||
import { HdlFileProjectType } from '../../hdlParser/common';
|
||||
import { integer } from 'vscode-languageclient';
|
||||
import { AnyARecord } from 'dns';
|
||||
import { interfaces } from 'mocha';
|
||||
import { readJSON } from '../../hdlFs/file';
|
||||
import { c } from 'tar';
|
||||
|
||||
const syn = ` <efx:synthesis tool_name="efx_map">
|
||||
<efx:param name="work_dir" value="work_syn" value_type="e_string"/>
|
||||
type ChainInfo = [number, number, number, number];
|
||||
|
||||
interface efinixIO {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class EfinityOperation {
|
||||
prjScript: string;
|
||||
efxPath: string;
|
||||
deviceName: string;
|
||||
constructor() {
|
||||
this.prjScript = '';
|
||||
this.deviceName = '';
|
||||
this.efxPath = hdlPath.join(opeParam.workspacePath, `${opeParam.prjInfo.prjName.PL}.xml`);
|
||||
}
|
||||
|
||||
public launch() {
|
||||
this.prjScript = `<efx:project xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="${opeParam.prjInfo.prjName.PL}" description="" last_change="1724639062" sw_version="2023.2.307" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">\n${this.getDeviceInfo(opeParam.prjInfo.device)}\n${this.getDesignInfo()}\n${this.getConstraintInfo()}\n <efx:sim_info />\n <efx:misc_info />\n <efx:ip_info />\n${this.getSynthInfo()}\n${this.getPnRInfo()}\n${this.getBitstreamInfo()}\n${this.getDebugInfo()}\n${this.getSecurityInfo()}\n</efx:project>`;
|
||||
|
||||
fs.writeFileSync(this.efxPath, this.prjScript);
|
||||
|
||||
const peri_xml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<efxpt:design_db name="${opeParam.prjInfo.prjName.PL}" device_def="${this.deviceName}" location="${opeParam.workspacePath}" version="2023.2.307" db_version="20232999" xmlns:efxpt="http://www.efinixinc.com/peri_design_db" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/peri_design_db peri_design_db.xsd ">\n${this.getIODeviceConfig()}\n${this.getGPIOInfo()}\n${this.getPLLInfo()}\n${this.getOscInfo()}\n${this.getLVDSInfo()}\n${this.getJtagInfo()}\n${this.getMIPIInfo()}\n${this.getFlashInfo()}\n${this.getHBRAMConfig()}\n</efxpt:design_db>`;
|
||||
|
||||
fs.writeFileSync(hdlPath.join(opeParam.workspacePath, `${opeParam.prjInfo.prjName.PL}.peri.xml`), peri_xml);
|
||||
}
|
||||
|
||||
public simulate() {
|
||||
|
||||
}
|
||||
|
||||
public simulateCli() {
|
||||
|
||||
}
|
||||
|
||||
public simulateGui() {
|
||||
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
this.launch();
|
||||
}
|
||||
|
||||
public build() {
|
||||
exec(`${this.updateEfinixPath()} ${this.efxPath} --flow compile --work_dir=${opeParam.workspacePath}/prj/efinix --output_dir ${opeParam.workspacePath}/prj/efinix/outflow --cleanup_work_dir work_pt`, (error, stdout, stderr) => {
|
||||
console.log(error);
|
||||
console.log(stdout);
|
||||
console.log(stderr);
|
||||
})
|
||||
}
|
||||
|
||||
public synth() {
|
||||
|
||||
}
|
||||
|
||||
public impl() {
|
||||
|
||||
}
|
||||
|
||||
public bitstream() {
|
||||
|
||||
}
|
||||
|
||||
public program() {
|
||||
const bitPath = hdlPath.join(opeParam.workspacePath, 'outflow/efinix.bit');
|
||||
const svfPath = hdlPath.join(opeParam.workspacePath, 'efinix.svf');
|
||||
this.convert_to_SVF_TrionX(bitPath, svfPath, "10660A79", "6E6", 2000, true, [0, 0, 0, 0]);
|
||||
|
||||
// exec()
|
||||
}
|
||||
|
||||
public gui() {
|
||||
|
||||
}
|
||||
|
||||
public exit() {
|
||||
|
||||
}
|
||||
|
||||
public setSrcTop() {
|
||||
|
||||
}
|
||||
|
||||
public setSimTop() {
|
||||
|
||||
}
|
||||
|
||||
private getDeviceInfo(device: string): string {
|
||||
const deviceInfo = device.split('-');
|
||||
this.deviceName = deviceInfo[0];
|
||||
let family = 'Trion';
|
||||
if (device.slice(0, 2).toLowerCase() === 'ti') {
|
||||
family = 'Titanium';
|
||||
}
|
||||
|
||||
return ` <efx:device_info>
|
||||
<efx:family name="${family}"/>
|
||||
<efx:device name="${this.deviceName}"/>
|
||||
<efx:timing_model name="${deviceInfo[1]}"/>
|
||||
</efx:device_info>`;
|
||||
}
|
||||
|
||||
private getDesignInfo(): string {
|
||||
let designFile = ` <efx:top_module name="${opeParam.firstSrcTopModule.name}"/>\n`;
|
||||
for (const hdlFile of hdlParam.getAllHdlFiles()) {
|
||||
switch (hdlFile.projectType) {
|
||||
case HdlFileProjectType.Src:
|
||||
case HdlFileProjectType.LocalLib:
|
||||
case HdlFileProjectType.RemoteLib:
|
||||
case HdlFileProjectType.Sim:
|
||||
designFile += ` <efx:design_file name="${hdlFile.path}" version="default" library="default"/>\n`;
|
||||
break;
|
||||
case HdlFileProjectType.IP:
|
||||
case HdlFileProjectType.Primitive:
|
||||
// IP 和 原语不用管
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
designFile += ` <efx:top_vhdl_arch name=""/>`
|
||||
return ` <efx:design_info def_veri_version="verilog_2k" def_vhdl_version="vhdl_2008">\n${designFile}
|
||||
</efx:design_info>`
|
||||
};
|
||||
|
||||
private getConstraintInfo(): string {
|
||||
let constraintFile = '';
|
||||
hdlFile.pickFileRecursive(opeParam.prjInfo.arch.hardware.data, filePath => {
|
||||
if (filePath.endsWith('.sdc')) {
|
||||
constraintFile += ` <efx:sdc_file name="${filePath}" />\n`;
|
||||
}
|
||||
});
|
||||
|
||||
constraintFile += ` <efx:inter_file name="" />\n`;
|
||||
|
||||
return ` <efx:constraint_info>\n${constraintFile} </efx:constraint_info>`;
|
||||
}
|
||||
|
||||
private getSynthInfo(): string {
|
||||
return ` <efx:synthesis tool_name="efx_map">
|
||||
<efx:param name="work_dir" value="${opeParam.prjInfo.prjPath}/efinix/work_syn" value_type="e_string"/>
|
||||
<efx:param name="write_efx_verilog" value="on" value_type="e_bool"/>
|
||||
<efx:param name="mode" value="speed" value_type="e_option"/>
|
||||
<efx:param name="max_ram" value="-1" value_type="e_integer"/>
|
||||
@ -47,9 +192,11 @@ const syn = ` <efx:synthesis tool_name="efx_map">
|
||||
<efx:param name="use-logic-for-small-rom" value="64" value_type="e_integer"/>
|
||||
<efx:param name="insert-carry-skip" value="0" value_type="e_option"/>
|
||||
</efx:synthesis>`;
|
||||
}
|
||||
|
||||
const pnr = ` <efx:place_and_route tool_name="efx_pnr">
|
||||
<efx:param name="work_dir" value="work_pnr" value_type="e_string"/>
|
||||
private getPnRInfo(): string {
|
||||
return ` <efx:place_and_route tool_name="efx_pnr">
|
||||
<efx:param name="work_dir" value="${opeParam.prjInfo.prjPath}/efinix/work_pnr" value_type="e_string"/>
|
||||
<efx:param name="verbose" value="off" value_type="e_bool"/>
|
||||
<efx:param name="load_delaym" value="on" value_type="e_bool"/>
|
||||
<efx:param name="optimization_level" value="NULL" value_type="e_option"/>
|
||||
@ -59,8 +206,10 @@ const pnr = ` <efx:place_and_route tool_name="efx_pnr">
|
||||
<efx:param name="print_critical_path" value="10" value_type="e_integer"/>
|
||||
<efx:param name="beneficial_skew" value="on" value_type="e_option"/>
|
||||
</efx:place_and_route>`;
|
||||
}
|
||||
|
||||
const bit = ` <efx:bitstream_generation tool_name="efx_pgm">
|
||||
private getBitstreamInfo(): string {
|
||||
return ` <efx:bitstream_generation tool_name="${opeParam.prjInfo.prjPath}/efinix/efx_pgm">
|
||||
<efx:param name="mode" value="active" value_type="e_option"/>
|
||||
<efx:param name="width" value="1" value_type="e_option"/>
|
||||
<efx:param name="enable_roms" value="smart" value_type="e_option"/>
|
||||
@ -80,14 +229,18 @@ const bit = ` <efx:bitstream_generation tool_name="efx_pgm">
|
||||
<efx:param name="cold_boot" value="off" value_type="e_bool"/>
|
||||
<efx:param name="cascade" value="off" value_type="e_option"/>
|
||||
</efx:bitstream_generation>`;
|
||||
}
|
||||
|
||||
const debug = ` <efx:debugger>
|
||||
<efx:param name="work_dir" value="work_dbg" value_type="e_string"/>
|
||||
private getDebugInfo(): string {
|
||||
return ` <efx:debugger>
|
||||
<efx:param name="work_dir" value="${opeParam.prjInfo.prjPath}/efinix/work_dbg" value_type="e_string"/>
|
||||
<efx:param name="auto_instantiation" value="off" value_type="e_bool"/>
|
||||
<efx:param name="profile" value="NONE" value_type="e_string"/>
|
||||
</efx:debugger>`;
|
||||
}
|
||||
|
||||
const security = ` <efx:security>
|
||||
private getSecurityInfo(): string {
|
||||
return ` <efx:security>
|
||||
<efx:param name="randomize_iv_value" value="on" value_type="e_bool"/>
|
||||
<efx:param name="iv_value" value="" value_type="e_string"/>
|
||||
<efx:param name="enable_bitstream_encrypt" value="off" value_type="e_bool"/>
|
||||
@ -95,90 +248,293 @@ const security = ` <efx:security>
|
||||
<efx:param name="encryption_key_file" value="NONE" value_type="e_string"/>
|
||||
<efx:param name="auth_key_file" value="NONE" value_type="e_string"/>
|
||||
</efx:security>`;
|
||||
|
||||
export interface ePLContext {
|
||||
// 保留启动上下文
|
||||
terminal? : vscode.Terminal,
|
||||
// 目前使用的启动上下文
|
||||
process?: ChildProcessWithoutNullStreams,
|
||||
// 工具类型
|
||||
tool? : string,
|
||||
// 第三方工具运行路径
|
||||
path? : string,
|
||||
// 操作类
|
||||
ope : EfinityOperation,
|
||||
};
|
||||
|
||||
export class EfinityOperation {
|
||||
script: string;
|
||||
efxPath: string;
|
||||
constructor() {
|
||||
this.script = '';
|
||||
this.efxPath = hdlPath.join(opeParam.workspacePath, `${opeParam.prjInfo.prjName.PL}.xml`);
|
||||
}
|
||||
|
||||
private getDeviceInfo(device: string): string {
|
||||
const deviceInfo = device.split('-');
|
||||
let family = 'Trion';
|
||||
if (device.slice(0, 2).toLowerCase() === 'ti') {
|
||||
family = 'Titanium';
|
||||
private getIODeviceConfig(): string {
|
||||
|
||||
function getIOBankInfo(params:Record<string, string>): string {
|
||||
let iobankInfo = '';
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
iobankInfo += ` <efxpt:iobank name="${key}" iostd="${value}" is_dyn_voltage="false" mode_sel_name="${key}_MODE_SEL"/>\n`;
|
||||
}
|
||||
return ` <efxpt:iobank_info>\n${iobankInfo} </efxpt:iobank_info>`;
|
||||
}
|
||||
|
||||
return ` <efx:device_info>
|
||||
<efx:family name="${family}"/>
|
||||
<efx:device name="${deviceInfo[0]}"/>
|
||||
<efx:timing_model name="${deviceInfo[1]}"/>
|
||||
</efx:device_info>`;
|
||||
|
||||
function getReconfigInfo(params:Record<string, string>): string {
|
||||
let ctrlInfo = '';
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
ctrlInfo += ` <efxpt:ctrl name="${key}" ctrl_def="${value}" clock_name="" is_clk_invert="false" cbsel_bus_name="${key}_CBSEL" config_ctrl_name="${key}_CONFIG" ena_capture_name="${key}_ENA" error_status_name="${key}_ERROR" um_signal_status_name="${key}_USR_STATUS" is_remote_update_enable="false" is_user_mode_enable="false"/>\n`;
|
||||
}
|
||||
return ` <efxpt:ctrl_info>\n${ctrlInfo} </efxpt:ctrl_info>`;
|
||||
}
|
||||
|
||||
function getSeuInfo(params:Record<string, string>): string {
|
||||
let seuInfo = '';
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
seuInfo += ` <efxpt:seu name="${key}" block_def="${value}" mode="auto" ena_detect="false" wait_interval="16500000">\n <efxpt:gen_pin>\n <efxpt:pin name="${key}_START" type_name="START" is_bus="false"/>\n <efxpt:pin name="${key}_INJECT_ERROR" type_name="INJECT_ERROR" is_bus="false"/>\n <efxpt:pin name="${key}_RST" type_name="RST" is_bus="false"/>\n <efxpt:pin name="${key}_CONFIG" type_name="CONFIG" is_bus="false"/>\n <efxpt:pin name="${key}_ERROR" type_name="ERROR" is_bus="false"/>\n <efxpt:pin name="${key}_DONE" type_name="DONE" is_bus="false"/>\n </efxpt:gen_pin>\n </efxpt:seu>\n`;
|
||||
}
|
||||
return ` <efxpt:seu_info>\n${seuInfo} </efxpt:seu_info>`;
|
||||
}
|
||||
|
||||
function getCLKMUXInfo(params:Record<string, string>): string {
|
||||
let clkmuxInfo = '';
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
clkmuxInfo += ` <efxpt:clkmux name="${key}" block_def="${value}" is_mux_bot0_dyn="false" is_mux_bot7_dyn="false">\n <efxpt:gen_pin>\n <efxpt:pin name="" type_name="ROUTE0" is_bus="false" is_clk="true" is_clk_invert="false"/>\n <efxpt:pin name="" type_name="ROUTE1" is_bus="false" is_clk="true" is_clk_invert="false"/>\n <efxpt:pin name="" type_name="ROUTE2" is_bus="false" is_clk="true" is_clk_invert="false"/>\n <efxpt:pin name="" type_name="ROUTE3" is_bus="false" is_clk="true" is_clk_invert="false"/>\n <efxpt:pin name="" type_name="DYN_MUX_OUT_0" is_bus="false"/>\n <efxpt:pin name="" type_name="DYN_MUX_OUT_7" is_bus="false"/>\n <efxpt:pin name="" type_name="DYN_MUX_SEL_0" is_bus="true"/>\n <efxpt:pin name="" type_name="DYN_MUX_SEL_7" is_bus="true"/>\n </efxpt:gen_pin>\n </efxpt:clkmux>\n`;
|
||||
}
|
||||
return ` <efxpt:clkmux_info>\n${clkmuxInfo} </efxpt:clkmux_info>`;
|
||||
}
|
||||
|
||||
return ` <efxpt:device_info>\n${getIOBankInfo({
|
||||
"1A_4B" : "1.8 V LVCMOS",
|
||||
"1B" : "1.8 V LVCMOS",
|
||||
"2A_2B" : "1.8 V LVCMOS",
|
||||
"3A" : "1.8 V LVCMOS",
|
||||
"3B_4A" : "1.8 V LVCMOS",
|
||||
"BL" : "1.8 V LVCMOS"
|
||||
})}\n${getReconfigInfo({
|
||||
"cfg" : "CONFIG_CTRL0"
|
||||
})}\n${getSeuInfo({
|
||||
"seu" : "CONFIG_SEU0"
|
||||
})}\n${getCLKMUXInfo({
|
||||
"CLKMUX_B" : "CLKMUX_B",
|
||||
"CLKMUX_L" : "CLKMUX_L",
|
||||
"CLKMUX_R" : "CLKMUX_R",
|
||||
"CLKMUX_T" : "CLKMUX_T"
|
||||
})}
|
||||
<efxpt:ext_flash_ctrl_info>
|
||||
<efxpt:ext_flash_ctrl ena_ext_flash_ctrl="false"/>
|
||||
</efxpt:ext_flash_ctrl_info>
|
||||
</efxpt:device_info>`
|
||||
}
|
||||
|
||||
private getDesignInfo(): string {
|
||||
let designFile = ` <efx:top_module name="${opeParam.firstSrcTopModule.name}"/>\n`;
|
||||
for (const hdlFile of hdlParam.getAllHdlFiles()) {
|
||||
switch (hdlFile.projectType) {
|
||||
case HdlFileProjectType.Src:
|
||||
case HdlFileProjectType.LocalLib:
|
||||
case HdlFileProjectType.RemoteLib:
|
||||
case HdlFileProjectType.Sim:
|
||||
designFile += ` <efx:design_file name="${hdlFile.path}" version="default" library="default"/>\n`;
|
||||
break;
|
||||
case HdlFileProjectType.IP:
|
||||
case HdlFileProjectType.Primitive:
|
||||
// IP 和 原语不用管
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
private getGPIOInfo(): string {
|
||||
const topModule = hdlParam.getHdlModule(opeParam.firstSrcTopModule.path || '', opeParam.firstSrcTopModule.name);
|
||||
|
||||
if (!topModule) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const edc = readJSON(hdlPath.join(opeParam.prjInfo.arch.hardware.data, 'edc.json'));
|
||||
|
||||
let compGPIO = '';
|
||||
for (let index = 0; index < topModule.ports.length; index++) {
|
||||
const port = topModule.ports[index];
|
||||
if (port.type === 'input') {
|
||||
compGPIO += setCompInputGPIO(port.name, edc);
|
||||
} else if (port.type === 'output') {
|
||||
compGPIO += setCompOutputGPIO(port.name, edc);
|
||||
}
|
||||
}
|
||||
designFile += ` <efx:top_vhdl_arch name=""/>`
|
||||
return ` <efx:design_info def_veri_version="verilog_2k" def_vhdl_version="vhdl_2008">\n${designFile}
|
||||
</efx:design_info>`
|
||||
};
|
||||
|
||||
private getConstraintInfo(): string {
|
||||
let constraintFile = '';
|
||||
hdlFile.pickFileRecursive(opeParam.prjInfo.arch.hardware.data, filePath => {
|
||||
if (filePath.endsWith('.sdc')) {
|
||||
constraintFile += ` <efx:constraint_file name="${filePath}" />\n`;
|
||||
}
|
||||
|
||||
return ` <efxpt:gpio_info>\n${compGPIO} </efxpt:gpio_info>`;
|
||||
|
||||
function setCompOutputGPIO(name:string, param:Record<string, any>) {
|
||||
return ` <efxpt:comp_gpio name="${name}" gpio_def="${param[name].type}" mode="output" bus_name="" io_standard="${param[name].iostd}">
|
||||
<efxpt:output_config name="${name}" name_ddio_lo="" register_option="none" clock_name="" is_clock_inverted="false" is_slew_rate="false" tied_option="none" ddio_type="none" delay="0" is_serial="false" drive_strength="4" fastclk_name=""/>
|
||||
</efxpt:comp_gpio>\n`;
|
||||
}
|
||||
|
||||
function setCompInputGPIO(name:string, param:Record<string, any>): string {
|
||||
return ` <efxpt:comp_gpio name="${name}" gpio_def="${param[name].type}" mode="input" bus_name="" io_standard="${param[name].iostd}">
|
||||
<efxpt:input_config name="${name}" name_ddio_lo="" conn_type="normal" is_register="false" clock_name="" is_clock_inverted="false" pull_option="none" is_schmitt_trigger="false" ddio_type="none" is_bus_hold="false" delay="0" is_serial="false" is_dyn_delay="false" fastclk_name="" pullup_ena_name="${name}_PULL_UP_ENA" dyn_delay_en_name="${name}_DLY_ENA" dyn_delay_reset_name="${name}_DLY_RST" dyn_delay_ctrl_name="${name}_DLY_CTRL" clkmux_buf_name=""/>
|
||||
</efxpt:comp_gpio>\n`;
|
||||
}
|
||||
}
|
||||
|
||||
private getPLLInfo(): string {
|
||||
return ` <efxpt:pll_info/>`;
|
||||
}
|
||||
|
||||
private getOscInfo(): string {
|
||||
return ` <efxpt:osc_info/>`;
|
||||
}
|
||||
|
||||
private getLVDSInfo(): string {
|
||||
return ` <efxpt:lvds_info/>`;
|
||||
}
|
||||
|
||||
private getJtagInfo(): string {
|
||||
return ` <efxpt:jtag_info/>`;
|
||||
}
|
||||
|
||||
private getMIPIInfo(): string {
|
||||
return ` <efxpt:mipi_dphy_info/>`;
|
||||
}
|
||||
|
||||
private getFlashInfo(): string {
|
||||
return ` <efxpt:spi_flash_info/>`;
|
||||
}
|
||||
|
||||
private getHBRAMConfig(): string {
|
||||
return ` <efxpt:hyper_ram_info>
|
||||
<efxpt:hyper_ram name="hbc" block_def="HYPER_RAM0">
|
||||
<efxpt:gen_pin>
|
||||
<efxpt:pin name="ram_clk" type_name="CLK" is_bus="false" is_clk="true" is_clk_invert="false"/>
|
||||
<efxpt:pin name="ramclk90" type_name="CLK90" is_bus="false" is_clk="true" is_clk_invert="false"/>
|
||||
<efxpt:pin name="ram_clk_cal" type_name="CLKCAL" is_bus="false" is_clk="true" is_clk_invert="false"/>
|
||||
<efxpt:pin name="hbc_rst_n" type_name="RST_N" is_bus="false"/>
|
||||
<efxpt:pin name="hbc_cs_n" type_name="CS_N" is_bus="false"/>
|
||||
<efxpt:pin name="hbc_ck_p_HI" type_name="CK_P_HI" is_bus="false"/>
|
||||
<efxpt:pin name="hbc_ck_p_LO" type_name="CK_P_LO" is_bus="false"/>
|
||||
<efxpt:pin name="hbc_ck_N_HI" type_name="CK_N_HI" is_bus="false"/>
|
||||
<efxpt:pin name="hbc_ck_N_LO" type_name="CK_N_LO" is_bus="false"/>
|
||||
<efxpt:pin name="hbc_rwds_OUT_HI" type_name="RWDS_OUT_HI" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_rwds_OUT_LO" type_name="RWDS_OUT_LO" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_rwds_IN_HI" type_name="RWDS_IN_HI" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_rwds_IN_LO" type_name="RWDS_IN_LO" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_rwds_OE" type_name="RWDS_OE" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_dq_OUT_HI" type_name="DQ_OUT_HI" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_dq_OUT_LO" type_name="DQ_OUT_LO" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_dq_IN_HI" type_name="DQ_IN_HI" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_dq_IN_LO" type_name="DQ_IN_LO" is_bus="true"/>
|
||||
<efxpt:pin name="hbc_dq_OE" type_name="DQ_OE" is_bus="true"/>
|
||||
</efxpt:gen_pin>
|
||||
</efxpt:hyper_ram>
|
||||
</efxpt:hyper_ram_info>`
|
||||
}
|
||||
|
||||
private convert_to_SVF_TrionX(
|
||||
inputFile: string,
|
||||
destSVFFile: string,
|
||||
idcode: string,
|
||||
freq: string,
|
||||
sdrSize: number,
|
||||
enterUserMode: boolean,
|
||||
chainInfo: ChainInfo
|
||||
): void {
|
||||
const N = sdrSize;
|
||||
|
||||
// 读取 HEX 文件并转换为位数组(模拟 bitarray)
|
||||
const hexContent = fs.readFileSync(inputFile, 'utf-8').split(/\r?\n/);
|
||||
const numBits = this.get_bitstream_num_bits(inputFile);
|
||||
|
||||
const arr: boolean[] = [];
|
||||
hexContent.forEach(line => {
|
||||
const byte = parseInt(line, 16);
|
||||
const bits = byte.toString(2).padStart(8, '0');
|
||||
bits.split('').forEach(b => arr.push(b === '1'));
|
||||
});
|
||||
|
||||
constraintFile += ` <efx:inter_file name="" />\n`;
|
||||
// 处理 JTAG chain 信息
|
||||
const [len_hir, len_tir, len_hdr, len_tdr] = chainInfo;
|
||||
|
||||
return ` <efx:constraint_info>\n${constraintFile} </efx:constraint_info>`;
|
||||
const generateTDI = (length: number, bit: '0' | '1'): string => {
|
||||
if (length === 0) return '';
|
||||
const binary = Array(length).fill(bit).join('');
|
||||
const decimal = parseInt(binary, 2);
|
||||
return ` TDI (${decimal.toString(16).toUpperCase()})`;
|
||||
};
|
||||
|
||||
const hir_tdi = generateTDI(len_hir, '1');
|
||||
const tir_tdi = generateTDI(len_tir, '1');
|
||||
const hdr_tdi = generateTDI(len_hdr, '0');
|
||||
const tdr_tdi = generateTDI(len_tdr, '0');
|
||||
|
||||
// 构建 SVF 内容
|
||||
const svfLines: string[] = [
|
||||
'TRST OFF;',
|
||||
'ENDIR IDLE;',
|
||||
'ENDDR IDLE;',
|
||||
'STATE RESET;',
|
||||
'STATE IDLE;',
|
||||
`FREQUENCY ${freq} HZ;`,
|
||||
`TIR ${len_tir}${tir_tdi};`,
|
||||
`HIR ${len_hir}${hir_tdi};`,
|
||||
`TDR ${len_tdr}${tdr_tdi};`,
|
||||
`HDR ${len_hdr}${hdr_tdi};`,
|
||||
'// ',
|
||||
'// Check idcode',
|
||||
'SIR 5 TDI (3);',
|
||||
`SDR 32 TDI (00000000) TDO (${idcode}) MASK (ffffffff);`,
|
||||
'// ',
|
||||
'// Enter programming mode',
|
||||
'SIR 5 TDI (4);'
|
||||
];
|
||||
|
||||
if (idcode.toUpperCase() === '10660A79' || idcode.toUpperCase() === '10661A79') {
|
||||
svfLines.push('RUNTEST RESET 100 TCK;', 'SIR 5 TDI (4);');
|
||||
}
|
||||
|
||||
svfLines.push(
|
||||
'// ',
|
||||
'// Begin bitstream',
|
||||
'// ',
|
||||
'ENDDR DRPAUSE;',
|
||||
'HDR 0;',
|
||||
`TDR ${len_tdr}${tdr_tdi};`
|
||||
);
|
||||
|
||||
// 生成 SDR 命令
|
||||
let currBit = 0;
|
||||
while (currBit < numBits) {
|
||||
const demarcIndex = Math.min(currBit + N, numBits);
|
||||
const lineLength = demarcIndex - currBit;
|
||||
|
||||
let currLine = '';
|
||||
let nibbleBuffer = '';
|
||||
for (let i = currBit; i < demarcIndex; i++) {
|
||||
nibbleBuffer = (arr[i] ? '1' : '0') + nibbleBuffer;
|
||||
if (nibbleBuffer.length === 4) {
|
||||
currLine += parseInt(nibbleBuffer, 2).toString(16).toUpperCase();
|
||||
nibbleBuffer = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (nibbleBuffer.length > 0) {
|
||||
currLine += parseInt(nibbleBuffer.padEnd(4, '0'), 2).toString(16).toUpperCase();
|
||||
}
|
||||
|
||||
svfLines.push(`SDR ${lineLength} TDI (${currLine.split('').reverse().join('')});`);
|
||||
currBit = demarcIndex;
|
||||
}
|
||||
|
||||
// 添加额外 TCK
|
||||
const NUM_EXTRA_TCK = 2000;
|
||||
const NUM_EXTRA_TCK_LOOPS = (NUM_EXTRA_TCK / N) + 1;
|
||||
svfLines.push('// Extra clock ticks in SDR state');
|
||||
const tdiPattern = '0'.repeat(Math.ceil(N / 4));
|
||||
for (let i = 0; i < NUM_EXTRA_TCK_LOOPS; i++) {
|
||||
svfLines.push(`SDR ${N} TDI (${tdiPattern});`);
|
||||
}
|
||||
|
||||
// 用户模式处理
|
||||
svfLines.push('// ');
|
||||
if (enterUserMode) {
|
||||
svfLines.push(
|
||||
'// Enter user mode',
|
||||
'SIR 5 TDI (7);',
|
||||
'RUNTEST 100 TCK;'
|
||||
);
|
||||
} else {
|
||||
svfLines.push(
|
||||
'// Enter user mode -- DISABLED PER REQUEST',
|
||||
'// SIR 5 TDI (7);',
|
||||
'// RUNTEST 100 TCK;'
|
||||
);
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
fs.writeFileSync(destSVFFile, svfLines.join('\n'));
|
||||
}
|
||||
|
||||
public launch() {
|
||||
this.script = `<efx:project xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="${opeParam.prjInfo.prjName}" description="" last_change="1724639062" sw_version="2023.2.307" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">\n${this.getDeviceInfo(opeParam.prjInfo.device)}\n${this.getDesignInfo()}\n${this.getConstraintInfo()}\n <efx:sim_info />\n <efx:misc_info />\n <efx:ip_info />\n${syn}\n${pnr}\n${bit}\n${debug}\n${security}\n</efx:project>`;
|
||||
private get_bitstream_num_bits(input_file: string): integer {
|
||||
let ext = hdlPath.extname(input_file);
|
||||
let num_bytes = 0;
|
||||
if (ext === '.hex' || ext == '.bit') {
|
||||
const lines = fs.readFileSync(input_file, 'utf-8').split(/\r?\n/);
|
||||
num_bytes = lines.filter(line => {
|
||||
const trimmed = line.trim();
|
||||
|
||||
fs.writeFileSync(this.efxPath, this.script);
|
||||
// 有效性检查条件(根据你的 HEX 格式调整)
|
||||
return trimmed.length > 0 && // 非空行
|
||||
trimmed.length >= 2 && // 每行 2 个字符(例如 "1A")
|
||||
/^[0-9A-Fa-f]{2}$/.test(trimmed); // 合法 HEX 字符
|
||||
}).length;
|
||||
} else if (ext === '.bin') {
|
||||
num_bytes = fs.statSync(input_file).size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public build() {
|
||||
exec(`${this.updateEfinixPath()} ${this.efxPath} --flow compile --work_dir=${opeParam.workspacePath}/prj/efinix --output_dir ${opeParam.workspacePath}/prj/efinix/outflow --cleanup_work_dir work_pt`, (error, stdout, stderr) => {
|
||||
console.log(error);
|
||||
|
||||
})
|
||||
return num_bytes * 8;
|
||||
}
|
||||
|
||||
public updateEfinixPath(): string {
|
||||
|
@ -102,7 +102,6 @@ class PlManage extends BaseManage {
|
||||
this.context.ope.exit(this.context);
|
||||
}
|
||||
|
||||
|
||||
public setSrcTop(item: ModuleDataItem) {
|
||||
this.context.ope.setSrcTop(item.name, this.context);
|
||||
const type = moduleTreeProvider.getItemType(item);
|
||||
|
@ -286,14 +286,27 @@ class XilinxOperation {
|
||||
const plName = opeParam.prjInfo.prjName.PL;
|
||||
const targetPath = fspath.dirname(opeParam.prjInfo.arch.hardware.src);
|
||||
|
||||
const sourceIpPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/ip`;
|
||||
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/bd`;
|
||||
if (hdlDir.isDir(`${workspacePath}/prj/xilinx/${plName}.gen`)) {
|
||||
const sourceIpPath = `${workspacePath}/prj/xilinx/${plName}.gen/sources_1/ip`;
|
||||
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.gen/sources_1/bd`;
|
||||
|
||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||
HardwareOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
|
||||
|
||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||
HardwareOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
|
||||
}
|
||||
|
||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||
HardwareOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
|
||||
|
||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||
HardwareOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
|
||||
if (hdlDir.isDir(`${workspacePath}/prj/xilinx/${plName}.srcs`)) {
|
||||
const sourceIpPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/ip`;
|
||||
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/bd`;
|
||||
|
||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||
HardwareOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
|
||||
|
||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||
HardwareOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
|
||||
}
|
||||
|
||||
await this.closeAllWindows();
|
||||
}
|
||||
@ -1082,7 +1095,6 @@ const tools = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export {
|
||||
XilinxOperation,
|
||||
tools,
|
||||
|
@ -14,8 +14,8 @@ import { hdlIgnore } from './ignore';
|
||||
import { hdlMonitor } from '../monitor';
|
||||
import { t } from '../i18n';
|
||||
import { PpyAction } from '../monitor/propery';
|
||||
import { checkJson, readJSON } from '../hdlFs/file';
|
||||
|
||||
import { checkJson, readJSON, writeJSON } from '../hdlFs/file';
|
||||
import { PropertySchema } from '../global/propertySchema';
|
||||
|
||||
interface RefreshPrjConfig {
|
||||
mkdir: boolean
|
||||
@ -36,7 +36,7 @@ class PrjManage {
|
||||
}
|
||||
|
||||
const cachePPy = hdlPath.join(opeParam.dideHome, 'property-init.json');
|
||||
const propertyInitPath = fs.existsSync(cachePPy) ? cachePPy: opeParam.propertyInitPath;
|
||||
const propertyInitPath = fs.existsSync(cachePPy) ? cachePPy : opeParam.propertyInitPath;
|
||||
|
||||
const template = hdlFile.readJSON(propertyInitPath) as RawPrjInfo;
|
||||
hdlFile.writeJSON(opeParam.propertyJsonPath, template);
|
||||
@ -87,15 +87,15 @@ class PrjManage {
|
||||
const propertySchemaPath = hdlPath.join(extensionPath, 'project', 'property-schema.json');
|
||||
const propertyInitPath = hdlPath.join(extensionPath, 'project', 'property-init.json');
|
||||
|
||||
opeParam.setBasicInfo(os,
|
||||
extensionPath,
|
||||
workspacePath,
|
||||
propertyJsonPath,
|
||||
propertySchemaPath,
|
||||
propertyInitPath);
|
||||
|
||||
opeParam.setBasicInfo(os,
|
||||
extensionPath,
|
||||
workspacePath,
|
||||
propertyJsonPath,
|
||||
propertySchemaPath,
|
||||
propertyInitPath);
|
||||
|
||||
opeParam.prjInfo.initContextPath(extensionPath, workspacePath);
|
||||
const refreshPrjConfig: RefreshPrjConfig = {mkdir: true};
|
||||
const refreshPrjConfig: RefreshPrjConfig = { mkdir: true };
|
||||
if (fs.existsSync(propertyJsonPath)) {
|
||||
const rawPrjInfo = hdlFile.readJSON(propertyJsonPath) as RawPrjInfo;
|
||||
opeParam.mergePrjInfo(rawPrjInfo);
|
||||
@ -135,7 +135,7 @@ class PrjManage {
|
||||
// 先处理 lib 文件
|
||||
// const fileChange = await libManage.processLibFiles(prjInfo.library);
|
||||
// MainOutput.report(`libManage finish process, add ${fileChange.add.length} files, del ${fileChange.del.length} files`;
|
||||
|
||||
|
||||
// 默认搜索路径包括:
|
||||
// src, sim, lib
|
||||
searchPathSet.checkAdd(prjInfo.hardwareSrcPath);
|
||||
@ -145,7 +145,7 @@ class PrjManage {
|
||||
searchPathSet.checkAdd(prjInfo.getLibraryCustomPaths());
|
||||
}
|
||||
|
||||
const reportMsg = ['', ... searchPathSet.files].join('\n\t');
|
||||
const reportMsg = ['', ...searchPathSet.files].join('\n\t');
|
||||
MainOutput.report(t('info.launch.search-and-parse') + reportMsg, {
|
||||
level: ReportType.Run
|
||||
});
|
||||
@ -161,12 +161,12 @@ class PrjManage {
|
||||
*/
|
||||
public async getPrjIPs() {
|
||||
const toolchain = opeParam.prjInfo.toolChain;
|
||||
|
||||
|
||||
switch (toolchain) {
|
||||
case 'xilinx':
|
||||
return this.getXilinxIPs();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -202,14 +202,14 @@ class PrjManage {
|
||||
|
||||
// 初始化 ignore
|
||||
hdlIgnore.updatePatterns();
|
||||
|
||||
|
||||
// 解析 hdl 文件,构建 hdlParam
|
||||
const hdlFiles = await this.getPrjHardwareFiles();
|
||||
const hdlFiles = await this.getPrjHardwareFiles();
|
||||
await hdlParam.initializeHdlFiles(hdlFiles, progress);
|
||||
|
||||
// 根据 toolchain 解析合法的 IP,构建 hdlParam
|
||||
const IPsPath = await this.getPrjIPs();
|
||||
await hdlParam.initializeIPsPath(IPsPath, progress);
|
||||
await hdlParam.initializeIPsPath(IPsPath, progress);
|
||||
|
||||
// 构建 instance 解析
|
||||
await hdlParam.makeAllInstance();
|
||||
@ -253,7 +253,7 @@ class PrjManage {
|
||||
public async createFolderByRawPrjInfo(rawPrjInfo: RawPrjInfo) {
|
||||
if (rawPrjInfo.arch) {
|
||||
hdlDir.mkdir(rawPrjInfo.arch.prjPath);
|
||||
|
||||
|
||||
const hardware = rawPrjInfo.arch.hardware;
|
||||
const software = rawPrjInfo.arch.software;
|
||||
|
||||
@ -277,10 +277,10 @@ class PrjManage {
|
||||
|
||||
// 如果 soc.core 有效,那么就是 LS,否则是 PL
|
||||
const nextmode = this.getNextMode(rawPrjInfo);
|
||||
|
||||
|
||||
const hardware = opeParam.prjInfo.arch.hardware;
|
||||
const software = opeParam.prjInfo.arch.software;
|
||||
|
||||
|
||||
hdlDir.mkdir(hardware.src);
|
||||
hdlDir.mkdir(hardware.sim);
|
||||
hdlDir.mkdir(hardware.data);
|
||||
@ -331,9 +331,9 @@ class PrjManage {
|
||||
workspace: string,
|
||||
plname: string
|
||||
) {
|
||||
const xilinxPL = plname + '.srcs';
|
||||
const xilinxPS = plname + '.sdk';
|
||||
const ignores = ['user', 'prj', '.vscode', xilinxPL, xilinxPS];
|
||||
const xilinxPL = [plname + '.srcs', plname + '.gen'];
|
||||
const xilinxPS = [plname + '.sdk'];
|
||||
const ignores = ['user', 'prj', '.vscode'].concat(xilinxPL, xilinxPS);
|
||||
hdlDir.rmdir(hdlPath.join(workspace, '.Xil'));
|
||||
for (const file of fs.readdirSync(workspace)) {
|
||||
// 排除标准文件夹
|
||||
@ -386,7 +386,6 @@ class PrjManage {
|
||||
hdlDir.rmdir(bdPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description 搬移 Xilinx 项目中的 IP
|
||||
@ -398,24 +397,44 @@ class PrjManage {
|
||||
workspace: string,
|
||||
plname: string
|
||||
) {
|
||||
const xilinxSrcsPath = hdlPath.join(workspace, plname + '.srcs');
|
||||
const standardIpPath = hdlPath.join(workspace, 'user', 'ip');
|
||||
if (!fs.existsSync(xilinxSrcsPath)) {
|
||||
return;
|
||||
|
||||
if (hdlDir.isDir(hdlPath.join(workspace, plname + '.gen'))) {
|
||||
const xilinxSrcsPath = hdlPath.join(workspace, plname + '.gen');
|
||||
|
||||
const sourceNames = fs.readdirSync(xilinxSrcsPath).filter(filename => filename.startsWith(matchPrefix));
|
||||
for (const sn of sourceNames) {
|
||||
const ipPath = hdlPath.join(xilinxSrcsPath, sn, 'ip');
|
||||
|
||||
if (!hdlFile.isDir(ipPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const ipname of fs.readdirSync(ipPath)) {
|
||||
const sourcePath = hdlPath.join(ipPath, ipname);
|
||||
hdlDir.mvdir(sourcePath, standardIpPath, true);
|
||||
}
|
||||
hdlDir.rmdir(ipPath);
|
||||
}
|
||||
}
|
||||
const sourceNames = fs.readdirSync(xilinxSrcsPath).filter(filename => filename.startsWith(matchPrefix));
|
||||
for (const sn of sourceNames) {
|
||||
const ipPath = hdlPath.join(xilinxSrcsPath, sn, 'ip');
|
||||
|
||||
if (!hdlFile.isDir(ipPath)) {
|
||||
continue;
|
||||
}
|
||||
if (hdlDir.isDir(hdlPath.join(workspace, plname + '.srcs'))) {
|
||||
const xilinxSrcsPath = hdlPath.join(workspace, plname + '.srcs');
|
||||
|
||||
for (const ipname of fs.readdirSync(ipPath)) {
|
||||
const sourcePath = hdlPath.join(ipPath, ipname);
|
||||
hdlDir.mvdir(sourcePath, standardIpPath, true);
|
||||
const sourceNames = fs.readdirSync(xilinxSrcsPath).filter(filename => filename.startsWith(matchPrefix));
|
||||
for (const sn of sourceNames) {
|
||||
const ipPath = hdlPath.join(xilinxSrcsPath, sn, 'ip');
|
||||
|
||||
if (!hdlFile.isDir(ipPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const ipname of fs.readdirSync(ipPath)) {
|
||||
const sourcePath = hdlPath.join(ipPath, ipname);
|
||||
hdlDir.mvdir(sourcePath, standardIpPath, true);
|
||||
}
|
||||
hdlDir.rmdir(ipPath);
|
||||
}
|
||||
hdlDir.rmdir(ipPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,7 +491,7 @@ class PrjManage {
|
||||
}
|
||||
const standardSdkPath = hdlPath.join(workspace, 'user', 'sdk');
|
||||
hdlDir.mvdir(xilinxSdkPath, standardSdkPath, true);
|
||||
|
||||
|
||||
const hwNames = fs.readdirSync(standardSdkPath).filter(filename => filename.includes("_hw_platform_"));
|
||||
if (hwNames.length === 0) {
|
||||
return;
|
||||
@ -500,7 +519,7 @@ class PrjManage {
|
||||
location: vscode.ProgressLocation.Notification
|
||||
}, async () => {
|
||||
// 先获取 project name
|
||||
const xprfile = xprFile();
|
||||
const xprfile = xprFile();
|
||||
if (xprfile === undefined) {
|
||||
MainOutput.report(t('error.command.structure.not-valid-xilinx-project'), {
|
||||
level: ReportType.Error,
|
||||
@ -509,9 +528,22 @@ class PrjManage {
|
||||
return;
|
||||
}
|
||||
|
||||
const xprContext = hdlFile.readFile(hdlPath.join(opeParam.workspacePath, xprfile)) || '';
|
||||
const deviceRegExp = new RegExp([
|
||||
/<Option\s+Name=\"Part\"\s+/,
|
||||
/Val=\"(?<name>.+)\"\/>/
|
||||
].map(x => (typeof x === 'string') ? x : x.source).join(''), 'mg');
|
||||
|
||||
const deviceMatch = deviceRegExp.exec(xprContext);
|
||||
if (deviceMatch == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deviceInfo = deviceMatch.groups?.name || '';
|
||||
|
||||
const plname = xprfile.slice(0, -4);
|
||||
const workspacePath = opeParam.workspacePath;
|
||||
|
||||
|
||||
// 创建标准项目结构基本文件夹
|
||||
// xilinx prj
|
||||
hdlDir.mkdir(hdlPath.join(workspacePath, 'prj', 'xilinx'));
|
||||
@ -546,9 +578,10 @@ class PrjManage {
|
||||
transformXilinxPL('data', 'constrs_', workspacePath, plname);
|
||||
// 迁移文件夹 ${workspace}/${plname}.sdk
|
||||
transformXilinxPS(workspacePath, plname);
|
||||
|
||||
|
||||
// 删除原本的项目文件夹 ${workspace}/${plname}.srcs 和 ${workspace}/${plname}.sdk
|
||||
hdlDir.rmdir(hdlPath.join(workspacePath, plname + '.srcs'));
|
||||
hdlDir.rmdir(hdlPath.join(workspacePath, plname + '.gen'));
|
||||
hdlDir.rmdir(hdlPath.join(workspacePath, plname + '.sdk'));
|
||||
|
||||
// 创建 property.json
|
||||
@ -557,33 +590,23 @@ class PrjManage {
|
||||
PL: plname
|
||||
};
|
||||
|
||||
ppyTemplate.device = deviceInfo;
|
||||
hdlFile.writeJSON(opeParam.propertyJsonPath, ppyTemplate);
|
||||
|
||||
const propertyParam = hdlFile.readJSON(opeParam.propertySchemaPath) as PropertySchema;
|
||||
|
||||
// 同步到缓存中
|
||||
if (!propertyParam.properties.device.enum.includes(deviceInfo)) {
|
||||
const dideHome = opeParam.dideHome;
|
||||
const cachePPy = hdlPath.join(dideHome, 'property-schema.json');
|
||||
propertyParam.properties.device.enum.push(deviceInfo);
|
||||
hdlFile.writeJSON(opeParam.propertySchemaPath, propertyParam);
|
||||
hdlFile.writeJSON(cachePPy, propertyParam);
|
||||
}
|
||||
});
|
||||
|
||||
const res = await vscode.window.showInformationMessage(
|
||||
t('info.command.structure.reload-vscode'),
|
||||
{ title: t('info.common.confirm'), value: true }
|
||||
);
|
||||
|
||||
if (res?.value) {
|
||||
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
}
|
||||
|
||||
// await vscode.window.withProgress({
|
||||
// location: vscode.ProgressLocation.Window,
|
||||
// title: t('info.progress.initialization')
|
||||
// }, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||
// hdlParam.clear();
|
||||
|
||||
// // 初始化解析
|
||||
// await this.initialise(context, progress, false);
|
||||
|
||||
// // 刷新结构树
|
||||
// refreshArchTree();
|
||||
|
||||
// // 启动监视器
|
||||
// hdlMonitor.start();
|
||||
// });
|
||||
// 直接重启vscode
|
||||
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user