diff --git a/.github/workflows/create-perf-json.yml b/.github/workflows/create-perf-json.yml index 62aad97e..bed1926e 100644 --- a/.github/workflows/create-perf-json.yml +++ b/.github/workflows/create-perf-json.yml @@ -29,7 +29,7 @@ jobs: - name: Run unittests working-directory: ./scripts/unittesting - run: python metric_test.py + run: python -m unittest metric_test.py test_create_perf_json.py - name: Create perf json files working-directory: ./scripts diff --git a/scripts/create_perf_json.py b/scripts/create_perf_json.py index ec966414..043e1222 100644 --- a/scripts/create_perf_json.py +++ b/scripts/create_perf_json.py @@ -653,8 +653,15 @@ def smi_json(self) -> metric.MetricGroup: ]) @staticmethod - def extract_pebs_formula(formula): - MIN_MAX_PEBS = re.compile(r"([A-Za-z0-9\_\.@]+)\*(min|max)\(\s*(\$PEBS)\s*,((\s*([^\s\)])\s*)+)\)") + def extract_pebs_formula(formula: str) -> str: + """ + Convert metric formulas using $PEBS. + + Example: + Input: MEM_INST_RETIRED.STLB_HIT_LOADS*min($PEBS, 7) / tma_info_thread_clks + tma_load_stlb_miss + Return: MEM_INST_RETIRED.STLB_HIT_LOADS * min(MEM_INST_RETIRED.STLB_HIT_LOADS:R, 7) / tma_info_thread_clks + tma_load_stlb_miss + """ + MIN_MAX_PEBS = re.compile(r"([A-Za-z0-9_.@]+)\*(min|max)\( *(\$PEBS) *,([a-z0-9_ */+-]+)\)") NON_REL_OPS = r"(?]=?|==" STR_OPS = r"'[A-Z\-]+'" @@ -666,11 +673,10 @@ def extract_pebs_formula(formula): for m in re.finditer(MIN_MAX_PEBS, formula): main_event = m.group(1).strip() min_max = m.group(2) - pebs = m.group(3) alternative = m.group(4).strip() mod = 'R' if '@' in main_event else ':R' - new_string = f' {main_event} * {min_max}({main_event}{mod}, {alternative}) ' + new_string = f'{main_event} * {min_max}({main_event}{mod}, {alternative})' new_formula = re.sub(m.re, new_string, new_formula, count=1) formula_list = re.split(OPS, new_formula) @@ -681,6 +687,7 @@ def extract_pebs_formula(formula): mod = 'R' if '@' in event_name else ':R' new_element = f'( {event_name} * {event_name}{mod} )' new_formula = new_formula.replace(element, new_element) + return new_formula def extract_tma_metrics(self, csvfile: TextIO, pmu_prefix: str, diff --git a/scripts/unittesting/test_create_perf_json.py b/scripts/unittesting/test_create_perf_json.py new file mode 100644 index 00000000..5beec049 --- /dev/null +++ b/scripts/unittesting/test_create_perf_json.py @@ -0,0 +1,57 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause + +import unittest +import sys +from pathlib import Path + +# Add create_perf_json.py directory to the path before importing. +_script_dir = Path(__file__).resolve().parent +sys.path.append(str(_script_dir.parent)) + +from create_perf_json import Model + + +class TestModel(unittest.TestCase): + + def test_extract_pebs_formula(self): + """Test formulas which use $PEBS but do not include min() or max().""" + tests = [ + ( + 'EVENT.A*$PEBS', + '( EVENT.A * EVENT.A:R )', + ), + ( + 'EVENT.A + cpu_core@EVENT.B@*$PEBS', + 'EVENT.A + ( cpu_core@EVENT.B@ * cpu_core@EVENT.B@R )', + ), + ] + + for input, expected_result in tests: + with self.subTest(input=input, expected_result=expected_result): + self.assertEqual(expected_result, Model.extract_pebs_formula(input)) + + def test_extract_pebs_formula_with_min_max(self): + """Test formulas which use $PEBS and also min() or max().""" + tests = [ + ( + 'EVENT.A*min( $PEBS, 4) / EVENT.B', + 'EVENT.A * min(EVENT.A:R, 4) / EVENT.B', + ), + ( + 'EVENT.A*min($PEBS, 2) / (1 + EVENT.B*max($PEBS, 8))', + 'EVENT.A * min(EVENT.A:R, 2) / (1 + EVENT.B * max(EVENT.B:R, 8))', + ), + ( + 'EVENT.A*min($PEBS, 9 * test_info) * (1 + (cpu_core@EVENT.B@ / cpu_core@EVENT.C@) / 2) / test_info_2', + 'EVENT.A * min(EVENT.A:R, 9 * test_info) * (1 + (cpu_core@EVENT.B@ / cpu_core@EVENT.C@) / 2) / test_info_2', + ), + ( + '(cpu_core@EVENT.A@*min($PEBS, 24 * test_info) + cpu_core@EVENT.B@*min($PEBS, 24 - test_info) * (1 - (cpu_core@EVENT.C@ / (cpu_core@EVENT.D@ + cpu_core@EVENT.E@)))) * 5', + '(cpu_core@EVENT.A@ * min(cpu_core@EVENT.A@R, 24 * test_info) + cpu_core@EVENT.B@ * min(cpu_core@EVENT.B@R, 24 - test_info) * (1 - (cpu_core@EVENT.C@ / (cpu_core@EVENT.D@ + cpu_core@EVENT.E@)))) * 5', + ) + ] + + for input, expected_result in tests: + with self.subTest(input=input, expected_result=expected_result): + self.assertEqual(expected_result, Model.extract_pebs_formula(input))