2 # -*- coding: utf-8 -*-
6 from datetime import datetime
8 from glob import glob, iglob
9 from pathlib import Path
11 from lxml.etree import XMLSyntaxError
12 from zipfile import ZipFile
14 from matrix_runner import main, matrix_axis, matrix_action, matrix_command, matrix_filter, \
15 ConsoleReport, CropReport, TransformReport, JUnitReport
18 @matrix_axis("device", "d", "Device(s) to be considered.")
19 class DeviceAxis(Enum):
20 CM0 = ('Cortex-M0', 'CM0')
21 CM0plus = ('Cortex-M0plus', 'CM0plus')
22 CM3 = ('Cortex-M3', 'CM3')
23 CM4 = ('Cortex-M4', 'CM4')
24 CM4FP = ('Cortex-M4FP', 'CM4FP')
25 CM7 = ('Cortex-M7', 'CM7')
26 CM7SP = ('Cortex-M7SP', 'CM7SP')
27 CM7DP = ('Cortex-M7DP', 'CM7DP')
28 CM23 = ('Cortex-M23', 'CM23')
29 CM23S = ('Cortex-M23S', 'CM23S')
30 CM23NS = ('Cortex-M23NS', 'CM23NS')
31 CM33 = ('Cortex-M33', 'CM33')
32 CM33S = ('Cortex-M33S', 'CM33S')
33 CM33NS = ('Cortex-M33NS', 'CM33NS')
34 CM35P = ('Cortex-M35P', 'CM35P')
35 CM35PS = ('Cortex-M35PS', 'CM35PS')
36 CM35PNS = ('Cortex-M35PNS', 'CM35PNS')
37 CM55S = ('Cortex-M55S', 'CM55S')
38 CM55NS = ('Cortex-M55NS', 'CM55NS')
39 CM85S = ('Cortex-M85S', 'CM85S')
40 CM85NS = ('Cortex-M85NS', 'CM85NS')
41 CA5 = ('Cortex-A5', 'CA5')
42 CA7 = ('Cortex-A7', 'CA7')
43 CA9 = ('Cortex-A9', 'CA9')
44 # CA5NEON = ('Cortex-A5neon', 'CA5neon')
45 # CA7NEON = ('Cortex-A7neon', 'CA7neon')
46 # CA9NEON = ('Cortex-A9neon', 'CA9neon')
60 DeviceAxis.CM23NS: 'CM23S',
61 DeviceAxis.CM33NS: 'CM33S',
62 DeviceAxis.CM35PNS: 'CM35PS',
63 DeviceAxis.CM55NS: 'CM55S',
64 DeviceAxis.CM85NS: 'CM85S'
69 @matrix_axis("compiler", "c", "Compiler(s) to be considered.")
70 class CompilerAxis(Enum):
78 CompilerAxis.AC6: 'axf',
79 CompilerAxis.AC6LTM: 'axf',
80 CompilerAxis.GCC: 'elf'
85 @matrix_axis("optimize", "o", "Optimization level(s) to be considered.")
86 class OptimizationAxis(Enum):
89 HIGH = ('high', 'Ofast')
95 DeviceAxis.CM0: ("VHT_MPS2_Cortex-M0", []),
96 DeviceAxis.CM0plus: ("VHT_MPS2_Cortex-M0plus", []),
97 DeviceAxis.CM3: ("VHT_MPS2_Cortex-M3", []),
98 DeviceAxis.CM4: ("VHT_MPS2_Cortex-M4", []),
99 DeviceAxis.CM4FP: ("VHT_MPS2_Cortex-M4", []),
100 DeviceAxis.CM7: ("VHT_MPS2_Cortex-M7", []),
101 DeviceAxis.CM7DP: ("VHT_MPS2_Cortex-M7", []),
102 DeviceAxis.CM7SP: ("VHT_MPS2_Cortex-M7", []),
103 DeviceAxis.CM23: ("VHT_MPS2_Cortex-M23", []),
104 DeviceAxis.CM23S: ("VHT_MPS2_Cortex-M23", []),
105 DeviceAxis.CM23NS: ("VHT_MPS2_Cortex-M23", []),
106 DeviceAxis.CM33: ("VHT_MPS2_Cortex-M33", []),
107 DeviceAxis.CM33S: ("VHT_MPS2_Cortex-M33", []),
108 DeviceAxis.CM33NS: ("VHT_MPS2_Cortex-M33", []),
109 DeviceAxis.CM35P: ("VHT_MPS2_Cortex-M35P", []),
110 DeviceAxis.CM35PS: ("VHT_MPS2_Cortex-M35P", []),
111 DeviceAxis.CM35PNS: ("VHT_MPS2_Cortex-M35P", []),
112 DeviceAxis.CM55S: ("VHT_MPS2_Cortex-M55", []),
113 DeviceAxis.CM55NS: ("VHT_MPS2_Cortex-M55", []),
114 DeviceAxis.CM85S: ("VHT_MPS2_Cortex-M85", []),
115 DeviceAxis.CM85NS: ("VHT_MPS2_Cortex-M85", []),
116 DeviceAxis.CA5: ("FVP_VE_Cortex-A5x1", []),
117 DeviceAxis.CA7: ("FVP_VE_Cortex-A7x1", []),
118 DeviceAxis.CA9: ("FVP_VE_Cortex-A9x1", []),
119 # DeviceAxis.CA5NEON: ("FVP_VE_Cortex-A5x1", []),
120 # DeviceAxis.CA7NEON: ("FVP_VE_Cortex-A7x1", []),
121 # DeviceAxis.CA9NEON: ("FVP_VE_Cortex-A9x1", [])
124 def config_suffix(config, timestamp=True):
125 suffix = f"{config.compiler[0]}-{config.optimize[0]}-{config.device[1]}"
127 suffix += f"-{datetime.now().strftime('%Y%m%d%H%M%S')}"
131 def project_name(config):
132 return f"Validation.{config.compiler}_{config.optimize}+{config.device[1]}"
135 def bl_project_name(config):
136 return f"Bootloader.{config.compiler}_{config.optimize}+{config.device.bl_device}"
139 def output_dir(config):
140 return f"{project_name(config)}_outdir"
143 def bl_output_dir(config):
144 return f"{bl_project_name(config)}_outdir"
147 def model_config(config):
148 return f"../Layer/Target/{config.device[1]}/model_config.txt"
153 """Build the selected configurations using CMSIS-Build."""
154 yield cbuild_clean(f"{project_name(config)}/{project_name(config)}.cprj")
158 def build(config, results):
159 """Build the selected configurations using CMSIS-Build."""
161 if config.device.has_bl():
162 logging.info("Compiling Bootloader...")
163 yield csolution(f"{bl_project_name(config)}")
164 yield cbuild(f"{bl_project_name(config)}/{bl_project_name(config)}.cprj")
166 logging.info("Compiling Tests...")
168 if config.compiler == CompilerAxis.GCC and config.device.match("CA*"):
169 ldfile = Path(f"{project_name(config)}/RTE/Device/ARM{config.device[1]}/ARM{config.device[1]}.ld")
170 infile = ldfile.replace(ldfile.with_suffix('.ld.in'))
171 yield preprocess(infile, ldfile)
173 yield csolution(f"{project_name(config)}")
174 yield cbuild(f"{project_name(config)}/{project_name(config)}.cprj")
176 if not all(r.success for r in results):
179 file = f"Core_Validation-{config_suffix(config)}.zip"
180 logging.info(f"Archiving build output to {file}...")
181 with ZipFile(file, "w") as archive:
182 for content in iglob(f"{project_name(config)}/**/*", recursive=True):
183 if Path(content).is_file():
184 archive.write(content)
189 """Extract the latest build archive."""
190 archives = sorted(glob(f"RTOS2_Validation-{config_suffix(config, timestamp=False)}-*.zip"), reverse=True)
191 yield unzip(archives[0])
195 def run(config, results):
196 """Run the selected configurations."""
197 logging.info("Running Core Validation on Arm model ...")
198 yield model_exec(config)
201 results[0].test_report.write(f"Core_Validation-{config_suffix(config)}.junit")
202 except RuntimeError as e:
203 if isinstance(e.__cause__, XMLSyntaxError):
204 logging.error("No valid test report found in model output!")
210 def cbuild_clean(project):
211 return ["cbuild", "-c", project]
216 return ["bash", "-c", f"unzip {archive}"]
220 def preprocess(infile, outfile):
221 return ["arm-none-eabi-gcc", "-xc", "-E", infile, "-P", "-o", outfile]
224 def csolution(project):
225 return ["csolution", "convert", "-s", "Validation.csolution.yml", "-c", project]
229 return ["cbuild", project]
232 @matrix_command(test_report=ConsoleReport() |
233 CropReport('<\?xml version="1.0"\?>', '</report>') |
234 TransformReport('validation.xsl') |
235 JUnitReport(title=lambda title, result: f"{result.command.config.compiler}."
236 f"{result.command.config.optimize}."
237 f"{result.command.config.device}."
239 def model_exec(config):
240 cmdline = [MODEL_EXECUTABLE[config.device][0], "-q", "--simlimit", 100, "-f", model_config(config)]
241 cmdline += MODEL_EXECUTABLE[config.device][1]
242 cmdline += ["-a", f"{project_name(config)}/{output_dir(config)}/{project_name(config)}.{config.compiler.image_ext}"]
243 if config.device.has_bl():
244 cmdline += ["-a", f"{bl_project_name(config)}/{bl_output_dir(config)}/{bl_project_name(config)}.{config.compiler.image_ext}"]
248 if __name__ == "__main__":