]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Tests/build.py
Merge branch 'develop' of https://github.com/ARM-software/CMSIS_5 into develop
[cmsis] / CMSIS / CoreValidation / Tests / build.py
1 #! python
2
3 import sys
4 import os.path
5 from argparse import ArgumentParser
6 from datetime import datetime
7 from subprocess import call, Popen
8
9 sys.path.append('buildutils') 
10
11 from rtecmd import RteCmd 
12 from uv4cmd import Uv4Cmd 
13 from dscmd import DsCmd 
14 from fvpcmd import FvpCmd 
15 from iarcmd import IarCmd 
16 from testresult import TestResult
17
18 DEVICE_CM0     = 'Cortex-M0'
19 DEVICE_CM0PLUS = 'Cortex-M0plus'
20 DEVICE_CM3     = 'Cortex-M3'
21 DEVICE_CM4     = 'Cortex-M4'
22 DEVICE_CM4FP   = 'Cortex-M4FP'
23 DEVICE_CM7     = 'Cortex-M7'
24 DEVICE_CM7SP   = 'Cortex-M7SP'
25 DEVICE_CM7DP   = 'Cortex-M7DP'
26 DEVICE_CM23    = 'Cortex-M23'
27 DEVICE_CM33    = 'Cortex-M33'
28 DEVICE_CM23NS  = 'Cortex-M23NS'
29 DEVICE_CM33NS  = 'Cortex-M33NS'
30 DEVICE_CM23S   = 'Cortex-M23S'
31 DEVICE_CM33S   = 'Cortex-M33S'
32 DEVICE_CA5     = 'Cortex-A5'
33 DEVICE_CA7     = 'Cortex-A7'
34 DEVICE_CA9     = 'Cortex-A9'
35 DEVICE_CA5NEON = 'Cortex-A5neon'
36 DEVICE_CA7NEON = 'Cortex-A7neon'
37 DEVICE_CA9NEON = 'Cortex-A9neon'
38
39 CC_AC6 = 'AC6'
40 CC_AC5 = 'AC5'
41 CC_GCC = 'GCC'
42 CC_IAR = 'IAR'
43
44 MDK_ENV = {
45   'uVision' : [ DEVICE_CM0, DEVICE_CM0PLUS, DEVICE_CM3, DEVICE_CM4, DEVICE_CM4FP, DEVICE_CM7, DEVICE_CM7SP, DEVICE_CM7DP, DEVICE_CM23, DEVICE_CM33, DEVICE_CM23NS, DEVICE_CM33NS, DEVICE_CM23S, DEVICE_CM33S ],
46   'DS'      : [ ], 
47   'RTE'     : [ DEVICE_CA5, DEVICE_CA7, DEVICE_CA9, DEVICE_CA5NEON, DEVICE_CA7NEON, DEVICE_CA9NEON ]
48 }
49
50 TARGET_FVP = 'FVP'
51
52 ADEVICES = {
53     DEVICE_CM0     : 'CM0',
54     DEVICE_CM0PLUS : 'CM0plus',
55     DEVICE_CM3     : 'CM3',
56     DEVICE_CM4     : 'CM4',
57     DEVICE_CM4FP   : 'CM4FP',
58     DEVICE_CM7     : 'CM7',
59     DEVICE_CM7SP   : 'CM7SP',
60     DEVICE_CM7DP   : 'CM7DP',
61     DEVICE_CM23    : 'CM23',
62     DEVICE_CM33    : 'CM33',
63     DEVICE_CM23S   : 'CM23S',
64     DEVICE_CM33S   : 'CM33S',
65     DEVICE_CM33NS  : 'CM33NS',
66     DEVICE_CM23NS  : 'CM23NS',
67     DEVICE_CA5     : 'CA5',
68     DEVICE_CA7     : 'CA7',
69     DEVICE_CA9     : 'CA9',
70     DEVICE_CA5NEON : 'CA5neon',
71     DEVICE_CA7NEON : 'CA7neon',
72     DEVICE_CA9NEON : 'CA9neon'
73   }
74
75 DEVICES = [ DEVICE_CM0, DEVICE_CM0PLUS, DEVICE_CM3, DEVICE_CM4, DEVICE_CM4FP, DEVICE_CM7, DEVICE_CM7SP, DEVICE_CM7DP, DEVICE_CM23, DEVICE_CM33, DEVICE_CM23NS, DEVICE_CM33NS, DEVICE_CM23S, DEVICE_CM33S, DEVICE_CA5, DEVICE_CA7, DEVICE_CA9, DEVICE_CA5NEON, DEVICE_CA7NEON, DEVICE_CA9NEON ]
76 COMPILERS = [ CC_AC5, CC_AC6, CC_GCC, CC_IAR ]
77 TARGETS = [ TARGET_FVP ]
78
79 SKIP = [ 
80     [ DEVICE_CM23,   CC_AC5, None ],
81     [ DEVICE_CM33,   CC_AC5, None ],
82     [ DEVICE_CM23NS, CC_AC5, None ],
83     [ DEVICE_CM33NS, CC_AC5, None ],
84     [ DEVICE_CM23S,  CC_AC5, None ],
85     [ DEVICE_CM33S,  CC_AC5, None ],
86   ]
87   
88 FVP_MODELS = { 
89     DEVICE_CM0      : { 'cmd': "FVP_MPS2_Cortex-M0_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM0_config.txt" } },
90     DEVICE_CM0PLUS  : { 'cmd': "FVP_MPS2_Cortex-M0plus_MDK.exe",  'args': { 'limit': "50000000", 'config': "ARMCM0plus_config.txt" } },
91     DEVICE_CM3      : { 'cmd': "FVP_MPS2_Cortex-M3_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM3_config.txt" } },
92     DEVICE_CM4      : { 'cmd': "FVP_MPS2_Cortex-M4_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM4_config.txt" } },
93     DEVICE_CM4FP    : { 'cmd': "FVP_MPS2_Cortex-M4_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM4FP_config.txt" } },
94     DEVICE_CM7      : { 'cmd': "FVP_MPS2_Cortex-M7_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM7_config.txt" } },
95     DEVICE_CM7SP    : { 'cmd': "FVP_MPS2_Cortex-M7_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM7SP_config.txt" } },
96     DEVICE_CM7DP    : { 'cmd': "FVP_MPS2_Cortex-M7_MDK.exe",      'args': { 'limit': "50000000", 'config': "ARMCM7DP_config.txt" } },
97     DEVICE_CM23     : { 'cmd': "FVP_MPS2_Cortex-M23_MDK.exe",     'args': { 'limit': "50000000", 'config': "ARMCM23_config.txt",           'target': "cpu0" } },
98     DEVICE_CM33     : { 'cmd': "FVP_MPS2_Cortex-M33_MDK.exe",     'args': { 'limit': "50000000", 'config': "ARMCM33_config.txt",           'target': "cpu0" } },
99     DEVICE_CM23NS   : { 'cmd': "FVP_MPS2_Cortex-M23_MDK.exe",     'args': { 'limit': "50000000", 'config': "ARMCM23_TZ_config.txt",        'target': "cpu0" } },
100     DEVICE_CM33NS   : { 'cmd': "FVP_MPS2_Cortex-M33_MDK.exe",     'args': { 'limit': "50000000", 'config': "ARMCM33_DSP_FP_TZ_config.txt", 'target': "cpu0" } },
101     DEVICE_CM23S    : { 'cmd': "FVP_MPS2_Cortex-M23_MDK.exe",     'args': { 'limit': "50000000", 'config': "ARMCM23_TZ_config.txt",        'target': "cpu0" } },
102     DEVICE_CM33S    : { 'cmd': "FVP_MPS2_Cortex-M33_MDK.exe",     'args': { 'limit': "50000000", 'config': "ARMCM33_DSP_FP_TZ_config.txt", 'target': "cpu0" } },
103     DEVICE_CA5      : { 'cmd': "fvp_ve_cortex-a5x1.exe",          'args': { 'limit': "70000000", 'config': "ARMCA5_config.txt" } },
104     DEVICE_CA7      : { 'cmd': "fvp_ve_cortex-a7x1.exe",          'args': { 'limit': "170000000", 'config': "ARMCA7_config.txt" } },
105     DEVICE_CA9      : { 'cmd': "fvp_ve_cortex-a9x1.exe",          'args': { 'limit': "70000000", 'config': "ARMCA9_config.txt" } },
106     DEVICE_CA5NEON  : { 'cmd': "fvp_ve_cortex-a5x1.exe",          'args': { 'limit': "70000000", 'config': "ARMCA5neon_config.txt" } },
107     DEVICE_CA7NEON  : { 'cmd': "fvp_ve_cortex-a7x1.exe",          'args': { 'limit': "170000000", 'config': "ARMCA7neon_config.txt" } },
108     DEVICE_CA9NEON  : { 'cmd': "fvp_ve_cortex-a9x1.exe",          'args': { 'limit': "70000000", 'config': "ARMCA9neon_config.txt" } }
109   }
110
111 def isSkipped(dev, cc, target):
112   for skip in SKIP:
113     skipDev = (skip[0] == None or skip[0] == dev)
114     skipCc = (skip[1] == None or skip[1] == cc)
115     skipTarget = (skip[2] == None or skip[2] == target)
116     if skipDev and skipCc and skipTarget:
117       return True
118   return False
119   
120 def testProject(dev, cc, target):
121   rtebuild = "{dev}/{cc}/default.rtebuild".format(dev = dev, cc = cc, target=target)
122   if os.path.exists(rtebuild):
123     return [
124         rtebuild,
125         "{dev}/{cc}/build/{target}.elf".format(dev = dev, cc = cc, target=target)
126       ]
127   elif (cc == CC_AC5) or (cc == CC_AC6):
128     if dev in MDK_ENV['DS']:
129       return [
130           "{dev}/{cc}/.project".format(dev = dev, cc = cc),
131           "{dev}/{cc}/Debug/CMSIS_CV_{adev}_{cc}.axf".format(dev = dev, adev=ADEVICES[dev], cc = cc)
132         ]
133     elif dev in MDK_ENV['RTE']:
134       return [
135           "{dev}/{cc}/default.rtebuild".format(dev = dev, cc = cc, target=target),
136           "{dev}/{cc}/build/{target}.elf".format(dev = dev, cc = cc, target=target)
137         ]
138     else:
139       return [
140           "{dev}/{cc}/CMSIS_CV.uvprojx".format(dev = dev, cc = cc),
141           "{dev}/{cc}/Objects/CMSIS_CV.axf".format(dev = dev, cc = cc)
142         ]
143   elif (cc == CC_GCC):
144     if dev in MDK_ENV['DS']:
145       return [
146           "{dev}/{cc}/.project".format(dev = dev, cc = cc),
147           "{dev}/{cc}/Debug/CMSIS_CV_{adev}_{cc}.elf".format(dev = dev, adev=ADEVICES[dev], cc = cc)
148         ]
149     elif dev in MDK_ENV['RTE']:
150       return [
151           "{dev}/{cc}/default.rtebuild".format(dev = dev, cc = cc, target=target),
152           "{dev}/{cc}/build/{target}.elf".format(dev = dev, cc = cc, target=target)
153         ]
154     else:
155       return [
156           "{dev}/{cc}/CMSIS_CV.uvprojx".format(dev = dev, cc = cc),
157           "{dev}/{cc}/Objects/CMSIS_CV.elf".format(dev = dev, cc = cc)
158         ]
159   elif (cc == CC_IAR):
160     if dev in MDK_ENV['RTE']:
161       return [
162           "{dev}/{cc}/default.rtebuild".format(dev = dev, cc = cc, target=target),
163           "{dev}/{cc}/build/{target}.elf".format(dev = dev, cc = cc, target=target)
164         ]
165     else:
166       return [
167           "{dev}/{cc}/CMSIS_CV.ewp".format(dev = dev, cc = cc),
168           "{dev}/{cc}/{target}/Exe/CMSIS_CV.out".format(dev = dev, cc = cc, target = target)
169         ]
170   raise "Unknown compiler!"
171
172 def bootloaderProject(dev, cc, target):
173   rtebuild = "{dev}/{cc}/Bootloader/default.rtebuild".format(dev = dev, cc = cc, target=target)
174   if os.path.exists(rtebuild):
175     return [
176         rtebuild,
177         "{dev}/{cc}/Bootloader/build/{target}.elf".format(dev = dev, cc = cc, target=target)
178       ]
179   elif (cc == CC_AC5) or (cc == CC_AC6):
180     return [
181         "{dev}/{cc}/Bootloader/Bootloader.uvprojx".format(dev = dev, cc = cc),
182         "{dev}/{cc}/Bootloader/Objects/Bootloader.axf".format(dev = dev, cc = cc)
183       ] 
184   elif (cc == CC_GCC):
185     return [
186         "{dev}/{cc}/Bootloader/Bootloader.uvprojx".format(dev = dev, cc = cc),
187         "{dev}/{cc}/Bootloader/Objects/Bootloader.elf".format(dev = dev, cc = cc)
188       ] 
189   elif (cc == CC_IAR):
190     return [
191         "{dev}/{cc}/Bootloader/Bootloader.ewp".format(dev = dev, cc = cc),
192         "{dev}/{cc}/Bootloader/{target}/Exe/Bootloader.out".format(dev = dev, cc = cc, target = target)
193       ]
194   raise "Unknown compiler!"
195   
196 def buildStep(dev, cc, target, project):
197   STEP_TYPES = {
198     ".uvprojx"  : Uv4Cmd,
199     ".ewp"      : IarCmd,
200     ".rtebuild" : RteCmd
201   }
202   
203   projectfile, projectext = os.path.splitext(project)
204   
205   if not projectext in STEP_TYPES:
206     raise "Unknown project type '"+projectext+"'!"
207     
208   return STEP_TYPES[projectext](project, target)
209   
210 def prepare(steps, args):
211   for dev in args.devices:
212     for cc in args.compilers:
213       for target in args.targets:
214         if not isSkipped(dev, cc, target):
215           config = "{dev} ({cc}, {target})".format(dev = dev, cc = cc, target = target)
216           prefix = "{dev}_{cc}_{target}".format(dev = dev, cc = cc, target = target)
217           
218           rv = testProject(dev, cc, target)
219           build = [ buildStep(dev, cc, target, rv[0]) ]
220           binary = [ rv[1] ]
221           
222           bl = bootloaderProject(dev, cc, target)
223           if os.path.isfile(bl[0]):
224             build = [ buildStep(dev, cc, target, bl[0]) ] + build
225             binary = [ bl[1] ] + binary
226
227           if target == TARGET_FVP:
228             test = FvpCmd(FVP_MODELS[dev]['cmd'], binary, **FVP_MODELS[dev]['args'])
229           steps += [ { 'name': config, 'prefix': prefix, 'build': build, 'test': test } ]
230
231 def execute(steps, args):
232   for step in steps:
233     print(step['name'])
234     if step['build'] and not args.execute_only:
235       for b in step['build']:
236         b.run()
237     else:
238       print("Skipping build")
239       # step['build'].skip()
240       
241     if step['test'] and not args.build_only:
242       step['test'].run()
243       step['result'] = TestResult(step['test'].getOutput())
244       step['result'].saveXml("result_{0}_{1}.xml".format(step['prefix'], datetime.now().strftime("%Y%m%d%H%M%S")))
245     else:
246       print("Skipping test")
247       step['test'].skip()
248       
249 def printSummary(steps):
250   print("")
251   print("Test Summary")
252   print("============")
253   print()
254   print("Test run                       Total Exec  Pass  Fail  ")
255   print("-------------------------------------------------------")
256   for step in steps:
257     try:
258       print("{0:30} {1:>4}  {2:>4}  {3:>4}  {4:>4}".format(step['name'], *step['result'].getSummary()))
259     except:
260       print("{0:30} ------ NO RESULTS ------".format(step['name']))
261
262 def main(argv):
263   parser = ArgumentParser()
264   parser.add_argument('--genconfig', action='store_true')
265   parser.add_argument('-b', '--build-only', action='store_true')
266   parser.add_argument('-e', '--execute-only', action='store_true')
267   parser.add_argument('-d', '--devices', nargs='*', choices=(DEVICES+list(ADEVICES.values())), default=DEVICES, help = 'Devices to be considered.')
268   parser.add_argument('-c', '--compilers', nargs='*', choices=COMPILERS, default=COMPILERS, help = 'Compilers to be considered.')
269   parser.add_argument('-t', '--targets', nargs='*', choices=TARGETS, default=TARGETS, help = 'Targets to be considered.')
270   args = parser.parse_args()
271   
272   devices = set()
273   for d in args.devices:
274     if d in ADEVICES.values():
275       d = list(ADEVICES.keys())[list(ADEVICES.values()).index(d)]
276     devices.add(d)
277   
278   args.devices = list(devices)
279     
280   if args.genconfig:
281     for dev in args.devices:
282       model = FVP_MODELS[dev]
283       cmd = [ model['cmd'], '-l', '-o', model['args']['config'] ]
284       print(" ".join(cmd))
285       call(cmd)
286     return 1
287     
288   steps = []
289
290   prepare(steps, args)
291   
292   execute(steps, args)
293   
294   printSummary(steps)
295   
296 if __name__ == "__main__":
297   main(sys.argv[1:])