Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | #memory_footprint.py : Script for sending memory footprint data from the TFM CI |
| 4 | #to a SQUAD web interface |
| 5 | # |
Xinyu Zhang | 9a29f03 | 2022-01-19 15:13:24 +0800 | [diff] [blame] | 6 | #Copyright (c) 2020-2022, Arm Limited. All rights reserved. |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 7 | # |
| 8 | #SPDX-License-Identifier: BSD-3-Clause |
| 9 | |
| 10 | |
| 11 | import argparse |
| 12 | import os |
| 13 | import re |
| 14 | import sys |
| 15 | import json |
| 16 | import requests |
| 17 | import subprocess |
| 18 | import configs |
| 19 | from tfm_ci_pylib import utils |
| 20 | |
| 21 | # Arguments/parameters given by CI |
| 22 | PATH_TO_TFM = sys.argv[1] |
| 23 | CI_CONFIG = sys.argv[2] |
| 24 | REFERENCE_CONFIGS = sys.argv[3].split(",") |
| 25 | SQUAD_TOKEN = sys.argv[4] |
| 26 | |
| 27 | # local constant |
| 28 | SQUAD_BASE_PROJECT_URL = ("https://qa-reports.linaro.org/api/submit/tf/tf-m/") |
| 29 | |
| 30 | # This function uses arm_non_eabi_size to get the sizes of a file |
| 31 | # in the build directory of tfm |
| 32 | def get_file_size(filename): |
| 33 | f_path = os.path.join(PATH_TO_TFM, "build", "bin", filename) |
| 34 | if os.path.exists(f_path) : |
Hugo L'Hostis | 26dc296 | 2021-04-22 15:44:48 +0100 | [diff] [blame] | 35 | file_sizes = utils.arm_non_eabi_size(f_path)[0] |
| 36 | return file_sizes |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 37 | else : |
| 38 | print(f_path + "Not found") |
| 39 | return -1 |
| 40 | |
| 41 | # This function creates a json file containing all the data about |
| 42 | # memory footprint and sends this data to SQUAD |
| 43 | def send_file_size(change_id, config_name, bl2_sizes, tfms_sizes): |
| 44 | url = SQUAD_BASE_PROJECT_URL + change_id + '/' + config_name |
| 45 | |
| 46 | try: |
| 47 | metrics = json.dumps({ "bl2_size" : bl2_sizes["dec"], |
| 48 | "bl2_data" : bl2_sizes["data"], |
| 49 | "bl2_bss" : bl2_sizes["bss"], |
Hugo L'Hostis | 26dc296 | 2021-04-22 15:44:48 +0100 | [diff] [blame] | 50 | "bl2_text" : bl2_sizes["text"], |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 51 | "tfms_size" : tfms_sizes["dec"], |
| 52 | "tfms_data" : tfms_sizes["data"], |
Hugo L'Hostis | 26dc296 | 2021-04-22 15:44:48 +0100 | [diff] [blame] | 53 | "tfms_bss" : tfms_sizes["bss"], |
| 54 | "tfms_text" : tfms_sizes["text"]}) |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 55 | except: |
| 56 | return -1 |
| 57 | |
| 58 | headers = {"Auth-Token": SQUAD_TOKEN} |
| 59 | data= {"metrics": metrics} |
| 60 | |
| 61 | try: |
| 62 | #Sending the data to SQUAD, 40s timeout |
| 63 | result = requests.post(url, headers=headers, data=data, timeout=40) |
| 64 | except: |
| 65 | return -1 |
| 66 | |
| 67 | with open(os.path.join(PATH_TO_TFM, |
| 68 | "..", |
| 69 | "tf-m-ci-scripts", |
| 70 | "Memory_footprint", |
| 71 | "filesize.json"), "w") as F: |
| 72 | #Storing the json file |
| 73 | F.write(metrics) |
| 74 | |
| 75 | if not result.ok: |
| 76 | print(f"Error submitting to qa-reports: {result.reason}: {result.text}") |
| 77 | return -1 |
| 78 | else : |
| 79 | print ("POST request sent to project " + config_name ) |
| 80 | return 0 |
| 81 | |
| 82 | #Function used to launch the configs.py script and get the printed output |
| 83 | def get_configs_by_name(config_names): |
| 84 | clist = list(configs._builtin_configs.keys()) |
| 85 | out_cfg = {} |
| 86 | for group in clist: |
| 87 | build_manager = configs.get_build_manager(group) |
| 88 | for _cfg_name in config_names: |
| 89 | if _cfg_name in build_manager._tbm_build_cfg.keys(): |
| 90 | out_cfg[_cfg_name] = build_manager._tbm_build_cfg[_cfg_name] |
| 91 | return out_cfg |
| 92 | |
| 93 | # This funcion manipulates the format of the config given |
| 94 | # as entry to extract the name of the configuration used |
| 95 | def identify_config(): |
| 96 | name_config = "Unknown" |
| 97 | |
| 98 | try : |
| 99 | cfg = get_configs_by_name([CI_CONFIG])[CI_CONFIG] |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 100 | if (not cfg.lib_model and cfg.isolation_level == "1" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 101 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 102 | cfg.cmake_build_type == "Release" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 103 | cfg.with_bl2 and cfg.with_ns and |
| 104 | cfg.profile == "" and cfg.partition_ps == "ON"): |
| 105 | name_config = "CoreIPC" |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 106 | elif (cfg.lib_model and cfg.isolation_level == "1" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 107 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 108 | cfg.cmake_build_type == "Release" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 109 | cfg.with_bl2 and cfg.with_ns and |
| 110 | cfg.profile == "" and cfg.partition_ps == "ON"): |
| 111 | name_config = "Default" |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 112 | elif (not cfg.lib_model and cfg.isolation_level == "2" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 113 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 114 | cfg.cmake_build_type == "Release" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 115 | cfg.with_bl2 and cfg.with_ns and |
| 116 | cfg.profile == "" and cfg.partition_ps == "ON"): |
| 117 | name_config = "CoreIPCTfmLevel2" |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 118 | elif (cfg.lib_model and cfg.isolation_level == "1" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 119 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 120 | cfg.cmake_build_type == "Release" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 121 | cfg.with_bl2 and cfg.with_ns and |
| 122 | cfg.profile == "profile_small" and cfg.partition_ps == "OFF"): |
| 123 | name_config = "DefaultProfileS" |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 124 | elif (cfg.lib_model and cfg.isolation_level == "1" and |
Hugo L'Hostis | c99cd2b | 2021-04-12 11:48:49 +0100 | [diff] [blame] | 125 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 126 | cfg.cmake_build_type == "Minsizerel" and |
Hugo L'Hostis | c99cd2b | 2021-04-12 11:48:49 +0100 | [diff] [blame] | 127 | cfg.with_bl2 and cfg.with_ns and |
| 128 | cfg.profile == "profile_small" and cfg.partition_ps == "OFF"): |
| 129 | name_config = "MinSizeProfileS" |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 130 | elif (not cfg.lib_model and cfg.isolation_level == "2" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 131 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 132 | cfg.cmake_build_type == "Release" and |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 133 | cfg.with_bl2 and cfg.with_ns and |
| 134 | cfg.profile == "profile_medium" and cfg.partition_ps == "ON"): |
| 135 | name_config = "DefaultProfileM" |
Xinyu Zhang | 73ed299 | 2021-09-15 11:38:23 +0800 | [diff] [blame] | 136 | elif (not cfg.lib_model and cfg.isolation_level == "3" and |
Hugo L'Hostis | 26dc296 | 2021-04-22 15:44:48 +0100 | [diff] [blame] | 137 | not cfg.test_regression and cfg.test_psa_api == "OFF" and |
Xinyu Zhang | 589fd05 | 2022-04-19 17:54:16 +0800 | [diff] [blame] | 138 | cfg.cmake_build_type == "Release" and |
Hugo L'Hostis | 26dc296 | 2021-04-22 15:44:48 +0100 | [diff] [blame] | 139 | cfg.with_bl2 and cfg.with_ns and |
| 140 | cfg.profile == "profile_large" and cfg.partition_ps == "ON"): |
| 141 | name_config = "DefaultProfileL" |
Xinyu Zhang | 433771e | 2022-04-01 16:49:17 +0800 | [diff] [blame] | 142 | ret = [cfg.tfm_platform,cfg.compiler, name_config] |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 143 | except: |
| 144 | ret = ["Unknown", "Unknown", "Unknown"] |
| 145 | return ret |
| 146 | |
| 147 | # Function based on get_local_git_info() from utils, getting change id for the tfm repo |
| 148 | def get_change_id(directory): |
| 149 | directory = os.path.abspath(directory) |
| 150 | cur_dir = os.path.abspath(os.getcwd()) |
| 151 | cmd = "git log HEAD -n 1 --pretty=format:'%b'" |
| 152 | |
| 153 | os.chdir(directory) # Going to the repo's directory |
| 154 | |
| 155 | git_info_rex = re.compile(r'(?P<body>^[\s\S]*?)((?:Change-Id:\s)' |
| 156 | r'(?P<change_id>.*)\n?)', re.MULTILINE) |
| 157 | |
| 158 | r, e = subprocess.Popen(cmd, |
| 159 | shell=True, |
| 160 | stdout=subprocess.PIPE, |
| 161 | stderr=subprocess.PIPE).communicate() |
| 162 | |
| 163 | if e: |
| 164 | print("Error", e) |
| 165 | return -1 |
| 166 | else: |
| 167 | try: |
| 168 | txt_body = r.decode('ascii') |
| 169 | except UnicodeDecodeError as E: |
| 170 | txt_body = r.decode('utf-8') |
| 171 | result = txt_body.rstrip() |
| 172 | |
| 173 | try: |
| 174 | change_id = git_info_rex.search(result).groupdict()["change_id"].strip() |
| 175 | except: |
| 176 | return -1 |
| 177 | |
| 178 | os.chdir(cur_dir) #Going back to the initial directory |
| 179 | return change_id |
| 180 | |
| 181 | if __name__ == "__main__": |
Xinyu Zhang | 9a29f03 | 2022-01-19 15:13:24 +0800 | [diff] [blame] | 182 | # Export GCC v7.3.1 to ENV PATH |
| 183 | os.environ["PATH"] += os.pathsep + os.getenv('GCC_7_3_1_PATH') |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 184 | for i in range(len(REFERENCE_CONFIGS)): |
| 185 | REFERENCE_CONFIGS[i] = REFERENCE_CONFIGS[i].strip().lower() |
| 186 | config = identify_config() |
| 187 | if (config[2].lower() in REFERENCE_CONFIGS |
Summer Qin | 3c2b572 | 2021-05-26 10:43:45 +0800 | [diff] [blame] | 188 | and config[0] == "arm/mps2/an521" |
Arthur She | d6fd4a0 | 2022-06-20 18:55:44 +0800 | [diff] [blame] | 189 | and config[1] == "GCC_7_3_1"): |
Hugo L'Hostis | e55a275 | 2021-01-27 11:09:08 +0000 | [diff] [blame] | 190 | # Pushing data for AN521 and GNUARM |
| 191 | print("Configuration " + config[2] + " is a reference") |
| 192 | try : |
| 193 | change_id = get_change_id(PATH_TO_TFM) |
| 194 | except : |
| 195 | change_id = -1 |
| 196 | bl2_sizes = get_file_size("bl2.axf") |
| 197 | tfms_sizes = get_file_size("tfm_s.axf") |
| 198 | if (bl2_sizes != -1 and change_id != -1) : |
| 199 | send_file_size(change_id, config[2], bl2_sizes, tfms_sizes) |
| 200 | else : |
| 201 | #Directory or file weren't found |
| 202 | if change_id == -1 : |
| 203 | print("Error : trusted-firmware-m repo not found") |
| 204 | else : |
| 205 | print("Error : file not found") |