diff --git a/misc/config_tools/configurator/packages/configurator/src/lib/acrn.ts b/misc/config_tools/configurator/packages/configurator/src/lib/acrn.ts index 286ab6003..55e987b13 100644 --- a/misc/config_tools/configurator/packages/configurator/src/lib/acrn.ts +++ b/misc/config_tools/configurator/packages/configurator/src/lib/acrn.ts @@ -1,18 +1,631 @@ import {dialog, invoke} from "@tauri-apps/api"; import JSON2XML from "./json2xml" import {OpenDialogOptions} from "@tauri-apps/api/dialog"; +import _ from "lodash"; +import {vueUtils} from "@lljj/vue3-form-naive"; -enum HistoryType { +function all(arr: boolean[]): boolean { + return arr.every(element => element === true); +} + +function count(source, target) { + return (source.match(new RegExp(target, 'g')) || []).length; +} + + +declare global { + interface Window { + configurator: Configurator; + getSchemaData: () => any; + getCurrentScenarioData: () => any; + getBoardData: () => any; + pyodide: { + pyimport: (name: string) => { main: (...any) => any }, + runPython: (code: string) => string + }; + } +} + +enum HistoryTypeEnum { WorkingFolder, Board, Scenario } -export type HistoryTypeString = keyof typeof HistoryType; +export type HistoryTypes = keyof typeof HistoryTypeEnum; + + +enum PolicyTypeEnum { + Unified, + Code, + Data +} + +type PolicyType = keyof typeof PolicyTypeEnum + +type Policy = { + VM: string, + VCPU: number, + TYPE: PolicyType, + CLOS_MASK: string +} + +type CATDBRecord = { + CACHE_LEVEL: number, + CACHE_ID: string, + META: { vmid: number }, + VM: string, + VCPU: number, + TYPE: PolicyType, + CLOS_MASK: string +} + +type CATUIDataObject = { + errorMsg: string, + regions: { + level: number, + id: string, + capacity_mask_length: number, + type: string, + cache_size: number, + processors: number[], + data: { + RTCore: Policy[], + Standard: Policy[], + VCAT: Policy[], + }, + }[], + summary: { + [CATRegionLevel: string]: { + count: number, + [CATRegionID: string]: number + } + } +} + + +type vmID = number; + +class CAT { + private scenario: any; + private schemaData: any; + private CAT_REGION_INFO: any; + + private switches: { + SSRAM_ENABLED: boolean, + RDT_ENABLED: boolean, + CDP_ENABLED: boolean, + VCAT_ENABLED: boolean + }; + + private preLaunchedVMCPUs: string[]; + private serviceVM: any; + private serviceVMCPUs: string[]; + + public CATDB: CATDBRecord[]; + private vmIDs: { [vmName: string]: vmID }; + + hexToRange(hexValue, maxValue) { + let str_bin = Number.parseInt(hexValue).toString(2); + let block_length = str_bin.length; + let block_enabled_length = count(str_bin, "1"); + + let start: number + let end: number + + if (block_length > maxValue) { + if (block_enabled_length >= maxValue) { + str_bin = "1".repeat(maxValue); + } else { + str_bin = "0".repeat(maxValue - block_enabled_length) + "1".repeat(block_enabled_length); + } + } else { + if (block_length < maxValue) { + str_bin = "0".repeat(maxValue - block_length) + str_bin; + } + } + + start = str_bin.indexOf("1") !== -1 ? str_bin.indexOf("1") : 0; + end = start + count(str_bin, "1"); + + return [start, end] + } + + rangeToHex(value, max) { + let newHexValue = '0'.repeat(value[0]) + '1'.repeat(value[1] - value[0]) + '0'.repeat(max - value[1]) + newHexValue = (parseInt(newHexValue, 2).toString(16)) + let zeroPadding = '0'.repeat(Number.parseInt('1'.repeat(max), 2).toString(16).length - newHexValue.length) + newHexValue = '0x' + zeroPadding + newHexValue; + return newHexValue; + } + + formDataProxy(name, data = null, update = false) { + let path = { + 'SSRAM_ENABLED': 'FEATURES.SSRAM.SSRAM_ENABLED', + 'RDT_ENABLED': 'FEATURES.RDT.RDT_ENABLED', + 'CDP_ENABLED': 'FEATURES.RDT.CDP_ENABLED', + 'VCAT_ENABLED': 'FEATURES.RDT.VCAT_ENABLED', + }[name] + + // check parent node exists + let oldValue = vueUtils.getPathVal(this.scenario.hv, path); + if (oldValue === undefined) { + let t = path.split('.'); + let parentPath = t.splice(0, t.length - 1).join('.'); + if (!vueUtils.getPathVal(this.scenario.hv, parentPath)) { + vueUtils.setPathVal(this.scenario.hv, parentPath, {}); + } + // set to checkbox default value + vueUtils.setPathVal(this.scenario.hv, path, 'n'); + } + // if data is not empty, set value + if (data !== null) { + vueUtils.setPathVal(this.scenario.hv, path, data) + + // if data is not empty, set value as expected and update CAT_INFO + if (update) { + switch (name) { + case 'SSRAM_ENABLED': + this.formDataProxy('RDT_ENABLED', 'n'); + this.formDataProxy('CDP_ENABLED', 'n'); + this.formDataProxy('VCAT_ENABLED', 'n'); + break; + case 'RDT_ENABLED': + this.formDataProxy('SSRAM_ENABLED', 'n'); + if (data === 'n') { + this.formDataProxy('CDP_ENABLED', 'n'); + this.formDataProxy('VCAT_ENABLED', 'n'); + } + break; + case 'CDP_ENABLED': + this.formDataProxy('SSRAM_ENABLED', 'n'); + if (data === 'y') { + this.formDataProxy('RDT_ENABLED', 'y'); + this.formDataProxy('VCAT_ENABLED', 'n'); + } + break; + case 'VCAT_ENABLED': + this.formDataProxy('SSRAM_ENABLED', 'n'); + if (data === 'y') { + this.formDataProxy('RDT_ENABLED', 'y'); + this.formDataProxy('CDP_ENABLED', 'n'); + } + break; + } + } + } + let result: string; + // @ts-ignore + result = vueUtils.getPathVal(this.scenario.hv, path); + if (typeof result !== 'string') { + console.log(`Unexpected result of ${name}: `, result) + } + return result + } + + + scenarioLoaded() { + // get CAT schema && scenario data + this.schemaData = window.getSchemaData(); + this.scenario = window.getCurrentScenarioData(); + this.vmIDs = this.getVMIDs() + // get cat scenario data + this.CATDB = this.getCATDataFromScenario(); + } + + getScenarioDataFromCAT() { + let CATUIData = this.getCATUIData(); + let ScenarioCATData: { + CACHE_ALLOCATION: { + CACHE_ID: string, + CACHE_LEVEL: number, + POLICY: Policy[] + }[] + } + if (CATUIData.regions.length === 0) { + return null; + } + ScenarioCATData = {CACHE_ALLOCATION: []} + for (const region of CATUIData.regions) { + let policies: Policy[] = region.data.RTCore.concat(region.data.Standard, region.data.VCAT); + ScenarioCATData.CACHE_ALLOCATION.push({ + CACHE_ID: region.id, + CACHE_LEVEL: region.level, + POLICY: policies + }) + } + return ScenarioCATData; + } + + + getCATUIData(): CATUIDataObject { + // get CAT schema && scenario && board basic data + this.schemaData = window.getSchemaData(); + this.scenario = window.getCurrentScenarioData(); + this.CAT_REGION_INFO = window.getBoardData().CAT_INFO; + + // check scenario data is empty + // usually, this happens when user has no scenario loaded, then import a board + if (!this.scenario.hv) { + return null; + } + + + // get switches status from scenario + // @ts-ignore + this.switches = new Proxy({}, { + get: (target: {}, switchName: string | symbol): any => { + return this.formDataProxy(switchName) === 'y' + }, + set: (target: {}, switchName: string | symbol, value: boolean): boolean => { + return this.formDataProxy(switchName, value ? 'y' : 'n', true) === 'y'; + } + }) + + + // if no CAT REGION INFO from board xml, + // means this board(or CPU) not support CAT, or all support CAT region only have one CPU core + if (this.CAT_REGION_INFO.length === 0) { + let errorMsg = 'This board(or CPU) not support CAT, or all support CAT region only have one CPU core'; + console.log(errorMsg); + return { + errorMsg, + regions: [], + summary: {} + }; + } + + // correct switches and return rdt_enabled result + if (!this.correctSwitches()) { + return { + errorMsg: '', + regions: [], + summary: {} + } + } + + + // CPU affinity data checks + // If error, only show error message + let errorMsg = this.checkCPUAffinity() + + + // get CPU data + this.preLaunchedVMCPUs = this.getPreLaunchedVMCPUs(); + this.serviceVM = this.getServiceVM(); + this.serviceVMCPUs = this.getServiceVMVCPUs() + this.vmIDs = this.getVMIDs() + + + let CATUIData: CATUIDataObject = { + errorMsg, regions: [], summary: {} + }; + // mapping CAT region info + this.CAT_REGION_INFO.map(region => { + let regionData = _.cloneDeep(region); + if (!CATUIData.summary.hasOwnProperty(regionData.level)) { + CATUIData.summary[regionData.level] = {count: 0} + } + CATUIData.summary[regionData.level].count++; + CATUIData.summary[regionData.level][regionData.id] = CATUIData.summary[regionData.level].count; + + regionData['data'] = { + RTCore: this.getRTCoreData(regionData), + Standard: this.getStandardData(regionData), + VCAT: this.getVCATData(regionData) + } + CATUIData.regions.push(regionData); + }) + + + return CATUIData + } + + haveCPUAffinity(vmConfig) { + if (vmConfig.load_order === 'SERVICE_VM') { + return false + } + return ( + vmConfig.hasOwnProperty('cpu_affinity') && + vmConfig.cpu_affinity.hasOwnProperty('pcpu') && + _.isArray(vmConfig.cpu_affinity.pcpu) + ) + } + + checkCPUAffinity() { + // check cpu affinity + let errMsg = ['CPU affinity is not set for the following VMs:']; + let result = all(this.scenario.vm.map(vmConfig => { + if (vmConfig.load_order === 'SERVICE_VM') { + return true + } + let haveCPUAffinitySetting = this.haveCPUAffinity(vmConfig); + if (!haveCPUAffinitySetting) { + errMsg.push(`VM ${vmConfig.name} has no CPU affinity setting`); + } + return haveCPUAffinitySetting; + })) + if (result) { + return ''; + } + errMsg.push('Please set CPU affinity for all VMs'); + return errMsg.join('\n') + } + + correctSwitches() { + if (this.switches.SSRAM_ENABLED) { + if (this.switches.RDT_ENABLED) { + this.switches.RDT_ENABLED = false + } + if (this.switches.CDP_ENABLED) { + this.switches.CDP_ENABLED = false + } + if (this.switches.VCAT_ENABLED) { + this.switches.VCAT_ENABLED = false + } + } else if (this.switches.RDT_ENABLED) { + if (this.switches.CDP_ENABLED) { + if (this.switches.VCAT_ENABLED) { + this.switches.VCAT_ENABLED = false + } + } + } else if (this.switches.CDP_ENABLED || this.switches.VCAT_ENABLED) { + if (!this.switches.RDT_ENABLED) { + this.switches.RDT_ENABLED = true + } + } + return this.switches.RDT_ENABLED + } + + getPreLaunchedVMCPUs() { + let preLaunchedVMCPUs = []; + + this.scenario.vm.map(vmConfig => { + if (vmConfig.load_order === 'PRE_LAUNCHED_VM' && this.haveCPUAffinity(vmConfig)) { + let vmCPUIDs = vmConfig.cpu_affinity.pcpu.map(pcpu => { + return pcpu.pcpu_id; + }) + preLaunchedVMCPUs.concat(vmCPUIDs) + } + }) + + return preLaunchedVMCPUs; + } + + newPolicy(CACHE_ID, CACHE_LEVEL, vmConfig, VCPU, TYPE: PolicyType, maxLength): Policy { + let originPolicy = { + VM: vmConfig.name, + VCPU, TYPE, + CLOS_MASK: this.getCLOSMask(CACHE_ID, CACHE_LEVEL, vmConfig['@id'], vmConfig.name, VCPU, TYPE, maxLength) + } + return new Proxy(originPolicy, { + set: (target, key, value) => { + target[key] = value; + if (key === 'CLOS_MASK') { + console.log(`${CACHE_ID} ${CACHE_LEVEL} ${vmConfig.name} ${VCPU} ${TYPE} CLOS_MASK: ${value}`); + this.setCLOSMask(CACHE_ID, CACHE_LEVEL, vmConfig['@id'], vmConfig.name, VCPU, TYPE, value); + } + return true; + } + }) + } + + selectCATData(CACHE_ID, CACHE_LEVEL, vmID, vmName, VCPU, TYPE: PolicyType) { + for (let i = 0; i < this.CATDB.length; i++) { + let CATData = this.CATDB[i]; + if ( + CATData.CACHE_ID === CACHE_ID && CATData.CACHE_LEVEL === CACHE_LEVEL && + CATData.META.vmid === vmID && CATData.VCPU === VCPU && CATData.TYPE === TYPE + ) { + return CATData + } + } + return false; + } + + setCLOSMask(CACHE_ID, CACHE_LEVEL, vmID, vmName, VCPU, TYPE: PolicyType, CLOS_MASK: string) { + let CATData = this.selectCATData(CACHE_ID, CACHE_LEVEL, vmID, vmName, VCPU, TYPE); + if (CATData !== false) { + CATData.CLOS_MASK = CLOS_MASK; + return true; + } + + this.CATDB.push({ + META: {vmid: vmID}, + CACHE_ID, CACHE_LEVEL, + CLOS_MASK, + VM: vmName, VCPU, TYPE, + }) + return true; + } + + getCLOSMask(CACHE_ID, CACHE_LEVEL, vmID, vmName, VCPU, TYPE: PolicyType, maxLength: number) { + let CATData = this.selectCATData(CACHE_ID, CACHE_LEVEL, vmID, vmName, VCPU, TYPE); + if (CATData !== false) { + let CLOS_MASK = CATData.CLOS_MASK; + // ensure CLOS_MASK length is shorter or equal to maxLength + CLOS_MASK = this.rangeToHex(this.hexToRange(CLOS_MASK, maxLength), maxLength); + return CLOS_MASK; + } + let CLOS_MASK = "0x" + parseInt('1'.repeat(maxLength), 2).toString(16) + this.CATDB.push({ + META: {vmid: vmID}, + CACHE_ID, CACHE_LEVEL, + CLOS_MASK, + VM: vmName, VCPU, TYPE, + }) + return CLOS_MASK; + } + + getRTCoreData(regionData): Policy[] { + let RTCoreData: Policy[] = []; + this.scenario.vm.map(vmConfig => { + if (this.haveCPUAffinity(vmConfig)) { + vmConfig.cpu_affinity.pcpu.map( + (pcpu, index) => { + if ( + regionData.processors.indexOf(pcpu.pcpu_id) !== -1 && + pcpu.hasOwnProperty('real_time_vcpu') && + pcpu.real_time_vcpu === 'y' + ) { + if (!this.switches.CDP_ENABLED) { + RTCoreData.push(this.newPolicy(regionData.level, regionData.id, vmConfig, index, 'Unified', regionData.capacity_mask_length)) + } else { + RTCoreData.push(this.newPolicy(regionData.level, regionData.id, vmConfig, index, 'Code', regionData.capacity_mask_length)) + RTCoreData.push(this.newPolicy(regionData.level, regionData.id, vmConfig, index, 'Data', regionData.capacity_mask_length)) + } + } + } + ) + } + }) + + _.sortBy(RTCoreData, ['VM', 'VCPU', 'TYPE']); + + return RTCoreData; + } + + + getStandardData(regionData): Policy[] { + let StandardData: Policy[] = []; + this.scenario.vm.map(vmConfig => { + if (this.haveCPUAffinity(vmConfig)) { + vmConfig.cpu_affinity.pcpu.map( + (pcpu, index) => { + if ( + regionData.processors.indexOf(pcpu.pcpu_id) !== -1 && ( + !pcpu.hasOwnProperty('real_time_vcpu') || + pcpu.real_time_vcpu === 'n' + ) + ) { + if (!this.switches.CDP_ENABLED) { + StandardData.push(this.newPolicy(regionData.level, regionData.id, vmConfig, index, 'Unified', regionData.capacity_mask_length)) + } else { + StandardData.push(this.newPolicy(regionData.level, regionData.id, vmConfig, index, "Code", regionData.capacity_mask_length)) + StandardData.push(this.newPolicy(regionData.level, regionData.id, vmConfig, index, "Data", regionData.capacity_mask_length)) + } + } + }) + } + }) + + // add service vm policy + StandardData = StandardData.concat( + this.getServiceData(regionData), + ) + + _.sortBy(StandardData, ['VM', 'VCPU', 'TYPE']); + return StandardData; + } + + getServiceData(regionData): Policy[] { + let ServiceData: Policy[] = []; + + this.serviceVMCPUs.map((pcpuID, index) => { + if (regionData.processors.indexOf(pcpuID) !== -1) { + if (!this.switches.CDP_ENABLED) { + ServiceData.push(this.newPolicy(regionData.level, regionData.id, this.serviceVM, index, "Unified", regionData.capacity_mask_length)) + } else { + ServiceData.push(this.newPolicy(regionData.level, regionData.id, this.serviceVM, index, "Code", regionData.capacity_mask_length)) + ServiceData.push(this.newPolicy(regionData.level, regionData.id, this.serviceVM, index, "Data", regionData.capacity_mask_length)) + } + } + }) + return ServiceData; + } + + getVCATData(regionData): Policy[] { + let VCATData: Policy[] = []; + // VCAT is only available for CPU 0 + if (this.switches.VCAT_ENABLED && regionData.processors.indexOf(0) !== -1) { + this.scenario.vm.map(vmConfig => { + if ( + this.haveCPUAffinity(vmConfig) && + vmConfig.hasOwnProperty('virtual_cat_support') && + vmConfig.virtual_cat_support === "y" + ) { + VCATData.push( + this.newPolicy(regionData.level, regionData.id, vmConfig, 0, "Unified", vmConfig.virtual_cat_number) + ) + } + }) + } + _.sortBy(VCATData, ['VM']); + return VCATData; + } + + private getServiceVM() { + let serviceVM = null; + this.scenario.vm.map(vmConfig => { + if (vmConfig.load_order === 'SERVICE_VM') { + serviceVM = vmConfig; + } + }) + return serviceVM; + } + + private getServiceVMVCPUs() { + let serviceVMCPUs = []; + if (this.serviceVM !== null) { + // noinspection JSUnresolvedVariable + this.schemaData.HV.BasicConfigType.definitions.CPUAffinityConfiguration.properties.pcpu_id.enum.map((pcpu_id) => { + // if pcpu_id in preLaunchedVMCPUIDs, it's used by pre launched vm, we need skip it + if (this.preLaunchedVMCPUs.indexOf(pcpu_id) !== -1) { + return; + } + serviceVMCPUs.push(pcpu_id); + }) + } + return serviceVMCPUs; + } + + + private getCATDataFromScenario() { + let hv = this.scenario.hv; + let scenarioCATData: CATDBRecord[] = [] + + // noinspection JSUnresolvedVariable + if ( + hv !== null && + hv.hasOwnProperty('CACHE_ALLOCATION') && + _.isArray(hv.CACHE_ALLOCATION) + ) { + // noinspection JSUnresolvedVariable + hv.CACHE_ALLOCATION.map((cache_region) => { + if ( + cache_region.hasOwnProperty('POLICY') && + cache_region.POLICY.length > 0 + ) { + cache_region.POLICY.map(policy => { + scenarioCATData.push({ + CACHE_ID: cache_region.id, + CACHE_LEVEL: cache_region.level, + CLOS_MASK: policy.CLOS_MASK, + META: {vmid: this.vmIDs[policy.VM]}, + TYPE: policy.TYPE, + VCPU: policy.VCPU, + VM: policy.VM + }) + }) + } + + }) + } + + return scenarioCATData + } + + private getVMIDs(): { [vmName: string]: vmID } { + let vmIDs = {} + this.scenario.vm.map(vmConfig => { + vmIDs[vmConfig.name] = vmConfig['@id'] + }) + return vmIDs + } +} class PythonObject { api(scriptName, output_format, ...params) { - // @ts-ignore let pythonFunction = window.pyodide.pyimport(`configurator.pyodide.${scriptName}`); let result = pythonFunction.main(...params); if (output_format === 'json') { @@ -54,12 +667,14 @@ class PythonObject { class Configurator { public pythonObject: PythonObject; + public cat: CAT; constructor() { this.pythonObject = new PythonObject() + this.cat = new CAT() } - getHistory(historyType: HistoryTypeString): Promise { + getHistory(historyType: HistoryTypes): Promise { return invoke("get_history", {historyType}) .then((historyJsonText) => { if (typeof historyJsonText === "string") { @@ -69,7 +684,7 @@ class Configurator { }) } - addHistory(historyType: HistoryTypeString, historyPath: String) { + addHistory(historyType: HistoryTypes, historyPath: string) { return invoke("add_history", {historyType, historyPath}) } @@ -77,44 +692,43 @@ class Configurator { return dialog.open(options) } - readFile(filePath: String): Promise { + readFile(filePath: string): Promise { return invoke("acrn_read", {filePath}) } - writeFile(filePath: String, contents: String) { + writeFile(filePath: string, contents: string) { return invoke("acrn_write", {filePath, contents}) } - isFile(filePath: String): Promise { + isFile(filePath: string): Promise { return invoke("acrn_is_file", {path: filePath}) } - readDir(path: String, recursive: Boolean) { + readDir(path: string, recursive: Boolean) { return invoke('acrn_read_dir', {path, recursive}) } - creatDir(path: String, recursive = true) { + creatDir(path: string, recursive = true) { return invoke('acrn_create_dir', {path, recursive}) } - removeDir(path: String) { + removeDir(path: string) { return invoke('acrn_remove_dir', {path}) } - removeFile(path: String) { + removeFile(path: string) { return invoke('acrn_remove_file', {path}) } - runPython(code: String, isJSON = false): String | Object { - // @ts-ignore - let result = window.pydoide.runPython(code); + runPython(code: string, isJSON = false): string | Object { + let result = window.pyodide.runPython(code); if (isJSON) { result = JSON.parse(result) } return result } - loadBoard(path: String) { + loadBoard(path: string) { return this.readFile(path) .then((fileContent) => { let syntactical_errors = this.pythonObject.validateBoardStructure(fileContent); @@ -125,7 +739,7 @@ class Configurator { }) } - loadScenario(path: String): Object { + loadScenario(path: string): Object { return this.readFile(path).then((fileContent) => { let syntactical_errors = this.pythonObject.validateScenarioStructure(fileContent); if (syntactical_errors !== "") { @@ -174,11 +788,12 @@ class Configurator { convertScenarioToXML(scenarioData: Object) { let json2xml = new JSON2XML(); - let xml_data = json2xml.convert(scenarioData); - return xml_data + return json2xml.convert(scenarioData) } } let configurator = new Configurator() + +window.configurator = configurator export default configurator diff --git a/misc/config_tools/configurator/packages/configurator/src/pages/Config.vue b/misc/config_tools/configurator/packages/configurator/src/pages/Config.vue index 84cf1522f..875f310a9 100644 --- a/misc/config_tools/configurator/packages/configurator/src/pages/Config.vue +++ b/misc/config_tools/configurator/packages/configurator/src/pages/Config.vue @@ -192,6 +192,7 @@ export default { this.showFlag = false; this.updateCurrentFormSchema() this.updateCurrentFormData() + configurator.cat.scenarioLoaded() }, getSchemaData() { return this.schemas @@ -438,6 +439,8 @@ export default { let totalMsg = msg.length // msg and errMsg must be same length. let needSaveLaunchScript = false + this.scenario.hv.CACHE_REGION = configurator.cat.getScenarioDataFromCAT() + let scenarioWithDefaults = this.applyScenarioDefaults(this.scenario) let scenarioXMLData = this.scenarioToXML(scenarioWithDefaults) this.scenario = scenarioWithDefaults diff --git a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue index 55637955f..78b029b68 100644 --- a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue +++ b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue @@ -56,7 +56,11 @@ -
+ +
+ {{ CAT_INFO.errorMsg }} +
+

L3 Cache Allocation Technology
@@ -67,7 +71,7 @@

L{{ CACHE_ALLOCATION.level }} Cache Allocation Technology {{ - cat_level_region_sum[CACHE_ALLOCATION.level].count > 1 ? ' Module ' + cat_level_region_sum[CACHE_ALLOCATION.level][CACHE_ALLOCATION.id] : '' + CAT_INFO.summary[CACHE_ALLOCATION.level].count > 1 ? ' Module ' + CAT_INFO.summary[CACHE_ALLOCATION.level.toString()][CACHE_ALLOCATION.id] : '' }} (requires CPU affinity to cores {{ Math.min(...CACHE_ALLOCATION.processors) @@ -80,14 +84,24 @@
-
-
Real-time
-
Standard
-
Virtual CAT
- +
+ +
+
+
Real-time
+ {{ POLICY.VM }} vCPU {{ POLICY.VCPU }}{{ POLICY.TYPE === 'Unified' ? '' : "_" + POLICY.TYPE }} - +
+
+
Standard
+ + {{ POLICY.VM }} vCPU {{ POLICY.VCPU }}{{ POLICY.TYPE === 'Unified' ? '' : "_" + POLICY.TYPE }} + +
+
+
Virtual CAT
+ {{ POLICY.VM }}
@@ -103,14 +117,30 @@
-
+
-
+ v-if="index===0">
+
+
+
+ +
+
+
+
@@ -130,6 +160,7 @@ import _ from "lodash"; import {vueUtils, fieldProps} from "@lljj/vue3-form-naive"; import HexBlockRangeSelector from "./CAT/HexBlockRangeSelector.vue"; import IconInfo from '@lljj/vjsf-utils/icons/IconInfo.vue'; +import configurator from "../../../../lib/acrn"; function count(source, target) { return (source.match(new RegExp(target, 'g')) || []).length; @@ -185,29 +216,9 @@ export default { } }, }, - watch: { - CAT_INFO: { - handler(newValue, _) { - if (newValue === null) { - // set formData CACHE_REGION to null - vueUtils.setPathVal(this.rootFormData, this.curNodePath, newValue) - return; - } - let data = []; - for (let i = 0; i < newValue.length; i++) { - data.push(newValue[i].data) - } - // set formData CACHE_REGION.CACHE_ALLOCATION to data - let CACHE_REGION = {CACHE_ALLOCATION: data} - vueUtils.setPathVal(this.rootFormData, this.curNodePath, CACHE_REGION) - }, - deep: true - }, - }, data() { return { - CAT_INFO: null, - cat_level_region_sum: {}, + CAT_INFO: {errorMsg: null, regions: [], summary: {}}, SSRAMInfo: this.rootSchema.definitions['SSRAMInfo'], RDTType: this.rootSchema.definitions['RDTType'] } @@ -302,414 +313,28 @@ export default { return vueUtils.getPathVal(this.rootFormData, path) }, setDefaultClosMask(CACHE_REGION) { - if (CACHE_REGION.capacity_mask_length < (CACHE_REGION.real_time_count + 1)) { + if (CACHE_REGION.data.RTCore.length === 0) { + return; + } + if (CACHE_REGION.capacity_mask_length < (CACHE_REGION.data.RTCore.length + 1)) { alert('Can\'t generate default settings for this region(due to too many realtime cpu)') return; } - for (let policyIndex = 0; policyIndex < CACHE_REGION.data.POLICY.length; policyIndex++) { - if (policyIndex < CACHE_REGION.real_time_count) { - // noinspection JSUnresolvedVariable - CACHE_REGION.data.POLICY[policyIndex].CLOS_MASK = '0x' + parseInt( - '0'.repeat(policyIndex) + '1' + '0'.repeat(CACHE_REGION.capacity_mask_length - policyIndex - 1), - 2).toString(16) - } else { - // noinspection JSUnresolvedVariable - CACHE_REGION.data.POLICY[policyIndex].CLOS_MASK = '0x' + parseInt( - '0'.repeat(CACHE_REGION.real_time_count) + '1'.repeat(CACHE_REGION.capacity_mask_length - CACHE_REGION.real_time_count), - 2).toString(16) - } + for (let policyIndex = 0; policyIndex < CACHE_REGION.data.RTCore.length; policyIndex++) { + CACHE_REGION.data.RTCore[policyIndex].CLOS_MASK = '0x' + parseInt( + '0'.repeat(policyIndex) + '1' + '0'.repeat(CACHE_REGION.capacity_mask_length - policyIndex - 1), + 2).toString(16) + } + + for (let policyIndex = 0; policyIndex < CACHE_REGION.data.Standard.length; policyIndex++) { + // noinspection JSUnresolvedVariable + CACHE_REGION.data.Standard[policyIndex].CLOS_MASK = '0x' + parseInt( + '0'.repeat(CACHE_REGION.data.RTCore.length) + '1'.repeat(CACHE_REGION.capacity_mask_length - CACHE_REGION.data.RTCore.length), + 2).toString(16); } }, updateCatInfo() { - // get settings from formData - let RDT_ENABLED = this.RDT_ENABLED === 'y' - let CDP_ENABLED = this.CDP_ENABLED === 'y' - let VCAT_ENABLED = this.VCAT_ENABLED === 'y' - - if (!RDT_ENABLED) { - // keep CAT_INFO - return - } - - // get vmConfig from formData - // let getCPUAffinity = () => { - // // vmName: {pcpu_id:0, vcpu_id:0, isRT:false} - // let vmCpuAffinity = {}; - // window.getCurrentScenarioData().vm.map((vmConfig) => { - // // if this vm is service vm, skip it - // if (vmConfig.load_order === 'SERVICE_VM') { - // return; - // } - // - // }) - // } - - - let getCurrentFormDataCPUAffinitySettings = () => { - /** - * let vCatsExample = [ - * // VCPU is force set to 0 - * // CLOS_MASK is force set to width of capacity_mask_length (for vcat only) - * {"VM": "VM_C", "VCPU": 0, "CLOS_MASK": 2}, - * {"VM": "VM_D", "VCPU": 0, "CLOS_MASK": 5}, - * ] - */ - let vCats = [] - /** - * get pcpu config from current formData - * let pcpu_vms_example = { - * 0: { - * 'y': [], - * 'n': [ - * {"VM": "POST_VM_1", "VCPU": 0}, - * {"VM": "POST_VM_2", "VCPU": 2} - * ] - * }, - * 1: { - * 'y': [ - * {"VM": "POST_VM_1", "VCPU": 1} - * ], - * 'n': [ - * {"VM": "POST_VM_2", "VCPU": 2} - * ] - * } - * } - */ - let pcpu_vms = {} - let serviceVM = null; - let preLaunchedVMCPUIDs = []; - - window.getCurrentScenarioData().vm.map((vmConfig) => { - // if this vm is service vm, we got it and skip it - if (vmConfig.load_order === 'SERVICE_VM') { - serviceVM = vmConfig; - return; - } - - // no cpu affinity, skip it - if ( - !vmConfig.hasOwnProperty('cpu_affinity') || - !vmConfig.cpu_affinity.hasOwnProperty('pcpu') || - !_.isArray(vmConfig.cpu_affinity.pcpu) - ) { - return - } - - // now, we got pre/post vm config with cpu affinity data here - - if (vmConfig.load_order === 'PRE_LAUNCHED_VM') { - preLaunchedVMCPUIDs = preLaunchedVMCPUIDs.concat(vmConfig.cpu_affinity.pcpu) - return; - } - - // if vcat is enabled in hv, we need to check current vm is enabled vcat - // noinspection JSUnresolvedVariable - if ( - VCAT_ENABLED && - vmConfig.hasOwnProperty('virtual_cat_support') && - vmConfig.virtual_cat_support === "y" - ) { - // if enabled vcat in vmConfig, add vm's vcat config to vCats - // noinspection JSUnresolvedVariable - vCats.push({"VM": vmConfig.name, "VCPU": 0, "CLOS_MASK": vmConfig.virtual_cat_number}) - // for enabled virtual_cat_support vm, it doesn't need set CAT - return; - } - - // get cpu affinity settings from pre/post vms which are not enabled vCAT - vmConfig.cpu_affinity.pcpu.map((pcpu, index) => { - if (!pcpu_vms.hasOwnProperty(pcpu.pcpu_id)) { - pcpu_vms[pcpu.pcpu_id] = {'y': [], 'n': []} - } - pcpu_vms[pcpu.pcpu_id][ - // old scenario may not have this attr - pcpu.real_time_vcpu ? - // if it had this attr, use it - pcpu.real_time_vcpu : - // doesn't have it, auto set to no - 'n' - ].push({ - // '@id': vmConfig['@id'], - "VM": vmConfig.name, - "VCPU": index, - }) - }) - }) - // generate service vm cpu affinity setting - if (serviceVM !== null) { - let serviceVMCPUIndex = 0; - let schemaData = window.getSchemaData() - // noinspection JSUnresolvedVariable - schemaData.HV.BasicConfigType.definitions.CPUAffinityConfiguration.properties.pcpu_id.enum.map((pcpu_id) => { - // if pcpu_id in preLaunchedVMCPUIDs, it's used by pre launched vm, we need skip it - if (preLaunchedVMCPUIDs.indexOf(pcpu_id) !== -1) { - return; - } - // noinspection JSCheckFunctionSignatures - if (!pcpu_vms.hasOwnProperty(pcpu_id)) { - pcpu_vms[pcpu_id] = {'y': [], 'n': []} - } - pcpu_vms[pcpu_id].n.push({ - // '@id': serviceVM['@id'], - "VM": serviceVM.name, - "VCPU": serviceVMCPUIndex - }) - serviceVMCPUIndex++; - }) - } - return { - vCats: vCats, - pcpu_vms: pcpu_vms, - serviceVM: serviceVM - } - } - - let getScenarioCATData = () => { - /** - * load data from scenario - * let scenarioHVCACHE_REGIONData_data_example = { - * "CACHE_ALLOCATION": [ - * { - * "CACHE_ID": "0x8", "CACHE_LEVEL": 2, "POLICY": [ - * {"VM": "POST_RT_VM1", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"}, - * {"VM": "POST_RT_VM1", "VCPU": 1, "TYPE": "Unified", "CLOS_MASK": "0x0fff"}, - * {"VM": "VM4-RTVM2", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"}, - * {"VM": "VM4-RTVM2", "VCPU": 1, "TYPE": "Unified", "CLOS_MASK": "0x0fff"} - * ] - * }, - * { - * "CACHE_ID": "0x9", "CACHE_LEVEL": 2, "POLICY": [ - * {"VM": "VM5-RTVM3", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"}, - * {"VM": "VM5-RTVM3", "VCPU": 1, "TYPE": "Unified", "CLOS_MASK": "0x0fff"}, - * {"VM": "VM6-RTVM4", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"}, - * {"VM": "VM6-RTVM4", "VCPU": 1, "TYPE": "Unified", "CLOS_MASK": "0x0fff"} - * ] - * } - * ] - * } - */ - let scenarioHVCACHE_REGIONData = vueUtils.getPathVal(this.rootFormData, this.curNodePath); - - /** - * let scenario_cat_data_example = { - * 2: { - * '0x7': { - * "CACHE_ID": "0x7", "CACHE_LEVEL": 2, "POLICY": [ - * {"VM": "POST_RT_VM1", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"} - * ] - * }, - * '0x8': { - * "CACHE_ID": "0x8", "CACHE_LEVEL": 2, "POLICY": [ - * {"VM": "POST_RT_VM1", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"} - * ] - * } - * }, - * 3: { - * '0x0': {} - * } - * } - */ - let scenario_cat_data = {} - // noinspection JSUnresolvedVariable - if ( - scenarioHVCACHE_REGIONData !== null && - scenarioHVCACHE_REGIONData.hasOwnProperty('CACHE_ALLOCATION') && - _.isArray(scenarioHVCACHE_REGIONData.CACHE_ALLOCATION) - ) { - // noinspection JSUnresolvedVariable - scenarioHVCACHE_REGIONData.CACHE_ALLOCATION.map((cache_region) => { - if (!scenario_cat_data.hasOwnProperty(cache_region['CACHE_LEVEL'])) { - scenario_cat_data[cache_region['CACHE_LEVEL']] = {} - } - scenario_cat_data[cache_region['CACHE_LEVEL']][cache_region['CACHE_ID']] = cache_region - }) - } - return scenario_cat_data - } - - - let mergeAndGenerateData = (currentFormDataCPUAffinitySettings, scenarioCatData) => { - - /** - * get CAT info from board xml - * let board_cat_info_example = [ - * { - * "id": "0x0", "level": 3, "type": "3", "cache_size": 31457280, "capacity_mask_length": 12, - * "processors": [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15] - * } - * ] - */ - - /** - * let cat_level_region_sum_example = { - * 2: { - * count: 2, - * '0x8': 1, - * '0x9': 2 - * }, - * 3: { - * count: 1, - * '0x0': 1 - * } - * } - */ - - let scenario_cat_data = scenarioCatData - let {pcpu_vms, vCats} = currentFormDataCPUAffinitySettings; - - this.cat_level_region_sum = {} - - let board_cat_info = _.cloneDeep(window.getBoardData().CAT_INFO); - - board_cat_info.map(( - cat_region_info - ) => { - - // count regions for each cat level - if (!this.cat_level_region_sum.hasOwnProperty(cat_region_info.level)) { - this.cat_level_region_sum[cat_region_info.level] = {count: 0}; - } - this.cat_level_region_sum[cat_region_info.level].count += 1 - this.cat_level_region_sum[cat_region_info.level][cat_region_info.id] = this.cat_level_region_sum[cat_region_info.level].count; - - /** - * get vm cpu clos_mask from scenario - * let vmCPUClosMasks_example = { - * 'VM_NAME': { - * // vcpu_id: {type: clos_mask} - * 0: {"Unified": '0xfff'}, - * 1: {"Code": '0xff0', "Data": '0x00f'} // CDP_ENABLED - * } - * } - */ - let vmCPUClosMasks = {} - if ( - scenario_cat_data.hasOwnProperty(cat_region_info.level) && - scenario_cat_data[cat_region_info.level].hasOwnProperty(cat_region_info.id) - ) { - /** - * let current_region_scenario_cat_data_example = { - * "CACHE_ID": "0x7", "CACHE_LEVEL": 2, "POLICY": [ - * {"VM": "POST_RT_VM1", "VCPU": 0, "TYPE": "Unified", "CLOS_MASK": "0x0fff"} - * ] - * } - */ - let current_region_scenario_cat_data = scenario_cat_data[cat_region_info.level][cat_region_info.id]; - - for (let i = 0; i < current_region_scenario_cat_data.POLICY.length; i++) { - let currentRegionScenarioPolicy = current_region_scenario_cat_data.POLICY[i] - if (!vmCPUClosMasks.hasOwnProperty(currentRegionScenarioPolicy.VM)) { - vmCPUClosMasks[currentRegionScenarioPolicy.VM] = {} - } - if (!vmCPUClosMasks[currentRegionScenarioPolicy.VM].hasOwnProperty(currentRegionScenarioPolicy.VCPU)) { - vmCPUClosMasks[currentRegionScenarioPolicy.VM][currentRegionScenarioPolicy.VCPU] = {} - } - if (["Unified", "Code", "Data"].indexOf(currentRegionScenarioPolicy.TYPE) >= 0) { - vmCPUClosMasks[currentRegionScenarioPolicy.VM][currentRegionScenarioPolicy.VCPU][currentRegionScenarioPolicy.TYPE] = currentRegionScenarioPolicy.CLOS_MASK - } - } - } - - cat_region_info['data'] = { - "CACHE_ID": cat_region_info.id, - "CACHE_LEVEL": cat_region_info.level, - "POLICY": [] - } - - function addCATPolicy(cpu_policy_line, line_type, vcat_mask_length = null) { - let cpu_policy = _.cloneDeep(cpu_policy_line) - cpu_policy['TYPE'] = line_type; - // noinspection JSUnresolvedVariable - let clos_mask = "0x" + parseInt('1'.repeat( - // if vcat_mask_length is not null - vcat_mask_length !== null ? - // filled by vcat_mask_length - vcat_mask_length : - // filled by capacity_mask_length - cat_region_info.capacity_mask_length - ), 2).toString(16); - if ( - vmCPUClosMasks.hasOwnProperty(cpu_policy.VM) && - vmCPUClosMasks[cpu_policy.VM].hasOwnProperty(cpu_policy.VCPU) && - vmCPUClosMasks[cpu_policy.VM][cpu_policy.VCPU].hasOwnProperty(line_type) - ) { - let scenario_clos_mask = vmCPUClosMasks[cpu_policy.VM][cpu_policy.VCPU][line_type]; - if (vcat_mask_length === null || count(Number.parseInt(scenario_clos_mask).toString(2), '1') === vcat_mask_length) { - clos_mask = scenario_clos_mask - } - } - cpu_policy['CLOS_MASK'] = clos_mask; - cat_region_info.data.POLICY.push(cpu_policy) - } - - /** - * let cpu_policies_example = [ - * {"VM": "POST_VM_1", "VCPU": 0}, - * {"VM": "POST_VM_2", "VCPU": 2} - * ] - */ - function addPolicy(cpu_policies) { - for (let j = 0; j < cpu_policies.length; j++) { - let cpu_policies_line = cpu_policies[j]; - if (CDP_ENABLED) { - addCATPolicy(cpu_policies_line, "Code") - addCATPolicy(cpu_policies_line, "Data") - } else { - addCATPolicy(cpu_policies_line, "Unified") - } - } - return CDP_ENABLED ? 2 * cpu_policies.length : cpu_policies.length - } - - // add rt vm policy - cat_region_info.real_time_count = 0 - // noinspection JSUnresolvedVariable - for (let i = 0; i < cat_region_info.processors.length; i++) { - // noinspection JSUnresolvedVariable - let pcpu_id = cat_region_info.processors[i]; - let cpu_policies = pcpu_vms[pcpu_id] ? pcpu_vms[pcpu_id]['y'] : []; - cat_region_info.real_time_count += addPolicy(cpu_policies) - } - // add std vm policy - cat_region_info.cat_count = _.cloneDeep(cat_region_info.real_time_count) - // noinspection JSUnresolvedVariable - for (let i = 0; i < cat_region_info.processors.length; i++) { - // noinspection JSUnresolvedVariable - let pcpu_id = cat_region_info.processors[i]; - let cpu_policies = pcpu_vms[pcpu_id] ? pcpu_vms[pcpu_id]['n'] : []; - cat_region_info.cat_count += addPolicy(cpu_policies) - } - - // add vcat vm policy - // noinspection JSUnresolvedVariable - if (cat_region_info.processors.indexOf(0) !== -1) { - for (let i = 0; i < vCats.length; i++) { - addCATPolicy(vCats[i], 'Unified', vCats[i].CLOS_MASK) - } - } - - // order policy by @id - // cat_region_info.data.POLICY.sort(function (a, b) { - // return a['@id'] - b['@id'] - // }); - }) - - for (let i = 0; i < board_cat_info.length; i++) { - if (board_cat_info[i].data.POLICY.length === 0) { - board_cat_info.splice(i--, 1) - } - } - return board_cat_info; - } - - let generate = () => { - let currentFormDataCPUAffinitySettings = getCurrentFormDataCPUAffinitySettings(); - let scenarioCatData = getScenarioCATData(); - this.CAT_INFO = mergeAndGenerateData(currentFormDataCPUAffinitySettings, scenarioCatData); - } - - - generate() + this.CAT_INFO = configurator.cat.getCATUIData() } } } diff --git a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT/HexBlockRangeSelector.vue b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT/HexBlockRangeSelector.vue index e6c39c8d4..ee68ae891 100644 --- a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT/HexBlockRangeSelector.vue +++ b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT/HexBlockRangeSelector.vue @@ -6,20 +6,14 @@