#add FSM | #add Netlist

This commit is contained in:
锦恢 2023-07-15 01:00:51 +08:00
parent d0bcf417fb
commit 858352b45c
23 changed files with 37245 additions and 36827 deletions

1
css/boxicons.2.0.7.min.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
fonts/boxicons.woff2 Normal file

Binary file not shown.

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention */
const fs = require("fs");
const fspath = require("path");
const vscode = require("vscode");
@ -198,7 +199,7 @@ class FsmViewer {
}
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);
let html = fs.readFileSync(resource_path, 'utf-8');

View File

@ -11,7 +11,7 @@
<script src="../../public/full.render.js"></script>
<script src="../../public/viz.js"></script>
<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>
<body>
@ -23,7 +23,7 @@
</label>
</div>
</div>
<script src="fsm_draw.js"></script>
<script src="./fsm_draw.js"></script>
<div id="error-info" class="trontron">
<div id="inner" class="fuck"></div>
</div>

View File

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

View File

@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/naming-convention */
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() {
this.kernel = null;
this.vrfs = null;
@ -11,7 +12,7 @@ class Operation {
async launch() {
this.kernel = await kernel();
this.vrfs = new fs.vrfs(this.kernel);
this.vrfs = new Vrfs(this.kernel);
this.vrfs.diskMount();
}
@ -145,4 +146,6 @@ class Operation {
this.vrfs = null;
}
}
module.exports = operation;
module.exports = {
NetlistKernel
};

File diff suppressed because one or more lines are too long

View 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;

View File

Before

Width:  |  Height:  |  Size: 479 B

After

Width:  |  Height:  |  Size: 479 B

View File

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 522 B

View File

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 473 B

View File

Before

Width:  |  Height:  |  Size: 45 B

After

Width:  |  Height:  |  Size: 45 B

View File

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 381 B

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

View File

@ -8,19 +8,20 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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="../web/svg-pan-zoom.min.js"></script>
<script type="text/javascript" src="../web/full.render.js"></script>
<script type="text/javascript" src="../web/viz.js"></script>
<script type="text/javascript" src="../web/elk.bundled.js"></script>
<script type="text/javascript" src="../web/jquery.ztree.core.min.js"></script>
<script type="text/javascript" src="../../public/jquery-2.2.4.min.js"></script>
<script type="text/javascript" src="../../public/svg-pan-zoom.min.js"></script>
<script type="text/javascript" src="../../public/full.render.js"></script>
<script type="text/javascript" src="../../public/viz.js"></script>
<script type="text/javascript" src="../../public/elk.bundled.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="./netlist_view.js"></script>
<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/netlist_style.css" type="text/css">
<!-- <link href='https://unpkg.com/boxicons@2.0.7/css/boxicons.min.css' rel='stylesheet'> -->
<link rel="stylesheet" href="../../../css/boxicons.2.0.7.min.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>
<body>

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention */
"use strict";
class render{
constructor() {
@ -17,14 +18,14 @@ class render{
this.curNetIndex--;
this.showNetlist(this.netLists[this.curNetIndex]);
}
}
};
document.getElementById("next").onclick = function () {
if (this.curNetIndex < this.netLists.length-1) {
this.curNetIndex++;
this.showNetlist(this.netLists[this.curNetIndex]);
}
}
};
}
async showNetlist(netList, isClear) {
@ -35,8 +36,6 @@ class render{
}
let netnode = this.showTreelist(netList);
console.log('net node');
console.log(netnode);
var setting = {};
$(document).ready(function () {
@ -117,7 +116,7 @@ class render{
removeClickEvent() {
function handleRemove() {
console.log("ok");
console.w("ok");
}
let countries = this.embed_svg.childNodes;
for (let i = 0; i < countries.length; i++) {

View File

@ -16,6 +16,7 @@ import * as tool from './tool';
// special function
import * as FSM from './fsm';
import * as Netlist from './netlist';
function registerDocumentation(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('digital-ide.hdlDoc.showWebview', hdlDoc.showDocWebview);
@ -90,9 +91,7 @@ function registerFSM(context: vscode.ExtensionContext) {
}
function registerNetlist(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('digital-ide.netlist.show', uri => {
vscode.window.showInformationMessage('launch netlist');
});
vscode.commands.registerCommand('digital-ide.netlist.show', uri => Netlist.openNetlistViewer(context, uri));
}
export {

View 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
};

View File

@ -213,7 +213,6 @@ class ToolTreeProvider extends BaseCommandTreeProvider {
hdlDir.mvdir(sourceIpPath, targetPath, true);
hdlDir.mvdir(sourceBdPath, targetPath, true);
const ignores = hdlIgnore.getIgnoreFiles();
const strFiles = hdlFile.pickFileRecursive(workspacePath, ignores, p => p.endsWith('.str'));

View 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
View File

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