blob: 46fce74fe49f9561b1d2465093176b80fda1eccc [file] [log] [blame]
Hugo L'Hostise55a2752021-01-27 11:09:08 +00001#!/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 Zhang9a29f032022-01-19 15:13:24 +08006#Copyright (c) 2020-2022, Arm Limited. All rights reserved.
Hugo L'Hostise55a2752021-01-27 11:09:08 +00007#
8#SPDX-License-Identifier: BSD-3-Clause
9
10
11import argparse
12import os
13import re
14import sys
15import json
16import requests
17import subprocess
18import configs
19from tfm_ci_pylib import utils
20
21# Arguments/parameters given by CI
22PATH_TO_TFM = sys.argv[1]
23CI_CONFIG = sys.argv[2]
24REFERENCE_CONFIGS = sys.argv[3].split(",")
25SQUAD_TOKEN = sys.argv[4]
26
27# local constant
28SQUAD_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
32def 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'Hostis26dc2962021-04-22 15:44:48 +010035 file_sizes = utils.arm_non_eabi_size(f_path)[0]
36 return file_sizes
Hugo L'Hostise55a2752021-01-27 11:09:08 +000037 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
43def 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'Hostis26dc2962021-04-22 15:44:48 +010050 "bl2_text" : bl2_sizes["text"],
Hugo L'Hostise55a2752021-01-27 11:09:08 +000051 "tfms_size" : tfms_sizes["dec"],
52 "tfms_data" : tfms_sizes["data"],
Hugo L'Hostis26dc2962021-04-22 15:44:48 +010053 "tfms_bss" : tfms_sizes["bss"],
54 "tfms_text" : tfms_sizes["text"]})
Hugo L'Hostise55a2752021-01-27 11:09:08 +000055 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
83def 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
95def identify_config():
96 name_config = "Unknown"
97
98 try :
99 cfg = get_configs_by_name([CI_CONFIG])[CI_CONFIG]
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800100 if (not cfg.lib_model and cfg.isolation_level == "1" and
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000101 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800102 cfg.cmake_build_type == "Release" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800103 cfg.with_bl2 and cfg.with_ns and cfg.profile == ""):
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000104 name_config = "CoreIPC"
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800105 elif (cfg.lib_model and cfg.isolation_level == "1" and
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000106 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800107 cfg.cmake_build_type == "Release" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800108 cfg.with_bl2 and cfg.with_ns and cfg.profile == ""):
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000109 name_config = "Default"
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800110 elif (not cfg.lib_model and cfg.isolation_level == "2" and
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000111 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800112 cfg.cmake_build_type == "Release" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800113 cfg.with_bl2 and cfg.with_ns and cfg.profile == ""):
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000114 name_config = "CoreIPCTfmLevel2"
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800115 elif (cfg.lib_model and cfg.isolation_level == "1" and
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000116 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800117 cfg.cmake_build_type == "Release" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800118 cfg.with_bl2 and cfg.with_ns and cfg.profile == "profile_small"):
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000119 name_config = "DefaultProfileS"
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800120 elif (cfg.lib_model and cfg.isolation_level == "1" and
Hugo L'Hostisc99cd2b2021-04-12 11:48:49 +0100121 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800122 cfg.cmake_build_type == "Minsizerel" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800123 cfg.with_bl2 and cfg.with_ns and cfg.profile == "profile_small"):
Hugo L'Hostisc99cd2b2021-04-12 11:48:49 +0100124 name_config = "MinSizeProfileS"
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800125 elif (not cfg.lib_model and cfg.isolation_level == "2" and
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000126 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800127 cfg.cmake_build_type == "Release" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800128 cfg.with_bl2 and cfg.with_ns and cfg.profile == "profile_medium"):
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000129 name_config = "DefaultProfileM"
Xinyu Zhang73ed2992021-09-15 11:38:23 +0800130 elif (not cfg.lib_model and cfg.isolation_level == "3" and
Hugo L'Hostis26dc2962021-04-22 15:44:48 +0100131 not cfg.test_regression and cfg.test_psa_api == "OFF" and
Xinyu Zhang589fd052022-04-19 17:54:16 +0800132 cfg.cmake_build_type == "Release" and
Xinyu Zhangdf88e302022-09-19 11:27:57 +0800133 cfg.with_bl2 and cfg.with_ns and cfg.profile == "profile_large"):
Hugo L'Hostis26dc2962021-04-22 15:44:48 +0100134 name_config = "DefaultProfileL"
Xinyu Zhang433771e2022-04-01 16:49:17 +0800135 ret = [cfg.tfm_platform,cfg.compiler, name_config]
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000136 except:
137 ret = ["Unknown", "Unknown", "Unknown"]
138 return ret
139
140# Function based on get_local_git_info() from utils, getting change id for the tfm repo
141def get_change_id(directory):
142 directory = os.path.abspath(directory)
143 cur_dir = os.path.abspath(os.getcwd())
144 cmd = "git log HEAD -n 1 --pretty=format:'%b'"
145
146 os.chdir(directory) # Going to the repo's directory
147
148 git_info_rex = re.compile(r'(?P<body>^[\s\S]*?)((?:Change-Id:\s)'
149 r'(?P<change_id>.*)\n?)', re.MULTILINE)
150
151 r, e = subprocess.Popen(cmd,
152 shell=True,
153 stdout=subprocess.PIPE,
154 stderr=subprocess.PIPE).communicate()
155
156 if e:
157 print("Error", e)
158 return -1
159 else:
160 try:
161 txt_body = r.decode('ascii')
162 except UnicodeDecodeError as E:
163 txt_body = r.decode('utf-8')
164 result = txt_body.rstrip()
165
166 try:
167 change_id = git_info_rex.search(result).groupdict()["change_id"].strip()
168 except:
169 return -1
170
171 os.chdir(cur_dir) #Going back to the initial directory
172 return change_id
173
174if __name__ == "__main__":
Xinyu Zhang16a218e2022-10-11 17:21:39 +0800175 # Export GCC v10.3 to ENV PATH
176 os.environ["PATH"] += os.pathsep + os.getenv('GCC_10_3_PATH')
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000177 for i in range(len(REFERENCE_CONFIGS)):
178 REFERENCE_CONFIGS[i] = REFERENCE_CONFIGS[i].strip().lower()
179 config = identify_config()
180 if (config[2].lower() in REFERENCE_CONFIGS
Summer Qin3c2b5722021-05-26 10:43:45 +0800181 and config[0] == "arm/mps2/an521"
Xinyu Zhang16a218e2022-10-11 17:21:39 +0800182 and config[1] == "GCC_10_3"):
Hugo L'Hostise55a2752021-01-27 11:09:08 +0000183 # Pushing data for AN521 and GNUARM
184 print("Configuration " + config[2] + " is a reference")
185 try :
186 change_id = get_change_id(PATH_TO_TFM)
187 except :
188 change_id = -1
189 bl2_sizes = get_file_size("bl2.axf")
190 tfms_sizes = get_file_size("tfm_s.axf")
191 if (bl2_sizes != -1 and change_id != -1) :
192 send_file_size(change_id, config[2], bl2_sizes, tfms_sizes)
193 else :
194 #Directory or file weren't found
195 if change_id == -1 :
196 print("Error : trusted-firmware-m repo not found")
197 else :
198 print("Error : file not found")