5 from argparse import ArgumentParser
6 from datetime import datetime
7 from subprocess import call, Popen
8 from pathlib import Path
10 sys.path.append('buildutils')
12 from rtecmd import RteCmd
13 from uv4cmd import Uv4Cmd
14 from dscmd import DsCmd
15 from fvpcmd import FvpCmd
16 from iarcmd import IarCmd
17 from testresult import TestResult
20 rtebuildhome = os.path.join(os.path.abspath(Path.home()), ".rtebuild")
21 sys.path.append(rtebuildhome)
23 except ModuleNotFoundError:
24 print("No custom buildenv.py found in "+rtebuildhome)
28 DEVICE_CM0 = 'Cortex-M0'
29 DEVICE_CM0PLUS = 'Cortex-M0plus'
30 DEVICE_CM3 = 'Cortex-M3'
31 DEVICE_CM4 = 'Cortex-M4'
32 DEVICE_CM4FP = 'Cortex-M4FP'
33 DEVICE_CM7 = 'Cortex-M7'
34 DEVICE_CM7SP = 'Cortex-M7SP'
35 DEVICE_CM7DP = 'Cortex-M7DP'
36 DEVICE_CM23 = 'Cortex-M23'
37 DEVICE_CM33 = 'Cortex-M33'
38 DEVICE_CM23NS = 'Cortex-M23NS'
39 DEVICE_CM33NS = 'Cortex-M33NS'
40 DEVICE_CM23S = 'Cortex-M23S'
41 DEVICE_CM33S = 'Cortex-M33S'
42 DEVICE_CA5 = 'Cortex-A5'
43 DEVICE_CA7 = 'Cortex-A7'
44 DEVICE_CA9 = 'Cortex-A9'
45 DEVICE_CA5NEON = 'Cortex-A5neon'
46 DEVICE_CA7NEON = 'Cortex-A7neon'
47 DEVICE_CA9NEON = 'Cortex-A9neon'
59 DEVICE_CM0PLUS : 'CM0plus',
62 DEVICE_CM4FP : 'CM4FP',
64 DEVICE_CM7SP : 'CM7SP',
65 DEVICE_CM7DP : 'CM7DP',
68 DEVICE_CM23S : 'CM23S',
69 DEVICE_CM33S : 'CM33S',
70 DEVICE_CM33NS : 'CM33NS',
71 DEVICE_CM23NS : 'CM23NS',
75 DEVICE_CA5NEON : 'CA5neon',
76 DEVICE_CA7NEON : 'CA7neon',
77 DEVICE_CA9NEON : 'CA9neon'
80 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 ]
81 COMPILERS = [ CC_AC5, CC_AC6, CC_AC6LTM, CC_GCC, CC_IAR ]
82 TARGETS = [ TARGET_FVP ]
85 [ DEVICE_CM23, CC_AC5, None ],
86 [ DEVICE_CM33, CC_AC5, None ],
87 [ DEVICE_CM23NS, CC_AC5, None ],
88 [ DEVICE_CM33NS, CC_AC5, None ],
89 [ DEVICE_CM23S, CC_AC5, None ],
90 [ DEVICE_CM33S, CC_AC5, None ],
91 [ DEVICE_CM0, CC_AC6LTM, None ],
92 [ DEVICE_CM0PLUS, CC_AC6LTM, None ],
93 [ DEVICE_CM23, CC_AC6LTM, None ],
94 [ DEVICE_CM33, CC_AC6LTM, None ],
95 [ DEVICE_CM23NS, CC_AC6LTM, None ],
96 [ DEVICE_CM33NS, CC_AC6LTM, None ],
97 [ DEVICE_CM23S, CC_AC6LTM, None ],
98 [ DEVICE_CM33S, CC_AC6LTM, None ],
102 DEVICE_CM0 : { 'cmd': "FVP_MPS2_Cortex-M0_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM0_config.txt" } },
103 DEVICE_CM0PLUS : { 'cmd': "FVP_MPS2_Cortex-M0plus_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM0plus_config.txt" } },
104 DEVICE_CM3 : { 'cmd': "FVP_MPS2_Cortex-M3_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM3_config.txt" } },
105 DEVICE_CM4 : { 'cmd': "FVP_MPS2_Cortex-M4_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM4_config.txt" } },
106 DEVICE_CM4FP : { 'cmd': "FVP_MPS2_Cortex-M4_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM4FP_config.txt" } },
107 DEVICE_CM7 : { 'cmd': "FVP_MPS2_Cortex-M7_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM7_config.txt" } },
108 DEVICE_CM7SP : { 'cmd': "FVP_MPS2_Cortex-M7_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM7SP_config.txt" } },
109 DEVICE_CM7DP : { 'cmd': "FVP_MPS2_Cortex-M7_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM7DP_config.txt" } },
110 DEVICE_CM23 : { 'cmd': "FVP_MPS2_Cortex-M23_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM23_config.txt", 'target': "cpu0" } },
111 DEVICE_CM33 : { 'cmd': "FVP_MPS2_Cortex-M33_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM33_config.txt", 'target': "cpu0" } },
112 DEVICE_CM23NS : { 'cmd': "FVP_MPS2_Cortex-M23_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM23_TZ_config.txt", 'target': "cpu0" } },
113 DEVICE_CM33NS : { 'cmd': "FVP_MPS2_Cortex-M33_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM33_DSP_FP_TZ_config.txt", 'target': "cpu0" } },
114 DEVICE_CM23S : { 'cmd': "FVP_MPS2_Cortex-M23_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM23_TZ_config.txt", 'target': "cpu0" } },
115 DEVICE_CM33S : { 'cmd': "FVP_MPS2_Cortex-M33_MDK.exe", 'args': { 'limit': "50000000", 'config': "ARMCM33_DSP_FP_TZ_config.txt", 'target': "cpu0" } },
116 DEVICE_CA5 : { 'cmd': "fvp_ve_cortex-a5x1.exe", 'args': { 'limit': "70000000", 'config': "ARMCA5_config.txt" } },
117 DEVICE_CA7 : { 'cmd': "fvp_ve_cortex-a7x1.exe", 'args': { 'limit': "170000000", 'config': "ARMCA7_config.txt" } },
118 DEVICE_CA9 : { 'cmd': "fvp_ve_cortex-a9x1.exe", 'args': { 'limit': "70000000", 'config': "ARMCA9_config.txt" } },
119 DEVICE_CA5NEON : { 'cmd': "fvp_ve_cortex-a5x1.exe", 'args': { 'limit': "70000000", 'config': "ARMCA5neon_config.txt" } },
120 DEVICE_CA7NEON : { 'cmd': "fvp_ve_cortex-a7x1.exe", 'args': { 'limit': "170000000", 'config': "ARMCA7neon_config.txt" } },
121 DEVICE_CA9NEON : { 'cmd': "fvp_ve_cortex-a9x1.exe", 'args': { 'limit': "70000000", 'config': "ARMCA9neon_config.txt" } }
124 def isSkipped(dev, cc, target):
126 skipDev = (skip[0] == None or skip[0] == dev)
127 skipCc = (skip[1] == None or skip[1] == cc)
128 skipTarget = (skip[2] == None or skip[2] == target)
129 if skipDev and skipCc and skipTarget:
133 def testProject(dev, cc, target):
134 rtebuild = "{dev}/{cc}/default.rtebuild".format(dev = dev, cc = cc, target=target)
135 if os.path.exists(rtebuild):
138 "{dev}/{cc}/build/{target}/{target}.elf".format(dev = dev, cc = cc, target=target)
140 elif (cc == CC_AC5) or (cc == CC_AC6):
142 "{dev}/{cc}/CMSIS_CV.uvprojx".format(dev = dev, cc = cc),
143 "{dev}/{cc}/Objects/CMSIS_CV.axf".format(dev = dev, cc = cc)
145 elif (cc == CC_AC6LTM):
147 "{dev}/{cc}/CMSIS_CV.uvprojx".format(dev = dev, cc = CC_AC6),
148 "{dev}/{cc}/Objects/CMSIS_CV.axf".format(dev = dev, cc = CC_AC6)
152 "{dev}/{cc}/CMSIS_CV.uvprojx".format(dev = dev, cc = cc),
153 "{dev}/{cc}/Objects/CMSIS_CV.elf".format(dev = dev, cc = cc)
157 "{dev}/{cc}/CMSIS_CV.ewp".format(dev = dev, cc = cc),
158 "{dev}/{cc}/{target}/Exe/CMSIS_CV.out".format(dev = dev, cc = cc, target = target)
160 raise "Unknown compiler!"
162 def bootloaderProject(dev, cc, target):
163 rtebuild = "{dev}/{cc}/Bootloader/default.rtebuild".format(dev = dev, cc = cc, target=target)
164 if os.path.exists(rtebuild):
167 "{dev}/{cc}/Bootloader/build/{target}/{target}.elf".format(dev = dev, cc = cc, target=target)
169 elif (cc == CC_AC5) or (cc == CC_AC6):
171 "{dev}/{cc}/Bootloader/Bootloader.uvprojx".format(dev = dev, cc = cc),
172 "{dev}/{cc}/Bootloader/Objects/Bootloader.axf".format(dev = dev, cc = cc)
174 elif (cc == CC_AC6LTM):
176 "{dev}/{cc}/Bootloader/Bootloader.uvprojx".format(dev = dev, cc = CC_AC6),
177 "{dev}/{cc}/Bootloader/Objects/Bootloader.axf".format(dev = dev, cc = CC_AC6)
181 "{dev}/{cc}/Bootloader/Bootloader.uvprojx".format(dev = dev, cc = cc),
182 "{dev}/{cc}/Bootloader/Objects/Bootloader.elf".format(dev = dev, cc = cc)
186 "{dev}/{cc}/Bootloader/Bootloader.ewp".format(dev = dev, cc = cc),
187 "{dev}/{cc}/Bootloader/{target}/Exe/Bootloader.out".format(dev = dev, cc = cc, target = target)
189 raise "Unknown compiler!"
191 def buildStep(dev, cc, target, project, env=os.environ):
198 projectfile, projectext = os.path.splitext(project)
200 if not projectext in STEP_TYPES:
201 raise "Unknown project type '"+projectext+"'!"
203 return STEP_TYPES[projectext](project, target, env)
205 def prepare(steps, args):
206 for dev in args.devices:
207 for cc in args.compilers:
208 for target in args.targets:
209 if not isSkipped(dev, cc, target):
210 config = "{dev} ({cc}, {target})".format(dev = dev, cc = cc, target = target)
211 prefix = "{dev}_{cc}_{target}".format(dev = dev, cc = cc, target = target)
214 if hasattr(buildenv, "env_"+cc):
215 env = getattr(buildenv, "env_"+cc)()
217 rv = testProject(dev, cc, target)
218 build = [ buildStep(dev, cc, target, rv[0], env=env) ]
221 bl = bootloaderProject(dev, cc, target)
222 if os.path.isfile(bl[0]):
223 build = [ buildStep(dev, cc, target, bl[0], env=env) ] + build
224 binary = [ bl[1] ] + binary
226 if target == TARGET_FVP:
227 test = FvpCmd(FVP_MODELS[dev]['cmd'], binary, **FVP_MODELS[dev]['args'])
228 steps += [ { 'name': config, 'prefix': prefix, 'build': build, 'test': test } ]
230 def execute(steps, args):
233 if step['build'] and not args.execute_only:
234 for b in step['build']:
237 print("Skipping build")
238 # step['build'].skip()
240 if step['test'] and not args.build_only:
242 step['result'] = TestResult(step['test'].getOutput())
243 step['result'].saveXml("result_{0}_{1}.xml".format(step['prefix'], datetime.now().strftime("%Y%m%d%H%M%S")))
245 print("Skipping test")
248 def printSummary(steps):
250 print("Test Summary")
251 print("============")
253 print("Test run Total Exec Pass Fail ")
254 print("-------------------------------------------------------")
257 print("{0:30} {1:>4} {2:>4} {3:>4} {4:>4}".format(step['name'], *step['result'].getSummary()))
259 print("{0:30} ------ NO RESULTS ------".format(step['name']))
262 parser = ArgumentParser()
263 parser.add_argument('--genconfig', action='store_true')
264 parser.add_argument('-b', '--build-only', action='store_true')
265 parser.add_argument('-e', '--execute-only', action='store_true')
266 parser.add_argument('-d', '--devices', nargs='*', choices=(DEVICES+list(ADEVICES.values())), default=DEVICES, help = 'Devices to be considered.')
267 parser.add_argument('-c', '--compilers', nargs='*', choices=COMPILERS, default=COMPILERS, help = 'Compilers to be considered.')
268 parser.add_argument('-t', '--targets', nargs='*', choices=TARGETS, default=TARGETS, help = 'Targets to be considered.')
269 args = parser.parse_args()
272 for d in args.devices:
273 if d in ADEVICES.values():
274 d = list(ADEVICES.keys())[list(ADEVICES.values()).index(d)]
277 args.devices = list(devices)
280 for dev in args.devices:
281 model = FVP_MODELS[dev]
282 cmd = [ model['cmd'], '-l', '-o', model['args']['config'] ]
295 if __name__ == "__main__":