#add FSM | #add Netlist
1
css/boxicons.2.0.7.min.css
vendored
Normal file
BIN
fonts/boxicons.woff2
Normal file
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const fspath = require("path");
|
const fspath = require("path");
|
||||||
const vscode = require("vscode");
|
const vscode = require("vscode");
|
||||||
@ -198,7 +199,7 @@ class FsmViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getWebviewContent() {
|
getWebviewContent() {
|
||||||
const resource_path = fspath.join(this.rootPath, 'resources', 'fsm', 'fsm_viewer.html');
|
const resource_path = fspath.join(this.rootPath, 'resources', 'fsm', 'view', 'fsm_viewer.html');
|
||||||
const dir_path = fspath.dirname(resource_path);
|
const dir_path = fspath.dirname(resource_path);
|
||||||
|
|
||||||
let html = fs.readFileSync(resource_path, 'utf-8');
|
let html = fs.readFileSync(resource_path, 'utf-8');
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<script src="../../public/full.render.js"></script>
|
<script src="../../public/full.render.js"></script>
|
||||||
<script src="../../public/viz.js"></script>
|
<script src="../../public/viz.js"></script>
|
||||||
<div id="svg" style="text-align: center;"></div>
|
<div id="svg" style="text-align: center;"></div>
|
||||||
<link rel="stylesheet" href="../../css/fsm_viewer.css" type="text/css" />
|
<link rel="stylesheet" href="../../../css/fsm_viewer.css" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="fsm_draw.js"></script>
|
<script src="./fsm_draw.js"></script>
|
||||||
<div id="error-info" class="trontron">
|
<div id="error-info" class="trontron">
|
||||||
<div id="inner" class="fuck"></div>
|
<div id="inner" class="fuck"></div>
|
||||||
</div>
|
</div>
|
||||||
|
28
resources/netlist/index.d.ts
vendored
@ -0,0 +1,28 @@
|
|||||||
|
interface SynthOptions {
|
||||||
|
path: string
|
||||||
|
type: string
|
||||||
|
argu: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExportOptions {
|
||||||
|
path?: string
|
||||||
|
type?: string
|
||||||
|
argu?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module Netlist {
|
||||||
|
export class NetlistKernel {
|
||||||
|
public async launch();
|
||||||
|
public exec(command: string);
|
||||||
|
public printHelp(): string;
|
||||||
|
public setInnerOutput(params: boolean);
|
||||||
|
public setMessageCallback(callback: (message: string, type: string) => void);
|
||||||
|
public load(files: string[]): string;
|
||||||
|
public synth(options: SynthOptions);
|
||||||
|
public export(options: ExportOptions): string;
|
||||||
|
public reset();
|
||||||
|
public exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = Netlist;
|
@ -1,9 +1,10 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const fs = require("../HDLfilesys");
|
|
||||||
|
|
||||||
const kernel = require("./kernel");
|
const kernel = require('./utils/kernel');
|
||||||
|
const Vrfs = require('./utils/vrfs');
|
||||||
|
|
||||||
class Operation {
|
class NetlistKernel {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.kernel = null;
|
this.kernel = null;
|
||||||
this.vrfs = null;
|
this.vrfs = null;
|
||||||
@ -11,7 +12,7 @@ class Operation {
|
|||||||
|
|
||||||
async launch() {
|
async launch() {
|
||||||
this.kernel = await kernel();
|
this.kernel = await kernel();
|
||||||
this.vrfs = new fs.vrfs(this.kernel);
|
this.vrfs = new Vrfs(this.kernel);
|
||||||
this.vrfs.diskMount();
|
this.vrfs.diskMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,4 +146,6 @@ class Operation {
|
|||||||
this.vrfs = null;
|
this.vrfs = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = operation;
|
module.exports = {
|
||||||
|
NetlistKernel
|
||||||
|
};
|
239
resources/netlist/utils/vrfs.js
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
const fspath = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const os = require('os');
|
||||||
|
const exec = require("child_process").execSync;
|
||||||
|
|
||||||
|
class Vrfs {
|
||||||
|
constructor(module) {
|
||||||
|
this.module = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptionCn 显示指定文件夹下的所有子目录, 并返回
|
||||||
|
* @param {*} path 所要显示的文件夹的绝对路径 (省略对应root的\)
|
||||||
|
* @returns 返回所有子目录
|
||||||
|
*/
|
||||||
|
readdir(path) {
|
||||||
|
let lists = this.module.FS.readdir(`/${path}`);
|
||||||
|
console.log(lists);
|
||||||
|
return lists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptionCn 将本地路径挂载到虚拟文件系统下
|
||||||
|
* @param {*} local 需要挂载的本地路径
|
||||||
|
* @param {*} virtual 所要挂载到的虚拟文件系统的绝对路径 (省略对应root的/)
|
||||||
|
*/
|
||||||
|
mount(local, virtual) {
|
||||||
|
this.mkdir(virtual);
|
||||||
|
this.module.FS.mount(this.module.NODEFS, { root: local }, `/${virtual}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptionCn 将当前系统根目录进行挂在到虚拟文件系统下
|
||||||
|
*/
|
||||||
|
diskMount() {
|
||||||
|
var aDrives = [];
|
||||||
|
var result = null;
|
||||||
|
var stdout = null;
|
||||||
|
switch (os.platform().toLowerCase()) {
|
||||||
|
case 'win32':
|
||||||
|
result = exec('wmic logicaldisk get Caption,FreeSpace,Size,VolumeSerialNumber,Description /format:list');
|
||||||
|
stdout = result.toString();
|
||||||
|
var aLines = stdout.split('\r\r\n');
|
||||||
|
var bNew = false;
|
||||||
|
var sCaption = '', sDescription = '', sFreeSpace = '', sSize = '', sVolume = '';
|
||||||
|
// For each line get information
|
||||||
|
// Format is Key=Value
|
||||||
|
for(var i = 0; i < aLines.length; i++) {
|
||||||
|
if (aLines[i] !== '') {
|
||||||
|
var aTokens = aLines[i].split('=');
|
||||||
|
switch (aTokens[0]) {
|
||||||
|
case 'Caption':
|
||||||
|
sCaption = aTokens[1];
|
||||||
|
bNew = true;
|
||||||
|
break;
|
||||||
|
case 'Description':
|
||||||
|
sDescription = aTokens[1];
|
||||||
|
break;
|
||||||
|
case 'FreeSpace':
|
||||||
|
sFreeSpace = aTokens[1];
|
||||||
|
break;
|
||||||
|
case 'Size':
|
||||||
|
sSize = aTokens[1];
|
||||||
|
break;
|
||||||
|
case 'VolumeSerialNumber':
|
||||||
|
sVolume = aTokens[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Empty line
|
||||||
|
// If we get an empty line and bNew is true then we have retrieved
|
||||||
|
// all information for one drive, add to array and reset variables
|
||||||
|
if (bNew) {
|
||||||
|
sSize = parseFloat(sSize);
|
||||||
|
if (isNaN(sSize)) {
|
||||||
|
sSize = 0;
|
||||||
|
}
|
||||||
|
sFreeSpace = parseFloat(sFreeSpace);
|
||||||
|
if (isNaN(sFreeSpace)) {
|
||||||
|
sFreeSpace = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sUsed = (sSize - sFreeSpace);
|
||||||
|
var sPercent = '0%';
|
||||||
|
if (sSize !== '' && parseFloat(sSize) > 0) {
|
||||||
|
sPercent = Math.round((parseFloat(sUsed) / parseFloat(sSize)) * 100) + '%';
|
||||||
|
}
|
||||||
|
aDrives[aDrives.length] = {
|
||||||
|
filesystem: sDescription,
|
||||||
|
blocks: sSize,
|
||||||
|
used: sUsed,
|
||||||
|
available: sFreeSpace,
|
||||||
|
capacity: sPercent,
|
||||||
|
mounted: sCaption
|
||||||
|
};
|
||||||
|
bNew = false;
|
||||||
|
sCaption = '';
|
||||||
|
sDescription = '';
|
||||||
|
sFreeSpace = '';
|
||||||
|
sSize = '';
|
||||||
|
sVolume = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < aDrives.length; i++) {
|
||||||
|
let diskName = aDrives[i].mounted.toLowerCase();
|
||||||
|
console.log(diskName);
|
||||||
|
this.mount(diskName, diskName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.mount('/', 'host');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @state finish-test
|
||||||
|
* @descriptionCn 虚拟文件系统下创建文件夹
|
||||||
|
* @param {*} path 虚拟文件系统内部的绝对路径 (省略对应root的\)
|
||||||
|
* 可越级创建,会自动生成父级文件夹
|
||||||
|
*/
|
||||||
|
mkdir(path) {
|
||||||
|
if (this.module.FS.findObject(`/${path}`) !== null) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
let dirname = fspath.dirname(path);
|
||||||
|
if (dirname === path) {
|
||||||
|
this.module.FS.mkdir(`/${path}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (this.mkdir(dirname)) {
|
||||||
|
this.module.FS.mkdir(`/${path}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptionCn 删除虚拟文件系统下的文件夹
|
||||||
|
* @param {*} path 虚拟文件系统内部的绝对路径 (省略对应root的\)
|
||||||
|
* 可越级创建,会自动删除父级文件夹
|
||||||
|
*/
|
||||||
|
rmdir(path) {
|
||||||
|
let files = [];
|
||||||
|
if (this.module.FS.findObject(`/${path}`) !== null) {
|
||||||
|
files = this.module.FS.readdir(`/${path}`);
|
||||||
|
for (let index = 2; index < files.length; index++) {
|
||||||
|
const element = files[index];
|
||||||
|
let curPath = fspath.join(`/${path}`, element).replace(/\\/g, "\/");
|
||||||
|
let value = this.module.FS.isDir(this.module.FS.stat(curPath).mode);
|
||||||
|
if (value) {
|
||||||
|
this.rmdir(curPath);
|
||||||
|
} else {
|
||||||
|
this.module.FS.unlink(curPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.module.FS.rmdir(`/${path}`); //清除文件夹
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @state finish-test
|
||||||
|
* @descriptionCn 删除虚拟文件系统下的指定文件
|
||||||
|
* @param {*} path 虚拟文件系统内部的绝对路径 (省略对应root的\)
|
||||||
|
*/
|
||||||
|
rmfile(path) {
|
||||||
|
this.module.FS.unlink(`/${path}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @state finish-test
|
||||||
|
* @descriptionCn 将本地路径下的文件写入虚拟文件系统
|
||||||
|
* @param {*} src 文件的本地的绝对路径
|
||||||
|
* @param {*} des 虚拟文件系统内部指定地址 (省略对应root的\)
|
||||||
|
* 可越级创建,会自动生成父级文件夹
|
||||||
|
*/
|
||||||
|
writeFileFormPath(src, des) {
|
||||||
|
let desDir = fspath.dirname(des);
|
||||||
|
let content = fs.readFileSync(src);
|
||||||
|
if (this.module.FS.findObject(`/${desDir}`) !== null) {
|
||||||
|
this.module.FS.writeFile(`/${des}`, content, { encoding: 'utf8' });
|
||||||
|
} else {
|
||||||
|
this.mkdir(`/${desDir}`);
|
||||||
|
this.module.FS.writeFile(`/${des}`, content, { encoding: 'utf8' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @state finish-test
|
||||||
|
* @descriptionCn 将文件内容写入虚拟文件系统
|
||||||
|
* @param {*} text 要写入的文件内容
|
||||||
|
* @param {*} path 虚拟文件系统内部指定地址 (省略对应root的\)
|
||||||
|
* 可越级创建,会自动生成父级文件夹
|
||||||
|
*/
|
||||||
|
writeFileFormText(text, path) {
|
||||||
|
let pathDir = fspath.dirname(path);
|
||||||
|
if (this.module.FS.findObject(`/${pathDir}`) !== null) {
|
||||||
|
this.module.FS.writeFile(`/${path}`, text, { encoding: 'utf8' });
|
||||||
|
} else {
|
||||||
|
this.mkdir(`/${pathDir}`);
|
||||||
|
this.module.FS.writeFile(`/${path}`, text, { encoding: 'utf8' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @state finish-test
|
||||||
|
* @descriptionCn 从虚拟文件系统中读出文件到本地
|
||||||
|
* @param {*} src 虚拟文件系统内部指定地址 (省略对应root的\)
|
||||||
|
* @param {*} des 要写到的本地文件的绝对路径
|
||||||
|
*/
|
||||||
|
readFileToPath(src, des) {
|
||||||
|
if (this.module.FS.findObject(`/${src}`) !== null) {
|
||||||
|
let content = this.module.FS.readFile(`/${src}`, { encoding: 'utf8' });
|
||||||
|
fs.writeFileSync(des, content);
|
||||||
|
} else {
|
||||||
|
console.log(`ERROR: The ${src} is not at this virtual system.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @state finish-test
|
||||||
|
* @descriptionCn 从虚拟文件系统中读出文件内容
|
||||||
|
* @param {*} path 虚拟文件系统内部指定地址 (省略对应root的\)
|
||||||
|
* @returns 读出文件的内容
|
||||||
|
*/
|
||||||
|
readFileToText(path) {
|
||||||
|
if (this.module.FS.findObject(`/${path}`) !== null) {
|
||||||
|
let content = this.module.FS.readFile(`/${path}`, { encoding: 'utf8' });
|
||||||
|
return content;
|
||||||
|
} else {
|
||||||
|
console.log(`ERROR: The ${path} is not at this virtual system.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = Vrfs;
|
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 479 B |
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 522 B |
Before Width: | Height: | Size: 473 B After Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 45 B After Width: | Height: | Size: 45 B |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
36757
resources/netlist/view/netlist_view.js
Normal file
@ -8,19 +8,20 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
<script type="text/javascript" src="../web/jquery-2.2.4.min.js"></script>
|
<script type="text/javascript" src="../../public/jquery-2.2.4.min.js"></script>
|
||||||
<script type="text/javascript" src="../web/svg-pan-zoom.min.js"></script>
|
<script type="text/javascript" src="../../public/svg-pan-zoom.min.js"></script>
|
||||||
<script type="text/javascript" src="../web/full.render.js"></script>
|
<script type="text/javascript" src="../../public/full.render.js"></script>
|
||||||
<script type="text/javascript" src="../web/viz.js"></script>
|
<script type="text/javascript" src="../../public/viz.js"></script>
|
||||||
<script type="text/javascript" src="../web/elk.bundled.js"></script>
|
<script type="text/javascript" src="../../public/elk.bundled.js"></script>
|
||||||
<script type="text/javascript" src="../web/jquery.ztree.core.min.js"></script>
|
<script type="text/javascript" src="../../public/jquery.ztree.core.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="./render.js"></script>
|
<script type="text/javascript" src="./render.js"></script>
|
||||||
<script type="text/javascript" src="./netlist_view.js"></script>
|
<script type="text/javascript" src="./netlist_view.js"></script>
|
||||||
|
|
||||||
<link href='https://unpkg.com/boxicons@2.0.7/css/boxicons.min.css' rel='stylesheet'>
|
<!-- <link href='https://unpkg.com/boxicons@2.0.7/css/boxicons.min.css' rel='stylesheet'> -->
|
||||||
<link rel="stylesheet" href="../../css/netlist_tree_style.css" type="text/css">
|
<link rel="stylesheet" href="../../../css/boxicons.2.0.7.min.css">
|
||||||
<link rel="stylesheet" href="../../css/netlist_style.css" type="text/css">
|
<link rel="stylesheet" href="../../../css/netlist_tree_style.css" type="text/css">
|
||||||
|
<link rel="stylesheet" href="../../../css/netlist_style.css" type="text/css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
"use strict";
|
"use strict";
|
||||||
class render{
|
class render{
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -17,14 +18,14 @@ class render{
|
|||||||
this.curNetIndex--;
|
this.curNetIndex--;
|
||||||
this.showNetlist(this.netLists[this.curNetIndex]);
|
this.showNetlist(this.netLists[this.curNetIndex]);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
document.getElementById("next").onclick = function () {
|
document.getElementById("next").onclick = function () {
|
||||||
if (this.curNetIndex < this.netLists.length-1) {
|
if (this.curNetIndex < this.netLists.length-1) {
|
||||||
this.curNetIndex++;
|
this.curNetIndex++;
|
||||||
this.showNetlist(this.netLists[this.curNetIndex]);
|
this.showNetlist(this.netLists[this.curNetIndex]);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async showNetlist(netList, isClear) {
|
async showNetlist(netList, isClear) {
|
||||||
@ -35,8 +36,6 @@ class render{
|
|||||||
}
|
}
|
||||||
|
|
||||||
let netnode = this.showTreelist(netList);
|
let netnode = this.showTreelist(netList);
|
||||||
console.log('net node');
|
|
||||||
console.log(netnode);
|
|
||||||
|
|
||||||
var setting = {};
|
var setting = {};
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
@ -117,7 +116,7 @@ class render{
|
|||||||
|
|
||||||
removeClickEvent() {
|
removeClickEvent() {
|
||||||
function handleRemove() {
|
function handleRemove() {
|
||||||
console.log("ok");
|
console.w("ok");
|
||||||
}
|
}
|
||||||
let countries = this.embed_svg.childNodes;
|
let countries = this.embed_svg.childNodes;
|
||||||
for (let i = 0; i < countries.length; i++) {
|
for (let i = 0; i < countries.length; i++) {
|
@ -16,6 +16,7 @@ import * as tool from './tool';
|
|||||||
|
|
||||||
// special function
|
// special function
|
||||||
import * as FSM from './fsm';
|
import * as FSM from './fsm';
|
||||||
|
import * as Netlist from './netlist';
|
||||||
|
|
||||||
function registerDocumentation(context: vscode.ExtensionContext) {
|
function registerDocumentation(context: vscode.ExtensionContext) {
|
||||||
vscode.commands.registerCommand('digital-ide.hdlDoc.showWebview', hdlDoc.showDocWebview);
|
vscode.commands.registerCommand('digital-ide.hdlDoc.showWebview', hdlDoc.showDocWebview);
|
||||||
@ -90,9 +91,7 @@ function registerFSM(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function registerNetlist(context: vscode.ExtensionContext) {
|
function registerNetlist(context: vscode.ExtensionContext) {
|
||||||
vscode.commands.registerCommand('digital-ide.netlist.show', uri => {
|
vscode.commands.registerCommand('digital-ide.netlist.show', uri => Netlist.openNetlistViewer(context, uri));
|
||||||
vscode.window.showInformationMessage('launch netlist');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
159
src/function/netlist/index.ts
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as fspath from 'path';
|
||||||
|
|
||||||
|
import { NetlistKernel } from '../../../resources/netlist';
|
||||||
|
import { MainOutput, opeParam, ReportType, YosysOutput } from '../../global';
|
||||||
|
import { hdlParam } from '../../hdlParser';
|
||||||
|
import { hdlFile, hdlPath } from '../../hdlFs';
|
||||||
|
|
||||||
|
|
||||||
|
class Netlist {
|
||||||
|
kernel?: NetlistKernel;
|
||||||
|
context: vscode.ExtensionContext;
|
||||||
|
panel?: vscode.WebviewPanel;
|
||||||
|
|
||||||
|
constructor(context: vscode.ExtensionContext) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async open(uri: vscode.Uri) {
|
||||||
|
// get dependence of the current uri
|
||||||
|
const prjFiles = [];
|
||||||
|
const path = hdlPath.toSlash(uri.fsPath);
|
||||||
|
|
||||||
|
const hdlFile = hdlParam.getHdlFile(path);
|
||||||
|
if (!hdlFile) {
|
||||||
|
const errorMsg = `${path} is not a valid hdl file in our parse list, check your property.json to see if arch.hardware.src is set correctly!
|
||||||
|
\ncurrent parse list: \n${opeParam.prjInfo.hardwareSrcPath}\n${opeParam.prjInfo.hardwareSimPath}`;
|
||||||
|
vscode.window.showErrorMessage(errorMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const hdlModule of hdlFile.getAllHdlModules()) {
|
||||||
|
const hdlDependence = hdlParam.getAllDependences(path, hdlModule.name);
|
||||||
|
if (hdlDependence) {
|
||||||
|
// kernel supports `include, so only others are needed
|
||||||
|
prjFiles.push(...hdlDependence.others);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prjFiles.push(path);
|
||||||
|
|
||||||
|
// launch kernel
|
||||||
|
this.kernel = new NetlistKernel();
|
||||||
|
await this.kernel.launch();
|
||||||
|
|
||||||
|
// set info output in kernel to console
|
||||||
|
this.kernel.setMessageCallback((message, type) => {
|
||||||
|
if (message !== '') {
|
||||||
|
YosysOutput.report('type: ' + type + ', ' + message);
|
||||||
|
}
|
||||||
|
if (type === "error") {
|
||||||
|
vscode.window.showErrorMessage('type: ' + type + ', ' + message);
|
||||||
|
YosysOutput.report('type: ' + type + ', ' + message, ReportType.Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.kernel.load(prjFiles);
|
||||||
|
this.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private create() {
|
||||||
|
// Create panel
|
||||||
|
this.panel = vscode.window.createWebviewPanel(
|
||||||
|
'netlist',
|
||||||
|
'Schematic viewer',
|
||||||
|
vscode.ViewColumn.One, {
|
||||||
|
enableScripts: true,
|
||||||
|
retainContextWhenHidden: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.panel.onDidDispose(() => {
|
||||||
|
// When the panel is closed, cancel any future updates to the webview content
|
||||||
|
this.kernel?.exit();
|
||||||
|
this.panel?.dispose();
|
||||||
|
|
||||||
|
this.kernel = undefined;
|
||||||
|
this.panel = undefined;
|
||||||
|
}, null, this.context.subscriptions);
|
||||||
|
|
||||||
|
// Handle messages from the webview
|
||||||
|
this.panel.webview.onDidReceiveMessage(message => {
|
||||||
|
console.log(message);
|
||||||
|
switch (message.command) {
|
||||||
|
case 'export':
|
||||||
|
this.export(message.type, message.svg);
|
||||||
|
break;
|
||||||
|
case 'exec':
|
||||||
|
this.send();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, undefined, this.context.subscriptions);
|
||||||
|
|
||||||
|
const previewHtml = this.getWebviewContent();
|
||||||
|
if (this.panel && previewHtml) {
|
||||||
|
this.panel.webview.html = previewHtml;
|
||||||
|
} else {
|
||||||
|
YosysOutput.report('preview html in <Netlist.create> is empty', ReportType.Warn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public send() {
|
||||||
|
this.kernel?.exec('proc');
|
||||||
|
const netlist = this.kernel?.export({type: 'json'});
|
||||||
|
|
||||||
|
const command = 'netlist';
|
||||||
|
this.panel?.webview.postMessage({command, netlist});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getWebviewContent() {
|
||||||
|
const netlistPath = hdlPath.join(opeParam.extensionPath, 'resources', 'netlist', 'view');
|
||||||
|
const htmlIndexPath = hdlPath.join(netlistPath, 'netlist_viewer.html');
|
||||||
|
|
||||||
|
const html = hdlFile.readFile(htmlIndexPath)?.replace(/(<link.+?href="|<script.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => {
|
||||||
|
const absLocalPath = fspath.resolve(netlistPath, $2);
|
||||||
|
const webviewUri = this.panel?.webview.asWebviewUri(vscode.Uri.file(absLocalPath));
|
||||||
|
const replaceHref = $1 + webviewUri?.toString() + '"';
|
||||||
|
return replaceHref;
|
||||||
|
});
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async export(type: string, svg: string) {
|
||||||
|
switch (type) {
|
||||||
|
case "svg":
|
||||||
|
await this.exportSvg(svg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async exportSvg(svg: string) {
|
||||||
|
const filter = { 'svg': ['svg'] };
|
||||||
|
const fileInfos = await vscode.window.showSaveDialog({ filters: filter });
|
||||||
|
|
||||||
|
if (fileInfos && fileInfos.path) {
|
||||||
|
let savePath = fileInfos.path;
|
||||||
|
|
||||||
|
if (savePath[0] === '/' && require('os').platform() === 'win32') {
|
||||||
|
savePath = savePath.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdlFile.writeFile(savePath, svg);
|
||||||
|
|
||||||
|
vscode.window.showInformationMessage('Schematic saved in ' + savePath);
|
||||||
|
YosysOutput.report('Schematic saved in ' + savePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openNetlistViewer(context: vscode.ExtensionContext, uri: vscode.Uri) {
|
||||||
|
const viewer = new Netlist(context);
|
||||||
|
viewer.open(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
openNetlistViewer
|
||||||
|
};
|
@ -213,7 +213,6 @@ class ToolTreeProvider extends BaseCommandTreeProvider {
|
|||||||
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
hdlDir.mvdir(sourceIpPath, targetPath, true);
|
||||||
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
hdlDir.mvdir(sourceBdPath, targetPath, true);
|
||||||
|
|
||||||
|
|
||||||
const ignores = hdlIgnore.getIgnoreFiles();
|
const ignores = hdlIgnore.getIgnoreFiles();
|
||||||
|
|
||||||
const strFiles = hdlFile.pickFileRecursive(workspacePath, ignores, p => p.endsWith('.str'));
|
const strFiles = hdlFile.pickFileRecursive(workspacePath, ignores, p => p.endsWith('.str'));
|
||||||
|
33
src/test/user/src/netlist_test.v
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// borrowed with some modifications from
|
||||||
|
// http://www.ee.ed.ac.uk/~gerard/Teach/Verilog/manual/Example/lrgeEx2/cooley.html
|
||||||
|
module up3down5(clock, data_in, up, down, carry_out, borrow_out, count_out, parity_out);
|
||||||
|
|
||||||
|
input [8:0] data_in;
|
||||||
|
input clock, up, down;
|
||||||
|
|
||||||
|
output reg [8:0] count_out;
|
||||||
|
output reg carry_out, borrow_out, parity_out;
|
||||||
|
|
||||||
|
reg [9:0] cnt_up, cnt_dn;
|
||||||
|
reg [8:0] count_nxt;
|
||||||
|
|
||||||
|
always @(posedge clock)
|
||||||
|
begin
|
||||||
|
cnt_dn = count_out - 3'b 101;
|
||||||
|
cnt_up = count_out + 2'b 11;
|
||||||
|
|
||||||
|
case ({up,down})
|
||||||
|
2'b 00 : count_nxt = data_in;
|
||||||
|
2'b 01 : count_nxt = cnt_dn;
|
||||||
|
2'b 10 : count_nxt = cnt_up;
|
||||||
|
2'b 11 : count_nxt = count_out;
|
||||||
|
default : count_nxt = 9'bX;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
parity_out <= ^count_nxt;
|
||||||
|
carry_out <= up & cnt_up[9];
|
||||||
|
borrow_out <= down & cnt_dn[9];
|
||||||
|
count_out <= count_nxt;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
77
test.js
@ -1,77 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
|
||||||
const fs = require('fs');
|
|
||||||
const fspath = require('path');
|
|
||||||
|
|
||||||
const { vlogFast } = require('./resources/hdlParser');
|
|
||||||
|
|
||||||
const COMMON_PATH = fspath.resolve('./lib/common/Driver');
|
|
||||||
|
|
||||||
const TEST_FILE = './parser_stuck.v';
|
|
||||||
const TEST_FILE2 = './src/test/vlog/dependence_test/parent.v';
|
|
||||||
const TEST_FILE3 = './src/test/vlog/formatter_test.v';
|
|
||||||
|
|
||||||
|
|
||||||
function isFile(path) {
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const state = fs.statSync(path);
|
|
||||||
if (state.isDirectory()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* judge if the path represent a Dir
|
|
||||||
* @param path
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function isDir(path) {
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const state = fs.statSync(path);
|
|
||||||
if (state.isDirectory()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function* walk(path, condition) {
|
|
||||||
if (isFile(path)) {
|
|
||||||
if (!condition || condition(path)) {
|
|
||||||
yield path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (const file of fs.readdirSync(path)) {
|
|
||||||
const filePath = fspath.join(path, file);
|
|
||||||
if (isDir(filePath)) {
|
|
||||||
for (const targetPath of walk(filePath, condition)) {
|
|
||||||
yield targetPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isFile(filePath)) {
|
|
||||||
if (!condition || condition(filePath)) {
|
|
||||||
yield filePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(async() => {
|
|
||||||
console.time('test');
|
|
||||||
// await vlogFast('./lib/common/Apply/DSP/Advance/FFT/Flow_FFT_IFFT/BF_op.v');
|
|
||||||
for (const file of walk('./src/test/vlog/dependence_test', f => f.endsWith('.v'))) {
|
|
||||||
console.log('[file] ', file);
|
|
||||||
try {
|
|
||||||
const res = await vlogFast(file);
|
|
||||||
console.log(res);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.timeEnd('test');
|
|
||||||
})();
|
|