build.py 6.9 KB

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