diff --git a/media/VisqRunner/index.html b/media/VisqRunner/index.html
new file mode 100644
index 00000000..93bffe98
--- /dev/null
+++ b/media/VisqRunner/index.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+ VISQ configuration runner
+
+
+
+
+
+
+
+ Run visq on the following configuration
+
+
+
+ Run configuration
+
+
+
+
+
+
+
+ Input
+
+
+
+
+ Float model
+
+
+ Path to the fp32 circle model.
+
+
+
+
+
+ Quantized model
+
+
+ Path to the quantized circle model.
+
+
+
+
+
+ h5 data file
+
+
+ Path to the data used for inference. Random data will be used if this option is not given.
+
+
+
+
+
+
+
+
+
+ Output
+
+
+ MPEIR
+
+
+
+ Path to the output json file (qerror metric = MPEIR).
+
+
+
+
+ MSE
+
+
+
+ Path to the output json file (qerror metric = MSE).
+
+
+
+
+ TAE
+
+
+
+ Path to the output json file (qerror metric = TAE).
+
+
+
+
+ SRMSE
+
+
+
+ Path to the output json file (qerror metric = SRMSE).
+
+
+
+
+
+
+
+
+
+ Options
+
+
+ Dump dot graph
+
+
+
+
+
diff --git a/media/VisqRunner/index.js b/media/VisqRunner/index.js
new file mode 100644
index 00000000..74ba7c4b
--- /dev/null
+++ b/media/VisqRunner/index.js
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const vscode = acquireVsCodeApi();
+
+// Just like a regular webpage we need to wait for the webview
+// DOM to load before we can reference any of the HTML elements
+// or toolkit components
+window.addEventListener("load", main);
+
+function main() {
+ register();
+
+ window.addEventListener("message", (event) => {
+ const message = event.data;
+ switch (message.type) {
+ case "displayCFG":
+ displayCFGToEditor(message.content);
+ break;
+ default:
+ break;
+ }
+ });
+
+ vscode.postMessage({ type: "requestDisplayCFG" });
+}
+
+function register() {
+ registerMainControls();
+}
+
+function registerMainControls() {
+ {
+ document
+ .getElementById("float-file")
+ .addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadFloatInputFile",
+ });
+ });
+
+ document
+ .getElementById("quantized-file")
+ .addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadQuantizedInputFile",
+ });
+ });
+
+ document.getElementById("h5-file").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadH5DataFile",
+ });
+ });
+ }
+
+ {
+ document.getElementById("MPEIR-on").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "toggleMPEIROutputFile",
+ on: document.getElementById("MPEIR-on").checked,
+ });
+ });
+ document
+ .getElementById("mpeir-file")
+ .addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadMPEIROutputFile",
+ });
+ });
+ document
+ .getElementById("MPEIROutputPath")
+ .addEventListener("input", function () {
+ vscode.postMessage({
+ type: "onMPEIRChanged",
+ path: document.getElementById("MPEIROutputPath").value,
+ });
+ });
+ }
+
+ {
+ document.getElementById("MSE-on").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "toggleMSEOutputFile",
+ on: document.getElementById("MSE-on").checked,
+ });
+ });
+
+ document.getElementById("mse-file").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadMSEInputFile",
+ });
+ });
+
+ document
+ .getElementById("MSEOutputPath")
+ .addEventListener("input", function () {
+ vscode.postMessage({
+ type: "onMSEChanged",
+ path: document.getElementById("MSEOutputPath").value,
+ });
+ });
+ }
+
+ {
+ document.getElementById("TAE-on").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "toggleTAEOutputFile",
+ on: document.getElementById("TAE-on").checked,
+ });
+ });
+ document.getElementById("tae-file").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadTAEOutputFile",
+ });
+ });
+ document
+ .getElementById("TAEOutputPath")
+ .addEventListener("input", function () {
+ vscode.postMessage({
+ type: "onTAEChanged",
+ path: document.getElementById("TAEOutputPath").value,
+ });
+ });
+ }
+
+ {
+ document.getElementById("SRMSE-on").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "toggleSRMSEOutputFile",
+ on: document.getElementById("SRMSE-on").checked,
+ });
+ });
+ document
+ .getElementById("srmse-file")
+ .addEventListener("click", function () {
+ vscode.postMessage({
+ type: "loadSRMSEOutputFile",
+ });
+ });
+ document
+ .getElementById("SRMSEOutputPath")
+ .addEventListener("input", function () {
+ vscode.postMessage({
+ type: "onSRMSEChanged",
+ path: document.getElementById("SRMSEOutputPath").value,
+ });
+ });
+ }
+
+ document.getElementById("DumpDot").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "dumpDot",
+ dump: document.getElementById("DumpDot").checked,
+ });
+ });
+
+ document.getElementById("RunCfg").addEventListener("click", function () {
+ vscode.postMessage({
+ type: "runCfg",
+ });
+ });
+}
+
+function displayCFGToEditor(cfg) {
+ document.getElementById("FloatModelInputPath").value = cfg?.["fp32_circle"];
+ document.getElementById("QuantizedModelInputPath").value = cfg?.["q_circle"];
+ document.getElementById("DataInputPath").value = cfg?.["data"];
+ document.getElementById("MPEIR-on").checked = cfg?.["mpeir_on"];
+ document.getElementById("MPEIROutputPath").value = cfg?.["mpeir_output"];
+ document.getElementById("MSE-on").checked = cfg?.["mse_on"];
+ document.getElementById("MSEOutputPath").value = cfg?.["mse_output"];
+ document.getElementById("TAE-on").checked = cfg?.["tae_on"];
+ document.getElementById("TAEOutputPath").value = cfg?.["tae_output"];
+ document.getElementById("SRMSE-on").checked = cfg?.["srmse_on"];
+ document.getElementById("SRMSEOutputPath").value = cfg?.["srmse_output"];
+ document.getElementById("DumpDot").checked = cfg?.["dump_dot_graph"];
+}
diff --git a/media/VisqRunner/style.css b/media/VisqRunner/style.css
new file mode 100644
index 00000000..38204c07
--- /dev/null
+++ b/media/VisqRunner/style.css
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+label {
+ white-space: pre-wrap;
+}
+
+body {
+ min-width: 500px;
+ width: auto !important;
+}
+
+.maintitle {
+ width: 100%;
+ display: flex;
+}
+
+.maintitle .text {
+ float: left;
+ display: block;
+ font-size: medium;
+ font-weight: 600;
+ padding: 2px 0 0 5px;
+}
+
+.title {
+ font-size: medium;
+}
+
+.codicon.codicon-question .help,
+.codicon.codicon-play .help {
+ visibility: hidden;
+ width: auto;
+ background-color: var(--vscode-editorSuggestWidget-background);
+ color: var(--vscode-editorSuggestWidget-foreground);
+ border: 2px solid var(--vscode-editorSuggestWidget-border);
+ font-size: small;
+ text-align: left;
+ position: absolute;
+ z-index: 1;
+ margin-left: 10px;
+ padding: 6px 6px 10px 8px;
+ font-family: var(--vscode-font-family);
+}
+
+.codicon.codicon-question:hover .help {
+ visibility: visible;
+}
+
+.codicon.codicon-play:hover .help {
+ visibility: visible;
+}
+
+.input {
+ display: block;
+ margin-bottom: 5px;
+}
+
+.sections {
+ display: inline-block;
+}
+
+.output_grid {
+ display: inline-grid;
+ grid-template-columns: auto auto;
+ row-gap: 5px;
+}
diff --git a/package.json b/package.json
index ff229e69..4480ac63 100644
--- a/package.json
+++ b/package.json
@@ -128,6 +128,16 @@
}
],
"priority": "default"
+ },
+ {
+ "viewType": "one.editor.cfgvisq",
+ "displayName": "VISQ Runner",
+ "selector": [
+ {
+ "filenamePattern": "*.cfg.visq.json"
+ }
+ ],
+ "priority": "default"
}
],
"commands": [
@@ -256,6 +266,11 @@
"command": "one.editor.cfg.setDefaultValues",
"title": "ONE: Set Default Values",
"category": "ONE"
+ },
+ {
+ "command": "one.editor.visqcfg.showFromDefaultExplorer",
+ "title": "Create VISQ data",
+ "category": "ONE"
}
],
"keybindings": [
@@ -370,6 +385,10 @@
"command": "one.viewer.metadata.showFromDefaultExplorer",
"when": "resourceExtname in one.metadata.supportedFiles && !explorerResourceIsFolder",
"group": "7_metadata@1"
+ },
+ {
+ "command": "one.editor.visqcfg.showFromDefaultExplorer",
+ "group": "7_metadata@2"
}
],
"commandPalette": [
@@ -452,6 +471,10 @@
{
"command": "one.viewer.metadata.showFromOneExplorer",
"when": "false"
+ },
+ {
+ "command": "one.editor.visqcfg.showFromDefaultExplorer",
+ "when": "false"
}
]
},
diff --git a/src/Job/Job.ts b/src/Job/Job.ts
index 67ea1e3e..bb41a40a 100644
--- a/src/Job/Job.ts
+++ b/src/Job/Job.ts
@@ -48,5 +48,6 @@ export const enum JobType {
tPrerequisites,
tInstall,
tUninstall,
+ tVisq,
// TODO add more
}
diff --git a/src/VisqRunner/VisqRunProvider.ts b/src/VisqRunner/VisqRunProvider.ts
new file mode 100644
index 00000000..41c0291b
--- /dev/null
+++ b/src/VisqRunner/VisqRunProvider.ts
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import * as fs from "fs";
+import * as path from "path";
+import * as vscode from "vscode";
+
+import { Logger } from "../Utils/Logger";
+import { getNonce } from "../Utils/external/Nonce";
+import { getUri } from "../Utils/external/Uri";
+import { JobRunner } from "../Job/JobRunner";
+import { Command } from "../Backend/Command";
+import { WorkJobs } from "../Job/WorkJobs";
+import { JobCommand } from "../Job/JobCommand";
+import { JobType } from "../Job/Job";
+import { Balloon } from "../Utils/Balloon";
+
+class VisqCommand extends JobCommand {
+ constructor(cmd: Command) {
+ super(cmd);
+ this.jobType = JobType.tVisq;
+ this.name = "visq";
+ this.notiTitle = "Running visq...";
+ this.valid = true;
+ }
+}
+
+class VISQCfgData {
+ private _content: any;
+
+ static floatModelKey: string = "fp32_circle";
+ static quantizedModelKey: string = "q_circle";
+ static dataKey: string = "data";
+ static mpeirOutputKey: string = "mpeir_output";
+ static mseOutputKey: string = "mse_output";
+ static taeOutputKey: string = "tae_output";
+ static srmseOutputKey: string = "srmse_output";
+ static dumpDotKey: string = "dump_dot_graph";
+ static mpeirOnKey: string = "mpeir_on";
+ static mseOnKey: string = "mse_on";
+ static taeOnKey: string = "tae_on";
+ static srmseOnKey: string = "srmse_on";
+
+ static keys: string[] = [
+ VISQCfgData.floatModelKey,
+ VISQCfgData.quantizedModelKey,
+ VISQCfgData.dataKey,
+ ];
+
+ static metricKeys: { [metric: string]: any } = {
+ mpeir: [VISQCfgData.mpeirOnKey, VISQCfgData.mpeirOutputKey],
+ mse: [VISQCfgData.mseOnKey, VISQCfgData.mseOutputKey],
+ tae: [VISQCfgData.taeOnKey, VISQCfgData.taeOutputKey],
+ srmse: [VISQCfgData.srmseOnKey, VISQCfgData.srmseOutputKey],
+ };
+
+ constructor() {
+ this._content = {};
+ }
+
+ getAsString(): string {
+ return JSON.stringify(this._content, null, " ");
+ }
+
+ setWithString(text: string) {
+ this._content = JSON.parse(text);
+ }
+
+ getToolArgs(): string[] {
+ let args: string[] = [];
+ // set inputs
+ for (let key of VISQCfgData.keys) {
+ if (key in this._content) {
+ args.push("--" + key);
+ args.push(this._content[key]);
+ }
+ }
+
+ {
+ for (let metric in VISQCfgData.metricKeys) {
+ const onKey = VISQCfgData.metricKeys[metric][0];
+ const outputKey = VISQCfgData.metricKeys[metric][1];
+ if (
+ onKey in this._content &&
+ this._content[onKey] &&
+ outputKey in this._content
+ ) {
+ args.push("--" + outputKey);
+ args.push(this._content[outputKey]);
+ }
+ }
+ }
+
+ // set options
+ if (
+ VISQCfgData.dumpDotKey in this._content &&
+ this._content[VISQCfgData.dumpDotKey]
+ ) {
+ args.push("--" + VISQCfgData.dumpDotKey);
+ }
+
+ return args;
+ }
+
+ getOutputFiles(): string[] {
+ let outputs: string[] = [];
+ for (let metric in VISQCfgData.metricKeys) {
+ const onKey = VISQCfgData.metricKeys[metric][0];
+ const outputKey = VISQCfgData.metricKeys[metric][1];
+ if (
+ onKey in this._content &&
+ this._content[onKey] &&
+ outputKey in this._content
+ ) {
+ outputs.push(this._content[outputKey]);
+ }
+ }
+
+ return outputs;
+ }
+
+ setFloatModel(model: string): void {
+ this._content[VISQCfgData.floatModelKey] = model;
+ }
+
+ setQuantizedModel(model: string): void {
+ this._content[VISQCfgData.quantizedModelKey] = model;
+ }
+
+ setH5Data(data: string): void {
+ this._content[VISQCfgData.dataKey] = data;
+ }
+
+ setMPEIROutputPath(path: string): void {
+ this._content[VISQCfgData.mpeirOutputKey] = path;
+ }
+
+ setMSEOutputPath(path: string): void {
+ this._content[VISQCfgData.mseOutputKey] = path;
+ }
+
+ setTAEOutputPath(path: string): void {
+ this._content[VISQCfgData.taeOutputKey] = path;
+ }
+
+ setSRMSEOutputPath(path: string): void {
+ this._content[VISQCfgData.srmseOutputKey] = path;
+ }
+
+ setDumpDot(dump: boolean): void {
+ this._content[VISQCfgData.dumpDotKey] = dump;
+ }
+
+ setMPEIROn(on: boolean): void {
+ this._content[VISQCfgData.mpeirOnKey] = on;
+ }
+
+ setMSEOn(on: boolean): void {
+ this._content[VISQCfgData.mseOnKey] = on;
+ }
+
+ setTAEOn(on: boolean): void {
+ this._content[VISQCfgData.taeOnKey] = on;
+ }
+
+ setSRMSEOn(on: boolean): void {
+ this._content[VISQCfgData.srmseOnKey] = on;
+ }
+}
+
+export class VISQRunProvider implements vscode.CustomTextEditorProvider {
+ public static readonly viewType = "one.editor.cfgvisq";
+ public static readonly fileExtension = ".cfg.visq.json";
+
+ private _disposables: vscode.Disposable[] = [];
+ private _cfgDataMap: any = {};
+
+ public static register(context: vscode.ExtensionContext): void {
+ const provider = new VISQRunProvider(context);
+ const registrations = [
+ vscode.window.registerCustomEditorProvider(
+ VISQRunProvider.viewType,
+ provider,
+ {
+ webviewOptions: { retainContextWhenHidden: true },
+ }
+ ),
+ // Add command registration here
+ vscode.commands.registerCommand(
+ "one.editor.visqcfg.showFromDefaultExplorer",
+ (uri, selected) => {
+ // parse selection to get float model, quantized model, data path
+ let circleModels: string[] = [];
+ let h5Data: string = "";
+ for (let uri of selected) {
+ const extName = path.parse(uri.path).ext.slice(1);
+ if (extName === "circle") {
+ circleModels.push(uri.path);
+ } else if (extName === "h5") {
+ h5Data = uri.path;
+ }
+ }
+ if (circleModels.length < 1 || circleModels.length > 2) {
+ // TODO
+ return;
+ }
+ let floatModel = circleModels[0];
+ let quantizedModel =
+ circleModels.length === 2 ? circleModels[1] : undefined;
+ if (quantizedModel !== undefined) {
+ if (
+ floatModel.toLowerCase().includes(".q8") ||
+ floatModel.toLowerCase().includes(".q16")
+ ) {
+ [floatModel, quantizedModel] = [quantizedModel, floatModel];
+ }
+ }
+ const dirPath = path.parse(floatModel).dir;
+ const modelName = path.parse(floatModel).name;
+ const extName = path.parse(floatModel).ext.slice(1);
+
+ let defData = new VISQCfgData();
+ defData.setFloatModel(floatModel);
+ if (quantizedModel !== undefined) {
+ defData.setQuantizedModel(quantizedModel);
+ }
+ if (h5Data.length > 0) {
+ defData.setH5Data(h5Data);
+ }
+ let msePath: string = path.join(
+ dirPath,
+ modelName + ".mse.visq.json"
+ );
+ defData.setMSEOutputPath(msePath);
+ defData.setMSEOn(true);
+
+ let mpeirPath: string = path.join(
+ dirPath,
+ modelName + ".mpeir.visq.json"
+ );
+ defData.setMPEIROutputPath(mpeirPath);
+ defData.setMPEIROn(true);
+
+ let taePath: string = path.join(
+ dirPath,
+ modelName + ".tae.visq.json"
+ );
+ defData.setTAEOutputPath(taePath);
+ defData.setTAEOn(true);
+
+ let srmsePath: string = path.join(
+ dirPath,
+ modelName + ".srmse.visq.json"
+ );
+ defData.setSRMSEOutputPath(srmsePath);
+ defData.setSRMSEOn(true);
+
+ defData.setDumpDot(false);
+
+ const content = defData.getAsString();
+
+ const findInputPath = (name: string): string => {
+ const maxIters = 5;
+ for (let i = 0; i < maxIters; i++) {
+ const mpqPath: string = path.join(
+ dirPath,
+ name + VISQRunProvider.fileExtension
+ );
+ if (!fs.existsSync(mpqPath)) {
+ return name + VISQRunProvider.fileExtension;
+ }
+ name = name + "(1)";
+ }
+ return "";
+ };
+
+ let cfgName = findInputPath(modelName);
+ if (cfgName.length < 1) {
+ // failed to find valid name, just revert to initial version
+ cfgName = modelName + VISQRunProvider.fileExtension;
+ }
+
+ const validateInputPath = (name: string): string | undefined => {
+ const cfgPath: string = path.join(dirPath, name);
+ if (!cfgPath.endsWith(VISQRunProvider.fileExtension)) {
+ return (
+ "A file extension must be " + VISQRunProvider.fileExtension
+ );
+ }
+ if (fs.existsSync(cfgPath)) {
+ return `A file or folder ${cfgPath} already exists at this location. Please choose a different name.`;
+ }
+ };
+
+ vscode.window
+ .showInputBox({
+ title: `Create visq run configuration for '${modelName}.${extName}' :`,
+ placeHolder: `Enter a file name`,
+ value: cfgName,
+ valueSelection: [
+ 0,
+ cfgName.length - `${VISQRunProvider.fileExtension}`.length,
+ ],
+ validateInput: validateInputPath,
+ })
+ .then((value) => {
+ if (!value) {
+ Logger.debug("VISQRunProvider", "User hit the escape key!");
+ return;
+ }
+
+ // 'uri' path is not occupied, assured by validateInputPath
+ const uri = vscode.Uri.file(`${dirPath}/${value}`);
+ const edit = new vscode.WorkspaceEdit();
+ edit.createFile(uri);
+ edit.insert(uri, new vscode.Position(0, 0), content);
+ vscode.workspace.applyEdit(edit).then((isSuccess) => {
+ if (isSuccess) {
+ vscode.workspace.openTextDocument(uri).then((document) => {
+ document.save();
+ vscode.commands.executeCommand(
+ "vscode.openWith",
+ uri,
+ VISQRunProvider.viewType
+ );
+ });
+ } else {
+ Logger.error(
+ "VisqCfgRunner",
+ "CreateVisqCfg",
+ `Failed to create the file ${uri}`
+ );
+ }
+ });
+ });
+ }
+ ),
+ ];
+
+ registrations.forEach((disposable) =>
+ context.subscriptions.push(disposable)
+ );
+ }
+
+ constructor(private readonly context: vscode.ExtensionContext) {}
+
+ public async resolveCustomTextEditor(
+ document: vscode.TextDocument,
+ webviewPanel: vscode.WebviewPanel,
+ _token: vscode.CancellationToken
+ ): Promise {
+ this._cfgDataMap[document.uri.toString()] = new VISQCfgData();
+ await this.initWebview(document, webviewPanel);
+ this.initWebviewPanel(document, webviewPanel);
+ this.updateWebview(document, webviewPanel.webview);
+ }
+
+ private async initWebview(
+ document: vscode.TextDocument,
+ webviewPanel: vscode.WebviewPanel
+ ): Promise {
+ let webview: vscode.Webview = webviewPanel.webview;
+
+ webview.options = {
+ enableScripts: true,
+ };
+
+ const nonce = getNonce();
+ const scriptUri = getUri(webview, this.context.extensionUri, [
+ "media",
+ "VisqRunner",
+ "index.js",
+ ]);
+ const styleUri = getUri(webview, this.context.extensionUri, [
+ "media",
+ "VisqRunner",
+ "style.css",
+ ]);
+ const codiconUri = getUri(webview, this.context.extensionUri, [
+ "node_modules",
+ "@vscode",
+ "codicons",
+ "dist",
+ "codicon.css",
+ ]);
+ const toolkitUri = getUri(webview, this.context.extensionUri, [
+ "node_modules",
+ "@vscode",
+ "webview-ui-toolkit",
+ "dist",
+ "toolkit.js",
+ ]);
+ const htmlUri = vscode.Uri.joinPath(
+ this.context.extensionUri,
+ "media/VisqRunner/index.html"
+ );
+ let html = Buffer.from(
+ await vscode.workspace.fs.readFile(htmlUri)
+ ).toString();
+ html = html.replace(/\${nonce}/g, `${nonce}`);
+ html = html.replace(/\${webview.cspSource}/g, `${webview.cspSource}`);
+ html = html.replace(/\${scriptUri}/g, `${scriptUri}`);
+ html = html.replace(/\${toolkitUri}/g, `${toolkitUri}`);
+ html = html.replace(/\${cssUri}/g, `${styleUri}`);
+ html = html.replace(/\${codiconUri}/g, `${codiconUri}`);
+ webview.html = html;
+
+ // Receive message from the webview.
+ webview.onDidReceiveMessage((e) => {
+ switch (e.type) {
+ case "requestDisplayCFG":
+ this.updateWebview(document, webview);
+ break;
+ case "loadFloatInputFile":
+ this.handleLoadInputFile(true, document);
+ break;
+ case "loadQuantizedInputFile":
+ this.handleLoadInputFile(false, document);
+ break;
+ case "loadH5DataFile":
+ this.handleLoadH5DataFile(document);
+ break;
+ case "loadMPEIROutputFile":
+ this.handleLoadMPEIRInputFile(document);
+ break;
+ case "loadMSEOutputFile":
+ this.handleLoadMSEInputFile(document);
+ break;
+ case "loadTAEOutputFile":
+ this.handleLoadTAEInputFile(document);
+ break;
+ case "loadSRMSEOutputFile":
+ this.handleLoadSRMSEInputFile(document);
+ break;
+ case "dumpDot":
+ this.handleDumpDotToggled(e.dump, document);
+ break;
+ case "runCfg":
+ this.handleRunCfg(document);
+ break;
+ case "toggleMPEIROutputFile":
+ this.handleMPEIRToggle(e.on, document);
+ break;
+ case "toggleMSEOutputFile":
+ this.handleMSEToggle(e.on, document);
+ break;
+ case "toggleTAEOutputFile":
+ this.handleTAEToggle(e.on, document);
+ break;
+ case "toggleSRMSEOutputFile":
+ this.handleSRMSEToggle(e.on, document);
+ break;
+ case "onMPEIRChanged":
+ this.handleMPEIRChanged(e.path, document);
+ break;
+ case "onMSEChanged":
+ this.handleMSEChanged(e.path, document);
+ break;
+ case "onTAEChanged":
+ this.handleTAEChanged(e.path, document);
+ break;
+ case "onSRMSEChanged":
+ this.handleSRMSEhanged(e.path, document);
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ private handleLoadInputFile(float: boolean, document: vscode.TextDocument) {
+ let filters = {};
+ if (float) {
+ filters = { "target files": ["circle"] };
+ } else {
+ filters = { "target files": ["q8.circle", "q16.circle", "circle"] };
+ }
+
+ const dialogOptions = {
+ canSelectMany: false,
+ canSelectFolders: false,
+ openLabel: "Open",
+ filters: filters,
+ };
+
+ vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
+ if (fileUri && fileUri[0]) {
+ const path = fileUri[0].fsPath.toString();
+
+ let docUri = document.uri.toString();
+ if (float) {
+ this._cfgDataMap[docUri].setFloatModel(path);
+ } else {
+ this._cfgDataMap[docUri].setQuantizedModel(path);
+ }
+ this.updateDocument(document);
+ }
+ });
+ }
+
+ private handleLoadH5DataFile(document: vscode.TextDocument) {
+ const dialogOptions = {
+ canSelectMany: false,
+ canSelectFolders: false,
+ openLabel: "Open",
+ filters: { "target files": ["h5"] },
+ };
+
+ vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
+ if (fileUri && fileUri[0]) {
+ const path = fileUri[0].fsPath.toString();
+ this._cfgDataMap[document.uri.toString()].setH5Data(path);
+ this.updateDocument(document);
+ }
+ });
+ }
+
+ private handleLoadMPEIRInputFile(document: vscode.TextDocument) {
+ const dialogOptions = {
+ canSelectMany: false,
+ canSelectFolders: false,
+ openLabel: "Open",
+ filters: { "target files": ["mpeir.visq.json"] },
+ };
+
+ vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
+ if (fileUri && fileUri[0]) {
+ const path = fileUri[0].fsPath.toString();
+ this._cfgDataMap[document.uri.toString()].setMPEIROutputPath(path);
+ this.updateDocument(document);
+ }
+ });
+ }
+
+ private handleLoadMSEInputFile(document: vscode.TextDocument) {
+ const dialogOptions = {
+ canSelectMany: false,
+ canSelectFolders: false,
+ openLabel: "Open",
+ filters: { "target files": ["mse.visq.json"] },
+ };
+
+ vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
+ if (fileUri && fileUri[0]) {
+ const path = fileUri[0].fsPath.toString();
+ this._cfgDataMap[document.uri.toString()].setMSEOutputPath(path);
+ this.updateDocument(document);
+ }
+ });
+ }
+
+ private handleLoadTAEInputFile(document: vscode.TextDocument) {
+ const dialogOptions = {
+ canSelectMany: false,
+ canSelectFolders: false,
+ openLabel: "Open",
+ filters: { "target files": ["tae.visq.json"] },
+ };
+
+ vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
+ if (fileUri && fileUri[0]) {
+ const path = fileUri[0].fsPath.toString();
+ this._cfgDataMap[document.uri.toString()].setTAEOutputPath(path);
+ this.updateDocument(document);
+ }
+ });
+ }
+
+ private handleLoadSRMSEInputFile(document: vscode.TextDocument) {
+ const dialogOptions = {
+ canSelectMany: false,
+ canSelectFolders: false,
+ openLabel: "Open",
+ filters: { "target files": ["mse.visq.json"] },
+ };
+
+ vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
+ if (fileUri && fileUri[0]) {
+ const path = fileUri[0].fsPath.toString();
+ this._cfgDataMap[document.uri.toString()].setSRMSEOutputPath(path);
+ this.updateDocument(document);
+ }
+ });
+ }
+
+ private handleRunCfg(document: vscode.TextDocument) {
+ // as for now installed visq doesn't work because it lacks DotBuilder.py
+ // which is not included into installation
+ const tool =
+ "/home/stanislav/repos/ONE_f/ONE/build/release_build_4/bin/visq"; //"/usr/share/one/bin/visq";
+ const cmd = new Command(tool);
+ const toolargs: string[] =
+ this._cfgDataMap[document.uri.toString()].getToolArgs();
+ toolargs.forEach((option) => {
+ cmd.push(option);
+ });
+ let visqJob = new VisqCommand(cmd);
+ visqJob.successCallback = () => {
+ Balloon.info("Running visq has succeeded.");
+ const outputs: string[] =
+ this._cfgDataMap[document.uri.toString()].getOutputFiles();
+ for (let output of outputs) {
+ let uri: vscode.Uri = vscode.Uri.file(output);
+ vscode.commands.executeCommand("vscode.open", uri);
+ }
+ };
+
+ visqJob.failureCallback = () => {
+ Balloon.error("Running visq has failed.");
+ };
+
+ let jobs = new WorkJobs(visqJob);
+ let runner = new JobRunner();
+ runner.start(jobs);
+ }
+
+ private handleDumpDotToggled(dump: boolean, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setDumpDot(dump);
+ this.updateDocument(document);
+ }
+
+ private handleMPEIRToggle(on: boolean, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setMPEIROn(on);
+ this.updateDocument(document);
+ }
+
+ private handleMSEToggle(on: boolean, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setMSEOn(on);
+ this.updateDocument(document);
+ }
+
+ private handleTAEToggle(on: boolean, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setTAEOn(on);
+ this.updateDocument(document);
+ }
+
+ private handleSRMSEToggle(on: boolean, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setSRMSEOn(on);
+ this.updateDocument(document);
+ }
+
+ private handleMPEIRChanged(path: string, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setMPEIROutputPath(path);
+ this.updateDocument(document);
+ }
+
+ private handleMSEChanged(path: string, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setMSEOutputPath(path);
+ this.updateDocument(document);
+ }
+
+ private handleTAEChanged(path: string, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setTAEOutputPath(path);
+ this.updateDocument(document);
+ }
+
+ private handleSRMSEhanged(path: string, document: vscode.TextDocument) {
+ this._cfgDataMap[document.uri.toString()].setSRMSEOutputPath(path);
+ this.updateDocument(document);
+ }
+
+ private updateDocument(document: vscode.TextDocument) {
+ if (
+ this._cfgDataMap[document.uri.toString()].getAsString() !==
+ document.getText()
+ ) {
+ // TODO Optimize this to modify only changed lines
+ const edit = new vscode.WorkspaceEdit();
+ edit.replace(
+ document.uri,
+ new vscode.Range(0, 0, document.lineCount, 0),
+ this._cfgDataMap[document.uri.toString()].getAsString()
+ );
+ vscode.workspace.applyEdit(edit);
+ }
+ }
+
+ private initWebviewPanel(
+ document: vscode.TextDocument,
+ webviewPanel: vscode.WebviewPanel
+ ): void {
+ vscode.commands.executeCommand(
+ "setContext",
+ VISQRunProvider.viewType,
+ true
+ );
+
+ const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument(
+ (e) => {
+ if (
+ e.contentChanges.length > 0 &&
+ e.document.uri.toString() === document.uri.toString()
+ ) {
+ this.updateWebview(document, webviewPanel.webview);
+ }
+ }
+ );
+
+ webviewPanel.onDidChangeViewState(
+ () => {
+ vscode.commands.executeCommand(
+ "setContext",
+ VISQRunProvider.viewType,
+ webviewPanel.visible
+ );
+ },
+ null,
+ this._disposables
+ );
+
+ webviewPanel.onDidDispose(() => {
+ changeDocumentSubscription.dispose();
+ while (this._disposables.length) {
+ const x = this._disposables.pop();
+ if (x) {
+ x.dispose();
+ }
+ }
+ vscode.commands.executeCommand(
+ "setContext",
+ VISQRunProvider.viewType,
+ false
+ );
+ });
+ }
+
+ private updateWebview(
+ document: vscode.TextDocument,
+ webview: vscode.Webview
+ ): void {
+ this._cfgDataMap[document.uri.toString()].setWithString(document.getText());
+ const content = JSON.parse(document.getText());
+ if (content !== undefined) {
+ webview.postMessage({
+ type: "displayCFG",
+ content: content,
+ });
+ }
+ }
+}
diff --git a/src/extension.ts b/src/extension.ts
index ad6c476e..19a31c4a 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -30,6 +30,7 @@ import { PartGraphSelPanel } from "./PartEditor/PartGraphSelector";
import { ToolchainProvider } from "./Toolchain/ToolchainProvider";
import { Logger } from "./Utils/Logger";
import { VisqViewerProvider } from "./Visquv/VisqViewer";
+import { VISQRunProvider } from "./VisqRunner/VisqRunProvider";
/* istanbul ignore next */
export function activate(context: vscode.ExtensionContext) {
@@ -77,6 +78,8 @@ export function activate(context: vscode.ExtensionContext) {
MetadataViewerProvider.register(context);
+ VISQRunProvider.register(context);
+
// returning backend registration function that will be called by backend extensions
return backendRegistrationApi();
}