config_tools: refine cat widget

refine cat widget

Tracked-On: #6691
Signed-off-by: Weiyi Feng <weiyix.feng@intel.com>
This commit is contained in:
Weiyi Feng 2022-06-21 13:20:27 +08:00 committed by acrnsi-robot
parent 9f7c4b6bab
commit 342e8c05f6
4 changed files with 704 additions and 492 deletions

View File

@ -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<String[] | []> {
getHistory(historyType: HistoryTypes): Promise<String[] | []> {
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<String> {
readFile(filePath: string): Promise<String> {
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<Boolean> {
isFile(filePath: string): Promise<Boolean> {
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

View File

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

View File

@ -56,7 +56,11 @@
</b-form-checkbox>
</div>
</div>
<div class="py-4" v-for="CACHE_ALLOCATION in CAT_INFO" v-if="RDT_ENABLED==='y'">
<!-- begin CAT Table -->
<div class="py-3" v-if="CAT_INFO.errorMsg">
{{ CAT_INFO.errorMsg }}
</div>
<div class="py-4" v-for="CACHE_ALLOCATION in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
<p v-if="CACHE_ALLOCATION.level===3">
L3 Cache Allocation Technology
<br/>
@ -67,7 +71,7 @@
<div class="d-flex justify-content-between py-2 align-items-center">
<text>
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 @@
<div class="d-flex">
<div class="leftTitle">
<!--left title-->
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.POLICY">
<div v-if="index===0&&CACHE_ALLOCATION.real_time_count>0">Real-time</div>
<div v-if="index===CACHE_ALLOCATION.real_time_count&&CACHE_ALLOCATION.cat_count>0">Standard</div>
<div v-if="index===CACHE_ALLOCATION.cat_count">Virtual CAT</div>
<text v-if="index<CACHE_ALLOCATION.cat_count">
<div style="min-height: 36px">
<!-- for align right -->
</div>
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.RTCore">
<div v-if="index===0">Real-time</div>
<text>
{{ POLICY.VM }} vCPU {{ POLICY.VCPU }}{{ POLICY.TYPE === 'Unified' ? '' : "_" + POLICY.TYPE }}
</text>
<text v-else>
</div>
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.Standard">
<div v-if="index===0">Standard</div>
<text>
{{ POLICY.VM }} vCPU {{ POLICY.VCPU }}{{ POLICY.TYPE === 'Unified' ? '' : "_" + POLICY.TYPE }}
</text>
</div>
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.VCAT">
<div v-if="index===0">Virtual CAT</div>
<text>
{{ POLICY.VM }}
</text>
</div>
@ -103,14 +117,30 @@
</div>
<div>
<!--right table-->
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.POLICY">
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.RTCore">
<div class="policyDisabledBlock"
v-if="index===CACHE_ALLOCATION.real_time_count && CACHE_ALLOCATION.real_time_count>0"></div>
<div class="policyDisabledBlock"
v-if="index===CACHE_ALLOCATION.cat_count && CACHE_ALLOCATION.cat_count>0"></div>
v-if="index===0"></div>
<HexBlockRangeSelector
v-model="POLICY.CLOS_MASK"
:isVcat="index>=CACHE_ALLOCATION.cat_count"
:isVcat="false"
:max="CACHE_ALLOCATION.capacity_mask_length"
/>
</div>
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.Standard">
<div class="policyDisabledBlock"
v-if="index===0"></div>
<HexBlockRangeSelector
v-model="POLICY.CLOS_MASK"
:isVcat="false"
:max="CACHE_ALLOCATION.capacity_mask_length"
/>
</div>
<div v-for="(POLICY,index) in CACHE_ALLOCATION.data.VCAT">
<div class="policyDisabledBlock"
v-if="index===0"></div>
<HexBlockRangeSelector
v-model="POLICY.CLOS_MASK"
:isVcat="true"
:max="CACHE_ALLOCATION.capacity_mask_length"
/>
</div>
@ -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()
}
}
}

View File

@ -6,20 +6,14 @@
<script>
import Slider from '@vueform/slider'
import configurator from '../../../../../lib/acrn'
function count(source, target) {
return (source.match(new RegExp(target, 'g')) || []).length;
}
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
let getHexValue = (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;
}
export default {
name: "HexBlockRangeSelector",
@ -36,32 +30,7 @@ export default {
},
hexField: {
get() {
let str_bin = Number.parseInt(this.modelValue).toString(2);
let block_length = str_bin.length;
let block_enabled_length = count(str_bin, "1");
let start = 0
let end = 0
if (block_length > this.max) {
if (block_enabled_length >= this.max) {
str_bin = "1".repeat(this.max);
} else {
str_bin = "0".repeat(this.max - block_enabled_length) + "1".repeat(block_enabled_length);
}
} else {
if (block_length < this.max) {
str_bin = "0".repeat(this.max - block_length) + str_bin;
}
}
start = str_bin.indexOf("1") !== -1 ? str_bin.indexOf("1") : 0;
end = start + count(str_bin, "1");
// noinspection UnnecessaryLocalVariableJS
let result = [start, end]
return result
return configurator.cat.hexToRange(this.modelValue, this.max)
},
set(value) {
if (value[1] - value[0] === 0) {
@ -71,7 +40,7 @@ export default {
} else {
this.lastValue = JSON.parse(JSON.stringify(value))
}
this.$emit("update:modelValue", getHexValue(value, this.max))
this.$emit("update:modelValue", configurator.cat.rangeToHex(value, this.max))
}
}
},