diff --git a/misc/config_tools/library/rdt.py b/misc/config_tools/library/rdt.py
new file mode 100644
index 000000000..34a561ff1
--- /dev/null
+++ b/misc/config_tools/library/rdt.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys, os
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
+import common
+import re
+from collections import defaultdict
+from collections import namedtuple
+
+policy_owner = namedtuple("policy_owner", ["vm_name", "vcpu", "cache_type"])
+
+class Policy:
+ def __init__(self, cache_id, clos_mask):
+ self.cache_id = cache_id
+ self.clos_mask = clos_mask
+
+ def get_cache_id(self):
+ return self.cache_id
+
+ def get_clos_mask(self):
+ return self.clos_mask
+
+ def match_policy(self, src):
+ return (self.clos_mask == None) or (src.clos_mask == None) or (self.clos_mask == src.clos_mask)
+
+class L3Policy(Policy):
+ def __init__(self, policy):
+ self.cache_id = policy.get_cache_id()
+ self.clos_mask = policy.get_clos_mask()
+
+ def merge_policy(self, src):
+ return self.match_policy(src)
+
+class L2Policy:
+ cache2_id_list = []
+
+ def __init__(self, policy):
+ self.policy_list = []
+ for index,cache2_id in enumerate(self.cache2_id_list):
+ if cache2_id == policy.cache_id:
+ self.policy_list.append(policy)
+ else:
+ self.policy_list.append(Policy(None, None))
+
+ def get_cache_id(self, index):
+ return self.policy_list[index].get_cache_id()
+
+ def get_clos_mask(self, index):
+ return self.policy_list[index].get_clos_mask()
+
+ def match_policy(self, src):
+ for index in range(0, len(self.policy_list)):
+ if not self.policy_list[index].match_policy(src.policy_list[index]):
+ return False
+ return True
+
+ def merge_policy(self, src):
+ if self.match_policy(src):
+ for index in range(0, len(self.policy_list)):
+ if self.policy_list[index].clos_mask is None:
+ self.policy_list[index].clos_mask = src.policy_list[index].clos_mask
+ return True
+ return False
+
+class RdtPolicy:
+ def __init__(self, policy_list, policy_owner):
+ cache2_id = None
+ cache3_id = None
+ l2_mask = None
+ l3_mask = None
+ for policy in policy_list:
+ cache_level = common.get_node("../CACHE_LEVEL/text()", policy)
+ cache_id = common.get_node("../CACHE_ID/text()", policy)
+ clos_mask = common.get_node("./CLOS_MASK/text()", policy)
+ if cache_level == "2":
+ l2_mask = clos_mask
+ cache2_id = cache_id
+ else:
+ l3_mask = clos_mask
+ cache3_id = cache_id
+ self.l2policy = L2Policy(Policy(cache2_id, l2_mask))
+ self.l3policy = L3Policy(Policy(cache3_id, l3_mask))
+
+ # a list stored the vCPU or VM info
+ self.policy_owner_list = [policy_owner]
+
+ def match_policy(self, src):
+ return self.l2policy.match_policy(src.l2policy) and self.l3policy.match_policy(src.l3policy)
+
+ #check whether the src could be merged, if yes, add the src owner to policy_owner_list list and return True
+ def merge_policy(self, src):
+ if self.match_policy(src):
+ self.l2policy.merge_policy(src.l2policy)
+ self.l3policy.merge_policy(src.l3policy)
+ self.policy_owner_list += src.policy_owner_list
+ return True
+ return False
+
+ #check whether a VM/vCPU could use this policy
+ def find_policy_owner(self, policy_owner):
+ return policy_owner in self.policy_owner_list
+
+class vCatPolicy(RdtPolicy):
+ def merge_policy(self, src):
+ return False
+
+class CdpPolicy():
+ def __init__(self,data_list, code_list, owner):
+ self.data_policy = RdtPolicy(data_list, policy_owner(owner.vm_name, owner.vcpu, "Data"))
+ self.code_policy = RdtPolicy(code_list, policy_owner(owner.vm_name, owner.vcpu, "Code"))
+
+ def merge_policy(self, src):
+ if self.code_policy.match_policy(src.code_policy) and self.data_policy.match_policy(src.data_policy):
+ self.code_policy.merge_policy(src.code_policy)
+ self.data_policy.merge_policy(src.data_policy)
+ return True
+ return False
+
+def merge_policy_list(policy_list):
+ result_list = []
+ for index,p in enumerate(policy_list):
+ merged = False
+ for result in result_list:
+ if result.merge_policy(p):
+ merged = True
+ break;
+ if not merged:
+ result_list.append(p)
+ return result_list
+
+def gen_policy_owner_list(scenario_etree):
+ policy_owner_list = []
+ vm_list = scenario_etree.xpath("//POLICY/VM")
+ for vm in vm_list:
+ vm_name = common.get_node("./text()", vm)
+ vcpu = common.get_node("../VCPU/text()", vm)
+ cache_type = common.get_node("../TYPE/text()", vm)
+ policy_owner_list.append(policy_owner(vm_name, vcpu, cache_type))
+ return policy_owner_list
+
+def vm_vcat_enable(scenario_etree, vm_name):
+ vcat_enable = common.get_node(f"//VCAT_ENABLED/text()", scenario_etree)
+ virtual_cat_support = common.get_node(f"//vm[name = '{vm_name}']/virtual_cat_support/text()", scenario_etree)
+ return (vcat_enable == "y") and (virtual_cat_support == "y")
+
+def cdp_enable(scenario_etree):
+ cdp_enable = common.get_node(f"//CDP_ENABLED/text()", scenario_etree)
+ return cdp_enable == "y"
+
+def convert_cdp_to_normal(cdp_policy_list):
+ policy_list = []
+ for cdp_policy in cdp_policy_list:
+ policy_list.append(cdp_policy.data_policy)
+ policy_list.append(cdp_policy.code_policy)
+ return policy_list
+
+def get_policy_list(scenario_etree):
+ init_cache2_id_list(scenario_etree)
+ policy_owner_list = gen_policy_owner_list(scenario_etree)
+
+ result_list = []
+ for policy_owner in policy_owner_list:
+ dict_tmp = {}
+ policy_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}']")
+ if cdp_enable(scenario_etree):
+ data_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}' and TYPE = 'Data']")
+ code_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}' and TYPE = 'Code']")
+ if policy_owner.cache_type == "Code":
+ continue
+ elif policy_owner.cache_type == "Data":
+ result_list.append(CdpPolicy(data_list, code_list, policy_owner))
+ elif vm_vcat_enable(scenario_etree, policy_owner.vm_name):
+ result_list.append(vCatPolicy(policy_list, policy_owner))
+ else:
+ result_list.append(RdtPolicy(policy_list, policy_owner))
+ result_list = merge_policy_list(result_list)
+
+ if cdp_enable(scenario_etree):
+ result_list = convert_cdp_to_normal(result_list)
+
+ return result_list
+
+def init_cache2_id_list(scenario_etree):
+ cache2_id_list = scenario_etree.xpath("//CACHE_ALLOCATION[CACHE_LEVEL = 2]/CACHE_ID/text()")
+ cache2_id_list.sort()
+ L2Policy.cache2_id_list = cache2_id_list
diff --git a/misc/config_tools/scenario_config/elementpath_overlay.py b/misc/config_tools/scenario_config/elementpath_overlay.py
index 5178db3bd..c95015ee9 100644
--- a/misc/config_tools/scenario_config/elementpath_overlay.py
+++ b/misc/config_tools/scenario_config/elementpath_overlay.py
@@ -9,6 +9,7 @@
from decimal import Decimal
from copy import copy
import operator
+import rdt
import elementpath
BaseParser = elementpath.XPath2Parser
@@ -20,6 +21,8 @@ class CustomParser(BaseParser):
'has',
'duplicate-values',
+
+ 'number-of-clos-id-needed',
}
method = CustomParser.method
@@ -84,6 +87,14 @@ def select_duplicate_values_function(self, context=None):
yield from duplicate_values()
+@method(function('number-of-clos-id-needed', nargs=1))
+def evaluate_number_of_clos_id_needed(self, context=None):
+ op = self.get_argument(context, index=0)
+ try:
+ return len(rdt.get_policy_list(op.elem)) if op else 0
+ except AttributeError as err:
+ raise self.error('XPTY0004', err)
+
###
# Collection of counter examples
diff --git a/misc/config_tools/schema/checks/rdt_support.xsd b/misc/config_tools/schema/checks/rdt_support.xsd
index 38c045471..74b0b64ed 100644
--- a/misc/config_tools/schema/checks/rdt_support.xsd
+++ b/misc/config_tools/schema/checks/rdt_support.xsd
@@ -89,4 +89,12 @@ This error cannot be fixed by adjusting the configuration. Report a `GitHub issu
+
+
+ The current CAT configuration requires {string($needed)} CLOS IDs, which exceeds the capacity of the platform which supports {string($capacity)} at most.
+
+
+
diff --git a/misc/config_tools/schema/datachecks.xsd b/misc/config_tools/schema/datachecks.xsd
index ff32e973c..3f6b2ebca 100644
--- a/misc/config_tools/schema/datachecks.xsd
+++ b/misc/config_tools/schema/datachecks.xsd
@@ -17,6 +17,7 @@
+
diff --git a/misc/config_tools/static_allocators/clos.py b/misc/config_tools/static_allocators/clos.py
index f2add7d35..a9c4c348c 100644
--- a/misc/config_tools/static_allocators/clos.py
+++ b/misc/config_tools/static_allocators/clos.py
@@ -8,121 +8,12 @@
import sys, os
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
import common
+import rdt
import re
from collections import defaultdict
from itertools import combinations
from collections import namedtuple
-
-policy_owner = namedtuple("policy_owner", ["vm_name", "vcpu", "cache_type"])
-
-class Policy:
- def __init__(self, cache_id, clos_mask):
- self.cache_id = cache_id
- self.clos_mask = clos_mask
-
- def get_cache_id(self):
- return self.cache_id
-
- def get_clos_mask(self):
- return self.clos_mask
-
- def match_policy(self, src):
- return (self.clos_mask == None) or (src.clos_mask == None) or (self.clos_mask == src.clos_mask)
-
-class L3Policy(Policy):
- def __init__(self, policy):
- self.cache_id = policy.get_cache_id()
- self.clos_mask = policy.get_clos_mask()
-
- def merge_policy(self, src):
- return self.match_policy(src)
-
-class L2Policy:
- cache2_id_list = []
-
- def __init__(self, policy):
- self.policy_list = []
- for index,cache2_id in enumerate(self.cache2_id_list):
- if cache2_id == policy.cache_id:
- self.policy_list.append(policy)
- else:
- self.policy_list.append(Policy(None, None))
-
- def get_cache_id(self, index):
- return self.policy_list[index].get_cache_id()
-
- def get_clos_mask(self, index):
- return self.policy_list[index].get_clos_mask()
-
- def match_policy(self, src):
- for index in range(0, len(self.policy_list)):
- if not self.policy_list[index].match_policy(src.policy_list[index]):
- return False
- return True
-
- def merge_policy(self, src):
- if self.match_policy(src):
- for index in range(0, len(self.policy_list)):
- if self.policy_list[index].clos_mask is None:
- self.policy_list[index].clos_mask = src.policy_list[index].clos_mask
- return True
- return False
-
-class RdtPolicy:
- def __init__(self, policy_list, policy_owner):
- cache2_id = None
- cache3_id = None
- l2_mask = None
- l3_mask = None
- for policy in policy_list:
- cache_level = common.get_node("../CACHE_LEVEL/text()", policy)
- cache_id = common.get_node("../CACHE_ID/text()", policy)
- clos_mask = common.get_node("./CLOS_MASK/text()", policy)
- if cache_level == "2":
- l2_mask = clos_mask
- cache2_id = cache_id
- else:
- l3_mask = clos_mask
- cache3_id = cache_id
- self.l2policy = L2Policy(Policy(cache2_id, l2_mask))
- self.l3policy = L3Policy(Policy(cache3_id, l3_mask))
-
- # a list stored the vCPU or VM info
- self.policy_owner_list = [policy_owner]
-
- def match_policy(self, src):
- return self.l2policy.match_policy(src.l2policy) and self.l3policy.match_policy(src.l3policy)
-
- #check whether the src could be merged, if yes, add the src owner to policy_owner_list list and return True
- def merge_policy(self, src):
- if self.match_policy(src):
- self.l2policy.merge_policy(src.l2policy)
- self.l3policy.merge_policy(src.l3policy)
- self.policy_owner_list += src.policy_owner_list
- return True
- return False
-
- #check whether a VM/vCPU could use this policy
- def find_policy_owner(self, policy_owner):
- return policy_owner in self.policy_owner_list
-
-class vCatPolicy(RdtPolicy):
- def merge_policy(self, src):
- return False
-
-class CdpPolicy():
- def __init__(self,data_list, code_list, owner):
- self.data_policy = RdtPolicy(data_list, policy_owner(owner.vm_name, owner.vcpu, "Data"))
- self.code_policy = RdtPolicy(code_list, policy_owner(owner.vm_name, owner.vcpu, "Code"))
-
- def merge_policy(self, src):
- if self.code_policy.match_policy(src.code_policy) and self.data_policy.match_policy(src.data_policy):
- self.code_policy.merge_policy(src.code_policy)
- self.data_policy.merge_policy(src.data_policy)
- return True
- return False
-
def create_clos_node(scenario_etree, vm_id, index_list):
allocation_vm_node = common.get_node(f"/acrn-config/vm[@id = '{vm_id}']", scenario_etree)
if allocation_vm_node is None:
@@ -132,69 +23,6 @@ def create_clos_node(scenario_etree, vm_id, index_list):
for index in index_list:
common.append_node(f"./vcpu_clos", str(index), clos_node)
-def merge_policy_list(policy_list):
- result_list = []
- for index,p in enumerate(policy_list):
- merged = False
- for result in result_list:
- if result.merge_policy(p):
- merged = True
- break;
- if not merged:
- result_list.append(p)
- return result_list
-
-def gen_policy_owner_list(scenario_etree):
- policy_owner_list = []
- vm_list = scenario_etree.xpath("//POLICY/VM")
- for vm in vm_list:
- vm_name = common.get_node("./text()", vm)
- vcpu = common.get_node("../VCPU/text()", vm)
- cache_type = common.get_node("../TYPE/text()", vm)
- policy_owner_list.append(policy_owner(vm_name, vcpu, cache_type))
- return policy_owner_list
-
-def vm_vcat_enable(scenario_etree, vm_name):
- vcat_enable = common.get_node(f"//VCAT_ENABLED/text()", scenario_etree)
- virtual_cat_support = common.get_node(f"//vm[name = '{vm_name}']/virtual_cat_support/text()", scenario_etree)
- return (vcat_enable == "y") and (virtual_cat_support == "y")
-
-def cdp_enable(scenario_etree):
- cdp_enable = common.get_node(f"//CDP_ENABLED/text()", scenario_etree)
- return cdp_enable == "y"
-
-def convert_cdp_to_normal(cdp_policy_list):
- policy_list = []
- for cdp_policy in cdp_policy_list:
- policy_list.append(cdp_policy.data_policy)
- policy_list.append(cdp_policy.code_policy)
- return policy_list
-
-def get_policy_list(board_etree, scenario_etree, allocation_etree):
- policy_owner_list = gen_policy_owner_list(scenario_etree)
-
- result_list = []
- for policy_owner in policy_owner_list:
- dict_tmp = {}
- policy_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}']")
- if cdp_enable(scenario_etree):
- data_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}' and TYPE = 'Data']")
- code_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}' and TYPE = 'Code']")
- if policy_owner.cache_type == "Code":
- continue
- elif policy_owner.cache_type == "Data":
- result_list.append(CdpPolicy(data_list, code_list, policy_owner))
- elif vm_vcat_enable(scenario_etree, policy_owner.vm_name):
- result_list.append(vCatPolicy(policy_list, policy_owner))
- else:
- result_list.append(RdtPolicy(policy_list, policy_owner))
- result_list = merge_policy_list(result_list)
-
- if cdp_enable(scenario_etree):
- result_list = convert_cdp_to_normal(result_list)
-
- return result_list
-
def get_clos_id(rdt_list, policy_owner):
for index,rdt in enumerate(rdt_list):
if rdt.find_policy_owner(policy_owner):
@@ -208,10 +36,10 @@ def alloc_clos_index(board_etree, scenario_etree, allocation_etree, mask_list):
vcpu_list = scenario_etree.xpath(f"//POLICY[VM = '{vm_name}']/VCPU/text()")
index_list = []
for vcpu in sorted(list(set(vcpu_list))):
- if cdp_enable(scenario_etree):
- index = get_clos_id(mask_list, policy_owner(vm_name, vcpu, "Data")) // 2
+ if rdt.cdp_enable(scenario_etree):
+ index = get_clos_id(mask_list, rdt.policy_owner(vm_name, vcpu, "Data")) // 2
else:
- index = get_clos_id(mask_list, policy_owner(vm_name, vcpu, "Unified"))
+ index = get_clos_id(mask_list, rdt.policy_owner(vm_name, vcpu, "Unified"))
index_list.append(index)
create_clos_node(allocation_etree, common.get_node("./@id", vm_node), index_list)
@@ -233,7 +61,7 @@ def create_mask_list_node(board_etree, scenario_etree, allocation_etree, rdt_pol
else:
value = default_l3_value
common.append_node(f"./clos", value, clos_mask)
- for index,cache2 in enumerate(L2Policy.cache2_id_list):
+ for index,cache2 in enumerate(rdt.L2Policy.cache2_id_list):
length = common.get_node(f"//cache[@level='2' and @id = '{cache2}']/capability/capacity_mask_length/text()", board_etree)
if length is not None:
default_l2_value = hex((1 << int(length)) - 1)
@@ -249,13 +77,7 @@ def create_mask_list_node(board_etree, scenario_etree, allocation_etree, rdt_pol
value = default_l2_value
common.append_node(f"./clos", value, clos_mask)
-def init_cache2_id_list(scenario_etree):
- cache2_id_list = scenario_etree.xpath("//CACHE_ALLOCATION[CACHE_LEVEL = 2]/CACHE_ID/text()")
- cache2_id_list.sort()
- L2Policy.cache2_id_list = cache2_id_list
-
def fn(board_etree, scenario_etree, allocation_etree):
- init_cache2_id_list(scenario_etree)
- policy_list = get_policy_list(board_etree, scenario_etree, allocation_etree)
+ policy_list = rdt.get_policy_list(scenario_etree)
create_mask_list_node(board_etree, scenario_etree, allocation_etree, policy_list)
alloc_clos_index(board_etree, scenario_etree, allocation_etree, policy_list)