]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Tests/build.py
CoreValidation: Fix Cortex-A builds.
[cmsis] / CMSIS / CoreValidation / Tests / build.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 import logging
5 import re
6
7 from datetime import datetime
8 from enum import Enum
9 from lxml.etree import XMLSyntaxError
10 from zipfile import ZipFile
11
12 from matrix_runner import main, matrix_axis, matrix_action, matrix_command, matrix_filter, ConsoleReport, CropReport, \
13     TransformReport, JUnitReport
14
15
16 @matrix_axis("device", "d", "Device(s) to be considered.")
17 class DeviceAxis(Enum):
18     CM0 = ('Cortex-M0', 'CM0')
19     CM0PLUS = ('Cortex-M0plus', 'CM0plus', 'Cortex-M0+', 'CM0+')
20     CM3 = ('Cortex-M3', 'CM3')
21     CM4 = ('Cortex-M4', 'CM4')
22     CM4FP = ('Cortex-M4FP', 'CM4FP')
23     CM7 = ('Cortex-M7', 'CM7')
24     CM7SP = ('Cortex-M7SP', 'CM7SP')
25     CM7DP = ('Cortex-M7DP', 'CM7DP')
26     CM23 = ('Cortex-M23', 'CM23')
27     CM23S = ('Cortex-M23S', 'CM23S')
28     CM23NS = ('Cortex-M23NS', 'CM23NS')
29     CM33 = ('Cortex-M33', 'CM33')
30     CM33S = ('Cortex-M33S', 'CM33S')
31     CM33NS = ('Cortex-M33NS', 'CM33NS')
32     CM35P = ('Cortex-M35P', 'CM35P')
33     CM35PS = ('Cortex-M35PS', 'CM35PS')
34     CM35PNS = ('Cortex-M35PNS', 'CM35PNS')
35     CM55 = ('Cortex-M55', 'CM55')
36     CM55S = ('Cortex-M55S', 'CM55S')
37     CM55NS = ('Cortex-M55NS', 'CM55NS')
38     CA5 = ('Cortex-A5', 'CA5')
39     CA7 = ('Cortex-A7', 'CA7')
40     CA9 = ('Cortex-A9', 'CA9')
41     CA5NEON = ('Cortex-A5neon', 'CA5neon')
42     CA7NEON = ('Cortex-A7neon', 'CA7neon')
43     CA9NEON = ('Cortex-A9neon', 'CA9neon')
44     
45     def has_bootloader(self):
46         return self in [
47             DeviceAxis.CM23NS,
48             DeviceAxis.CM33NS,
49             DeviceAxis.CM35PNS,
50             DeviceAxis.CM55NS
51         ]
52
53
54 @matrix_axis("compiler", "c", "Compiler(s) to be considered.")
55 class CompilerAxis(Enum):
56     AC5 = ('AC5', 'ArmCompiler5', 'armcc')
57     AC6 = ('AC6', 'ArmCompiler6', 'armclang')
58     AC6LTM = ('AC6LTM', 'ArmCompiler6-LTM', 'armclang-ltm')
59     GCC = ('GCC')
60     
61
62 @matrix_axis("optimize", "o", "Optimization level(s) to be considered.")
63 class OptimizationAxis(Enum):
64     LOW = ('low', 'O1', 'O0', 'O1')
65     MID = ('mid', 'O2', 'O1', 'O2' )
66     HIGH = ('high', 'Ofast', 'Otime', 'Ofast')
67     SIZE = ('size', 'Os', 'O2', 'Os')
68     TINY = ('tiny', 'Oz', 'O3', 'O3')
69
70     def for_compiler(self, compiler):
71         COMPILER = {
72             CompilerAxis.AC5: 2,
73             CompilerAxis.AC6: 1,
74             CompilerAxis.AC6LTM: 1,
75             CompilerAxis.GCC: 3
76         }        
77         return self[COMPILER[compiler]]
78
79
80 FVP_MODELS = {
81     DeviceAxis.CM0: ("FVP_MPS2_Cortex-M0", ""),
82     DeviceAxis.CM0PLUS: ("FVP_MPS2_Cortex-M0plus", ""),
83     DeviceAxis.CM3: ("FVP_MPS2_Cortex-M3", ""),
84     DeviceAxis.CM4: ("FVP_MPS2_Cortex-M4", ""),
85     DeviceAxis.CM4FP: ("FVP_MPS2_Cortex-M4", ""),
86     DeviceAxis.CM7: ("FVP_MPS2_Cortex-M7", ""),
87     DeviceAxis.CM7SP: ("FVP_MPS2_Cortex-M7", ""),
88     DeviceAxis.CM7DP: ("FVP_MPS2_Cortex-M7", ""),
89     DeviceAxis.CM23: ("FVP_MPS2_Cortex-M23", "cpu0"),
90     DeviceAxis.CM23S: ("FVP_MPS2_Cortex-M23", "cpu0"),
91     DeviceAxis.CM23NS: ("FVP_MPS2_Cortex-M23", "cpu0"),
92     DeviceAxis.CM33: ("FVP_MPS2_Cortex-M33", "cpu0"),
93     DeviceAxis.CM33S: ("FVP_MPS2_Cortex-M33", "cpu0"),
94     DeviceAxis.CM33NS: ("FVP_MPS2_Cortex-M33", "cpu0"),
95     DeviceAxis.CM35P: ("FVP_MPS2_Cortex-M35P", "cpu0"),
96     DeviceAxis.CM35PS: ("FVP_MPS2_Cortex-M35P", "cpu0"),
97     DeviceAxis.CM35PNS: ("FVP_MPS2_Cortex-M35P", "cpu0"),
98     DeviceAxis.CM55: ("FVP_MPS2_Cortex-M55", "cpu0"),
99     DeviceAxis.CM55S: ("FVP_MPS2_Cortex-M55", "cpu0"),
100     DeviceAxis.CM55NS: ("FVP_MPS2_Cortex-M55", "cpu0"),
101     DeviceAxis.CA5: ("FVP_VE_Cortex-A5x1", ""),
102     DeviceAxis.CA7: ("FVP_VE_Cortex-A7x1", ""),
103     DeviceAxis.CA9: ("FVP_VE_Cortex-A9x1", ""),
104     DeviceAxis.CA5NEON: ("FVP_VE_Cortex-A5x1", ""),
105     DeviceAxis.CA7NEON: ("FVP_VE_Cortex-A7x1", ""),
106     DeviceAxis.CA9NEON: ("FVP_VE_Cortex-A9x1", ""),
107 }
108
109
110 @matrix_action
111 def build(config, results):
112     """Build the selected configurations."""
113     if config.device.has_bootloader():
114         logging.info("Compiling Bootloader...")
115         yield rtebuild(config, f"bootloader/{config.compiler[0].lower()}.rtebuild")
116     
117     logging.info("Compiling Tests...")
118     yield rtebuild(config, f"{config.compiler[0].lower()}.rtebuild")
119     
120     if not all(r.success for r in results):
121         return
122         
123     devname = config.device[1]
124     file = f"CoreValidation_{config.compiler}_{devname}_{config.optimize[1]}.zip"
125     logging.info(f"Archiving build output to {file}...")
126     with ZipFile(file, "w") as archive:
127         archive.write(f"build/arm{devname.lower()}/arm{devname.lower()}.elf")
128         archive.write(f"build/arm{devname.lower()}/arm{devname.lower()}.map")
129         if config.device.has_bootloader():
130             archive.write(f"bootloader/build/arm{devname.lower()}/arm{devname.lower()}.elf")
131             archive.write(f"bootloader/build/arm{devname.lower()}/arm{devname.lower()}.map")
132
133
134 @matrix_action
135 def run(config, results):
136     """Run the selected configurations."""
137     logging.info("Running CoreValidation in Fast Model...")
138     yield fastmodel(config)
139     
140     try:
141         results[0].test_report.write(f"corevalidation_{datetime.now().strftime('%Y%m%d%H%M%S')}.junit")
142     except RuntimeError as e:
143         if isinstance(e.__cause__ , XMLSyntaxError):
144             logging.error("No valid test report found in model output!")
145         else:
146             logging.exception(e)
147
148 @matrix_command(needs_shell=True)
149 def rtebuild(config, spec):
150     return ["rtebuild.py", "build", 
151             "-c", spec,
152             "-l",
153             "-t", f"arm{config.device[1].lower()}", 
154             "-o", f"optimize={config.optimize.for_compiler(config.compiler)}"]
155
156
157 @matrix_command(test_report=ConsoleReport() |
158                             CropReport('<\?xml version="1.0"\?>', '</report>') |
159                             TransformReport('validation.xsl') |
160                             JUnitReport(title=lambda title, result: f"{result.command.config.compiler}."
161                                                                     f"{result.command.config.device}."
162                                                                     f"{result.command.config.optimize[1]}."
163                                                                     f"{title}"))
164 def fastmodel(config):
165     devname = config.device[1]
166     cmdline = [FVP_MODELS[config.device][0], "-q", "--cyclelimit", 1000000000, "-f", f"config/ARM{devname}_config.txt"]
167     cmdline += ["-a", f"{get_model_inst(config.device)}build/arm{devname.lower()}/arm{devname.lower()}.elf"]
168     if config.device.has_bootloader():
169         cmdline += ["-a", f"{get_model_inst(config.device)}bootloader/build/arm{devname.lower()}/arm{devname.lower()}.elf"]
170     return cmdline
171
172
173 def get_model_inst(model):
174     if FVP_MODELS[model][1]:
175         return f"{FVP_MODELS[model][1]}="
176     return ""
177
178
179 @matrix_filter
180 def filter_ac5_armv8m(config):
181     return (config.compiler == CompilerAxis.AC5 and 
182             config.device.match("CM[235][35]*"))
183
184
185 @matrix_filter
186 def filter_ac6ltm_armv81m(config):
187     return (config.compiler == CompilerAxis.AC6LTM and 
188             config.device.match("CM[35]5*"))
189
190
191 if __name__ == "__main__":
192     main()