diff --git a/media/MPQEditor/index.html b/media/MPQEditor/index.html new file mode 100644 index 00000000..20dd57d6 --- /dev/null +++ b/media/MPQEditor/index.html @@ -0,0 +1,72 @@ + + + + + + + + Mixed Precision Quantization editor + + + + + + +
+
+
+ + + uint8 + int16 + +
+
+ + + layer + channel + +
+
+
+
+ +
+
+
+ + + +
+
+
+ + + Name + Quantization + Granularity +   + + +
+ + diff --git a/media/MPQEditor/index.js b/media/MPQEditor/index.js new file mode 100644 index 00000000..c68e97af --- /dev/null +++ b/media/MPQEditor/index.js @@ -0,0 +1,276 @@ +/* + * 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 "displayMPQ": + displayMPQToEditor(message.content); + break; + case "modelNodesChanged": + handleModelNodesChanged(message.names); + break; + default: + break; + } + }); + + vscode.postMessage({ type: "requestModelNodes" }); +} + +function register() { + registerMainControls(); +} + +function handleModelNodesChanged(names) { + document.getElementById("AddSpecificLayer").disabled = names.length < 1; +} + +function registerMainControls() { + document + .getElementById("DefaultDtype") + .addEventListener("click", function () { + updateDefaultQuantization(); + applyUpdates(); + }); + + document + .getElementById("DefaultGranularity") + .addEventListener("click", function () { + updateGranularity(); + applyUpdates(); + }); + + document + .getElementById("AddSpecificLayer") + .addEventListener("click", function () { + vscode.postMessage({ + type: "addSpecificLayerFromDialog", + }); + }); + + document.getElementById("AddSpecificLayer").disabled = true; +} + +function displayMPQToEditor(mpqCfg) { + document.getElementById("DefaultDtype").value = + mpqCfg?.["default_quantization_dtype"]; + document.getElementById("DefaultGranularity").value = + mpqCfg?.["default_granularity"]; + + const length = mpqCfg && mpqCfg["layers"] ? mpqCfg["layers"].length : 0; + + let names = Array(length); + let quantization = Array(length); + let granularity = Array(length); + for (let i = 0; i < length; i++) { + names[i] = mpqCfg["layers"][i]["name"]; + quantization[i] = mpqCfg["layers"][i]["dtype"]; + granularity[i] = mpqCfg["layers"][i]["granularity"]; + } + + const layersTable = document.getElementById("LayersTable"); + layersTable.replaceChildren(); + addQuantizedNodes(names, quantization, granularity, false); +} + +function addQuantizedNodes(names, quantization, granularity, update) { + const layersTable = document.getElementById("LayersTable"); + for (let idx = 0; idx < names.length; idx++) { + if (names[idx].length < 1) { + continue; + } + + let row = document.createElement("vscode-data-grid-row"); + const name = names[idx]; + + // name + let cellName = document.createElement("vscode-data-grid-cell"); + cellName.textContent = name; + cellName.setAttribute("grid-column", "1"); + row.appendChild(cellName); + // quantization + let cellQuantization = document.createElement("vscode-data-grid-cell"); + let quantDropdown = document.createElement("vscode-dropdown"); + { + let uint8Opt = document.createElement("vscode-option"); + uint8Opt.innerText = "uint8"; + uint8Opt.value = 0; + quantDropdown.appendChild(uint8Opt); + let int16Opt = document.createElement("vscode-option"); + int16Opt.innerText = "int16"; + int16Opt.value = 1; + quantDropdown.appendChild(int16Opt); + } + quantDropdown.setAttribute("id", "dropdownQuantization" + name); + cellQuantization.appendChild(quantDropdown); + cellQuantization.setAttribute("grid-column", "2"); + row.appendChild(cellQuantization); + // granularity + let cellGranularity = document.createElement("vscode-data-grid-cell"); + let granularityDropdown = document.createElement("vscode-dropdown"); + { + let layerOpt = document.createElement("vscode-option"); + layerOpt.innerText = "layer"; + layerOpt.value = 0; + granularityDropdown.appendChild(layerOpt); + let channelOpt = document.createElement("vscode-option"); + channelOpt.innerText = "channel"; + channelOpt.value = 1; + granularityDropdown.appendChild(channelOpt); + } + granularityDropdown.setAttribute("id", "dropdownGranularity" + name); + cellGranularity.appendChild(granularityDropdown); + cellGranularity.setAttribute("grid-column", "3"); + row.appendChild(cellGranularity); + + // remove button + let cellRemoveBtn = document.createElement("vscode-data-grid-cell"); + let remBtn = document.createElement("vscode-button"); + remBtn.setAttribute("id", "removeButton" + name); + remBtn.appearance = "icon"; + { + let iconSpan = document.createElement("span"); + iconSpan.className = "codicon codicon-chrome-close"; + iconSpan.slot = "start"; + remBtn.appendChild(iconSpan); + } + cellRemoveBtn.appendChild(remBtn); + cellRemoveBtn.setAttribute("grid-column", "4"); + row.appendChild(cellRemoveBtn); + + layersTable.appendChild(row); + } + + // set quantization and granularity attributes + for (let idx = 0; idx < names.length; idx++) { + if (names[idx].length < 1) { + continue; + } + + const name = names[idx]; + const qValue = quantization[idx] === "uint8" ? 0 : 1; + document.getElementById("dropdownQuantization" + name).value = qValue; + + const gValue = granularity[idx] === "layer" ? 0 : 1; + document.getElementById("dropdownGranularity" + name).value = gValue; + } + + // set change values + for (let idx = 0; idx < names.length; idx++) { + if (names[idx].length < 1) { + continue; + } + + const name = names[idx]; + document + .getElementById("dropdownQuantization" + name) + .addEventListener("change", function () { + updateSpecificQuantization(name); + applyUpdates(); + }); + + document + .getElementById("dropdownGranularity" + name) + .addEventListener("change", function () { + updateSpecificGranularity(name); + applyUpdates(); + }); + + document + .getElementById("removeButton" + name) + .addEventListener("click", function () { + removeLayer(name); + }); + } + + if (update) { + updateLayers(names, quantization, granularity); + applyUpdates(); + } +} + +function updateLayers(names, quantization, granularity) { + vscode.postMessage({ + type: "updateLayers", + names: names, + quantization: quantization, + granularity: granularity, + }); +} + +function removeLayer(name) { + vscode.postMessage({ + type: "removeLayer", + name: name, + }); +} + +function updateSpecificQuantization(name) { + const value = + document.getElementById("dropdownQuantization" + name).value === 0 + ? "uint8" + : "int16"; + vscode.postMessage({ + type: "updateSpecificQuantization", + name: name, + value: value, + }); +} + +function updateSpecificGranularity(name) { + const value = + document.getElementById("dropdownGranularity" + name).value === 0 + ? "layer" + : "channel"; + vscode.postMessage({ + type: "updateSpecificGranularity", + name: name, + value: value, + }); +} + +function updateDefaultQuantization() { + let value = document.getElementById("DefaultDtype").value; + vscode.postMessage({ + type: "updateSection", + section: "default_quantization_dtype", + value: value, + }); +} + +function updateGranularity() { + let value = document.getElementById("DefaultGranularity").value; + vscode.postMessage({ + type: "updateSection", + section: "default_granularity", + value: value, + }); +} + +function applyUpdates() { + vscode.postMessage({ type: "updateDocument" }); +} diff --git a/media/MPQEditor/style.css b/media/MPQEditor/style.css new file mode 100644 index 00000000..6c86eb72 --- /dev/null +++ b/media/MPQEditor/style.css @@ -0,0 +1,28 @@ +/* + * 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; +} + +.leftbtns { +float: left; +}